Source Code Cross Referenced for AbstractComponentDecorator.java in  » Testing » abbot-1.0.1 » abbot » editor » widgets » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Testing » abbot 1.0.1 » abbot.editor.widgets 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        package abbot.editor.widgets;
002:
003:        import java.awt.*;
004:        import java.awt.event.ComponentAdapter;
005:        import java.awt.event.ComponentEvent;
006:        import java.awt.event.HierarchyEvent;
007:        import java.awt.event.HierarchyListener;
008:        import java.awt.event.MouseEvent;
009:        import java.awt.geom.AffineTransform;
010:        import java.awt.geom.Area;
011:        import java.beans.PropertyChangeEvent;
012:        import java.beans.PropertyChangeListener;
013:        import java.lang.reflect.Field;
014:        import java.util.ArrayList;
015:        import java.util.Iterator;
016:        import java.util.List;
017:        import javax.swing.JComponent;
018:        import javax.swing.JLayeredPane;
019:        import javax.swing.RootPaneContainer;
020:        import javax.swing.SwingUtilities;
021:        import javax.swing.border.LineBorder;
022:
023:        /** Provide a method for consistently augmenting the appearance of a given 
024:         * component by painting something on it <i>after</i> the component itself
025:         * gets painted.  If not explicitly removed via {@link #dispose}, an instance
026:         * of this object will live as long as its target component.<p>
027:         * By default, the decorator matches the location and size of the decorated 
028:         * component, but the bounds can be adjusted by overriding 
029:         * {@link #getDecorationBounds()}.  The {@link #synch()} method should be called
030:         * whenever the bounds returned by {@link #getDecorationBounds()} would change.
031:         * <p>
032:         * The decoration is clipped to the bounds set on the decoration, which does
033:         * not necessarily need to be the same as the decorated component's bounds.  The
034:         * decoration may extend beyond the decorated component bounds, or it may be
035:         * reduced to a smaller region.  
036:         */
037:        // NOTE: OSX 1.6 lacks hierarchy events that w32 sends on layer changes
038:        // TODO: should probably do some locking on Component.getTreeLock()
039:        // TODO: synch underlying cursor when decorator covers more than 
040:        // one component; the cursor should change if the decoration exceeds the 
041:        // component's bounds (add mouse listener?)
042:        public abstract class AbstractComponentDecorator {
043:            public static final Rectangle DEFAULT_BOUNDS = null;
044:            public static final int TOP = 0;
045:            // Disabled for now, since it doesn't work properly
046:            private static final int BOTTOM = -1;
047:            /** Account for the difference between the decorator actual origin
048:             * and the logical origin we want to pass to the {@link #paint} method.
049:             */
050:            private Point originOffset = new Point(0, 0);
051:
052:            private Painter painter;
053:            private JComponent component;
054:            private Container parent;
055:            private Component layerRoot;
056:            private Listener listener;
057:            private int layerOffset;
058:            private int position;
059:            private Rectangle bounds;
060:
061:            /** Create a decorator for the given component. */
062:            public AbstractComponentDecorator(JComponent c) {
063:                this (c, 1);
064:            }
065:
066:            /** Create a decorator for the given component, indicating the layer
067:             * offset from the target component.  Negative values mean the decoration
068:             * is painted <em>before</em> the target component is painted.
069:             */
070:            public AbstractComponentDecorator(JComponent c, int layerOffset) {
071:                this (c, layerOffset, TOP);
072:            }
073:
074:            /** Create a decorator with the given position within its layer. 
075:             * Use {@link #TOP} to cover other decorations, or {@link #BOTTOM} 
076:             * to be covered by other decorations.<p>
077:             * WARNING: BOTTOM doesn't currently work, probably a JLayeredPane bug
078:             * in either the code or documentation.
079:             * @see JLayeredPane
080:             */
081:            public AbstractComponentDecorator(JComponent c, int layerOffset,
082:                    int position) {
083:                component = c;
084:                this .layerOffset = layerOffset;
085:                this .position = position;
086:                this .bounds = DEFAULT_BOUNDS;
087:                parent = c.getParent();
088:                painter = new Painter();
089:                listener = new Listener();
090:                component.addHierarchyListener(listener);
091:                component.addComponentListener(listener);
092:                attach();
093:            }
094:
095:            /** Set the text to be displayed when the mouse is over the decoration.
096:             * @see JComponent#setToolTipText(String) 
097:             */
098:            public void setToolTipText(String text) {
099:                painter.setToolTipText(text);
100:            }
101:
102:            /** Return the currently set default tooltip text. 
103:             * @see JComponent#setToolTipText
104:             */
105:            public String getToolTipText() {
106:                return painter.getToolTipText();
107:            }
108:
109:            /** Provide for different tool tips depending on the actual location
110:             * over the decoration.  Note that if you <em>only</em> override this
111:             * method, you must also invoke {@link #setToolTipText(String)} with
112:             * a non-<span class="javakeyword">null</span> argument.
113:             * @see JComponent#getToolTipText(MouseEvent)
114:             */
115:            public String getToolTipText(MouseEvent e) {
116:                return getToolTipText();
117:            }
118:
119:            /** Indicate whether the decoration is showing.  Its painter must be
120:             * visible and showing (showing depends on window ancestor).
121:             */
122:            public boolean isShowing() {
123:                return painter.isShowing();
124:            }
125:
126:            /** Indicate whether any of the decoration is visible.  The decoration
127:             * may be clipped by ancestor scroll panes or by being moved outside
128:             * if the visible region of its parent window.
129:             */
130:            public boolean isVisible() {
131:                return painter.isVisible();
132:            }
133:
134:            /** Use this to change the visibility of the decoration. */
135:            public void setVisible(boolean visible) {
136:                painter.setVisible(visible);
137:            }
138:
139:            protected void attach() {
140:                if (layerRoot != null) {
141:                    layerRoot.removePropertyChangeListener(listener);
142:                    layerRoot = null;
143:                }
144:                RootPaneContainer rpc = (RootPaneContainer) SwingUtilities
145:                        .getAncestorOfClass(RootPaneContainer.class, component);
146:                if (rpc != null
147:                        && SwingUtilities.isDescendingFrom(component, rpc
148:                                .getLayeredPane())) {
149:                    JLayeredPane lp = rpc.getLayeredPane();
150:                    Component layeredChild = component;
151:                    int layer = JLayeredPane.DRAG_LAYER.intValue();
152:                    if (this  instanceof  BackgroundPainter) {
153:                        layer = ((BackgroundPainter) this ).layer;
154:                        painter.setDecoratedLayer(layer);
155:                    } else if (layeredChild == lp) {
156:                        // Is the drag layer the best layer to use when decorating
157:                        // the layered pane?
158:                        painter.setDecoratedLayer(layer);
159:                    } else {
160:                        while (layeredChild.getParent() != lp) {
161:                            layeredChild = layeredChild.getParent();
162:                        }
163:                        int base = lp.getLayer(layeredChild);
164:                        // NOTE: JLayeredPane doesn't properly repaint an overlapping
165:                        // child when an obscured child calls repaint() if the two
166:                        // are in the same layer, so we use the next-higher layer
167:                        // instead of simply using a different position within the 
168:                        // layer.
169:                        layer = base + layerOffset;
170:                        if (layerOffset < 0) {
171:                            BackgroundPainter bp = (BackgroundPainter) lp
172:                                    .getClientProperty(BackgroundPainter
173:                                            .key(base));
174:                            if (bp == null) {
175:                                bp = new BackgroundPainter(lp, base);
176:                            }
177:                        }
178:                        painter.setDecoratedLayer(base);
179:                        layerRoot = layeredChild;
180:                        layerRoot.addPropertyChangeListener(listener);
181:                    }
182:                    lp.add(painter, new Integer(layer), position);
183:                } else {
184:                    // Always detach when the target component's window is null
185:                    // or is not a suitable container,
186:                    // otherwise we might prevent GC of the component
187:                    Container parent = painter.getParent();
188:                    if (parent != null) {
189:                        parent.remove(painter);
190:                    }
191:                }
192:                // Track size changes in the decorated component's parent
193:                if (parent != null) {
194:                    parent.removeComponentListener(listener);
195:                }
196:                parent = component.getParent();
197:                if (parent != null) {
198:                    parent.addComponentListener(listener);
199:                }
200:                synch();
201:            }
202:
203:            /** Ensure the size of the decorator matches the current 
204:             * decoration bounds with appropriate clipping to viewports.
205:             */
206:            protected void synch() {
207:                Container painterParent = painter.getParent();
208:                if (painterParent != null) {
209:                    Rectangle decorated = getDecorationBounds();
210:                    Rectangle clipRect = clipDecorationBounds(decorated);
211:
212:                    Point pt = SwingUtilities.convertPoint(component,
213:                            clipRect.x, clipRect.y, painterParent);
214:                    if (clipRect.width <= 0 || clipRect.height <= 0) {
215:                        setPainterBounds(-1, -1, 0, 0);
216:                        setVisible(false);
217:                    } else {
218:                        setPainterBounds(pt.x, pt.y, clipRect.width,
219:                                clipRect.height);
220:                        setVisible(true);
221:                    }
222:                    painterParent.repaint();
223:                }
224:            }
225:
226:            /** Adjust the painting offsets and size of the decoration to
227:             * account for ancestor clipping.  This might be due to scroll panes
228:             * or having the decoration lie outside the parent layered pane.
229:             */
230:            protected Rectangle clipDecorationBounds(Rectangle decorated) {
231:                // Amount we have to translate the Graphics context
232:                originOffset.x = decorated.x;
233:                originOffset.y = decorated.y;
234:                // If the the component is obscured (by a viewport or some
235:                // other means), use the painter bounds to clip to the visible 
236:                // bounds.  Doing may change the actual origin, so adjust our
237:                // origin offset accordingly
238:                Rectangle visible = getClippingRect(component, decorated);
239:                Rectangle clipRect = decorated.intersection(visible);
240:                if (decorated.x < visible.x)
241:                    originOffset.x += visible.x - decorated.x;
242:                if (decorated.y < visible.y)
243:                    originOffset.y += visible.y - decorated.y;
244:                return clipRect;
245:            }
246:
247:            /** Return any clipping rectangle detected above the given component,
248:             * in the coordinate space of the given component.  The given rectangle
249:             * is desired to be visible.
250:             */
251:            private Rectangle getClippingRect(Container component,
252:                    Rectangle desired) {
253:                Rectangle visible = component instanceof  JComponent ? ((JComponent) component)
254:                        .getVisibleRect()
255:                        : new Rectangle(0, 0, component.getWidth(), component
256:                                .getHeight());
257:                Rectangle clip = new Rectangle(desired);
258:                if (desired.x >= visible.x
259:                        && desired.y >= visible.y
260:                        && desired.x + desired.width <= visible.x
261:                                + visible.width
262:                        && desired.y + desired.height <= visible.y
263:                                + visible.height) {
264:                    // desired rect is within the current clip rect
265:                } else if (component.getParent() != null) {
266:                    // Only apply the clip if it is actually smaller than the 
267:                    // component's visible area
268:                    if (component != painter.getParent()
269:                            && (visible.x > 0 || visible.y > 0
270:                                    || visible.width < component.getWidth() || visible.height < component
271:                                    .getHeight())) {
272:                        // Don't alter the original rectangle
273:                        desired = new Rectangle(desired);
274:                        desired.x = Math.max(desired.x, visible.x);
275:                        desired.y = Math.max(desired.y, visible.y);
276:                        desired.width = Math.min(desired.width, visible.x
277:                                + visible.width - desired.x);
278:                        desired.height = Math.min(desired.height, visible.y
279:                                + visible.height - desired.y);
280:
281:                        // Check for clipping further up the hierarchy
282:                        desired.x += component.getX();
283:                        desired.y += component.getY();
284:                        clip = getClippingRect(component.getParent(), desired);
285:                        clip.x -= component.getX();
286:                        clip.y -= component.getY();
287:                    }
288:                }
289:                return clip;
290:            }
291:
292:            /** Return the bounds, relative to the decorated component, of the
293:             * decoration.  The default covers the entire component.  Note that
294:             * this method will be called from the constructor, so be careful
295:             * when overriding and referencing derived class state.
296:             */
297:            protected Rectangle getDecorationBounds() {
298:                return bounds != DEFAULT_BOUNDS ? bounds : new Rectangle(0, 0,
299:                        component.getWidth(), component.getHeight());
300:            }
301:
302:            /** Change the bounds of the decoration, relative to the decorated 
303:             * component.  The special value {@link #DEFAULT_BOUNDS} means the bounds
304:             * will track the component bounds.
305:             */
306:            public void setDecorationBounds(Rectangle bounds) {
307:                if (bounds == DEFAULT_BOUNDS) {
308:                    this .bounds = bounds;
309:                } else {
310:                    this .bounds = new Rectangle(bounds);
311:                }
312:                synch();
313:            }
314:
315:            /** Change the bounds of the decoration, relative to the decorated 
316:             * component.
317:             */
318:            public void setDecorationBounds(int x, int y, int w, int h) {
319:                setDecorationBounds(new Rectangle(x, y, w, h));
320:            }
321:
322:            protected void setPainterBounds(int x, int y, int w, int h) {
323:                painter.setLocation(x, y);
324:                painter.setSize(w, h);
325:                repaint();
326:            }
327:
328:            /** Returns the decorated component. */
329:            protected JComponent getComponent() {
330:                return component;
331:            }
332:
333:            /** Returns the component used to paint the decoration and optionally
334:             * track events.
335:             */
336:            protected JComponent getPainter() {
337:                return painter;
338:            }
339:
340:            /** Set the cursor to appear anywhere over the decoration bounds. 
341:             * If null, the cursor of the decorated component will be used.
342:             */
343:            public void setCursor(Cursor cursor) {
344:                painter.setCursor(cursor);
345:            }
346:
347:            /** Force a refresh of the underlying component and its decoration. */
348:            public void repaint() {
349:                JLayeredPane p = (JLayeredPane) painter.getParent();
350:                if (p != null) {
351:                    p.repaint(painter.getBounds());
352:                }
353:            }
354:
355:            /** Stop decorating. */
356:            public void dispose() {
357:                if (component == null)
358:                    return;
359:
360:                // Disposal must occur on the EDT
361:                if (!SwingUtilities.isEventDispatchThread()) {
362:                    SwingUtilities.invokeLater(new Runnable() {
363:                        public void run() {
364:                            dispose();
365:                        }
366:                    });
367:                    return;
368:                }
369:                component.removeHierarchyListener(listener);
370:                component.removeComponentListener(listener);
371:                if (parent != null) {
372:                    parent.removeComponentListener(listener);
373:                    parent = null;
374:                }
375:                if (layerRoot != null) {
376:                    layerRoot.removePropertyChangeListener(listener);
377:                    layerRoot = null;
378:                }
379:                Container painterParent = painter.getParent();
380:                if (painterParent != null) {
381:                    Rectangle bounds = painter.getBounds();
382:                    painterParent.remove(painter);
383:                    painterParent.repaint(bounds.x, bounds.y, bounds.width,
384:                            bounds.height);
385:                }
386:                component.repaint();
387:                component = null;
388:            }
389:
390:            /** Define the decoration's appearance.  The point (0,0) represents
391:             * the upper left corner of the decorated component.
392:             * The default clip mask will be the extents of the decoration bounds, as 
393:             * indicated by {@link #getDecorationBounds()}, which defaults to the 
394:             * decorated component bounds.
395:             */
396:            public abstract void paint(Graphics g);
397:
398:            public String toString() {
399:                return super .toString() + " on " + getComponent();
400:            }
401:
402:            private static Field nComponents;
403:            static {
404:                try {
405:                    nComponents = Container.class
406:                            .getDeclaredField("ncomponents");
407:                    nComponents.setAccessible(true);
408:                } catch (Exception e) {
409:                    nComponents = null;
410:                }
411:            }
412:
413:            private static boolean useSimpleBackground() {
414:                return nComponents == null;
415:            }
416:
417:            /** Used to hook into the Swing painting and event architecture. */
418:            protected class Painter extends JComponent {
419:                private int base;
420:                private Cursor cursor;
421:                {
422:                    setFocusable(false);
423:                }
424:
425:                public JComponent getComponent() {
426:                    return AbstractComponentDecorator.this .getComponent();
427:                }
428:
429:                public void setDecoratedLayer(int base) {
430:                    this .base = base;
431:                }
432:
433:                public int getDecoratedLayer() {
434:                    return base;
435:                }
436:
437:                public boolean isBackgroundDecoration() {
438:                    return layerOffset < 0;
439:                }
440:
441:                /** Set the cursor to something else.  If null, the cursor of
442:                 * the decorated component will be used.
443:                 */
444:                public void setCursor(Cursor cursor) {
445:                    Cursor oldCursor = getCursor();
446:                    // Make sure the cursor actually changed, otherwise
447:                    // we get cursor flicker (notably on w32 title bars)
448:                    if (oldCursor == null && cursor != null
449:                            || oldCursor != null && !oldCursor.equals(cursor)) {
450:                        this .cursor = cursor;
451:                        super .setCursor(cursor);
452:                    }
453:                }
454:
455:                /** Returns the cursor of the decorated component, or the last
456:                 * cursor set by {@link #setCursor}. 
457:                 */
458:                public Cursor getCursor() {
459:                    return cursor != null ? cursor : component.getCursor();
460:                }
461:
462:                /** Delegate to the containing decorator to perform the paint.
463:                 */
464:                public void paintComponent(Graphics g) {
465:                    if (!component.isShowing())
466:                        return;
467:                    Graphics g2 = g.create();
468:                    g2.translate(-originOffset.x, -originOffset.y);
469:                    AbstractComponentDecorator.this .paint(g2);
470:                    g2.dispose();
471:                }
472:
473:                /** Provide a decorator-specific tooltip, shown when within the
474:                 * decorator's bounds. 
475:                 */
476:                public String getToolTipText(MouseEvent e) {
477:                    return AbstractComponentDecorator.this .getToolTipText(e);
478:                }
479:
480:                public String toString() {
481:                    return "Painter for " + AbstractComponentDecorator.this ;
482:                }
483:            }
484:
485:            /** Provides a shared background painting mechanism for multiple 
486:             * decorations.  This ensures that the background is only painted once
487:             * if more than one background decorator is applied.
488:             */
489:            private static class BackgroundPainter extends
490:                    AbstractComponentDecorator {
491:                private static String key(int layer) {
492:                    return "backgroundPainter for layer " + layer;
493:                }
494:
495:                private String key;
496:                private int layer;
497:
498:                public BackgroundPainter(JLayeredPane p, int layer) {
499:                    super (p, 0, TOP);
500:                    this .layer = layer;
501:                    key = key(layer);
502:                    p.putClientProperty(key, this );
503:                }
504:
505:                private int hideChildren(Container c) {
506:                    if (c == null)
507:                        return 0;
508:                    int value = c.getComponentCount();
509:                    try {
510:                        nComponents.set(c, new Integer(0));
511:                    } catch (Exception e) {
512:                        return c.getComponentCount();
513:                    }
514:                    return value;
515:                }
516:
517:                private void restoreChildren(Container c, int count) {
518:                    if (c != null) {
519:                        try {
520:                            nComponents.set(c, new Integer(count));
521:                        } catch (Exception e) {
522:                        }
523:                    }
524:                }
525:
526:                private void paintBackground(Graphics g, Component parent,
527:                        JComponent jc) {
528:                    int x = jc.getX();
529:                    int y = jc.getY();
530:                    int w = jc.getWidth();
531:                    int h = jc.getHeight();
532:                    paintBackground(g.create(x, y, w, h), jc);
533:                }
534:
535:                private void paintBackground(Graphics g, JComponent jc) {
536:                    if (jc.isOpaque()) {
537:                        if (useSimpleBackground()) {
538:                            g.setColor(jc.getBackground());
539:                            g.fillRect(0, 0, jc.getWidth(), jc.getHeight());
540:                        } else {
541:                            int count = hideChildren(jc);
542:                            boolean db = jc.isDoubleBuffered();
543:                            if (db)
544:                                jc.setDoubleBuffered(false);
545:                            jc.paint(g);
546:                            if (db)
547:                                jc.setDoubleBuffered(true);
548:                            restoreChildren(jc, count);
549:                        }
550:                    }
551:                    Component[] kids = jc.getComponents();
552:                    for (int i = 0; i < kids.length; i++) {
553:                        if (kids[i] instanceof  JComponent) {
554:                            paintBackground(g, jc, (JComponent) kids[i]);
555:                        }
556:                    }
557:                }
558:
559:                private List findOpaque(Component root) {
560:                    List list = new ArrayList();
561:                    if (root.isOpaque() && root instanceof  JComponent) {
562:                        list.add(root);
563:                        ((JComponent) root).setOpaque(false);
564:                    }
565:                    if (root instanceof  Container) {
566:                        Component[] kids = ((Container) root).getComponents();
567:                        for (int i = 0; i < kids.length; i++) {
568:                            list.addAll(findOpaque(kids[i]));
569:                        }
570:                    }
571:                    return list;
572:                }
573:
574:                private List findDoubleBuffered(Component root) {
575:                    List list = new ArrayList();
576:                    if (root.isDoubleBuffered() && root instanceof  JComponent) {
577:                        list.add(root);
578:                        ((JComponent) root).setDoubleBuffered(false);
579:                    }
580:                    if (root instanceof  Container) {
581:                        Component[] kids = ((Container) root).getComponents();
582:                        for (int i = 0; i < kids.length; i++) {
583:                            list.addAll(findDoubleBuffered(kids[i]));
584:                        }
585:                    }
586:                    return list;
587:                }
588:
589:                private void paintForeground(Graphics g, JComponent jc) {
590:                    List opaque = findOpaque(jc);
591:                    List db = findDoubleBuffered(jc);
592:                    jc.paint(g);
593:                    for (Iterator i = opaque.iterator(); i.hasNext();) {
594:                        ((JComponent) i.next()).setOpaque(true);
595:                    }
596:                    for (Iterator i = db.iterator(); i.hasNext();) {
597:                        ((JComponent) i.next()).setDoubleBuffered(true);
598:                    }
599:                }
600:
601:                /** Walk the list of "background" decorators and paint them. */
602:                public void paint(Graphics g) {
603:
604:                    JLayeredPane lp = (JLayeredPane) getComponent();
605:                    Component[] kids = lp.getComponents();
606:                    // Construct an area of the intersection of all decorators
607:                    Area area = new Area();
608:                    List painters = new ArrayList();
609:                    List components = new ArrayList();
610:                    for (int i = kids.length - 1; i >= 0; i--) {
611:                        if (kids[i] instanceof  Painter) {
612:                            Painter p = (Painter) kids[i];
613:                            if (p.isBackgroundDecoration()
614:                                    && p.getDecoratedLayer() == layer
615:                                    && p.isShowing()) {
616:                                painters.add(p);
617:                                area.add(new Area(p.getBounds()));
618:                            }
619:                        } else if (lp.getLayer(kids[i]) == layer
620:                                && kids[i] instanceof  JComponent) {
621:                            components.add(kids[i]);
622:                        }
623:                    }
624:                    if (painters.size() == 0) {
625:                        dispose();
626:                        return;
627:                    }
628:                    g.setClip(area);
629:
630:                    // Paint background for that area
631:                    for (Iterator i = components.iterator(); i.hasNext();) {
632:                        JComponent c = (JComponent) i.next();
633:                        paintBackground(g, lp, c);
634:                    }
635:
636:                    // Paint the bg decorators
637:                    for (Iterator i = painters.iterator(); i.hasNext();) {
638:                        Painter p = (Painter) i.next();
639:                        p.paint(g.create(p.getX(), p.getY(), p.getWidth(), p
640:                                .getHeight()));
641:                    }
642:                    // Paint foreground for the area
643:                    for (Iterator i = components.iterator(); i.hasNext();) {
644:                        JComponent c = (JComponent) i.next();
645:                        paintForeground(g.create(c.getX(), c.getY(), c
646:                                .getWidth(), c.getHeight()), c);
647:                    }
648:                }
649:
650:                public void dispose() {
651:                    getComponent().putClientProperty(key, null);
652:                    super .dispose();
653:                }
654:
655:                public String toString() {
656:                    return key + " on " + getComponent();
657:                }
658:            }
659:
660:            /** Tracks changes to component configuration. */
661:            private final class Listener extends ComponentAdapter implements 
662:                    HierarchyListener, PropertyChangeListener {
663:                // NOTE: OSX (1.6) doesn't generate these the same as w32
664:                public void hierarchyChanged(HierarchyEvent e) {
665:                    if ((e.getChangeFlags() & HierarchyEvent.PARENT_CHANGED) != 0) {
666:                        attach();
667:                    }
668:                }
669:
670:                public void propertyChange(PropertyChangeEvent e) {
671:                    if (JLayeredPane.LAYER_PROPERTY.equals(e.getPropertyName())) {
672:                        attach();
673:                    }
674:                }
675:
676:                public void componentMoved(ComponentEvent e) {
677:                    // FIXME figure out why attach works and synch doesn't
678:                    // when painting a selection marquee over a decorated background
679:                    attach();
680:                }
681:
682:                public void componentResized(ComponentEvent e) {
683:                    // FIXME figure out why attach works and synch doesn't
684:                    // when painting a selection marquee over a decorated background
685:                    attach();
686:                }
687:
688:                public void componentHidden(ComponentEvent e) {
689:                    setVisible(false);
690:                }
691:
692:                public void componentShown(ComponentEvent e) {
693:                    setVisible(true);
694:                }
695:            }
696:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.