source: trunk/src/org/expeditee/gui/FrameGraphics.java@ 37

Last change on this file since 37 was 37, checked in by ra33, 16 years ago
File size: 21.6 KB
Line 
1package org.expeditee.gui;
2
3import java.awt.Color;
4import java.awt.Component;
5import java.awt.Container;
6import java.awt.Dimension;
7import java.awt.Font;
8import java.awt.Graphics;
9import java.awt.Graphics2D;
10import java.awt.GraphicsEnvironment;
11import java.awt.Point;
12import java.awt.RenderingHints;
13import java.awt.image.VolatileImage;
14import java.util.LinkedList;
15import java.util.List;
16
17import javax.swing.JPopupMenu;
18import javax.swing.SwingUtilities;
19
20import org.expeditee.actions.Misc;
21import org.expeditee.items.Dot;
22import org.expeditee.items.InteractiveWidget;
23import org.expeditee.items.Item;
24import org.expeditee.items.Line;
25import org.expeditee.items.Picture;
26import org.expeditee.items.Text;
27import org.expeditee.items.WidgetEdge;
28
29public class FrameGraphics {
30 public static final int MESSAGE_BUFFER_HEIGHT = 100;
31
32 private static final int MESSAGE_LINK_Y_OFFSET = 100;
33
34 private static final int MESSAGE_LINK_X = 50;
35
36 // the graphics used to paint with
37 private static Graphics2D _DisplayGraphics;
38
39 // the maximum size that can be used to paint on
40 private static Dimension _MaxSize;
41
42 // messages shown in the message window
43 public static Text[] Messages = new Text[4];
44
45 // buffer of the message window
46 private static VolatileImage _MessageBuffer = null;
47
48 // font used for the messages
49 private static Font _MessageFont = Font.decode("Serif-Plain-16");
50
51 // the number of messages currently shown (used for scrolling up)
52 private static int _MessageCount = 1;
53
54 // modes
55 public static final int MODE_NORMAL = 0;
56
57 public static final int MODE_AUDIENCE = 1;
58
59 public static final int MODE_XRAY = 2;
60
61 private static int _Mode = MODE_NORMAL;
62
63 // if true, error messages are not shown to the user
64 private static boolean _SupressErrors = false;
65
66 // The link to the message frameset
67 public static Text MessageLink = new Text(-2, "Messages");
68
69 // Date\time formatter for timestamping the messages
70 /*
71 * private static SimpleDateFormat _formatter = new SimpleDateFormat( "
72 * [ddMMMyyyy:HHmm]");
73 */
74
75 // creator for creating the message frames
76 private static FrameCreator _creator;
77
78 /**
79 * Returns the Graphics2D object currently being used to draw with, this may
80 * be null if no Graphics2D has been assigned yet.
81 *
82 * @return the Graphics2D object being used to draw, or null.
83 */
84 public static Graphics2D getGraphics() {
85 return _DisplayGraphics;
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 if (_Mode == MODE_AUDIENCE)
94 _Mode = MODE_NORMAL;
95 else
96 _Mode = MODE_AUDIENCE;
97
98 FrameUtils.Parse(DisplayIO.getCurrentFrame());
99 DisplayIO.UpdateTitle();
100 Repaint();
101 }
102
103 /**
104 * If X-Ray Mode is on this method will toggle it to be off, or vice-versa.
105 * This results in the Frame being re-parsed and repainted.
106 */
107 public static void ToggleXRayMode() {
108 if (_Mode == MODE_XRAY)
109 _Mode = MODE_NORMAL;
110 else
111 _Mode = MODE_XRAY;
112
113 FrameUtils.Parse(DisplayIO.getCurrentFrame());
114 Repaint();
115 }
116
117 /**
118 * @return True if Audience Mode is currently on, False otherwise.
119 */
120 public static boolean isAudienceMode() {
121 return _Mode == MODE_AUDIENCE;
122 }
123
124 /**
125 * @return True if X-Ray Mode is currently on, False otherwise.
126 */
127 public static boolean isXRayMode() {
128 return _Mode == MODE_XRAY;
129 }
130
131 public static void setMaxSize(Dimension max) {
132 if (_MaxSize == null)
133 _MaxSize = max;
134
135 // Mike assumes this is the height of the Message window?
136 _MaxSize.setSize(max.width, max.height - MESSAGE_BUFFER_HEIGHT);
137 if (DisplayIO.getCurrentFrame() != null) {
138 DisplayIO.getCurrentFrame().setBuffer(null);
139 DisplayIO.getCurrentFrame().setMaxSize(max);
140 }
141
142 _MessageBuffer = null;
143
144 for (int i = 0; i < Messages.length; i++) {
145 if (Messages[i] != null) {
146 Messages[i].setOffset(0, -_MaxSize.height);
147 Messages[i].setMaxSize(_MaxSize);
148 }
149 }
150
151 MessageLink.setOffset(0, -_MaxSize.height);
152 MessageLink.setMaxSize(_MaxSize);
153 MessageLink.setPosition(_MaxSize.width - MESSAGE_LINK_Y_OFFSET,
154 MESSAGE_LINK_X);
155
156 Repaint();
157 }
158
159 public static Dimension getMaxSize() {
160 return _MaxSize;
161 }
162
163 public static Dimension getMaxFrameSize() {
164 if (DisplayIO.isTwinFramesOn()) {
165 return new Dimension((_MaxSize.width / 2), _MaxSize.height);
166 } else
167 return _MaxSize;
168 }
169
170 /**
171 * Sets the Graphics2D object that should be used for all painting tasks.
172 * Note: Actual painting is done by using g.create() to create temporary
173 * instances that are then disposed of using g.dispose().
174 *
175 * @param g
176 * The Graphics2D object to use for all painting
177 */
178 public static void setDisplayGraphics(Graphics2D g) {
179 _DisplayGraphics = g;
180 }
181
182 /*
183 * Displays the given Item on the screen
184 */
185 private static void PaintItem(Graphics2D g, Item i) {
186 if (i == null || g == null)
187 return;
188
189 // do not paint annotation items in audience mode
190 if (g != null
191 && (!isAudienceMode()
192 || (isAudienceMode() && !i.isAnnotation()) || i == FrameUtils.LastEdited)) {
193
194 Graphics2D tg = (Graphics2D) g.create();
195 i.paint(tg);
196 tg.dispose();
197 }
198 }
199
200 public static void AddAllOverlayItems(List<Item> items, Frame overlay,
201 List<Frame> seenOverlays) {
202 if (seenOverlays.contains(overlay))
203 return;
204
205 seenOverlays.add(overlay);
206
207 for (Overlay o : overlay.getOverlays())
208 AddAllOverlayItems(items, o.Frame, seenOverlays);
209
210 items.addAll(overlay.getItems());
211 }
212
213 /**
214 * Recursive function similar to AddAllOverlayItems.
215 *
216 * @param widgets
217 * The collection the widgets will be added to
218 * @param overlay
219 * An "overlay" frame - this intially will be the parent frame
220 * @param seenOverlays
221 * Used for state in the recursion stack. Pass as an empty
222 * (non-null) list.
223 */
224 public static void AddAllOverlayWidgets(List<InteractiveWidget> widgets,
225 Frame overlay, List<Frame> seenOverlays) {
226 if (seenOverlays.contains(overlay))
227 return;
228
229 seenOverlays.add(overlay);
230
231 for (Overlay o : overlay.getOverlays())
232 AddAllOverlayWidgets(widgets, o.Frame, seenOverlays);
233
234 widgets.addAll(overlay.getInteractiveWidgets());
235 }
236
237 private static VolatileImage Paint(Frame toPaint) {
238 return Paint(toPaint, true);
239 }
240
241 private static VolatileImage Paint(Frame toPaint, boolean paintOverlay) {
242 if (toPaint == null)
243 return null;
244
245 // the buffer is not valid, so it must be recreated
246 if (!toPaint.isBufferValid()) {
247 VolatileImage buffer = toPaint.getBuffer();
248 if (buffer == null) {
249 GraphicsEnvironment ge = GraphicsEnvironment
250 .getLocalGraphicsEnvironment();
251 buffer = ge.getDefaultScreenDevice().getDefaultConfiguration()
252 .createCompatibleVolatileImage(_MaxSize.width,
253 _MaxSize.height);
254 toPaint.setBuffer(buffer);
255 }
256
257 Graphics2D bg = (Graphics2D) buffer.getGraphics();
258
259 // Nicer looking lines, but may be too jerky while
260 // rubber-banding on older machines
261 if (UserSettings.AntiAlias)
262 ((Graphics2D) bg).setRenderingHint(
263 RenderingHints.KEY_ANTIALIASING,
264 RenderingHints.VALUE_ANTIALIAS_ON);
265
266 bg.setColor(toPaint.getPaintBackgroundColor());
267 bg.fillRect(0, 0, _MaxSize.width, _MaxSize.height);
268
269 List<Item> paintItems = new LinkedList<Item>();
270 List<InteractiveWidget> paintWidgets;
271
272 if (paintOverlay) {
273
274 AddAllOverlayItems(paintItems, toPaint, new LinkedList<Frame>());
275
276 paintWidgets = new LinkedList<InteractiveWidget>();
277 AddAllOverlayWidgets(paintWidgets, toPaint,
278 new LinkedList<Frame>());
279
280 } else {
281 paintItems.addAll(toPaint.getItems());
282 paintWidgets = toPaint.getInteractiveWidgets();
283 }
284
285 // FIRST: Paint widgets swing gui (not expeditee gui) .
286 // Note that these are the ancored widgets
287 for (InteractiveWidget iw : paintWidgets) {
288 iw.paint(bg);
289 }
290
291 PaintPictures(bg, paintItems);
292
293 if (toPaint == DisplayIO.getCurrentFrame())
294 PaintPictures(bg, Frame.FreeItems);
295
296 PaintNonLinesNonPicture(bg, paintItems);
297 PaintLines(bg, paintItems);
298
299 if (toPaint == DisplayIO.getCurrentFrame())
300 PaintNonLinesNonPicture(bg, Frame.FreeItems);
301
302 // toPaint.setBufferValid(true);
303
304 if (DisplayIO.isTwinFramesOn()) {
305 List<Item> lines = new LinkedList<Item>();
306 for (Item i : Frame.FreeItems) {
307 if (i instanceof Line) {
308 Line line = (Line) i;
309
310 if (toPaint != DisplayIO.getCurrentFrame()) {
311 if (line.getEndItem().isFloating()
312 ^ line.getStartItem().isFloating()) {
313 lines.add(TransposeLine(line,
314 line.getEndItem(), toPaint, DisplayIO
315 .getRealMouseX(), -DisplayIO
316 .getMiddle()));
317 lines.add(TransposeLine(line, line
318 .getStartItem(), toPaint, DisplayIO
319 .getRealMouseX(), -DisplayIO
320 .getMiddle()));
321 }
322 } else {
323 if (line.getEndItem().isFloating()
324 ^ line.getStartItem().isFloating()) {
325 Line l = TransposeLine(line, line.getEndItem(),
326 toPaint, 0, 0);
327 if (l == null)
328 l = TransposeLine(line,
329 line.getStartItem(), toPaint, 0, 0);
330 if (l == null)
331 l = line;
332 lines.add(l);
333 } else
334 lines.add(line);
335 }
336 }
337 }
338 PaintLines(bg, lines);
339 } else {
340 // PaintPictures(bg, Frame.FreeItems);
341 // PaintNonLinesNonPicture(bg, Frame.FreeItems);
342 PaintLines(bg, Frame.FreeItems);
343 }
344
345 if (paintOverlay) {
346 PaintItem(bg, toPaint.getFrameNameItem());
347 }
348
349 // BROOK: Ensure popups are repainted
350 if (Browser._theBrowser != null)
351 repaintPopups(Browser._theBrowser.getLayeredPane(), bg);
352
353 bg.dispose();
354 }
355
356 return toPaint.getBuffer();
357 }
358
359 // creates a new line so that lines are shown correctly when spanning
360 // across frames in TwinFrames mode
361 private static Line TransposeLine(Line line, Item d, Frame toPaint,
362 int base, int adj) {
363 Line nl = null;
364
365 if (toPaint != DisplayIO.getCurrentFrame() && d.getParent() == null
366 && line.getOppositeEnd(d).getParent() == toPaint) {
367 nl = line.copy();
368 if (d == line.getStartItem())
369 d = nl.getStartItem();
370 else
371 d = nl.getEndItem();
372
373 if (DisplayIO.FrameOnSide(toPaint) == 0)
374 d.setX(base);
375 else
376 d.setX(base + adj);
377
378 } else if (toPaint == DisplayIO.getCurrentFrame()
379 && d.getParent() == null
380 && line.getOppositeEnd(d).getParent() != toPaint) {
381 nl = line.copy();
382
383 if (d == line.getStartItem())
384 d = nl.getEndItem();
385 else
386 d = nl.getStartItem();
387
388 if (DisplayIO.FrameOnSide(toPaint) == 1)
389 d.setX(d.getX() - DisplayIO.getMiddle());
390 else
391 d.setX(d.getX() + DisplayIO.getMiddle());
392 }
393
394 return nl;
395 }
396
397 private static void Paint(VolatileImage left, VolatileImage right,
398 Color background) {
399 if (_MessageBuffer == null) {
400 GraphicsEnvironment ge = GraphicsEnvironment
401 .getLocalGraphicsEnvironment();
402 _MessageBuffer = ge.getDefaultScreenDevice()
403 .getDefaultConfiguration().createCompatibleVolatileImage(
404 _MaxSize.width, MESSAGE_BUFFER_HEIGHT);
405 }
406
407 paintMessage(_MessageBuffer.createGraphics(), background);
408 Graphics g = _DisplayGraphics.create();
409
410 // if TwinFrames mode is on, then clipping etc has to be set
411 if (DisplayIO.isTwinFramesOn()) {
412 // draw the two lines down the middle of the window
413 if (left != null)
414 left.getGraphics().drawLine(DisplayIO.getMiddle() - 2, 0,
415 DisplayIO.getMiddle() - 2, _MaxSize.height);
416
417 if (right != null)
418 right.getGraphics().drawLine(0, 0, 0, _MaxSize.height);
419
420 // set the clipping area
421 ((Graphics2D) g).setClip(0, 0, DisplayIO.getMiddle() - 1,
422 _MaxSize.height);
423 g.drawImage(left, 0, 0, DisplayIO.DEFAULT_BACKGROUND, null);
424 ((Graphics2D) g).setClip(null);
425 g.drawImage(right, DisplayIO.getMiddle() + 1, 0,
426 DisplayIO.DEFAULT_BACKGROUND, null);
427
428 // otherwise, just draw whichever side is active
429 } else {
430 if (DisplayIO.getCurrentSide() == 0)
431 g.drawImage(left, 0, 0, DisplayIO.DEFAULT_BACKGROUND, null);
432 else
433 g.drawImage(right, 0, 0, DisplayIO.DEFAULT_BACKGROUND, null);
434 }
435 // draw the message area
436 g.drawImage(_MessageBuffer, 0, _MaxSize.height, null);
437 g.dispose();
438
439 }
440
441 /**
442 * Paints the message area
443 * @param g
444 * @param background
445 */
446 private static void paintMessage(Graphics2D g, Color background) {
447 ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
448 RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
449 g.setColor(background);
450 g.fillRect(0, 0, _MaxSize.width, MESSAGE_BUFFER_HEIGHT);
451 g.setFont(_MessageFont);
452 g.setColor(Color.BLACK);
453 g.drawLine(0, 0, _MaxSize.width, 0);
454 for (Text t : Messages)
455 PaintItem(g, t);
456 if (MessageLink.getLink() != null)
457 PaintItem(g, MessageLink);
458 g.dispose();
459 }
460
461 public static void Clear() {
462 Graphics g = _DisplayGraphics.create();
463 g.setColor(Color.WHITE);
464 g.fillRect(0, 0, _MaxSize.width, _MaxSize.height);
465 g.dispose();
466 }
467
468 /**
469 * Called to refresh the display screen.
470 *
471 */
472 public static void Repaint() {
473 if (_DisplayGraphics == null)
474 return;
475
476 if (UserSettings.Threading) {
477 if (painter == null) {
478 painter = new FrameGraphics().new Repainter();
479
480 painter.setDaemon(true);
481 painter.setPriority(Thread.MIN_PRIORITY);
482
483 painter.start();
484 } else
485 painter.run();
486 } else {
487 Frame[] toPaint = DisplayIO.getFrames();
488
489 if (toPaint != null) {
490 VolatileImage left = Paint(toPaint[0]);
491 VolatileImage right = Paint(toPaint[1]);
492 Paint(left, right, DisplayIO.DEFAULT_BACKGROUND);
493 }
494 }
495 }
496
497 private static Repainter painter = null;
498
499 private static void PaintNonLinesNonPicture(Graphics2D g, List<Item> toPaint) {
500 for (Item i : toPaint)
501 if (!(i instanceof Line) && !(i instanceof Picture))
502 PaintItem(g, i);
503 }
504
505 private static void PaintLines(Graphics2D g, List<Item> toPaint) {
506 for (Item i : toPaint)
507 if (i instanceof Line)
508 PaintItem(g, i);
509 }
510
511 private static void PaintPictures(Graphics2D g, List<Item> toPaint) {
512 for (Item i : toPaint) {
513 if (i instanceof Picture)
514 PaintItem(g, i);
515 else if (i instanceof Dot)
516 ((Dot) i).paintFill(g);
517 }
518 }
519
520 /**
521 * Highlights an item on the screen Note: All graphics are handled by the
522 * Item itself.
523 *
524 * @param i
525 * The Item to highlight.
526 * @param val
527 * True if the highlighting is being shown, false if it is being
528 * erased.
529 */
530 public static void Highlight(Item i) {
531 if ((i instanceof Line)) {
532 // Check if within 20% of the end of the line
533 Line l = (Line) i;
534 Item toDisconnect = l.getEndPointToDisconnect(
535 FrameMouseActions.MouseX, FrameMouseActions.MouseY);
536
537 // Brook: Widget Edges do not have such a context
538 if (toDisconnect != null && !(i instanceof WidgetEdge)) {
539 Item.SelectedMode newMode = toDisconnect.getSelectedMode();
540 if (Frame.itemAttachedToCursor())
541 newMode = Item.SelectedMode.Normal;
542 // unhighlight all the other dots
543 for (Item conn : toDisconnect.getAllConnected()) {
544 conn.setSelectedMode(Item.SelectedMode.None);
545 }
546 l.setSelectedMode(newMode);
547 // highlight the dot that will be in disconnect mode
548 toDisconnect.setSelectedMode(newMode);
549 } else {
550 List<Item> connected = i.getAllConnected();
551 for (Item conn : connected) {
552 conn.setSelectedMode(Item.SelectedMode.Connected);
553 }
554 }
555 } else {
556 i.setSelectedMode(Item.SelectedMode.Normal);
557 }
558
559 Repaint();
560 }
561
562 public static void ChangeSelectionMode(Item item, Item.SelectedMode newMode) {
563 if (item == null)
564 return;
565
566 for(Item i: item.getAllConnected())
567 i.setSelectedMode(newMode);
568 Repaint();
569 }
570
571 public static void OverwriteMessage(String message) {
572 for (int ind = Messages.length - 1; ind >= 0; ind--) {
573 if (Messages[ind] != null) {
574 Messages[ind].setText(message);
575 Repaint();
576 return;
577 }
578 }
579
580 // if we have not returned, then there are no messages yet
581 DisplayMessage(message, Color.darkGray);
582 }
583
584 /**
585 * Displays the given message in the message area of the Frame, any previous
586 * message is cleared from the screen.
587 *
588 * @param message
589 * The message to display to the user in the message area
590 */
591 public static void DisplayMessage(String message) {
592 DisplayMessageAlways(message);
593 }
594
595 public static void DisplayMessage(String message, Color textColor) {
596 displayMessage(message, null, textColor);
597 Misc.Beep();
598 }
599
600 public static void DisplayMessage(Text message) {
601 displayMessage(message.getFirstLine(), message.getLink(), message
602 .getColor());
603 // Misc.Beep();
604 }
605
606 public static void DisplayMessageAlways(String message) {
607 // _lastMessage = null;
608 displayMessage(message, null, Color.BLACK);
609 Misc.Beep();
610 }
611
612 public static void WarningMessage(String message) {
613 displayMessage(message, null, Color.MAGENTA);
614 Misc.Beep();
615 }
616
617 // private static String _lastMessage = null;
618
619 private static void displayMessage(String message, String link, Color color) {
620 // add timestamp to message
621 // if (message.equals(_lastMessage))
622 // return;
623 // _lastMessage = message;
624
625 // message += _formatter.format(Calendar.getInstance().getTime());
626
627 // if the creator needs to be initialised (happens on first message)
628 if (_creator == null) {
629 _creator = new FrameCreator("Messages", true);
630
631 // set up 'Messages' link on the right hand side
632 MessageLink.setPosition(_MaxSize.width - MESSAGE_LINK_Y_OFFSET,
633 MESSAGE_LINK_X);
634 MessageLink.setOffset(0, -_MaxSize.height);
635 }
636
637 // if the message slots have not all been used yet
638 if (_MessageCount <= Messages.length) {
639 int pos = 15;
640 // find the next empty slot, and create the new message
641 for (int i = 0; i < Messages.length; i++) {
642 if (Messages[i] == null) {
643 Messages[i] = new Text(-1, "@" + _MessageCount++ + ": "
644 + message);
645 Messages[i].setPosition(20, pos);
646 Messages[i].setOffset(0, -_MaxSize.height);
647 Messages[i].setMaxSize(_MaxSize);
648 Messages[i].setColor(color);
649 Messages[i].setLink(link);
650
651 _creator.addItem(Messages[i].copy());
652 MessageLink.setLink(_creator.getCurrent());
653 Repaint();
654 return;
655 }
656
657 pos += 25;
658 }
659 }
660
661 // if we have not returned then all message slots are used
662 for (int i = 0; i < Messages.length - 1; i++) {
663 Messages[i].setText(Messages[i + 1].getFirstLine());
664 Messages[i].setColor(Messages[i + 1].getColor());
665 Messages[i].setLink(Messages[i + 1].getLink());
666 }
667
668 // show the new message
669 Text last = Messages[Messages.length - 1];
670 last.setColor(color);
671 last.setText("@" + _MessageCount++ + ": " + message);
672 last.setLink(link);
673
674 _creator.addItem(last.copy());
675 // update the link to the latest message frame
676 MessageLink.setLink(_creator.getCurrent());
677 Repaint();
678 }
679
680 /**
681 * Checks if the error message ends with a frame name after the
682 * frameNameSeparator symbol
683 *
684 * @param message
685 * the message to be displayed
686 */
687 public static void LinkedErrorMessage(String message) {
688 if (_SupressErrors)
689 return;
690 Misc.Beep();
691 String[] tokens = message.split(Text.FRAME_NAME_SEPARATOR);
692 String link = null;
693 if (tokens.length > 1)
694 link = tokens[tokens.length - 1];
695 displayMessage(message, link, Color.RED);
696 }
697
698 public static void ErrorMessage(String message) {
699 if (_SupressErrors)
700 return;
701 Misc.Beep();
702 displayMessage(message, null, Color.RED);
703
704 // Michael is confused about why this code is gettting into infinite
705 // loop
706
707 /*
708 * Exception e = new Exception();
709 *
710 * try{ throw e; }catch(Exception ex){ StackTraceElement[] trace =
711 * ex.getStackTrace(); message += " (" + trace[1].getFileName() + ":" +
712 * trace[1].getLineNumber() + ")";
713 *
714 * String source = trace[1].getClassName(); source = "src.java." +
715 * source; source = source.replace(".", File.separator); source +=
716 * ".java";
717 *
718 * try{ BufferedReader reader = new BufferedReader(new
719 * FileReader(source)); FrameCreator creator = new
720 * FrameCreator("Messages", false);
721 *
722 * int min = trace[1].getLineNumber() - 10; int max =
723 * trace[1].getLineNumber() + 3;
724 *
725 * int line = 0; while(reader.ready()){ if(line > min && line < max)
726 * if(line == trace[1].getLineNumber() - 1)
727 * creator.addText(reader.readLine(), Color.RED); else
728 * creator.addText(reader.readLine()); else if(line > max) break; else
729 * reader.readLine();
730 *
731 * line++; }
732 *
733 * reader.close();
734 *
735 * displayMessage(message, creator.getCurrent(), Color.RED);
736 * }catch(Exception ioe){ ioe.printStackTrace(); } }
737 */
738 }
739
740 private class Repainter extends Thread {
741 public boolean isPainting = false;
742
743 public void run() {
744 isPainting = true;
745
746 Frame[] toPaint = DisplayIO.getFrames();
747
748 if (toPaint != null) {
749 VolatileImage left = Paint(toPaint[0]);
750 VolatileImage right = Paint(toPaint[1]);
751 Paint(left, right, DisplayIO.DEFAULT_BACKGROUND);
752 }
753
754 isPainting = false;
755 }
756 }
757
758 /**
759 * Invalidates the buffered image of the current Frame and forces it to be
760 * repainted on to the screen.
761 */
762 public static void ForceRepaint() {
763 Frame current = DisplayIO.getCurrentFrame();
764
765 if (current == null)
766 return;
767
768 Repaint();
769 }
770
771 /**
772 * Repaints the buffer of the given Frame.
773 *
774 * @param toUpdate
775 * The Frame whose buffer is to be repainted.
776 */
777
778 public static void UpdateBuffer(Frame toUpdate, boolean paintOverlays) {
779 if (toUpdate == null)
780 return;
781
782 VolatileImage vi = Paint(toUpdate, paintOverlays);
783 toUpdate.setBuffer(vi);
784 }
785
786 public static void SupressErrors(boolean val) {
787 _SupressErrors = val;
788 }
789
790 private static void repaintPopups(Container parent, Graphics g) {
791 for (Component c : parent.getComponents()) {
792 if (c instanceof JPopupMenu && ((JPopupMenu) c).isVisible()) {
793
794 Point p = SwingUtilities.convertPoint(c, c.getLocation(),
795 Browser._theBrowser.getContentPane());
796
797 g.translate(p.x, p.y);
798 c.paint(g);
799 g.translate(-p.x, -p.y);
800 } else if (c instanceof Container
801 && c != Browser._theBrowser.getContentPane()) {
802 repaintPopups((Container) c, g);
803 }
804 }
805 }
806}
Note: See TracBrowser for help on using the repository browser.