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 26package javax.swing.plaf.basic; 27 28import java.awt.*; 29import java.awt.event.*; 30import javax.swing.*; 31import javax.swing.event.*; 32import javax.swing.border.*; 33import javax.swing.plaf.*; 34import 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 */ 43public 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 */ 69 public static ComponentUI createUI(JComponent c) { 70 return new BasicDesktopIconUI(); 71 } 72 73 /** 74 * Constructs a new instance of {@code BasicDesktopIconUI}. 75 */ 76 public BasicDesktopIconUI() { 77 } 78 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 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 */ 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 */ 137 protected void uninstallComponents() { 138 desktopIcon.remove(iconPane); 139 desktopIcon.setLayout(null); 140 iconPane = null; 141 } 142 143 /** 144 * Registers listeners. 145 */ 146 protected void installListeners() { 147 mouseInputListener = createMouseInputListener(); 148 desktopIcon.addMouseMotionListener(mouseInputListener); 149 desktopIcon.addMouseListener(mouseInputListener); 150 } 151 152 /** 153 * Unregisters listeners. 154 */ 155 protected void uninstallListeners() { 156 desktopIcon.removeMouseMotionListener(mouseInputListener); 157 desktopIcon.removeMouseListener(mouseInputListener); 158 mouseInputListener = null; 159 } 160 161 /** 162 * Installs default properties. 163 */ 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 */ 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 */ 181 protected MouseInputListener createMouseInputListener() { 182 return new MouseInputHandler(); 183 } 184 185 public Dimension getPreferredSize(JComponent c) { 186 return desktopIcon.getLayout().preferredLayoutSize(desktopIcon); 187 } 188 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 */ 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 */ 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 */ 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 public void mouseReleased(MouseEvent e) { 247 _x = 0; 248 _y = 0; 249 __x = 0; 250 __y = 0; 251 startingBounds = null; 252 253 JDesktopPane d; 254 if((d = desktopIcon.getDesktopPane()) != null) { 255 DesktopManager dm = d.getDesktopManager(); 256 dm.endDraggingFrame(desktopIcon); 257 } 258 259 } 260 261 public void mousePressed(MouseEvent e) { 262 Point p = SwingUtilities.convertPoint((Component)e.getSource(), 263 e.getX(), e.getY(), null); 264 __x = e.getX(); 265 __y = e.getY(); 266 _x = p.x; 267 _y = p.y; 268 startingBounds = desktopIcon.getBounds(); 269 270 JDesktopPane d; 271 if((d = desktopIcon.getDesktopPane()) != null) { 272 DesktopManager dm = d.getDesktopManager(); 273 dm.beginDraggingFrame(desktopIcon); 274 } 275 276 try { frame.setSelected(true); } catch (PropertyVetoException e1) { } 277 if(desktopIcon.getParent() instanceof JLayeredPane) { 278 ((JLayeredPane)desktopIcon.getParent()).moveToFront(desktopIcon); 279 } 280 281 if(e.getClickCount() > 1) { 282 if(frame.isIconifiable() && frame.isIcon()) { 283 deiconize(); 284 } 285 } 286 287 } 288 289 public void mouseMoved(MouseEvent e) {} 290 291 public void mouseDragged(MouseEvent e) { 292 Point p; 293 int newX, newY, newW, newH; 294 int deltaX; 295 int deltaY; 296 Dimension min; 297 Dimension max; 298 p = SwingUtilities.convertPoint((Component)e.getSource(), 299 e.getX(), e.getY(), null); 300 301 Insets i = desktopIcon.getInsets(); 302 int pWidth, pHeight; 303 pWidth = ((JComponent)desktopIcon.getParent()).getWidth(); 304 pHeight = ((JComponent)desktopIcon.getParent()).getHeight(); 305 306 if (startingBounds == null) { 307 // (STEVE) Yucky work around for bug ID 4106552 308 return; 309 } 310 newX = startingBounds.x - (_x - p.x); 311 newY = startingBounds.y - (_y - p.y); 312 // Make sure we stay in-bounds 313 if(newX + i.left <= -__x) 314 newX = -__x - i.left; 315 if(newY + i.top <= -__y) 316 newY = -__y - i.top; 317 if(newX + __x + i.right > pWidth) 318 newX = pWidth - __x - i.right; 319 if(newY + __y + i.bottom > pHeight) 320 newY = pHeight - __y - i.bottom; 321 322 JDesktopPane d; 323 if((d = desktopIcon.getDesktopPane()) != null) { 324 DesktopManager dm = d.getDesktopManager(); 325 dm.dragFrame(desktopIcon, newX, newY); 326 } else { 327 moveAndRepaint(desktopIcon, newX, newY, 328 desktopIcon.getWidth(), desktopIcon.getHeight()); 329 } 330 return; 331 } 332 333 /** 334 * Moves and repaints a component {@code f}. 335 * 336 * @param f a component 337 * @param newX a new X coordinate 338 * @param newY a new Y coordinate 339 * @param newWidth a new width 340 * @param newHeight a new height 341 */ 342 public void moveAndRepaint(JComponent f, int newX, int newY, 343 int newWidth, int newHeight) { 344 Rectangle r = f.getBounds(); 345 f.setBounds(newX, newY, newWidth, newHeight); 346 SwingUtilities.computeUnion(newX, newY, newWidth, newHeight, r); 347 f.getParent().repaint(r.x, r.y, r.width, r.height); 348 } 349 }; /// End MotionListener 350 351} 352