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
26package com.sun.java.swing.plaf.motif;
27
28import sun.swing.SwingUtilities2;
29import java.awt.*;
30import java.awt.event.*;
31import javax.swing.*;
32import javax.swing.border.*;
33import javax.swing.plaf.*;
34import javax.swing.plaf.basic.*;
35import java.beans.*;
36import java.util.EventListener;
37import java.io.Serializable;
38
39
40/**
41 * Motif rendition of the component.
42 *
43 * @author Thomas Ball
44 * @author Rich Schiavi
45 */
46public 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    static final int LABEL_HEIGHT = 18;
63    static final int LABEL_DIVIDER = 4;    // padding between icon and label
64
65    static final 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        @SuppressWarnings("deprecation")
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        @SuppressWarnings("deprecation")
249        public boolean isFocusTraversable() {
250            return false;
251        }
252
253        public Dimension getMinimumSize() {
254            return new Dimension(defaultIcon.getIconWidth() + 1,
255                                 LABEL_HEIGHT + LABEL_DIVIDER);
256        }
257
258        public Dimension getPreferredSize() {
259            String title = frame.getTitle();
260            FontMetrics fm = frame.getFontMetrics(defaultTitleFont);
261            int w = 4;
262            if (title != null) {
263                w += SwingUtilities2.stringWidth(frame, fm, title);
264            }
265            return new Dimension(w, LABEL_HEIGHT + LABEL_DIVIDER);
266        }
267
268        public void paint(Graphics g) {
269            super.paint(g);
270
271            // touch-up frame
272            int maxX = getWidth() - 1;
273            Color shadow =
274                UIManager.getColor("inactiveCaptionBorder").darker().darker();
275            g.setColor(shadow);
276            g.setClip(0, 0, getWidth(), getHeight());
277            g.drawLine(maxX - 1, 1, maxX - 1, 1);
278            g.drawLine(maxX, 0, maxX, 0);
279
280            // fill background
281            g.setColor(UIManager.getColor("inactiveCaption"));
282            g.fillRect(2, 1, maxX - 3, LABEL_HEIGHT + 1);
283
284            // draw text -- clipping to truncate text like CDE/Motif
285            g.setClip(2, 1, maxX - 4, LABEL_HEIGHT);
286            int y = LABEL_HEIGHT - SwingUtilities2.getFontMetrics(frame, g).
287                                                   getDescent();
288            g.setColor(UIManager.getColor("inactiveCaptionText"));
289            String title = frame.getTitle();
290            if (title != null) {
291                SwingUtilities2.drawString(frame, g, title, 4, y);
292            }
293        }
294    }
295
296    @SuppressWarnings("serial") // Superclass is not serializable across versions
297    protected class IconButton extends JButton {
298        Icon icon;
299
300        IconButton(Icon icon) {
301            super(icon);
302            this.icon = icon;
303            // Forward mouse events to titlebar for moves.
304            addMouseMotionListener(new MouseMotionListener() {
305                public void mouseDragged(MouseEvent e) {
306                    forwardEventToParent(e);
307                }
308                public void mouseMoved(MouseEvent e) {
309                    forwardEventToParent(e);
310                }
311            });
312            addMouseListener(new MouseListener() {
313                public void mouseClicked(MouseEvent e) {
314                    forwardEventToParent(e);
315                }
316                public void mousePressed(MouseEvent e) {
317                    forwardEventToParent(e);
318                }
319                public void mouseReleased(MouseEvent e) {
320                    if (!systemMenu.isShowing()) {
321                        forwardEventToParent(e);
322                    }
323                }
324                public void mouseEntered(MouseEvent e) {
325                    forwardEventToParent(e);
326                }
327                public void mouseExited(MouseEvent e) {
328                    forwardEventToParent(e);
329                }
330            });
331        }
332        @SuppressWarnings("deprecation")
333        void forwardEventToParent(MouseEvent e) {
334            getParent().dispatchEvent(new MouseEvent(
335                getParent(), e.getID(), e.getWhen(), e.getModifiers(),
336                e.getX(), e.getY(), e.getXOnScreen(), e.getYOnScreen(),
337                e.getClickCount(), e.isPopupTrigger(), MouseEvent.NOBUTTON ));
338        }
339
340        @SuppressWarnings("deprecation")
341        public boolean isFocusTraversable() {
342            return false;
343        }
344    }
345
346
347    protected class DesktopIconActionListener implements ActionListener {
348        public void actionPerformed(ActionEvent e){
349            systemMenu.show(iconButton, 0, getDesktopIcon().getHeight());
350        }
351    }
352
353    protected class DesktopIconMouseListener extends MouseAdapter {
354        // if we drag or move we should deengage the popup
355        public void mousePressed(MouseEvent e){
356            if (e.getClickCount() > 1) {
357                try {
358                    getFrame().setIcon(false);
359                } catch (PropertyVetoException e2){ }
360                systemMenu.setVisible(false);
361                /* the mouse release will not get reported correctly,
362                   because the icon will no longer be in the hierarchy;
363                   maybe that should be fixed, but until it is, we need
364                   to do the required cleanup here. */
365                getFrame().getDesktopPane().getDesktopManager().endDraggingFrame((JComponent)e.getSource());
366            }
367        }
368    }
369}
370