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 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     @SuppressWarnings("serial") // Superclass is not serializable across versions
 204     protected class IconLabel extends JPanel {
 205         JInternalFrame frame;
 206 
 207         IconLabel(JInternalFrame f) {
 208             super();
 209             this.frame = f;
 210             setFont(defaultTitleFont);
 211 
 212             // Forward mouse events to titlebar for moves.
 213             addMouseMotionListener(new MouseMotionListener() {
 214                 public void mouseDragged(MouseEvent e) {
 215                     forwardEventToParent(e);
 216                 }
 217                 public void mouseMoved(MouseEvent e) {
 218                     forwardEventToParent(e);
 219                 }
 220             });
 221             addMouseListener(new MouseListener() {
 222                 public void mouseClicked(MouseEvent e) {
 223                     forwardEventToParent(e);
 224                 }
 225                 public void mousePressed(MouseEvent e) {
 226                     forwardEventToParent(e);
 227                 }
 228                 public void mouseReleased(MouseEvent e) {
 229                     forwardEventToParent(e);
 230                 }
 231                 public void mouseEntered(MouseEvent e) {
 232                     forwardEventToParent(e);
 233                 }
 234                 public void mouseExited(MouseEvent e) {
 235                     forwardEventToParent(e);
 236                 }
 237             });
 238         }
 239 
 240         void forwardEventToParent(MouseEvent e) {
 241             getParent().dispatchEvent(new MouseEvent(
 242                 getParent(), e.getID(), e.getWhen(), e.getModifiers(),
 243                 e.getX(), e.getY(), e.getXOnScreen(),
 244                 e.getYOnScreen(), e.getClickCount(),
 245                 e.isPopupTrigger(), MouseEvent.NOBUTTON));
 246         }
 247 
 248         public boolean isFocusTraversable() {
 249             return false;
 250         }
 251 
 252         public Dimension getMinimumSize() {
 253             return new Dimension(defaultIcon.getIconWidth() + 1,
 254                                  LABEL_HEIGHT + LABEL_DIVIDER);
 255         }
 256 
 257         public Dimension getPreferredSize() {
 258             String title = frame.getTitle();
 259             FontMetrics fm = frame.getFontMetrics(defaultTitleFont);
 260             int w = 4;
 261             if (title != null) {
 262                 w += SwingUtilities2.stringWidth(frame, fm, title);
 263             }
 264             return new Dimension(w, LABEL_HEIGHT + LABEL_DIVIDER);
 265         }
 266 
 267         public void paint(Graphics g) {
 268             super.paint(g);
 269 
 270             // touch-up frame
 271             int maxX = getWidth() - 1;
 272             Color shadow =
 273                 UIManager.getColor("inactiveCaptionBorder").darker().darker();
 274             g.setColor(shadow);
 275             g.setClip(0, 0, getWidth(), getHeight());
 276             g.drawLine(maxX - 1, 1, maxX - 1, 1);
 277             g.drawLine(maxX, 0, maxX, 0);
 278 
 279             // fill background
 280             g.setColor(UIManager.getColor("inactiveCaption"));
 281             g.fillRect(2, 1, maxX - 3, LABEL_HEIGHT + 1);
 282 
 283             // draw text -- clipping to truncate text like CDE/Motif
 284             g.setClip(2, 1, maxX - 4, LABEL_HEIGHT);
 285             int y = LABEL_HEIGHT - SwingUtilities2.getFontMetrics(frame, g).
 286                                                    getDescent();
 287             g.setColor(UIManager.getColor("inactiveCaptionText"));
 288             String title = frame.getTitle();
 289             if (title != null) {
 290                 SwingUtilities2.drawString(frame, g, title, 4, y);
 291             }
 292         }
 293     }
 294 
 295     @SuppressWarnings("serial") // Superclass is not serializable across versions
 296     protected class IconButton extends JButton {
 297         Icon icon;
 298 
 299         IconButton(Icon icon) {
 300             super(icon);
 301             this.icon = icon;
 302             // Forward mouse events to titlebar for moves.
 303             addMouseMotionListener(new MouseMotionListener() {
 304                 public void mouseDragged(MouseEvent e) {
 305                     forwardEventToParent(e);
 306                 }
 307                 public void mouseMoved(MouseEvent e) {
 308                     forwardEventToParent(e);
 309                 }
 310             });
 311             addMouseListener(new MouseListener() {
 312                 public void mouseClicked(MouseEvent e) {
 313                     forwardEventToParent(e);
 314                 }
 315                 public void mousePressed(MouseEvent e) {
 316                     forwardEventToParent(e);
 317                 }
 318                 public void mouseReleased(MouseEvent e) {
 319                     if (!systemMenu.isShowing()) {
 320                         forwardEventToParent(e);
 321                     }
 322                 }
 323                 public void mouseEntered(MouseEvent e) {
 324                     forwardEventToParent(e);
 325                 }
 326                 public void mouseExited(MouseEvent e) {
 327                     forwardEventToParent(e);
 328                 }
 329             });
 330         }
 331 
 332         void forwardEventToParent(MouseEvent e) {
 333             getParent().dispatchEvent(new MouseEvent(
 334                 getParent(), e.getID(), e.getWhen(), e.getModifiers(),
 335                 e.getX(), e.getY(), e.getXOnScreen(), e.getYOnScreen(),
 336                 e.getClickCount(), e.isPopupTrigger(), MouseEvent.NOBUTTON ));
 337         }
 338 
 339         public boolean isFocusTraversable() {
 340             return false;
 341         }
 342     }
 343 
 344 
 345     protected class DesktopIconActionListener implements ActionListener {
 346         public void actionPerformed(ActionEvent e){
 347             systemMenu.show(iconButton, 0, getDesktopIcon().getHeight());
 348         }
 349     }
 350 
 351     protected class DesktopIconMouseListener extends MouseAdapter {
 352         // if we drag or move we should deengage the popup
 353         public void mousePressed(MouseEvent e){
 354             if (e.getClickCount() > 1) {
 355                 try {
 356                     getFrame().setIcon(false);
 357                 } catch (PropertyVetoException e2){ }
 358                 systemMenu.setVisible(false);
 359                 /* the mouse release will not get reported correctly,
 360                    because the icon will no longer be in the hierarchy;
 361                    maybe that should be fixed, but until it is, we need
 362                    to do the required cleanup here. */
 363                 getFrame().getDesktopPane().getDesktopManager().endDraggingFrame((JComponent)e.getSource());
 364             }
 365         }
 366     }
 367 }