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