Source Code Cross Referenced for JCollapsiblePane.java in  » Swing-Library » l2fprod-common » com » l2fprod » common » swing » 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 » Swing Library » l2fprod common » com.l2fprod.common.swing 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /**
002:         * L2FProd.com Common Components 7.3 License.
003:         *
004:         * Copyright 2005-2007 L2FProd.com
005:         *
006:         * Licensed under the Apache License, Version 2.0 (the "License");
007:         * you may not use this file except in compliance with the License.
008:         * You may obtain a copy of the License at
009:         *
010:         *     http://www.apache.org/licenses/LICENSE-2.0
011:         *
012:         * Unless required by applicable law or agreed to in writing, software
013:         * distributed under the License is distributed on an "AS IS" BASIS,
014:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015:         * See the License for the specific language governing permissions and
016:         * limitations under the License.
017:         */package com.l2fprod.common.swing;
018:
019:        import java.awt.AlphaComposite;
020:        import java.awt.BorderLayout;
021:        import java.awt.Component;
022:        import java.awt.Composite;
023:        import java.awt.Container;
024:        import java.awt.Dimension;
025:        import java.awt.Graphics;
026:        import java.awt.Graphics2D;
027:        import java.awt.LayoutManager;
028:        import java.awt.Rectangle;
029:        import java.awt.event.ActionEvent;
030:        import java.awt.event.ActionListener;
031:        import java.awt.image.BufferedImage;
032:        import java.beans.PropertyChangeEvent;
033:        import java.beans.PropertyChangeListener;
034:
035:        import javax.swing.AbstractAction;
036:        import javax.swing.JComponent;
037:        import javax.swing.JPanel;
038:        import javax.swing.SwingUtilities;
039:        import javax.swing.Timer;
040:
041:        /**
042:         * <code>JCollapsiblePane</code> provides a component which can collapse or
043:         * expand its content area with animation and fade in/fade out effects.
044:         * It also acts as a standard container for other Swing components.
045:         * 
046:         * <p>
047:         * In this example, the <code>JCollapsiblePane</code> is used to build
048:         * a Search pane which can be shown and hidden on demand.
049:         * 
050:         * <pre>
051:         * <code>
052:         * JCollapsiblePane cp = new JCollapsiblePane();
053:         *
054:         * // JCollapsiblePane can be used like any other container
055:         * cp.setLayout(new BorderLayout());
056:         * 
057:         * // the Controls panel with a textfield to filter the tree
058:         * JPanel controls = new JPanel(new FlowLayout(FlowLayout.LEFT, 4, 0));
059:         * controls.add(new JLabel("Search:"));
060:         * controls.add(new JTextField(10));    
061:         * controls.add(new JButton("Refresh"));
062:         * controls.setBorder(new TitledBorder("Filters"));
063:         * cp.add("Center", controls);
064:         *   
065:         * JFrame frame = new JFrame();
066:         * frame.setLayout(new BorderLayout());
067:         *  
068:         * // Put the "Controls" first
069:         * frame.add("North", cp);
070:         *    
071:         * // Then the tree - we assume the Controls would somehow filter the tree
072:         * JScrollPane scroll = new JScrollPane(new JTree());
073:         * frame.add("Center", scroll);
074:         *
075:         * // Show/hide the "Controls"
076:         * JButton toggle = new JButton(cp.getActionMap().get(JCollapsiblePane.TOGGLE_ACTION));
077:         * toggle.setText("Show/Hide Search Panel");
078:         * frame.add("South", toggle);
079:         *
080:         * frame.pack();
081:         * frame.setVisible(true);
082:         * </code>
083:         * </pre>
084:         * 
085:         * <p>
086:         * Note: <code>JCollapsiblePane</code> requires its parent container to have a
087:         * {@link java.awt.LayoutManager} using {@link #getPreferredSize()} when
088:         * calculating its layout (example {@link com.l2fprod.common.swing.PercentLayout},
089:         * {@link java.awt.BorderLayout}). 
090:         * 
091:         * @javabean.attribute
092:         *          name="isContainer"
093:         *          value="Boolean.TRUE"
094:         *          rtexpr="true"
095:         * 
096:         * @javabean.attribute
097:         *          name="containerDelegate"
098:         *          value="getContentPane"
099:         *          
100:         * @javabean.class
101:         *          name="JCollapsiblePane"
102:         *          shortDescription="A pane which hides its content with an animation."
103:         *          stopClass="java.awt.Component"
104:         *          
105:         * @author rbair (from the JDNC project)
106:         * @author <a href="mailto:fred@L2FProd.com">Frederic Lavigne</a>
107:         */
108:        public class JCollapsiblePane extends JPanel {
109:
110:            /**
111:             * Used when generating PropertyChangeEvents for the "animationState" property
112:             */
113:            public final static String ANIMATION_STATE_KEY = "animationState";
114:
115:            /**
116:             * JCollapsible has a built-in toggle action which can be bound to buttons.
117:             * Accesses the action through
118:             * <code>collapsiblePane.getActionMap().get(JCollapsiblePane.TOGGLE_ACTION)</code>.
119:             */
120:            public final static String TOGGLE_ACTION = "toggle";
121:
122:            /**
123:             * The icon used by the "toggle" action when the JCollapsiblePane is
124:             * expanded, i.e the icon which indicates the pane can be collapsed.
125:             */
126:            public final static String COLLAPSE_ICON = "collapseIcon";
127:
128:            /**
129:             * The icon used by the "toggle" action when the JCollapsiblePane is
130:             * collapsed, i.e the icon which indicates the pane can be expanded.
131:             */
132:            public final static String EXPAND_ICON = "expandIcon";
133:
134:            /**
135:             * Indicates whether the component is collapsed or expanded
136:             */
137:            private boolean collapsed = false;
138:
139:            /**
140:             * Timer used for doing the transparency animation (fade-in)
141:             */
142:            private Timer animateTimer;
143:            private AnimationListener animator;
144:            private int currentHeight = -1;
145:            private WrapperContainer wrapper;
146:            private boolean useAnimation = true;
147:            private AnimationParams animationParams;
148:
149:            /**
150:             * Constructs a new JCollapsiblePane with a {@link JPanel} as content pane and
151:             * a vertical {@link PercentLayout} with a gap of 2 pixels as layout manager.
152:             */
153:            public JCollapsiblePane() {
154:                super .setLayout(new BorderLayout(0, 0));
155:
156:                JPanel panel = new JPanel();
157:                panel.setLayout(new PercentLayout(PercentLayout.VERTICAL, 2));
158:                setContentPane(panel);
159:
160:                animator = new AnimationListener();
161:                setAnimationParams(new AnimationParams(30, 8, 0.01f, 1.0f));
162:
163:                // add an action to automatically toggle the state of the pane
164:                getActionMap().put(TOGGLE_ACTION, new ToggleAction());
165:            }
166:
167:            /**
168:             * Toggles the JCollapsiblePane state and updates its icon based on the
169:             * JCollapsiblePane "collapsed" status.
170:             */
171:            private class ToggleAction extends AbstractAction implements 
172:                    PropertyChangeListener {
173:                public ToggleAction() {
174:                    super (TOGGLE_ACTION);
175:                    updateIcon();
176:                    // the action must track the collapsed status of the pane to update its
177:                    // icon
178:                    JCollapsiblePane.this .addPropertyChangeListener(
179:                            "collapsed", this );
180:                }
181:
182:                public void putValue(String key, Object newValue) {
183:                    super .putValue(key, newValue);
184:                    if (EXPAND_ICON.equals(key) || COLLAPSE_ICON.equals(key)) {
185:                        updateIcon();
186:                    }
187:                }
188:
189:                public void actionPerformed(ActionEvent e) {
190:                    setCollapsed(!isCollapsed());
191:                }
192:
193:                public void propertyChange(PropertyChangeEvent evt) {
194:                    updateIcon();
195:                }
196:
197:                void updateIcon() {
198:                    if (isCollapsed()) {
199:                        putValue(SMALL_ICON, getValue(EXPAND_ICON));
200:                    } else {
201:                        putValue(SMALL_ICON, getValue(COLLAPSE_ICON));
202:                    }
203:                }
204:            }
205:
206:            /**
207:             * Sets the content pane of this JCollapsiblePane. Components must be added
208:             * to this content pane, not to the JCollapsiblePane.
209:             * 
210:             * @param contentPanel
211:             * @throws IllegalArgumentException
212:             *           if contentPanel is null
213:             */
214:            public void setContentPane(Container contentPanel) {
215:                if (contentPanel == null) {
216:                    throw new IllegalArgumentException(
217:                            "Content pane can't be null");
218:                }
219:
220:                if (wrapper != null) {
221:                    super .remove(wrapper);
222:                }
223:                wrapper = new WrapperContainer(contentPanel);
224:                super .addImpl(wrapper, BorderLayout.CENTER, -1);
225:            }
226:
227:            /**
228:             * @return the content pane
229:             */
230:            public Container getContentPane() {
231:                return wrapper.c;
232:            }
233:
234:            /**
235:             * Overriden to redirect call to the content pane.
236:             */
237:            public void setLayout(LayoutManager mgr) {
238:                // wrapper can be null when setLayout is called by "super()" constructor
239:                if (wrapper != null) {
240:                    getContentPane().setLayout(mgr);
241:                }
242:            }
243:
244:            /**
245:             * Overriden to redirect call to the content pane.
246:             */
247:            protected void addImpl(Component comp, Object constraints, int index) {
248:                getContentPane().add(comp, constraints, index);
249:            }
250:
251:            /**
252:             * Overriden to redirect call to the content pane
253:             */
254:            public void remove(Component comp) {
255:                getContentPane().remove(comp);
256:            }
257:
258:            /**
259:             * Overriden to redirect call to the content pane.
260:             */
261:            public void remove(int index) {
262:                getContentPane().remove(index);
263:            }
264:
265:            /**
266:             * Overriden to redirect call to the content pane.
267:             */
268:            public void removeAll() {
269:                getContentPane().removeAll();
270:            }
271:
272:            /**
273:             * If true, enables the animation when pane is collapsed/expanded. If false,
274:             * animation is turned off.
275:             * 
276:             * <p>
277:             * When animated, the <code>JCollapsiblePane</code> will progressively
278:             * reduce (when collapsing) or enlarge (when expanding) the height of its
279:             * content area until it becomes 0 or until it reaches the preferred height of
280:             * the components it contains. The transparency of the content area will also
281:             * change during the animation.
282:             * 
283:             * <p>
284:             * If not animated, the <code>JCollapsiblePane</code> will simply hide
285:             * (collapsing) or show (expanding) its content area.
286:             * 
287:             * @param animated
288:             * @javabean.property bound="true" preferred="true"
289:             */
290:            public void setAnimated(boolean animated) {
291:                if (animated != useAnimation) {
292:                    useAnimation = animated;
293:                    firePropertyChange("animated", !useAnimation, useAnimation);
294:                }
295:            }
296:
297:            /**
298:             * @return true if the pane is animated, false otherwise
299:             * @see #setAnimated(boolean)
300:             */
301:            public boolean isAnimated() {
302:                return useAnimation;
303:            }
304:
305:            /**
306:             * @return true if the pane is collapsed, false if expanded
307:             */
308:            public boolean isCollapsed() {
309:                return collapsed;
310:            }
311:
312:            /**
313:             * Expands or collapses this <code>JCollapsiblePane</code>.
314:             * 
315:             * <p>
316:             * If the component is collapsed and <code>val</code> is false, then this
317:             * call expands the JCollapsiblePane, such that the entire JCollapsiblePane
318:             * will be visible. If {@link #isAnimated()} returns true, the expansion will
319:             * be accompanied by an animation.
320:             * 
321:             * <p>
322:             * However, if the component is expanded and <code>val</code> is true, then
323:             * this call collapses the JCollapsiblePane, such that the entire
324:             * JCollapsiblePane will be invisible. If {@link #isAnimated()} returns true,
325:             * the collapse will be accompanied by an animation.
326:             * 
327:             * @see #isAnimated()
328:             * @see #setAnimated(boolean)
329:             * @javabean.property
330:             *          bound="true"
331:             *          preferred="true"
332:             */
333:            public void setCollapsed(boolean val) {
334:                if (collapsed != val) {
335:                    collapsed = val;
336:                    if (isAnimated()) {
337:                        if (collapsed) {
338:                            setAnimationParams(new AnimationParams(30, Math
339:                                    .max(8, wrapper.getHeight() / 10), 1.0f,
340:                                    0.01f));
341:                            animator.reinit(wrapper.getHeight(), 0);
342:                            animateTimer.start();
343:                        } else {
344:                            setAnimationParams(new AnimationParams(30,
345:                                    Math.max(8, getContentPane()
346:                                            .getPreferredSize().height / 10),
347:                                    0.01f, 1.0f));
348:                            animator.reinit(wrapper.getHeight(),
349:                                    getContentPane().getPreferredSize().height);
350:                            animateTimer.start();
351:                        }
352:                    } else {
353:                        wrapper.c.setVisible(!collapsed);
354:                        invalidate();
355:                        doLayout();
356:                    }
357:                    repaint();
358:                    firePropertyChange("collapsed", !collapsed, collapsed);
359:                }
360:            }
361:
362:            public Dimension getMinimumSize() {
363:                return getPreferredSize();
364:            }
365:
366:            /**
367:             * The critical part of the animation of this <code>JCollapsiblePane</code>
368:             * relies on the calculation of its preferred size. During the animation, its
369:             * preferred size (specially its height) will change, when expanding, from 0
370:             * to the preferred size of the content pane, and the reverse when collapsing.
371:             * 
372:             * @return this component preferred size
373:             */
374:            public Dimension getPreferredSize() {
375:                /*
376:                 * The preferred size is calculated based on the current position of the
377:                 * component in its animation sequence. If the Component is expanded, then
378:                 * the preferred size will be the preferred size of the top component plus
379:                 * the preferred size of the embedded content container. <p>However, if the
380:                 * scroll up is in any state of animation, the height component of the
381:                 * preferred size will be the current height of the component (as contained
382:                 * in the currentHeight variable)
383:                 */
384:                Dimension dim;
385:                if (!isAnimated()) {
386:                    if (getContentPane().isVisible()) {
387:                        dim = getContentPane().getPreferredSize();
388:                    } else {
389:                        dim = super .getPreferredSize();
390:                    }
391:                } else {
392:                    dim = new Dimension(getContentPane().getPreferredSize());
393:                    if (!getContentPane().isVisible() && currentHeight != -1) {
394:                        dim.height = currentHeight;
395:                    }
396:                }
397:                return dim;
398:            }
399:
400:            /**
401:             * Sets the parameters controlling the animation
402:             * 
403:             * @param params
404:             * @throws IllegalArgumentException
405:             *           if params is null
406:             */
407:            private void setAnimationParams(AnimationParams params) {
408:                if (params == null) {
409:                    throw new IllegalArgumentException("params can't be null");
410:                }
411:                if (animateTimer != null) {
412:                    animateTimer.stop();
413:                }
414:                animationParams = params;
415:                animateTimer = new Timer(animationParams.waitTime, animator);
416:                animateTimer.setInitialDelay(0);
417:            }
418:
419:            /**
420:             * Tagging interface for containers in a JCollapsiblePane hierarchy who needs
421:             * to be revalidated (invalidate/validate/repaint) when the pane is expanding
422:             * or collapsing. Usually validating only the parent of the JCollapsiblePane
423:             * is enough but there might be cases where the parent parent must be
424:             * validated.
425:             */
426:            public static interface JCollapsiblePaneContainer {
427:                Container getValidatingContainer();
428:            }
429:
430:            /**
431:             * Parameters controlling the animations
432:             */
433:            private static class AnimationParams {
434:                final int waitTime;
435:                final int deltaY;
436:                final float alphaStart;
437:                final float alphaEnd;
438:
439:                /**
440:                 * @param waitTime
441:                 *          the amount of time in milliseconds to wait between calls to the
442:                 *          animation thread
443:                 * @param deltaY
444:                 *          the delta in the Y direction to inc/dec the size of the scroll
445:                 *          up by
446:                 * @param alphaStart
447:                 *          the starting alpha transparency level
448:                 * @param alphaEnd
449:                 *          the ending alpha transparency level
450:                 */
451:                public AnimationParams(int waitTime, int deltaY,
452:                        float alphaStart, float alphaEnd) {
453:                    this .waitTime = waitTime;
454:                    this .deltaY = deltaY;
455:                    this .alphaStart = alphaStart;
456:                    this .alphaEnd = alphaEnd;
457:                }
458:            }
459:
460:            /**
461:             * This class actual provides the animation support for scrolling up/down this
462:             * component. This listener is called whenever the animateTimer fires off. It
463:             * fires off in response to scroll up/down requests. This listener is
464:             * responsible for modifying the size of the content container and causing it
465:             * to be repainted.
466:             * 
467:             * @author Richard Bair
468:             */
469:            private final class AnimationListener implements  ActionListener {
470:                /**
471:                 * Mutex used to ensure that the startHeight/finalHeight are not changed
472:                 * during a repaint operation.
473:                 */
474:                private final Object ANIMATION_MUTEX = "Animation Synchronization Mutex";
475:                /**
476:                 * This is the starting height when animating. If > finalHeight, then the
477:                 * animation is going to be to scroll up the component. If it is < then
478:                 * finalHeight, then the animation will scroll down the component.
479:                 */
480:                private int startHeight = 0;
481:                /**
482:                 * This is the final height that the content container is going to be when
483:                 * scrolling is finished.
484:                 */
485:                private int finalHeight = 0;
486:                /**
487:                 * The current alpha setting used during "animation" (fade-in/fade-out)
488:                 */
489:                private float animateAlpha = 1.0f;
490:
491:                public void actionPerformed(ActionEvent e) {
492:                    /*
493:                     * Pre-1) If startHeight == finalHeight, then we're done so stop the timer
494:                     * 1) Calculate whether we're contracting or expanding. 2) Calculate the
495:                     * delta (which is either positive or negative, depending on the results
496:                     * of (1)) 3) Calculate the alpha value 4) Resize the ContentContainer 5)
497:                     * Revalidate/Repaint the content container
498:                     */
499:                    synchronized (ANIMATION_MUTEX) {
500:                        if (startHeight == finalHeight) {
501:                            animateTimer.stop();
502:                            animateAlpha = animationParams.alphaEnd;
503:                            // keep the content pane hidden when it is collapsed, other it may
504:                            // still receive focus.
505:                            if (finalHeight > 0) {
506:                                wrapper.showContent();
507:                                validate();
508:                                JCollapsiblePane.this .firePropertyChange(
509:                                        ANIMATION_STATE_KEY, null, "expanded");
510:                                return;
511:                            }
512:                        }
513:
514:                        final boolean contracting = startHeight > finalHeight;
515:                        final int delta_y = contracting ? -1
516:                                * animationParams.deltaY
517:                                : animationParams.deltaY;
518:                        int newHeight = wrapper.getHeight() + delta_y;
519:                        if (contracting) {
520:                            if (newHeight < finalHeight) {
521:                                newHeight = finalHeight;
522:                            }
523:                        } else {
524:                            if (newHeight > finalHeight) {
525:                                newHeight = finalHeight;
526:                            }
527:                        }
528:                        animateAlpha = (float) newHeight
529:                                / (float) wrapper.c.getPreferredSize().height;
530:
531:                        Rectangle bounds = wrapper.getBounds();
532:                        int oldHeight = bounds.height;
533:                        bounds.height = newHeight;
534:                        wrapper.setBounds(bounds);
535:                        bounds = getBounds();
536:                        bounds.height = (bounds.height - oldHeight) + newHeight;
537:                        currentHeight = bounds.height;
538:                        setBounds(bounds);
539:                        startHeight = newHeight;
540:
541:                        // it happens the animateAlpha goes over the alphaStart/alphaEnd range
542:                        // this code ensures it stays in bounds. This behavior is seen when
543:                        // component such as JTextComponents are used in the container.
544:                        if (contracting) {
545:                            // alphaStart > animateAlpha > alphaEnd
546:                            if (animateAlpha < animationParams.alphaEnd) {
547:                                animateAlpha = animationParams.alphaEnd;
548:                            }
549:                            if (animateAlpha > animationParams.alphaStart) {
550:                                animateAlpha = animationParams.alphaStart;
551:                            }
552:                        } else {
553:                            // alphaStart < animateAlpha < alphaEnd
554:                            if (animateAlpha > animationParams.alphaEnd) {
555:                                animateAlpha = animationParams.alphaEnd;
556:                            }
557:                            if (animateAlpha < animationParams.alphaStart) {
558:                                animateAlpha = animationParams.alphaStart;
559:                            }
560:                        }
561:                        wrapper.alpha = animateAlpha;
562:
563:                        validate();
564:                    }
565:                }
566:
567:                void validate() {
568:                    Container parent = SwingUtilities.getAncestorOfClass(
569:                            JCollapsiblePaneContainer.class,
570:                            JCollapsiblePane.this );
571:                    if (parent != null) {
572:                        parent = ((JCollapsiblePaneContainer) parent)
573:                                .getValidatingContainer();
574:                    } else {
575:                        parent = getParent();
576:                    }
577:
578:                    if (parent != null) {
579:                        if (parent instanceof  JComponent) {
580:                            ((JComponent) parent).revalidate();
581:                        } else {
582:                            parent.invalidate();
583:                        }
584:                        parent.doLayout();
585:                        parent.repaint();
586:                    }
587:                }
588:
589:                /**
590:                 * Reinitializes the timer for scrolling up/down the component. This method
591:                 * is properly synchronized, so you may make this call regardless of whether
592:                 * the timer is currently executing or not.
593:                 * 
594:                 * @param startHeight
595:                 * @param stopHeight
596:                 */
597:                public void reinit(int startHeight, int stopHeight) {
598:                    synchronized (ANIMATION_MUTEX) {
599:                        JCollapsiblePane.this .firePropertyChange(
600:                                ANIMATION_STATE_KEY, null, "reinit");
601:                        this .startHeight = startHeight;
602:                        this .finalHeight = stopHeight;
603:                        animateAlpha = animationParams.alphaStart;
604:                        currentHeight = -1;
605:                        wrapper.showImage();
606:                    }
607:                }
608:            }
609:
610:            private final class WrapperContainer extends JPanel {
611:                private BufferedImage img;
612:                private Container c;
613:                float alpha = 1.0f;
614:
615:                public WrapperContainer(Container c) {
616:                    super (new BorderLayout());
617:                    this .c = c;
618:                    add(c, BorderLayout.CENTER);
619:
620:                    // we must ensure the container is opaque. It is not opaque it introduces
621:                    // painting glitches specially on Linux with JDK 1.5 and GTK look and feel.
622:                    // GTK look and feel calls setOpaque(false)
623:                    if (c instanceof  JComponent && !((JComponent) c).isOpaque()) {
624:                        ((JComponent) c).setOpaque(true);
625:                    }
626:                }
627:
628:                public void showImage() {
629:                    // render c into the img
630:                    makeImage();
631:                    c.setVisible(false);
632:                }
633:
634:                public void showContent() {
635:                    currentHeight = -1;
636:                    c.setVisible(true);
637:                }
638:
639:                void makeImage() {
640:                    // if we have no image or if the image has changed      
641:                    if (getGraphicsConfiguration() != null && getWidth() > 0) {
642:                        Dimension dim = c.getPreferredSize();
643:                        // width and height must be > 0 to be able to create an image
644:                        if (dim.height > 0) {
645:                            img = getGraphicsConfiguration()
646:                                    .createCompatibleImage(getWidth(),
647:                                            dim.height);
648:                            c.setSize(getWidth(), dim.height);
649:                            c.paint(img.getGraphics());
650:                        } else {
651:                            img = null;
652:                        }
653:                    }
654:                }
655:
656:                public void paintComponent(Graphics g) {
657:                    if (!useAnimation || c.isVisible()) {
658:                        super .paintComponent(g);
659:                    } else {
660:                        // within netbeans, it happens we arrive here and the image has not been
661:                        // created yet. We ensure it is.
662:                        if (img == null) {
663:                            makeImage();
664:                        }
665:                        // and we paint it only if it has been created and only if we have a
666:                        // valid graphics
667:                        if (g != null && img != null) {
668:                            // draw the image with y being height - imageHeight
669:                            g.drawImage(img, 0, getHeight() - img.getHeight(),
670:                                    null);
671:                        }
672:                    }
673:                }
674:
675:                public void paint(Graphics g) {
676:                    Graphics2D g2d = (Graphics2D) g;
677:                    Composite oldComp = g2d.getComposite();
678:                    Composite alphaComp = AlphaComposite.getInstance(
679:                            AlphaComposite.SRC_OVER, alpha);
680:                    g2d.setComposite(alphaComp);
681:                    super.paint(g2d);
682:                    g2d.setComposite(oldComp);
683:                }
684:
685:            }
686:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.