KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > jcckit > GraphicsPlotCanvas


1 /*
2  * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved
3  *
4  * This library is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License as published by
6  * the Free Software Foundation; either version 2.1 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU Lesser General Public License for more details
13  * (http://www.gnu.org/copyleft/lesser.html).
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  */

19 package jcckit;
20
21 import java.awt.BorderLayout JavaDoc;
22 import java.awt.Canvas JavaDoc;
23 import java.awt.Component JavaDoc;
24 import java.awt.Dimension JavaDoc;
25 import java.awt.Frame JavaDoc;
26 import java.awt.Graphics JavaDoc;
27 import java.awt.Image JavaDoc;
28 import java.awt.event.WindowAdapter JavaDoc;
29 import java.awt.event.WindowEvent JavaDoc;
30 import java.util.Properties JavaDoc;
31
32 import jcckit.data.DataPlot;
33 import jcckit.graphic.GraphPoint;
34 import jcckit.graphic.GraphicalElement;
35 import jcckit.graphic.Renderer;
36 import jcckit.plot.Plot;
37 import jcckit.plot.PlotCanvas;
38 import jcckit.plot.PlotEvent;
39 import jcckit.plot.PlotEventType;
40 import jcckit.renderer.GraphicsRenderer;
41 import jcckit.renderer.Transformation;
42 import jcckit.util.ConfigParameters;
43 import jcckit.util.ConfigParametersBasedConfigData;
44 import jcckit.util.Factory;
45 import jcckit.util.PropertiesBasedConfigData;
46
47 /**
48  * Class which handles plotting into a <tt>Graphics</tt> context based on
49  * the {@link jcckit.renderer.GraphicsRenderer}.
50  * This class is not a subclass of <tt>java.awt.Component</tt>.
51  * The actual AWT component presenting the plot is an innerclass. Its
52  * instance wrapped by <tt>GraphicsPlotCanvas</tt> can be obtained with
53  * {@link #getGraphicsCanvas}.
54  * <p>
55  * The plot is painted by using double-buffering and pre-rendered
56  * view of the coordinate system. That is, the coordinate system is
57  * drawn into an off-screen image. It will be redrawn only if the
58  * size of the embedding AWT component is changed.
59  *
60  * @author Franz-Josef Elmer
61  */

62 public class GraphicsPlotCanvas extends PlotCanvas {
63   /** Key of a configuration parameter. */
64   public static final String JavaDoc BACKGROUND_KEY = "background",
65                              FOREGROUND_KEY = "foreground",
66                              DOUBLE_BUFFERING_KEY = "doubleBuffering";
67                      
68   /**
69    * Class which does the actual painting. Needs the <tt>Component</tt>
70    * into which the plot is painted for some resources like size,
71    * background color, etc.
72    *
73    * @author Franz-Josef Elmer
74    */

75   protected class GraphicsPainter {
76     private final Component JavaDoc _component;
77     private Image JavaDoc _buffer;
78     private Image JavaDoc _coordinateSystem;
79     private Graphics JavaDoc _bufferGraphics;
80     private Dimension JavaDoc _currentSize;
81
82     /**
83      * Creates an instance for the specified component.
84      * @param component AWT or Swing component.
85      */

86     public GraphicsPainter(Component JavaDoc component) {
87       _component = component;
88     }
89
90     /**
91      * Paints the plot. If {@link GraphicsPlotCanvas#_doubleBuffering}
92      * is set double-buffering and pre-rendered view of
93      * the coordinate system is used.
94      */

95     public void paint(Graphics JavaDoc g)
96     {
97       Dimension JavaDoc size = _component.getSize();
98       if (size.width <= 0)
99       {
100         size.width = 1;
101       }
102       if (size.height <= 0)
103       {
104         size.height = 1;
105       }
106       if (_reset || !size.equals(_currentSize))
107       {
108         init(size);
109       }
110       //long time = System.currentTimeMillis();
111
Plot plot = getPlot();
112       drawCoordinateSystem(size, plot, g);
113       drawPlot(plot, _doubleBuffering ? _bufferGraphics : g);
114       if (_doubleBuffering)
115       {
116         g.drawImage(_buffer, 0, 0, null);
117       }
118       if (_marker != null)
119       {
120         _marker.renderWith(createRenderer(g));
121       }
122       //System.out.println((System.currentTimeMillis() - time) + " msec");
123
}
124     
125     private void drawPlot(Plot plot, Graphics JavaDoc g)
126     {
127       prepare(g);
128       if (_doubleBuffering)
129       {
130         g.drawImage(_coordinateSystem, 0, 0, null);
131       }
132       Renderer renderer = createRenderer(g);
133       GraphicalElement[] curves = plot.getCurves();
134       for (int i = 0; i < curves.length; i++) {
135         curves[i].renderWith(renderer);
136       }
137       GraphicalElement annotation = plot.getAnnotation();
138       if (annotation != null)
139       {
140         annotation.renderWith(renderer);
141       }
142       if (plot.isLegendVisible()) {
143         plot.getLegend().renderWith(renderer);
144       }
145     }
146
147     private void init(Dimension JavaDoc size)
148     {
149       _reset = false;
150       _currentSize = size;
151       if (_buffer != null)
152       {
153         _buffer.flush();
154         _bufferGraphics.dispose();
155       }
156       if (_doubleBuffering)
157       {
158         _buffer = _component.createImage(size.width, size.height);
159         _bufferGraphics = _buffer.getGraphics();
160       }
161       if (_coordinateSystem != null)
162       {
163         _coordinateSystem.flush();
164         _coordinateSystem = null;
165       }
166       calculateTransformation(size);
167     }
168
169     private void drawCoordinateSystem(Dimension JavaDoc size, Plot plot, Graphics JavaDoc g)
170     {
171       if (_coordinateSystem == null || _doubleBuffering == false)
172       {
173         if (_doubleBuffering)
174         {
175           _coordinateSystem = _component.createImage(size.width, size.height);
176           g = _coordinateSystem.getGraphics();
177         }
178         g.setColor(_component.getBackground());
179         g.fillRect(0, 0, size.width, size.height);
180         g.setColor(_component.getForeground());
181         plot.getCoordinateSystem().renderWith(createRenderer(g));
182         if (_doubleBuffering)
183         {
184           g.dispose();
185         }
186       }
187     }
188
189     /**
190      * Prepare graphics context before drawing the pre-rendered view of
191      * the coordinate system. Does nothing but will be used in subclasses.
192      */

193     protected void prepare(Graphics JavaDoc g) {}
194
195     /**
196      * Calculate the transformation form device-independent coordinates
197      * into device-dependent coordinates according to the specified
198      * canvas size.
199      */

200     protected void calculateTransformation(Dimension JavaDoc size) {
201       _transformation = new Transformation(size.width, size.height,
202               getPaper(), getHorizontalAnchor(), getVerticalAnchor());
203     }
204     
205     /**
206      * Creates an appropriated {@link Renderer} for the specified
207      * <tt>Graphics</tt> context.
208      */

209     protected Renderer createRenderer(Graphics JavaDoc g) {
210       return ((GraphicsRenderer) Factory.create(_renderer))
211                                       .init(g, _component, _transformation);
212     }
213   }
214
215   /**
216    * AWT component which actually shows the rendered plot.
217    *
218    * @author Franz-Josef Elmer
219    */

220   protected class GraphicsCanvas extends Canvas JavaDoc {
221     /** Painter which does the actual painting. */
222     protected GraphicsPainter _painter;
223     
224     /**
225      * Creates an instance with an appropriated
226      * {@link GraphicsPlotCanvas.GraphicsPainter}.
227      */

228     public GraphicsCanvas() {
229       super();
230       _painter = new GraphicsPainter(this);
231     }
232
233     /** Handles the event. Just invokes <tt>repaint()</tt>. */
234     public void handleEvent(PlotEvent event) {
235       repaint();
236     }
237
238     /** Directly invokes <tt>paint</tt>. */
239     public void update(Graphics JavaDoc g) {
240       paint(g);
241     }
242
243     /**
244      * Paints the plot. If {@link GraphicsPlotCanvas#_doubleBuffering}
245      * is set double-buffering and pre-rendered view of
246      * the coordinate system is used.
247      */

248     public void paint(Graphics JavaDoc g) {
249       _painter.paint(g);
250     }
251   } // end class GraphicsCanvas
252

253   private Transformation _transformation;
254   private boolean _reset = true;
255   private boolean _doubleBuffering;
256   private String JavaDoc _renderer = "jcckit.renderer.GraphicsRenderer";
257
258   /** Wrapped AWT component. */
259   protected GraphicsCanvas _canvas;
260   
261   private GraphicalElement _marker;
262
263   /**
264    * Creates an instance from the specified configuration parameters.
265    * <table border=1 cellpadding=5>
266    * <tr><th>Key &amp; Default Value</th><th>Type</th><th>Mandatory</th>
267    * <th>Description</th></tr>
268    * <tr><td><tt>background = </tt><i>default background color of the wrapped
269    * AWT component</i></td>
270    * <td><tt>Color</tt></td><td>no</td>
271    * <td>Background color of the wrapped AWT component.</td></tr>
272    * <tr><td><tt>foreground = </tt><i>default foreground color of the wrapped
273    * AWT component</i></td>
274    * <td><tt>Color</tt></td><td>no</td>
275    * <td>Foreground color of the wrapped AWT component.</td></tr>
276    * <tr><td><tt>doubleBuffering = true</td>
277    * <td><tt>boolean</tt></td><td>no</td>
278    * <td>If <tt>true</tt> the plot will be painted by using
279    * double-buffering and pre-rendered view of the coordinate system.
280    * </td></tr>
281    * </table>
282    * In addition the configuration parameters of the
283    * <a HREF="plot/PlotCanvas.html#PlotCanvas(jcckit.util.ConfigParameters)">
284    * constructor</a> of the superclass {@link jcckit.plot.PlotCanvas} apply.
285    */

286   public GraphicsPlotCanvas(ConfigParameters config) {
287     super(config);
288     createGraphicsCanvas();
289     _doubleBuffering = config.getBoolean(DOUBLE_BUFFERING_KEY, true);
290     _canvas.setBackground(config.getColor(BACKGROUND_KEY,
291                                           _canvas.getBackground()));
292     _canvas.setForeground(config.getColor(FOREGROUND_KEY,
293                                           _canvas.getForeground()));
294   }
295   
296   /**
297    * Sets the renderer used to render the plot. The default value is
298    * {@link GraphicsRenderer}.
299    * @param className Fully qualified name of the renderer class.
300    */

301   public void setRenderer(String JavaDoc className) {
302     _renderer = className;
303   }
304
305   /**
306    * Sets the flag for double buffering. For off-screen rendering this
307    * flag has to be set <tt>false</tt>.
308    */

309   public void setDoubleBuffering(boolean doubleBuffering)
310   {
311     _doubleBuffering = doubleBuffering;
312   }
313   
314   /**
315    * Draws the plot into the specified image. Can be used for off-screen
316    * renderering if double-buffering is switched off and if all texts
317    * are not rotated. Otherwise <tt>NullPointerException</tt> will be
318    * thrown.
319    */

320   public void drawInto(Image JavaDoc image)
321   {
322     _canvas.setSize(image.getWidth(null), image.getHeight(null));
323     _canvas.paint(image.getGraphics());
324   }
325   
326   /**
327    * Creates an instance of {@link GraphicsCanvas}
328    * which wraps the rendered plot.
329    */

330   protected void createGraphicsCanvas() {
331     _canvas = new GraphicsCanvas();
332   }
333
334   /** Repaints the wrapping GUI component. */
335   public void plotChanged(PlotEvent event) {
336     if (event.getType() == PlotEventType.COODINATE_SYSTEM_CHANGED)
337     {
338       _reset = true;;
339     }
340     _canvas.handleEvent(event);
341   }
342
343   /**
344    * Returns an AWT component which wraps the rendered plot.
345    * Note that the returned <tt>Canvas</tt> object has preferred size zero.
346    * This is important to know when used with certain LayoutManagers like
347    * <tt>FlowLayout</tt>.
348    */

349   public Canvas JavaDoc getGraphicsCanvas() {
350     return _canvas;
351   }
352   
353   /**
354    * Maps the cursor position onto a point in device-independent coordinates.
355    * @param x X-coordinate of the cursor.
356    * @param y Y-coordinate of the cursor.
357    */

358   public GraphPoint mapCursorPosition(int x, int y) {
359     return _transformation.transformBack(x, y);
360   }
361   
362   /**
363    * Defines a graphical marker which will be drawn on top of the plot.
364    * To remove the marker call this method with argument <tt>null</tt>.
365    * @param marker Marker element. Can be <tt>null</tt>.
366    */

367   public void setMarker(GraphicalElement marker)
368   {
369     _marker = marker;
370   }
371
372   /**
373    * Shows a plot in a <tt>Frame</tt>. The plot (data and layout) is
374    * defined in the <tt>.properties</tt> file specified by the first
375    * command line argument.
376    * <p>
377    * Usage: <tt>java jcckit.GraphicsPlotCanvas [-r &lt;renderer class&gt;]
378    * &lt;<i>properties file</i>&gt;</tt>
379    */

380   public static void main(String JavaDoc[] args) throws Exception JavaDoc {
381     run(args, "jcckit.GraphicsPlotCanvas");
382   }
383   
384   protected static void run(String JavaDoc[] args, String JavaDoc plotCanvas)
385                         throws Exception JavaDoc {
386     if (args.length == 0) {
387       printUsageAndExit(plotCanvas);
388     }
389     String JavaDoc file = args[0];
390     String JavaDoc renderer = null;
391     if (file.equals("-r")) {
392       if (args.length > 2) {
393         renderer = args[1];
394         file = args[2];
395       } else {
396         printUsageAndExit(plotCanvas);
397       }
398     }
399     Properties JavaDoc p = new Properties JavaDoc();
400     p.put(Factory.CLASS_NAME_KEY, plotCanvas);
401     ConfigParameters config
402         = new ConfigParameters(
403               new ConfigParametersBasedConfigData(
404                   new ConfigParameters(new PropertiesBasedConfigData(file)),
405                   new ConfigParameters(new PropertiesBasedConfigData(p))));
406     GraphicsPlotCanvas canvas = (GraphicsPlotCanvas) Factory.create(config);
407     if (renderer != null) {
408       canvas.setRenderer(renderer);
409     }
410     canvas.connect(DataPlot.create(config));
411     
412     Frame JavaDoc frame = new Frame JavaDoc("JCCKit: " + file);
413     frame.addWindowListener(new WindowAdapter JavaDoc() {
414               public void windowClosing(WindowEvent JavaDoc event) {
415                 System.exit(0);
416               }
417             }
418           );
419     frame.add(canvas.getGraphicsCanvas(), BorderLayout.CENTER);
420     frame.setSize(666, 555);
421     frame.show();
422   }
423   
424   private static void printUsageAndExit(String JavaDoc plotCanvas) {
425     System.out.println("Usage: java " + plotCanvas
426                        + " [-r <renderer class>] <properties file>");
427     System.exit(0);
428   }
429 }
430
Popular Tags