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

Last change on this file since 74 was 74, checked in by ra33, 16 years ago

Fixed bugs... added some more features!!

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