Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » BIRT » Dynamic chart legend wrapping
Dynamic chart legend wrapping [message #548958] Fri, 23 July 2010 14:34 Go to next message
Missing name Missing name is currently offline Missing name Missing name
Messages: 94
Registered: November 2009
Member
Hi,
I'm trying to use the following blog to make the wrapping of the chart legend a little smarter: http://java.sys-con.com/node/1469694

Does anyone know how to create the new wrapped text to set back on the legendItemHints object or why he is talking about a binary search?

so far i've got
function beforeRendering(gcs, icsc) {
importPackage(org.eclipse.birt.chart.computation);
	var legendLayoutHints = gcs.getRunTimeContext().getLegendLayoutHints();
	var legendItemHints = legendLayoutHints.getLegendItemHints();

	for(i = 0; i < legendItemHints.length; i++) {
		
		var chartComputation = new BIRTChartComputation();
		
		var label = GObjectFactory.instance().createLabel();
		
		label.getCaption().setValue(legendItemHints[i].getItemText());
		label.getCaption().getFont().setWordWrap(true);
		
		var fontHeight = chartComputation.computeFontHeight(
			gcs.getDisplayServer(), label);
			
		var labelSize = chartComputation.computeLabelSize(
			gcs.getDisplayServer(), label, 20, fontHeight);
		chartComputation.applyWrapping(gcs.getDisplayServer(), label, 3); 
		legendItemHints[i].setItemText(label.getCaption().getValue());	
	}
}


However, no wrapping occurs....i'm not sure that the dWrapping paramter is supposed to be so i've tried random values of 20 and 3 respectively
thanks

[Updated on: Fri, 23 July 2010 16:15]

Report message to a moderator

Re: Dynamic chart legend wrapping [message #548999 is a reply to message #548958] Fri, 23 July 2010 16:13 Go to previous messageGo to next message
Missing name Missing name is currently offline Missing name Missing name
Messages: 94
Registered: November 2009
Member
Updated to have correct link: http://java.sys-con.com/node/1469694
Re: Dynamic chart legend wrapping [message #549021 is a reply to message #548958] Fri, 23 July 2010 17:23 Go to previous messageGo to next message
Steve Schafer is currently offline Steve Schafer
Messages: 22
Registered: December 2009
Junior Member
Hi,

To answer your question about binary search, I wrote my own code to do the wrapping rather than chartComputation.applyWrapping since I had special requirements . I did a binary search looking for wrap-points using chartComputation.computeLabelSize to tell me how wide the strings were.

The reason I use the binary search is that computeLabelSize is relatively expensive. In my first attempt I walked the string from left to right, executing computeLabelSize for each added character, and it was noticeably slow. Also I noticed that binary search is used in the BIRT code for similar operations.

I can't answer your question about applyWrapping since I haven't worked with it. I can tell you that applyWrapping is used by the chart code to wrap the legends so it ought to work. If you use applyWrapping, you shouldn't need computeLabelSize.

My original blog is at http://birtworld.blogspot.com/2010/07/manipulating-chart-leg ends-in-event.html.

Steve
Re: Dynamic chart legend wrapping [message #549057 is a reply to message #548958] Fri, 23 July 2010 21:55 Go to previous messageGo to next message
Missing name Missing name is currently offline Missing name Missing name
Messages: 94
Registered: November 2009
Member
Thanks for that Steve. Would it be possible for you to post a sample report of what you implemented?

Re: Dynamic chart legend wrapping [message #549356 is a reply to message #549057] Mon, 26 July 2010 14:02 Go to previous messageGo to next message
Steve Schafer is currently offline Steve Schafer
Messages: 22
Registered: December 2009
Junior Member
I encapsulated the wrapping logic in the following classes. Usage: Instantiate Wrapper and then call the wrap method. There are a couple of externally defined static variables but I think it should be obvious what they are. Let me know if you have questions.

  private static class WrapResult
  {
    private final boolean truncated;
    private final double height;
    private final String text;

    public WrapResult( final boolean truncated, final double height, final String text )
    {
      this.truncated = truncated;
      this.height = height;
      this.text = text;
    }
  }

  private static class Wrapper
  {
    private final char[] chars;
    private final Label label;
    private final double maxHeight;
    private final double maxWidth;
    private final int minWordWrapLength;
    private final IDisplayServer displayServer;
    private final Double fontHeight;
    private int lineStart = 0;
    private int lineEnd = 0;
    BoundingBox boundingBox = null;

    public Wrapper( final String text, final double height, final double width, final GeneratedChartState gcs,
                    final int minWordWrapLength ) throws ChartException
    {
      this.chars = text.toCharArray();
      // create a label to use for computations
      this.label = goFactory.createLabel();
      this.label.setCaption( goFactory.copyOf( gcs.getChartModel().getLegend().getText() ) );
      this.label.getCaption().setValue( text );
      this.maxHeight = height;
      this.maxWidth = width;
      this.minWordWrapLength = minWordWrapLength;
      this.displayServer = gcs.getDisplayServer();
      this.fontHeight = chartComputation.computeFontHeight( this.displayServer, this.label );
    }

    private void updateLabel()
    {
      final int count = this.lineEnd - this.lineStart;
      final String text = new String( this.chars, this.lineStart, count ).trim();
      this.label.getCaption().setValue( text );
    }

    private void updateBoundingBox() throws ChartException
    {
      this.updateLabel();
      this.boundingBox = chartComputation.computeLabelSize( this.displayServer, this.label, 0, this.fontHeight );
    }

    private void setLineEnd( final int lineEnd ) throws ChartException
    {
      this.lineEnd = lineEnd;
      this.updateBoundingBox();
    }

    private void skipSpaces()
    {
      while ( this.lineStart < this.chars.length && Character.isWhitespace( this.chars[ this.lineStart ] ) )
        this.lineStart++;
    }

    private void findWordWrapPoint() throws ChartException
    {
      int tmpLineEnd = this.lineEnd;
      while ( tmpLineEnd - this.lineStart > this.minWordWrapLength )
      {
        if ( Character.isWhitespace( this.chars[ tmpLineEnd - 1 ] ) )
        {
          this.setLineEnd( tmpLineEnd );
          return;
        }
        tmpLineEnd--;
      }
    }

    private boolean getNextLine() throws ChartException
    {
      this.lineStart = this.lineEnd;
      this.skipSpaces();
      // binary search for lineEnd
      int lo = this.lineStart;
      int hi = this.chars.length;
      if ( hi - lo <= 0 )
        return false;
      if ( hi - lo == 1 )
      {
        // only 1 char
        this.setLineEnd( this.chars.length );
        return true;
      }
      while ( hi - lo > 1 )
      {
        this.setLineEnd( lo + ( hi - lo ) / 2 );
        if ( this.boundingBox.getWidth() > this.maxWidth )
          hi = this.lineEnd;
        else
          lo = this.lineEnd;
      }
      // binary search can leave us one character short
      if ( this.lineEnd < this.chars.length && this.boundingBox.getWidth() <= this.maxWidth )
      {
        this.setLineEnd( this.lineEnd + 1 );
        if ( this.lineEnd > this.lineStart && this.boundingBox.getWidth() > this.maxWidth )
          this.setLineEnd( this.lineEnd - 1 );
      }
      this.findWordWrapPoint();
      return true;
    }

    public WrapResult wrap() throws ChartException
    {
      final List<String> lines = new ArrayList<String>();
      double heightOfLines = 0;
      boolean truncated = false;
      while ( this.getNextLine() && !truncated )
      {
        heightOfLines += this.boundingBox.getHeight();
        truncated = heightOfLines > this.maxHeight;
        if ( !truncated )
          lines.add( this.label.getCaption().getValue() );
      }
      final StringBuilder sb = new StringBuilder();
      String sep = "";
      for ( final String line : lines )
      {
        sb.append( sep );
        sep = "\r\n";
        sb.append( line );
      }
      return new WrapResult( truncated, heightOfLines, sb.toString() );
    }
  }
Re: Dynamic chart legend wrapping [message #550759 is a reply to message #549356] Wed, 04 August 2010 09:35 Go to previous message
Missing name Missing name is currently offline Missing name Missing name
Messages: 94
Registered: November 2009
Member
Used the above as a basis and got my wrapping going.

Thanks a mill!
Previous Topic:ReportItemModel extension and defining a JavaObject property
Next Topic:Table header/footer/detail style issues
Goto Forum:
  


Current Time: Tue Oct 21 21:48:45 GMT 2014

Powered by FUDForum. Page generated in 0.03584 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software