KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > core > windows > view > ui > TabbedHandler


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
20
21 package org.netbeans.core.windows.view.ui;
22
23
24 import org.netbeans.core.windows.Constants;
25 import org.netbeans.core.windows.WindowManagerImpl;
26 import org.netbeans.core.windows.ModeImpl;
27 import org.netbeans.core.windows.actions.ActionUtils;
28 import org.netbeans.core.windows.actions.MaximizeWindowAction;
29 import org.netbeans.core.windows.view.ModeView;
30 import org.netbeans.core.windows.view.ui.tabcontrol.TabbedAdapter;
31 import org.netbeans.core.windows.WindowManagerImpl;
32 import org.netbeans.core.windows.view.SlidingView;
33 import org.netbeans.core.windows.view.ui.slides.SlideOperation;
34 import org.netbeans.core.windows.view.ui.slides.TabbedSlideAdapter;
35 import org.netbeans.swing.tabcontrol.TabbedContainer;
36 import org.netbeans.swing.tabcontrol.event.TabActionEvent;
37 import org.openide.windows.TopComponent;
38 import org.openide.util.Utilities;
39
40 import javax.swing.*;
41 import javax.swing.event.ChangeEvent JavaDoc;
42 import javax.swing.event.ChangeListener JavaDoc;
43 import java.awt.*;
44 import java.awt.event.ActionEvent JavaDoc;
45 import java.awt.event.ActionListener JavaDoc;
46 import java.awt.event.MouseEvent JavaDoc;
47 import java.awt.event.AWTEventListener JavaDoc;
48 import org.netbeans.core.windows.view.ui.slides.SlideBar;
49 import org.netbeans.core.windows.view.ui.slides.SlideBarActionEvent;
50 import org.netbeans.core.windows.view.ui.slides.SlideOperationFactory;
51
52
53 /** Helper class which handles <code>Tabbed</code> component inside
54  * <code>ModeComponent</code>.
55  *
56  * @author Peter Zavadsky
57  */

58 public final class TabbedHandler implements ChangeListener JavaDoc, ActionListener JavaDoc {
59
60     /** Associated mode container. */
61     private final ModeView modeView;
62     
63     /** Component which plays tabbed. */
64     private final Tabbed tabbed;
65     /** kind of the mode view we are handling tabs for */
66     private final int kind;
67
68     /** Ignore own changes. */
69     private boolean ignoreChange = false;
70
71     private static ActivationManager activationManager = null;
72
73     /** Creates new SimpleContainerImpl */
74     public TabbedHandler(ModeView modeView, int kind, Tabbed tbd) {
75         this.modeView = modeView;
76         this.kind = kind;
77
78         synchronized (TabbedHandler.class) {
79             if (activationManager == null) {
80                 activationManager = new ActivationManager();
81                 Toolkit.getDefaultToolkit().addAWTEventListener(
82                     activationManager, AWTEvent.MOUSE_EVENT_MASK);
83             }
84         }
85         tabbed = tbd;
86         tabbed.addChangeListener(this);
87         tabbed.addActionListener(this);
88 // tabbed = createTabbedComponent(kind);
89

90         // E.g. when switching tabs in mode.
91
((Container)tabbed.getComponent()).setFocusCycleRoot(true);
92     }
93
94     
95 // /** Gets tabbed container on supplied position */
96
// private Tabbed createTabbedComponent(int kind) {
97
// Tabbed tabbed;
98
//
99
// if(kind == Constants.MODE_KIND_EDITOR) {
100
// tabbed = new TabbedAdapter(Constants.MODE_KIND_EDITOR);
101
// } else if (kind == Constants.MODE_KIND_SLIDING) {
102
// tabbed = new TabbedSlideAdapter(((SlidingView)modeView).getSide());
103
// } else {
104
// tabbed = new TabbedAdapter(Constants.MODE_KIND_VIEW);
105
// }
106
//
107
// tabbed.addChangeListener(this);
108
// tabbed.addActionListener(this);
109
//
110
// return tabbed;
111
// }
112

113     public void requestAttention (TopComponent tc) {
114         tabbed.requestAttention(tc);
115     }
116
117     public void cancelRequestAttention (TopComponent tc) {
118         tabbed.cancelRequestAttention(tc);
119     }
120     
121     public Component getComponent() {
122         return tabbed.getComponent();
123     }
124
125     /** Adds given top component to this container. */
126     public void addTopComponent(TopComponent tc, int kind) {
127         addTCIntoTab(tc, kind);
128     }
129     
130
131     public void setTopComponents(TopComponent[] tcs, TopComponent selected) {
132         ignoreChange = true;
133         try {
134             tabbed.setTopComponents(tcs, selected);
135         } finally {
136             ignoreChange = false;
137         }
138     }
139     
140     /** Adds TopComponent into specified tab. */
141     private void addTCIntoTab(TopComponent tc, int kind) {
142         
143         if(containsTC(tabbed, tc)) {
144             return;
145         }
146
147         Image icon = tc.getIcon();
148         
149         try {
150             ignoreChange = true;
151             String JavaDoc title = WindowManagerImpl.getInstance().getTopComponentDisplayName(tc);
152             if(title == null) {
153                 title = ""; // NOI18N
154
}
155             tabbed.addTopComponent(
156                 title,
157                 icon == null ? null : new ImageIcon(icon),
158                 tc, tc.getToolTipText());
159         } finally {
160             ignoreChange = false;
161         }
162     }
163
164     /** Checks whether the tabbedPane already contains the component. */
165     private static boolean containsTC(Tabbed tabbed, TopComponent tc) {
166         return tabbed.indexOf(tc) != -1;
167     }
168     
169     /** Removes TopComponent from this container. */
170     public void removeTopComponent(TopComponent tc) {
171         removeTCFromTab(tc);
172     }
173
174     /** Removes TC from tab. */
175     private void removeTCFromTab (TopComponent tc) {
176         if(tabbed.indexOf(tc) != -1) {
177             try {
178                 ignoreChange = true;
179                 tabbed.removeComponent(tc);
180             } finally {
181                 ignoreChange = false;
182             }
183
184             //Bugfix #27644: Remove reference from TopComponent's accessible context
185
//to our tabbed pane.
186
tc.getAccessibleContext().setAccessibleParent(null);
187         }
188     }
189     
190     /** Called when icon of some component in this multi frame has changed */
191     public void topComponentIconChanged(TopComponent tc) {
192         int index = tabbed.indexOf(tc);
193         if (index < 0) {
194             return;
195         }
196         
197         tabbed.setIconAt(index, new ImageIcon(tc.getIcon()));
198     }
199     
200     /** Called when the name of some component has changed */
201     public void topComponentNameChanged(TopComponent tc, int kind) {
202         int index = tabbed.indexOf(tc);
203         if (index < 0) {
204             return;
205         }
206         
207         String JavaDoc title = WindowManagerImpl.getInstance().getTopComponentDisplayName(tc);
208         if(title == null) {
209             title = ""; // NOI18N
210
}
211         tabbed.setTitleAt (index, title);
212     }
213     
214     public void topComponentToolTipChanged(TopComponent tc) {
215         int index = tabbed.indexOf(tc);
216         if (index < 0) {
217             return;
218         }
219         
220         tabbed.setToolTipTextAt(index, tc.getToolTipText());
221     }
222     
223     /** Sets selected <code>TopComponent</code>.
224      * Ensures GUI components to set accordingly. */

225     public void setSelectedTopComponent(TopComponent tc) {
226         if(tc == getSelectedTopComponent()) {
227             return;
228         }
229         if (tc == null && !isNullSelectionAllowed()) {
230             return;
231         }
232         
233         if(tabbed.indexOf(tc) >= 0 || (isNullSelectionAllowed() && tc == null)) {
234             try {
235                 ignoreChange = true;
236                 tabbed.setSelectedComponent(tc);
237             } finally {
238                 ignoreChange = false;
239             }
240         }
241     }
242     
243     private boolean isNullSelectionAllowed() {
244         return kind == Constants.MODE_KIND_SLIDING;
245     }
246     
247     public TopComponent getSelectedTopComponent() {
248         return tabbed.getSelectedTopComponent();
249     }
250
251     public TopComponent[] getTopComponents() {
252         return tabbed.getTopComponents();
253     }
254
255     public void setActive(boolean active) {
256         tabbed.setActive(active);
257     }
258     
259     ///////////////////
260
// ChangeListener
261
public void stateChanged(ChangeEvent JavaDoc evt) {
262         if(ignoreChange || evt.getSource() != tabbed) {
263             return;
264         }
265         TopComponent selected = tabbed.getSelectedTopComponent();
266         modeView.getController().userSelectedTab(modeView, (TopComponent)selected);
267     }
268     
269     // DnD>>
270
public Shape getIndicationForLocation(Point location, TopComponent startingTransfer,
271     Point startingPoint, boolean attachingPossible) {
272         return tabbed.getIndicationForLocation(location, startingTransfer,
273                                             startingPoint, attachingPossible);
274     }
275     
276     public Object JavaDoc getConstraintForLocation(Point location, boolean attachingPossible) {
277         return tabbed.getConstraintForLocation(location, attachingPossible);
278     }
279     
280     // Sliding
281
public Rectangle getTabBounds(int tabIndex) {
282         return tabbed.getTabBounds(tabIndex);
283     }
284
285     public void actionPerformed(ActionEvent e) {
286         if (e instanceof TabActionEvent) {
287             TabActionEvent tae = (TabActionEvent) e;
288             String JavaDoc cmd = tae.getActionCommand();
289             if (TabbedContainer.COMMAND_SELECT.equals(cmd)) {
290                 return;
291             }
292             tae.consume();
293             if (TabbedContainer.COMMAND_CLOSE == cmd) { //== test is safe here
294
TopComponent tc = (TopComponent) tabbed.getTopComponentAt(tae.getTabIndex());
295                 if (tc == null) {
296                     throw new IllegalStateException JavaDoc ("Component to be closed " +
297                         "is null at index " + tae.getTabIndex());
298                 }
299                 modeView.getController().userClosedTopComponent(modeView, tc);
300             } else if (TabbedContainer.COMMAND_POPUP_REQUEST == cmd) {
301                 handlePopupMenuShowing(tae.getMouseEvent(), tae.getTabIndex());
302             } else if (TabbedContainer.COMMAND_MAXIMIZE == cmd) {
303                 handleMaximization(tae);
304             } else if (TabbedContainer.COMMAND_CLOSE_ALL == cmd) {
305                 ActionUtils.closeAllDocuments();
306             } else if (TabbedContainer.COMMAND_CLOSE_ALL_BUT_THIS == cmd) {
307                 TopComponent tc = (TopComponent) tabbed.getTopComponentAt(tae.getTabIndex());
308                 ActionUtils.closeAllExcept(tc);
309             //Pin button handling here
310
} else if (TabbedContainer.COMMAND_ENABLE_AUTO_HIDE.equals(cmd)) {
311                 TopComponent tc = (TopComponent) tabbed.getTopComponentAt(tae.getTabIndex());
312                 // prepare slide operation
313
Component tabbedComp = tabbed.getComponent();
314                 
315                 String JavaDoc side = WindowManagerImpl.getInstance().guessSlideSide(tc);
316                 SlideOperation operation = SlideOperationFactory.createSlideIntoEdge(
317                     tabbedComp, side, true);
318                 operation.setStartBounds(
319                        new Rectangle(tabbedComp.getLocationOnScreen(), tabbedComp.getSize()));
320                 operation.prepareEffect();
321                 
322                 modeView.getController().userEnabledAutoHide(modeView, tc);
323                 modeView.getController().userTriggeredSlideIntoEdge(modeView, operation);
324             }
325         } else if (e instanceof SlideBarActionEvent) {
326             // slide bar commands
327
SlideBarActionEvent sbe = (SlideBarActionEvent)e;
328             String JavaDoc cmd = sbe.getActionCommand();
329             if (SlideBar.COMMAND_POPUP_REQUEST.equals(cmd)) {
330                 handlePopupMenuShowing(sbe.getMouseEvent(), sbe.getTabIndex());
331             } else if (SlideBar.COMMAND_SLIDE_IN.equals(cmd)) {
332                 modeView.getController().userTriggeredSlideIn(modeView, sbe.getSlideOperation());
333             } else if (SlideBar.COMMAND_SLIDE_RESIZE.equals(cmd)) {
334                 modeView.getController().userResizedSlidingWindow(modeView, sbe.getSlideOperation());
335             } else if (SlideBar.COMMAND_SLIDE_OUT.equals(cmd)) {
336                 // when the call comes from the change of tehmodel rather than user clicking,
337
// ignore activation requests.
338
// #48539
339
SlideOperation op = new ProxySlideOperation(sbe.getSlideOperation(), ignoreChange);
340                 modeView.getController().userTriggeredSlideOut(modeView, op);
341             } else if (SlideBar.COMMAND_DISABLE_AUTO_HIDE.equals(cmd)) {
342                 TopComponent tc = (TopComponent) tabbed.getTopComponentAt(sbe.getTabIndex());
343                 modeView.getController().userDisabledAutoHide(modeView, tc);
344             } else if( SlideBar.COMMAND_MAXIMIZE == cmd ) {
345                 TopComponent tc = (TopComponent) tabbed.getTopComponentAt(sbe.getTabIndex());
346                 MaximizeWindowAction mwa = new MaximizeWindowAction(tc);
347                 mwa.actionPerformed(e);
348             }
349         }
350     }
351
352     /** Possibly invokes popup menu. */
353     public static void handlePopupMenuShowing(MouseEvent JavaDoc e, int idx) {
354         Component c = (Component) e.getSource();
355         while (c != null && !(c instanceof Tabbed.Accessor))
356             c = c.getParent();
357         if (c == null) {
358             return;
359         }
360         final Tabbed tab = ((Tabbed.Accessor)c).getTabbed();
361
362         final Point p = SwingUtilities.convertPoint((Component) e.getSource(), e.getPoint(), c);
363
364         final int clickTab = idx;
365         if (clickTab < 0) {
366             return;
367         }
368
369         TopComponent tc = tab.getTopComponentAt(clickTab);
370         if(tc == null) {
371             return;
372         }
373         
374         // ask also tabbed to possibly alter actions
375
Action[] actions = tab.getPopupActions(tc.getActions(), clickTab);
376         if (actions == null) {
377             actions = tc.getActions();
378         }
379
380         showPopupMenu(
381             Utilities.actionsToPopup(actions, tc.getLookup()), p, c);
382     }
383
384     /** Shows given popup on given coordinations and takes care about the
385      * situation when menu can exceed screen limits */

386     private static void showPopupMenu (JPopupMenu popup, Point p, Component comp) {
387         popup.show(comp, p.x, p.y);
388     }
389
390     /** Possibly invokes the (un)maximization. */
391     public static void handleMaximization(TabActionEvent tae) {
392         Component c = (Component) tae.getSource();
393         while (c != null && !(c instanceof Tabbed))
394             c = c.getParent();
395         if (c == null) {
396             return;
397         }
398         
399         final Tabbed tab = (Tabbed) c;
400         TopComponent tc = tab.getTopComponentAt(tae.getTabIndex());
401         // perform action
402
MaximizeWindowAction mwa = new MaximizeWindowAction(tc);
403         mwa.actionPerformed(tae);
404     }
405
406     /** Well, we can't totally get rid of AWT event listeners - this is what
407      * keeps track of the activated mode. */

408     private static class ActivationManager implements AWTEventListener JavaDoc {
409         public void eventDispatched(AWTEvent e) {
410             if(e.getID() == MouseEvent.MOUSE_PRESSED) {
411                 handleActivation((MouseEvent JavaDoc) e);
412             }
413         }
414
415         //
416
/* XXX(-ttran) when the split container contains two TopComponents say TC1
417          * and TC2. If TC2 itself does not accept focus or the user clicks on one
418          * of TC2's child compoennts which does not accept focus, then the whole
419          * split container is activated. It in turn may choose to activate TC1 not
420          * TC2. This is a very annoying problem if TC1 is an Explorer and TC2 is
421          * the global property sheet. The user clicks on the property sheet but
422          * the Explorer gets activated which has a different selected node than the
423          * one attached to the property sheet at that moment. The contents of the
424          * property sheet is updated immediately after the mouse click. For more
425          * details see <http://www.netbeans.org/issues/show_bug.cgi?id=11149>
426          *
427          * What follows here is a special hack for mouse click on _any_
428          * TopComponent. The hack will cause the nearest upper TopComponent in the
429          * AWT hieararchy to be activated on MOUSE_PRESSED on any of its child
430          * components. This behavior is compatible with all window managers I can
431          * imagine.
432          */

433         private void handleActivation(MouseEvent JavaDoc evt) {
434             Object JavaDoc obj = evt.getSource();
435             if (!(obj instanceof Component)) {
436                 return;
437             }
438             Component comp = (Component) obj;
439             
440             while (comp != null && !(comp instanceof ModeComponent)) {
441                 if (comp instanceof JComponent) {
442                     JComponent c = (JComponent)comp;
443                     // don't activate if requested
444
if (Boolean.TRUE.equals(c.getClientProperty("dontActivate"))) { //NOI18N
445
return;
446                     }
447                 }
448                 if (comp instanceof TopComponent) {
449                     TopComponent tc = (TopComponent)comp;
450                     // special way of activation for topcomponents in sliding mode
451
if (Boolean.TRUE.equals(tc.getClientProperty("isSliding"))) { //NOI18N
452
tc.requestActive();
453                         return;
454                     }
455                 }
456                 comp = comp.getParent();
457             }
458
459             if (comp instanceof ModeComponent) {
460                 ModeComponent modeComp = (ModeComponent)comp;
461                 // don't activate sliding views when user clicked edge bar
462
if (modeComp.getKind() != Constants.MODE_KIND_SLIDING) {
463                     ModeView modeView = modeComp.getModeView();
464                     modeView.getController().userActivatedModeView(modeView);
465                 }
466             }
467         }
468         
469     } // end of ActivationManager
470

471     /**
472      * proxy slide operation that disables activation reqeuest when the operation comes from the model, not really user action.
473      */

474     private static class ProxySlideOperation implements SlideOperation {
475         
476         private SlideOperation original;
477         private boolean disable;
478         
479         public ProxySlideOperation(SlideOperation orig, boolean disableActivation) {
480             original = orig;
481             disable = disableActivation;
482         }
483         
484         public Component getComponent() {
485             return original.getComponent();
486         }
487
488         public Rectangle getFinishBounds() {
489             return original.getFinishBounds();
490         }
491
492         public String JavaDoc getSide() {
493             return original.getSide();
494         }
495
496         public Rectangle getStartBounds() {
497             return original.getStartBounds();
498         }
499
500         public int getType() {
501             return original.getType();
502         }
503
504         public void prepareEffect() {
505             original.prepareEffect();
506         }
507
508         public boolean requestsActivation() {
509             if (disable) {
510                 return false;
511             }
512             return original.requestsActivation();
513         }
514
515         public void run(JLayeredPane pane, Integer JavaDoc layer) {
516             original.run(pane, layer);
517         }
518
519         public void setFinishBounds(Rectangle bounds) {
520             original.setFinishBounds(bounds);
521         }
522
523         public void setStartBounds(Rectangle bounds) {
524             original.setStartBounds(bounds);
525         }
526     }
527
528 }
529
530
Popular Tags