1 31 32 package org.antlr.works.visualization.graphics.panel; 33 34 import org.antlr.works.visualization.graphics.GContext; 35 import org.antlr.works.visualization.graphics.graph.GGraphAbstract; 36 import org.antlr.works.visualization.graphics.graph.GGraphGroup; 37 import org.antlr.works.visualization.graphics.path.GPath; 38 import org.antlr.works.visualization.graphics.path.GPathGroup; 39 import org.antlr.xjlib.appkit.menu.XJMenu; 40 import org.antlr.xjlib.appkit.menu.XJMenuItem; 41 import org.antlr.xjlib.appkit.menu.XJMenuItemDelegate; 42 import org.antlr.xjlib.appkit.utils.XJSmoothScrolling; 43 44 import javax.swing.*; 45 import java.awt.*; 46 import java.awt.event.*; 47 import java.awt.image.BufferedImage ; 48 import java.util.ArrayList ; 49 import java.util.List ; 50 51 public class GView extends JPanel implements XJMenuItemDelegate { 52 53 protected boolean useCachedImage = true; 54 protected boolean cachedImageRerender = false; 55 protected boolean cachedImageResize = false; 56 57 protected String placeholder; 58 protected BufferedImage cachedImage = null; 59 protected Dimension outOfMemoryDimension = new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE); 60 61 protected List graphs = new ArrayList (); 62 protected int currentGraphIndex = 0; 63 protected GPanel panel; 64 protected GContext context; 65 protected XJSmoothScrolling smoothScrolling; 66 67 protected Point lastMouse; 68 69 protected static final Font DEFAULT_FONT = new Font("Courier", Font.BOLD, 18); 70 71 public int offset_x = 10; 72 public int offset_y = 10; 73 74 public int prev_offset_x = 0; 75 public int prev_offset_y = 0; 76 77 public GView(GPanel panel, GContext context) { 78 this.panel = panel; 79 this.context = context; 80 this.context.setContainer(this); 81 82 smoothScrolling = new XJSmoothScrolling(this, null); 83 84 setFocusable(true); 85 86 setBackground(Color.white); 87 adjustSize(); 88 89 addMouseMotionListener(new DefaultMouseMotionListener()); 90 addMouseListener(new DefaultMouseListener()); 91 addKeyListener(new DefaultKeyListener()); 92 } 93 94 public void setEnable(boolean flag) { 95 for (Object graph1 : graphs) { 96 GGraphAbstract graph = (GGraphAbstract) graph1; 97 graph.setEnable(flag); 98 } 99 } 100 101 public void setPlaceholder(String placeholder) { 102 this.placeholder = placeholder; 103 } 104 105 public void setGraphs(List graphs) { 106 this.graphs.clear(); 107 108 if(graphs == null) 109 return; 110 111 this.graphs.addAll(graphs); 112 113 if(currentGraphIndex >= graphs.size()) 114 currentGraphIndex = graphs.size()-1; 115 116 applyContext(); 117 } 118 119 public List getGraphs() { 120 return graphs; 121 } 122 123 public void applyContext() { 124 for (Object graph1 : graphs) { 125 GGraphAbstract graph = (GGraphAbstract) graph1; 126 graph.setContext(context); 127 } 128 } 129 130 public void setCacheEnabled(boolean flag) { 131 if(useCachedImage != flag) { 132 useCachedImage = flag; 133 cacheInvalidate(); 134 } 135 } 136 137 public boolean isCachedEnabled() { 138 return useCachedImage; 139 } 140 141 public void cacheInvalidate() { 142 cachedImage = null; 143 } 144 145 public void cacheRerender() { 146 cachedImageRerender = true; 147 } 148 149 public void setCacheResizeImage(boolean flag) { 150 cachedImageResize = flag; 151 } 152 153 public BufferedImage getCachedImage() { 154 return cachedImage; 155 } 156 157 public boolean setNextGraph() { 158 currentGraphIndex++; 159 if(currentGraphIndex>=graphs.size()) { 160 currentGraphIndex = graphs.size()-1; 161 return false; 162 } else 163 return true; 164 } 165 166 public boolean setPrevGraph() { 167 currentGraphIndex--; 168 if(currentGraphIndex<0) { 169 currentGraphIndex = 0; 170 return false; 171 } else 172 return true; 173 } 174 175 public int getCurrentGraphIndex() { 176 return currentGraphIndex; 177 } 178 179 public GGraphAbstract getCurrentGraph() { 180 if(graphs.size()>0) 181 return (GGraphAbstract)graphs.get(currentGraphIndex); 182 else 183 return null; 184 } 185 186 public GGraphGroup getCurrentGraphGroup() { 187 return (GGraphGroup)getCurrentGraph(); 188 } 189 190 public GPathGroup getCurrentPathGroup() { 191 return getCurrentGraphGroup().pathGroup; 192 } 193 194 public GPath getCurrentPath() { 195 return getCurrentPathGroup().getCurrentPath(); 196 } 197 198 public void refresh() { 199 if(getCurrentGraph() != null) 200 getCurrentGraph().render(0, 0); 201 202 cacheInvalidate(); 203 adjustSize(); 204 repaint(); 205 } 206 207 public void refreshSizeChanged(boolean useCacheImageResize) { 208 if(useCachedImage) { 209 setCacheResizeImage(useCacheImageResize); 210 if(!useCacheImageResize) { 211 if(getCurrentGraph() != null) 212 getCurrentGraph().render(0, 0); 213 cacheInvalidate(); 214 } 215 adjustSize(); 216 repaint(); 217 } else { 218 refresh(); 219 } 220 } 221 222 public void adjustSize() { 223 if(getCurrentGraph() == null || context == null) 224 return; 225 226 Dimension dimension = new Dimension(getGraphWidth()+2*offset_x, getGraphHeight()+2*offset_y); 227 setPreferredSize(dimension); 228 revalidate(); 229 } 230 231 public int getGraphWidth() { 232 if(getCurrentGraph().getDimension() == null) 233 return 400; 234 else 235 return (int)getCurrentGraph().getWidth()+20; 236 } 237 238 public int getGraphHeight() { 239 if(getCurrentGraph().getDimension() == null) 240 return 200; 241 else 242 return (int)getCurrentGraph().getHeight()+20; 243 } 244 245 public void addMenuItem(JPopupMenu menu, String title, int tag, Object object) { 246 XJMenuItem item = new XJMenuItem(); 247 item.setTitle(title); 248 item.setTag(tag); 249 item.setObject(object); 250 item.setDelegate(this); 251 252 menu.add(item.getSwingComponent()); 253 } 254 255 public JPopupMenu getContextualMenu() { 256 return null; 257 } 258 259 public void handleMenuEvent(XJMenu menu, XJMenuItem item) { 260 } 261 262 public void processMouseEvent(MouseEvent e) { 263 if(e.isPopupTrigger()) { 264 JPopupMenu menu = getContextualMenu(); 265 if(menu != null) 266 menu.show(this, e.getX(), e.getY()); 267 } else 268 super.processMouseEvent(e); 269 } 270 271 public void pathCurrentElementDidChange() { 272 GPath path = getCurrentPath(); 273 Rectangle rect = path.getBoundsOfSelectedElement(); 274 if(!rect.isEmpty()) { 275 rect.x -= 50; 277 rect.y -= 50; 278 rect.width += 100; 279 rect.height += 100; 280 smoothScrolling.scrollTo(rect); 281 } 282 } 283 284 public boolean canDraw() { 285 return getCurrentGraph() != null && getCurrentGraph().getDimension() != null && getCurrentGraph().isRendered(); 286 } 287 288 public void render(Graphics2D g2d) { 289 context.offsetX = offset_x; 290 context.offsetY = offset_y; 291 context.setGraphics2D(g2d); 292 g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON); 293 g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); 294 getCurrentGraph().draw(); 295 } 296 297 public void paintComponent(Graphics g) { 298 super.paintComponent(g); 299 300 if(!canDraw()) { 301 paintPlaceholder(g); 302 return; 303 } 304 305 int width = getGraphWidth()+offset_x; 306 int height = getGraphHeight()+offset_y+1; 307 308 if(useCachedImage) { 309 boolean sizeChanged = cachedImage != null && (cachedImage.getWidth() != width || cachedImage.getHeight() != height); 310 311 if(sizeChanged) { 312 if(!cachedImageResize && cachedImage != null) { 316 cachedImage.flush(); 317 cachedImage = null; 318 } 319 } 320 321 if(cachedImage == null) { 322 if(width<outOfMemoryDimension.width && height<outOfMemoryDimension.height) { 325 try { 326 cachedImage = new BufferedImage (width, height, BufferedImage.TYPE_3BYTE_BGR); 327 Graphics2D gCache = (Graphics2D)cachedImage.getGraphics(); 328 gCache.setColor(Color.white); 329 gCache.fillRect(0, 0, width, height); 330 render(gCache); 331 gCache.dispose(); 332 } catch(OutOfMemoryError e) { 333 outOfMemoryDimension.width = width; 334 outOfMemoryDimension.height = height; 335 cachedImage = null; 336 System.err.println("Out of memory, disabling cache ("+(int)(width*height*3.0/(1024*1024))+" Mb)"); 337 } 338 } 339 } else if(cachedImageRerender) { 340 Graphics2D gCache = (Graphics2D)cachedImage.getGraphics(); 342 gCache.setColor(Color.white); 343 gCache.fillRect(0, 0, width, height); 344 render(gCache); 345 gCache.dispose(); 346 cachedImageRerender = false; 347 } 348 } 349 350 if(cachedImage == null) 351 render((Graphics2D)g); 352 else 353 g.drawImage(cachedImage, 0, 0, width, height, null); 354 355 if(!cachedImageResize && getCurrentGraph() instanceof GGraphGroup) { 356 Graphics2D g2d = (Graphics2D)g; 358 context.offsetX = offset_x; 359 context.offsetY = offset_y; 360 context.setGraphics2D(g2d); 361 g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON); 362 g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); 363 364 getCurrentPathGroup().drawSelectedElement(); 365 } 366 } 367 368 public void paintPlaceholder(Graphics g) { 369 if(placeholder == null) 370 return; 371 372 g.setFont(DEFAULT_FONT); 373 374 FontMetrics fm = g.getFontMetrics(); 375 Rectangle r = getVisibleRect(); 376 int x = r.x+r.width/2-fm.stringWidth(placeholder)/2; 377 int y = r.y+r.height/2+fm.getHeight()/2; 378 379 g.setColor(Color.gray); 380 g.drawString(placeholder, x, y); 381 } 382 383 public class DefaultMouseMotionListener extends MouseMotionAdapter { 384 385 public void mouseDragged(MouseEvent e) { 386 if(lastMouse == null) 387 return; 388 389 Point mouse = e.getPoint(); 390 int dx = mouse.x - lastMouse.x; 391 int dy = mouse.y - lastMouse.y; 392 offset_x = prev_offset_x+dx; 393 offset_y = prev_offset_y+dy; 394 refresh(); 395 } 396 397 public void mouseMoved(MouseEvent e) { 398 } 399 } 400 401 public class DefaultMouseListener extends MouseAdapter { 402 403 public void mousePressed(MouseEvent e) { 404 if(!isFocusOwner()) 405 requestFocusInWindow(); 406 407 setCacheEnabled(false); 408 prev_offset_x = offset_x; 409 prev_offset_y = offset_y; 410 lastMouse = e.getPoint(); 411 412 if(getCurrentGraph() instanceof GGraphGroup) 413 handleMousePressedInGraphGroup(e); 414 415 423 } 424 425 public void mouseReleased(MouseEvent e) { 426 lastMouse = null; 427 setCacheEnabled(true); 428 repaint(); 431 } 432 433 public void handleMousePressedInGraphGroup(MouseEvent e) { 434 getCurrentPathGroup().selectPath(e.getPoint()); 435 } 436 } 437 438 public class DefaultKeyListener extends KeyAdapter { 439 440 public void keyPressed(KeyEvent e) { 441 if(getCurrentGraph() instanceof GGraphGroup) 442 handleKeyPressedInGraphGroup(e); 443 } 444 445 public void handleKeyPressedInGraphGroup(KeyEvent e) { 446 GPath path = getCurrentPath(); 447 switch(e.getKeyCode()) { 448 case KeyEvent.VK_RIGHT: 449 path.nextElement(); 450 pathCurrentElementDidChange(); 451 e.consume(); 452 break; 453 case KeyEvent.VK_LEFT: 454 path.previousElement(); 455 pathCurrentElementDidChange(); 456 e.consume(); 457 break; 458 case KeyEvent.VK_UP: 459 path.lastElement(); 460 pathCurrentElementDidChange(); 461 e.consume(); 462 break; 463 case KeyEvent.VK_DOWN: 464 path.firstElement(); 465 pathCurrentElementDidChange(); 466 e.consume(); 467 break; 468 469 case KeyEvent.VK_A: 470 getCurrentPathGroup().toggleShowRuleLinks(); 471 cacheRerender(); 472 e.consume(); 473 break; 474 } 475 476 if(e.isConsumed()) 477 repaint(); 478 } 479 } 480 } 481 | Popular Tags |