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

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

Added lots of stuff

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