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


001:        /*
002:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003:         *
004:         * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005:         *
006:         * The contents of this file are subject to the terms of either the GNU
007:         * General Public License Version 2 only ("GPL") or the Common
008:         * Development and Distribution License("CDDL") (collectively, the
009:         * "License"). You may not use this file except in compliance with the
010:         * License. You can obtain a copy of the License at
011:         * http://www.netbeans.org/cddl-gplv2.html
012:         * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013:         * specific language governing permissions and limitations under the
014:         * License.  When distributing the software, include this License Header
015:         * Notice in each file and include the License file at
016:         * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
017:         * particular file as subject to the "Classpath" exception as provided
018:         * by Sun in the GPL Version 2 section of the License file that
019:         * accompanied this code. If applicable, add the following below the
020:         * License Header, with the fields enclosed by brackets [] replaced by
021:         * your own identifying information:
022:         * "Portions Copyrighted [year] [name of copyright owner]"
023:         *
024:         * Contributor(s):
025:         *
026:         * The Original Software is NetBeans. The Initial Developer of the Original
027:         * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028:         * Microsystems, Inc. All Rights Reserved.
029:         *
030:         * If you wish your version of this file to be governed by only the CDDL
031:         * or only the GPL Version 2, indicate your decision by adding
032:         * "[Contributor] elects to include this software in this distribution
033:         * under the [CDDL or GPL Version 2] license." If you do not indicate a
034:         * single choice of license, a recipient has the option to distribute
035:         * your version of this file under either the CDDL, the GPL Version 2 or
036:         * to extend the choice of license to its licensees as provided above.
037:         * However, if you add GPL Version 2 code and therefore, elected the GPL
038:         * Version 2 license, then the option applies only if the new code is
039:         * made subject to such option by the copyright holder.
040:         */
041:
042:        package org.netbeans.swing.tabcontrol;
043:
044:        import javax.accessibility.Accessible;
045:        import org.netbeans.swing.tabcontrol.event.TabActionEvent;
046:        import org.netbeans.swing.tabcontrol.plaf.DefaultTabbedContainerUI;
047:
048:        import javax.swing.*;
049:        import java.awt.*;
050:        import java.awt.event.AWTEventListener;
051:        import java.awt.event.ActionListener;
052:        import java.awt.event.KeyEvent;
053:        import java.awt.event.MouseEvent;
054:        import java.util.ArrayList;
055:        import java.util.Collections;
056:        import java.util.List;
057:        import javax.accessibility.AccessibleRole;
058:        import javax.swing.JComponent.AccessibleJComponent;
059:        import org.openide.util.NbBundle;
060:
061:        /**
062:         * A tabbed container similar to a JTabbedPane.  The tabbed container is a
063:         * simple container which contains two components - the tabs displayer, and the
064:         * content displayer.  The tabs displayer is the thing that actually draws the
065:         * tabs; the content displayer contains the components that are being shown.
066:         * <p>
067:         * The first difference from a JTabbedPane is that it is entirely model driven -
068:         * the tab contents are in a data model owned by the displayer.  It is not
069:         * strictly necessary for the contained components to even be installed in the
070:         * AWT hierarchy when not displayed.
071:         * <p>
072:         * Other differences are more flexibility in the way tabs are displayed by
073:         * completely separating the implementation and UI for that from that of
074:         * displaying the contents.
075:         * <p>
076:         * Other interesting aspects are the ability of TabDataModel to deliver complex,
077:         * granular events in a single pass with no information loss.  Generally, great
078:         * effort has been gone to to conflate nothing - that is, adding a component
079:         * does not equal selecting it does not equal changing focus, et. cetera,
080:         * leaving these decisions more in the hands of the user of the control.
081:         * <p>
082:         * It is possible to implement a subclass which provides the API of JTabbedPane,
083:         * making it a drop-in replacement.
084:         * <p>
085:         * There are several UI styles a <code>TabbedContainer</code> can have.  The type
086:         * is passed as an argument to the constructor (support for changing these on the
087:         * fly may be added in the future, but such a change is a very heavyweight operation,
088:         * and is only desirable to enable use of this component in its various permutations
089:         * inside GUI designers).  The following styles are supported:
090:         * <ul>
091:         * <li><b>TYPE_VIEW</b> - These are tabs such as the Explorer window has in NetBeans -
092:         * all tabs are always displayed, with the available space equally divided between them.</li>
093:         * <li><b>TYPE_EDITOR</b> - Scrolling tabs, coupled with control buttons and mouse wheel
094:         * support for scrolling the visible tabs, and a popup which displays a list of tabs.</li>
095:         * <li><b>TYPE_SLIDING</b> - Tabs which are displayed as buttons, and may provide a
096:         * fade or sliding effect when displayed.  For this style, a second click on the selected
097:         * tab will hide the selected tab (setting the selection model's selected index to -1).</li></ul>
098:         * <p>
099:         * <h4>Customizing the appearance of tabs</h4>
100:         * Tabs are customized by providing a different UI delegate for the tab displayer component,
101:         * via UIManager, in the same manner as any standard Swing component; for <code>TYPE_SLIDING</code>
102:         * tabs, simply implementing an alternate UI delegate for the buttons used to represent tabs
103:         * is all that is needed.
104:         *
105:         * <h4>Managing user events on tabs</h4>
106:         * When a user clicks a tab, the TabbedContainer will fire an action event to all of its listeners.
107:         * This action event will always be an instance of <code>TabActionEvent</code>, which can provide
108:         * the index of the tab that was pressed, and the command name of the action that was performed.
109:         * A client which wants to handle the event itself (for example, the asking a user if they want
110:         * to save data, and possibly vetoing the closing of a tab) may veto (or take full responsibility
111:         * for performing) the action by consuming the TabActionEvent.
112:         *
113:         *<h4>Indication of focus and the &quot;activated&quot; state</h4>
114:         * The property <code>active</code> is provided to allow a tabbed container to indicate that it
115:         * contains the currently focused component. However, no effort is made to track focus on the
116:         * part of the tabbed control - there is too much variability possible (for example, if
117:         * a component inside a tab opens a modal dialog, is the tab active or not?).  In fact, using
118:         * keyboard focus at all to manage the activated state of the component turns out to be a potent
119:         * source of hard-to-fix, hard-to-reproduce bugs (especially when components are being added
120:         * and removed, or hidden and shown or components which do not reliably produce focus events).
121:         * What NetBeans does to solve the problem in a reliable way is the following:
122:         * <ol>
123:         * <li>Use an AWT even listener to track mouse clicks, and when the mouse is clicked,
124:         *     <ul>
125:         *     <li>Find the ancestor that is a tabbed container (if any)</li>
126:         *     <li>Set the activated state appropriately on it and the previously active container</li>
127:         *     <li>Ensure that keyboard focus moves into that container</li>
128:         *     </ul>
129:         * <li>Block ctrl-tab style keyboard based focus traversal out of tabbed containers</li>
130:         * <li>Provide keyboard actions, with menu items, which will change to a different container,
131:         *     activating it</li>
132:         * </ol>
133:         * This may seem complicated, and it probably is overkill for a small application (as is this
134:         * tabbed control - it wasn't designed for a small application).  It's primary advantage is
135:         * that it works.
136:         *
137:         * @see TabDisplayer
138:         * @author Tim Boudreau, Dafe Simonek
139:         */
140:        public class TabbedContainer extends JComponent implements  Accessible {
141:            /**
142:             * UIManager key for the UI Delegate to be used by tabbed containers.
143:             */
144:            public static final String TABBED_CONTAINER_UI_CLASS_ID = "TabbedContainerUI"; //NOI18N
145:
146:            /**
147:             * Creates a &quot;view&quot; style displayer; typically this will have a
148:             * fixed width and a single row of tabs which get smaller as more tabs are
149:             * added, as seen in NetBeans&rsquo; Explorer window.
150:             */
151:            public static final int TYPE_VIEW = 0;
152:            /**
153:             * Creates a &quot;editor&quot; style displayer; typically this uses a
154:             * scrolling tabs UI for the tab displayer.  This is the most scalable of the available
155:             * UI styles - it can handle a very large number of tabs with minimal overhead, and
156:             * the standard UI implementations of it use a cell-renderer model for painting.
157:             */
158:            public static final int TYPE_EDITOR = 1;
159:
160:            /** Creates a &quot;sliding&quot; view, typically with tabs rendered as
161:             * buttons along the left, bottom or right edge, with no scrolling behavior for tabs.
162:             * Significant about this UI style is that re-clicking the selected tab will
163:             * cause the component displayed to be hidden.
164:             * <p>
165:             * This is the least scalable of the available UI types, and is intended primarily for
166:             * use with a small, fixed set of tabs.  By default, the position of the tab displayer
167:             * will be determined based on the proximity of the container to the edges of its
168:             * parent window.  This can be turned off by setting the client property
169:             * PROP_MANAGE_TAB_POSITION to Boolean.FALSE.
170:             */
171:            public static final int TYPE_SLIDING = 2;
172:
173:            /**
174:             * Creates a Toolbar-style displayer (the style used by the NetBeans Form Editor's
175:             * Component Inspector and a few other places in NetBeans).
176:             */
177:            public static final int TYPE_TOOLBAR = 3;
178:
179:            /**
180:             * Property fired when <code>setActive()</code> is called
181:             */
182:            public static final String PROP_ACTIVE = "active"; //NOI18N
183:
184:            /** Client property applicable only to TYPE_SLIDING tabs.  If set to 
185:             * Boolean.FALSE, the UI will not automatically try to determine a 
186:             * correct position for the tab displayer.
187:             */
188:            public static final String PROP_MANAGE_TAB_POSITION = "manageTabPosition";
189:
190:            /**
191:             * Action command indicating that the action event signifies the user
192:             * clicking the Close button on a tab.
193:             */
194:            public static final String COMMAND_CLOSE = "close"; //NOI18N
195:
196:            /**
197:             * Action command indicating that the action event fired signifies the user
198:             * selecting a tab
199:             */
200:            public static final String COMMAND_SELECT = "select"; //NOI18N
201:
202:            /** Action command indicating that a popup menu should be shown */
203:            public static final String COMMAND_POPUP_REQUEST = "popup"; //NOI18N
204:
205:            /** Command indicating a maximize (double-click) request */
206:            public static final String COMMAND_MAXIMIZE = "maximize"; //NOI18N
207:
208:            public static final String COMMAND_CLOSE_ALL = "closeAll"; //NOI18N
209:
210:            public static final String COMMAND_CLOSE_ALL_BUT_THIS = "closeAllButThis"; //NOI18N
211:
212:            public static final String COMMAND_ENABLE_AUTO_HIDE = "enableAutoHide"; //NOI18N
213:
214:            public static final String COMMAND_DISABLE_AUTO_HIDE = "disableAutoHide"; //NOI18N
215:
216:            public static final String COMMAND_TOGGLE_TRANSPARENCY = "toggleTransparency"; //NOI18N
217:
218:            //XXX support supressing close buttons
219:
220:            /**
221:             * The data model which contains information about the tabs, such as the
222:             * corresponding component, the icon and the tooltip.  Currently this is
223:             * assigned in the constructor and cannot be modified later, though this
224:             * could be supported in the future (with substantial effort).
225:             *
226:             * @see TabData
227:             * @see TabDataModel
228:             */
229:            private TabDataModel model;
230:
231:            /**
232:             * The type of this container, which determines what UI delegate is used for
233:             * the tab displayer
234:             */
235:            private final int type;
236:
237:            /**
238:             * Holds the value of the active property, determining if the displayer
239:             * should be painted with the focused or unfocused colors
240:             */
241:            private boolean active = false;
242:
243:            /**
244:             * Flag used to block the call to updateUI() from the superclass constructor
245:             * - at that time, none of our instance fields are set, so the UI can't yet
246:             * set up the tab displayer correctly
247:             */
248:            private boolean initialized = false;
249:
250:            /**
251:             * Utility field holding list of ActionListeners.
252:             */
253:            private transient List<ActionListener> actionListenerList;
254:
255:            /**
256:             * Content policy in which all components contained in the data model should immediately
257:             * be added to the AWT hierarchy at the time they appear in the data model.
258:             *
259:             * @see #setContentPolicy
260:             */
261:            public static final int CONTENT_POLICY_ADD_ALL = 1;
262:            /**
263:             * Content policy by which components contained in the data model are added to the AWT
264:             * hierarchy the first time they are shown, and remain their thereafter unless removed
265:             * from the data model.
266:             *
267:             * @see #setContentPolicy
268:             */
269:            public static final int CONTENT_POLICY_ADD_ON_FIRST_USE = 2;
270:            /**
271:             * Content policy by which components contained in the data model are added to the AWT
272:             * hierarchy the when they are shown, and removed immediately when the user changes tabs.
273:             */
274:            public static final int CONTENT_POLICY_ADD_ONLY_SELECTED = 3;
275:
276:            private int contentPolicy = DEFAULT_CONTENT_POLICY;
277:
278:            /** The default content policy, currently CONTENT_POLICY_ADD_ALL.  To facilitate experimentation with
279:             * different settings application-wide, set the system property &quot;nb.tabcontrol.contentpolicy&quot;
280:             * to 1, 2 or 3 for ADD_ALL, ADD_ON_FIRST_USE or ADD_ONLY_SELECTED, respectively (note other values
281:             * will throw an <code>Error</code>).  Do not manipulate this value at runtime, it will likely become
282:             * a final field in a future release.  It is a protected field only to ensure its inclusion in documentation.
283:             *
284:             * @see #setContentPolicy
285:             */
286:            protected static int DEFAULT_CONTENT_POLICY = CONTENT_POLICY_ADD_ALL;
287:
288:            /** The component converter which will tranlate TabData's from the model into
289:             * components. */
290:            private ComponentConverter converter = null;
291:
292:            /** Winsys info needed for tab control or null if not available */
293:            private WinsysInfoForTabbed winsysInfo = null;
294:
295:            @Deprecated
296:            private LocationInformer locationInformer = null;
297:
298:            /**
299:             * Create a new pane with the default model and tabs displayer
300:             */
301:            public TabbedContainer() {
302:                this (null, TYPE_VIEW);
303:            }
304:
305:            /**
306:             * Create a new pane with asociated model and the default tabs displayer
307:             */
308:            public TabbedContainer(TabDataModel model) {
309:                this (model, TYPE_VIEW);
310:            }
311:
312:            public TabbedContainer(int type) {
313:                this (null, type);
314:            }
315:
316:            /**
317:             * Create a new pane with the specified model and displayer type
318:             *
319:             * @param model The model
320:             */
321:            public TabbedContainer(TabDataModel model, int type) {
322:                this (model, type, (WinsysInfoForTabbed) null);
323:            }
324:
325:            /**
326:             * Deprecated, please use constructor with WinsysInfoForTabbed instead.
327:             */
328:            @Deprecated
329:            public TabbedContainer(TabDataModel model, int type,
330:                    LocationInformer locationInformer) {
331:                this (model, type, (WinsysInfoForTabbed) null);
332:                this .locationInformer = locationInformer;
333:            }
334:
335:            /**
336:             * Create a new pane with the specified model, displayer type and extra
337:             * information from winsys
338:             */
339:            public TabbedContainer(TabDataModel model, int type,
340:                    WinsysInfoForTabbed winsysInfo) {
341:                switch (type) {
342:                case TYPE_VIEW:
343:                case TYPE_EDITOR:
344:                case TYPE_SLIDING:
345:                case TYPE_TOOLBAR:
346:                    break;
347:                default:
348:                    throw new IllegalArgumentException("Unknown UI type: "
349:                            + type); //NOI18N
350:                }
351:                if (model == null) {
352:                    model = new DefaultTabDataModel();
353:                }
354:                this .model = model;
355:                this .type = Boolean.getBoolean("nb.tabcontrol.alltoolbar") ? TYPE_TOOLBAR
356:                        : type;
357:                this .winsysInfo = winsysInfo;
358:                initialized = true;
359:                updateUI();
360:                //A few borders and such will check this
361:                //@see org.netbeans.swing.plaf.gtk.AdaptiveMatteBorder
362:                putClientProperty("viewType", new Integer(type)); //NOI18N
363:            }
364:
365:            /**
366:             * Overridden as follows:  When called by the superclass constructor (before
367:             * the <code>type</code> field is set), it will simply return; the  
368:             * TabbedContainer constructor will call updateUI() explicitly later.
369:             * <p>
370:             * Will first search UIManager for a matching UI class.  If non-null
371:             * (by default it is set in the core/swing/plaf library), it will compare
372:             * the found class name with the current UI.  If they are a match, it
373:             * will call TabbedContainerUI.shouldReplaceUI() to decide whether to
374:             * actually do anything or not (in most cases it would just replace an
375:             * instance of DefaultTabbedContainerUI with another one; but this call
376:             * allows DefaultTabbedContainerUI.uichange() to update the tab displayer
377:             * as needed).
378:             * <p>
379:             * If no UIManager UI class is defined, this method will silently use an
380:             * instance of DefaultTabbedContainerUI.
381:             */
382:            @Override
383:            public void updateUI() {
384:                if (!initialized) {
385:                    //Block the superclass call to updateUI(), which comes before the
386:                    //field is set to tell if we are a view tab control or an editor
387:                    //tab control - the UI won't be able to set up the tab displayer
388:                    //correctly until this is set.
389:                    return;
390:                }
391:                TabbedContainerUI ui = null;
392:                String UIClass = (String) UIManager.get(getUIClassID());
393:                if (getUI() != null
394:                        && (getUI().getClass().getName().equals(UIClass) | UIClass == null)) {
395:                    if (!getUI().shouldReplaceUI()) {
396:                        return;
397:                    }
398:                }
399:
400:                if (UIClass != null) { //Avoid a stack trace
401:                    try {
402:                        ui = (TabbedContainerUI) UIManager.getUI(this );
403:                    } catch (Error e) {
404:                        //do nothing
405:                    }
406:                }
407:                if (ui != null) {
408:                    setUI(ui);
409:                } else {
410:                    setUI(DefaultTabbedContainerUI.createUI(this ));
411:                }
412:            }
413:
414:            /**
415:             * Get the type of this displayer - it is either TYPE_EDITOR or TYPE_VIEW.
416:             * This property is set in the constructor and is immutable
417:             */
418:            public final int getType() {
419:                return type;
420:            }
421:
422:            /**
423:             * Returns <code>TabbedContainer.TABBED_CONTAINER_UI_CLASS_ID</code>
424:             */
425:            @Override
426:            public String getUIClassID() {
427:                return TABBED_CONTAINER_UI_CLASS_ID;
428:            }
429:
430:            /** Get the ui delegate for this component */
431:            public TabbedContainerUI getUI() {
432:                return (TabbedContainerUI) ui;
433:            }
434:
435:            /**
436:             * Set the converter that converts user objects in the data model into
437:             * components to display.  If set to null (the default), the user object
438:             * at the selected index in the data model will be cast as an instance
439:             * of JComponent when searching for what to show for a given tab.  
440:             * <p>
441:             * For use cases where a single component is to be displayed for more
442:             * than one tab, just reconfigured when the selection changes, simply
443:             * supply a ComponentConverter.Fixed with the component that should be
444:             * used for all tabs.
445:             */
446:            public final void setComponentConverter(ComponentConverter cc) {
447:                ComponentConverter old = converter;
448:                converter = cc;
449:                if (old instanceof  ComponentConverter.Fixed
450:                        && cc instanceof  ComponentConverter.Fixed) {
451:                    List<TabData> l = getModel().getTabs();
452:                    if (!l.isEmpty()) {
453:                        TabData[] td = l.toArray(new TabData[0]);
454:                        getModel().setTabs(new TabData[0]);
455:                        getModel().setTabs(td);
456:                    }
457:                }
458:            }
459:
460:            /** Get the component converter which is used to fetch a component
461:             * corresponding to an element in the data model.  If the value has
462:             * not been set, it will use ComponentConverter.DEFAULT, which simply
463:             * delegates to TabData.getComponent(). 
464:             */
465:            public final ComponentConverter getComponentConverter() {
466:                if (converter != null) {
467:                    return converter;
468:                }
469:                return ComponentConverter.DEFAULT;
470:            }
471:
472:            /** Experimental property - alter the policy by which the components in
473:             * the model are added to the container.  This may not remain suppported.
474:             * If used, it should be called before populating the data model.
475:             */
476:            public final void setContentPolicy(int i) {
477:                switch (i) {
478:                case CONTENT_POLICY_ADD_ALL:
479:                case CONTENT_POLICY_ADD_ON_FIRST_USE:
480:                case CONTENT_POLICY_ADD_ONLY_SELECTED:
481:                    break;
482:                default:
483:                    throw new IllegalArgumentException(
484:                            "Unknown content policy: " + i);
485:                }
486:
487:                if (i != contentPolicy) {
488:                    int old = contentPolicy;
489:                    contentPolicy = i;
490:                    firePropertyChange("contentPolicy", old, i); //NOI18N
491:                }
492:            }
493:
494:            /** Determine the policy by which components are added to the container.
495:             * There are various pros and cons to each:
496:             * <ul>
497:             * <li>CONTENT_POLICY_ADD_ALL - All components in the data model are
498:             * automatically added to the container, and whenever the model changes,
499:             * components are added and removed as need be.  This is less scalable,
500:             * but absolutely reliable</li>
501:             * <li>CONTENT_POLICY_ADD_ON_FIRST_USE - Components are not added to the
502:             * container until the first time they are used, and then they remain in
503:             * the AWT hierarchy until their TabData elements are removed from the 
504:             * model.  This is more scalable, and probably has some startup time 
505:             * benefits</li>
506:             * <li>CONTENT_POLICY_ADD_ONLY_SELECTED - The only component that will
507:             * ever be in the AWT hierarchy is the one that is being displayed.  This
508:             * is safest in the case that heavyweight AWT components may be used </li>
509:             * </ul>
510:             */
511:            public int getContentPolicy() {
512:                return contentPolicy;
513:            }
514:
515:            @Override
516:            public boolean isValidateRoot() {
517:                return true;
518:            }
519:
520:            public boolean isPaintingOrigin() {
521:                return true;
522:            }
523:
524:            public void setToolTipTextAt(int index, String toolTip) {
525:                //Do this quietly - no notification is needed
526:                TabData tabData = getModel().getTab(index);
527:                if (tabData != null) {
528:                    tabData.tip = toolTip;
529:                }
530:            }
531:
532:            /**
533:             * Get the data model that represents the tabs this component has.  All
534:             * programmatic manipulation of tabs should be done via the data model.
535:             *
536:             * @return The model
537:             */
538:            public final TabDataModel getModel() {
539:                return model;
540:            }
541:
542:            /**
543:             * Get the selection model.  The selection model tracks the index of the
544:             * selected component, modifying this index appropriately when tabs are
545:             * added or removed.
546:             *
547:             * @return The model
548:             */
549:            public final SingleSelectionModel getSelectionModel() {
550:                return getUI().getSelectionModel();
551:            }
552:
553:            /**
554:             * Fetch the rectangle of the tab for a given index, in the coordinate space
555:             * of this component, by reconfiguring the passed rectangle object
556:             */
557:            public final Rectangle getTabRect(int index, final Rectangle r) {
558:                return getUI().getTabRect(index, r);
559:            }
560:
561:            /** Gets the index of the tab at point p, or -1 if no tab is there */
562:            public int tabForCoordinate(Point p) {
563:                return getUI().tabForCoordinate(p);
564:            }
565:
566:            /**
567:             * Set the &quot;active&quot; state of this tab control - this affects the
568:             * way the tabs are displayed, to indicate focus.  Note that this method
569:             * will <i>never</i> be called automatically in stand-alone use of
570:             * TabbedContainer. While one would expect a component gaining keyboard
571:             * focus to be a good determinant, it actually turns out to be a potent
572:             * source of subtle and hard-to-fix bugs.
573:             * <p/>
574:             * NetBeans uses an AWTEventListener to track mouse clicks, and allows
575:             * components to become activated only via a mouse click or via a keyboard
576:             * action or menu item which activates the component.  This approach is far
577:             * more robust and is the recommended usage pattern.
578:             */
579:            public final void setActive(boolean active) {
580:                if (active != this .active) {
581:                    this .active = active;
582:                    firePropertyChange(PROP_ACTIVE, !active, active);
583:                }
584:            }
585:
586:            /**
587:             * Cause the tab at the specified index to blink or otherwise suggest that
588:             * the user should click it.
589:             */
590:            public final void requestAttention(int tab) {
591:                getUI().requestAttention(tab);
592:            }
593:
594:            public final void cancelRequestAttention(int tab) {
595:                getUI().cancelRequestAttention(tab);
596:            }
597:
598:            /**
599:             * Cause the specified tab to blink or otherwisse suggest that the user should
600:             * click it.
601:             */
602:            public final boolean requestAttention(TabData data) {
603:                int idx = getModel().indexOf(data);
604:                boolean result = idx >= 0;
605:                if (result) {
606:                    requestAttention(idx);
607:                }
608:                return result;
609:            }
610:
611:            public final void cancelRequestAttention(TabData data) {
612:                int idx = getModel().indexOf(data);
613:                if (idx != -1) {
614:                    cancelRequestAttention(idx);
615:                }
616:            }
617:
618:            /**
619:             * Determine if this component thinks it is &quot;active&quot;, which
620:             * affects how the tabs are painted - typically used to indicate that
621:             * keyboard focus is somewhere within the component
622:             */
623:            public final boolean isActive() {
624:                return active;
625:            }
626:
627:            /**
628:             * Register an ActionListener.  TabbedContainer and TabDisplayer guarantee
629:             * that the type of event fired will always be TabActionEvent.  There are
630:             * two special things about TabActionEvent: <ol> <li>There are methods on
631:             * TabActionEvent to find the index of the tab the event was performed on,
632:             * and if present, retrieve the mouse event that triggered it, for clients
633:             * that wish to provide different handling for different mouse buttons</li>
634:             * <li>TabActionEvents can be consumed.  If a listener consumes the event,
635:             * the UI will take no action - the selection will not be changed, the tab
636:             * will not be closed.  Consuming the event means taking responsibility for
637:             * doing whatever would normally happen automatically.  This is useful for,
638:             * for example, showing a dialog and possibly aborting closing a tab if it
639:             * contains unsaved data, for instance.</li> </ol> Action events will be
640:             * fired <strong>before</strong> any action has been taken to alter the
641:             * state of the control to match the action, so that they may be vetoed or
642:             * modified by consuming the event.
643:             *
644:             * @param listener The listener to register.
645:             */
646:            public final synchronized void addActionListener(
647:                    ActionListener listener) {
648:                if (actionListenerList == null) {
649:                    actionListenerList = new ArrayList<ActionListener>();
650:                }
651:                actionListenerList.add(listener);
652:            }
653:
654:            /**
655:             * Remove an action listener.
656:             *
657:             * @param listener The listener to remove.
658:             */
659:            public final synchronized void removeActionListener(
660:                    ActionListener listener) {
661:                if (actionListenerList != null) {
662:                    actionListenerList.remove(listener);
663:                    if (actionListenerList.isEmpty()) {
664:                        actionListenerList = null;
665:                    }
666:                }
667:            }
668:
669:            /**
670:             * Used by the UI to post action events for selection and close operations.
671:             * If the event is consumed, the UI should take no action to change the
672:             * selection or close the tab, and will presume that the receiver of the
673:             * event is handling performing whatever action is appropriate.
674:             *
675:             * @param event The event to be fired
676:             */
677:            protected final void postActionEvent(TabActionEvent event) {
678:                List<ActionListener> list;
679:                synchronized (this ) {
680:                    if (actionListenerList == null)
681:                        return;
682:                    list = Collections.unmodifiableList(actionListenerList);
683:                }
684:                for (ActionListener l : list) {
685:                    l.actionPerformed(event);
686:                }
687:            }
688:
689:            public void setIconAt(int index, Icon icon) {
690:                getModel().setIcon(index, icon);
691:            }
692:
693:            public void setTitleAt(int index, String title) {
694:                getModel().setText(index, title);
695:            }
696:
697:            /** Create an image of a single tab, suitable for use in drag and drop operations */
698:            public Image createImageOfTab(int idx) {
699:                return getUI().createImageOfTab(idx);
700:            }
701:
702:            /** Get the number of tabs.  Equivalent to <code>getModel().size()</code> */
703:            public int getTabCount() {
704:                return getModel().size();
705:            }
706:
707:            /**
708:             * Set whether or not close buttons should be shown.
709:             * This can be defaulted with the system property
710:             * <code>nb.tabs.suppressCloseButton</code>; if the system
711:             * property is not set, the default is true.
712:             */
713:            public final void setShowCloseButton(boolean val) {
714:                boolean wasShow = isShowCloseButton();
715:                if (val != wasShow) {
716:                    getUI().setShowCloseButton(val);
717:                    firePropertyChange("showCloseButton", wasShow, val);
718:                }
719:            }
720:
721:            /**
722:             * Determine whether or not close buttons are being shown. 
723:             */
724:            public final boolean isShowCloseButton() {
725:                return getUI().isShowCloseButton();
726:            }
727:
728:            /** Get the index of a component */
729:            public int indexOf(Component comp) {
730:                int max = getModel().size();
731:                TabDataModel mdl = getModel();
732:                for (int i = 0; i < max; i++) {
733:                    if (getComponentConverter().getComponent(mdl.getTab(i)) == comp) {
734:                        return i;
735:                    }
736:                }
737:                return -1;
738:            }
739:
740:            /** The index at which a tab should be inserted if a drop operation
741:             * occurs at this point.
742:             *
743:             * @param location A point anywhere on the TabbedContainer
744:             * @return A tab index, or -1
745:             */
746:            public int dropIndexOfPoint(Point location) {
747:                return getUI().dropIndexOfPoint(location);
748:            }
749:
750:            /**
751:             * Get a shape appropriate for drawing on the window's glass pane to indicate
752:             * where a component should appear in the tab order if it is dropped here.
753:             *
754:             * @param dragged An object being dragged, or null. The object may be an instance
755:             *        of <code>TabData</code> or <code>Component</code>, in which case a check
756:             *        will be done of whether the dragged object is already in the data model,
757:             *        so that attempts to drop the object over the place it already is in the
758:             *        model will always return the exact indication of that tab's position.
759:             *
760:             * @param location A point
761:             * @return Drop indication drawing
762:             */
763:            public Shape getDropIndication(Object dragged, Point location) {
764:                int ix;
765:                if (dragged instanceof  Component) {
766:                    ix = indexOf((Component) dragged);
767:                } else if (dragged instanceof  TabData) {
768:                    ix = getModel().indexOf((TabData) dragged);
769:                } else {
770:                    ix = -1;
771:                }
772:
773:                int over = dropIndexOfPoint(location);
774:
775:                if (over < 0) { // XXX PENDING The tab is not found, later simulate the last one.
776:                    Rectangle r = getBounds();
777:                    r.setLocation(0, 0);
778:                    return r;
779:                }
780:                /*
781:                if (over == ix || (over == ix + 1 && ix != -1 && over < getModel().size())) { //+1 - dropping on the next tab will put it in the same place
782:                    return getUI().getExactTabIndication(over);
783:                } else {
784:                    return getUI().getInsertTabIndication(over);
785:                }
786:                 */
787:                if (over == ix && ix != -1) {
788:                    return getUI().getExactTabIndication(over);
789:                } else {
790:                    return getUI().getInsertTabIndication(over);
791:                }
792:            }
793:
794:            @Deprecated
795:            public LocationInformer getLocationInformer() {
796:                return locationInformer;
797:            }
798:
799:            public WinsysInfoForTabbed getWinsysInfo() {
800:                return winsysInfo;
801:            }
802:
803:            static {
804:                //Support for experimenting with different content policies in NetBeans
805:                String s = System.getProperty("nb.tabcontrol.contentpolicy"); //NOI18N
806:                if (s != null) {
807:                    try {
808:                        DEFAULT_CONTENT_POLICY = Integer.parseInt(s);
809:                        switch (DEFAULT_CONTENT_POLICY) {
810:                        case CONTENT_POLICY_ADD_ALL:
811:                        case CONTENT_POLICY_ADD_ON_FIRST_USE:
812:                        case CONTENT_POLICY_ADD_ONLY_SELECTED:
813:                            System.err.println("Using custom content policy: "
814:                                    + DEFAULT_CONTENT_POLICY);
815:                            break;
816:                        default:
817:                            throw new Error("Bad value for default content "
818:                                    + "policy: " + s + " only values 1, 2 or 3"
819:                                    + "are meaningful"); //NOI18N
820:                        }
821:                        System.err.println("Default content policy is "
822:                                + DEFAULT_CONTENT_POLICY);
823:                    } catch (Exception e) {
824:                        System.err.println("Error parsing default content "
825:                                + "policy: \"" + s + "\""); //NOI18N
826:                    }
827:                }
828:            }
829:
830:            @Override
831:            public javax.accessibility.AccessibleContext getAccessibleContext() {
832:                if (null == accessibleContext) {
833:                    accessibleContext = new AccessibleJComponent() {
834:                        @Override
835:                        public AccessibleRole getAccessibleRole() {
836:                            return AccessibleRole.PAGE_TAB_LIST;
837:                        }
838:                    };
839:
840:                    accessibleContext.setAccessibleName(NbBundle.getMessage(
841:                            TabbedContainer.class, "ACS_TabbedContainer"));
842:                    accessibleContext.setAccessibleDescription(NbBundle
843:                            .getMessage(TabbedContainer.class,
844:                                    "ACSD_TabbedContainer"));
845:                }
846:
847:                return accessibleContext;
848:            }
849:
850:            //+++++++++++++++++++++++++
851:            //Begin: Transparency support 
852:            //+++++++++++++++++++++++++
853:            private static final float ALPHA_TRESHOLD = 0.2f;
854:            private float currentAlpha = 1.0f;
855:
856:            /**
857:             * @return True if the container is transparent, i.e. painted if Alpha set to 0.2 or less.
858:             */
859:            public boolean isTransparent() {
860:                return isSliding() && currentAlpha <= ALPHA_TRESHOLD;
861:            }
862:
863:            /**
864:             * Turn container transparency on/off
865:             * @param transparent True to make the container transparent
866:             */
867:            public void setTransparent(boolean transparent) {
868:                if (!isSliding()) {
869:                    //support only slided-in windows
870:                    throw new IllegalStateException(
871:                            "Transparency is supported for sliding windows only.");
872:                }
873:                float oldAlpha = currentAlpha;
874:                currentAlpha = transparent ? ALPHA_TRESHOLD : 1.0f;
875:                if (oldAlpha != currentAlpha) {
876:                    repaint();
877:                }
878:            }
879:
880:            AWTEventListener awtListener = null;
881:
882:            private AWTEventListener getAWTListener() {
883:                if (null == awtListener) {
884:                    awtListener = new AWTEventListener() {
885:                        public void eventDispatched(AWTEvent event) {
886:                            if (event.getID() == MouseEvent.MOUSE_PRESSED) {
887:                                //ignore mouse clicks outside this container
888:                                if (event.getSource() instanceof  Component
889:                                        && !SwingUtilities.isDescendingFrom(
890:                                                (Component) event.getSource(),
891:                                                TabbedContainer.this ))
892:                                    return;
893:                                if (((MouseEvent) event).getButton() != MouseEvent.BUTTON3)
894:                                    setTransparent(false);
895:                            } else if (event.getID() == KeyEvent.KEY_PRESSED) {
896:                                KeyEvent ke = (KeyEvent) event;
897:                                //TODO make shortcut configurable
898:                                if (ke.getKeyCode() == KeyEvent.VK_NUMPAD0
899:                                        && ke.isControlDown()) {
900:                                    setTransparent(!isTransparent());
901:                                    ke.consume();
902:                                    return;
903:                                }
904:                                if (!(ke.getKeyCode() == KeyEvent.VK_ALT
905:                                        || ke.getKeyCode() == KeyEvent.VK_SHIFT
906:                                        || ke.getKeyCode() == KeyEvent.VK_META || ke
907:                                        .getKeyCode() == KeyEvent.VK_CONTROL)) {
908:                                    setTransparent(false);
909:                                }
910:                            } else if (event.getID() == MouseEvent.MOUSE_PRESSED) {
911:                                setTransparent(false);
912:                            } else if (event.getID() == KeyEvent.KEY_PRESSED) {
913:                                KeyEvent ke = (KeyEvent) event;
914:                                if (!(ke.getKeyCode() == KeyEvent.VK_ALT || ke
915:                                        .getKeyCode() == KeyEvent.VK_SHIFT))
916:                                    setTransparent(false);
917:                            }
918:                        }
919:                    };
920:                }
921:                return awtListener;
922:            }
923:
924:            /**
925:             * @return True if the container holds slided-in window.
926:             */
927:            private boolean isSliding() {
928:                boolean res = false;
929:                if (getModel().size() == 1) {
930:                    Component c = getModel().getTab(0).getComponent();
931:                    if (c instanceof  JComponent) {
932:                        Object val = ((JComponent) c)
933:                                .getClientProperty("isSliding"); //NOI18N
934:                        res = null != val && val instanceof  Boolean
935:                                && ((Boolean) val).booleanValue();
936:                    }
937:                }
938:                return res;
939:            }
940:
941:            @Override
942:            public void addNotify() {
943:                super .addNotify();
944:                if (isSliding()) {
945:                    //register AWT listener in case the inner top component has its only mouse listener
946:                    Toolkit.getDefaultToolkit().addAWTEventListener(
947:                            getAWTListener(),
948:                            MouseEvent.MOUSE_WHEEL_EVENT_MASK
949:                                    + MouseEvent.MOUSE_EVENT_MASK
950:                                    + KeyEvent.KEY_EVENT_MASK);
951:                }
952:            }
953:
954:            @Override
955:            public void removeNotify() {
956:                if (null != awtListener) {
957:                    Toolkit.getDefaultToolkit().removeAWTEventListener(
958:                            awtListener);
959:                    awtListener = null;
960:                }
961:                super .removeNotify();
962:                currentAlpha = 1.0f;
963:            }
964:
965:            @Override
966:            public void paint(Graphics g) {
967:                if (isSliding() && currentAlpha != 1.0f) {
968:                    Graphics2D g2d = (Graphics2D) g;
969:                    Composite oldComposite = g2d.getComposite();
970:                    g2d.setComposite(AlphaComposite.getInstance(
971:                            AlphaComposite.SRC_OVER, currentAlpha));
972:                    super .paint(g);
973:                    g2d.setComposite(oldComposite);
974:                } else {
975:                    super .paint(g);
976:                }
977:            }
978:            //+++++++++++++++++++++++++
979:            //End: Transparency support 
980:            //+++++++++++++++++++++++++    
981:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.