KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > swing > tabcontrol > ButtonPopupSwitcher


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 package org.netbeans.swing.tabcontrol;
21
22 import java.awt.AWTEvent JavaDoc;
23 import java.awt.Component JavaDoc;
24 import java.awt.Point JavaDoc;
25 import java.awt.Toolkit JavaDoc;
26 import java.awt.event.AWTEventListener JavaDoc;
27 import java.awt.event.KeyEvent JavaDoc;
28 import java.awt.event.MouseEvent JavaDoc;
29 import javax.swing.JComponent JavaDoc;
30 import javax.swing.Popup JavaDoc;
31 import javax.swing.PopupFactory JavaDoc;
32 import javax.swing.SwingUtilities JavaDoc;
33 import javax.swing.event.MouseInputListener JavaDoc;
34 import org.netbeans.swing.popupswitcher.SwitcherTable;
35 import org.netbeans.swing.popupswitcher.SwitcherTableItem;
36
37 /**
38  * Represents Popup for "Document switching" which is shown after an user clicks
39  * the down-arrow button in tabcontrol displayer.
40  *
41  * @author mkrauskopf
42  */

43 final class ButtonPopupSwitcher
44         implements MouseInputListener JavaDoc, AWTEventListener JavaDoc {
45     
46     /**
47      * Reference to the popup object currently showing the default instance, if
48      * it is visible
49      */

50     private static Popup JavaDoc popup;
51     
52     /**
53      * Reference to the focus owner when addNotify was called. This is the
54      * component that received the mouse event, so it's what we need to listen
55      * on to update the selected cell as the user drags the mouse
56      */

57     private Component JavaDoc invokingComponent = null;
58     
59     /**
60      * Time of invocation, used to determine if a mouse release is delayed long
61      * enough from a mouse press that it should close the popup, instead of
62      * assuming the user wants move-and-click behavior instead of
63      * drag-and-click behavior
64      */

65     private long invocationTime = -1;
66     
67     /** Indicating whether a popup is shown? */
68     private static boolean shown;
69     
70     private SwitcherTable pTable;
71     
72     private int x;
73     private int y;
74     
75     /**
76      * Creates and shows the popup with given <code>items</code>. When user
77      * choose an item <code>SwitcherTableItem.Activatable.activate()</code> is
78      * called. So what exactly happens depends on the concrete
79      * <code>SwitcherTableItem.Activatable</code> implementation. A popup appears
80      * on <code>x</code>, <code>y</code> coordinates.
81      */

82     public static void selectItem(JComponent JavaDoc owner, SwitcherTableItem[] items,
83             int x, int y) {
84         ButtonPopupSwitcher switcher
85                 = new ButtonPopupSwitcher(items, x, y);
86         switcher.doSelect(owner);
87     }
88     
89     /** Creates a new instance of TabListPanel */
90     private ButtonPopupSwitcher(SwitcherTableItem items[],
91             int x,
92             int y) {
93         this.pTable = new SwitcherTable(items, y);
94         this.x = x - (int) pTable.getPreferredSize().getWidth();
95         this.y = y + 1;
96     }
97     
98     private void doSelect(JComponent JavaDoc owner) {
99         invokingComponent = owner;
100         invokingComponent.addMouseListener(this);
101         invokingComponent.addMouseMotionListener(this);
102         pTable.addMouseListener(this);
103         pTable.addMouseMotionListener(this);
104         
105         Toolkit.getDefaultToolkit().addAWTEventListener(this,
106                 AWTEvent.MOUSE_EVENT_MASK
107                 | AWTEvent.KEY_EVENT_MASK);
108         popup = PopupFactory.getSharedInstance().getPopup(
109                 invokingComponent, pTable, x, y);
110         popup.show();
111         shown = true;
112         invocationTime = System.currentTimeMillis();
113     }
114     
115     /**
116      * Returns true if popup is displayed.
117      *
118      * @return True if a popup was closed.
119      */

120     public static boolean isShown() {
121         return shown;
122     }
123     
124     /**
125      * Clean up listners and hide popup.
126      */

127     private synchronized void hideCurrentPopup() {
128         pTable.removeMouseListener(this);
129         pTable.removeMouseMotionListener(this);
130         Toolkit.getDefaultToolkit().removeAWTEventListener(this);
131         if (invokingComponent != null) {
132             invokingComponent.removeMouseListener(this);
133             invokingComponent.removeMouseMotionListener(this);
134             invokingComponent = null;
135         }
136         if (popup != null) {
137             // Issue 41121 - use invokeLater to allow any pending event
138
// processing against the popup contents to run before the popup is
139
// hidden
140
SwingUtilities.invokeLater(new PopupHider(popup));
141             popup = null;
142             shown = false;
143         }
144     }
145     
146     /**
147      * Runnable which hides the popup in a subsequent event queue loop. This
148      * is to avoid problems with BasicToolbarUI, which will try to process
149      * events on the component after it has been hidden and throw exceptions.
150      *
151      * @see http://www.netbeans.org/issues/show_bug.cgi?id=41121
152      */

153     private class PopupHider implements Runnable JavaDoc {
154         private Popup JavaDoc toHide;
155         public PopupHider(Popup JavaDoc popup) {
156             toHide = popup;
157         }
158         
159         public void run() {
160             toHide.hide();
161             toHide = null;
162         }
163     }
164     
165     public void mouseMoved(MouseEvent JavaDoc e) {
166         Point JavaDoc p = e.getPoint();
167         // It may have occured on the button that invoked the tabtable
168
if (e.getSource() != this) {
169             p = SwingUtilities.convertPoint((Component JavaDoc) e.getSource(), p, pTable);
170         }
171         if (pTable.contains(p)) {
172             int row = pTable.rowAtPoint(p);
173             int col = pTable.columnAtPoint(p);
174             pTable.changeSelection(row, col, false, false);
175         } else {
176             pTable.clearSelection();
177         }
178         e.consume();
179     }
180     
181     public void mousePressed(MouseEvent JavaDoc e) {
182         Point JavaDoc p = e.getPoint();
183         p = SwingUtilities.convertPoint((Component JavaDoc) e.getSource(), p, pTable);
184         if (pTable.contains(p)) {
185             final SwitcherTableItem item = pTable.getSelectedItem();
186             if (item != null) {
187                 item.activate();
188                 hideCurrentPopup();
189                 e.consume();
190             }
191         }
192     }
193     
194     public void mouseReleased(MouseEvent JavaDoc e) {
195         if (e.getSource() == invokingComponent) {
196             long time = System.currentTimeMillis();
197             if (time - invocationTime > 500) {
198                 mousePressed(e);
199             }
200         }
201         e.consume();
202     }
203     
204     public void mouseClicked(MouseEvent JavaDoc e) {
205         e.consume();
206     }
207     
208     public void mouseEntered(MouseEvent JavaDoc e) {
209         mouseDragged(e);
210         e.consume();
211     }
212     
213     public void mouseExited(MouseEvent JavaDoc e) {
214         pTable.clearSelection();
215         e.consume();
216     }
217     
218     //MouseMotionListener
219
public void mouseDragged(MouseEvent JavaDoc e) {
220         mouseMoved(e);
221         e.consume();
222     }
223     
224     /**
225      * Was mouse upon the popup table when mouse action had been taken.
226      */

227     private boolean onSwitcherTable(MouseEvent JavaDoc e) {
228         Point JavaDoc p = e.getPoint();
229         p = SwingUtilities.convertPoint((Component JavaDoc) e.getSource(), p, pTable);
230         return pTable.contains(p);
231     }
232     
233     /**
234      * Popup should be closed under some circumstances. Namely when mouse is
235      * pressed or released outside of popup or when key is pressed during the
236      * time popup is visible.
237      */

238     public void eventDispatched(AWTEvent JavaDoc event) {
239         if (event.getSource() == this) {
240             return;
241         }
242         if (event instanceof MouseEvent JavaDoc) {
243             if (event.getID() == MouseEvent.MOUSE_RELEASED) {
244                 long time = System.currentTimeMillis();
245                 // check if button was just slowly clicked
246
if (time - invocationTime > 500) {
247                     if (!onSwitcherTable((MouseEvent JavaDoc) event)) {
248                         // Don't take any chances
249
hideCurrentPopup();
250                     }
251                 }
252             } else if (event.getID() == MouseEvent.MOUSE_PRESSED) {
253                 if (!onSwitcherTable((MouseEvent JavaDoc) event)) {
254                     // Don't take any chances
255
if (event.getSource() != invokingComponent) {
256                         // If it's the invoker, don't do anything - it will
257
// generate another call to invoke(), which will do the
258
// hiding - if we do it here, it will get shown again
259
// when the button processes the event
260
hideCurrentPopup();
261                     }
262                 }
263             }
264         } else if (event instanceof KeyEvent JavaDoc) {
265             if (event.getID() == KeyEvent.KEY_PRESSED) {
266                 Toolkit.getDefaultToolkit().removeAWTEventListener(this);
267                 hideCurrentPopup();
268             }
269         }
270     }
271 }
272
Popular Tags