KickJava   Java API By Example, From Geeks To Geeks.

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


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.Graphics2D JavaDoc;
31 import java.util.ArrayList JavaDoc;
32 import java.util.Collection JavaDoc;
33 import java.util.HashMap JavaDoc;
34 import java.util.HashSet JavaDoc;
35 import java.util.Iterator JavaDoc;
36 import java.util.LinkedList JavaDoc;
37 import java.util.List JavaDoc;
38 import java.util.Map JavaDoc;
39 import java.util.Set JavaDoc;
40
41 import org.eclipse.draw2d.Figure;
42 import org.eclipse.draw2d.Graphics;
43 import org.eclipse.draw2d.IFigure;
44 import org.eclipse.draw2d.geometry.Dimension;
45 import org.eclipse.draw2d.geometry.Point;
46 import org.eclipse.draw2d.geometry.Rectangle;
47
48 /**
49  *
50  * @author Alexander Bieber <alex[at]nightlabs[DOT]de>
51  *
52  */

53 public class SmartUpdateFigure
54     extends Figure
55     implements ISmartUpdateFigure
56 {
57     /**
58      * Inner tile class.
59      */

60     private static class Tile implements FigureTile {
61         
62         private Rectangle bounds;
63         private String JavaDoc key;
64         private List JavaDoc figures = new LinkedList JavaDoc();
65         
66         public Tile(Rectangle bounds) {
67             this.bounds = bounds;
68         }
69         
70         public String JavaDoc getKey() {
71             if (key == null)
72                 key = getTileKey(bounds.x, bounds.y);
73             return key;
74         }
75
76         /**
77          * @see org.nightlabs.editor2d.figures.FigureTile#intersects(org.eclipse.draw2d.geometry.Rectangle)
78          */

79         public boolean intersects(Rectangle rect) {
80             return bounds.intersects(rect);
81         }
82
83         /**
84          * @see org.nightlabs.editor2d.figures.FigureTile#getBounds()
85          */

86         public Rectangle getBounds() {
87             return bounds;
88         }
89         
90         /**
91          * @see org.nightlabs.editor2d.figures.FigureTile#getTileFigures()
92          */

93         public Collection JavaDoc getTileFigures() {
94             return figures;
95         }
96
97         /**
98          * @see org.nightlabs.editor2d.figures.FigureTile#addFigure(org.eclipse.draw2d.Figure)
99          */

100         public void addFigure(IFigure figure) {
101             if (!figures.contains(figure))
102                 figures.add(figure);
103         }
104
105         /**
106          * @see org.nightlabs.editor2d.figures.FigureTile#removeFigure(org.eclipse.draw2d.Figure)
107          */

108         public void removeFigure(IFigure figure) {
109             figures.remove(figure);
110         }
111
112         /**
113          * @see org.nightlabs.editor2d.figures.FigureTile#getIntersectionFigures(org.eclipse.draw2d.geometry.Rectangle)
114          */

115         public Collection JavaDoc getIntersectingFigures(Rectangle rect) {
116             List JavaDoc result = new ArrayList JavaDoc();
117             for (Iterator JavaDoc iter = figures.iterator(); iter.hasNext();) {
118                 Figure figure = (Figure) iter.next();
119                 if (figure.intersects(rect)) {
120                     result.add(figure);
121                 }
122             }
123             return result;
124         }
125         
126     }
127     
128     /**
129      * key: String: (x,y) upper left tile corner <br/>
130      * value: FigureTile: The FigureTile for this tile
131      */

132     private Map JavaDoc tiles = new HashMap JavaDoc();
133     
134     /**
135      * key Figure: childfigure <br/>
136      * value: Set of FigureTiles
137      */

138     private Map JavaDoc figuresInTiles = new HashMap JavaDoc();
139
140     /**
141      * The tile dimension calculated in {@link #rebuildTiles()}
142      */

143     private Dimension tileDimension;
144     
145     /**
146      * EveryTime on rebuild this method is
147      * consulted for the new tile dimensions.
148      * This implementation returns
149      * x = bounds.x/round(sqrt(childCount)) and
150      * y = bounds.y/round(sqrt(childCount))
151      * May be overridden.
152      *
153      * @return Optimal? tile dimensions for this Figure
154      */

155     protected Dimension calculateTileDimension() {
156         Dimension dim = new Dimension();
157         int fraction = (int)Math.round(Math.sqrt(getChildren().size()));
158         if (fraction == 0) {
159             dim.width = 0;
160             dim.height = 0;
161         }
162         else {
163             dim.width = getBounds().width / fraction;
164             dim.height = getBounds().height / fraction;
165         }
166         return dim;
167     }
168     
169     public static String JavaDoc getTileKey(int x, int y) {
170         return "("+x+","+y+")";
171     }
172     
173     /**
174      * Retrieve the FigureTile at the given Position.
175      * Autocreate if not existent.
176      */

177     protected FigureTile getTile(int x, int y) {
178         String JavaDoc tileKey = getTileKey(x, y);
179         FigureTile figureTile = (FigureTile)tiles.get(tileKey);
180         if (figureTile == null) {
181             figureTile = new Tile(new Rectangle(x, y, tileDimension.width, tileDimension.height));
182             tiles.put(tileKey, figureTile);
183         }
184         return figureTile;
185     }
186     
187     /**
188      * Get all tiles this figure is registered in.
189      *
190      * @param figure The figure
191      * @return The figures tiles.
192      */

193     protected Set JavaDoc getTilesForFigure(IFigure figure) {
194         Set JavaDoc figureTiles = (Set JavaDoc)figuresInTiles.get(figure);
195         if (figureTiles == null) {
196             figureTiles = new HashSet JavaDoc();
197             figuresInTiles.put(figure, figureTiles);
198         }
199         return figureTiles;
200     }
201     
202     /**
203      * Get the top left Position of the
204      * tile this point is in.
205      *
206      * @param x The points x
207      * @param y The points y
208      */

209     protected Point getTileTopLeft(int x, int y) {
210         return new Point(
211                 (x/tileDimension.width) * tileDimension.width,
212                 (y/tileDimension.height) * tileDimension.height
213             );
214     }
215     
216     /**
217      * Integrates the given figure in the current tile build.
218      * Makes sure that the registrations in the tile maps are
219      * correct after execution.
220      *
221      * @param figure The figure to integrate
222      */

223     protected void integrateFigure(IFigure figure) {
224         Rectangle figureBounds = figure.getBounds();
225         Point topLefTilePosition = getTileTopLeft(figureBounds.x, figureBounds.y);
226         Point bottomRightTilePosition = getTileTopLeft(figureBounds.x + figureBounds.width, figureBounds.y+figureBounds.height);
227         
228         // clear registration in current build
229
Set JavaDoc figureTiles = getTilesForFigure(figure);
230         for (Iterator JavaDoc iter = figureTiles.iterator(); iter.hasNext();) {
231             FigureTile figureTile = (FigureTile) iter.next();
232             figureTile.removeFigure(figure);
233         }
234         figureTiles.clear();
235         
236         // reintegrate in build
237
for (int row = topLefTilePosition.y; row <= bottomRightTilePosition.y; row += tileDimension.height) {
238             for (int col = topLefTilePosition.x; col <= bottomRightTilePosition.x; col += tileDimension.width) {
239                 FigureTile figureTile = getTile(col, row);
240                 figureTile.addFigure(figure);
241                 figureTiles.add(figureTile);
242             }
243         }
244     }
245     
246     
247     private boolean tilesBuild = false;
248     /**
249      * Clears and rebuilds the tiles
250      *
251      */

252     protected void rebuildTiles() {
253         tiles.clear();
254         figuresInTiles.clear();
255         tileDimension = calculateTileDimension();
256         for (Iterator JavaDoc iter = getChildren().iterator(); iter.hasNext();) {
257             Figure figure = (Figure) iter.next();
258             integrateFigure(figure);
259         }
260     }
261     
262     /**
263      * @see org.nightlabs.editor2d.figures.ISmartUpdateFigure#paintRegion(Graphics, Rectangle)
264      */

265     public void paintRegion(Graphics graphics, Rectangle region) {
266         internalPaintRegion(graphics, region);
267     }
268
269     /**
270      * @see org.nightlabs.editor2d.figures.ISmartUpdateFigure#paintRegion(java.awt.Graphics2D, org.eclipse.draw2d.geometry.Rectangle)
271      */

272     public void paintRegion(Graphics2D JavaDoc graphics, Rectangle region) {
273         internalPaintRegion(graphics, region);
274     }
275
276     private void internalPaintRegion(Object JavaDoc graphics, Rectangle region) {
277         if (!tilesBuild)
278             rebuildTiles();
279         tilesBuild = true;
280         internalPaintSelf(graphics, region);
281         if (getChildren().size() == 0)
282             return;
283         Rectangle regionToPaint = getBounds().getIntersection(region);
284         if (regionToPaint.width == 0 && regionToPaint.height == 0)
285             return;
286         Point topLefTilePosition = getTileTopLeft(regionToPaint.x, regionToPaint.y);
287         Point bottomRightTilePosition = getTileTopLeft(regionToPaint.x + regionToPaint.width, regionToPaint.y+regionToPaint.height);
288         
289         for (int row = topLefTilePosition.y; row <= bottomRightTilePosition.y; row += tileDimension.height) {
290             for (int col = topLefTilePosition.x; col <= bottomRightTilePosition.x; col += tileDimension.width) {
291                 FigureTile figureTile = getTile(col, row);
292                 for (Iterator JavaDoc iter = figureTile.getIntersectingFigures(regionToPaint).iterator(); iter.hasNext();) {
293                     Figure figure = (Figure) iter.next();
294                     internalPaintChild(figure, graphics, regionToPaint);
295                 }
296             }
297         }
298     }
299     
300     private void internalPaintSelf(Object JavaDoc graphics, Rectangle region) {
301         if (graphics instanceof Graphics) {
302             Graphics d2dGraphics = (Graphics)graphics;
303             this.paint(d2dGraphics);
304         }
305         else if (graphics instanceof Graphics2D JavaDoc) {
306             Graphics2D JavaDoc j2dGraphics = (Graphics2D JavaDoc)graphics;
307             if (this instanceof ISmartUpdateFigure)
308                 ((ISmartUpdateFigure)this).paintRegion(j2dGraphics, region);
309             else if (this instanceof RendererFigure)
310                 ((RendererFigure)this).paint(j2dGraphics);
311         }
312     }
313     
314     private void internalPaintChild(Figure child, Object JavaDoc graphics, Rectangle regionToPaint) {
315         if (graphics instanceof Graphics) {
316             Graphics d2dGraphics = (Graphics)graphics;
317             if (child instanceof ISmartUpdateFigure)
318                 ((ISmartUpdateFigure)child).paintRegion(d2dGraphics, regionToPaint);
319             else
320                 child.paint(d2dGraphics);
321         }
322         else if (graphics instanceof Graphics2D JavaDoc) {
323             Graphics2D JavaDoc j2dGraphics = (Graphics2D JavaDoc)graphics;
324             if (child instanceof ISmartUpdateFigure)
325                 ((ISmartUpdateFigure)child).paintRegion(j2dGraphics, regionToPaint);
326             else if (child instanceof RendererFigure)
327                 ((RendererFigure)child).paint(j2dGraphics);
328         }
329     }
330
331
332     /**
333      * @see org.nightlabs.editor2d.figures.ISmartUpdateFigure#refresh()
334      */

335     public void refresh() {
336         tilesBuild = false;
337     }
338
339     /**
340      * @see org.nightlabs.editor2d.figures.ISmartUpdateFigure#refresh(org.eclipse.draw2d.Figure)
341      */

342     public void refresh(IFigure figure) {
343         if (!tilesBuild)
344             rebuildTiles();
345         tilesBuild = true;
346         integrateFigure(figure);
347     }
348     
349 }
350
Popular Tags