~ubuntu-branches/debian/stretch/insubstantial/stretch

« back to all changes in this revision

Viewing changes to flamingo/src/main/java/org/pushingpixels/flamingo/api/common/popup/PopupPanelManager.java

  • Committer: Package Import Robot
  • Author(s): Felix Natter
  • Date: 2016-01-18 20:58:45 UTC
  • Revision ID: package-import@ubuntu.com-20160118205845-crbmrkda61qsi5qa
Tags: upstream-7.3+dfsg2
ImportĀ upstreamĀ versionĀ 7.3+dfsg2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2005-2010 Flamingo Kirill Grouchnikov. All Rights Reserved.
 
3
 *
 
4
 * Redistribution and use in source and binary forms, with or without 
 
5
 * modification, are permitted provided that the following conditions are met:
 
6
 * 
 
7
 *  o Redistributions of source code must retain the above copyright notice, 
 
8
 *    this list of conditions and the following disclaimer. 
 
9
 *     
 
10
 *  o Redistributions in binary form must reproduce the above copyright notice, 
 
11
 *    this list of conditions and the following disclaimer in the documentation 
 
12
 *    and/or other materials provided with the distribution. 
 
13
 *     
 
14
 *  o Neither the name of Flamingo Kirill Grouchnikov nor the names of 
 
15
 *    its contributors may be used to endorse or promote products derived 
 
16
 *    from this software without specific prior written permission. 
 
17
 *     
 
18
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
 
19
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 
 
20
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
 
21
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 
 
22
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
 
23
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
 
24
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
 
25
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
 
26
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
 
27
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 
 
28
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 
29
 */
 
30
package org.pushingpixels.flamingo.api.common.popup;
 
31
 
 
32
import java.awt.Component;
 
33
import java.awt.event.ComponentEvent;
 
34
import java.util.*;
 
35
 
 
36
import javax.swing.JComponent;
 
37
import javax.swing.Popup;
 
38
import javax.swing.event.EventListenerList;
 
39
 
 
40
import org.pushingpixels.flamingo.api.common.JCommandButton;
 
41
 
 
42
/**
 
43
 * Manager for showing and hiding {@link JPopupPanel}s.
 
44
 * 
 
45
 * @author Kirill Grouchnikov
 
46
 */
 
47
public class PopupPanelManager {
 
48
        /**
 
49
         * Listener on showing and hiding the popup panels.
 
50
         * 
 
51
         * @author Kirill Grouchnikov
 
52
         */
 
53
        public static interface PopupListener extends EventListener {
 
54
                /**
 
55
                 * Fired when a popup panel has been shown.
 
56
                 * 
 
57
                 * @param event
 
58
                 *            Popup event.
 
59
                 */
 
60
                void popupShown(PopupEvent event);
 
61
 
 
62
                /**
 
63
                 * Fired when a popup panel has been hidden.
 
64
                 * 
 
65
                 * @param event
 
66
                 *            Popup event.
 
67
                 */
 
68
                void popupHidden(PopupEvent event);
 
69
        }
 
70
 
 
71
        /**
 
72
         * Popup event.
 
73
         * 
 
74
         * @author Kirill Grouchnikov
 
75
         */
 
76
        public static class PopupEvent extends ComponentEvent {
 
77
                /**
 
78
                 * ID of "popup shown" event.
 
79
                 */
 
80
                public static final int POPUP_SHOWN = 100;
 
81
 
 
82
                /**
 
83
                 * ID of "popup hidden" event.
 
84
                 */
 
85
                public static final int POPUP_HIDDEN = 101;
 
86
 
 
87
                /**
 
88
                 * The popup originator component.
 
89
                 */
 
90
                private JComponent popupOriginator;
 
91
 
 
92
                /**
 
93
                 * Creates a new popup event.
 
94
                 * 
 
95
                 * @param source
 
96
                 *            Event source.
 
97
                 * @param id
 
98
                 *            Event ID.
 
99
                 * @param popupOriginator
 
100
                 *            Popup originator component.
 
101
                 */
 
102
                public PopupEvent(JPopupPanel source, int id, JComponent popupOriginator) {
 
103
                        super(source, id);
 
104
                        this.popupOriginator = popupOriginator;
 
105
                }
 
106
 
 
107
                /**
 
108
                 * Returns the popup originator component.
 
109
                 * 
 
110
                 * @return Popup originator component.
 
111
                 */
 
112
                public JComponent getPopupOriginator() {
 
113
                        return this.popupOriginator;
 
114
                }
 
115
        }
 
116
 
 
117
        /**
 
118
         * List of all registered listeners.
 
119
         */
 
120
        protected EventListenerList listenerList = new EventListenerList();
 
121
 
 
122
        /**
 
123
         * The singleton instance of popup panel manager.
 
124
         */
 
125
        private static final PopupPanelManager instance = new PopupPanelManager();
 
126
 
 
127
        /**
 
128
         * Information on a single showing popup.
 
129
         * 
 
130
         * @author Kirill Grouchnikov
 
131
         */
 
132
        public static class PopupInfo {
 
133
                /**
 
134
                 * The popup panel.
 
135
                 */
 
136
                private JPopupPanel popupPanel;
 
137
 
 
138
                /**
 
139
                 * The originating component.
 
140
                 */
 
141
                private JComponent popupOriginator;
 
142
 
 
143
                /**
 
144
                 * Creates a new information object.
 
145
                 * 
 
146
                 * @param popupOriginator
 
147
                 *            The originating component.
 
148
                 * @param popupPanel
 
149
                 *            The popup panel.
 
150
                 */
 
151
                public PopupInfo(JComponent popupOriginator, JPopupPanel popupPanel) {
 
152
                        this.popupOriginator = popupOriginator;
 
153
                        this.popupPanel = popupPanel;
 
154
                }
 
155
 
 
156
                /**
 
157
                 * Returns the popup panel.
 
158
                 * 
 
159
                 * @return The popup panel.
 
160
                 */
 
161
                public JPopupPanel getPopupPanel() {
 
162
                        return this.popupPanel;
 
163
                }
 
164
 
 
165
                /**
 
166
                 * Returns the originating component.
 
167
                 * 
 
168
                 * @return The originating component.
 
169
                 */
 
170
                public JComponent getPopupOriginator() {
 
171
                        return this.popupOriginator;
 
172
                }
 
173
        }
 
174
 
 
175
        /**
 
176
         * Returns the default popup panel manager.
 
177
         * 
 
178
         * @return a PopupPanelManager object
 
179
         */
 
180
        public static PopupPanelManager defaultManager() {
 
181
                return instance;
 
182
        }
 
183
 
 
184
        /**
 
185
         * All currently shown popup panels.
 
186
         */
 
187
        protected LinkedList<PopupInfo> shownPath = new LinkedList<PopupInfo>();
 
188
 
 
189
        /**
 
190
         * Map of all popup panels and associated {@link Popup} objects.
 
191
         */
 
192
        protected Map<JPopupPanel, Popup> popupPanels = new HashMap<JPopupPanel, Popup>();
 
193
 
 
194
        /**
 
195
         * Adds new popup to the tracking structures.
 
196
         * 
 
197
         * @param popupOriginator
 
198
         *            The originating component.
 
199
         * @param popup
 
200
         *            The new popup.
 
201
         * @param popupInitiator
 
202
         *            The initiator of the popup.
 
203
         */
 
204
        public void addPopup(JComponent popupOriginator, Popup popup,
 
205
                        JPopupPanel popupInitiator) {
 
206
                popupPanels.put(popupInitiator, popup);
 
207
                shownPath.addLast(new PopupInfo(popupOriginator, popupInitiator));
 
208
                popup.show();
 
209
                if (popupOriginator instanceof JCommandButton) {
 
210
                        ((JCommandButton) popupOriginator).getPopupModel().setPopupShowing(
 
211
                                        true);
 
212
                }
 
213
                this.firePopupShown(popupInitiator, popupOriginator);
 
214
        }
 
215
 
 
216
        /**
 
217
         * Hides the last shown popup panel.
 
218
         */
 
219
        public void hideLastPopup() {
 
220
                if (shownPath.size() == 0)
 
221
                        return;
 
222
                PopupInfo last = shownPath.removeLast();
 
223
                Popup popup = popupPanels.get(last.popupPanel);
 
224
                popup.hide();
 
225
                popupPanels.remove(last.popupPanel);
 
226
                if (last.popupOriginator instanceof JCommandButton) {
 
227
                        ((JCommandButton) last.popupOriginator).getPopupModel()
 
228
                                        .setPopupShowing(false);
 
229
                }
 
230
 
 
231
                // KeyTipManager.defaultManager().showChainBefore(last.popupPanel);
 
232
                this.firePopupHidden(last.popupPanel, last.popupOriginator);
 
233
        }
 
234
 
 
235
        /**
 
236
         * Hides all popup panels based on the specified component. We find the
 
237
         * first ancestor of the specified component that is popup panel, and close
 
238
         * all popup panels that were open from that popup panel. If the specified
 
239
         * component is <code>null</code>, all popup panels are closed.
 
240
         * 
 
241
         * @param comp
 
242
         *            Component.
 
243
         */
 
244
        public void hidePopups(Component comp) {
 
245
                // System.out.println("Hiding all popups");
 
246
                // try {
 
247
                // throw new Exception();
 
248
                // }
 
249
                // catch (Exception exc) {
 
250
                // exc.printStackTrace(System.out);
 
251
                // System.out.println("At " + System.currentTimeMillis() + "\n");
 
252
                // }
 
253
                boolean foundAndDismissed = false;
 
254
                if (comp != null) {
 
255
                        Component c = comp;
 
256
                        // find JPopupGallery parent of the component
 
257
                        while (c != null) {
 
258
                                if (c instanceof JPopupPanel) {
 
259
                                        foundAndDismissed = true;
 
260
                                        // And close all popups that were opened
 
261
                                        // from the found popup panel
 
262
                                        while (shownPath.size() > 0) {
 
263
                                                if (shownPath.getLast().popupPanel == c)
 
264
                                                        return;
 
265
                                                PopupInfo last = shownPath.removeLast();
 
266
                                                Popup popup = popupPanels.get(last.popupPanel);
 
267
                                                popup.hide();
 
268
                                                if (last.popupOriginator instanceof JCommandButton) {
 
269
                                                        ((JCommandButton) last.popupOriginator)
 
270
                                                                        .getPopupModel().setPopupShowing(false);
 
271
                                                }
 
272
                                                this.firePopupHidden(last.popupPanel,
 
273
                                                                last.popupOriginator);
 
274
                                                popupPanels.remove(last.popupPanel);
 
275
                                        }
 
276
                                }
 
277
                                c = c.getParent();
 
278
                        }
 
279
                }
 
280
                if (!foundAndDismissed || (comp == null)) {
 
281
                        while (shownPath.size() > 0) {
 
282
                                PopupInfo last = shownPath.removeLast();
 
283
                                Popup popup = popupPanels.get(last.popupPanel);
 
284
                                popup.hide();
 
285
                                if (last.popupOriginator instanceof JCommandButton) {
 
286
                                        ((JCommandButton) last.popupOriginator).getPopupModel()
 
287
                                                        .setPopupShowing(false);
 
288
                                }
 
289
                                this.firePopupHidden(last.popupPanel, last.popupOriginator);
 
290
                                popupPanels.remove(last.popupPanel);
 
291
                        }
 
292
                }
 
293
        }
 
294
 
 
295
        /**
 
296
         * Returns all currently shown popup panels.
 
297
         * 
 
298
         * @return All currently shown popup panels.
 
299
         */
 
300
        public List<PopupInfo> getShownPath() {
 
301
                List<PopupInfo> toReturn = new ArrayList<PopupInfo>();
 
302
                for (PopupInfo pInfo : this.shownPath)
 
303
                        toReturn.add(pInfo);
 
304
                return toReturn;
 
305
        }
 
306
 
 
307
        /**
 
308
         * Adds the specified popup listener.
 
309
         * 
 
310
         * @param l
 
311
         *            Listener to add.
 
312
         */
 
313
        public void addPopupListener(PopupListener l) {
 
314
                this.listenerList.add(PopupListener.class, l);
 
315
        }
 
316
 
 
317
        /**
 
318
         * Removes the specified popup listener.
 
319
         * 
 
320
         * @param l
 
321
         *            Listener to remove.
 
322
         */
 
323
        public void removePopupListener(PopupListener l) {
 
324
                this.listenerList.remove(PopupListener.class, l);
 
325
        }
 
326
 
 
327
        /**
 
328
         * Fires an event on showing the specified popup panel.
 
329
         * 
 
330
         * @param panel
 
331
         *            Popup panel that was shown.
 
332
         * @param popupOriginator
 
333
         *            The originating component.
 
334
         */
 
335
        protected void firePopupShown(JPopupPanel panel, JComponent popupOriginator) {
 
336
                // Guaranteed to return a non-null array
 
337
                Object[] listeners = listenerList.getListenerList();
 
338
                PopupEvent popupEvent = new PopupEvent(panel, PopupEvent.POPUP_SHOWN,
 
339
                                popupOriginator);
 
340
                // Process the listeners last to first, notifying
 
341
                // those that are interested in this event
 
342
                for (int i = listeners.length - 2; i >= 0; i -= 2) {
 
343
                        if (listeners[i] == PopupListener.class) {
 
344
                                ((PopupListener) listeners[i + 1]).popupShown(popupEvent);
 
345
                        }
 
346
                }
 
347
        }
 
348
 
 
349
        /**
 
350
         * Fires an event on hiding the specified popup panel.
 
351
         * 
 
352
         * @param panel
 
353
         *            Popup panel that was hidden.
 
354
         * @param popupOriginator
 
355
         *            The originating component.
 
356
         */
 
357
        protected void firePopupHidden(JPopupPanel panel, JComponent popupOriginator) {
 
358
                // Guaranteed to return a non-null array
 
359
                Object[] listeners = listenerList.getListenerList();
 
360
                PopupEvent popupEvent = new PopupEvent(panel, PopupEvent.POPUP_HIDDEN,
 
361
                                popupOriginator);
 
362
                // Process the listeners last to first, notifying
 
363
                // those that are interested in this event
 
364
                for (int i = listeners.length - 2; i >= 0; i -= 2) {
 
365
                        if (listeners[i] == PopupListener.class) {
 
366
                                ((PopupListener) listeners[i + 1]).popupHidden(popupEvent);
 
367
                        }
 
368
                }
 
369
        }
 
370
}