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