1 /*
2  * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 package javax.swing.plaf.basic;
27 
28 import java.awt.*;
29 import java.awt.event.*;
30 import javax.swing.*;
31 import javax.swing.event.*;
32 import javax.swing.border.*;
33 import javax.swing.plaf.*;
34 import java.beans.*;
35 
36 /**
37  * Basic L&F for a minimized window on a desktop.
38  *
39  * @author David Kloba
40  * @author Steve Wilson
41  * @author Rich Schiavi
42  */
43 public class BasicDesktopIconUI extends DesktopIconUI {
44 
45     /**
46      * The instance of {@code JInternalFrame.JDesktopIcon}.
47      */
48     protected JInternalFrame.JDesktopIcon desktopIcon;
49 
50     /**
51      * The instance of {@code JInternalFrame}.
52      */
53     protected JInternalFrame frame;
54 
55     /**
56      * The title pane component used in the desktop icon.
57      *
58      * @since 1.5
59      */
60     protected JComponent iconPane;
61     MouseInputListener mouseInputListener;
62 
63     /**
64      * Constructs a new instance of {@code BasicDesktopIconUI}.
65      *
66      * @param c a component
67      * @return a new instance of {@code BasicDesktopIconUI}
68      */
createUI(JComponent c)69     public static ComponentUI createUI(JComponent c)    {
70         return new BasicDesktopIconUI();
71     }
72 
73     /**
74      * Constructs a new instance of {@code BasicDesktopIconUI}.
75      */
BasicDesktopIconUI()76     public BasicDesktopIconUI() {
77     }
78 
installUI(JComponent c)79     public void installUI(JComponent c)   {
80         desktopIcon = (JInternalFrame.JDesktopIcon)c;
81         frame = desktopIcon.getInternalFrame();
82         installDefaults();
83         installComponents();
84 
85         // Update icon layout if frame is already iconified
86         JInternalFrame f = desktopIcon.getInternalFrame();
87         if (f.isIcon() && f.getParent() == null) {
88             JDesktopPane desktop = desktopIcon.getDesktopPane();
89             if (desktop != null) {
90                 DesktopManager desktopManager = desktop.getDesktopManager();
91                 if (desktopManager instanceof DefaultDesktopManager) {
92                     desktopManager.iconifyFrame(f);
93                 }
94             }
95         }
96 
97         installListeners();
98         JLayeredPane.putLayer(desktopIcon, JLayeredPane.getLayer(frame));
99     }
100 
uninstallUI(JComponent c)101     public void uninstallUI(JComponent c) {
102         uninstallDefaults();
103         uninstallComponents();
104 
105         // Force future UI to relayout icon
106         JInternalFrame f = desktopIcon.getInternalFrame();
107         if (f.isIcon()) {
108             JDesktopPane desktop = desktopIcon.getDesktopPane();
109             if (desktop != null) {
110                 DesktopManager desktopManager = desktop.getDesktopManager();
111                 if (desktopManager instanceof DefaultDesktopManager) {
112                     // This will cause DefaultDesktopManager to layout the icon
113                     f.putClientProperty("wasIconOnce", null);
114                     // Move aside to allow fresh layout of all icons
115                     desktopIcon.setLocation(Integer.MIN_VALUE, 0);
116                 }
117             }
118         }
119 
120         uninstallListeners();
121         frame = null;
122         desktopIcon = null;
123     }
124 
125     /**
126      * Registers components.
127      */
installComponents()128     protected void installComponents() {
129         iconPane = new BasicInternalFrameTitlePane(frame);
130         desktopIcon.setLayout(new BorderLayout());
131         desktopIcon.add(iconPane, BorderLayout.CENTER);
132     }
133 
134     /**
135      * Unregisters components.
136      */
uninstallComponents()137     protected void uninstallComponents() {
138         desktopIcon.remove(iconPane);
139         desktopIcon.setLayout(null);
140         iconPane = null;
141     }
142 
143     /**
144      * Registers listeners.
145      */
installListeners()146     protected void installListeners() {
147         mouseInputListener = createMouseInputListener();
148         desktopIcon.addMouseMotionListener(mouseInputListener);
149         desktopIcon.addMouseListener(mouseInputListener);
150     }
151 
152     /**
153      * Unregisters listeners.
154      */
uninstallListeners()155     protected void uninstallListeners() {
156         desktopIcon.removeMouseMotionListener(mouseInputListener);
157         desktopIcon.removeMouseListener(mouseInputListener);
158         mouseInputListener = null;
159     }
160 
161     /**
162      * Installs default properties.
163      */
installDefaults()164     protected void installDefaults() {
165         LookAndFeel.installBorder(desktopIcon, "DesktopIcon.border");
166         LookAndFeel.installProperty(desktopIcon, "opaque", Boolean.TRUE);
167     }
168 
169     /**
170      * Uninstalls default properties.
171      */
uninstallDefaults()172     protected void uninstallDefaults() {
173         LookAndFeel.uninstallBorder(desktopIcon);
174     }
175 
176     /**
177      * Returns a new instance of {@code MouseInputListener}.
178      *
179      * @return a new instance of {@code MouseInputListener}
180      */
createMouseInputListener()181     protected MouseInputListener createMouseInputListener() {
182         return new MouseInputHandler();
183     }
184 
getPreferredSize(JComponent c)185     public Dimension getPreferredSize(JComponent c) {
186         return desktopIcon.getLayout().preferredLayoutSize(desktopIcon);
187     }
188 
getMinimumSize(JComponent c)189     public Dimension getMinimumSize(JComponent c) {
190         Dimension dim = new Dimension(iconPane.getMinimumSize());
191         Border border = frame.getBorder();
192 
193         if (border != null) {
194             dim.height += border.getBorderInsets(frame).bottom +
195                           border.getBorderInsets(frame).top;
196         }
197         return dim;
198     }
199 
200     /**
201      * Desktop icons can not be resized.  Therefore, we should always
202      * return the minimum size of the desktop icon.
203      *
204      * @see #getMinimumSize
205      */
getMaximumSize(JComponent c)206     public Dimension getMaximumSize(JComponent c){
207         return iconPane.getMaximumSize();
208     }
209 
210     /**
211      * Returns the insets.
212      *
213      * @param c a component
214      * @return the insets
215      */
getInsets(JComponent c)216     public Insets getInsets(JComponent c) {
217         JInternalFrame iframe = desktopIcon.getInternalFrame();
218         Border border = iframe.getBorder();
219         if(border != null)
220             return border.getBorderInsets(iframe);
221 
222         return new Insets(0,0,0,0);
223     }
224 
225     /**
226      * De-iconifies the internal frame.
227      */
deiconize()228     public void deiconize() {
229         try { frame.setIcon(false); } catch (PropertyVetoException e2) { }
230     }
231 
232     /**
233      * Listens for mouse movements and acts on them.
234      *
235      * This class should be treated as a "protected" inner class.
236      * Instantiate it only within subclasses of {@code BasicDesktopIconUI}.
237      */
238     public class MouseInputHandler extends MouseInputAdapter
239     {
240         // _x & _y are the mousePressed location in absolute coordinate system
241         int _x, _y;
242         // __x & __y are the mousePressed location in source view's coordinate system
243         int __x, __y;
244         Rectangle startingBounds;
245 
246         /**
247          * Constructs a {@code MouseInputHandler}.
248          */
MouseInputHandler()249         public MouseInputHandler() {}
250 
mouseReleased(MouseEvent e)251         public void mouseReleased(MouseEvent e) {
252             _x = 0;
253             _y = 0;
254             __x = 0;
255             __y = 0;
256             startingBounds = null;
257 
258             JDesktopPane d;
259             if((d = desktopIcon.getDesktopPane()) != null) {
260                 DesktopManager dm = d.getDesktopManager();
261                 dm.endDraggingFrame(desktopIcon);
262             }
263 
264         }
265 
mousePressed(MouseEvent e)266         public void mousePressed(MouseEvent e) {
267             Point p = SwingUtilities.convertPoint((Component)e.getSource(),
268                         e.getX(), e.getY(), null);
269             __x = e.getX();
270             __y = e.getY();
271             _x = p.x;
272             _y = p.y;
273             startingBounds = desktopIcon.getBounds();
274 
275             JDesktopPane d;
276             if((d = desktopIcon.getDesktopPane()) != null) {
277                 DesktopManager dm = d.getDesktopManager();
278                 dm.beginDraggingFrame(desktopIcon);
279             }
280 
281             try { frame.setSelected(true); } catch (PropertyVetoException e1) { }
282             if(desktopIcon.getParent() instanceof JLayeredPane) {
283                 ((JLayeredPane)desktopIcon.getParent()).moveToFront(desktopIcon);
284             }
285 
286             if(e.getClickCount() > 1) {
287                 if(frame.isIconifiable() && frame.isIcon()) {
288                     deiconize();
289                 }
290             }
291 
292         }
293 
mouseMoved(MouseEvent e)294          public void mouseMoved(MouseEvent e) {}
295 
mouseDragged(MouseEvent e)296          public void mouseDragged(MouseEvent e) {
297             Point p;
298             int newX, newY, newW, newH;
299             int deltaX;
300             int deltaY;
301             Dimension min;
302             Dimension max;
303             p = SwingUtilities.convertPoint((Component)e.getSource(),
304                                         e.getX(), e.getY(), null);
305 
306                 Insets i = desktopIcon.getInsets();
307                 int pWidth, pHeight;
308                 pWidth = ((JComponent)desktopIcon.getParent()).getWidth();
309                 pHeight = ((JComponent)desktopIcon.getParent()).getHeight();
310 
311                 if (startingBounds == null) {
312                   // (STEVE) Yucky work around for bug ID 4106552
313                     return;
314                 }
315                 newX = startingBounds.x - (_x - p.x);
316                 newY = startingBounds.y - (_y - p.y);
317                 // Make sure we stay in-bounds
318                 if(newX + i.left <= -__x)
319                     newX = -__x - i.left;
320                 if(newY + i.top <= -__y)
321                     newY = -__y - i.top;
322                 if(newX + __x + i.right > pWidth)
323                     newX = pWidth - __x - i.right;
324                 if(newY + __y + i.bottom > pHeight)
325                     newY =  pHeight - __y - i.bottom;
326 
327                 JDesktopPane d;
328                 if((d = desktopIcon.getDesktopPane()) != null) {
329                     DesktopManager dm = d.getDesktopManager();
330                     dm.dragFrame(desktopIcon, newX, newY);
331                 } else {
332                     moveAndRepaint(desktopIcon, newX, newY,
333                                 desktopIcon.getWidth(), desktopIcon.getHeight());
334                 }
335                 return;
336         }
337 
338         /**
339          * Moves and repaints a component {@code f}.
340          *
341          * @param f a component
342          * @param newX a new X coordinate
343          * @param newY a new Y coordinate
344          * @param newWidth a new width
345          * @param newHeight a new height
346          */
moveAndRepaint(JComponent f, int newX, int newY, int newWidth, int newHeight)347         public void moveAndRepaint(JComponent f, int newX, int newY,
348                                         int newWidth, int newHeight) {
349             Rectangle r = f.getBounds();
350             f.setBounds(newX, newY, newWidth, newHeight);
351             SwingUtilities.computeUnion(newX, newY, newWidth, newHeight, r);
352             f.getParent().repaint(r.x, r.y, r.width, r.height);
353         }
354     }; /// End MotionListener
355 
356 }
357