1 27 28 package org.nightlabs.editor2d.figures; 29 30 import java.awt.Graphics2D ; 31 import java.util.ArrayList ; 32 import java.util.Collection ; 33 import java.util.HashMap ; 34 import java.util.HashSet ; 35 import java.util.Iterator ; 36 import java.util.LinkedList ; 37 import java.util.List ; 38 import java.util.Map ; 39 import java.util.Set ; 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 53 public class SmartUpdateFigure 54 extends Figure 55 implements ISmartUpdateFigure 56 { 57 60 private static class Tile implements FigureTile { 61 62 private Rectangle bounds; 63 private String key; 64 private List figures = new LinkedList (); 65 66 public Tile(Rectangle bounds) { 67 this.bounds = bounds; 68 } 69 70 public String getKey() { 71 if (key == null) 72 key = getTileKey(bounds.x, bounds.y); 73 return key; 74 } 75 76 79 public boolean intersects(Rectangle rect) { 80 return bounds.intersects(rect); 81 } 82 83 86 public Rectangle getBounds() { 87 return bounds; 88 } 89 90 93 public Collection getTileFigures() { 94 return figures; 95 } 96 97 100 public void addFigure(IFigure figure) { 101 if (!figures.contains(figure)) 102 figures.add(figure); 103 } 104 105 108 public void removeFigure(IFigure figure) { 109 figures.remove(figure); 110 } 111 112 115 public Collection getIntersectingFigures(Rectangle rect) { 116 List result = new ArrayList (); 117 for (Iterator 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 132 private Map tiles = new HashMap (); 133 134 138 private Map figuresInTiles = new HashMap (); 139 140 143 private Dimension tileDimension; 144 145 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 getTileKey(int x, int y) { 170 return "("+x+","+y+")"; 171 } 172 173 177 protected FigureTile getTile(int x, int y) { 178 String 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 193 protected Set getTilesForFigure(IFigure figure) { 194 Set figureTiles = (Set )figuresInTiles.get(figure); 195 if (figureTiles == null) { 196 figureTiles = new HashSet (); 197 figuresInTiles.put(figure, figureTiles); 198 } 199 return figureTiles; 200 } 201 202 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 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 Set figureTiles = getTilesForFigure(figure); 230 for (Iterator iter = figureTiles.iterator(); iter.hasNext();) { 231 FigureTile figureTile = (FigureTile) iter.next(); 232 figureTile.removeFigure(figure); 233 } 234 figureTiles.clear(); 235 236 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 252 protected void rebuildTiles() { 253 tiles.clear(); 254 figuresInTiles.clear(); 255 tileDimension = calculateTileDimension(); 256 for (Iterator iter = getChildren().iterator(); iter.hasNext();) { 257 Figure figure = (Figure) iter.next(); 258 integrateFigure(figure); 259 } 260 } 261 262 265 public void paintRegion(Graphics graphics, Rectangle region) { 266 internalPaintRegion(graphics, region); 267 } 268 269 272 public void paintRegion(Graphics2D graphics, Rectangle region) { 273 internalPaintRegion(graphics, region); 274 } 275 276 private void internalPaintRegion(Object 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 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 graphics, Rectangle region) { 301 if (graphics instanceof Graphics) { 302 Graphics d2dGraphics = (Graphics)graphics; 303 this.paint(d2dGraphics); 304 } 305 else if (graphics instanceof Graphics2D ) { 306 Graphics2D j2dGraphics = (Graphics2D )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 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 ) { 323 Graphics2D j2dGraphics = (Graphics2D )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 335 public void refresh() { 336 tilesBuild = false; 337 } 338 339 342 public void refresh(IFigure figure) { 343 if (!tilesBuild) 344 rebuildTiles(); 345 tilesBuild = true; 346 integrateFigure(figure); 347 } 348 349 } 350 | Popular Tags |