KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > nightlabs > editor2d > figures > OversizedBufferFreeformLayer


1 /* *****************************************************************************
2  * NightLabs Editor2D - Graphical editor framework *
3  * Copyright (C) 2004-2005 NightLabs - http://NightLabs.org *
4  * Project author: Daniel Mazurek <Daniel.Mazurek [at] nightlabs [dot] org> *
5  * *
6  * This library is free software; you can redistribute it and/or *
7  * modify it under the terms of the GNU Lesser General Public *
8  * License as published by the Free Software Foundation; either *
9  * version 2.1 of the License, or (at your option) any later version. *
10  * *
11  * This library is distributed in the hope that it will be useful, *
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
14  * Lesser General Public License for more details. *
15  * *
16  * You should have received a copy of the GNU Lesser General Public *
17  * License along with this library; if not, write to the *
18  * Free Software Foundation, Inc., *
19  * 51 Franklin St, Fifth Floor, *
20  * Boston, MA 02110-1301 USA *
21  * *
22  * Or get it online : *
23  * http://www.gnu.org/copyleft/lesser.html *
24  * *
25  * *
26  ******************************************************************************/

27
28 package org.nightlabs.editor2d.figures;
29
30 import java.awt.Color JavaDoc;
31 import java.awt.Graphics2D JavaDoc;
32 import java.awt.image.BufferedImage JavaDoc;
33 import java.util.Iterator JavaDoc;
34 import java.util.LinkedList JavaDoc;
35 import java.util.List JavaDoc;
36
37 import org.apache.log4j.Logger;
38 import org.eclipse.draw2d.Figure;
39 import org.eclipse.draw2d.FreeformFigure;
40 import org.eclipse.draw2d.FreeformListener;
41 import org.eclipse.draw2d.Graphics;
42 import org.eclipse.draw2d.IFigure;
43 import org.eclipse.draw2d.J2DGraphics;
44 import org.eclipse.draw2d.Layer;
45 import org.eclipse.draw2d.geometry.Point;
46 import org.eclipse.draw2d.geometry.Rectangle;
47 import org.eclipse.gef.EditPart;
48 import org.eclipse.gef.EditPartViewer;
49 import org.eclipse.gef.ui.parts.ScrollingGraphicalViewer;
50 import org.eclipse.swt.widgets.Control;
51 import org.holongate.j2d.J2DRegistry;
52
53 import org.nightlabs.editor2d.util.EditorUtil;
54
55 /**
56  * Buffers its contents for optimized painting.
57  *
58  * @author Daniel Mazurek
59  * @author Alexander Bieber <alex[AT]nightlabs[DOT]de>
60  */

61 public class OversizedBufferFreeformLayer
62 extends Layer
63 implements FreeformFigure, BufferedFreeformLayer
64 {
65     public static final Logger LOGGER = Logger.getLogger(OversizedBufferFreeformLayer.class);
66     
67     // private FreeformHelper helper = new FreeformHelper(this);
68
private LayerFreeformHelper helper = new LayerFreeformHelper(this);
69     
70     /**
71      * The offscreen buffer
72      */

73     private BufferedImage JavaDoc bufferedImage;
74     /**
75      * The control is needed to know the buffers needed size
76      */

77     private Control viewerControl;
78     /**
79      * The editpart is needed for EditorUtil methods and
80      * to retrieve the control. It is passed to the constructor
81      */

82     private EditPart editPart;
83     /**
84      * Current zoom, buffer will be cleared if the
85      * editPart's zoom differes from that
86      */

87     private double currentZoom = 1.0;
88     /**
89      * The scroll offset at the time when the buffer was (re)created
90      */

91     private Point bufferedScrollOffset;
92     /**
93      * The current size of the associated Control
94      */

95     private Point currentSize = new Point(0,0);
96     /**
97      * The current size of the buffer
98      */

99     private Point bufferSize = new Point(0,0);
100     /**
101      * The translation within the buffer caused by its size
102      * given in coordinatates of the controls
103      * system so not scaled with the current zoom
104      */

105     private Point bufferTranslation = new Point(0,0);
106     /**
107      * The origin within the buffer for the copy operation used in paint
108      */

109     private Point bufferOrigin = new Point(0,0);
110     /**
111      * To be able to paint children even if not an instance of RendererFigure
112      */

113     private List JavaDoc nonDCFChildren = new LinkedList JavaDoc();
114     
115     
116     protected Point calculateBufferFactors() {
117         Point result = new Point(1,1);
118         Point realSizeBounds = EditorUtil.toAbsolute(editPart, currentSize.x, currentSize.y);
119         Point so = EditorUtil.getScrollOffset(editPart);
120 // Point realSO = EditorUtil.toAbsolute(editPart, so.x, so.y);
121
Rectangle childBound = getChildBounds();
122         if (childBounds == null)
123             return result;
124         if (realSizeBounds.x >= childBound.width && realSizeBounds.y >= childBound.height) {
125             // all children fit in the control
126
// do not overdimension buffer
127
return result;
128         }
129         else {
130             int addX = 1;
131             int addY = 1;
132             if (so.x > 0)
133                 addX = 2;
134             if (so.y > 0)
135                 addY = 2;
136             result.setLocation(
137                     Math.min(4, (childBound.width / realSizeBounds.x)+addX),
138                     Math.min(4, (childBound.height / realSizeBounds.y)+addY)
139                 );
140         }
141 // LOGGER.debug("Calculated buffer factors: "+result);
142
return result;
143     }
144     
145     /**
146      * Returns the offscreen buffer (recrates if neccassary) and sets
147      * {@link #bufferOrigin} to the correct value concerning the
148      * current scroll offset.
149      *
150      * @return The offscreen buffer
151      */

152     protected BufferedImage JavaDoc getBufferedImage()
153     {
154         double tmpZoom = EditorUtil.getZoom(editPart);
155         if (tmpZoom != currentZoom) {
156             // clear buffer if zoom changed
157
currentZoom = EditorUtil.getZoom(editPart);
158             clearBuffer();
159         }
160         if (bufferedScrollOffset == null) {
161             clearBuffer();
162         }
163         if (bufferedImage == null) {
164             long time = System.currentTimeMillis();
165             currentSize.setLocation(viewerControl.getSize().x, viewerControl.getSize().x);
166             Point factors = calculateBufferFactors();
167             bufferSize.setLocation(currentSize.x * factors.x, currentSize.y*factors.y);
168             if (bufferedImage == null) {
169                 bufferedImage = new BufferedImage JavaDoc(bufferSize.x, bufferSize.y, BufferedImage.TYPE_INT_ARGB);
170             }
171             Graphics2D JavaDoc bufferedGraphics = bufferedImage.createGraphics();
172 // bufferedGraphics.copyArea()
173
try {
174                 bufferedGraphics.setClip(null);
175                 bufferedGraphics.scale(currentZoom, currentZoom);
176                 bufferedScrollOffset = EditorUtil.getScrollOffset(editPart);
177                 Point offsetTranslation = EditorUtil.toAbsolute(
178                         editPart,
179                         bufferedScrollOffset.x,
180                         bufferedScrollOffset.y
181                 );
182                 bufferTranslation.setLocation((bufferSize.x - currentSize.x) / 2, (bufferSize.y - currentSize.y) / 2);
183                 Point absoluteBufferTranslation = EditorUtil.toAbsolute(
184                         editPart,
185                         bufferTranslation.x,
186                         bufferTranslation.y
187                         
188                 );
189                 bufferedGraphics.translate(
190                         absoluteBufferTranslation.x-offsetTranslation.x,
191                         absoluteBufferTranslation.y-offsetTranslation.y
192                 );
193                 J2DRegistry.initGraphics(bufferedGraphics);
194                 nonDCFChildren.clear();
195                 for (Iterator JavaDoc iter = getChildren().iterator(); iter.hasNext();)
196                 {
197                     Figure figure = (Figure) iter.next();
198                     if (figure instanceof RendererFigure) {
199                         // let all children draw on the buffer
200
((RendererFigure)figure).paint(bufferedGraphics);
201                     }
202                     else {
203                         // Figure can not draw on a Graphics2D
204
// will be painted unbuffered
205
nonDCFChildren.add(figure);
206                     }
207                 }
208                 LOGGER.debug("buffer created in "+(System.currentTimeMillis()-time)+" ms");
209             }
210             finally {
211                 if (bufferedGraphics != null)
212                 bufferedGraphics.dispose();
213             }
214             
215         }
216         Point scrollOffset = EditorUtil.getScrollOffset(editPart);
217         bufferOrigin.setLocation(0,0);
218         bufferOrigin.translate(
219             (scrollOffset.x-bufferedScrollOffset.x)+bufferTranslation.x,
220             (scrollOffset.y-bufferedScrollOffset.y)+bufferTranslation.y
221         );
222         if (
223                 (bufferOrigin.x < 0 || bufferOrigin.y < 0) ||
224                 (bufferOrigin.x > (bufferSize.x - currentSize.x) || bufferOrigin.y > (bufferSize.y - currentSize.y))
225             ) {
226             // clear buffer if region to copy is outside
227
// of the buffer
228
clearBuffer();
229             return getBufferedImage();
230         }
231         return bufferedImage;
232     }
233     
234     public void paint(Graphics graphics)
235     {
236 // LOGGER.debug("paint called");
237
long time = System.currentTimeMillis();
238         if (graphics instanceof J2DGraphics)
239         {
240             J2DGraphics j2dGraphics = (J2DGraphics)graphics;
241 // j2dGraphics.clipRect(null);
242

243             // get / create the buffer
244
BufferedImage JavaDoc buffer = getBufferedImage();
245             
246             // create the Graphics where the buffer is drawn on
247
Graphics2D JavaDoc g2d = j2dGraphics.createGraphics2D();
248             // scale it invers of the current zoom ...
249
g2d.scale(1/currentZoom, 1/currentZoom);
250             // and translate it with the current scroll offset
251
// so 0,0 will be drawn on top left of the control
252
Point scrollOffset = EditorUtil.getScrollOffset(editPart);
253             g2d.translate(scrollOffset.x, scrollOffset.y);
254             
255             // now copy the buffer region
256
g2d.setPaint(Color.WHITE);
257             g2d.fillRect(-2, -2, currentSize.x+2, currentSize.y+2);
258             g2d.drawImage(
259                 buffer,
260                 0, 0, currentSize.x, currentSize.y,
261                 bufferOrigin.x, bufferOrigin.y, bufferOrigin.x+currentSize.x, bufferOrigin.y+currentSize.y,
262                 null
263             );
264             g2d.dispose();
265             // Paint all children that are not an instance of DrawComponentFigure
266
for (Iterator JavaDoc iter = nonDCFChildren.iterator(); iter.hasNext();) {
267                 Figure figure = (Figure) iter.next();
268                 figure.paint(graphics);
269             }
270         }
271         else {
272             super.paint(graphics);
273         }
274 // LOGGER.debug("painted in "+(System.currentTimeMillis()-time));
275
}
276             
277     protected void clearBuffer() {
278         // TODO: make sure this is called when editor is closed
279
if (bufferedImage != null) {
280             bufferedImage.flush();
281 // long time = System.currentTimeMillis();
282
// System.gc();
283
// LOGGER.debug("gc() took "+(System.currentTimeMillis()-time)+" ms");
284
}
285         bufferedImage = null;
286         childBounds = null;
287         LOGGER.debug("buffer cleared()");
288     }
289     
290     
291     /**
292      * @see BufferedFreeformLayer#refresh()
293      */

294     public void refresh() {
295         clearBuffer();
296     }
297
298     /**
299      * @see BufferedFreeformLayer#refresh(Figure)
300      */

301     public void refresh(IFigure figure) {
302         clearBuffer();
303     }
304     
305 // public void refresh(List figures) {
306
// clearBuffer();
307
// }
308

309     private Rectangle childBounds;
310     
311     protected Rectangle getChildBounds()
312     {
313         if (childBounds == null) {
314             for (Iterator JavaDoc iter = getChildren().iterator(); iter.hasNext();) {
315                 Figure figure = (Figure) iter.next();
316                 Rectangle figureBounds = figure.getBounds();
317                 if (childBounds == null)
318                     childBounds = new Rectangle(figureBounds);
319                 else
320                     childBounds.union(figureBounds);
321             }
322         }
323         return childBounds;
324     }
325     
326     /**
327      * Constructs a new OversizedBufferFreeformLayer. The
328      * root of the given editPart is consulted to
329      * retrieve the parent Graphical viewer and
330      * its Control.
331      *
332      * @param editPart The editPart.
333      */

334     public OversizedBufferFreeformLayer()
335     {
336         //TODO remove this workaround, and instead try to catch the Layer-selection in the outline
337
// I think this is ok now (Alex)
338
super.setBounds(new Rectangle(-Integer.MAX_VALUE / 2, -Integer.MAX_VALUE / 2, Integer.MAX_VALUE, Integer.MAX_VALUE));
339     }
340     
341     public void init(EditPart editPart) {
342         this.editPart = editPart;
343         EditPartViewer viewer = editPart.getRoot().getViewer();
344         if (viewer instanceof ScrollingGraphicalViewer) {
345             ScrollingGraphicalViewer graphicalViewer = (ScrollingGraphicalViewer) viewer;
346             Control control = graphicalViewer.getControl();
347             this.viewerControl = control;
348         }
349     }
350     
351     /**
352      * @see IFigure#add(IFigure, Object, int)
353      */

354     public void add(IFigure child, Object JavaDoc constraint, int index) {
355         super.add(child, constraint, index);
356         helper.hookChild(child);
357         clearBuffer();
358     }
359     
360     /**
361      * @see FreeformFigure#addFreeformListener(FreeformListener)
362      */

363     public void addFreeformListener(FreeformListener listener) {
364         addListener(FreeformListener.class, listener);
365     }
366     
367     /**
368      * @see FreeformFigure#fireExtentChanged()
369      */

370     public void fireExtentChanged() {
371         Iterator JavaDoc iter = getListeners(FreeformListener.class);
372         while (iter.hasNext())
373             ((FreeformListener)iter.next())
374             .notifyFreeformExtentChanged();
375     }
376     
377 // /**
378
// * Overrides to do nothing.
379
// * @see Figure#fireMoved()
380
// */
381
// protected void fireMoved() { }
382

383     /**
384      * @see FreeformFigure#getFreeformExtent()
385      */

386     public Rectangle getFreeformExtent() {
387         return helper.getFreeformExtent();
388     }
389     
390     /**
391      * @see Figure#primTranslate(int, int)
392      */

393     public void primTranslate(int dx, int dy) {
394         bounds.x += dx;
395         bounds.y += dy;
396     }
397     
398     /**
399      * @see IFigure#remove(IFigure)
400      */

401     public void remove(IFigure child) {
402         helper.unhookChild(child);
403         super.remove(child);
404         clearBuffer();
405     }
406     
407     /**
408      * @see FreeformFigure#removeFreeformListener(FreeformListener)
409      */

410     public void removeFreeformListener(FreeformListener listener) {
411         removeListener(FreeformListener.class, listener);
412     }
413     
414     /**
415      * @see FreeformFigure#setFreeformBounds(Rectangle)
416      */

417     public void setFreeformBounds(Rectangle bounds)
418     {
419 // clearBuffer();
420
// LOGGER.debug("setFreeformBounds("+bounds+")");
421
// helper.setFreeformBounds(bounds);
422
}
423     
424     public void setBounds(Rectangle rect)
425     {
426 // clearBuffer();
427
// LOGGER.debug("setBounds("+rect+")");
428
// super.setBounds(rect);
429
}
430         
431 }
432
Popular Tags