KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2  * Created on 03.06.2005
3  *
4  */

5 package com.nightlabs.editor2d.figures;
6
7 import java.awt.Graphics2D JavaDoc;
8 import java.util.ArrayList JavaDoc;
9 import java.util.Collection JavaDoc;
10 import java.util.HashMap JavaDoc;
11 import java.util.HashSet JavaDoc;
12 import java.util.Iterator JavaDoc;
13 import java.util.LinkedList JavaDoc;
14 import java.util.List JavaDoc;
15 import java.util.Map JavaDoc;
16 import java.util.Set JavaDoc;
17
18 import org.eclipse.draw2d.Figure;
19 import org.eclipse.draw2d.Graphics;
20 import org.eclipse.draw2d.geometry.Dimension;
21 import org.eclipse.draw2d.geometry.Point;
22 import org.eclipse.draw2d.geometry.Rectangle;
23
24 /**
25  *
26  * @author Alexander Bieber <alex[at]nightlabs[DOT]de>
27  *
28  */

29 public class SmartUpdateFigure
30     extends Figure
31     implements ISmartUpdateFigure
32 {
33     /**
34      * Inner tile class.
35      */

36     private static class Tile implements FigureTile {
37         
38         private Rectangle bounds;
39         private String JavaDoc key;
40         private List JavaDoc figures = new LinkedList JavaDoc();
41         
42         public Tile(Rectangle bounds) {
43             this.bounds = bounds;
44         }
45         
46         public String JavaDoc getKey() {
47             if (key == null)
48                 key = getTileKey(bounds.x, bounds.y);
49             return key;
50         }
51
52         /**
53          * @see com.nightlabs.editor2d.figures.FigureTile#intersects(org.eclipse.draw2d.geometry.Rectangle)
54          */

55         public boolean intersects(Rectangle rect) {
56             return bounds.intersects(rect);
57         }
58
59         /**
60          * @see com.nightlabs.editor2d.figures.FigureTile#getBounds()
61          */

62         public Rectangle getBounds() {
63             return bounds;
64         }
65         
66         /**
67          * @see com.nightlabs.editor2d.figures.FigureTile#getTileFigures()
68          */

69         public Collection JavaDoc getTileFigures() {
70             return figures;
71         }
72
73         /**
74          * @see com.nightlabs.editor2d.figures.FigureTile#addFigure(org.eclipse.draw2d.Figure)
75          */

76         public void addFigure(Figure figure) {
77             if (!figures.contains(figure))
78                 figures.add(figure);
79         }
80
81         /**
82          * @see com.nightlabs.editor2d.figures.FigureTile#removeFigure(org.eclipse.draw2d.Figure)
83          */

84         public void removeFigure(Figure figure) {
85             figures.remove(figure);
86         }
87
88         /**
89          * @see com.nightlabs.editor2d.figures.FigureTile#getIntersectionFigures(org.eclipse.draw2d.geometry.Rectangle)
90          */

91         public Collection JavaDoc getIntersectingFigures(Rectangle rect) {
92             List JavaDoc result = new ArrayList JavaDoc();
93             for (Iterator JavaDoc iter = figures.iterator(); iter.hasNext();) {
94                 Figure figure = (Figure) iter.next();
95                 if (figure.intersects(rect)) {
96                     result.add(figure);
97                 }
98             }
99             return result;
100         }
101         
102     }
103     
104     /**
105      * key: String: (x,y) upper left tile corner <br/>
106      * value: FigureTile: The FigureTile for this tile
107      */

108     private Map JavaDoc tiles = new HashMap JavaDoc();
109     
110     /**
111      * key Figure: childfigure <br/>
112      * value: Set of FigureTiles
113      */

114     private Map JavaDoc figuresInTiles = new HashMap JavaDoc();
115
116     /**
117      * The tile dimension calculated in {@link #rebuildTiles()}
118      */

119     private Dimension tileDimension;
120     
121     /**
122      * EveryTime on rebuild this method is
123      * consulted for the new tile dimensions.
124      * This implementation returns
125      * x = bounds.x/round(sqrt(childCount)) and
126      * y = bounds.y/round(sqrt(childCount))
127      * May be overridden.
128      *
129      * @return Optimal? tile dimensions for this Figure
130      */

131     protected Dimension calculateTileDimension() {
132         Dimension dim = new Dimension();
133         int fraction = (int)Math.round(Math.sqrt(getChildren().size()));
134         if (fraction == 0) {
135             dim.width = 0;
136             dim.height = 0;
137         }
138         else {
139             dim.width = getBounds().width / fraction;
140             dim.height = getBounds().height / fraction;
141         }
142         return dim;
143     }
144     
145     public static String JavaDoc getTileKey(int x, int y) {
146         return "("+x+","+y+")";
147     }
148     
149     /**
150      * Retrieve the FigureTile at the given Position.
151      * Autocreate if not existent.
152      */

153     protected FigureTile getTile(int x, int y) {
154         String JavaDoc tileKey = getTileKey(x, y);
155         FigureTile figureTile = (FigureTile)tiles.get(tileKey);
156         if (figureTile == null) {
157             figureTile = new Tile(new Rectangle(x, y, tileDimension.width, tileDimension.height));
158             tiles.put(tileKey, figureTile);
159         }
160         return figureTile;
161     }
162     
163     /**
164      * Get all tiles this figure is registered in.
165      *
166      * @param figure The figure
167      * @return The figures tiles.
168      */

169     protected Set JavaDoc getTilesForFigure(Figure figure) {
170         Set JavaDoc figureTiles = (Set JavaDoc)figuresInTiles.get(figure);
171         if (figureTiles == null) {
172             figureTiles = new HashSet JavaDoc();
173             figuresInTiles.put(figure, figureTiles);
174         }
175         return figureTiles;
176     }
177     
178     /**
179      * Get the top left Position of the
180      * tile this point is in.
181      *
182      * @param x The points x
183      * @param y The points y
184      */

185     protected Point getTileTopLeft(int x, int y) {
186         return new Point(
187                 (x/tileDimension.width) * tileDimension.width,
188                 (y/tileDimension.height) * tileDimension.height
189             );
190     }
191     
192     /**
193      * Integrates the given figure in the current tile build.
194      * Makes sure that the registrations in the tile maps are
195      * correct after execution.
196      *
197      * @param figure The figure to integrate
198      */

199     protected void integrateFigure(Figure figure) {
200         Rectangle figureBounds = figure.getBounds();
201         Point topLefTilePosition = getTileTopLeft(figureBounds.x, figureBounds.y);
202         Point bottomRightTilePosition = getTileTopLeft(figureBounds.x + figureBounds.width, figureBounds.y+figureBounds.height);
203         
204         // clear registration in current build
205
Set JavaDoc figureTiles = getTilesForFigure(figure);
206         for (Iterator JavaDoc iter = figureTiles.iterator(); iter.hasNext();) {
207             FigureTile figureTile = (FigureTile) iter.next();
208             figureTile.removeFigure(figure);
209         }
210         figureTiles.clear();
211         
212         // reintegrate in build
213
for (int row = topLefTilePosition.y; row <= bottomRightTilePosition.y; row += tileDimension.height) {
214             for (int col = topLefTilePosition.x; col <= bottomRightTilePosition.x; col += tileDimension.width) {
215                 FigureTile figureTile = getTile(col, row);
216                 figureTile.addFigure(figure);
217                 figureTiles.add(figureTile);
218             }
219         }
220     }
221     
222     
223     private boolean tilesBuild = false;
224     /**
225      * Clears and rebuilds the tiles
226      *
227      */

228     protected void rebuildTiles() {
229         tiles.clear();
230         figuresInTiles.clear();
231         tileDimension = calculateTileDimension();
232         for (Iterator JavaDoc iter = getChildren().iterator(); iter.hasNext();) {
233             Figure figure = (Figure) iter.next();
234             integrateFigure(figure);
235         }
236     }
237     
238     /**
239      * @see com.nightlabs.editor2d.figures.ISmartUpdateFigure#paintRegion(Graphics, Rectangle)
240      */

241     public void paintRegion(Graphics graphics, Rectangle region) {
242         internalPaintRegion(graphics, region);
243     }
244
245     /**
246      * @see com.nightlabs.editor2d.figures.ISmartUpdateFigure#paintRegion(java.awt.Graphics2D, org.eclipse.draw2d.geometry.Rectangle)
247      */

248     public void paintRegion(Graphics2D JavaDoc graphics, Rectangle region) {
249         internalPaintRegion(graphics, region);
250     }
251
252     private void internalPaintRegion(Object JavaDoc graphics, Rectangle region) {
253         if (!tilesBuild)
254             rebuildTiles();
255         tilesBuild = true;
256         internalPaintSelf(graphics, region);
257         if (getChildren().size() == 0)
258             return;
259         Rectangle regionToPaint = getBounds().getIntersection(region);
260         if (regionToPaint.width == 0 && regionToPaint.height == 0)
261             return;
262         Point topLefTilePosition = getTileTopLeft(regionToPaint.x, regionToPaint.y);
263         Point bottomRightTilePosition = getTileTopLeft(regionToPaint.x + regionToPaint.width, regionToPaint.y+regionToPaint.height);
264         
265         for (int row = topLefTilePosition.y; row <= bottomRightTilePosition.y; row += tileDimension.height) {
266             for (int col = topLefTilePosition.x; col <= bottomRightTilePosition.x; col += tileDimension.width) {
267                 FigureTile figureTile = getTile(col, row);
268                 for (Iterator JavaDoc iter = figureTile.getIntersectingFigures(regionToPaint).iterator(); iter.hasNext();) {
269                     Figure figure = (Figure) iter.next();
270                     internalPaintChild(figure, graphics, regionToPaint);
271                 }
272             }
273         }
274     }
275     
276     private void internalPaintSelf(Object JavaDoc graphics, Rectangle region) {
277         if (graphics instanceof Graphics) {
278             Graphics d2dGraphics = (Graphics)graphics;
279             this.paint(d2dGraphics);
280         }
281         else if (graphics instanceof Graphics2D JavaDoc) {
282             Graphics2D JavaDoc j2dGraphics = (Graphics2D JavaDoc)graphics;
283             if (this instanceof ISmartUpdateFigure)
284                 ((ISmartUpdateFigure)this).paintRegion(j2dGraphics, region);
285             else if (this instanceof RendererFigure)
286                 ((RendererFigure)this).paint(j2dGraphics);
287         }
288     }
289     
290     private void internalPaintChild(Figure child, Object JavaDoc graphics, Rectangle regionToPaint) {
291         if (graphics instanceof Graphics) {
292             Graphics d2dGraphics = (Graphics)graphics;
293             if (child instanceof ISmartUpdateFigure)
294                 ((ISmartUpdateFigure)child).paintRegion(d2dGraphics, regionToPaint);
295             else
296                 child.paint(d2dGraphics);
297         }
298         else if (graphics instanceof Graphics2D JavaDoc) {
299             Graphics2D JavaDoc j2dGraphics = (Graphics2D JavaDoc)graphics;
300             if (child instanceof ISmartUpdateFigure)
301                 ((ISmartUpdateFigure)child).paintRegion(j2dGraphics, regionToPaint);
302             else if (child instanceof RendererFigure)
303                 ((RendererFigure)child).paint(j2dGraphics);
304         }
305     }
306
307
308     /**
309      * @see com.nightlabs.editor2d.figures.ISmartUpdateFigure#refresh()
310      */

311     public void refresh() {
312         tilesBuild = false;
313     }
314
315     /**
316      * @see com.nightlabs.editor2d.figures.ISmartUpdateFigure#refresh(org.eclipse.draw2d.Figure)
317      */

318     public void refresh(Figure figure) {
319         if (!tilesBuild)
320             rebuildTiles();
321         tilesBuild = true;
322         integrateFigure(figure);
323     }
324     
325 }
326
Popular Tags