Plot w/ TextTitle enhacement

A discussion forum for JFreeChart (a 2D chart library for the Java platform).
Locked
tbardzil

Plot w/ TextTitle enhacement

Post by tbardzil » Wed May 12, 2004 6:59 pm

David,

I have written an enhancement for XYPlot that draws a subtitle in a rectangle directly over the plot. Here an example of two such plots that have been added to a CombinedDomainXYPlot.

Image

Right now I have this in a subclass of XYPlot but conceivably it could be added to the Plot base class so that others could use it as well. Its very handle for both combined xy and combined category plots to label each individual subplot.

Here is the code:

Code: Select all

        double width = rectangle2D.getWidth();

        double titleHeight = title.getPreferredHeight(graphics2D, (float) width);
        double plotHeight = rectangle2D.getHeight() - titleHeight;

        Rectangle2D plotRect = new Rectangle2D.Double(
                rectangle2D.getX(),
                rectangle2D.getY() + titleHeight,
                rectangle2D.getWidth(),
                plotHeight);

        super.draw(graphics2D, plotRect, point2D, plotState, plotRenderingInfo);

        Rectangle2D dataArea = plotRenderingInfo.getDataArea();

        Rectangle2D titleRect = new Rectangle2D.Double(
                dataArea.getX(),
                dataArea.getY() - titleHeight,
                dataArea.getWidth(),
                titleHeight);

        title.draw(graphics2D, titleRect);

        graphics2D.setStroke(super.getOutlineStroke());
        graphics2D.setPaint(super.getOutlinePaint());
        graphics2D.draw(titleRect);
title is simply a TextTitle instance that is provided to the constructor of the plot.

Tim

tbardzil

Post by tbardzil » Wed May 12, 2004 7:00 pm

Not sure why the image is not displaying but its can be viewed here -

http://disk.bardzil.net/chart.jpg

astenwick
Posts: 13
Joined: Tue Apr 13, 2004 8:03 pm
Location: Seattle

Post by astenwick » Wed May 12, 2004 7:08 pm

I did the same thing except I put the code within my CombinedDomainPlot class. I draw the title beforing drawing the subplot.

Code: Select all

	public void drawTitle(TextTitle title, Graphics2D g2, Rectangle2D area) {

		Rectangle2D titleArea = new Rectangle2D.Double();
		double availableHeight = 0.0;
		double availableWidth = 0.0;
		
		availableWidth = area.getWidth();
		availableHeight = Math.min(title.getPreferredHeight(g2, (float) availableWidth), area.getHeight());
		titleArea.setRect(area.getX(), area.getY(), availableWidth, availableHeight);
		title.setBackgroundPaint(Color.white);
		title.draw(g2, titleArea);
		area.setRect(area.getX(), Math.min(area.getY() + availableHeight, area.getMaxY()),
					availableWidth, Math.max(area.getHeight() - availableHeight, 0));
		
	}
Where title is the subtitle passed to the CombinedDomainPlot, and area is the initial subplot calculated area.

Clearly this type of functionality is needed in JFreeChart.

tbardzil

Post by tbardzil » Wed May 12, 2004 8:57 pm

I thinking that this actually belongs on the base Plot class because there might be other uses for this besides the current combined plots.

For example, I've created a Plot subclass that is very similar to existing combined plots but doesn't do any of the shared axis stuff. Basically its just a convenient way to put multiple unreleated plots within a single chart. In this case I also want to have titles drawn over each of the subplots. So the easiest way to support this would be to add the title functionality to the base class.

I noticed that you are just drawing the text without a rectangle surround it as I have in my example? Is this correct? Probably both options would need to be supported because I can think of cases (pie plots) when the rectange wouldn't look nice.

Tim

david.gilbert
JFreeChart Project Leader
Posts: 11734
Joined: Fri Mar 14, 2003 10:29 am
antibot: No, of course not.
Contact:

Post by david.gilbert » Wed May 12, 2004 10:40 pm

I think this is a useful feature. Previously I've thought about using a similar title/subtitle API as in the JFreeChart class. That would work pretty well for a single plot, but I can see some problems that would arise with the combined plots (axis alignment issues when the subplots have different combinations of titles).

I agree with Tim that the code should go into the Plot class.
David Gilbert
JFreeChart Project Leader

:idea: Read my blog
:idea: Support JFree via the Github sponsorship program

astenwick
Posts: 13
Joined: Tue Apr 13, 2004 8:03 pm
Location: Seattle

Post by astenwick » Wed May 12, 2004 11:13 pm

I think putting it in the base plot class would be a good idea. All my plots are shown as a png image on a webpage and have a white background and I definetely think it looks better without the rectangle.

[/code]

tbardzil

Post by tbardzil » Thu May 13, 2004 2:44 am

Well I could probably live without the rectangle because I noticed that TextTitle allows the background color of the bounding rectange to be set so I could achieve a similar result.

As for David's point I'm not sure I see the need for the complete title / subtitle functionality at the plot level. I guess it couldn't hurt but the immediate need is just a single text title to describe each individual subplot when several are present.

Also I'm not sure I see how axis alignment could be a problem so long as the title 'steals' a portion of the plot rectangle and then passes what is left down to the actual draw() method for that plot. The plot won't know the difference and everything should work as it currently does.

So what about something like this on Plot.


Code: Select all

public void draw(Graphics2D g2, 
                         Rectangle2D plotArea, 
                         PlotState parentState, 
                         PlotRenderingInfo info) {

   if (title != null) {
        // if we have a title to draw resize the plot rectangle
        // using the non-title space and draw the plot and title
        double width = rectangle2D.getWidth(); 

        double titleHeight = title.getPreferredHeight(graphics2D, (float) width); 
        double plotHeight = rectangle2D.getHeight() - titleHeight; 

        Rectangle2D plotRect = new Rectangle2D.Double( 
                rectangle2D.getX(), 
                rectangle2D.getY() + titleHeight, 
                rectangle2D.getWidth(), 
                plotHeight); 

        drawImpl(graphics2D, plotRect, point2D, plotState, plotRenderingInfo); 

        Rectangle2D dataArea = plotRenderingInfo.getDataArea(); 

        Rectangle2D titleRect = new Rectangle2D.Double( 
                dataArea.getX(), 
                dataArea.getY() - titleHeight, 
                dataArea.getWidth(), 
                titleHeight); 

        title.draw(graphics2D, titleRect); 
   }
   else {
        drawImpl(graphics2D, plotRect, point2D, plotState, plotRenderingInfo);
   } 

}
        
This of course would require drawImpl() to be declared as an abstract method on Plot to take the place of the current draw() method and all subclasses would need to override this instead. Doesn't seem like too big a deal since it's really and internal change and doesn't affect the public API.

Also my preference is to have the title drawn centered over the data area rather than over the entire plot area b/c this gives very nice results w/ xy plots as my example above shows. However, it might be nice to control this as well as other things like whether the title gets drawn above, below, or to the side of the plot.

Warning the code above hasn't been tested yet but I give it a shot tomorrow back at work :)

Tim

Locked