1 5 package com.nightlabs.editor2d.figures; 6 7 import java.awt.Graphics2D ; 8 import java.util.ArrayList ; 9 import java.util.Collection ; 10 import java.util.HashMap ; 11 import java.util.HashSet ; 12 import java.util.Iterator ; 13 import java.util.LinkedList ; 14 import java.util.List ; 15 import java.util.Map ; 16 import java.util.Set ; 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 29 public class SmartUpdateFigure 30 extends Figure 31 implements ISmartUpdateFigure 32 { 33 36 private static class Tile implements FigureTile { 37 38 private Rectangle bounds; 39 private String key; 40 private List figures = new LinkedList (); 41 42 public Tile(Rectangle bounds) { 43 this.bounds = bounds; 44 } 45 46 public String getKey() { 47 if (key == null) 48 key = getTileKey(bounds.x, bounds.y); 49 return key; 50 } 51 52 55 public boolean intersects(Rectangle rect) { 56 return bounds.intersects(rect); 57 } 58 59 62 public Rectangle getBounds() { 63 return bounds; 64 } 65 66 69 public Collection getTileFigures() { 70 return figures; 71 } 72 73 76 public void addFigure(Figure figure) { 77 if (!figures.contains(figure)) 78 figures.add(figure); 79 } 80 81 84 public void removeFigure(Figure figure) { 85 figures.remove(figure); 86 } 87 88 91 public Collection getIntersectingFigures(Rectangle rect) { 92 List result = new ArrayList (); 93 for (Iterator 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 108 private Map tiles = new HashMap (); 109 110 114 private Map figuresInTiles = new HashMap (); 115 116 119 private Dimension tileDimension; 120 121 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 getTileKey(int x, int y) { 146 return "("+x+","+y+")"; 147 } 148 149 153 protected FigureTile getTile(int x, int y) { 154 String 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 169 protected Set getTilesForFigure(Figure figure) { 170 Set figureTiles = (Set )figuresInTiles.get(figure); 171 if (figureTiles == null) { 172 figureTiles = new HashSet (); 173 figuresInTiles.put(figure, figureTiles); 174 } 175 return figureTiles; 176 } 177 178 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 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 Set figureTiles = getTilesForFigure(figure); 206 for (Iterator iter = figureTiles.iterator(); iter.hasNext();) { 207 FigureTile figureTile = (FigureTile) iter.next(); 208 figureTile.removeFigure(figure); 209 } 210 figureTiles.clear(); 211 212 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 228 protected void rebuildTiles() { 229 tiles.clear(); 230 figuresInTiles.clear(); 231 tileDimension = calculateTileDimension(); 232 for (Iterator iter = getChildren().iterator(); iter.hasNext();) { 233 Figure figure = (Figure) iter.next(); 234 integrateFigure(figure); 235 } 236 } 237 238 241 public void paintRegion(Graphics graphics, Rectangle region) { 242 internalPaintRegion(graphics, region); 243 } 244 245 248 public void paintRegion(Graphics2D graphics, Rectangle region) { 249 internalPaintRegion(graphics, region); 250 } 251 252 private void internalPaintRegion(Object 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 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 graphics, Rectangle region) { 277 if (graphics instanceof Graphics) { 278 Graphics d2dGraphics = (Graphics)graphics; 279 this.paint(d2dGraphics); 280 } 281 else if (graphics instanceof Graphics2D ) { 282 Graphics2D j2dGraphics = (Graphics2D )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 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 ) { 299 Graphics2D j2dGraphics = (Graphics2D )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 311 public void refresh() { 312 tilesBuild = false; 313 } 314 315 318 public void refresh(Figure figure) { 319 if (!tilesBuild) 320 rebuildTiles(); 321 tilesBuild = true; 322 integrateFigure(figure); 323 } 324 325 } 326 | Popular Tags |