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

« back to all changes in this revision

Viewing changes to laf-widget/src/main/java/org/pushingpixels/lafwidget/tabbed/TabPreviewWindow.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 Laf-Widget 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 Laf-Widget 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.lafwidget.tabbed;
 
31
 
 
32
import java.awt.*;
 
33
import java.awt.event.*;
 
34
import java.awt.image.BufferedImage;
 
35
 
 
36
import javax.swing.*;
 
37
 
 
38
import org.pushingpixels.lafwidget.*;
 
39
import org.pushingpixels.lafwidget.animation.AnimationConfigurationManager;
 
40
import org.pushingpixels.lafwidget.tabbed.TabPreviewThread.TabPreviewInfo;
 
41
import org.pushingpixels.trident.Timeline;
 
42
 
 
43
/**
 
44
 * Tab preview window. Is displayed when the mouse hovers over relevant
 
45
 * (previewable) tabs.
 
46
 * 
 
47
 * @author Kirill Grouchnikov
 
48
 */
 
49
public class TabPreviewWindow extends JWindow implements ActionListener {
 
50
        public static final class PreviewLabel extends JLabel {
 
51
                float alpha = 0.0f;
 
52
 
 
53
                private PreviewLabel(Icon image) {
 
54
                        super(image);
 
55
                }
 
56
 
 
57
                public void setAlpha(float alpha) {
 
58
                        this.alpha = alpha;
 
59
                        this.repaint();
 
60
                }
 
61
 
 
62
                @Override
 
63
                protected void paintComponent(Graphics g) {
 
64
                        Graphics2D g2 = (Graphics2D) g.create();
 
65
                        g2.setComposite(AlphaComposite.SrcOver.derive(this.alpha));
 
66
                        super.paintComponent(g2);
 
67
                        g2.dispose();
 
68
                }
 
69
        }
 
70
 
 
71
        /**
 
72
         * Singleton instance of tab preview window.
 
73
         */
 
74
        protected static TabPreviewWindow instance;
 
75
 
 
76
        /**
 
77
         * Information on the current tab preview request.
 
78
         */
 
79
        protected static TabPreviewInfo currTabPreviewInfo;
 
80
 
 
81
        /**
 
82
         * Currently running timer task.
 
83
         */
 
84
        protected static Timer currTabPreviewTimer;
 
85
 
 
86
        /**
 
87
         * Returns the singleton instance of tab preview window.
 
88
         * 
 
89
         * @return The singleton instance of tab preview window.
 
90
         */
 
91
        public static synchronized TabPreviewWindow getInstance() {
 
92
                if (TabPreviewWindow.instance == null) {
 
93
                        TabPreviewWindow.instance = new TabPreviewWindow();
 
94
                        TabPreviewWindow.instance.setLayout(new BorderLayout());
 
95
                        // instance.addHierarchyListener(new HierarchyListener() {
 
96
                        // public void hierarchyChanged(HierarchyEvent e) {
 
97
                        // System.err.println(e.getID());
 
98
                        // }
 
99
                        // });
 
100
                }
 
101
                return TabPreviewWindow.instance;
 
102
        }
 
103
 
 
104
        /**
 
105
         * Posts a preview request for a tab component in the specified tabbed pane.
 
106
         * 
 
107
         * @param tabPane
 
108
         *            Tabbed pane.
 
109
         * @param tabIndex
 
110
         *            Index of the tab to preview.
 
111
         */
 
112
        public synchronized void postPreviewRequest(JTabbedPane tabPane,
 
113
                        int tabIndex) {
 
114
                TabPreviewPainter previewPainter = LafWidgetUtilities2
 
115
                                .getTabPreviewPainter(tabPane);
 
116
                if ((previewPainter == null)
 
117
                                || (!previewPainter.hasPreviewWindow(tabPane, tabIndex)))
 
118
                        return;
 
119
 
 
120
                // check if already showing
 
121
                if (currTabPreviewInfo != null) {
 
122
                        if ((currTabPreviewInfo.tabPane == tabPane)
 
123
                                        && (currTabPreviewInfo.tabIndexToPreview == tabIndex))
 
124
                                return;
 
125
                }
 
126
 
 
127
                if (currTabPreviewTimer != null) {
 
128
                        if (currTabPreviewTimer.isRunning())
 
129
                                currTabPreviewTimer.stop();
 
130
                }
 
131
 
 
132
                Dimension previewDim = previewPainter.getPreviewWindowDimension(
 
133
                                tabPane, tabIndex);
 
134
                int pWidth = previewDim.width;
 
135
                int pHeight = previewDim.height;
 
136
                Component tabComponent = tabPane.getComponentAt(tabIndex);
 
137
                if (tabComponent != null) {
 
138
                        int width = tabComponent.getWidth();
 
139
                        int height = tabComponent.getHeight();
 
140
                        double ratio = (double) width / (double) height;
 
141
                        double pRatio = (double) previewDim.width
 
142
                                        / (double) previewDim.height;
 
143
                        if (pRatio > ratio) {
 
144
                                pWidth = (int) (pHeight * ratio);
 
145
                        } else {
 
146
                                pHeight = (int) (pWidth / ratio);
 
147
                        }
 
148
                }
 
149
 
 
150
                currTabPreviewInfo = new TabPreviewInfo();
 
151
                currTabPreviewInfo.tabPane = tabPane;
 
152
                currTabPreviewInfo.tabIndexToPreview = tabIndex;
 
153
                currTabPreviewInfo.setPreviewWidth(pWidth);
 
154
                currTabPreviewInfo.setPreviewHeight(pHeight);
 
155
                currTabPreviewInfo.initiator = tabPane;
 
156
                currTabPreviewInfo.previewCallback = new TabPreviewThread.TabPreviewCallback() {
 
157
                        /*
 
158
                         * (non-Javadoc)
 
159
                         * 
 
160
                         * @seeorg.pushingpixels.lafwidget.tabbed.TabPreviewThread.
 
161
                         * TabPreviewCallback #start(javax.swing.JTabbedPane, int,
 
162
                         * org.pushingpixels
 
163
                         * .lafwidget.tabbed.TabPreviewThread.TabPreviewInfo)
 
164
                         */
 
165
                        @Override
 
166
            public void start(JTabbedPane tabPane, int tabCount,
 
167
                                        TabPreviewInfo tabPreviewInfo) {
 
168
                                // Nothing to do since the callback was registered
 
169
                                // for a specific tab.
 
170
                        }
 
171
 
 
172
                        /*
 
173
                         * (non-Javadoc)
 
174
                         * 
 
175
                         * @seeorg.pushingpixels.lafwidget.tabbed.TabPreviewThread.
 
176
                         * TabPreviewCallback #offer(javax.swing.JTabbedPane, int,
 
177
                         * java.awt.image.BufferedImage)
 
178
                         */
 
179
                        @Override
 
180
            public void offer(JTabbedPane tabPane, int tabIndex,
 
181
                                        BufferedImage componentSnap) {
 
182
                                if (currTabPreviewInfo == null) {
 
183
                                        // has since been cancelled
 
184
                                        return;
 
185
                                }
 
186
                                if ((tabPane != currTabPreviewInfo.tabPane)
 
187
                                                || (tabIndex != currTabPreviewInfo.tabIndexToPreview)) {
 
188
                                        // has since been cancelled
 
189
                                        return;
 
190
                                }
 
191
                                Rectangle previewScreenRectangle = TabPreviewWindow.this
 
192
                                                .getPreviewWindowScreenRect(tabPane, tabIndex,
 
193
                                                                currTabPreviewInfo.getPreviewWidth(),
 
194
                                                                currTabPreviewInfo.getPreviewHeight());
 
195
                                TabPreviewWindow.this.getContentPane().removeAll();
 
196
                                final JLabel previewLabel = new PreviewLabel(new ImageIcon(
 
197
                                                componentSnap));
 
198
                                TabPreviewWindow.this
 
199
                                                .addComponentListener(new ComponentAdapter() {
 
200
                                                        @Override
 
201
                                                        public void componentShown(ComponentEvent e) {
 
202
                                                                previewLabel.setVisible(true);
 
203
                                                                // Start fading-in of the image.
 
204
                                                                Timeline timeline = new Timeline(previewLabel);
 
205
                                                                AnimationConfigurationManager.getInstance()
 
206
                                                                                .configureTimeline(timeline);
 
207
                                                                timeline.addPropertyToInterpolate("alpha",
 
208
                                                                                0.0f, 1.0f);
 
209
                                                                timeline.play();
 
210
                                                        }
 
211
                                                });
 
212
                                // previewLabel.setBorder(new SubstanceBorder());
 
213
                                TabPreviewWindow.this.getContentPane().add(previewLabel,
 
214
                                                BorderLayout.CENTER);
 
215
                                TabPreviewWindow.this.setSize(previewScreenRectangle.width,
 
216
                                                previewScreenRectangle.height);
 
217
                                TabPreviewWindow.this.setLocation(previewScreenRectangle.x,
 
218
                                                previewScreenRectangle.y);
 
219
                                previewLabel.setVisible(false);
 
220
                                TabPreviewWindow.this.setVisible(true);
 
221
                        }
 
222
                };
 
223
 
 
224
                int extraDelay = previewPainter.getPreviewWindowExtraDelay(tabPane,
 
225
                                tabIndex);
 
226
                if (extraDelay < 0) {
 
227
                        throw new IllegalArgumentException(
 
228
                                        "Extra delay for tab preview must be non-negative");
 
229
                }
 
230
                currTabPreviewTimer = new Timer(2000 + extraDelay, this);
 
231
                currTabPreviewTimer.setRepeats(false);
 
232
                currTabPreviewTimer.start();
 
233
        }
 
234
 
 
235
        /*
 
236
         * (non-Javadoc)
 
237
         * 
 
238
         * @see
 
239
         * java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
 
240
         */
 
241
        @Override
 
242
    public void actionPerformed(ActionEvent e) {
 
243
                if (currTabPreviewInfo == null)
 
244
                        return;
 
245
 
 
246
                // If we are here - the delay timer has expired.
 
247
 
 
248
                // System.err.println("Post " + tabIndex);
 
249
                TabPreviewPainter previewPainter = LafWidgetUtilities2
 
250
                                .getTabPreviewPainter(currTabPreviewInfo.tabPane);
 
251
                if ((previewPainter == null)
 
252
                                || (!previewPainter.hasPreviewWindow(
 
253
                                                currTabPreviewInfo.tabPane,
 
254
                                                currTabPreviewInfo.tabIndexToPreview)))
 
255
                        return;
 
256
 
 
257
                // Queue the request with the preview thread.
 
258
                TabPreviewThread.getInstance().queueTabPreviewRequest(
 
259
                                currTabPreviewInfo);
 
260
        }
 
261
 
 
262
        /**
 
263
         * Returns the screen rectangle for the preview window.
 
264
         * 
 
265
         * @param tabPane
 
266
         *            Tabbed pane.
 
267
         * @param tabIndex
 
268
         *            Tab index.
 
269
         * @param pWidth
 
270
         *            Preview width.
 
271
         * @param pHeight
 
272
         *            Preview height.
 
273
         * @return The screen rectangle for the preview window.
 
274
         */
 
275
        protected Rectangle getPreviewWindowScreenRect(JTabbedPane tabPane,
 
276
                        int tabIndex, int pWidth, int pHeight) {
 
277
                LafWidgetSupport lafSupport = LafWidgetRepository.getRepository()
 
278
                                .getLafSupport();
 
279
 
 
280
                Rectangle relative = lafSupport.getTabRectangle(tabPane, tabIndex);
 
281
                if (relative == null)
 
282
                        return null;
 
283
 
 
284
                Rectangle result = new Rectangle(pWidth, pHeight);
 
285
                boolean ltr = tabPane.getComponentOrientation().isLeftToRight();
 
286
                if (ltr) {
 
287
                        if (tabPane.getTabPlacement() != SwingConstants.BOTTOM) {
 
288
                                result.setLocation(relative.x, relative.y + relative.height);
 
289
                        } else {
 
290
                                result.setLocation(relative.x, relative.y - pHeight);
 
291
                        }
 
292
                } else {
 
293
                        if (tabPane.getTabPlacement() != SwingConstants.BOTTOM) {
 
294
                                result.setLocation(relative.x + relative.width - pWidth,
 
295
                                                relative.y + relative.height);
 
296
                        } else {
 
297
                                result.setLocation(relative.x + relative.width - pWidth,
 
298
                                                relative.y - pHeight);
 
299
                        }
 
300
                }
 
301
                int dx = tabPane.getLocationOnScreen().x;
 
302
                int dy = tabPane.getLocationOnScreen().y;
 
303
                result.x += dx;
 
304
                result.y += dy;
 
305
 
 
306
                // Fix to make the tab preview window stay in screen bounds
 
307
                Rectangle virtualBounds = new Rectangle();
 
308
                GraphicsEnvironment ge = GraphicsEnvironment
 
309
                                .getLocalGraphicsEnvironment();
 
310
                GraphicsDevice[] gds = ge.getScreenDevices();
 
311
                for (int i = 0; i < gds.length; i++) {
 
312
                        GraphicsDevice gd = gds[i];
 
313
                        GraphicsConfiguration gc = gd.getDefaultConfiguration();
 
314
                        virtualBounds = virtualBounds.union(gc.getBounds());
 
315
                }
 
316
 
 
317
                if (result.x + result.width > (virtualBounds.width - 1)) {
 
318
                        result.x -= (result.x + result.width - virtualBounds.width + 1);
 
319
                }
 
320
                if (result.y + result.height > (virtualBounds.height - 1)) {
 
321
                        result.y -= (result.y + result.height - virtualBounds.height + 1);
 
322
                }
 
323
                if (result.x < virtualBounds.x)
 
324
                        result.x = virtualBounds.x + 1;
 
325
                if (result.y < virtualBounds.y)
 
326
                        result.y = virtualBounds.y + 1;
 
327
                return result;
 
328
        }
 
329
 
 
330
        /**
 
331
         * Cancels the currently pending preview request.
 
332
         */
 
333
        public static synchronized void cancelPreviewRequest() {
 
334
                // System.err.println("Cancel");
 
335
                currTabPreviewInfo = null;
 
336
                if ((currTabPreviewTimer != null) && currTabPreviewTimer.isRunning()) {
 
337
                        currTabPreviewTimer.stop();
 
338
                        currTabPreviewTimer = null;
 
339
                }
 
340
                if (instance != null)
 
341
                        instance.dispose();// setVisible(false);
 
342
        }
 
343
}