1 /*
   2  * Copyright (c) 1997, 2005, 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 com.sun.java.swing.plaf.motif;
  27 
  28 import sun.swing.SwingUtilities2;
  29 import java.awt.*;
  30 import java.awt.event.*;
  31 import javax.swing.*;
  32 import javax.swing.border.*;
  33 import javax.swing.plaf.*;
  34 import javax.swing.plaf.basic.*;
  35 import java.beans.*;
  36 import java.util.EventListener;
  37 import java.io.Serializable;
  38 
  39 
  40 /**
  41  * Motif rendition of the component.
  42  *
  43  * @author Thomas Ball
  44  * @author Rich Schiavi
  45  */
  46 public class MotifDesktopIconUI extends BasicDesktopIconUI
  47 {
  48     protected DesktopIconActionListener desktopIconActionListener;
  49     protected DesktopIconMouseListener  desktopIconMouseListener;
  50 
  51     protected Icon       defaultIcon;
  52     protected IconButton iconButton;
  53     protected IconLabel  iconLabel;
  54 
  55     // This is only used for its system menu, but we need a reference to it so
  56     // we can remove its listeners.
  57     private MotifInternalFrameTitlePane sysMenuTitlePane;
  58 
  59     JPopupMenu systemMenu;
  60     EventListener mml;
  61 
  62     final static int LABEL_HEIGHT = 18;
  63     final static int LABEL_DIVIDER = 4;    // padding between icon and label
  64 
  65     final static Font defaultTitleFont =
  66         new Font(Font.SANS_SERIF, Font.PLAIN, 12);
  67 
  68     public static ComponentUI createUI(JComponent c)    {
  69         return new MotifDesktopIconUI();
  70     }
  71 
  72     public MotifDesktopIconUI() {
  73     }
  74 
  75     protected void installDefaults(){
  76         super.installDefaults();
  77         setDefaultIcon(UIManager.getIcon("DesktopIcon.icon"));
  78         iconButton = createIconButton(defaultIcon);
  79         // An underhanded way of creating a system popup menu.
  80         sysMenuTitlePane =  new MotifInternalFrameTitlePane(frame);
  81         systemMenu = sysMenuTitlePane.getSystemMenu();
  82 
  83         MotifBorders.FrameBorder border = new MotifBorders.FrameBorder(desktopIcon);
  84         desktopIcon.setLayout(new BorderLayout());
  85         iconButton.setBorder(border);
  86         desktopIcon.add(iconButton, BorderLayout.CENTER);
  87         iconLabel = createIconLabel(frame);
  88         iconLabel.setBorder(border);
  89         desktopIcon.add(iconLabel, BorderLayout.SOUTH);
  90         desktopIcon.setSize(desktopIcon.getPreferredSize());
  91         desktopIcon.validate();
  92         JLayeredPane.putLayer(desktopIcon, JLayeredPane.getLayer(frame));
  93     }
  94 
  95     protected void installComponents(){
  96     }
  97 
  98     protected void uninstallComponents(){
  99     }
 100 
 101     protected void installListeners(){
 102         super.installListeners();
 103         desktopIconActionListener = createDesktopIconActionListener();
 104         desktopIconMouseListener = createDesktopIconMouseListener();
 105         iconButton.addActionListener(desktopIconActionListener);
 106         iconButton.addMouseListener(desktopIconMouseListener);
 107         iconLabel.addMouseListener(desktopIconMouseListener);
 108     }
 109 
 110     JInternalFrame.JDesktopIcon getDesktopIcon(){
 111       return desktopIcon;
 112     }
 113 
 114     void setDesktopIcon(JInternalFrame.JDesktopIcon d){
 115       desktopIcon = d;
 116     }
 117 
 118     JInternalFrame getFrame(){
 119       return frame;
 120     }
 121 
 122     void setFrame(JInternalFrame f){
 123       frame = f ;
 124     }
 125 
 126     protected void showSystemMenu(){
 127       systemMenu.show(iconButton, 0, getDesktopIcon().getHeight());
 128     }
 129 
 130     protected void hideSystemMenu(){
 131       systemMenu.setVisible(false);
 132     }
 133 
 134     protected IconLabel createIconLabel(JInternalFrame frame){
 135         return new IconLabel(frame);
 136     }
 137 
 138     protected IconButton createIconButton(Icon i){
 139         return new IconButton(i);
 140     }
 141 
 142     protected DesktopIconActionListener createDesktopIconActionListener(){
 143         return new DesktopIconActionListener();
 144     }
 145 
 146     protected DesktopIconMouseListener createDesktopIconMouseListener(){
 147         return new DesktopIconMouseListener();
 148     }
 149 
 150     protected void uninstallDefaults(){
 151         super.uninstallDefaults();
 152         desktopIcon.setLayout(null);
 153         desktopIcon.remove(iconButton);
 154         desktopIcon.remove(iconLabel);
 155     }
 156 
 157     protected void uninstallListeners(){
 158         super.uninstallListeners();
 159         iconButton.removeActionListener(desktopIconActionListener);
 160         iconButton.removeMouseListener(desktopIconMouseListener);
 161         sysMenuTitlePane.uninstallListeners();
 162     }
 163 
 164     public Dimension getMinimumSize(JComponent c) {
 165         JInternalFrame iframe = desktopIcon.getInternalFrame();
 166 
 167         int w = defaultIcon.getIconWidth();
 168         int h = defaultIcon.getIconHeight() + LABEL_HEIGHT + LABEL_DIVIDER;
 169 
 170         Border border = iframe.getBorder();
 171         if(border != null) {
 172             w += border.getBorderInsets(iframe).left +
 173                 border.getBorderInsets(iframe).right;
 174             h += border.getBorderInsets(iframe).bottom +
 175                 border.getBorderInsets(iframe).top;
 176         }
 177 
 178         return new Dimension(w, h);
 179     }
 180 
 181     public Dimension getPreferredSize(JComponent c) {
 182         return getMinimumSize(c);
 183     }
 184 
 185     public Dimension getMaximumSize(JComponent c){
 186         return getMinimumSize(c);
 187     }
 188 
 189     /**
 190       * Returns the default desktop icon.
 191       */
 192     public Icon getDefaultIcon() {
 193         return defaultIcon;
 194     }
 195 
 196     /**
 197       * Sets the icon used as the default desktop icon.
 198       */
 199     public void setDefaultIcon(Icon newIcon) {
 200         defaultIcon = newIcon;
 201     }
 202 
 203     protected class IconLabel extends JPanel {
 204         JInternalFrame frame;
 205 
 206         IconLabel(JInternalFrame f) {
 207             super();
 208             this.frame = f;
 209             setFont(defaultTitleFont);
 210 
 211             // Forward mouse events to titlebar for moves.
 212             addMouseMotionListener(new MouseMotionListener() {
 213                 public void mouseDragged(MouseEvent e) {
 214                     forwardEventToParent(e);
 215                 }
 216                 public void mouseMoved(MouseEvent e) {
 217                     forwardEventToParent(e);
 218                 }
 219             });
 220             addMouseListener(new MouseListener() {
 221                 public void mouseClicked(MouseEvent e) {
 222                     forwardEventToParent(e);
 223                 }
 224                 public void mousePressed(MouseEvent e) {
 225                     forwardEventToParent(e);
 226                 }
 227                 public void mouseReleased(MouseEvent e) {
 228                     forwardEventToParent(e);
 229                 }
 230                 public void mouseEntered(MouseEvent e) {
 231                     forwardEventToParent(e);
 232                 }
 233                 public void mouseExited(MouseEvent e) {
 234                     forwardEventToParent(e);
 235                 }
 236             });
 237         }
 238 
 239         void forwardEventToParent(MouseEvent e) {
 240             getParent().dispatchEvent(new MouseEvent(
 241                 getParent(), e.getID(), e.getWhen(), e.getModifiers(),
 242                 e.getX(), e.getY(), e.getXOnScreen(),
 243                 e.getYOnScreen(), e.getClickCount(),
 244                 e.isPopupTrigger(), MouseEvent.NOBUTTON));
 245         }
 246 
 247         public boolean isFocusTraversable() {
 248             return false;
 249         }
 250 
 251         public Dimension getMinimumSize() {
 252             return new Dimension(defaultIcon.getIconWidth() + 1,
 253                                  LABEL_HEIGHT + LABEL_DIVIDER);
 254         }
 255 
 256         public Dimension getPreferredSize() {
 257             String title = frame.getTitle();
 258             FontMetrics fm = frame.getFontMetrics(defaultTitleFont);
 259             int w = 4;
 260             if (title != null) {
 261                 w += SwingUtilities2.stringWidth(frame, fm, title);
 262             }
 263             return new Dimension(w, LABEL_HEIGHT + LABEL_DIVIDER);
 264         }
 265 
 266         public void paint(Graphics g) {
 267             super.paint(g);
 268 
 269             // touch-up frame
 270             int maxX = getWidth() - 1;
 271             Color shadow =
 272                 UIManager.getColor("inactiveCaptionBorder").darker().darker();
 273             g.setColor(shadow);
 274             g.setClip(0, 0, getWidth(), getHeight());
 275             g.drawLine(maxX - 1, 1, maxX - 1, 1);
 276             g.drawLine(maxX, 0, maxX, 0);
 277 
 278             // fill background
 279             g.setColor(UIManager.getColor("inactiveCaption"));
 280             g.fillRect(2, 1, maxX - 3, LABEL_HEIGHT + 1);
 281 
 282             // draw text -- clipping to truncate text like CDE/Motif
 283             g.setClip(2, 1, maxX - 4, LABEL_HEIGHT);
 284             int y = LABEL_HEIGHT - SwingUtilities2.getFontMetrics(frame, g).
 285                                                    getDescent();
 286             g.setColor(UIManager.getColor("inactiveCaptionText"));
 287             String title = frame.getTitle();
 288             if (title != null) {
 289                 SwingUtilities2.drawString(frame, g, title, 4, y);
 290             }
 291         }
 292     }
 293 
 294     protected class IconButton extends JButton {
 295         Icon icon;
 296 
 297         IconButton(Icon icon) {
 298             super(icon);
 299             this.icon = icon;
 300             // Forward mouse events to titlebar for moves.
 301             addMouseMotionListener(new MouseMotionListener() {
 302                 public void mouseDragged(MouseEvent e) {
 303                     forwardEventToParent(e);
 304                 }
 305                 public void mouseMoved(MouseEvent e) {
 306                     forwardEventToParent(e);
 307                 }
 308             });
 309             addMouseListener(new MouseListener() {
 310                 public void mouseClicked(MouseEvent e) {
 311                     forwardEventToParent(e);
 312                 }
 313                 public void mousePressed(MouseEvent e) {
 314                     forwardEventToParent(e);
 315                 }
 316                 public void mouseReleased(MouseEvent e) {
 317                     if (!systemMenu.isShowing()) {
 318                         forwardEventToParent(e);
 319                     }
 320                 }
 321                 public void mouseEntered(MouseEvent e) {
 322                     forwardEventToParent(e);
 323                 }
 324                 public void mouseExited(MouseEvent e) {
 325                     forwardEventToParent(e);
 326                 }
 327             });
 328         }
 329 
 330         void forwardEventToParent(MouseEvent e) {
 331             getParent().dispatchEvent(new MouseEvent(
 332                 getParent(), e.getID(), e.getWhen(), e.getModifiers(),
 333                 e.getX(), e.getY(), e.getXOnScreen(), e.getYOnScreen(),
 334                 e.getClickCount(), e.isPopupTrigger(), MouseEvent.NOBUTTON ));
 335         }
 336 
 337         public boolean isFocusTraversable() {
 338             return false;
 339         }
 340     }
 341 
 342 
 343     protected class DesktopIconActionListener implements ActionListener {
 344         public void actionPerformed(ActionEvent e){
 345             systemMenu.show(iconButton, 0, getDesktopIcon().getHeight());
 346         }
 347     }
 348 
 349     protected class DesktopIconMouseListener extends MouseAdapter {
 350         // if we drag or move we should deengage the popup
 351         public void mousePressed(MouseEvent e){
 352             if (e.getClickCount() > 1) {
 353                 try {
 354                     getFrame().setIcon(false);
 355                 } catch (PropertyVetoException e2){ }
 356                 systemMenu.setVisible(false);
 357                 /* the mouse release will not get reported correctly,
 358                    because the icon will no longer be in the hierarchy;
 359                    maybe that should be fixed, but until it is, we need
 360                    to do the required cleanup here. */
 361                 getFrame().getDesktopPane().getDesktopManager().endDraggingFrame((JComponent)e.getSource());
 362             }
 363         }
 364     }
 365 }