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

Last change on this file since 32 was 32, checked in by ra33, 16 years ago
File size: 21.8 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 ChangeSelectionMode(Item item, Item.SelectedMode newMode) {
572 if (item == null)
573 return;
574
575 for(Item i: item.getAllConnected())
576 i.setSelectedMode(newMode);
577 Repaint();
578 }
579
580 public static void OverwriteMessage(String message) {
581 for (int ind = Messages.length - 1; ind >= 0; ind--) {
582 if (Messages[ind] != null) {
583 Messages[ind].setText(message);
584 Repaint();
585 return;
586 }
587 }
588
589 // if we have not returned, then there are no messages yet
590 DisplayMessage(message, Color.darkGray);
591 }
592
593 /**
594 * Displays the given message in the message area of the Frame, any previous
595 * message is cleared from the screen.
596 *
597 * @param message
598 * The message to display to the user in the message area
599 */
600 public static void DisplayMessage(String message) {
601 DisplayMessageAlways(message);
602 }
603
604 public static void DisplayMessage(String message, Color textColor) {
605 displayMessage(message, null, textColor);
606 Misc.Beep();
607 }
608
609 public static void DisplayMessage(Text message) {
610 displayMessage(message.getFirstLine(), message.getLink(), message
611 .getColor());
612 // Misc.Beep();
613 }
614
615 public static void DisplayMessageAlways(String message) {
616 // _lastMessage = null;
617 displayMessage(message, null, Color.BLACK);
618 Misc.Beep();
619 }
620
621 public static void WarningMessage(String message) {
622 displayMessage(message, null, Color.MAGENTA);
623 Misc.Beep();
624 }
625
626 // private static String _lastMessage = null;
627
628 private static void displayMessage(String message, String link, Color color) {
629 // add timestamp to message
630 // if (message.equals(_lastMessage))
631 // return;
632 // _lastMessage = message;
633
634 // message += _formatter.format(Calendar.getInstance().getTime());
635
636 // if the creator needs to be initialised (happens on first message)
637 if (_creator == null) {
638 _creator = new FrameCreator("Messages", true);
639
640 // set up 'Messages' link on the right hand side
641 MessageLink.setPosition(_MaxSize.width - MESSAGE_LINK_Y_OFFSET,
642 MESSAGE_LINK_X);
643 MessageLink.setOffset(0, -_MaxSize.height);
644 }
645
646 // if the message slots have not all been used yet
647 if (_MessageCount <= Messages.length) {
648 int pos = 15;
649 // find the next empty slot, and create the new message
650 for (int i = 0; i < Messages.length; i++) {
651 if (Messages[i] == null) {
652 Messages[i] = new Text(-1, "@" + _MessageCount++ + ": "
653 + message);
654 Messages[i].setPosition(20, pos);
655 Messages[i].setOffset(0, -_MaxSize.height);
656 Messages[i].setMaxSize(_MaxSize);
657 Messages[i].setColor(color);
658 Messages[i].setLink(link);
659
660 _creator.addItem(Messages[i].copy());
661 MessageLink.setLink(_creator.getCurrent());
662 Repaint();
663 return;
664 }
665
666 pos += 25;
667 }
668 }
669
670 // if we have not returned then all message slots are used
671 for (int i = 0; i < Messages.length - 1; i++) {
672 Messages[i].setText(Messages[i + 1].getFirstLine());
673 Messages[i].setColor(Messages[i + 1].getColor());
674 Messages[i].setLink(Messages[i + 1].getLink());
675 }
676
677 // show the new message
678 Text last = Messages[Messages.length - 1];
679 last.setColor(color);
680 last.setText("@" + _MessageCount++ + ": " + message);
681 last.setLink(link);
682
683 _creator.addItem(last.copy());
684 // update the link to the latest message frame
685 MessageLink.setLink(_creator.getCurrent());
686 Repaint();
687 }
688
689 /**
690 * Checks if the error message ends with a frame name after the
691 * frameNameSeparator symbol
692 *
693 * @param message
694 * the message to be displayed
695 */
696 public static void LinkedErrorMessage(String message) {
697 if (_SupressErrors)
698 return;
699 Misc.Beep();
700 String[] tokens = message.split(Text.FRAME_NAME_SEPARATOR);
701 String link = null;
702 if (tokens.length > 1)
703 link = tokens[tokens.length - 1];
704 displayMessage(message, link, Color.RED);
705 }
706
707 public static void ErrorMessage(String message) {
708 if (_SupressErrors)
709 return;
710 Misc.Beep();
711 displayMessage(message, null, Color.RED);
712
713 // Michael is confused about why this code is gettting into infinite
714 // loop
715
716 /*
717 * Exception e = new Exception();
718 *
719 * try{ throw e; }catch(Exception ex){ StackTraceElement[] trace =
720 * ex.getStackTrace(); message += " (" + trace[1].getFileName() + ":" +
721 * trace[1].getLineNumber() + ")";
722 *
723 * String source = trace[1].getClassName(); source = "src.java." +
724 * source; source = source.replace(".", File.separator); source +=
725 * ".java";
726 *
727 * try{ BufferedReader reader = new BufferedReader(new
728 * FileReader(source)); FrameCreator creator = new
729 * FrameCreator("Messages", false);
730 *
731 * int min = trace[1].getLineNumber() - 10; int max =
732 * trace[1].getLineNumber() + 3;
733 *
734 * int line = 0; while(reader.ready()){ if(line > min && line < max)
735 * if(line == trace[1].getLineNumber() - 1)
736 * creator.addText(reader.readLine(), Color.RED); else
737 * creator.addText(reader.readLine()); else if(line > max) break; else
738 * reader.readLine();
739 *
740 * line++; }
741 *
742 * reader.close();
743 *
744 * displayMessage(message, creator.getCurrent(), Color.RED);
745 * }catch(Exception ioe){ ioe.printStackTrace(); } }
746 */
747 }
748
749 private class Repainter extends Thread {
750 public boolean isPainting = false;
751
752 public void run() {
753 isPainting = true;
754
755 Frame[] toPaint = DisplayIO.getFrames();
756
757 if (toPaint != null) {
758 VolatileImage left = Paint(toPaint[0]);
759 VolatileImage right = Paint(toPaint[1]);
760 Paint(left, right, DisplayIO.DEFAULT_BACKGROUND);
761 }
762
763 isPainting = false;
764 }
765 }
766
767 /**
768 * Invalidates the buffered image of the current Frame and forces it to be
769 * repainted on to the screen.
770 */
771 public static void ForceRepaint() {
772 Frame current = DisplayIO.getCurrentFrame();
773
774 if (current == null)
775 return;
776
777 Repaint();
778 }
779
780 /**
781 * Repaints the buffer of the given Frame.
782 *
783 * @param toUpdate
784 * The Frame whose buffer is to be repainted.
785 */
786
787 public static void UpdateBuffer(Frame toUpdate, boolean paintOverlays) {
788 if (toUpdate == null)
789 return;
790
791 VolatileImage vi = Paint(toUpdate, paintOverlays);
792 toUpdate.setBuffer(vi);
793 }
794
795 public static void SupressErrors(boolean val) {
796 _SupressErrors = val;
797 }
798
799 private static void repaintPopups(Container parent, Graphics g) {
800 for (Component c : parent.getComponents()) {
801 if (c instanceof JPopupMenu && ((JPopupMenu) c).isVisible()) {
802
803 Point p = SwingUtilities.convertPoint(c, c.getLocation(),
804 Browser._theBrowser.getContentPane());
805
806 g.translate(p.x, p.y);
807 c.paint(g);
808 g.translate(-p.x, -p.y);
809 } else if (c instanceof Container
810 && c != Browser._theBrowser.getContentPane()) {
811 repaintPopups((Container) c, g);
812 }
813 }
814 }
815}
Note: See TracBrowser for help on using the repository browser.