Source for javax.swing.plaf.basic.BasicDesktopIconUI

   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: }