Source Code Cross Referenced for DefaultTabbedContainerUI.java in  » IDE-Netbeans » library » org » netbeans » swing » tabcontrol » plaf » 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 » IDE Netbeans » library » org.netbeans.swing.tabcontrol.plaf 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0003:         *
0004:         * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
0005:         *
0006:         * The contents of this file are subject to the terms of either the GNU
0007:         * General Public License Version 2 only ("GPL") or the Common
0008:         * Development and Distribution License("CDDL") (collectively, the
0009:         * "License"). You may not use this file except in compliance with the
0010:         * License. You can obtain a copy of the License at
0011:         * http://www.netbeans.org/cddl-gplv2.html
0012:         * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
0013:         * specific language governing permissions and limitations under the
0014:         * License.  When distributing the software, include this License Header
0015:         * Notice in each file and include the License file at
0016:         * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
0017:         * particular file as subject to the "Classpath" exception as provided
0018:         * by Sun in the GPL Version 2 section of the License file that
0019:         * accompanied this code. If applicable, add the following below the
0020:         * License Header, with the fields enclosed by brackets [] replaced by
0021:         * your own identifying information:
0022:         * "Portions Copyrighted [year] [name of copyright owner]"
0023:         *
0024:         * Contributor(s):
0025:         *
0026:         * The Original Software is NetBeans. The Initial Developer of the Original
0027:         * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
0028:         * Microsystems, Inc. All Rights Reserved.
0029:         *
0030:         * If you wish your version of this file to be governed by only the CDDL
0031:         * or only the GPL Version 2, indicate your decision by adding
0032:         * "[Contributor] elects to include this software in this distribution
0033:         * under the [CDDL or GPL Version 2] license." If you do not indicate a
0034:         * single choice of license, a recipient has the option to distribute
0035:         * your version of this file under either the CDDL, the GPL Version 2 or
0036:         * to extend the choice of license to its licensees as provided above.
0037:         * However, if you add GPL Version 2 code and therefore, elected the GPL
0038:         * Version 2 license, then the option applies only if the new code is
0039:         * made subject to such option by the copyright holder.
0040:         */
0041:
0042:        package org.netbeans.swing.tabcontrol.plaf;
0043:
0044:        import java.awt.AlphaComposite;
0045:        import java.awt.BorderLayout;
0046:        import java.awt.Component;
0047:        import java.awt.Composite;
0048:        import java.awt.Container;
0049:        import java.awt.Dimension;
0050:        import java.awt.Graphics;
0051:        import java.awt.Graphics2D;
0052:        import java.awt.GraphicsEnvironment;
0053:        import java.awt.Image;
0054:        import java.awt.Insets;
0055:        import java.awt.LayoutManager;
0056:        import java.awt.Point;
0057:        import java.awt.Polygon;
0058:        import java.awt.Rectangle;
0059:        import java.awt.event.ActionEvent;
0060:        import java.awt.event.ActionListener;
0061:        import java.awt.event.ComponentAdapter;
0062:        import java.awt.event.ComponentEvent;
0063:        import java.awt.event.ComponentListener;
0064:        import java.awt.event.HierarchyEvent;
0065:        import java.awt.event.HierarchyListener;
0066:        import java.awt.event.MouseEvent;
0067:        import java.awt.event.MouseListener;
0068:        import java.awt.geom.AffineTransform;
0069:        import java.awt.image.BufferedImage;
0070:        import java.beans.PropertyChangeEvent;
0071:        import java.beans.PropertyChangeListener;
0072:        import java.util.HashSet;
0073:        import java.util.Iterator;
0074:        import java.util.List;
0075:        import java.util.Set;
0076:        import javax.swing.JComponent;
0077:        import javax.swing.JPanel;
0078:        import javax.swing.SingleSelectionModel;
0079:        import javax.swing.SwingUtilities;
0080:        import javax.swing.Timer;
0081:        import javax.swing.UIManager;
0082:        import javax.swing.border.Border;
0083:        import javax.swing.event.ChangeEvent;
0084:        import javax.swing.event.ChangeListener;
0085:        import javax.swing.event.ListDataEvent;
0086:        import javax.swing.plaf.ComponentUI;
0087:        import org.netbeans.swing.tabcontrol.TabData;
0088:        import org.netbeans.swing.tabcontrol.TabDisplayer;
0089:        import org.netbeans.swing.tabcontrol.TabbedContainer;
0090:        import org.netbeans.swing.tabcontrol.TabbedContainerUI;
0091:        import org.netbeans.swing.tabcontrol.WinsysInfoForTabbed;
0092:        import org.netbeans.swing.tabcontrol.event.ArrayDiff;
0093:        import org.netbeans.swing.tabcontrol.event.ComplexListDataEvent;
0094:        import org.netbeans.swing.tabcontrol.event.ComplexListDataListener;
0095:        import org.netbeans.swing.tabcontrol.event.TabActionEvent;
0096:        import org.netbeans.swing.tabcontrol.event.VeryComplexListDataEvent;
0097:
0098:        /**
0099:         * Default UI implementation for tabbed containers.  Manages installing the tab
0100:         * contentDisplayer and content contentDisplayer components, and the
0101:         * relationship between the data models and selection models of the UI.
0102:         * <p>
0103:         * Note that there is typically little reasons to subclass this - to affect the display
0104:         * or behavior of the tabs, implement {@link org.netbeans.swing.tabcontrol.TabDisplayerUI},
0105:         * the UI delegate for the embedded component which displays the tabs.
0106:         *
0107:         * @author Tim Boudreau
0108:         */
0109:        public class DefaultTabbedContainerUI extends TabbedContainerUI {
0110:            /**
0111:             * Action listener which receives actions from the tab displayer and propagates them through
0112:             * action listeners on the tab displayer, to allow clients to consume the events.
0113:             */
0114:            private ActionListener actionListener = null;
0115:            /**
0116:             * Flag to ensure listeners attached, since ComponentShown notifications are not always
0117:             * reliable.
0118:             */
0119:            /** UIManager key for the border of the tab displayer in editor ui type. */
0120:            public static final String KEY_EDITOR_CONTENT_BORDER = "TabbedContainer.editor.contentBorder"; //NOI18N
0121:            /** UIManager key for the border of the tab displayer in editor ui type */
0122:            public static final String KEY_EDITOR_TABS_BORDER = "TabbedContainer.editor.tabsBorder"; //NOI18N
0123:            /** UIManager key for the border of the entire tabbed container in editor ui type*/
0124:            public static final String KEY_EDITOR_OUTER_BORDER = "TabbedContainer.editor.outerBorder"; //NOI18N
0125:
0126:            /** UIManager key for the border of the tab displayer in view ui type. */
0127:            public static final String KEY_VIEW_CONTENT_BORDER = "TabbedContainer.view.contentBorder"; //NOI18N
0128:            /** UIManager key for the border of the tab displayer in view ui type. */
0129:            public static final String KEY_VIEW_TABS_BORDER = "TabbedContainer.view.tabsBorder"; //NOI18N
0130:            /** UIManager key for the border of the entire tabbed container in view ui type.*/
0131:            public static final String KEY_VIEW_OUTER_BORDER = "TabbedContainer.view.outerBorder"; //NOI18N
0132:
0133:            /** UIManager key for the border of the tab displayer in sliding ui type. */
0134:            public static final String KEY_SLIDING_CONTENT_BORDER = "TabbedContainer.sliding.contentBorder"; //NOI18N
0135:            /** UIManager key for the border of the tab displayer in sliding ui type */
0136:            public static final String KEY_SLIDING_TABS_BORDER = "TabbedContainer.sliding.tabsBorder"; //NOI18N
0137:            /** UIManager key for the border of the entire tabbed container in sliding ui type*/
0138:            public static final String KEY_SLIDING_OUTER_BORDER = "TabbedContainer.sliding.outerBorder"; //NOI18N
0139:
0140:            /** UIManager key for the border of the tab displayer in toolbar ui type. */
0141:            public static final String KEY_TOOLBAR_CONTENT_BORDER = "TabbedContainer.toolbar.contentBorder"; //NOI18N
0142:            /** UIManager key for the border of the tab displayer in toolbar ui type */
0143:            public static final String KEY_TOOLBAR_TABS_BORDER = "TabbedContainer.toolbar.tabsBorder"; //NOI18N
0144:            /** UIManager key for the border of the entire tabbed container in toolbar ui type*/
0145:            public static final String KEY_TOOLBAR_OUTER_BORDER = "TabbedContainer.toolbar.outerBorder"; //NOI18N
0146:
0147:            /** Component listener which listens on the container, and attaches/detaches listeners.
0148:             * <strong>do not alter the value in this field.  To provide a different implementation,
0149:             * override the appropriate creation method.</strong>
0150:             **/
0151:            protected ComponentListener componentListener = null;
0152:            /** Change listener which tracks changes in the selection model and changes the displayed
0153:             * component to reflect the selected tab
0154:             * <strong>do not alter the value in this field.  To provide a different implementation,
0155:             * override the appropriate creation method.</strong>
0156:             */
0157:            protected ChangeListener selectionListener = null;
0158:            /** Listener on the data model, which handles updating the contained components to keep them
0159:             * in sync with the contents of the data model.
0160:             * <strong>do not alter the value in this field.  To provide a different implementation,
0161:             * override the appropriate creation method.</strong>
0162:             * @see TabbedContainer#setContentPolicy
0163:             */
0164:            protected ComplexListDataListener modelListener = null;
0165:            /**
0166:             * Layout manager which will handle layout of the tabbed container.
0167:             * <strong>do not alter the value in this field.  To provide a different implementation,
0168:             * override the appropriate creation method.</strong>
0169:             */
0170:            protected LayoutManager contentDisplayerLayout = null;
0171:            /** Property change listener which detects changes on the tabbed container, such as its active state, which
0172:             * should be propagated to the tab displayer.
0173:             * <strong>do not alter the value in this field.  To provide a different implementation,
0174:             * override the appropriate creation method.</strong>
0175:             */
0176:            protected PropertyChangeListener propertyChangeListener = null;
0177:            /**
0178:             * FxProvider which will provide transition effects when tabs are changed.  By default, only used for
0179:             * TabbedContainer.TYPE_SLIDE tabs.
0180:             * <strong>do not alter the value in this field.  To provide a different implementation,
0181:             * override the appropriate creation method.</strong>
0182:             */
0183:            protected FxProvider slideEffectManager = null;
0184:
0185:            /**
0186:             * The component which displays the selected component in the tabbed container.
0187:             * <strong>do not alter the value in this field.  To provide a different implementation,
0188:             * override the appropriate creation method.</strong>
0189:             */
0190:            protected JComponent contentDisplayer = null;
0191:            /**
0192:             * The Displayer for the tabs.  Normally an instance of <code>TabDisplayer</code>.  To get the actual
0193:             * GUI component that is showing tabs, call its <code>getComponent()</code> method.
0194:             * <strong>do not alter the value in this field.  To provide a different implementation,
0195:             * override the appropriate creation method.</strong>
0196:             */
0197:            protected TabDisplayer tabDisplayer = null;
0198:
0199:            private HierarchyListener hierarchyListener = null;
0200:
0201:            /**
0202:             * Creates a new instance of DefaultTabbedContainerUI
0203:             */
0204:            public DefaultTabbedContainerUI(TabbedContainer c) {
0205:                super (c);
0206:            }
0207:
0208:            public static ComponentUI createUI(JComponent c) {
0209:                return new DefaultTabbedContainerUI((TabbedContainer) c);
0210:            }
0211:
0212:            /** This method is final.  Subclasses which need to provide additional initialization should override
0213:             * <code>install()</code>
0214:             *
0215:             * @param c A JComponent, which must == the displayer field initialized in the constructor
0216:             */
0217:            public final void installUI(JComponent c) {
0218:                assert c == container;
0219:                container.setLayout(createLayout());
0220:                contentDisplayer = createContentDisplayer();
0221:                tabDisplayer = createTabDisplayer();
0222:                selectionListener = createSelectionListener();
0223:                modelListener = createModelListener();
0224:                componentListener = createComponentListener();
0225:                propertyChangeListener = createPropertyChangeListener();
0226:                contentDisplayerLayout = createContentDisplayerLayout();
0227:                slideEffectManager = createFxProvider();
0228:                actionListener = createDisplayerActionListener();
0229:                container.setLayout(createLayout());
0230:                hierarchyListener = new ContainerHierarchyListener();
0231:                forward = new ForwardingMouseListener(container);
0232:                installContentDisplayer();
0233:                installTabDisplayer();
0234:                installBorders();
0235:                installListeners();
0236:                install();
0237:                //#41681, #44278, etc. FOCUS related. the UI needs to be the first listener to be notified
0238:                // that the selection has changed. Otherwise strange focus effects kick in, eg. when the winsys snapshot gets undated beforehand..
0239:                tabDisplayer.getSelectionModel().addChangeListener(
0240:                        selectionListener);
0241:
0242:            }
0243:
0244:            /** Used by unit tests */
0245:            TabDisplayer getTabDisplayer() {
0246:                return tabDisplayer;
0247:            }
0248:
0249:            private MouseListener forward = null;
0250:
0251:            /** This method is final.  Subclasses which need to provide additional initialization should override
0252:             * <code>uninstall()</code>
0253:             *
0254:             * @param c A JComponent, which must == the displayer field initialized in the constructor
0255:             */
0256:            public final void uninstallUI(JComponent c) {
0257:                assert c == container;
0258:                tabDisplayer.getSelectionModel().removeChangeListener(
0259:                        selectionListener);
0260:                uninstall();
0261:                uninstallListeners();
0262:                uninstallDisplayers();
0263:
0264:                container = null;
0265:                contentDisplayer = null;
0266:                tabDisplayer = null;
0267:                selectionListener = null;
0268:                modelListener = null;
0269:                componentListener = null;
0270:                propertyChangeListener = null;
0271:                contentDisplayerLayout = null;
0272:                actionListener = null;
0273:                forward = null;
0274:            }
0275:
0276:            /** Subclasses may override this method to do anything they need to do on installUI().  It will
0277:             * be called after listeners, the displayer, etc. (all pseudo-final protected fields) have been
0278:             * initialized.
0279:             */
0280:            protected void install() {
0281:
0282:            }
0283:
0284:            /** Subclasses may override this method to do anything they need to do on uninstallUI().  It will
0285:             * be called before the protected fields of the instance have been nulled.
0286:             */
0287:            protected void uninstall() {
0288:
0289:            }
0290:
0291:            protected boolean uichange() {
0292:                installBorders();
0293:                return false;
0294:            }
0295:
0296:            /**
0297:             * Installs the content displayer component and its layout manager
0298:             */
0299:            protected void installContentDisplayer() {
0300:                contentDisplayer.setLayout(contentDisplayerLayout);
0301:                container.add(contentDisplayer, BorderLayout.CENTER);
0302:            }
0303:
0304:            /**
0305:             * Installs the tab displayer component into the container.  By default, installs it using the
0306:             * constraint <code>BorderLayout.NORTH</code>.
0307:             */
0308:            protected void installTabDisplayer() {
0309:                container.add(tabDisplayer, BorderLayout.NORTH);
0310:                tabDisplayer.registerShortcuts(container);
0311:            }
0312:
0313:            /**
0314:             * Installs borders on the container, content displayer and tab displayer
0315:             */
0316:            protected void installBorders() {
0317:                String tabsKey;
0318:                String contentKey;
0319:                String outerKey;
0320:                switch (container.getType()) {
0321:                case TabbedContainer.TYPE_EDITOR:
0322:                    tabsKey = KEY_EDITOR_TABS_BORDER;
0323:                    contentKey = KEY_EDITOR_CONTENT_BORDER;
0324:                    outerKey = KEY_EDITOR_OUTER_BORDER;
0325:                    break;
0326:                case TabbedContainer.TYPE_VIEW:
0327:                    tabsKey = KEY_VIEW_TABS_BORDER;
0328:                    contentKey = KEY_VIEW_CONTENT_BORDER;
0329:                    outerKey = KEY_VIEW_OUTER_BORDER;
0330:                    break;
0331:                case TabbedContainer.TYPE_SLIDING:
0332:                    tabsKey = KEY_SLIDING_TABS_BORDER;
0333:                    contentKey = KEY_SLIDING_CONTENT_BORDER;
0334:                    outerKey = KEY_SLIDING_OUTER_BORDER;
0335:                    break;
0336:                case TabbedContainer.TYPE_TOOLBAR:
0337:                    tabsKey = KEY_TOOLBAR_TABS_BORDER;
0338:                    contentKey = KEY_TOOLBAR_CONTENT_BORDER;
0339:                    outerKey = KEY_TOOLBAR_OUTER_BORDER;
0340:                    break;
0341:                default:
0342:                    throw new IllegalStateException("Unknown type: "
0343:                            + container.getType());
0344:                }
0345:                try {
0346:                    Border b = (Border) UIManager.get(contentKey);
0347:                    contentDisplayer.setBorder(b);
0348:                    b = (Border) UIManager.get(tabsKey);
0349:                    tabDisplayer.setBorder(b);
0350:                    b = (Border) UIManager.get(outerKey);
0351:                    container.setBorder(b);
0352:                } catch (ClassCastException cce) {
0353:                    System.err.println("Expected a border from UIManager for "
0354:                            + tabsKey + "," + contentKey + "," + outerKey);
0355:                }
0356:            }
0357:
0358:            /**
0359:             * Installs a component listener on the component.  Listeners on the data
0360:             * model and selection model are installed when the component is shown, as
0361:             * detected by the component listener.
0362:             */
0363:            protected void installListeners() {
0364:                container.addComponentListener(componentListener);
0365:                container.addHierarchyListener(hierarchyListener);
0366:                //Allow mouse events to be forwarded as if they came from the 
0367:                //container
0368:                tabDisplayer.addMouseListener(forward);
0369:                contentDisplayer.addMouseListener(forward);
0370:            }
0371:
0372:            /**
0373:             * Begin listening to the model for changes in the selection, which should
0374:             * cause us to update the displayed component in the content
0375:             * contentDisplayer. Listening starts when the component is first shown, and
0376:             * stops when it is hidden;  if you override <code>createComponentListener()</code>,
0377:             * you will need to call this method when the component is shown.
0378:             */
0379:            protected void attachModelAndSelectionListeners() {
0380:                container.getModel().addComplexListDataListener(modelListener);
0381:                container.addPropertyChangeListener(propertyChangeListener);
0382:                tabDisplayer.setActive(container.isActive());
0383:                tabDisplayer.addActionListener(actionListener);
0384:            }
0385:
0386:            /**
0387:             * Stop listening to the model for changes in the selection, which should
0388:             * cause us to update the displayed component in the content
0389:             * contentDisplayer, and changes in the data model which can affect the
0390:             * displayed component. Listening starts when the component is first shown,
0391:             * and stops when it is hidden;  if you override <code>createComponentListener()</code>,
0392:             * you will need to call this method when the component is hidden.
0393:             */
0394:            protected void detachModelAndSelectionListeners() {
0395:                container.getModel().removeComplexListDataListener(
0396:                        modelListener);
0397:                container.removePropertyChangeListener(propertyChangeListener);
0398:                tabDisplayer.removeActionListener(actionListener);
0399:            }
0400:
0401:            /**
0402:             * Uninstalls the component listener installed in <code>installListeners()</code>
0403:             */
0404:            protected void uninstallListeners() {
0405:                container.removeComponentListener(componentListener);
0406:                container.removeHierarchyListener(hierarchyListener);
0407:                componentListener = null;
0408:                propertyChangeListener = null;
0409:                tabDisplayer.removeMouseListener(forward);
0410:                contentDisplayer.removeMouseListener(forward);
0411:            }
0412:
0413:            /**
0414:             * Uninstalls and nulls references to the content contentDisplayer and tab
0415:             * contentDisplayer, and removes all components from the content
0416:             * contentDisplayer.
0417:             */
0418:            protected void uninstallDisplayers() {
0419:                container.remove(contentDisplayer);
0420:                container.remove(tabDisplayer);
0421:                tabDisplayer.unregisterShortcuts(container);
0422:                contentDisplayer.removeAll();
0423:                contentDisplayer = null;
0424:                tabDisplayer = null;
0425:            }
0426:
0427:            /**
0428:             * Create the component which will display the tabs.
0429:             */
0430:            protected TabDisplayer createTabDisplayer() {
0431:                TabDisplayer result = null;
0432:                WinsysInfoForTabbed winsysInfo = container.getWinsysInfo();
0433:                if (winsysInfo != null) {
0434:                    result = new TabDisplayer(container.getModel(), container
0435:                            .getType(), winsysInfo);
0436:                } else {
0437:                    result = new TabDisplayer(container.getModel(), container
0438:                            .getType(), container.getLocationInformer());
0439:                }
0440:                result.setName("Tab Displayer"); //NOI18N
0441:                return result;
0442:            }
0443:
0444:            /**
0445:             * Create the component which will contain the content (the components which
0446:             * correspond to tabs).  The default implementation simply returns a
0447:             * vanilla, unadorned <code>JPanel</code>.
0448:             */
0449:            protected JPanel createContentDisplayer() {
0450:                JPanel result = new JPanel();
0451:                result.setName("Content displayer"); //NOI18N
0452:                return result;
0453:            }
0454:
0455:            /**
0456:             * Create an FxProvider instance which will provide transition effects when tabs are selected.
0457:             * By default creates a no-op instance for all displayer types except TYPE_SLIDING.
0458:             *
0459:             * @return An instance of FxProvider
0460:             */
0461:            protected FxProvider createFxProvider() {
0462:                if (NO_EFFECTS
0463:                        || (tabDisplayer.getType() != TabDisplayer.TYPE_SLIDING && !EFFECTS_EVERYWHERE)) {
0464:                    return new NoOpFxProvider();
0465:                } else {
0466:                    if (ADD_TO_GLASSPANE) {
0467:                        return new LiveComponentSlideFxProvider();
0468:                    } else {
0469:                        return new ImageSlideFxProvider();
0470:                    }
0471:                }
0472:            }
0473:
0474:            /**
0475:             * Creates the content contentDisplayer's layout manager, responsible for
0476:             * ensuring that the correct component is on top and is the only one
0477:             * showing
0478:             */
0479:            protected LayoutManager createContentDisplayerLayout() {
0480:                return new StackLayout();
0481:            }
0482:
0483:            /**
0484:             * Create the layout manager that will manage the layout of the
0485:             * TabbedContainer.  A TabbedContainer contains two components - the tabs
0486:             * contentDisplayer, and the component contentDisplayer.
0487:             * <p/>
0488:             * The layout manager determines the position of the tabs relative to the
0489:             * contentDisplayer component which displays the tab contents.
0490:             * <p/>
0491:             * The default implementation uses BorderLayout.  If you override this, you
0492:             * should probably override <code>installDisplayer()</code> as well.
0493:             */
0494:            protected LayoutManager createLayout() {
0495:                if (container.getType() == TabbedContainer.TYPE_SLIDING) {
0496:                    return new SlidingTabsLayout();
0497:                } else if (container.getType() == TabbedContainer.TYPE_TOOLBAR) {
0498:                    return new ToolbarTabsLayout();
0499:                } else {
0500:                    return new BorderLayout();
0501:                }
0502:            }
0503:
0504:            /**
0505:             * Create a component listener responsible for initializing the
0506:             * contentDisplayer component when the tabbed container is shown
0507:             */
0508:            protected ComponentListener createComponentListener() {
0509:                return new ContainerComponentListener();
0510:            }
0511:
0512:            /**
0513:             * Create a property change listener which will update the tab displayer in
0514:             * accordance with property changes on the container.  Currently the only
0515:             * property change of interest is calls to <code>TabbedContainer.setActive()</code>,
0516:             * which simply cause the active state to be set on the displayer.
0517:             */
0518:            protected PropertyChangeListener createPropertyChangeListener() {
0519:                return new ContainerPropertyChangeListener();
0520:            }
0521:
0522:            /** Creates an action listener to catch actions performed on the tab displayer
0523:             * and forward them to listeners on the container for consumption.
0524:             *
0525:             * @return An action listener
0526:             */
0527:            private ActionListener createDisplayerActionListener() {
0528:                return new DisplayerActionListener();
0529:            }
0530:
0531:            /**
0532:             * Ensures that the component the selection model says is selected is the
0533:             * one that is showing.
0534:             */
0535:            protected void ensureSelectedComponentIsShowing() {
0536:                int i = tabDisplayer.getSelectionModel().getSelectedIndex();
0537:                if (i != -1) {
0538:                    TabData td = container.getModel().getTab(i);
0539:                    showComponent(toComp(td));
0540:                }
0541:            }
0542:
0543:            /** Convenience method for fetching a component from a TabData object
0544:             * via the container's ComponentConverter */
0545:            protected final Component toComp(TabData data) {
0546:                return container.getComponentConverter().getComponent(data);
0547:            }
0548:
0549:            /**
0550:             * Shows the passed component. <strong>This method does not communicate with
0551:             * the data model in any way shape or form, it just moves the passed
0552:             * component to the front.  It should only be called in response to an event
0553:             * from the data model or selection model.
0554:             * <p/>
0555:             * If you override <code>createContentDisplayerLayoutModel()</code> to
0556:             * provide your own layout manager to arrange the displayed component, you
0557:             * need to override this to tell the layout (or do whatever is needed) to
0558:             * change the component that is shown.
0559:             *
0560:             * @param c The component to be shown
0561:             * @return The previously showing component, or null if no change was made
0562:             */
0563:            protected Component showComponent(Component c) {
0564:                if (contentDisplayerLayout instanceof  StackLayout) {
0565:                    StackLayout stack = ((StackLayout) contentDisplayerLayout);
0566:                    Component last = stack.getVisibleComponent();
0567:                    stack.showComponent(c, contentDisplayer);
0568:                    if (c != null) {
0569:                        Integer offset = (Integer) ((JComponent) c)
0570:                                .getClientProperty("MultiViewBorderHack.topOffset");
0571:                        contentDisplayer.putClientProperty(
0572:                                "MultiViewBorderHack.topOffset", offset);
0573:                    } else {
0574:                        contentDisplayer.putClientProperty(
0575:                                "MultiViewBorderHack.topOffset", null);
0576:                    }
0577:                    if (last != c) {
0578:                        maybeRemoveLastComponent(last);
0579:                        return last;
0580:                    }
0581:                }
0582:                return null;
0583:            }
0584:
0585:            /**
0586:             * Shows a component in the control, using the <code>FxProvider</code> created in
0587:             * <code>createFxProvider()</code> to manage showing it.  Equivalent to calling <code>showComponent</code>,
0588:             * but there may be a delay while the effect is performed.  If no <code>FxProvider</code> is installed,
0589:             * this will simply delegate to <code>showComponent</code>; if not, the <code>FxProvider</code> is expected
0590:             * to do that when its effect is completed.
0591:             *
0592:             * @param c The component to be shown.
0593:             */
0594:            protected final void showComponentWithFxProvider(Component c) {
0595:                if (slideEffectManager == null || !container.isShowing()
0596:                        || (!(c instanceof  JComponent))) {
0597:                    Component last = showComponent(c);
0598:                    maybeRemoveLastComponent(last);
0599:                } else {
0600:                    slideEffectManager.start((JComponent) c, container
0601:                            .getRootPane(), tabDisplayer
0602:                            .getClientProperty(TabDisplayer.PROP_ORIENTATION));
0603:                }
0604:            }
0605:
0606:            /**
0607:             * Removes the passed component from the AWT hierarchy if the container's content policy is
0608:             * CONTENT_POLICY_ADD_ONLY_SELECTED.
0609:             *
0610:             * @param c The component that should be removed
0611:             */
0612:            private final void maybeRemoveLastComponent(Component c) {
0613:                if (c != null
0614:                        && container.getContentPolicy() == TabbedContainer.CONTENT_POLICY_ADD_ONLY_SELECTED) {
0615:                    contentDisplayer.remove(c);
0616:                }
0617:            }
0618:
0619:            /**
0620:             * Fills contentDisplayer container with components retrieved from model.
0621:             */
0622:            protected void initDisplayer() {
0623:                if (container.getContentPolicy() == TabbedContainer.CONTENT_POLICY_ADD_ALL) {
0624:                    List tabs = container.getModel().getTabs();
0625:                    Component curC = null;
0626:                    for (Iterator iter = tabs.iterator(); iter.hasNext();) {
0627:                        curC = toComp((TabData) iter.next());
0628:                        // string parameter is needed for StackLayout to kick in correctly
0629:                        contentDisplayer.add(curC, "");
0630:                    }
0631:                } else {
0632:                    int i = tabDisplayer.getSelectionModel().getSelectedIndex();
0633:                    if (i != -1) {
0634:                        TabData td = container.getModel().getTab(i);
0635:                        contentDisplayer.add(toComp(td), "");
0636:                    }
0637:                }
0638:                updateActiveState();
0639:            }
0640:
0641:            /**
0642:             * Create a listener for the TabDataModel.  This listener is responsible for
0643:             * keeping the state of the contained components in the displayer in sync
0644:             * with the contents of the data model.  Note that it is not necessary for
0645:             * this listener to adjust the selection - DefaultTabSelectionModel handles
0646:             * cases such as removing the selected component appropriately, so if such a
0647:             * model change happens, a selection change will be immediately forthcoming
0648:             * to handle it.
0649:             * <p/>
0650:             * Note that it is important that this listener be added to the data model
0651:             * <i>after</i> the DefaultSelectionModel has added its listener. It is
0652:             * important to create the displayer component before adding this listener.
0653:             * Some support for privilged listeners may be added to DefaultTabDataModel
0654:             * in the future to avoid this issue entirely.
0655:             */
0656:            protected ComplexListDataListener createModelListener() {
0657:                return new ModelListener();
0658:            }
0659:
0660:            /**
0661:             * Create a ChangeListener which will listen to the selection model of the
0662:             * tab displayer, and update the displayed component in the displayer when
0663:             * the selection model changes.
0664:             */
0665:            protected ChangeListener createSelectionListener() {
0666:                return new SelectionListener();
0667:            }
0668:
0669:            /** Sets the active state of the displayer to match that of the container */
0670:            private void updateActiveState() {
0671:                //#45630 - more of a hack than a fix.
0672:                //apparently uninstallUI() was called before the the ContainerPropertyChangeListener instance was removed in 
0673:                //ContainerHierarchyListener's hierarchyChanged method.
0674:                // for such case the property change should be a noop.
0675:                TabDisplayer displ = tabDisplayer;
0676:                TabbedContainer cont = container;
0677:                if (displ != null && cont != null) {
0678:                    displ.setActive(cont.isActive());
0679:                }
0680:
0681:            }
0682:
0683:            public Rectangle getTabRect(int tab, Rectangle r) {
0684:                if (r == null) {
0685:                    r = new Rectangle();
0686:                }
0687:                tabDisplayer.getTabRect(tab, r);
0688:                Point p = tabDisplayer.getLocation();
0689:                r.x += p.x;
0690:                r.y += p.y;
0691:                return r;
0692:            }
0693:
0694:            protected void requestAttention(int tab) {
0695:                tabDisplayer.requestAttention(tab);
0696:            }
0697:
0698:            protected void cancelRequestAttention(int tab) {
0699:                tabDisplayer.cancelRequestAttention(tab);
0700:            }
0701:
0702:            public void setShowCloseButton(boolean val) {
0703:                tabDisplayer.setShowCloseButton(val);
0704:            }
0705:
0706:            public boolean isShowCloseButton() {
0707:                return tabDisplayer.isShowCloseButton();
0708:            }
0709:
0710:            /**
0711:             * Scroll pane-like border, good general border around windows. Used if no
0712:             * border is provided via UIDefaults.
0713:             */
0714:            private static final class DefaultWindowBorder implements  Border {
0715:                private static final Insets insets = new Insets(1, 1, 2, 2);
0716:
0717:                public void paintBorder(Component c, Graphics g, int x, int y,
0718:                        int w, int h) {
0719:                    g.translate(x, y);
0720:
0721:                    g.setColor(UIManager.getColor("controlShadow")); //NOI18N
0722:                    g.drawRect(0, 0, w - 2, h - 2);
0723:                    g.setColor(UIManager.getColor("controlHighlight")); //NOI18N
0724:                    g.drawLine(w - 1, 1, w - 1, h - 1);
0725:                    g.drawLine(1, h - 1, w - 1, h - 1);
0726:
0727:                    g.translate(-x, -y);
0728:                }
0729:
0730:                public Insets getBorderInsets(Component c) {
0731:                    return insets;
0732:                }
0733:
0734:                public boolean isBorderOpaque() {
0735:                    return true;
0736:                }
0737:            } // end of DefaultWindowBorder
0738:
0739:            protected class ContainerPropertyChangeListener implements 
0740:                    PropertyChangeListener {
0741:
0742:                public void propertyChange(PropertyChangeEvent evt) {
0743:                    if (TabbedContainer.PROP_ACTIVE.equals(evt
0744:                            .getPropertyName())) {
0745:                        updateActiveState();
0746:                    }
0747:                }
0748:            }
0749:
0750:            /** Checks the position of the tabbed container relative to its parent
0751:             * window, and potentially updates its orientation client property.
0752:             *
0753:             * @see TabDisplayer#PROP_ORIENTATION
0754:             */
0755:            protected final void updateOrientation() {
0756:                if (!container.isDisplayable()) {
0757:                    return;
0758:                }
0759:                if (Boolean.FALSE
0760:                        .equals(container
0761:                                .getClientProperty(TabbedContainer.PROP_MANAGE_TAB_POSITION))) {
0762:                    //The client has specified that it does not want automatic management
0763:                    //of the displayer orientation
0764:                    return;
0765:                }
0766:                Object currOrientation = tabDisplayer
0767:                        .getClientProperty(TabDisplayer.PROP_ORIENTATION);
0768:                Container window = container.getTopLevelAncestor();
0769:
0770:                Rectangle containerBounds = container.getBounds();
0771:                containerBounds = SwingUtilities.convertRectangle(container,
0772:                        containerBounds, window);
0773:
0774:                boolean longestIsVertical = containerBounds.width < containerBounds.height;
0775:
0776:                int distanceToLeft = containerBounds.x;
0777:                int distanceToTop = containerBounds.y;
0778:                int distanceToRight = window.getWidth()
0779:                        - (containerBounds.x + containerBounds.width);
0780:                int distanceToBottom = window.getHeight()
0781:                        - (containerBounds.y + containerBounds.height);
0782:
0783:                Object orientation;
0784:                if (!longestIsVertical) {
0785:                    if (distanceToBottom > distanceToTop) {
0786:                        orientation = TabDisplayer.ORIENTATION_NORTH;
0787:                    } else {
0788:                        orientation = TabDisplayer.ORIENTATION_SOUTH;
0789:                    }
0790:                } else {
0791:                    if (distanceToLeft > distanceToRight) {
0792:                        orientation = TabDisplayer.ORIENTATION_EAST;
0793:                    } else {
0794:                        orientation = TabDisplayer.ORIENTATION_WEST;
0795:                    }
0796:                }
0797:
0798:                if (currOrientation != orientation) {
0799:                    tabDisplayer.putClientProperty(
0800:                            TabDisplayer.PROP_ORIENTATION, orientation);
0801:                    container.validate();
0802:                }
0803:            }
0804:
0805:            public int tabForCoordinate(Point p) {
0806:                p = SwingUtilities.convertPoint(container, p, tabDisplayer);
0807:                return tabDisplayer.tabForCoordinate(p);
0808:            }
0809:
0810:            public void makeTabVisible(int tab) {
0811:                tabDisplayer.makeTabVisible(tab);
0812:            }
0813:
0814:            public SingleSelectionModel getSelectionModel() {
0815:                return tabDisplayer.getSelectionModel();
0816:            }
0817:
0818:            public Image createImageOfTab(int idx) {
0819:                return tabDisplayer.getUI().createImageOfTab(idx);
0820:            }
0821:
0822:            public Polygon getExactTabIndication(int idx) {
0823:                Polygon result = tabDisplayer.getUI()
0824:                        .getExactTabIndication(idx);
0825:                scratchPoint.setLocation(0, 0);
0826:                Point p = SwingUtilities.convertPoint(tabDisplayer,
0827:                        scratchPoint, container);
0828:                result.translate(-p.x, -p.y);
0829:                return appendContentBoundsTo(result);
0830:            }
0831:
0832:            private Point scratchPoint = new Point();
0833:
0834:            public Polygon getInsertTabIndication(int idx) {
0835:                Polygon result = tabDisplayer.getUI().getInsertTabIndication(
0836:                        idx);
0837:                scratchPoint.setLocation(0, 0);
0838:                Point p = SwingUtilities.convertPoint(tabDisplayer,
0839:                        scratchPoint, container);
0840:                result.translate(-p.x, -p.y);
0841:                return appendContentBoundsTo(result);
0842:            }
0843:
0844:            private Polygon appendContentBoundsTo(Polygon p) {
0845:                int width = contentDisplayer.getWidth();
0846:                int height = contentDisplayer.getHeight();
0847:
0848:                int[] xpoints = new int[p.npoints + 4];
0849:                int[] ypoints = new int[xpoints.length];
0850:
0851:                //XXX not handling this correctly for non-top orientations
0852:
0853:                int pos = 0;
0854:                Object orientation = tabDisplayer
0855:                        .getClientProperty(TabDisplayer.PROP_ORIENTATION);
0856:
0857:                int tabsHeight = tabDisplayer.getHeight();
0858:                if (orientation == null
0859:                        || orientation == TabDisplayer.ORIENTATION_NORTH) {
0860:
0861:                    xpoints[pos] = 0;
0862:                    ypoints[pos] = tabsHeight;
0863:
0864:                    pos++;
0865:
0866:                    xpoints[pos] = p.xpoints[p.npoints - 1];
0867:                    ypoints[pos] = tabsHeight;
0868:                    pos++;
0869:
0870:                    for (int i = 0; i < p.npoints - 2; i++) {
0871:                        xpoints[pos] = p.xpoints[i];
0872:                        ypoints[pos] = p.ypoints[i];
0873:                        pos++;
0874:                    }
0875:
0876:                    xpoints[pos] = xpoints[pos - 1];
0877:                    ypoints[pos] = tabsHeight;
0878:
0879:                    pos++;
0880:
0881:                    xpoints[pos] = width - 1;
0882:                    ypoints[pos] = tabsHeight;
0883:
0884:                    pos++;
0885:
0886:                    xpoints[pos] = width - 1;
0887:                    ypoints[pos] = height - 1;
0888:
0889:                    pos++;
0890:
0891:                    xpoints[pos] = 0;
0892:                    ypoints[pos] = height - 1;
0893:                } else if (orientation == TabDisplayer.ORIENTATION_SOUTH) {
0894:                    int yxlate = contentDisplayer.getHeight() * 2;
0895:
0896:                    xpoints[pos] = 0;
0897:                    ypoints[pos] = 0;
0898:
0899:                    pos++;
0900:
0901:                    xpoints[pos] = container.getWidth();
0902:                    ypoints[pos] = 0;
0903:
0904:                    pos++;
0905:
0906:                    xpoints[pos] = container.getWidth();
0907:                    ypoints[pos] = container.getHeight() - tabsHeight;
0908:
0909:                    pos++;
0910:
0911:                    int upperRight = 0;
0912:                    //Search backward for the upper right corner - we only know
0913:                    //the location of the left upper corner
0914:                    int highestFound = Integer.MIN_VALUE;
0915:                    for (int i = p.npoints - 2; i >= 0; i--) {
0916:                        if (highestFound < p.ypoints[i]) {
0917:                            upperRight = i;
0918:                            highestFound = p.ypoints[i];
0919:                        } else if (highestFound == p.ypoints[i]) {
0920:                            break;
0921:                        }
0922:                    }
0923:
0924:                    int curr = upperRight - 1;
0925:                    for (int i = p.npoints - 1; i >= 0; i--) {
0926:                        xpoints[pos] = p.xpoints[curr];
0927:                        if (ypoints[pos] == highestFound) {
0928:                            ypoints[pos] = Math.min(
0929:                                    tabDisplayer.getLocation().y,
0930:                                    p.ypoints[curr] + yxlate);
0931:                        } else {
0932:                            ypoints[pos] = p.ypoints[curr] + yxlate;
0933:                        }
0934:                        pos++;
0935:                        curr++;
0936:                        if (curr == p.npoints - 1) {
0937:                            curr = 0;
0938:                        }
0939:                    }
0940:
0941:                    xpoints[pos] = 0;
0942:                    ypoints[pos] = container.getHeight() - tabsHeight;
0943:                } else {
0944:                    //Punt on side tabs for now
0945:                    xpoints = p.xpoints;
0946:                    ypoints = p.ypoints;
0947:                }
0948:
0949:                Polygon result = new EqualPolygon(xpoints, ypoints,
0950:                        xpoints.length);
0951:                return result;
0952:            }
0953:
0954:            public Rectangle getContentArea() {
0955:                return contentDisplayer.getBounds();
0956:            }
0957:
0958:            public Rectangle getTabsArea() {
0959:                return tabDisplayer.getBounds();
0960:            }
0961:
0962:            public int dropIndexOfPoint(Point p) {
0963:                Point p2 = SwingUtilities.convertPoint(container, p,
0964:                        tabDisplayer);
0965:                return tabDisplayer.getUI().dropIndexOfPoint(p2);
0966:            }
0967:
0968:            public Rectangle getTabsArea(Rectangle dest) {
0969:                return tabDisplayer.getBounds();
0970:            }
0971:
0972:            /**
0973:             * A ComponentListener which listens for show/hide to add and remove the
0974:             * selection and model listeners
0975:             */
0976:            protected class ContainerComponentListener extends ComponentAdapter {
0977:                public ContainerComponentListener() {
0978:                }
0979:
0980:                public void componentMoved(ComponentEvent e) {
0981:                    if (container.getType() == TabbedContainer.TYPE_SLIDING) {
0982:                        updateOrientation();
0983:                    }
0984:                }
0985:
0986:                public void componentResized(ComponentEvent e) {
0987:                    if (container.getType() == TabbedContainer.TYPE_SLIDING) {
0988:                        updateOrientation();
0989:                    }
0990:                }
0991:            }
0992:
0993:            private boolean bug4924561knownShowing = false;
0994:
0995:            /**
0996:             * Calls <code>initDisplayer()</code>, then <code>attachModelAndSelectionListeners</code>,
0997:             * then <code>ensureSelectedComponentIsShowing</code>
0998:             */
0999:            private class ContainerHierarchyListener implements 
1000:                    HierarchyListener {
1001:                public ContainerHierarchyListener() {
1002:                }
1003:
1004:                public void hierarchyChanged(HierarchyEvent e) {
1005:                    if ((e.getChangeFlags() & HierarchyEvent.SHOWING_CHANGED) != 0) {
1006:                        boolean showing = container.isShowing();
1007:                        if (showing != bug4924561knownShowing) {
1008:                            if (container.isShowing()) {
1009:                                initDisplayer();
1010:                                attachModelAndSelectionListeners();
1011:                                ensureSelectedComponentIsShowing();
1012:                                if (container.getType() == TabbedContainer.TYPE_SLIDING) {
1013:                                    updateOrientation();
1014:                                }
1015:                            } else {
1016:                                detachModelAndSelectionListeners();
1017:                                if (container.getType() == TabbedContainer.TYPE_SLIDING) {
1018:                                    updateOrientation();
1019:                                }
1020:                            }
1021:                        }
1022:                        bug4924561knownShowing = showing;
1023:                    }
1024:                }
1025:            }
1026:
1027:            private class ToolbarTabsLayout implements  LayoutManager {
1028:
1029:                public void layoutContainer(Container container) {
1030:                    Dimension tabSize = tabDisplayer.getPreferredSize();
1031:                    Insets ins = container.getInsets();
1032:                    int w = container.getWidth() - (ins.left + ins.right);
1033:                    tabDisplayer
1034:                            .setBounds(ins.left, ins.top, w, tabSize.height);
1035:                    contentDisplayer.setBounds(ins.left, ins.top
1036:                            + tabSize.height, w, container.getHeight()
1037:                            - (ins.top + ins.bottom + tabSize.height));
1038:                }
1039:
1040:                public Dimension minimumLayoutSize(Container container) {
1041:                    Dimension tabSize = tabDisplayer.getMinimumSize();
1042:                    Dimension contentSize = contentDisplayer.getMinimumSize();
1043:                    Insets ins = container.getInsets();
1044:                    Dimension result = new Dimension(ins.left + ins.top,
1045:                            ins.right + ins.bottom);
1046:                    result.width += Math.max(tabSize.width, contentSize.width);
1047:                    result.height += tabSize.height + contentSize.height;
1048:                    return result;
1049:                }
1050:
1051:                public Dimension preferredLayoutSize(Container container) {
1052:                    Dimension tabSize = tabDisplayer.getPreferredSize();
1053:                    Dimension contentSize = contentDisplayer.getPreferredSize();
1054:                    Insets ins = container.getInsets();
1055:                    Dimension result = new Dimension(ins.left + ins.top,
1056:                            ins.right + ins.bottom);
1057:                    result.width += Math.max(tabSize.width, contentSize.width);
1058:                    result.height += tabSize.height + contentSize.height;
1059:                    return result;
1060:                }
1061:
1062:                public void removeLayoutComponent(Component component) {
1063:                    //do nothing
1064:                }
1065:
1066:                public void addLayoutComponent(String str, Component component) {
1067:                    //do nothing
1068:                }
1069:            }
1070:
1071:            /**
1072:             * A ChangeListener which updates the component displayed in the content
1073:             * displayer with the selected component in the tab displayer's selection
1074:             * model
1075:             */
1076:            protected class SelectionListener implements  ChangeListener {
1077:                public SelectionListener() {
1078:                }
1079:
1080:                public void stateChanged(ChangeEvent e) {
1081:                    if (container.isShowing()
1082:                    //a special case for property sheet dialog window - the selection 
1083:                            //change must be processed otherwise the tabbed container may have
1084:                            //undefined preferred size so the property window will be too small
1085:                            || container.getClientProperty("tc") != null) { //NOI18N
1086:                        int idx = tabDisplayer.getSelectionModel()
1087:                                .getSelectedIndex();
1088:                        if (idx != -1) {
1089:                            Component c = toComp(container.getModel().getTab(
1090:                                    idx));
1091:                            c.setBounds(0, 0, contentDisplayer.getWidth(),
1092:                                    contentDisplayer.getHeight());
1093:                            showComponentWithFxProvider(c);
1094:                        } else {
1095:                            showComponent(null);
1096:                        }
1097:                    }
1098:                }
1099:            }
1100:
1101:            /**
1102:             * This class does the heavy lifting of keeping the content of the content
1103:             * displayer up-to-date with the contents of the data model.
1104:             */
1105:            protected class ModelListener implements  ComplexListDataListener {
1106:                public ModelListener() {
1107:                }
1108:
1109:                /**
1110:                 * DefaultTabDataModel will always call this method with an instance of
1111:                 * ComplexListDataEvent.
1112:                 */
1113:                public void contentsChanged(ListDataEvent e) {
1114:                    //Only need to reread components on setTab (does winsys even use it?)
1115:                    if (e instanceof  ComplexListDataEvent) {
1116:                        ComplexListDataEvent clde = (ComplexListDataEvent) e;
1117:                        int index = clde.getIndex0();
1118:                        if (clde.isUserObjectChanged() && index != -1) {
1119:                            Component comp = contentDisplayer
1120:                                    .getComponent(index);
1121:                            Component nue = toComp(tabDisplayer.getModel()
1122:                                    .getTab(index));
1123:                            contentDisplayer.remove(comp);
1124:
1125:                            boolean add = container.getContentPolicy() == TabbedContainer.CONTENT_POLICY_ADD_ALL
1126:                                    || index == container.getSelectionModel()
1127:                                            .getSelectedIndex();
1128:
1129:                            if (add) {
1130:                                contentDisplayer.add(nue, index);
1131:                            }
1132:                        }
1133:                        if (clde.isTextChanged()) {
1134:                            maybeMakeSelectedTabVisible(clde);
1135:                        }
1136:                    }
1137:                }
1138:
1139:                /**
1140:                 * This method is called to scroll the selected tab into view if its
1141:                 * title changes (it may be scrolled offscreen).  NetBeans' editor uses
1142:                 * this to ensure that the user can see what file they're editing when
1143:                 * the user starts typing (this triggers a * being appended to the tab
1144:                 * title, thus triggering this call).
1145:                 */
1146:                private void maybeMakeSelectedTabVisible(
1147:                        ComplexListDataEvent clde) {
1148:                    if (!container.isShowing() || container.getWidth() < 10) {
1149:                        //Java module fires icon changes from badging before the
1150:                        //main window has been validated for the first time
1151:                        return;
1152:                    }
1153:                    if (tabDisplayer.getType() == TabDisplayer.TYPE_EDITOR) {
1154:                        int idx = tabDisplayer.getSelectionModel()
1155:                                .getSelectedIndex();
1156:                        //If more than one tab changed, it's probably not an event we want.
1157:                        //Only do this if there is only one.
1158:                        if ((clde.getIndex0() == clde.getIndex1())
1159:                                && clde.getIndex0() == idx) {
1160:                            (tabDisplayer).makeTabVisible(idx);
1161:                        }
1162:                    }
1163:                }
1164:
1165:                public void intervalAdded(ListDataEvent e) {
1166:                    if (container.getContentPolicy() == TabbedContainer.CONTENT_POLICY_ADD_ALL) {
1167:                        Component curC = null;
1168:                        for (int i = e.getIndex0(); i <= e.getIndex1(); i++) {
1169:                            curC = toComp(container.getModel().getTab(i));
1170:                            contentDisplayer.add(curC, "");
1171:                        }
1172:                    }
1173:                }
1174:
1175:                public void intervalRemoved(ListDataEvent e) {
1176:                    //  we know that it must be complex data event
1177:                    ComplexListDataEvent clde = (ComplexListDataEvent) e;
1178:                    TabData[] removedTabs = clde.getAffectedItems();
1179:                    Component curComp;
1180:                    for (int i = 0; i < removedTabs.length; i++) {
1181:                        curComp = toComp(removedTabs[i]);
1182:                        contentDisplayer.remove(curComp);
1183:                    }
1184:                }
1185:
1186:                public void indicesAdded(ComplexListDataEvent e) {
1187:                    Component curC = null;
1188:                    if (container.getContentPolicy() == TabbedContainer.CONTENT_POLICY_ADD_ALL) {
1189:                        int[] indices = e.getIndices();
1190:                        for (int i = 0; i < indices.length; i++) {
1191:                            curC = toComp(container.getModel().getTab(
1192:                                    indices[i]));
1193:                            contentDisplayer.add(curC, "");
1194:                        }
1195:                    }
1196:                }
1197:
1198:                public void indicesRemoved(ComplexListDataEvent e) {
1199:                    int[] indices = e.getIndices();
1200:                    TabData[] removedTabs = e.getAffectedItems();
1201:                    Component curComp;
1202:                    for (int i = 0; i < indices.length; i++) {
1203:                        curComp = toComp(removedTabs[i]);
1204:                        // TBD - add assertion curComp.getParent() != contentDisplayer
1205:                        contentDisplayer.remove(curComp);
1206:                    }
1207:                }
1208:
1209:                public void indicesChanged(ComplexListDataEvent e) {
1210:                    //XXX - if we keep contentPolicies, this could be simplified for
1211:                    //the non ADD_ALL policies
1212:                    if (e instanceof  VeryComplexListDataEvent) {
1213:                        ArrayDiff dif = ((VeryComplexListDataEvent) e)
1214:                                .getDiff();
1215:
1216:                        //Get the deleted and added indices
1217:                        Set deleted = dif.getDeletedIndices();
1218:                        Set added = dif.getAddedIndices();
1219:
1220:                        //Get the TabData array from before the change
1221:                        TabData[] old = dif.getOldData();
1222:                        //Get the TabData array from after the change
1223:                        TabData[] nue = dif.getNewData();
1224:
1225:                        //Now we need to fetch the set of components we should end up
1226:                        //displaying.  We need to do this because TabData.equals is only
1227:                        //true if the text *and* the component match.  So if the winsys
1228:                        //called setTabs just to change the title of a tab, we would
1229:                        //end up removing and re-adding the component for no reason.
1230:                        Set<Component> components = new HashSet<Component>();
1231:                        if (container.getContentPolicy() == TabbedContainer.CONTENT_POLICY_ADD_ALL) {
1232:                            for (int i = 0; i < nue.length; i++) {
1233:                                components.add(toComp(nue[i]));
1234:                            }
1235:                        }
1236:                        boolean changed = false;
1237:
1238:                        synchronized (contentDisplayer.getTreeLock()) {
1239:                            //See if we've got anything to delete
1240:                            if (!deleted.isEmpty()) {
1241:                                Iterator i = deleted.iterator();
1242:                                while (i.hasNext()) {
1243:                                    //Get the index into the old array of a deleted tab
1244:                                    Integer idx = (Integer) i.next();
1245:                                    //Find the TabData object for it
1246:                                    TabData del = old[idx.intValue()];
1247:                                    //Make sure its component is not one we'll be adding
1248:                                    if (!components.contains(toComp(del))) {
1249:                                        //remove it
1250:                                        contentDisplayer.remove(toComp(del));
1251:                                        changed = true;
1252:                                    }
1253:                                }
1254:                            }
1255:
1256:                            if (container.getContentPolicy() == TabbedContainer.CONTENT_POLICY_ADD_ALL) {
1257:
1258:                                //See if we've got anything to add
1259:                                if (!added.isEmpty()) {
1260:                                    Iterator i = added.iterator();
1261:                                    while (i.hasNext()) {
1262:                                        //Get the index into the new array of the added tab
1263:                                        Integer idx = (Integer) i.next();
1264:                                        //Find the TabData object that was added
1265:                                        TabData add = nue[idx.intValue()];
1266:                                        //Make sure it's not already showing so we don't do
1267:                                        //extra work
1268:                                        if (!contentDisplayer
1269:                                                .isAncestorOf(toComp(add))) {
1270:                                            contentDisplayer.add(toComp(add),
1271:                                                    "");
1272:                                            changed = true;
1273:                                        }
1274:                                    }
1275:                                }
1276:                            }
1277:                        }
1278:                        //repaint
1279:                        if (changed) {
1280:                            contentDisplayer.revalidate();
1281:                            contentDisplayer.repaint();
1282:                        }
1283:                    }
1284:                }
1285:            }
1286:
1287:            /** An action listener which listens on action events from the tab displayer (select, close, etc.)
1288:             * and propagates them to the tabbed container's action posting mechanism, so listeners on it also
1289:             * have an opportunity to veto undesired actions, or handle actions themselves.
1290:             */
1291:            private class DisplayerActionListener implements  ActionListener {
1292:                public void actionPerformed(ActionEvent ae) {
1293:                    TabActionEvent tae = (TabActionEvent) ae;
1294:                    if (!shouldPerformAction(tae.getActionCommand(), tae
1295:                            .getTabIndex(), tae.getMouseEvent())) {
1296:                        tae.consume();
1297:                    }
1298:                }
1299:            }
1300:
1301:            private class SlidingTabsLayout implements  LayoutManager {
1302:
1303:                public void addLayoutComponent(String name, Component comp) {
1304:                    //do nothing
1305:                }
1306:
1307:                public void layoutContainer(Container parent) {
1308:                    JComponent c = tabDisplayer;
1309:
1310:                    Object orientation = c
1311:                            .getClientProperty(TabDisplayer.PROP_ORIENTATION);
1312:
1313:                    Dimension d = tabDisplayer.getPreferredSize();
1314:                    Insets ins = container.getInsets();
1315:                    int width = parent.getWidth() - (ins.left + ins.right);
1316:                    int height = parent.getHeight() - (ins.top + ins.bottom);
1317:
1318:                    if (orientation == TabDisplayer.ORIENTATION_NORTH) {
1319:                        c.setBounds(ins.left, ins.top, width, d.height);
1320:
1321:                        contentDisplayer.setBounds(ins.left,
1322:                                ins.top + d.height, width, parent.getHeight()
1323:                                        - (d.height + ins.top + ins.bottom));
1324:
1325:                    } else if (orientation == TabDisplayer.ORIENTATION_SOUTH) {
1326:                        contentDisplayer.setBounds(ins.top, ins.left, width,
1327:                                parent.getHeight()
1328:                                        - (d.height + ins.top + ins.bottom));
1329:
1330:                        c.setBounds(ins.left, parent.getHeight()
1331:                                - (d.height + ins.top + ins.bottom), width,
1332:                                d.height);
1333:                    } else if (orientation == TabDisplayer.ORIENTATION_EAST) {
1334:                        contentDisplayer.setBounds(ins.left, ins.top, width
1335:                                - d.width, height);
1336:
1337:                        c.setBounds(parent.getWidth() - (ins.right + d.width),
1338:                                ins.top, d.width, height);
1339:
1340:                    } else if (orientation == TabDisplayer.ORIENTATION_WEST) {
1341:                        c.setBounds(ins.left, ins.top, d.width, height);
1342:
1343:                        contentDisplayer.setBounds(ins.left + d.width, ins.top,
1344:                                width - d.width, height);
1345:
1346:                    } else {
1347:                        throw new IllegalArgumentException(
1348:                                "Unknown orientation: " + orientation);
1349:                    }
1350:                }
1351:
1352:                public Dimension minimumLayoutSize(Container parent) {
1353:                    JComponent c = tabDisplayer;
1354:
1355:                    Object orientation = c
1356:                            .getClientProperty(TabDisplayer.PROP_ORIENTATION);
1357:
1358:                    Dimension tabSize = tabDisplayer.getPreferredSize();
1359:                    Insets ins = container.getInsets();
1360:
1361:                    Dimension result = new Dimension();
1362:
1363:                    Dimension contentSize = contentDisplayer.getPreferredSize();
1364:                    if (tabDisplayer.getSelectionModel().getSelectedIndex() == -1) {
1365:                        contentSize.width = 0;
1366:                        contentSize.height = 0;
1367:                    }
1368:
1369:                    if (orientation == TabDisplayer.ORIENTATION_NORTH
1370:                            || orientation == TabDisplayer.ORIENTATION_SOUTH) {
1371:                        result.height = ins.top + ins.bottom
1372:                                + contentSize.height + tabSize.height;
1373:                        result.width = ins.left + ins.right
1374:                                + Math.max(contentSize.width, tabSize.width);
1375:                    } else {
1376:                        result.width = ins.left + ins.right + contentSize.width
1377:                                + tabSize.width;
1378:                        result.height = ins.top + ins.bottom
1379:                                + Math.max(contentSize.height, tabSize.height);
1380:                    }
1381:                    return result;
1382:                }
1383:
1384:                public Dimension preferredLayoutSize(Container parent) {
1385:                    return minimumLayoutSize(parent);
1386:                }
1387:
1388:                public void removeLayoutComponent(Component comp) {
1389:                    //do nothing
1390:                }
1391:            }
1392:
1393:            /** A FxProvider which simply calls finish() from its start
1394:             * method, providing no effects whatsoever */
1395:            private final class NoOpFxProvider extends FxProvider {
1396:
1397:                public void cleanup() {
1398:                    //Do nothing
1399:                }
1400:
1401:                protected void doFinish() {
1402:                    showComponent(comp);
1403:
1404:                }
1405:
1406:                protected void doStart() {
1407:                    finish();
1408:                }
1409:            }
1410:
1411:            private final class ImageSlideFxProvider extends FxProvider
1412:                    implements  ActionListener {
1413:                private Timer timer = null;
1414:                private Component prevGlassPane = null;
1415:                private Dimension d = null;
1416:
1417:                protected void doStart() {
1418:                    if (timer == null) {
1419:                        timer = new Timer(TIMER, this );
1420:                        timer.setRepeats(true);
1421:                    }
1422:
1423:                    prevGlassPane = root.getGlassPane();
1424:
1425:                    if (prevGlassPane.isVisible() && prevGlassPane.isShowing()) {
1426:                        //Probably a drag and drop operation - don't interfere
1427:                        doFinish();
1428:                        return;
1429:                    }
1430:
1431:                    initSize();
1432:                    img = createImageOfComponent();
1433:
1434:                    ImageScalingGlassPane cp = getCustomGlassPane();
1435:                    root.setGlassPane(cp);
1436:                    cp.setIncrement(0.1f);
1437:                    cp.setBounds(root.getBounds());
1438:                    cp.setVisible(true);
1439:                    cp.revalidate();
1440:                    timer.start();
1441:                }
1442:
1443:                public void cleanup() {
1444:                    timer.stop();
1445:                    root.setGlassPane(prevGlassPane);
1446:                    prevGlassPane.setVisible(false);
1447:                    if (img != null) {
1448:                        img.flush();
1449:                    }
1450:                    img = null;
1451:                }
1452:
1453:                protected void doFinish() {
1454:                    showComponent(comp);
1455:                }
1456:
1457:                private void initSize() {
1458:                    d = comp.getPreferredSize();
1459:
1460:                    Dimension d2 = contentDisplayer.getSize();
1461:
1462:                    d.width = Math.max(d2.width, d.width);
1463:                    d.height = Math.max(d2.height, d.height);
1464:
1465:                    boolean flip = orientation == TabDisplayer.ORIENTATION_EAST
1466:                            || orientation == TabDisplayer.ORIENTATION_WEST;
1467:
1468:                    if (d.width == 0 || d.height == 0) {
1469:                        if (flip) {
1470:                            d.width = root.getWidth();
1471:                            d.height = tabDisplayer.getHeight();
1472:                        } else {
1473:                            d.width = tabDisplayer.getWidth();
1474:                            d.height = root.getHeight();
1475:                        }
1476:                    } else {
1477:                        if (flip) {
1478:                            d.height = Math.max(d.height, tabDisplayer
1479:                                    .getHeight());
1480:                        } else {
1481:                            d.width = Math
1482:                                    .max(d.width, tabDisplayer.getWidth());
1483:                        }
1484:                    }
1485:                }
1486:
1487:                private BufferedImage img = null;
1488:
1489:                private BufferedImage createImageOfComponent() {
1490:                    if (USE_SWINGPAINTING) {
1491:                        return null;
1492:                    }
1493:                    if (d.width == 0 || d.height == 0) {
1494:                        //Avoid problems in native graphics engine scaling if we should
1495:                        //end up with crazy values
1496:                        finish();
1497:                    }
1498:
1499:                    BufferedImage img = GraphicsEnvironment
1500:                            .getLocalGraphicsEnvironment()
1501:                            .getDefaultScreenDevice().getDefaultConfiguration()
1502:                            .createCompatibleImage(d.width, d.height);
1503:
1504:                    Graphics2D g2d = img.createGraphics();
1505:                    JComponent c = tabDisplayer;
1506:
1507:                    c.setBounds(0, 0, d.width, d.height);
1508:                    comp.paint(g2d);
1509:
1510:                    return img;
1511:                }
1512:
1513:                public void actionPerformed(java.awt.event.ActionEvent e) {
1514:                    float inc = customGlassPane.getIncrement();
1515:                    if (inc >= 1.0f) {
1516:                        finish();
1517:                    } else {
1518:                        customGlassPane.setIncrement(inc + INCREMENT);
1519:                    }
1520:                }
1521:
1522:                private ImageScalingGlassPane customGlassPane = null;
1523:
1524:                private ImageScalingGlassPane getCustomGlassPane() {
1525:                    if (customGlassPane == null) {
1526:                        customGlassPane = new ImageScalingGlassPane();
1527:                        customGlassPane.setOpaque(false);
1528:                    }
1529:                    return customGlassPane;
1530:                }
1531:
1532:                private class ImageScalingGlassPane extends JPanel {
1533:                    private float inc = 0f;
1534:                    private Rectangle rect = new Rectangle();
1535:                    private Rectangle r2 = new Rectangle();
1536:                    private boolean changed = true;
1537:
1538:                    private void setIncrement(float inc) {
1539:                        this .inc = inc;
1540:                        changed = true;
1541:                        if (isShowing()) {
1542:                            Rectangle r = getImageBounds();
1543:                            if (SYNCHRONOUS_PAINTING) {
1544:                                paintImmediately(r.x, r.y, r.width, r.height);
1545:                            } else {
1546:                                repaint(r.x, r.y, r.width, r.height);
1547:                            }
1548:                        }
1549:                    }
1550:
1551:                    private float getIncrement() {
1552:                        return inc;
1553:                    }
1554:
1555:                    private Rectangle getImageBounds() {
1556:                        if (!changed) {
1557:                            return rect;
1558:                        }
1559:                        Component c = tabDisplayer;
1560:                        r2.setBounds(0, 0, c.getWidth(), c.getHeight());
1561:
1562:                        Rectangle dispBounds = SwingUtilities.convertRectangle(
1563:                                c, r2, this );
1564:
1565:                        if (orientation == TabDisplayer.ORIENTATION_WEST) {
1566:                            rect.x = dispBounds.x + dispBounds.width;
1567:                            rect.y = dispBounds.y;
1568:                            rect.width = Math.round(inc * d.width);
1569:                            rect.height = dispBounds.height;
1570:                        } else if (orientation == TabDisplayer.ORIENTATION_EAST) {
1571:                            rect.width = Math.round(inc * d.width);
1572:                            rect.height = dispBounds.height;
1573:                            rect.x = dispBounds.x - rect.width;
1574:                            rect.y = dispBounds.y;
1575:                        } else if (orientation == TabDisplayer.ORIENTATION_SOUTH) {
1576:                            rect.width = dispBounds.width;
1577:                            rect.height = Math.round(inc * d.height);
1578:                            rect.x = dispBounds.x;
1579:                            rect.y = dispBounds.y - rect.height;
1580:                        } else if (orientation == TabDisplayer.ORIENTATION_NORTH) {
1581:                            rect.x = dispBounds.x;
1582:                            rect.y = dispBounds.y + dispBounds.height;
1583:                            rect.width = dispBounds.width;
1584:                            rect.height = Math.round(inc * d.height);
1585:                        }
1586:                        changed = false;
1587:                        return rect;
1588:                    }
1589:
1590:                    public void paint(Graphics g) {
1591:                        try {
1592:                            if (USE_SWINGPAINTING) {
1593:                                SwingUtilities.paintComponent(g, comp, this ,
1594:                                        getImageBounds());
1595:                            } else {
1596:                                Graphics2D g2d = (Graphics2D) g;
1597:                                Composite comp = null;
1598:                                if (true) {
1599:                                    comp = g2d.getComposite();
1600:                                    g2d.setComposite(AlphaComposite
1601:                                            .getInstance(
1602:                                                    AlphaComposite.SRC_OVER,
1603:                                                    Math.min(0.99f, inc)));
1604:                                }
1605:                                Rectangle r = getImageBounds();
1606:                                if (NO_SCALE) {
1607:                                    AffineTransform at = AffineTransform
1608:                                            .getTranslateInstance(r.x, r.y);
1609:                                    g2d.drawRenderedImage(img, at);
1610:                                } else {
1611:                                    g2d.drawImage(img, r.x, r.y, r.x + r.width,
1612:                                            r.y + r.height, 0, 0, d.width,
1613:                                            d.height, getBackground(), null);
1614:                                }
1615:                                if (comp != null) {
1616:                                    g2d.setComposite(comp);
1617:                                }
1618:                            }
1619:                        } catch (Exception e) {
1620:                            //Some problem in Apple's graphics scaling engine
1621:                            e.printStackTrace();
1622:                            finish();
1623:                        }
1624:                    }
1625:                }
1626:            }
1627:
1628:            private final class LiveComponentSlideFxProvider extends FxProvider
1629:                    implements  ActionListener {
1630:                private Timer timer = null;
1631:                private Component prevGlassPane = null;
1632:                private Dimension d = null;
1633:
1634:                protected void doStart() {
1635:                    if (timer == null) {
1636:                        timer = new Timer(TIMER, this );
1637:                        timer.setRepeats(true);
1638:                    }
1639:
1640:                    prevGlassPane = root.getGlassPane();
1641:                    if (prevGlassPane.isVisible() && prevGlassPane.isShowing()) {
1642:                        //Probably a drag and drop operation - don't interfere
1643:                        doFinish();
1644:                        return;
1645:                    }
1646:
1647:                    initSize();
1648:                    LiveComponentResizingGlassPane cp = getCustomGlassPane();
1649:                    root.setGlassPane(cp);
1650:                    cp.setIncrement(0.1f);
1651:                    cp.setBounds(root.getBounds());
1652:                    cp.setVisible(true);
1653:                    cp.revalidate();
1654:                    timer.start();
1655:                }
1656:
1657:                private void initSize() {
1658:                    d = comp.getPreferredSize();
1659:
1660:                    Dimension d2 = contentDisplayer.getSize();
1661:
1662:                    d.width = Math.max(d2.width, d.width);
1663:                    d.height = Math.max(d2.height, d.height);
1664:
1665:                    boolean flip = orientation == TabDisplayer.ORIENTATION_EAST
1666:                            || orientation == TabDisplayer.ORIENTATION_WEST;
1667:
1668:                    if (d.width == 0 || d.height == 0) {
1669:                        if (flip) {
1670:                            d.width = root.getWidth();
1671:                            d.height = tabDisplayer.getHeight();
1672:                        } else {
1673:                            d.width = tabDisplayer.getWidth();
1674:                            d.height = root.getHeight();
1675:                        }
1676:                    } else {
1677:                        if (flip) {
1678:                            d.height = Math.max(d.height, tabDisplayer
1679:                                    .getHeight());
1680:                        } else {
1681:                            d.width = Math
1682:                                    .max(d.width, tabDisplayer.getWidth());
1683:                        }
1684:                    }
1685:                }
1686:
1687:                public void cleanup() {
1688:                    timer.stop();
1689:                    root.setGlassPane(prevGlassPane);
1690:                    prevGlassPane.setVisible(false);
1691:                    customGlassPane.remove(comp);
1692:                }
1693:
1694:                protected void doFinish() {
1695:                    showComponent(comp);
1696:                }
1697:
1698:                public void actionPerformed(java.awt.event.ActionEvent e) {
1699:                    float inc = customGlassPane.getIncrement();
1700:                    if (inc >= 1.0f) {
1701:                        finish();
1702:                    } else {
1703:                        customGlassPane.setIncrement(inc + INCREMENT);
1704:                    }
1705:                }
1706:
1707:                private LiveComponentResizingGlassPane customGlassPane = null;
1708:
1709:                private LiveComponentResizingGlassPane getCustomGlassPane() {
1710:                    if (customGlassPane == null) {
1711:                        customGlassPane = new LiveComponentResizingGlassPane();
1712:                        customGlassPane.setOpaque(false);
1713:                    }
1714:                    return customGlassPane;
1715:                }
1716:
1717:                private class LiveComponentResizingGlassPane extends JPanel {
1718:                    private float inc = 0f;
1719:                    private Rectangle rect = new Rectangle();
1720:                    private Rectangle r2 = new Rectangle();
1721:                    private boolean changed = true;
1722:
1723:                    private void setIncrement(float inc) {
1724:                        this .inc = inc;
1725:                        changed = true;
1726:                        if (isShowing()) {
1727:                            if (comp.getParent() != this ) {
1728:                                add(comp);
1729:                                comp.setVisible(true);
1730:                            }
1731:                        }
1732:                        doLayout();
1733:                    }
1734:
1735:                    public void doLayout() {
1736:                        Rectangle r = getImageBounds();
1737:                        comp.setBounds(r.x, r.y, r.width, r.height);
1738:                    }
1739:
1740:                    private float getIncrement() {
1741:                        return inc;
1742:                    }
1743:
1744:                    private Rectangle getImageBounds() {
1745:                        if (!changed) {
1746:                            return rect;
1747:                        }
1748:                        Component c = tabDisplayer;
1749:                        r2.setBounds(0, 0, c.getWidth(), c.getHeight());
1750:
1751:                        Rectangle dispBounds = SwingUtilities.convertRectangle(
1752:                                c, r2, this );
1753:
1754:                        if (orientation == TabDisplayer.ORIENTATION_WEST) {
1755:                            rect.x = dispBounds.x + dispBounds.width;
1756:                            rect.y = dispBounds.y;
1757:                            rect.width = Math.round(inc * d.width);
1758:                            rect.height = dispBounds.height;
1759:                        } else if (orientation == TabDisplayer.ORIENTATION_EAST) {
1760:                            rect.width = Math.round(inc * d.width);
1761:                            rect.height = dispBounds.height;
1762:                            rect.x = dispBounds.x - rect.width;
1763:                            rect.y = dispBounds.y;
1764:                        } else if (orientation == TabDisplayer.ORIENTATION_SOUTH) {
1765:                            rect.width = dispBounds.width;
1766:                            rect.height = Math.round(inc * d.height);
1767:                            rect.x = dispBounds.x;
1768:                            rect.y = dispBounds.y - rect.height;
1769:                        } else if (orientation == TabDisplayer.ORIENTATION_NORTH) {
1770:                            rect.x = dispBounds.x;
1771:                            rect.y = dispBounds.y + dispBounds.height;
1772:                            rect.width = dispBounds.width;
1773:                            rect.height = Math.round(inc * d.height);
1774:                        }
1775:                        changed = false;
1776:                        return rect;
1777:                    }
1778:                }
1779:            }
1780:
1781:            //*** A bunch of options for testing
1782:
1783:            /** Sysprop to turn off all sliding effects */
1784:            static final boolean NO_EFFECTS = Boolean
1785:                    .getBoolean("nb.tabcontrol.no.fx"); //NOI18N
1786:            /** Sysprop to turn off scaling of the slide image */
1787:            static final boolean NO_SCALE = Boolean
1788:                    .getBoolean("nb.tabcontrol.fx.no.scaling"); //NOI18N
1789:            /** Sysprop to turn use SwingUtilities.paintComponent() instead of an image buffer for sliding effects */
1790:            static final boolean USE_SWINGPAINTING = Boolean
1791:                    .getBoolean("nb.tabcontrol.fx.swingpainting"); //NOI18N
1792:            /** Sysprop to turn add the component being scaled to the glasspane and alter its size on a 
1793:             * timer to accomplish growing the component */
1794:            static final boolean ADD_TO_GLASSPANE = Boolean
1795:                    .getBoolean("nb.tabcontrol.fx.use.resizing"); //NOI18N
1796:            /** For those who <strong>really</strong> love the sliding effect and want to see it on all
1797:             * tab controls of all types */
1798:            static final boolean EFFECTS_EVERYWHERE = Boolean
1799:                    .getBoolean("nb.tabcontrol.fx.everywhere")
1800:                    || Boolean.getBoolean("nb.tabcontrol.fx.gratuitous"); //NOI18N
1801:
1802:            /** Also have the scaled image be partially transparent as it's drawn */
1803:            static final boolean USE_ALPHA = Boolean
1804:                    .getBoolean("nb.tabcontrol.fx.use.alpha")
1805:                    || Boolean.getBoolean("nb.tabcontrol.fx.gratuitous"); //NOI18N
1806:
1807:            static boolean SYNCHRONOUS_PAINTING = Boolean
1808:                    .getBoolean("nb.tabcontrol.fx.synchronous"); //NOI18N
1809:
1810:            static float INCREMENT = 0.07f;
1811:
1812:            static int TIMER = 25;
1813:            static {
1814:                boolean gratuitous = Boolean
1815:                        .getBoolean("nb.tabcontrol.fx.gratuitous"); //NOI18N
1816:                String s = System.getProperty("nb.tabcontrol.fx.increment"); //NOI18N
1817:                if (s != null) {
1818:                    try {
1819:                        INCREMENT = Float.parseFloat(s);
1820:                    } catch (Exception e) {
1821:                        System.err.println("Bad float value specified: \"" + s
1822:                                + "\""); //NOI18N
1823:                    }
1824:                } else if (gratuitous) {
1825:                    INCREMENT = 0.02f;
1826:                }
1827:
1828:                s = System.getProperty("nb.tabcontrol.fx.timer"); //NOI18N
1829:                if (s != null) {
1830:                    try {
1831:                        TIMER = Integer.parseInt(s);
1832:                    } catch (Exception e) {
1833:                        System.err.println("Bad integer value specified: \""
1834:                                + s + "\""); //NOI18N
1835:                    }
1836:                } else if (gratuitous) {
1837:                    TIMER = 7;
1838:                }
1839:                if (gratuitous) {
1840:                    SYNCHRONOUS_PAINTING = true;
1841:                }
1842:            }
1843:
1844:            private static final class ForwardingMouseListener implements 
1845:                    MouseListener {
1846:                private final Container c;
1847:
1848:                public ForwardingMouseListener(Container c) {
1849:                    this .c = c;
1850:                }
1851:
1852:                public void mousePressed(MouseEvent me) {
1853:                    forward(me);
1854:                }
1855:
1856:                public void mouseReleased(MouseEvent me) {
1857:                    forward(me);
1858:                }
1859:
1860:                public void mouseClicked(MouseEvent me) {
1861:                    forward(me);
1862:                }
1863:
1864:                public void mouseEntered(MouseEvent me) {
1865:                    forward(me);
1866:                }
1867:
1868:                public void mouseExited(MouseEvent me) {
1869:                    forward(me);
1870:                }
1871:
1872:                private void forward(MouseEvent me) {
1873:                    MouseListener[] ml = c.getMouseListeners();
1874:                    if (ml.length == 0 || me.isConsumed()) {
1875:                        return;
1876:                    }
1877:                    MouseEvent me2 = SwingUtilities.convertMouseEvent(
1878:                            (Component) me.getSource(), me, c);
1879:
1880:                    for (int i = 0; i < ml.length; i++) {
1881:                        switch (me2.getID()) {
1882:                        case MouseEvent.MOUSE_ENTERED:
1883:                            ml[i].mouseEntered(me2);
1884:                            break;
1885:                        case MouseEvent.MOUSE_EXITED:
1886:                            ml[i].mouseExited(me2);
1887:                            break;
1888:                        case MouseEvent.MOUSE_PRESSED:
1889:                            ml[i].mousePressed(me2);
1890:                            break;
1891:                        case MouseEvent.MOUSE_RELEASED:
1892:                            ml[i].mouseReleased(me2);
1893:                            break;
1894:                        case MouseEvent.MOUSE_CLICKED:
1895:                            ml[i].mouseClicked(me2);
1896:                            break;
1897:                        default:
1898:                            assert false;
1899:                        }
1900:                    }
1901:                }
1902:
1903:            }
1904:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.