Frames | No Frames |
1: /* BasicDesktopIconUI.java -- 2: Copyright (C) 2004, 2005 Free Software Foundation, Inc. 3: 4: This file is part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2, or (at your option) 9: any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; see the file COPYING. If not, write to the 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19: 02110-1301 USA. 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. */ 37: 38: 39: package javax.swing.plaf.basic; 40: 41: import java.awt.BorderLayout; 42: import java.awt.Color; 43: import java.awt.Component; 44: import java.awt.Dimension; 45: import java.awt.Graphics; 46: import java.awt.Insets; 47: import java.awt.Rectangle; 48: import java.awt.event.ActionEvent; 49: import java.awt.event.ActionListener; 50: import java.awt.event.MouseEvent; 51: import java.beans.PropertyChangeEvent; 52: import java.beans.PropertyChangeListener; 53: import java.beans.PropertyVetoException; 54: 55: import javax.swing.Icon; 56: import javax.swing.JButton; 57: import javax.swing.JComponent; 58: import javax.swing.JDesktopPane; 59: import javax.swing.JInternalFrame; 60: import javax.swing.JInternalFrame.JDesktopIcon; 61: import javax.swing.SwingConstants; 62: import javax.swing.border.Border; 63: import javax.swing.event.MouseInputAdapter; 64: import javax.swing.event.MouseInputListener; 65: import javax.swing.plaf.ComponentUI; 66: import javax.swing.plaf.DesktopIconUI; 67: 68: /** 69: * This class acts as the UI delegate for JDesktopIcons for the Basic look and feel. 70: */ 71: public class BasicDesktopIconUI extends DesktopIconUI 72: { 73: /** 74: * This helper class handles mouse events that occur on the JDesktopIcon. 75: */ 76: public class MouseInputHandler extends MouseInputAdapter 77: { 78: /** The x offset from the MouseEvent coordinates to the top left corner. */ 79: private transient int xOffset; 80: 81: /** The y offset fromt he MouseEvent coordinates to the top left corner. */ 82: private transient int yOffset; 83: 84: /** A cached value of the JDesktopPane that parents this JDesktopIcon. */ 85: private transient JDesktopPane pane; 86: 87: /** 88: * This method is called when the mouse is dragged in the JDesktopIcon. 89: * 90: * @param e The MouseEvent. 91: */ 92: public void mouseDragged(MouseEvent e) 93: { 94: Rectangle b = desktopIcon.getBounds(); 95: 96: moveAndRepaint(desktopIcon, b.x + e.getX() - xOffset, 97: b.y + e.getY() - yOffset, b.width, b.height); 98: } 99: 100: /** 101: * This method is called when the mouse is moved in the JDesktopIcon. 102: * 103: * @param e The MouseEvent. 104: */ 105: public void mouseMoved(MouseEvent e) 106: { 107: // Nothing to do. 108: } 109: 110: /** 111: * This method is called when the mouse is pressed in the JDesktopIcon. 112: * 113: * @param e The MouseEvent. 114: */ 115: public void mousePressed(MouseEvent e) 116: { 117: xOffset = e.getX(); 118: yOffset = e.getY(); 119: pane = frame.getDesktopPane(); 120: if (pane != null) 121: pane.getDesktopManager().beginDraggingFrame(desktopIcon); 122: } 123: 124: /** 125: * This method is called when the mouse is released in the JDesktopIcon. 126: * 127: * @param e The MouseEvent. 128: */ 129: public void mouseReleased(MouseEvent e) 130: { 131: if (pane != null) 132: pane.getDesktopManager().endDraggingFrame(desktopIcon); 133: xOffset = 0; 134: yOffset = 0; 135: } 136: 137: /** 138: * This method moves and repaints the JDesktopIcon to the given bounds. 139: * 140: * @param f The JComponent to move and repaint. 141: * @param newX The new x coordinate. 142: * @param newY The new y coordinate. 143: * @param newWidth The new width. 144: * @param newHeight The new height. 145: */ 146: public void moveAndRepaint(JComponent f, int newX, int newY, int newWidth, 147: int newHeight) 148: { 149: if (pane != null) 150: pane.getDesktopManager().dragFrame(f, newX, newY); 151: else 152: desktopIcon.setBounds(newX, newY, newWidth, newHeight); 153: } 154: } 155: 156: /** 157: * This class acts as the border for the JDesktopIcon. 158: */ 159: private class DesktopIconBorder implements Border 160: { 161: /** The left inset value. */ 162: int left = 10; 163: 164: /** The top inset value. */ 165: int top = 4; 166: 167: /** The right inset value. */ 168: int right = top; 169: 170: /** The bottom inset value. */ 171: int bottom = top; 172: 173: /** 174: * This method returns the insets of the border. 175: * 176: * @param c The Component to find border insets for. 177: * 178: * @return The border insets. 179: */ 180: public Insets getBorderInsets(Component c) 181: { 182: return new Insets(top, left, bottom, right); 183: } 184: 185: /** 186: * This method returns whether the border is opaque. 187: * 188: * @return Whether the border is opaque. 189: */ 190: public boolean isBorderOpaque() 191: { 192: return true; 193: } 194: 195: /** 196: * This method paints the border. 197: * 198: * @param c The Component the border is in. 199: * @param g The Graphics object to paint with. 200: * @param x The x coordinate of the Component. 201: * @param y The y coordinate of the Component. 202: * @param width The width of the Component. 203: * @param height The height of the Component. 204: */ 205: public void paintBorder(Component c, Graphics g, int x, int y, int width, 206: int height) 207: { 208: g.translate(x, y); 209: Color saved = g.getColor(); 210: 211: g.setColor(Color.LIGHT_GRAY); 212: 213: g.fillRect(0, 0, left, height); 214: g.fillRect(0, 0, width, top); 215: g.fillRect(0, height - bottom, width, bottom); 216: g.fillRect(width - right, 0, right, height); 217: 218: g.setColor(Color.BLACK); 219: g.drawRect(0, 0, width - 1, height - 1); 220: 221: int fHeight = height / 4; 222: int hLeft = left / 2; 223: 224: g.setColor(Color.BLACK); 225: g.fillRect(hLeft, fHeight, 2, 2); 226: g.fillRect(hLeft, fHeight * 2, 2, 2); 227: g.fillRect(hLeft, fHeight * 3, 2, 2); 228: 229: g.setColor(saved); 230: g.translate(-x, -y); 231: } 232: } 233: 234: /** The static width and height of the iconSize. */ 235: private static final int iconSize = 16; 236: 237: /** 238: * This class represents the default frame icon when none 239: * is supplied by the JInternalFrame. 240: */ 241: static class InternalFrameDefaultMenuIcon implements Icon 242: { 243: /** 244: * This returns the icon height. 245: * 246: * @return The icon height. 247: */ 248: public int getIconHeight() 249: { 250: return iconSize; 251: } 252: 253: /** 254: * This returns the icon width. 255: * 256: * @return The icon width. 257: */ 258: public int getIconWidth() 259: { 260: return iconSize; 261: } 262: 263: /** 264: * This method paints the icon. 265: * 266: * @param c The Component this icon belongs to. 267: * @param g The Graphics object to paint with. 268: * @param x The x coordinate to paint at. 269: * @param y The y coordinate to paint at. 270: */ 271: public void paintIcon(Component c, Graphics g, int x, int y) 272: { 273: g.translate(x, y); 274: Color saved = g.getColor(); 275: 276: g.setColor(Color.BLUE); 277: g.fillRect(0, 0, iconSize, (int) ((double) iconSize / 3) + 1); 278: 279: g.setColor(Color.WHITE); 280: g.fillRect(0, (int) ((double) iconSize / 3), iconSize, iconSize * 5 / 6); 281: 282: g.setColor(Color.GRAY); 283: g.drawRect(0, 0, iconSize, iconSize); 284: 285: g.setColor(saved); 286: g.translate(-x, -y); 287: } 288: } 289: 290: /** The default JDesktopIcon width. */ 291: private static final int iconWidth = 160; 292: 293: /** The default JDesktopIcon height */ 294: private static final int iconHeight = 35; 295: 296: /** The JDesktopIcon this UI delegate represents. */ 297: protected JDesktopIcon desktopIcon; 298: 299: /** The JInternalFrame associated with the JDesktopIcon. */ 300: protected JInternalFrame frame; 301: 302: /** The MouseListener responsible for reacting to MouseEvents on the JDesktopIcon. */ 303: private transient MouseInputListener mouseHandler; 304: 305: /** The Button in the JDesktopIcon responsible for deiconifying it. 306: * This is package-private to avoid an accessor method. */ 307: transient BoundButton button; 308: 309: /** The PropertyChangeListener listening to the JDesktopIcon. */ 310: private transient PropertyChangeListener propertyHandler; 311: 312: /** The default icon used when no frame icon is given by the JInternalFrame. */ 313: static Icon defaultIcon = new InternalFrameDefaultMenuIcon(); 314: 315: /** 316: * This is a helper class that is used in JDesktopIcon and gives the Button a predetermined size. 317: */ 318: private class BoundButton extends JButton 319: { 320: /** 321: * Creates a new BoundButton object. 322: * 323: * @param title The title of the button. 324: */ 325: public BoundButton(String title) 326: { 327: super(title); 328: } 329: 330: /** 331: * This method returns a standard size (based on the defaults of the JDesktopIcon) and the insets. 332: * 333: * @return The preferred size of the JDesktopIcon. 334: */ 335: public Dimension getPreferredSize() 336: { 337: Insets insets = desktopIcon.getInsets(); 338: return new Dimension(iconWidth - insets.left - insets.right, 339: iconHeight - insets.top - insets.bottom); 340: } 341: 342: /** 343: * This method returns the minimum size of the button. 344: * 345: * @return The minimum size of the button. 346: */ 347: public Dimension getMinimumSize() 348: { 349: return getPreferredSize(); 350: } 351: 352: /** 353: * This method returns the maximum size of the button. 354: * 355: * @return The maximum size of the button. 356: */ 357: public Dimension getMaximumSize() 358: { 359: return getPreferredSize(); 360: } 361: } 362: 363: /** 364: * Creates a new BasicDesktopIconUI object. 365: */ 366: public BasicDesktopIconUI() 367: { 368: // Nothing to do here. 369: } 370: 371: /** 372: * This method creates a new BasicDesktopIconUI for the given JComponent. 373: * 374: * @param c The JComponent to create a UI for. 375: * 376: * @return A new BasicDesktopIconUI. 377: */ 378: public static ComponentUI createUI(JComponent c) 379: { 380: return new BasicDesktopIconUI(); 381: } 382: 383: /** 384: * This method installs the UI for the given JComponent. 385: * 386: * @param c The JComponent to install this UI for. 387: */ 388: public void installUI(JComponent c) 389: { 390: if (c instanceof JDesktopIcon) 391: { 392: desktopIcon = (JDesktopIcon) c; 393: desktopIcon.setLayout(new BorderLayout()); 394: frame = desktopIcon.getInternalFrame(); 395: 396: installDefaults(); 397: installComponents(); 398: installListeners(); 399: 400: desktopIcon.setOpaque(true); 401: } 402: } 403: 404: /** 405: * This method uninstalls the UI for the given JComponent. 406: * 407: * @param c The JComponent to uninstall this UI for. 408: */ 409: public void uninstallUI(JComponent c) 410: { 411: desktopIcon.setOpaque(false); 412: 413: uninstallListeners(); 414: uninstallComponents(); 415: uninstallDefaults(); 416: 417: frame = null; 418: desktopIcon.setLayout(null); 419: desktopIcon = null; 420: } 421: 422: /** 423: * This method installs the necessary sub components for the JDesktopIcon. 424: */ 425: protected void installComponents() 426: { 427: // Try to create a button based on what the frame's 428: // state is currently 429: button = new BoundButton(frame.getTitle()); 430: button.setHorizontalAlignment(SwingConstants.LEFT); 431: button.setHorizontalTextPosition(SwingConstants.TRAILING); 432: 433: Icon use = frame.getFrameIcon(); 434: if (use == null) 435: use = defaultIcon; 436: button.setIcon(use); 437: 438: desktopIcon.add(button, SwingConstants.CENTER); 439: } 440: 441: /** 442: * This method uninstalls the sub components for the JDesktopIcon. 443: */ 444: protected void uninstallComponents() 445: { 446: desktopIcon.remove(button); 447: 448: button = null; 449: } 450: 451: /** 452: * This method installs the listeners needed by this UI. 453: */ 454: protected void installListeners() 455: { 456: mouseHandler = createMouseInputListener(); 457: 458: desktopIcon.addMouseMotionListener(mouseHandler); 459: desktopIcon.addMouseListener(mouseHandler); 460: 461: propertyHandler = new PropertyChangeListener() 462: { 463: public void propertyChange(PropertyChangeEvent e) 464: { 465: if (e.getPropertyName().equals(JInternalFrame.TITLE_PROPERTY)) 466: button.setText(desktopIcon.getInternalFrame().getTitle()); 467: else if (e.getPropertyName().equals(JInternalFrame.FRAME_ICON_PROPERTY)) 468: { 469: Icon use = desktopIcon.getInternalFrame().getFrameIcon(); 470: if (use == null) 471: use = defaultIcon; 472: button.setIcon(use); 473: } 474: desktopIcon.revalidate(); 475: desktopIcon.repaint(); 476: } 477: }; 478: frame.addPropertyChangeListener(propertyHandler); 479: 480: button.addActionListener(new ActionListener() 481: { 482: public void actionPerformed(ActionEvent e) 483: { 484: deiconize(); 485: } 486: }); 487: } 488: 489: /** 490: * This method uninstalls the listeners needed by the UI. 491: */ 492: protected void uninstallListeners() 493: { 494: // button is nulled so no need to remove it. 495: 496: frame.removePropertyChangeListener(propertyHandler); 497: propertyHandler = null; 498: 499: desktopIcon.removeMouseMotionListener(mouseHandler); 500: desktopIcon.removeMouseListener(mouseHandler); 501: } 502: 503: /** 504: * This method installs the defaults for the JDesktopIcon. 505: */ 506: protected void installDefaults() 507: { 508: // FIXME: Move border to defaults. 509: desktopIcon.setBorder(new DesktopIconBorder()); 510: } 511: 512: /** 513: * This method uninstalls the defaults for the JDesktopIcon. 514: */ 515: protected void uninstallDefaults() 516: { 517: desktopIcon.setBorder(null); 518: } 519: 520: /** 521: * This method creates a new MouseInputListener for the JDesktopIcon. 522: * 523: * @return A new MouseInputListener. 524: */ 525: protected MouseInputListener createMouseInputListener() 526: { 527: return new MouseInputHandler(); 528: } 529: 530: /** 531: * This method returns the preferred size for the given JComponent. 532: * 533: * @param c The JComponent to find a preferred size for. 534: * 535: * @return The preferred size. 536: */ 537: public Dimension getPreferredSize(JComponent c) 538: { 539: return new Dimension(iconWidth, iconHeight); 540: } 541: 542: /** 543: * This method returns the minimum size for the given JComponent. 544: * 545: * @param c The JComponent to find a minimum size for. 546: * 547: * @return The minimum size. 548: */ 549: public Dimension getMinimumSize(JComponent c) 550: { 551: return getPreferredSize(c); 552: } 553: 554: /** 555: * This method returns the maximum size for the given JComponent. 556: * 557: * @param c The JComponent to find a maximum size for. 558: * 559: * @return The maximum size. 560: */ 561: public Dimension getMaximumSize(JComponent c) 562: { 563: return getPreferredSize(c); 564: } 565: 566: /** 567: * This method returns the insets of the given JComponent. 568: * 569: * @param c The JComponent to find insets for. 570: * 571: * @return The insets of the given JComponent. 572: */ 573: public Insets getInsets(JComponent c) 574: { 575: return c.getInsets(); 576: } 577: 578: /** 579: * This method deiconizes the JInternalFrame associated with the JDesktopIcon. 580: */ 581: public void deiconize() 582: { 583: try 584: { 585: frame.setIcon(false); 586: } 587: catch (PropertyVetoException pve) 588: { 589: // We do nothing if the attempt has been vetoed. 590: } 591: } 592: }