Changeset 1102 for trunk/src/org/expeditee/gui/FrameGraphics.java
- Timestamp:
- 05/10/18 16:04:51 (6 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/expeditee/gui/FrameGraphics.java
r1064 r1102 19 19 package org.expeditee.gui; 20 20 21 import java.awt.Color;22 import java.awt.Dimension;23 import java.awt.EventQueue;24 import java.awt.Graphics;25 import java.awt.Graphics2D;26 import java.awt.GraphicsDevice;27 import java.awt.GraphicsEnvironment;28 import java.awt.Image;29 import java.awt.Polygon;30 import java.awt.Rectangle;31 import java.awt.RenderingHints;32 import java.awt.geom.Area;33 import java.lang.reflect.Method;34 import java.awt.image.BufferedImage;35 21 import java.util.Collection; 36 22 import java.util.Collections; … … 41 27 import java.util.ListIterator; 42 28 29 import org.expeditee.core.Clip; 30 import org.expeditee.core.Colour; 31 import org.expeditee.core.Dimension; 32 import org.expeditee.core.Image; 33 import org.expeditee.core.bounds.PolygonBounds; 34 import org.expeditee.gio.EcosystemManager; 35 import org.expeditee.gio.input.StandardInputEventListeners; 36 import org.expeditee.gio.input.KBMInputEvent.Key; 43 37 import org.expeditee.items.Circle; 44 38 import org.expeditee.items.Dot; 45 39 import org.expeditee.items.Item; 46 import org.expeditee.items.ItemUtils;47 40 import org.expeditee.items.Line; 48 41 import org.expeditee.items.UserAppliedPermission; 49 42 import org.expeditee.items.XRayable; 50 43 import org.expeditee.items.Item.HighlightMode; 51 import org.expeditee.items.widgets. InteractiveWidget;44 import org.expeditee.items.widgets.Widget; 52 45 import org.expeditee.items.widgets.WidgetEdge; 53 46 import org.expeditee.settings.UserSettings; … … 55 48 public class FrameGraphics { 56 49 57 // the graphics used to paint with58 private static Graphics2D _DisplayGraphics;59 60 // the maximum size that can be used to paint on61 private static Dimension _MaxSize = null;62 63 50 // Final passes to rendering the current frame 64 51 private static LinkedList<FrameRenderPass> _frameRenderPasses = new LinkedList<FrameRenderPass>(); 65 66 // modes67 protected static final int MODE_NORMAL = 0;68 69 protected static final int MODE_AUDIENCE = 1;70 71 protected static final int MODE_XRAY = 2;72 52 73 protected static final int MODE_AUDIENCE_FULLSCREEN = 4; 74 75 76 // The following used to be true in the past: 77 // Start in XRay mode so that errors aren't thrown when parsing the profile 78 // frame if it has images on it 79 // More recently, so Exploratory Search starts up correctly with images 80 // rendered (rather than their @i form) the following assignment was changed 81 // to MODE_NORMAL. No issue of parse errors has not been seen 82 private static int _Mode = MODE_NORMAL; 83 84 private FrameGraphics() { 85 // util constructor 86 } 87 88 /** 89 * If Audience Mode is on this method will toggle it to be off, or 90 * vice-versa. This results in the Frame being re-parsed and repainted. 91 */ 92 public static void ToggleAudienceMode() { 93 Frame current = DisplayIO.getCurrentFrame(); 94 if (_Mode == MODE_XRAY) { 95 ToggleXRayMode(); 96 } 97 98 99 if (_Mode == MODE_AUDIENCE_FULLSCREEN) { 100 _Mode = MODE_NORMAL; 101 DisplayIO.leaveFullScreenMode(); 102 } 103 else if (_Mode == MODE_AUDIENCE) { 104 if (DisplayIO.fullScreenCapable()) { 105 // Don't need to worry about UpdateConnectedToAnnotations, as this 106 // will have already been taken care of going to the 'first stage' of 107 // audience mode (MODE_AUDIENCE) 108 _Mode = MODE_AUDIENCE_FULLSCREEN; 109 DisplayIO.enterFullScreenMode(); 110 } 111 else { 112 // return to normal mode 113 _Mode = MODE_NORMAL; 114 } 115 } 116 else { // must currently be in regular mode => move to audience mode 117 _Mode = MODE_AUDIENCE; 118 ItemUtils.UpdateConnectedToAnnotations(current.getItems()); 119 for (Overlay o : current.getOverlays()) { 120 ItemUtils.UpdateConnectedToAnnotations(o.Frame.getItems()); 121 } 122 for (Vector v : current.getVectorsDeep()) { 123 ItemUtils.UpdateConnectedToAnnotations(v.Frame.getItems()); 124 } 125 } 126 FrameUtils.Parse(current); 127 DisplayIO.UpdateTitle(); 128 setMaxSize(new Dimension(_MaxSize.width, MessageBay 129 .getMessageBufferHeight() 130 + _MaxSize.height)); 131 refresh(false); 132 } 133 134 /** 135 * If X-Ray Mode is on this method will toggle it to be off, or vice-versa. 136 * This results in the Frame being re-parsed and repainted. 137 */ 138 public static void ToggleXRayMode() { 139 if (_Mode == MODE_AUDIENCE) { 140 ToggleAudienceMode(); 141 } 142 143 if (_Mode == MODE_XRAY) { 144 setMode(MODE_NORMAL, true); 145 } else { 146 setMode(MODE_XRAY, true); 147 } 148 DisplayIO.getCurrentFrame().refreshSize(); 149 DisplayIO.UpdateTitle(); 150 FrameMouseActions.getInstance().refreshHighlights(); 151 FrameMouseActions.updateCursor(); 152 refresh(false); 153 } 154 155 public static void setMode(int mode, boolean parse) { 156 if (_Mode == mode) 157 return; 158 _Mode = mode; 159 if (parse) { 160 Frame current = DisplayIO.getCurrentFrame(); 161 current.parse(); 162 } 163 } 164 165 public static void forceXRayMode(boolean parse) { 166 setMode(MODE_XRAY,parse); 167 } 168 169 /** 170 * @return True if Audience Mode is currently on, False otherwise. 171 */ 172 public static boolean isAudienceMode() { 173 return (_Mode == MODE_AUDIENCE) || (_Mode == MODE_AUDIENCE_FULLSCREEN); 174 } 175 176 /** 177 * @return True if X-Ray Mode is currently on, False otherwise. 178 */ 179 public static boolean isXRayMode() { 180 return _Mode == MODE_XRAY; 181 } 182 183 public static void setMaxSize(Dimension max) { 184 if (_MaxSize == null) 185 _MaxSize = max; 186 187 // Hide the message buffer if in audience mode 188 int newMaxHeight = max.height 189 - (isAudienceMode() ? 0 : MessageBay.MESSAGE_BUFFER_HEIGHT); 190 if (newMaxHeight > 0) { 191 _MaxSize.setSize(max.width, newMaxHeight); 192 } 193 Frame current = DisplayIO.getCurrentFrame(); 194 if (current != null) { 195 current.setBuffer(null); 196 current.refreshSize(); 197 if (DisplayIO.isTwinFramesOn()) { 198 Frame opposite = DisplayIO.getOppositeFrame(); 199 200 /* When running the test suite opposite may be null! */ 201 if (opposite != null) { 202 opposite.setBuffer(null); 203 opposite.refreshSize(); 204 } 205 } 206 } 207 208 if (newMaxHeight > 0) { 209 MessageBay.updateSize(); 210 } 211 } 212 213 public static Dimension getMaxSize() { 214 return _MaxSize; 215 } 216 217 public static Dimension getMaxFrameSize() { 218 if (DisplayIO.isTwinFramesOn()) { 219 return new Dimension((_MaxSize.width / 2), _MaxSize.height); 220 } else 221 return _MaxSize; 222 } 223 224 /** 225 * Sets the Graphics2D object that should be used for all painting tasks. 226 * Note: Actual painting is done by using g.create() to create temporary 227 * instances that are then disposed of using g.dispose(). 228 * 229 * @param g 230 * The Graphics2D object to use for all painting 231 */ 232 public static void setDisplayGraphics(Graphics2D g) { 233 _DisplayGraphics = g; 234 } 235 236 /* 237 * Displays the given Item on the screen 238 */ 239 static void PaintItem(Graphics2D g, Item i) { 240 if (i == null || g == null) 241 return; 242 243 // do not paint annotation items in audience mode 244 if (!isAudienceMode() 245 || (isAudienceMode() && !i.isConnectedToAnnotation() && !i 246 .isAnnotation()) || i == FrameUtils.getLastEdited()) { 247 248 Graphics2D tg = (Graphics2D) g.create(); 249 i.paint(tg); 250 tg.dispose(); 251 } 252 } 253 254 /** 255 * Adds all the scaled vector items for a frame into a list. It uses 256 * recursion to get the items from nested vector frames. 257 * 258 * @param items 259 * the list into which the vector items will be placed. 260 * @param vector 261 * the frame containing vecor items. 262 * @param seenVectors 263 * the vectors which should be ignored to prevent infinate loops. 264 * @param origin 265 * start point for this frame or null if it is a top level frame. 266 * @param scale 267 * the factor by which the item on the vector frame are to be 268 * scaled. 269 */ 270 // public static void AddAllVectorItems(List<Item> items, Vector vector, 271 // Collection<Frame> seenVectors) { 272 // // Check all the vector items and add the items on the vectors 273 // if (seenVectors.contains(vector)) 274 // return; 275 // seenVectors.add(vector); 276 // 277 // float originX = origin == null ? 0 : origin.x; 278 // float originY = origin == null ? 0 : origin.y; 279 // 280 // for (Vector o : vector.getVectors()) 281 // AddAllVectorItems(items, o.Frame, new HashSet<Frame>(seenVectors), 282 // new Point2D.Float(originX + o.Origin.x * scale, originY 283 // + o.Origin.y * scale), o.Scale * scale, 284 // o.Foreground, o.Background); 285 // // if its the original frame then were done 286 // if (origin == null) { 287 // ItemUtils.EnclosedCheck(items); 288 // return; 289 // } 290 // // Put copies of the items shifted to the origin of the VectorTag 291 // items.addAll(ItemUtils 292 // .CopyItems(vector.getNonAnnotationItems(), vector)); 293 // 294 // } 295 /** 296 * Recursive function similar to AddAllOverlayItems. 297 * 298 * @param widgets 299 * The collection the widgets will be added to 300 * @param overlay 301 * An "overlay" frame - this intially will be the parent frame 302 * @param seenOverlays 303 * Used for state in the recursion stack. Pass as an empty 304 * (non-null) list. 305 */ 306 public static void AddAllOverlayWidgets(List<InteractiveWidget> widgets, 307 Frame overlay, List<Frame> seenOverlays) { 308 if (seenOverlays.contains(overlay)) 309 return; 310 311 seenOverlays.add(overlay); 312 313 for (Overlay o : overlay.getOverlays()) 314 AddAllOverlayWidgets(widgets, o.Frame, seenOverlays); 315 316 widgets.addAll(overlay.getInteractiveWidgets()); 317 } 318 319 private static Image Paint(Frame toPaint, Area clip) { 320 return Paint(toPaint, clip, true, true); 321 } 322 323 /** 324 * 325 * @param toPaint 326 * @param clip 327 * If null, then no clip applied. 328 * @param isActualFrame 329 * @return 330 */ 331 private static Image Paint(Frame toPaint, Area clip, boolean isActualFrame, 332 boolean createVolitile) { 333 if (toPaint == null) 334 return null; 53 private static Item _lastToolTippedItem = null; 54 55 /** Static-only class. */ 56 private FrameGraphics() 57 { 58 } 59 60 /** 61 * Gets an image of the given frame that has the given dimensions. If clip 62 * is not null, only the areas inside clip are guaranteed to be drawn. 63 */ 64 public static Image getFrameImage(Frame toPaint, Clip clip, Dimension size) 65 { 66 return getFrameImage(toPaint, clip, size, true, true); 67 } 68 69 /** 70 * Gets an image of the given frame that has the given dimensions. If clip 71 * is not null, only the areas inside clip are guaranteed to be drawn. 72 */ 73 public static Image getFrameImage(Frame toPaint, Clip clip, Dimension size, boolean isActualFrame, boolean createVolatile) 74 { 75 if (toPaint == null) return null; 335 76 336 77 // the buffer is not valid, so it must be recreated 337 78 if (!toPaint.isBufferValid()) { 79 338 80 Image buffer = toPaint.getBuffer(); 339 if (buffer == null) { 340 GraphicsEnvironment ge = GraphicsEnvironment 341 .getLocalGraphicsEnvironment(); 342 if (createVolitile) { 343 buffer = ge.getDefaultScreenDevice() 344 .getDefaultConfiguration() 345 .createCompatibleVolatileImage(_MaxSize.width, 346 _MaxSize.height); 81 // Get the size if it hasn't been given 82 if (size == null) { 83 // Can't get the size if there is no buffer 84 if (buffer == null) { 85 return null; 347 86 } else { 348 buffer = new BufferedImage(_MaxSize.width, _MaxSize.height, 349 BufferedImage.TYPE_INT_ARGB); 350 } 87 size = buffer.getSize(); 88 } 89 } 90 91 if (buffer == null || !buffer.getSize().equals(size)) { 92 buffer = Image.createImage(size.width, size.height, createVolatile); 351 93 toPaint.setBuffer(buffer); 352 } 353 354 Graphics2D bg = (Graphics2D) buffer.getGraphics(); 355 paintFrame(toPaint, clip, isActualFrame, createVolitile, bg); 356 357 bg.dispose(); 94 clip = null; 95 } 96 97 EcosystemManager.getGraphicsManager().pushDrawingSurface(buffer); 98 EcosystemManager.getGraphicsManager().pushClip(clip); 99 paintFrame(toPaint, isActualFrame, createVolatile); 100 EcosystemManager.getGraphicsManager().popDrawingSurface(); 358 101 } 359 102 … … 361 104 } 362 105 363 /** 364 * @param toPaint 365 * @param clip 366 * @param isActualFrame 367 * @param createVolitile 368 * @param bg 369 */ 370 public static void paintFrame(Frame toPaint, Area clip, 371 boolean isActualFrame, boolean createVolitile, Graphics2D bg) { 372 106 /** TODO: Comment. cts16 */ 107 public static void paintFrame(Frame toPaint, boolean isActualFrame, boolean createVolitile) 108 { 109 Clip clip = EcosystemManager.getGraphicsManager().peekClip(); 110 373 111 // Prepare render passes 374 112 if (isActualFrame) { 375 currentClip = clip;376 113 for (FrameRenderPass pass : _frameRenderPasses) { 377 currentClip = pass.paintStarted(currentClip); 378 clip = currentClip; 379 } 380 } 381 382 bg.setClip(clip); 114 clip = pass.paintStarted(clip); 115 } 116 } 383 117 384 118 // TODO: Revise images and clip - VERY IMPORTANT … … 386 120 // Nicer looking lines, but may be too jerky while 387 121 // rubber-banding on older machines 388 if (UserSettings.AntiAlias.get()) 389 bg.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 390 RenderingHints.VALUE_ANTIALIAS_ON); 391 // If we are doing @f etc... then have a clear background if its the 392 // default background color 393 Color backgroundColor = null; 122 if (UserSettings.AntiAlias.get()) EcosystemManager.getGraphicsManager().setAntialiasing(true); 123 124 // If we are doing @f etc... then have a clear background if its the default background color 125 Colour backgroundColor = null; 126 394 127 // Need to allow transparency for frameImages 395 128 if (createVolitile) { … … 397 130 } else { 398 131 backgroundColor = toPaint.getBackgroundColor(); 399 if (backgroundColor == null) 400 backgroundColor = Item.TRANSPARENT; 401 } 402 403 // if(isActual) 404 bg.setColor(backgroundColor); 405 if (isActualFrame) { 406 // bg.setColor(Color.white); // TODO: TEMP FOR DEBUGGING 407 408 // System.out.println("paintPic"); 409 } 410 bg.fillRect(0, 0, _MaxSize.width, _MaxSize.height); 132 if (backgroundColor == null) backgroundColor = Item.TRANSPARENT; 133 } 134 135 EcosystemManager.getGraphicsManager().clear(backgroundColor); 411 136 412 137 List<Item> visibleItems = new LinkedList<Item>(); 413 List< InteractiveWidget> paintWidgets;138 List<Widget> paintWidgets; 414 139 415 140 if (isActualFrame) { … … 417 142 // frames 418 143 visibleItems.addAll(toPaint.getAllItems()); 419 paintWidgets = new LinkedList<InteractiveWidget>();420 AddAllOverlayWidgets(paintWidgets, toPaint, new LinkedList<Frame>());144 paintWidgets = toPaint.getAllOverlayWidgets(); 145 paintWidgets.addAll(toPaint.getInteractiveWidgets()); 421 146 } else { 422 147 visibleItems.addAll(toPaint.getVisibleItems()); … … 425 150 } 426 151 427 428 HashSet<Item> paintedFillsAndLines = new HashSet<Item>(); 152 HashSet<Item> paintedFillsAndLines = new HashSet<Item>(); 429 153 // FIRST: Paint widgets swing gui (not expeditee gui) . 430 154 // Note that these are the anchored widgets 431 ListIterator<InteractiveWidget> widgetItor = paintWidgets 432 .listIterator(paintWidgets.size()); 155 ListIterator<Widget> widgetItor = paintWidgets.listIterator(paintWidgets.size()); 433 156 while (widgetItor.hasPrevious()) { 434 157 // Paint first-in-last-serve ordering - like swing 435 158 // If it is done the other way around then widgets are covered up by 436 159 // the box that is supposed to be underneath 437 InteractiveWidget iw = widgetItor.previous();438 if (clip == null || clip. intersects(iw.getComponant().getBounds())) {160 Widget iw = widgetItor.previous(); 161 if (clip == null || clip.getBounds() == null || clip.getBounds().intersects(iw.getBounds())) { 439 162 paintedFillsAndLines.addAll(iw.getItems()); 440 163 //iw.paint(bg); … … 457 180 paintItems = new LinkedList<Item>(); 458 181 for (Item i : visibleItems) { 459 if ( i.isInDrawingArea(clip)) {182 if (clip == null || i.isInDrawingArea(clip.getBounds())) { 460 183 paintItems.add(i); 461 184 } else if (i.isEnclosed()) { … … 469 192 } 470 193 } 471 // Only paint files and lines once ... between anchored AND free472 // items473 PaintPictures( bg,paintItems, fillOnlyItems, paintedFillsAndLines);474 PaintLines( bg,visibleItems);194 195 // Only paint files and lines once ... between anchored AND free items 196 PaintPictures(paintItems, fillOnlyItems, paintedFillsAndLines); 197 PaintLines(visibleItems); 475 198 476 199 … … 480 203 // If it is done the other way around then widgets are covered up by 481 204 // the box that is supposed to be underneath 482 InteractiveWidget iw = widgetItor.previous();483 if (clip == null || clip.i ntersects(iw.getComponant().getBounds())) {484 iw.paint( bg);485 PaintItem( bg,iw.getItems().get(4));205 Widget iw = widgetItor.previous(); 206 if (clip == null || clip.isNotClipped() || clip.getBounds().intersects(iw.getBounds())) { 207 iw.paint(); 208 PaintItem(iw.getItems().get(4)); 486 209 } 487 210 } … … 494 217 // Dont paint the free items for the other frame in twin frames mode 495 218 // if (toPaint == DisplayIO.getCurrentFrame()) { 496 if (clip == null ) {219 if (clip == null || clip.isNotClipped()) { 497 220 freeItemsToPaint = FreeItems.getInstance(); 498 221 } else { … … 500 223 fillOnlyItems.clear(); 501 224 for (Item i : FreeItems.getInstance()) { 502 if (i.isInDrawingArea(clip )) {225 if (i.isInDrawingArea(clip.getBounds())) { 503 226 freeItemsToPaint.add(i); 504 227 } else if (i.isEnclosed()) { … … 509 232 // } 510 233 511 if (isActualFrame && toPaint == DisplayIO.getCurrentFrame()) 512 PaintPictures(bg, freeItemsToPaint, fillOnlyItems, 513 paintedFillsAndLines); 234 if (isActualFrame && toPaint == DisplayController.getCurrentFrame()) { 235 PaintPictures(freeItemsToPaint, fillOnlyItems, paintedFillsAndLines); 236 } 237 514 238 // TODO if we can get transparency with FreeItems.getInstance()... 515 239 // then text can be done before freeItems 516 PaintNonLinesNonPicture( bg,paintItems);240 PaintNonLinesNonPicture(paintItems); 517 241 518 242 // toPaint.setBufferValid(true); 519 243 520 if (isActualFrame && ! isAudienceMode()) {521 PaintItem( bg,toPaint.getNameItem());522 } 523 524 if (Display IO.isTwinFramesOn()) {244 if (isActualFrame && !DisplayController.isAudienceMode()) { 245 PaintItem(toPaint.getNameItem()); 246 } 247 248 if (DisplayController.isTwinFramesOn()) { 525 249 List<Item> lines = new LinkedList<Item>(); 526 250 for (Item i : freeItemsToPaint) { … … 528 252 Line line = (Line) i; 529 253 530 if (toPaint == Display IO.getCurrentFrame()) {254 if (toPaint == DisplayController.getCurrentFrame()) { 531 255 // If exactly one end of the line is floating... 532 256 … … 560 284 } 561 285 } 562 if (isActualFrame)563 PaintLines(bg,lines);286 287 if (isActualFrame) PaintLines(lines); 564 288 } else { 565 // Don't paint the 566 if (isActualFrame) 567 PaintLines(bg, freeItemsToPaint); 568 } 569 570 if (isActualFrame && toPaint == DisplayIO.getCurrentFrame()) 571 PaintNonLinesNonPicture(bg, freeItemsToPaint); 289 if (isActualFrame) PaintLines(freeItemsToPaint); 290 } 291 292 if (isActualFrame && toPaint == DisplayController.getCurrentFrame()) { 293 PaintNonLinesNonPicture(freeItemsToPaint); 294 } 572 295 573 296 // Repaint popups / drags... As well as final passes 574 297 if (isActualFrame) { 575 298 for (FrameRenderPass pass : _frameRenderPasses) { 576 pass.paintPreLayeredPanePass(bg); 577 } 578 PopupManager.getInstance().paintLayeredPane(bg, clip); 299 pass.paintPreLayeredPanePass(); 300 } 301 302 //if (PopupManager.getInstance() != null) PopupManager.getInstance().paintLayeredPane(clip == null ? null : clip.getBounds()); 303 579 304 for (FrameRenderPass pass : _frameRenderPasses) { 580 pass.paintFinalPass( bg);305 pass.paintFinalPass(); 581 306 } 582 307 } 583 308 584 309 // paint tooltip 585 if(!FreeItems. itemsAttachedToCursor()) {310 if(!FreeItems.hasItemsAttachedToCursor()) { 586 311 Item current = FrameUtils.getCurrentItem(); 587 if(current != null) { 588 current.paintTooltip(bg); 589 } //else { 590 // Item.clearTooltipOwner(); 591 // } 592 if(previous != null) previous.clearTooltips(); 593 previous = current; 594 } 595 596 if (FreeItems.hasCursor() 597 && DisplayIO.getCursor() == Item.DEFAULT_CURSOR) 598 PaintNonLinesNonPicture(bg, FreeItems.getCursor()); 599 } 600 601 private static Item previous = null; 602 603 // creates a new line so that lines are shown correctly when spanning 604 // across frames in TwinFrames mode 605 // private static Line TransposeLine(Line line, Item d, Frame toPaint, 606 // int base, int adj) { 607 // Line nl = null; 608 // 609 // if (toPaint != DisplayIO.getCurrentFrame() && d.getParent() == null 610 // && line.getOppositeEnd(d).getParent() == toPaint) { 611 // nl = line.copy(); 612 // if (d == line.getStartItem()) 613 // d = nl.getStartItem(); 614 // else 615 // d = nl.getEndItem(); 616 // 617 // if (DisplayIO.FrameOnSide(toPaint) == 0) 618 // d.setX(base); 619 // else 620 // d.setX(base + adj); 621 // 622 // } else if (toPaint == DisplayIO.getCurrentFrame() 623 // && d.getParent() == null 624 // && line.getOppositeEnd(d).getParent() != toPaint) { 625 // nl = line.copy(); 626 // 627 // if (d == line.getStartItem()) 628 // d = nl.getEndItem(); 629 // else 630 // d = nl.getStartItem(); 631 // 632 // if (DisplayIO.FrameOnSide(toPaint) == 1) 633 // d.setX(d.getX() - DisplayIO.getMiddle()); 634 // else 635 // d.setX(d.getX() + DisplayIO.getMiddle()); 636 // } 637 // if (nl != null) { 638 // nl.invalidateAll(); 639 // FrameGraphics.requestRefresh(true); 640 // } 641 // return nl; 642 // } 643 644 private static void Paint(Graphics g, Image left, Image right, 645 Color background) { 646 647 // Triggers a FrameTransition is this has been signalled 648 // through an '@frameTransition: xxxx' on the frame. The type of 649 // transition is specified in the 'xxxx' part 650 651 652 // if TwinFrames mode is on, then clipping etc has to be set 653 if (DisplayIO.isTwinFramesOn()) { 654 // draw the two lines down the middle of the window 655 if (left != null) 656 left.getGraphics().drawLine(DisplayIO.getMiddle() - 2, 0, 657 DisplayIO.getMiddle() - 2, _MaxSize.height); 658 659 if (right != null) 660 right.getGraphics().drawLine(0, 0, 0, _MaxSize.height); 661 662 // set the clipping area 663 ((Graphics2D) g).setClip(0, 0, DisplayIO.getMiddle() - 1, 664 _MaxSize.height); 665 g.drawImage(left, 0, 0, Item.DEFAULT_BACKGROUND, null); 666 ((Graphics2D) g).setClip(null); 667 g.drawImage(right, DisplayIO.getMiddle() + 1, 0, 668 Item.DEFAULT_BACKGROUND, null); 669 670 671 } 672 // otherwise, just draw whichever side is active 673 else { 674 if (DisplayIO.getCurrentSide() == 0) { 675 if (!paintTransition(g,left)) { 676 // Nothing fancy occurred, just need to render the next slide to screen 677 g.drawImage(left, 0, 0, Item.DEFAULT_BACKGROUND, null); 678 } 679 } 680 else { 681 if (!paintTransition(g,right)) { 682 // Nothing fancy occurred, just need to render the next slide to screen 683 g.drawImage(right, 0, 0, Item.DEFAULT_BACKGROUND, null); 684 } 685 } 686 } 687 688 } 689 690 691 private static boolean paintTransition(Graphics g, Image image) 692 { 693 boolean performed_transition = false; 694 695 //If we are doing a transition 696 if(FrameTransitions.getSlide() == true){ 697 698 String input = "org.expeditee.gui.FrameTransitions"; 699 String slide_mode_method = FrameTransitions.getslideModeMethod(); 700 701 try { 702 Class<?> c = Class.forName(input); 703 704 Class[] cArg = new Class[3]; 705 cArg[0] = Graphics.class; 706 cArg[1] = Image.class; 707 cArg[2] = Dimension.class; 708 709 //Gets the method of transition and calls it 710 Method lMethod = c.getDeclaredMethod(slide_mode_method, cArg); 711 712 if(lMethod != null){ 713 // calling static method, so no class parameter needed 714 Object o = lMethod.invoke(null, g, image, _MaxSize); 715 performed_transition = true; 716 717 } 718 else{ 719 System.err.println("Unable to locate the transition '" + slide_mode_method + "'"); 720 } 721 722 } catch (Exception e) { 723 724 System.err.println("An Reflection Exception occurred trying to invoke '" + slide_mode_method + "'"); 725 e.printStackTrace(); 726 } 727 } 728 //Tells the frame to only transition once 729 FrameTransitions.setSlideFalse(); 730 731 return performed_transition; 732 } 733 734 735 public static void Clear() { 736 Graphics g = _DisplayGraphics.create(); 737 g.setColor(Color.WHITE); 738 g.fillRect(0, 0, _MaxSize.width, _MaxSize.height); 739 g.dispose(); 740 } 741 742 private static void PaintNonLinesNonPicture(Graphics2D g, List<Item> toPaint) { 743 for (Item i : toPaint) 744 if (!(i instanceof Line) && !(i instanceof XRayable)) 745 PaintItem(g, i); 312 if(current != null) current.paintTooltip(); 313 if (_lastToolTippedItem != null) _lastToolTippedItem.clearTooltips(); 314 _lastToolTippedItem = current; 315 } 316 317 if (FreeItems.hasCursor() && DisplayController.getCursor() == Item.DEFAULT_CURSOR) { 318 PaintNonLinesNonPicture(FreeItems.getCursor()); 319 } 320 } 321 322 private static void PaintNonLinesNonPicture(List<Item> toPaint) 323 { 324 for (Item i : toPaint) { 325 if (!(i instanceof Line) && !(i instanceof XRayable)) { 326 PaintItem(i); 327 } 328 } 746 329 } 747 330 … … 752 335 * @param toPaint 753 336 */ 754 private static void PaintLines(Graphics2D g, List<Item> toPaint) { 337 private static void PaintLines(List<Item> toPaint) 338 { 755 339 // Use this set to keep track of the items that have been painted 756 340 Collection<Item> done = new HashSet<Item>(); 757 for (Item i : toPaint) 341 for (Item i : toPaint) { 758 342 if (i instanceof Line) { 759 343 Line l = (Line) i; 760 344 if (done.contains(l)) { 761 l.paintArrows( g);345 l.paintArrows(); 762 346 } else { 763 347 // When painting a line all connected lines are painted too 764 348 done.addAll(l.getAllConnected()); 765 if (l.getStartItem().getEnclosedArea() == 0) 766 PaintItem(g, i);767 768 349 if (l.getStartItem().getEnclosedArea() == 0) PaintItem(i); 350 } 351 } 352 } 769 353 } 770 354 … … 776 360 * @param toPaint 777 361 */ 778 private static void PaintPictures( Graphics2D g, List<Item> toPaint,779 HashSet<Item> fillOnlyItems, HashSet<Item> done){362 private static void PaintPictures(List<Item> toPaint, HashSet<Item> fillOnlyItems, HashSet<Item> done) 363 { 780 364 781 365 List<Item> toFill = new LinkedList<Item>(); … … 783 367 // Ignore items that have already been done! 784 368 // Also ignore invisible items.. 785 // TODO possibly ignore invisible items before coming to this 786 // method? 787 if (done.contains(i)) 788 continue; 369 // TODO possibly ignore invisible items before coming to this method? 370 if (done.contains(i)) continue; 371 789 372 if (i instanceof XRayable) { 790 373 toFill.add(i); … … 792 375 } else if (i.hasEnclosures()) { 793 376 for (Item enclosure : i.getEnclosures()) { 794 if (!toFill.contains(enclosure)) 795 toFill.add(enclosure); 377 if (!toFill.contains(enclosure)) toFill.add(enclosure); 796 378 } 797 379 done.addAll(i.getConnected()); 798 } else if (i.isLineEnd() 799 && (!isAudienceMode() || !i.isConnectedToAnnotation())) { 380 } else if (i.isLineEnd() && (!DisplayController.isAudienceMode() || !i.isConnectedToAnnotation())) { 800 381 toFill.add(i); 801 382 done.addAll(i.getAllConnected()); … … 805 386 if (fillOnlyItems != null) { 806 387 for (Item i : fillOnlyItems) { 807 if (done.contains(i)) 388 if (done.contains(i)) { 808 389 continue; 809 else if (!isAudienceMode() || !i.isConnectedToAnnotation()) {390 } else if (!DisplayController.isAudienceMode() || !i.isConnectedToAnnotation()) { 810 391 toFill.add(i); 811 392 } … … 821 402 int cmp = aArea.compareTo(bArea); 822 403 if (cmp == 0) { 823 // System.out.println(a.getEnclosureID() + " " +824 // b.getID());\825 404 // Shapes to the left go underneath 826 Polygon pA = a.getEnclosedShape(); 827 Polygon pB = b.getEnclosedShape(); 828 if (pA == null || pB == null) 829 return 0; 830 return new Integer(pA.getBounds().x).compareTo(pB 831 .getBounds().x); 405 PolygonBounds pA = a.getEnclosedShape(); 406 PolygonBounds pB = b.getEnclosedShape(); 407 if (pA == null || pB == null) return 0; 408 return new Integer(pA.getMinX()).compareTo(pB.getMinX()); 832 409 } 833 410 return cmp * -1; 834 411 } 835 412 }); 413 836 414 for (Item i : toFill) { 837 415 if (i instanceof XRayable) { 838 PaintItem( g,i);416 PaintItem(i); 839 417 } else { 840 418 // Paint the fill and lines 841 i.paintFill( g);419 i.paintFill(); 842 420 List<Line> lines = i.getLines(); 843 if (lines.size() > 0) 844 PaintItem(g, lines.get(0)); 845 } 421 if (lines.size() > 0) PaintItem(lines.get(0)); 422 } 423 } 424 } 425 426 /** Displays the given Item on the screen. */ 427 static void PaintItem(Item i) 428 { 429 if (i == null) return; 430 431 // do not paint annotation items in audience mode 432 if (!DisplayController.isAudienceMode() || (!i.isConnectedToAnnotation() && !i.isAnnotation()) || i == FrameUtils.getLastEdited()) 433 { 434 i.paint(); 846 435 } 847 436 } … … 862 451 // Check if within 20% of the end of the line 863 452 Line l = (Line) i; 864 Item toDisconnect = l.getEndPointToDisconnect(Math 865 .round(FrameMouseActions.MouseX), Math 866 .round(FrameMouseActions.MouseY)); 453 Item toDisconnect = l.getEndPointToDisconnect(DisplayController.getMousePosition()); 867 454 868 455 // Brook: Widget Edges do not have such a context 869 456 if (toDisconnect != null && !(i instanceof WidgetEdge)) { 870 457 Item.HighlightMode newMode = toDisconnect.getHighlightMode(); 871 if (FreeItems. itemsAttachedToCursor())458 if (FreeItems.hasItemsAttachedToCursor()) 872 459 newMode = Item.HighlightMode.Normal; 873 460 // unhighlight all the other dots 874 461 for (Item conn : toDisconnect.getAllConnected()) { 875 462 conn.setHighlightMode(Item.HighlightMode.None); 463 conn.setHighlightColorToDefault(); 876 464 } 877 465 l.setHighlightMode(newMode); 466 l.setHighlightColorToDefault(); 878 467 // highlight the dot that will be in disconnect mode 879 468 toDisconnect.setHighlightMode(newMode); 469 toDisconnect.setHighlightColorToDefault(); 880 470 i = toDisconnect; 881 471 } else { 882 if (FrameMouseActions.isShiftDown()) {472 if (StandardInputEventListeners.kbmStateListener.isKeyDown(Key.SHIFT)) { 883 473 for(Item j : i.getAllConnected()) { 884 474 if(j instanceof Dot && !j.equals(i)) { 885 475 j.setHighlightMode(HighlightMode.None); 476 j.setHighlightColorToDefault(); 886 477 } 887 478 } 888 479 l.getStartItem().setHighlightMode(HighlightMode.Connected); 480 l.getStartItem().setHighlightColorToDefault(); 889 481 l.getEndItem().setHighlightMode(HighlightMode.Connected); 482 l.getEndItem().setHighlightColorToDefault(); 890 483 } else { 891 484 for(Item j : i.getAllConnected()) { 892 485 if(j instanceof Dot && !j.equals(i)) { 893 486 j.setHighlightMode(HighlightMode.Connected); 487 j.setHighlightColorToDefault(); 894 488 } 895 489 } … … 902 496 } else if (i instanceof Circle) { 903 497 i.setHighlightMode(Item.HighlightMode.Connected); 498 i.setHighlightColorToDefault(); 904 499 } else if (!i.isVisible()) { 905 500 changeHighlightMode(i, Item.HighlightMode.Connected, null); … … 913 508 // highlight connected dots, but only if there aren't items being carried on the cursor 914 509 if(FreeItems.getInstance().size() == 0) { 915 if (FrameMouseActions.isShiftDown()) {510 if (StandardInputEventListeners.kbmStateListener.isKeyDown(Key.SHIFT)) { 916 511 for(Item j : i.getAllConnected()) { 917 512 if(j instanceof Dot && !j.equals(i)) { 918 513 j.setHighlightMode(HighlightMode.Connected); 514 j.setHighlightColorToDefault(); 919 515 } 920 516 } … … 923 519 if(j instanceof Dot && !j.equals(i)) { 924 520 j.setHighlightMode(HighlightMode.None); 521 j.setHighlightColorToDefault(); 925 522 } 926 523 } … … 928 525 Item j = l.getOppositeEnd(i); 929 526 j.setHighlightMode(HighlightMode.Connected); 527 j.setHighlightColorToDefault(); 930 528 } 931 529 } … … 936 534 // For polygons need to make sure all other endpoints are 937 535 // unHighlighted 938 if (i.hasPermission(UserAppliedPermission.full)) 939 changeHighlightMode(i, Item.HighlightMode.Normal, 940 Item.HighlightMode.None); 941 else 942 changeHighlightMode(i, Item.HighlightMode.Connected, 943 Item.HighlightMode.Connected); 944 } 945 Repaint(); 536 if (i.hasPermission(UserAppliedPermission.full)) { 537 changeHighlightMode(i, Item.HighlightMode.Normal, Item.HighlightMode.None); 538 } else { 539 changeHighlightMode(i, Item.HighlightMode.Connected, Item.HighlightMode.Connected); 540 } 541 } 542 DisplayController.requestRefresh(true); 946 543 return i; 947 544 } 948 545 949 public static void changeHighlightMode(Item item, Item.HighlightMode newMode) { 546 public static void changeHighlightMode(Item item, Item.HighlightMode newMode) 547 { 950 548 changeHighlightMode(item, newMode, newMode); 951 549 } 952 550 953 public static void changeHighlightMode(Item item, 954 Item.HighlightMode newMode, Item.HighlightMode connectedNewMode) { 955 if (item == null) 956 return; 551 public static void changeHighlightMode(Item item, Item.HighlightMode newMode, Item.HighlightMode connectedNewMode) 552 { 553 if (item == null) return; 957 554 958 555 if (item.hasVector()) { … … 960 557 if (i.getEditTarget() == item) { 961 558 i.setHighlightMode(newMode); 559 i.setHighlightColorToDefault(); 962 560 } 963 561 } 964 562 item.setHighlightMode(newMode); 563 item.setHighlightColorToDefault(); 965 564 } else { 966 565 // Mike: TODO comment on why the line below is used!! 967 // I forgot already!! Opps566 // I forgot already!! Oops 968 567 boolean freeItem = FreeItems.getInstance().contains(item); 969 568 for (Item i : item.getAllConnected()) { 970 569 if (/* freeItem || */!FreeItems.getInstance().contains(i)) { 971 570 i.setHighlightMode(connectedNewMode); 972 } 973 } 974 if (!freeItem && newMode != connectedNewMode) 571 i.setHighlightColorToDefault(); 572 } 573 } 574 if (!freeItem && newMode != connectedNewMode) { 975 575 item.setHighlightMode(newMode); 976 } 977 Repaint(); 978 } 979 980 /** 981 * Repaints the buffer of the given Frame. 982 * 983 * @param toUpdate 984 * The Frame whose buffer is to be repainted. 985 */ 986 987 public static void UpdateBuffer(Frame toUpdate, boolean paintOverlays, 988 boolean useVolitile) { 989 toUpdate.setBuffer(getBuffer(toUpdate, paintOverlays, useVolitile)); 990 } 991 992 public static Image getBuffer(Frame toUpdate, boolean paintOverlays, 993 boolean useVolitile) { 994 if (toUpdate == null) 995 return null; 996 997 return Paint(toUpdate, null, paintOverlays, useVolitile); 998 } 999 1000 public static int getMode() { 1001 return _Mode; 1002 } 1003 1004 public static Graphics createGraphics() { 1005 // Error messages on start up will call this message before 1006 // _DisplayGraphics has been initialised 1007 if (_DisplayGraphics == null) 1008 return null; 1009 return _DisplayGraphics.create(); 1010 } 1011 1012 // Damaged areas pending to render. Accessessed by multiple threads 1013 private static HashSet<Rectangle> damagedAreas = new HashSet<Rectangle>(); 1014 1015 /** The clip used while paiting */ 1016 private static Area currentClip; 1017 1018 /** 1019 * The current clip that is used for painting at this instant. 1020 * 1021 * Intention: for extra clipping within an items paint method - the clip is 1022 * lost in the graphics object for which can be regained via this method. 1023 * 1024 * @return The current clip. Null if no clip (e.g. full screen render). 1025 */ 1026 public static Area getCurrentClip() { 1027 return (currentClip != null) ? (Area) currentClip.clone() : null; 1028 } 1029 1030 /** 1031 * Checks that the item is visible (on current frame && overlays) - if 1032 * visible then damaged area will be re-rendered on the next refresh. 1033 * 1034 * @param damagedItem 1035 * @param toRepaint 1036 */ 1037 public static void invalidateItem(Item damagedItem, Rectangle toRepaint) { 1038 // Only add area to repaint if item is visible... 1039 if (ItemUtils.isVisible(damagedItem)) { 1040 synchronized (damagedAreas) { 1041 damagedAreas.add(toRepaint); 1042 } 1043 } else if (MessageBay.isMessageItem(damagedItem)) { 1044 MessageBay.addDirtyArea(toRepaint); 1045 } 1046 } 1047 1048 /** 1049 * The given area will be re-rendered in the next refresh. This is the 1050 * quicker version and is more useful for re-rendering animated areas. 1051 * 1052 * @param toRepaint 1053 */ 1054 public static void invalidateArea(Rectangle toRepaint) { 1055 synchronized (damagedAreas) { 1056 damagedAreas.add(toRepaint); 1057 } 1058 } 1059 1060 public static void clearInvalidAreas() { 1061 synchronized (damagedAreas) { 1062 damagedAreas.clear(); 1063 } 1064 } 1065 1066 /** 1067 * Invalidates the buffered image of the current Frame and forces it to be 1068 * repainted on to the screen. Repaints all items. This is more expensive 1069 * than refresh. 1070 */ 1071 public static void ForceRepaint() { // TODO: TEMP: Use refresh 1072 Frame current = DisplayIO.getCurrentFrame(); 1073 1074 if (current == null) 1075 return; 1076 refresh(false); 1077 } 1078 1079 public static void Repaint() { // TODO: TEMP: Use refresh 1080 refresh(true); 1081 } 1082 1083 /** 1084 * Called to refresh the display screen. Thread safe. 1085 */ 1086 public static void refresh(boolean useInvalidation) { 1087 1088 if (_DisplayGraphics == null || _MaxSize.width <= 0 1089 || _MaxSize.height <= 0) 1090 return; 1091 1092 currentClip = null; 1093 if (useInvalidation) { // build clip 1094 1095 synchronized (damagedAreas) { 1096 if (!damagedAreas.isEmpty()) { 1097 1098 for (Rectangle r : damagedAreas) { 1099 if (currentClip == null) 1100 currentClip = new Area(r); 1101 else 1102 currentClip.add(new Area(r)); 1103 } 1104 damagedAreas.clear(); 1105 1106 } else if (MessageBay.isDirty()) { 1107 // Paint dirty message bay 1108 Graphics dg = _DisplayGraphics.create(); 1109 MessageBay.refresh(true, dg, Item.DEFAULT_BACKGROUND); 1110 return; 1111 1112 } else 1113 return; // nothing to render 1114 } 1115 1116 } else { 1117 synchronized (damagedAreas) { 1118 damagedAreas.clear(); 1119 } 1120 // System.out.println("FULLSCREEN REFRESH"); // TODO: REMOVE 1121 } 1122 1123 Frame[] toPaint = DisplayIO.getFrames(); 1124 Image left = Paint(toPaint[0], currentClip); 1125 Image right = Paint(toPaint[1], currentClip); 1126 1127 Graphics dg = _DisplayGraphics.create(); 1128 1129 // Paint frame to window 1130 Paint(dg, left, right, Item.DEFAULT_BACKGROUND); 1131 1132 // Paint any animations 1133 PopupManager.getInstance().paintAnimations(); 1134 1135 // Paint message bay 1136 MessageBay.refresh(useInvalidation, dg, Item.DEFAULT_BACKGROUND); 1137 1138 dg.dispose(); 1139 } 1140 1141 /** 1142 * If wanting to refresh from another thread - other than the main thread 1143 * that handles the expeditee datamodel (modifying / accessing / rendering). 1144 * Use this method for thread safety. 1145 */ 1146 public static synchronized void requestRefresh(boolean useInvalidation) { 1147 1148 _requestMarsheller._useInvalidation = useInvalidation; 1149 1150 if (_requestMarsheller._isQueued) { 1151 return; 1152 } 1153 1154 _requestMarsheller._isQueued = true; 1155 EventQueue.invokeLater(_requestMarsheller); // Render on AWT thread 1156 } 1157 1158 private static RenderRequestMarsheller _requestMarsheller = new FrameGraphics().new RenderRequestMarsheller(); 1159 1160 /** 1161 * Used for marshelling render requests from foreign threads to the event 1162 * dispatcher thread... (AWT) 1163 * 1164 * @author Brook Novak 1165 */ 1166 private class RenderRequestMarsheller implements Runnable { 1167 1168 boolean _useInvalidation = true; 1169 1170 boolean _isQueued = false; 1171 1172 public void run() { 1173 refresh(_useInvalidation); 1174 _isQueued = false; 1175 _useInvalidation = true; 1176 } 1177 1178 } 1179 576 item.setHighlightColorToDefault(); 577 } 578 } 579 DisplayController.requestRefresh(true); 580 } 581 582 /* 583 * 584 * FrameRenderPass stuff. (TODO: Not sure if this is used for anything? In Apollo. cts16) 585 * 586 */ 587 1180 588 /** 1181 589 * Adds a FinalFrameRenderPass to the frame-render pipeline... … … 1221 629 * situations. 1222 630 * 1223 * Although if there are multiples FinalFrameRenderPasses atta tach to the1224 * frame painter then it is not g araunteed to be rendered very last.631 * Although if there are multiples FinalFrameRenderPasses attach to the 632 * frame painter then it is not guaranteed to be rendered very last. 1225 633 * 1226 634 * @see FrameGraphics#addFinalFrameRenderPass(org.expeditee.gui.FrameGraphics.FrameRenderPass) … … 1236 644 * 1237 645 * @return The clip that the pass should use instead. i.e. if there are 1238 * any effects that cannot inv ladate prior to paint call.646 * any effects that cannot invalidate prior to paint call. 1239 647 */ 1240 Area paintStarted(AreacurrentClip);1241 1242 void paintFinalPass( Graphics g);1243 1244 void paintPreLayeredPanePass( Graphics g);648 Clip paintStarted(Clip currentClip); 649 650 void paintFinalPass(); 651 652 void paintPreLayeredPanePass(); 1245 653 } 1246 654
Note:
See TracChangeset
for help on using the changeset viewer.