Hitachi Vantara Pentaho Community Forums
Results 1 to 3 of 3

Thread: How to add elements to bands dynamically

  1. #1
    Join Date
    Nov 2005
    Posts
    4

    Default How to add elements to bands dynamically

    My program allows users to create reports dynamically.
    For example they can add up to 5 titles to the PageHeader band.
    Each title might have a different font name and size etc.
    I add each title as a LabelElement to the PageHeader object using the following code:
    Code:
    		int numTitles = reportTitles.length;
    		rect = new Rectangle2D.Double(0,0,-100,-100);
    		for &#40;int i = 0; i < numTitles; i++&#41; &#123;
    			TextElement title = LabelElementFactory.createLabelElement&#40;"title " +i, rect, titleColor,
     ElementAlignment.CENTER, ElementAlignment.MIDDLE, titleFont, reportTitles&#91;i&#93;&#41;;
    			pageHeader.addElement&#40;title&#41;;
    		&#125;
    Because each element is added with the same rectangle co-ordinates, they would just overwrite each other.
    Having read hints from other posts, I have created a function which calculates the height of each title element, and recreates the pageHeader object by adding the titles with the correct y co-ordinate so that they all print correctly.
    This works fine if all titles fit onto one line.
    However, if a title is too long, it disappears off the end of the page. I can rectify this by using setDynamicContent(true)
    However, my element height is no longer calculated correctly.
    Therefore, I have 2 questions.

    1. Is there a better way of achieving what I am trying to do ? (I assume there must be - I am new to JFreeReport)
    2. If what I am doing is basically ok, how can I amend my function so that it calculates the height of each element correctly, even when the content is set to dynamic ?

    The function code follows.
    Code:
    public class PageHeaderFunction extends AbstractElementFormatFunction &#123;
    	
    	public PageHeaderFunction&#40;&#41; &#123;
    		super&#40;&#41;;
    	&#125;
    
    	// Override the pageStarted method to call the reformatPageHeader function
    	public void pageStarted &#40;final ReportEvent event&#41; &#123;
    		if &#40;FunctionUtilities.isLayoutLevel&#40;event&#41; == false&#41; &#123;
    			return;
    		&#125;
    		final Band b = event.getReport&#40;&#41;.getPageHeader&#40;&#41;;
    		reformatPageHeader&#40;b, event.getReport&#40;&#41;&#41;;
    	&#125;
    	
    	protected void reformatPageHeader&#40;Band b, ReportDefinition report&#41; &#123;
    		// Only process this function on the PageHeader band
    		try &#123;
    			Class pageHeaderClass = Class.forName&#40;"org.jfree.report.PageHeader"&#41;;
    			if &#40;pageHeaderClass.isInstance&#40;b&#41;&#41; &#123;
    				final Element&#91;&#93; elements = b.getElementArray&#40;&#41;;
    				int numElements = elements.length;
    				if &#40;numElements == 0&#41; &#123;
    					return;
    				&#125;
    				// Reformat each title element with the correct height for each within the PageHeader band
    				double bandHeight = 0.0;
    				Rectangle2D.Double rect = new Rectangle2D.Double&#40;0,bandHeight,-100,-100&#41;;
    				for &#40;int i = 0; i < numElements; i++&#41; &#123;
    					String text = elements&#91;i&#93;.getValue&#40;&#41;.toString&#40;&#41;;
    					FontDefinition font = &#40;&#40;TextElement&#41;elements&#91;i&#93;&#41;.getFont&#40;&#41;;
    					double elementHeight = calculateHeight&#40;elements&#91;i&#93;, report&#41;;
    					rect.height = elementHeight;
    					Element title = LabelElementFactory.createLabelElement&#40;"title " +i, rect, Color.black, ElementAlignment.CENTER, ElementAlignment.MIDDLE, font, text&#41;;
    					//title.setDynamicContent&#40;true&#41;;
    					bandHeight += elementHeight;
    					rect.y = bandHeight;
    					b.removeElement&#40;elements&#91;i&#93;&#41;;
    					b.addElement&#40;i, title&#41;;
    				&#125;
    			&#125;
    		&#125; catch &#40;ClassNotFoundException cnfe&#41; &#123;
    			System.out.println&#40;"Class not Found" +cnfe.getMessage&#40;&#41;&#41;;
    		&#125;
    	&#125;
    	
    	protected void processRootBand&#40;Band b&#41; &#123;
    		// Do nothing on all bands other than the PageHeader band
    	&#125;
    	
    	double calculateHeight&#40;Element element, ReportDefinition report&#41; &#123;
    		double height = 0.0;
    		FontDefinition font = element.getStyle&#40;&#41;.getFontDefinitionProperty&#40;&#41;;
    		String text = String.valueOf&#40;element.getValue&#40;&#41;&#41;;
    		LayoutSupport layouter = &#40;LayoutSupport&#41;report.getProperties&#40;&#41;.get&#40;JFreeReport.REPORT_LAYOUT_SUPPORT&#41;;
    		try &#123;
    			SizeCalculator sc = layouter.createTextSizeCalculator&#40;font&#41;;
    			height = sc.getLineHeight&#40;&#41;;
    		&#125; catch &#40;SizeCalculatorException sce&#41; &#123;
    			// do nothing
    		&#125;
    		return height;
    	&#125;
    	
    	public Object getValue&#40;&#41; &#123;
    		return null;
    	&#125;
    
    &#125;

  2. #2
    Join Date
    Mar 2003
    Posts
    8,085

    Default

    Hi,

    if you use JFreeReport 0.8.6 or higher, then you can use the StackedLayoutManager to solve your problem. That layout-manager behaves like a vertical Box-Layout in Swing and therefore places all elements of a band below each other.

    If the stacking should be applied to only some of the elements, use subbands in the same way as you would use panels in a Swing/AWT Gui to sepate LayoutManager effects.

    Code:
    Band band = new Band&#40;&#41;;
    band.setLayoutManager &#40;new StackedLayoutManager&#40;&#41;&#41;;
    // add your elements. The absolute position is always 0,0, the element 
    // consumes the complete width of the band.
    
    int numTitles = reportTitles.length;
    // the rect is ignored by the layouter, but  it is required by the 
    // createLabelElement function &#40;for historical reasons&#41;.
    //
    // minimim height is changed to zero, as we let JFreeReport compute a 
    // suitable value
    rect = new Rectangle2D.Double&#40;0,0,-100, 0&#41;;
    for &#40;int i = 0; i < numTitles; i++&#41; 
    &#123;
        TextElement title = LabelElementFactory.createLabelElement
            &#40;"title " +i, rect, titleColor,  ElementAlignment.CENTER, 
             ElementAlignment.MIDDLE, titleFont, reportTitles&#91;i&#93;&#41;;
         // let JFreeReport compute the element's height. So you dont have to
         // guess.
         title.setDynamicHeight&#40;true&#41;;
        pageHeader.addElement&#40;title&#41;;
    &#125;
    No further computation is needed, JFreeReport takes care of that during the layouting.

    Regards,
    Thomas

  3. #3
    Join Date
    Nov 2005
    Posts
    4

    Default

    Thanks for your swift reply.
    I have used your suggestion, and it works - a much more elegant solution !

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Privacy Policy | Legal Notices | Safe Harbor Privacy Policy

Copyright © 2005 - 2019 Hitachi Vantara Corporation. All Rights Reserved.