KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > openide > explorer > propertysheet > PSheet


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19 package org.openide.explorer.propertysheet;
20
21 import org.openide.nodes.Node;
22 import org.openide.util.NbBundle;
23
24 import java.awt.Color JavaDoc;
25 import java.awt.Component JavaDoc;
26 import java.awt.Container JavaDoc;
27 import java.awt.Insets JavaDoc;
28 import java.awt.Point JavaDoc;
29 import java.awt.event.ActionEvent JavaDoc;
30 import java.awt.event.KeyEvent JavaDoc;
31 import java.awt.event.MouseEvent JavaDoc;
32 import java.awt.event.MouseListener JavaDoc;
33
34 import java.util.Arrays JavaDoc;
35
36 import javax.swing.AbstractAction JavaDoc;
37 import javax.swing.BorderFactory JavaDoc;
38 import javax.swing.JComponent JavaDoc;
39 import javax.swing.JPanel JavaDoc;
40 import javax.swing.JScrollPane JavaDoc;
41 import javax.swing.JSplitPane JavaDoc;
42 import javax.swing.JTable JavaDoc;
43 import javax.swing.JViewport JavaDoc;
44 import javax.swing.KeyStroke JavaDoc;
45 import javax.swing.SwingUtilities JavaDoc;
46 import javax.swing.UIManager JavaDoc;
47 import javax.swing.event.ChangeEvent JavaDoc;
48 import javax.swing.event.ChangeListener JavaDoc;
49 import javax.swing.plaf.ViewportUI JavaDoc;
50
51 import org.netbeans.modules.openide.explorer.TabbedContainerBridge;
52
53
54 /**
55  * UI handling portion of the property sheet - handles installing/uninstalling
56  * the description area, the tabbed container, etc. automatically. AddImpl
57  * is overridden to always do the correct thing in terms of what is added -
58  * if you add a description panel, it will automatically be wrapped in a
59  * JSplitPane and the table moved inside that; if a tab control is added,
60  * the split pane, if present, or the scroll pane if not, will automatically
61  * be set as the inner component of the SheetTabbedPane, etc. Adds can
62  * happen in any order.
63  * <p>
64  * This class contains no PropertySheet specific logic (and it should stay
65  * that way), only the code that manages toggling between the states of
66  * having a description panel, having tabs, etc. This can be handled quite
67  * transparently through setState().
68  * <p>
69  * This class contains a considerable amount of component management logic;
70  * however, it is all done in the simplest and most straightforward way
71  * possible (with the exception that org.netbeans.swing.TabControl is accessed
72  * through a bridge via Lookup, because OpenIDE may not use module code
73  * directly).
74  * The goal is to a., make the component management as bulletproof, readable
75  * and debuggable as possible. So this class should provide accessor methods
76  * to manipulate its child components, but under no circumstances should
77  * external code ever reference any of its internal components directly -
78  * only accessor methods on this class should be used for such purposes.
79  *
80  *
81  * @author Tim Boudreau
82  */

83 class PSheet extends JPanel JavaDoc implements MouseListener JavaDoc {
84     public final static int STATE_HAS_DESCRIPTION = 1;
85     public final static int STATE_HAS_TABS = 2;
86     private int addCount = 0;
87     private String JavaDoc description = ""; //NOI18N
88
private String JavaDoc title = ""; //NOI18N
89
private SelectionAndScrollPositionManager manager = new SelectionAndScrollPositionManager();
90     private boolean adjusting = false;
91     private boolean helpEnabled = true;
92     private boolean marginPainted = !PropUtils.neverMargin;
93     private Color JavaDoc marginColor = UIManager.getColor("controlShadow");
94     private String JavaDoc emptyString = "THIS IS A BUG"; //NOI18N
95
private Boolean JavaDoc firstSplit = null;
96     private Object JavaDoc[] tabbedContainerObjects = new String JavaDoc[] { "Hello", "World", "This", "Is", "Me" };
97     private String JavaDoc[] tabbedContainerTitles = new String JavaDoc[] { "Tab 1", "Tab 2", "Tab 3", "Tab 4", "Tab 5" };
98     private ChangeListener JavaDoc selectionListener = null;
99
100     public PSheet() {
101         getInputMap(WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(
102             KeyStroke.getKeyStroke(KeyEvent.VK_F10, KeyEvent.SHIFT_DOWN_MASK), "popup"
103         ); //NOI18N
104

105         getActionMap().put("popup", new PopupAction()); //NOI18N
106
getActionMap().put("PreviousViewAction", new SwitchTabAction(-1)); //NOI18N
107
getActionMap().put("NextViewAction", new SwitchTabAction(1)); //NOI18N
108
}
109
110     SelectionAndScrollPositionManager manager() {
111         return manager;
112     }
113
114     public void adjustForName(String JavaDoc nodeName) {
115         adjusting = true;
116
117         try {
118             JComponent JavaDoc comp = findTabbedContainer();
119             String JavaDoc tabname = null;
120
121             if (comp != null) {
122                 boolean success = false;
123                 
124                 //first try to keep the last used property group
125
tabname = manager().getLastSelectedGroupName();
126                 if( tabname != null && tabname.length() > 0 ) {
127                     success = TabbedContainerBridge.getDefault().setSelectionByName(comp, tabname);
128                 }
129                 
130                 //now try if there's a stored property group for the new node
131
if( !success ) {
132                 tabname = manager().getGroupNameForNodeName(nodeName);
133                     if( tabname != null && tabname.length() > 0 ) {
134                         success = TabbedContainerBridge.getDefault().setSelectionByName(comp, tabname);
135                     }
136                 }
137
138                 //just use default property group
139
if( !success ) {
140                     tabname = PropUtils.basicPropsTabName(); // use basic tab
141
success = TabbedContainerBridge.getDefault().setSelectionByName(comp, tabname);
142                 }
143
144                 if (success) {
145                     if (selectionListener != null) {
146                         ChangeEvent JavaDoc ce = new ChangeEvent JavaDoc(this);
147                         selectionListener.stateChanged(ce);
148                     }
149                 }
150             }
151
152             JScrollPane JavaDoc jsc = findScrollPane();
153
154             if (jsc != null) {
155                 String JavaDoc s = (tabname == null) ? manager().getCurrentNodeName() : tabname;
156
157                 if (s != null) { //Will be null the very first time
158

159                     int pos = manager().getScrollPositionForNodeName(s);
160
161                     if ((pos >= 0) && (pos < jsc.getVerticalScrollBar().getModel().getMaximum())) {
162                         jsc.getVerticalScrollBar().getModel().setValue(pos);
163                     }
164                 }
165             }
166         } finally {
167             adjusting = false;
168         }
169     }
170
171     public boolean isAdjusting() {
172         return adjusting;
173     }
174
175     public void storeScrollAndTabInfo() {
176         JComponent JavaDoc comp = findTabbedContainer();
177         String JavaDoc tab = null;
178         String JavaDoc node = manager().getCurrentNodeName();
179         String JavaDoc lastTab = manager().getLastSelectedGroupName();
180
181         if (node != null) {
182             if (comp != null) {
183                 tab = TabbedContainerBridge.getDefault().getCurrentSelectedTabName(comp);
184
185                 if (tab != null) {
186                     manager().storeLastSelectedGroup(tab);
187                 }
188             }
189
190             JScrollPane JavaDoc jsc = findScrollPane();
191
192             if (jsc != null) {
193                 int pos = jsc.getVerticalScrollBar().getModel().getValue();
194                 String JavaDoc nm = (lastTab != null) ? lastTab : ((tab != null) ? tab : node);
195                 manager().storeScrollPosition(pos, nm);
196             }
197         }
198     }
199
200     /**
201      * Set the description to be displayed in the description panel. If the
202      * description panel is not visible, the value will be cached and applied
203      * the next time it is made visible.
204      */

205     public void setDescription(String JavaDoc title, String JavaDoc txt) {
206         this.description = txt;
207         this.title = title;
208
209         DescriptionComponent desc = findDescriptionComponent();
210
211         if (desc != null) {
212             desc.setDescription(title, txt);
213         }
214     }
215
216     /**
217      * Set whether or not the help button in the description component should
218      * be enabled.
219      */

220     public void setHelpEnabled(boolean val) {
221         if (helpEnabled != val) {
222             helpEnabled = val;
223
224             DescriptionComponent desc = findDescriptionComponent();
225
226             if (desc != null) {
227                 desc.setHelpEnabled(val);
228             }
229         }
230     }
231
232     /** Set whether or not the margin should be painted in the viewport */
233     public void setMarginPainted(boolean val) {
234         if (marginPainted != val) {
235             marginPainted = val;
236
237             MarginViewportUI ui = findMVUI();
238
239             if (ui != null) {
240                 ui.setMarginPainted(val);
241             }
242         }
243     }
244
245     /** Set the color of the margin */
246     public void setMarginColor(Color JavaDoc c) {
247         if (!c.equals(marginColor)) {
248             marginColor = c;
249
250             MarginViewportUI ui = findMVUI();
251
252             if (ui != null) {
253                 ui.setMarginColor(c);
254             }
255         }
256     }
257
258     /** Set the string that should be painted when the table has 0 height */
259     public void setEmptyString(String JavaDoc s) {
260         if (!s.equals(emptyString)) {
261             emptyString = s;
262
263             MarginViewportUI ui = findMVUI();
264
265             if (ui != null) {
266                 ui.setEmptyString(s);
267             }
268         }
269     }
270
271     /**
272      * Find the MarginViewportUI owned by the scrollpane, to set up
273      * colors, margin, empty string */

274     private MarginViewportUI findMVUI() {
275         MarginViewportUI result = null;
276         JScrollPane JavaDoc pane = findScrollPane();
277
278         if (pane != null) {
279             ViewportUI JavaDoc ui = pane.getViewport().getUI();
280
281             if (ui instanceof MarginViewportUI) {
282                 result = (MarginViewportUI) ui;
283             } else {
284                 //L&F changed or something such
285
result = (MarginViewportUI) MarginViewportUI.createUI(pane.getViewport());
286                 pane.getViewport().setUI(result);
287             }
288         }
289
290         return result;
291     }
292
293     /**
294      * Overridden to handle our layout requirements
295      */

296     public void doLayout() {
297         Component JavaDoc[] c = getComponents();
298
299         if (c.length > 0 && getWidth() >= 0 && getHeight() >= 0) {
300             Insets JavaDoc ins = getInsets();
301             c[0].setBounds(ins.left, ins.top, getWidth() - (ins.right + ins.left), getHeight() - ins.top + ins.bottom);
302
303             if (c[0] instanceof JSplitPane JavaDoc && Boolean.TRUE.equals(firstSplit)) {
304                 JSplitPane JavaDoc pane = (JSplitPane JavaDoc) c[0];
305                 pane.setDividerLocation(0.80f);
306                 pane.resetToPreferredSizes();
307
308                 JComponent JavaDoc dc = findDescriptionComponent();
309
310                 if (dc != null) {
311                     if (dc.getHeight() > 0) {
312                         firstSplit = Boolean.FALSE;
313                     }
314                 } else {
315                     firstSplit = Boolean.FALSE;
316                 }
317             }
318
319             if (c.length > 1) {
320                 throw new IllegalStateException JavaDoc("Hmm, something is wrong: " + Arrays.asList(c));
321             }
322         }
323     }
324
325     /** Transfers focus to the table */
326     public void requestFocus() {
327         JScrollPane JavaDoc jsc = findScrollPane();
328
329         if ((jsc != null) && (jsc.getViewport().getView() != null)) {
330             jsc.getViewport().getView().requestFocus();
331         }
332     }
333
334     /** Transfers focus to the table */
335     public boolean requestFocusInWindow() {
336         JScrollPane JavaDoc jsc = findScrollPane();
337
338         if ((jsc != null) && (jsc.getViewport().getView() != null)) {
339             return jsc.getViewport().getView().requestFocusInWindow();
340         } else {
341             return false;
342         }
343     }
344
345     /**
346      * Set the state of the component. The state is a bitmask of
347      * STATE_HAS_DESCRIPTION and STATE_HAS_TABS, and may be 0 to indicate
348      * no tabs or description. Calling this method will change the
349      * component hierarchy to reflect the requested state.
350      */

351     public void setState(int state) {
352         if (state != getState()) {
353             synchronized (getTreeLock()) {
354                 switch (state) {
355                 case 0:
356
357                     JComponent JavaDoc tc = findTabbedContainer();
358
359                     if (tc != null) {
360                         remove(tc);
361                     }
362
363                     JSplitPane JavaDoc jsp = findSplitPane();
364
365                     if (jsp != null) {
366                         remove(jsp);
367                     }
368
369                     break;
370
371                 case PSheet.STATE_HAS_DESCRIPTION:
372
373                     JSplitPane JavaDoc split = findSplitPane();
374                     remove(findTabbedContainer());
375
376                     if (split != null) {
377                         addImpl(split, null, 0);
378                     } else {
379                         addImpl(createDescriptionComponent(), null, 0);
380                     }
381
382                     break;
383
384                 case PSheet.STATE_HAS_TABS:
385
386                     JScrollPane JavaDoc jsc = findScrollPane();
387                     JComponent JavaDoc tct = findTabbedContainer();
388
389                     if (tct == null) {
390                         addImpl(createTabbedContainer(), null, 0);
391                     }
392
393                     JSplitPane JavaDoc spl = findSplitPane();
394
395                     if (spl != null) {
396                         remove(spl);
397                     }
398
399                     if (jsc != null) {
400                         setTabbedContainerInnerComponent(findTabbedContainer(), jsc);
401                     }
402
403                     adjustForName(manager.getCurrentNodeName());
404
405                     break;
406
407                 case (PSheet.STATE_HAS_DESCRIPTION | PSheet.STATE_HAS_TABS):
408
409                     JComponent JavaDoc tcc = findTabbedContainer();
410                     JSplitPane JavaDoc splt = findSplitPane();
411                     JScrollPane JavaDoc scrl = findScrollPane();
412
413                     if (tcc == null) {
414                         tcc = createTabbedContainer();
415                         addImpl(tcc, null, 0);
416                     }
417
418                     if (splt == null) {
419                         addImpl(createDescriptionComponent(), null, 0);
420                         splt = findSplitPane();
421                     }
422
423                     setTabbedContainerInnerComponent(tcc, splt);
424
425                     if (scrl != null) {
426                         splt.setLeftComponent(scrl);
427                     }
428
429                     adjustForName(manager.getCurrentNodeName());
430
431                     break;
432
433                 default:
434                     throw new IllegalArgumentException JavaDoc(Integer.toString(state));
435                 }
436             }
437         }
438
439         revalidate();
440         repaint();
441     }
442
443     /**
444      * Get the current state of the component, as defined as a bitmask of
445      * STATE_HAS_TABS and STATE_HAS_DESCRIPTION.
446      */

447     public int getState() {
448         int result = 0;
449
450         if (findTabbedContainer() != null) {
451             result |= STATE_HAS_TABS;
452         }
453
454         if (findSplitPane() != null) {
455             result |= STATE_HAS_DESCRIPTION;
456         }
457
458         return result;
459     }
460
461     /**
462      * Overridden to handle component adds/removes. This class has very
463      * specific ideas about what to do with things that are added to it, such
464      * that getting it into the right state is simply a matter of calling add
465      * or remove with the right component. To wit:
466      * <ul>
467      * <li>Adding a JTable adds a JScrollPane with the JTable in it. If a
468      * split pane is present, it is added to the split pane; if a tabbed
469      * pane is present and a split pane isn't, it is added to the tabbed
470      * pane, otherwise it's added to the instance of this class itself.
471      * </li>
472      * <li>Adding a DescriptionComponent will cause a JSplitPane to be
473      * installed, and any scroll pane present moved into it; split pane
474      * will either be added to the container itself, or to a tabbed
475      * pane if present.
476      * </li>
477      * </ul>
478      * Basically, all of the logic that keeps the component state correct
479      * lives here and in remove(), and all outside code needs to do is
480      * add/remove things, or even more simply, call setState(), which handles
481      * that.
482      */

483     protected void addImpl(Component JavaDoc comp, Object JavaDoc constraints, int idx) {
484         if (
485             !(comp instanceof JSplitPane JavaDoc || comp instanceof JScrollPane JavaDoc || comp instanceof DescriptionComponent ||
486                 comp instanceof JTable JavaDoc ||
487                 (comp instanceof JComponent JavaDoc && Boolean.TRUE.equals(((JComponent JavaDoc) comp).getClientProperty("tc"))))
488         ) {
489             throw new IllegalArgumentException JavaDoc("Unexpected component " + comp);
490         }
491
492         synchronized (getTreeLock()) {
493             addCount++;
494
495             try {
496                 if (!Arrays.asList(comp.getMouseListeners()).contains(this)) {
497                     comp.addMouseListener(this);
498                 }
499
500                 if (comp instanceof JTable JavaDoc) {
501                     JScrollPane JavaDoc jsc = findScrollPane();
502
503                     if (jsc == null) {
504                         jsc = createScrollPane(comp);
505                     } else {
506                         jsc.setViewportView(comp);
507                     }
508
509                     JSplitPane JavaDoc split = findSplitPane();
510
511                     if (split != null) {
512                         split.setLeftComponent(jsc);
513                         split.revalidate();
514                     } else {
515                         JComponent JavaDoc tc = findTabbedContainer();
516
517                         if (tc != null) {
518                             setTabbedContainerInnerComponent(tc, split);
519                         } else {
520                             addImpl(jsc, constraints, idx);
521                         }
522                     }
523                 } else if (comp instanceof DescriptionComponent) {
524                     JSplitPane JavaDoc pane = findSplitPane();
525                     boolean hadPane = pane != null;
526
527                     if (pane == null) {
528                         pane = createSplitPane(comp);
529                     }
530
531                     JScrollPane JavaDoc scroll = findScrollPane();
532
533                     if (scroll != null) {
534                         pane.setLeftComponent(scroll);
535                     }
536
537                     if (!hadPane) {
538                         addImpl(pane, constraints, idx);
539                     }
540
541                     ((DescriptionComponent) comp).setDescription(title, description);
542                     ((DescriptionComponent) comp).setHelpEnabled(helpEnabled);
543                 } else if (isTabbedContainer(comp)) {
544                     JSplitPane JavaDoc split = findSplitPane();
545
546                     if (split != null) {
547                         super.remove(split);
548                         setTabbedContainerInnerComponent((JComponent JavaDoc) comp, split);
549                     } else {
550                         JScrollPane JavaDoc pane = findScrollPane();
551
552                         if (pane != null) {
553                             setTabbedContainerInnerComponent((JComponent JavaDoc) comp, pane);
554                             remove(pane);
555                         }
556                     }
557
558                     super.addImpl(comp, constraints, idx);
559                 } else if (comp instanceof JScrollPane JavaDoc) {
560                     JSplitPane JavaDoc split = findSplitPane();
561
562                     if (split != null) {
563                         split.setLeftComponent(comp);
564                         split.revalidate();
565                     } else {
566                         JComponent JavaDoc tc = findTabbedContainer();
567
568                         if (tc != null) {
569                             setTabbedContainerInnerComponent(tc, (JComponent JavaDoc) comp);
570                         } else {
571                             super.addImpl(comp, constraints, idx);
572                         }
573                     }
574                 } else if (comp instanceof JSplitPane JavaDoc) {
575                     JScrollPane JavaDoc jsc = findScrollPane();
576
577                     if (jsc != null) {
578                         ((JSplitPane JavaDoc) comp).setLeftComponent(jsc);
579                     }
580
581                     JComponent JavaDoc tc = findTabbedContainer();
582
583                     if (tc != null) {
584                         setTabbedContainerInnerComponent(tc, (JComponent JavaDoc) comp);
585                     } else {
586                         super.addImpl(comp, constraints, idx);
587                     }
588                 } else {
589                     super.addImpl(comp, constraints, idx);
590                 }
591             } finally {
592                 addCount--;
593                 revalidate();
594             }
595         }
596     }
597
598     /**
599      * Remove a component. Overridden to handle management of state, nested
600      * components, etc. It is legitimate to call this method with null
601      * (for convenience), or with a component that is a child of a child of
602      * this container.
603      */

604     public void remove(Component JavaDoc c) {
605         if (c == null) {
606             return;
607         }
608
609         c.removeMouseListener(this);
610
611         synchronized (getTreeLock()) {
612             if (c.getParent() == this) {
613                 super.remove(c);
614
615                 if (adding()) {
616                     return;
617                 }
618             }
619
620             if (isTabbedContainer(c)) {
621                 Component JavaDoc inner = getTabbedContainerInnerComponent((JComponent JavaDoc) c);
622
623                 if (inner != null) {
624                     addImpl(inner, null, 0);
625                 }
626             } else if (c instanceof JSplitPane JavaDoc) {
627                 if (c.getParent() != null) {
628                     c.getParent().remove(c);
629                 }
630
631                 Component JavaDoc inner = ((JSplitPane JavaDoc) c).getLeftComponent();
632
633                 if (inner != null) {
634                     addImpl(inner, null, 0);
635                 }
636             } else if (c instanceof DescriptionComponent) {
637                 JSplitPane JavaDoc jsp = findSplitPane();
638
639                 if (jsp != null) {
640                     jsp.remove(c);
641                     remove(jsp);
642                 }
643             }
644         }
645
646         revalidate();
647     }
648
649     /**
650      * Determine if a call to addImpl() is implicit or explicit. remove()
651      * uses this method to determine if it is being called from within
652      * addImpl() or not, as its behavior will be different in that case.
653      */

654     private boolean adding() {
655         return addCount > 0;
656     }
657
658     /**
659      * Create a description component */

660     private DescriptionComponent createDescriptionComponent() {
661         return new DescriptionComponent();
662     }
663
664     private JSplitPane JavaDoc createSplitPane(Component JavaDoc lower) {
665         JSplitPane JavaDoc pane = new JSplitPane JavaDoc();
666
667         if (firstSplit == null) {
668             firstSplit = Boolean.TRUE;
669         } else {
670             firstSplit = Boolean.FALSE;
671         }
672
673         pane.setRightComponent(lower);
674         pane.setOrientation(JSplitPane.VERTICAL_SPLIT);
675         pane.setContinuousLayout(true);
676         pane.setResizeWeight(1);
677         pane.setDividerLocation(0.80f);
678         pane.setBorder(BorderFactory.createEmptyBorder());
679         pane.setUI(PropUtils.createSplitPaneUI());
680
681         // #52188: default F6 behaviour doesn't make to much sense in NB
682
// property sheet and blocks NetBeans default F6
683
pane.getActionMap().getParent().remove("toggleFocus");
684
685         return pane;
686     }
687
688     private JScrollPane JavaDoc createScrollPane(Component JavaDoc inner) {
689         JScrollPane JavaDoc result = new JScrollPane JavaDoc(inner);
690         JViewport JavaDoc vp = result.getViewport();
691         vp.addMouseListener(this);
692
693         MarginViewportUI ui = (MarginViewportUI) MarginViewportUI.createUI(vp);
694         vp.setUI(ui);
695         ui.setMarginPainted(marginPainted);
696         ui.setMarginColor(marginColor);
697         ui.setEmptyString(emptyString);
698         result.setBorder(BorderFactory.createEmptyBorder());
699         result.setViewportBorder(result.getBorder());
700
701         return result;
702     }
703
704     private JComponent JavaDoc createTabbedContainer() {
705         JComponent JavaDoc result = TabbedContainerBridge.getDefault().createTabbedContainer();
706         result.putClientProperty("tc", Boolean.TRUE);
707         configureTabbedContainer(tabbedContainerObjects, tabbedContainerTitles, result);
708
709         if (selectionListener != null) {
710             TabbedContainerBridge.getDefault().attachSelectionListener(result, selectionListener);
711         }
712
713         return result;
714     }
715
716     public void setTabbedContainerItems(Object JavaDoc[] o, String JavaDoc[] s) {
717         adjusting = true;
718
719         try {
720             tabbedContainerObjects = o;
721             tabbedContainerTitles = s;
722
723             if (o.length == 0) {
724                 int newState = ((getState() & STATE_HAS_DESCRIPTION) != 0) ? STATE_HAS_DESCRIPTION : 0;
725                 setState(newState);
726             } else {
727                 configureTabbedContainer(o, s, null);
728             }
729         } finally {
730             adjusting = false;
731         }
732     }
733
734     public void setTabbedContainerSelection(Object JavaDoc item) {
735         JComponent JavaDoc tabbed = findTabbedContainer();
736
737         if (tabbed != null) {
738             adjusting = true;
739
740             try {
741                 TabbedContainerBridge.getDefault().setSelectedItem(tabbed, item);
742             } finally {
743                 adjusting = false;
744             }
745         }
746     }
747
748     public Object JavaDoc getTabbedContainerSelection() {
749         JComponent JavaDoc tabbed = findTabbedContainer();
750
751         if (tabbed != null) {
752             Object JavaDoc o = TabbedContainerBridge.getDefault().getSelectedItem(tabbed);
753
754             if (o instanceof Node.PropertySet[]) { //won't be first time
755

756                 return o;
757             }
758         }
759
760         return null;
761     }
762
763     private void configureTabbedContainer(Object JavaDoc[] o, String JavaDoc[] s, JComponent JavaDoc cont) {
764         if (cont == null) {
765             cont = findTabbedContainer();
766         }
767
768         if (cont != null) {
769             TabbedContainerBridge.getDefault().setItems(cont, o, s);
770         }
771     }
772
773     private void setTabbedContainerInnerComponent(JComponent JavaDoc tabbed, JComponent JavaDoc comp) {
774         if (tabbed == null) {
775             tabbed = findTabbedContainer();
776         }
777
778         TabbedContainerBridge.getDefault().setInnerComponent(tabbed, comp);
779     }
780
781     private static JComponent JavaDoc getTabbedContainerInnerComponent(JComponent JavaDoc c) {
782         JComponent JavaDoc result = TabbedContainerBridge.getDefault().getInnerComponent(c);
783
784         return result;
785     }
786
787     public void addSelectionChangeListener(ChangeListener JavaDoc l) {
788         if (selectionListener != l) {
789             JComponent JavaDoc comp = findTabbedContainer();
790             selectionListener = l;
791
792             if (comp != null) {
793                 TabbedContainerBridge.getDefault().attachSelectionListener(comp, l);
794             }
795         }
796     }
797
798     private static boolean isTabbedContainer(Component JavaDoc comp) {
799         return comp instanceof JComponent JavaDoc && Boolean.TRUE.equals(((JComponent JavaDoc) comp).getClientProperty("tc")); //NOI18N
800
}
801
802     /**
803      * Find the currently in use description component.
804      */

805     private DescriptionComponent findDescriptionComponent() {
806         return (DescriptionComponent) findChildOfClass(findSplitPane(), DescriptionComponent.class);
807     }
808
809     /**
810      * Find the currently in use scroll pane, if any (there should always be
811      * one)
812      */

813     private JScrollPane JavaDoc findScrollPane() {
814         JScrollPane JavaDoc result = (JScrollPane JavaDoc) findChildOfClass(this, JScrollPane JavaDoc.class);
815
816         if (result == null) {
817             result = (JScrollPane JavaDoc) findChildOfClass(findTabbedContainer(), JScrollPane JavaDoc.class);
818
819             if (result == null) {
820                 result = (JScrollPane JavaDoc) findChildOfClass(findSplitPane(), JScrollPane JavaDoc.class);
821             }
822         }
823
824         return result;
825     }
826
827     /**
828      * Find the currently in use split pane, if any
829      */

830     private JSplitPane JavaDoc findSplitPane() {
831         JSplitPane JavaDoc result = (JSplitPane JavaDoc) findChildOfClass(this, JSplitPane JavaDoc.class);
832
833         if (result == null) {
834             result = (JSplitPane JavaDoc) findChildOfClass(findTabbedContainer(), JSplitPane JavaDoc.class);
835         }
836
837         return result;
838     }
839
840     /**
841      * Find the currently in use tabbed container, if any
842      */

843     private JComponent JavaDoc findTabbedContainer() {
844         Component JavaDoc[] c = getComponents();
845
846         for (int i = 0; i < c.length; i++) {
847             if (c[i] instanceof JComponent JavaDoc && Boolean.TRUE.equals(((JComponent JavaDoc) c[i]).getClientProperty("tc"))) {
848                 return (JComponent JavaDoc) c[i];
849             }
850         }
851
852         return null;
853     }
854
855     /**
856      * Search one container for component of the requested class
857      */

858     private static Component JavaDoc findChildOfClass(Container JavaDoc container, Class JavaDoc clazz) {
859         if (container == null) {
860             return null;
861         }
862
863         if (isTabbedContainer((JComponent JavaDoc) container)) {
864             Component JavaDoc c = getTabbedContainerInnerComponent((JComponent JavaDoc) container);
865
866             if ((c != null) && (c.getClass() == clazz)) {
867                 return c;
868             }
869         } else {
870             Component JavaDoc[] c = container.getComponents();
871
872             for (int i = 0; i < c.length; i++) {
873                 if (clazz == c[i].getClass()) {
874                     return c[i];
875                 }
876             }
877         }
878
879         return null;
880     }
881
882     /**
883      * Notification method that the user has requested a popup menu.
884      */

885     protected void popupRequested(Point JavaDoc p) {
886         PropertySheet ps = (PropertySheet) SwingUtilities.getAncestorOfClass(PropertySheet.class, this);
887
888         if (ps != null) {
889             ps.showPopup(p);
890         }
891     }
892
893     /**
894      * Notification that the user has pressed the help button
895      */

896     protected void helpRequested() {
897         PropertySheet ps = (PropertySheet) SwingUtilities.getAncestorOfClass(PropertySheet.class, this);
898
899         if (ps != null) {
900             ps.helpAction.actionPerformed(new ActionEvent JavaDoc(this, ActionEvent.ACTION_PERFORMED, "invokeHelp")); //NOI18N
901
}
902     }
903
904     public void mousePressed(MouseEvent JavaDoc e) {
905         if (e.isPopupTrigger()) {
906             Point JavaDoc p = SwingUtilities.convertPoint((Component JavaDoc) e.getSource(), e.getPoint(), this);
907             updateSheetTableSelection(e);
908             popupRequested(p);
909         }
910     }
911
912     public void mouseReleased(MouseEvent JavaDoc e) {
913         if (e.isPopupTrigger()) {
914             Point JavaDoc p = SwingUtilities.convertPoint((Component JavaDoc) e.getSource(), e.getPoint(), this);
915             updateSheetTableSelection(e);
916             popupRequested(p);
917         }
918     }
919
920     private void updateSheetTableSelection(MouseEvent JavaDoc e) {
921         Component JavaDoc comp = (Component JavaDoc) e.getSource();
922
923         if (comp instanceof SheetTable) {
924             SheetTable table = (SheetTable) comp;
925             table.changeSelection(table.rowAtPoint(e.getPoint()), 0, false, false);
926         }
927     }
928
929     public void mouseClicked(MouseEvent JavaDoc e) {
930         //do nothing
931
}
932
933     public void mouseEntered(MouseEvent JavaDoc e) {
934         //do nothing
935
}
936
937     public void mouseExited(MouseEvent JavaDoc e) {
938         //do nothing
939
}
940
941     private class PopupAction extends AbstractAction JavaDoc {
942         public void actionPerformed(ActionEvent JavaDoc actionEvent) {
943             popupRequested(new Point JavaDoc(0, 0));
944         }
945     }
946     
947     private class SwitchTabAction extends AbstractAction JavaDoc {
948         private int increment;
949         public SwitchTabAction( int increment ) {
950             this.increment = increment;
951         }
952         
953         public void actionPerformed(ActionEvent JavaDoc actionEvent) {
954             JComponent JavaDoc tabbed = findTabbedContainer();
955
956             if( null == tabbed )
957                 return;
958             
959             Object JavaDoc o = TabbedContainerBridge.getDefault().getSelectedItem( tabbed );
960             if( null == o )
961                 return;
962             
963             Object JavaDoc[] items = TabbedContainerBridge.getDefault().getItems( tabbed );
964             int currentIndex = -1;
965             for( int i=0; null != items && i<items.length; i++ ) {
966                 if( items[i].equals( o ) ) {
967                     currentIndex = i;
968                     break;
969                 }
970             }
971
972             if( currentIndex < 0 )
973                 return;
974             
975             int newIndex = currentIndex + increment;
976             if( newIndex < 0 )
977                 newIndex = items.length-1;
978             if( newIndex >= items.length )
979                 newIndex = 0;
980             TabbedContainerBridge.getDefault().setSelectedItem( tabbed, items[newIndex] );
981         }
982     }
983 }
984
Popular Tags