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 javax.swing.*;
29 import java.awt.Rectangle;
30 import java.awt.Dimension;
31 import java.awt.Insets;
32 import java.awt.Color;
33 import java.awt.Graphics;
34 import java.awt.Component;
35 import java.awt.Point;
36 import javax.swing.plaf.*;
37 import java.io.Serializable;
38 
39 /**
40  * <p>
41  * <strong>Warning:</strong>
42  * Serialized objects of this class will not be compatible with
43  * future Swing releases.  The current serialization support is appropriate
44  * for short term storage or RMI between applications running the same
45  * version of Swing.  A future release of Swing will provide support for
46  * long term persistence.
47  *
48  * @author David Kloba
49  */
50 public class MotifDesktopPaneUI extends javax.swing.plaf.basic.BasicDesktopPaneUI
51 {
52 
53 /// DesktopPaneUI methods
createUI(JComponent d)54     public static ComponentUI createUI(JComponent d)    {
55         return new MotifDesktopPaneUI();
56     }
57 
MotifDesktopPaneUI()58     public MotifDesktopPaneUI() {
59     }
60 
installDesktopManager()61     protected void installDesktopManager() {
62         desktopManager = desktop.getDesktopManager();
63         if(desktopManager == null) {
64             desktopManager = new MotifDesktopManager();
65             desktop.setDesktopManager(desktopManager);
66             ((MotifDesktopManager)desktopManager).adjustIcons(desktop);
67         }
68     }
69 
getInsets(JComponent c)70     public Insets getInsets(JComponent c) {return new Insets(0,0,0,0);}
71 
72 ////////////////////////////////////////////////////////////////////////////////////
73 ///  DragPane class
74 ////////////////////////////////////////////////////////////////////////////////////
75     @SuppressWarnings("serial") // Superclass is not serializable across versions
76     private class DragPane extends JComponent {
paint(Graphics g)77         public void paint(Graphics g) {
78             g.setColor(Color.darkGray);
79             g.drawRect(0, 0, getWidth()-1, getHeight()-1);
80         }
81     };
82 
83 ////////////////////////////////////////////////////////////////////////////////////
84 ///  MotifDesktopManager class
85 ////////////////////////////////////////////////////////////////////////////////////
86     @SuppressWarnings("serial") // JDK-implementation class
87     private class MotifDesktopManager extends DefaultDesktopManager implements Serializable, UIResource {
88         JComponent dragPane;
89         boolean usingDragPane = false;
90         private transient JLayeredPane layeredPaneForDragPane;
91         int iconWidth, iconHeight;
92 
93     // PENDING(klobad) this should be optimized
setBoundsForFrame(JComponent f, int newX, int newY, int newWidth, int newHeight)94     public void setBoundsForFrame(JComponent f, int newX, int newY,
95                         int newWidth, int newHeight) {
96         if(!usingDragPane) {
97             boolean didResize;
98             didResize = (f.getWidth() != newWidth || f.getHeight() != newHeight);
99             Rectangle r = f.getBounds();
100             f.setBounds(newX, newY, newWidth, newHeight);
101             SwingUtilities.computeUnion(newX, newY, newWidth, newHeight, r);
102             f.getParent().repaint(r.x, r.y, r.width, r.height);
103             if(didResize) {
104                 f.validate();
105             }
106         } else {
107             Rectangle r = dragPane.getBounds();
108             dragPane.setBounds(newX, newY, newWidth, newHeight);
109             SwingUtilities.computeUnion(newX, newY, newWidth, newHeight, r);
110             dragPane.getParent().repaint(r.x, r.y, r.width, r.height);
111         }
112     }
113 
beginDraggingFrame(JComponent f)114     public void beginDraggingFrame(JComponent f) {
115         usingDragPane = false;
116         if(f.getParent() instanceof JLayeredPane) {
117             if(dragPane == null)
118                 dragPane = new DragPane();
119             layeredPaneForDragPane = (JLayeredPane)f.getParent();
120             layeredPaneForDragPane.setLayer(dragPane, Integer.MAX_VALUE);
121             dragPane.setBounds(f.getX(), f.getY(), f.getWidth(), f.getHeight());
122             layeredPaneForDragPane.add(dragPane);
123             usingDragPane = true;
124         }
125     }
126 
dragFrame(JComponent f, int newX, int newY)127     public void dragFrame(JComponent f, int newX, int newY) {
128         setBoundsForFrame(f, newX, newY, f.getWidth(), f.getHeight());
129     }
130 
endDraggingFrame(JComponent f)131     public void endDraggingFrame(JComponent f) {
132         if(usingDragPane) {
133             layeredPaneForDragPane.remove(dragPane);
134             usingDragPane = false;
135             if (f instanceof JInternalFrame) {
136                 setBoundsForFrame(f, dragPane.getX(), dragPane.getY(),
137                         dragPane.getWidth(), dragPane.getHeight());
138             } else if (f instanceof JInternalFrame.JDesktopIcon) {
139                 adjustBoundsForIcon((JInternalFrame.JDesktopIcon)f,
140                         dragPane.getX(), dragPane.getY());
141             }
142         }
143     }
144 
beginResizingFrame(JComponent f, int direction)145     public void beginResizingFrame(JComponent f, int direction) {
146         usingDragPane = false;
147         if(f.getParent() instanceof JLayeredPane) {
148             if(dragPane == null)
149                 dragPane = new DragPane();
150             JLayeredPane p = (JLayeredPane)f.getParent();
151             p.setLayer(dragPane, Integer.MAX_VALUE);
152             dragPane.setBounds(f.getX(), f.getY(),
153                                 f.getWidth(), f.getHeight());
154             p.add(dragPane);
155             usingDragPane = true;
156         }
157     }
158 
resizeFrame(JComponent f, int newX, int newY, int newWidth, int newHeight)159     public void resizeFrame(JComponent f, int newX, int newY,
160                                 int newWidth, int newHeight) {
161         setBoundsForFrame(f, newX, newY, newWidth, newHeight);
162     }
163 
endResizingFrame(JComponent f)164     public void endResizingFrame(JComponent f) {
165         if(usingDragPane) {
166             JLayeredPane p = (JLayeredPane)f.getParent();
167             p.remove(dragPane);
168             usingDragPane = false;
169             setBoundsForFrame(f, dragPane.getX(), dragPane.getY(),
170                                 dragPane.getWidth(), dragPane.getHeight());
171         }
172     }
173 
iconifyFrame(JInternalFrame f)174         public void iconifyFrame(JInternalFrame f) {
175             JInternalFrame.JDesktopIcon icon = f.getDesktopIcon();
176             Point p = icon.getLocation();
177             adjustBoundsForIcon(icon, p.x, p.y);
178             super.iconifyFrame(f);
179         }
180 
181         /**
182          * Change positions of icons in the desktop pane so that
183          * they do not overlap
184          */
adjustIcons(JDesktopPane desktop)185         protected void adjustIcons(JDesktopPane desktop) {
186             // We need to know Motif icon size
187             JInternalFrame.JDesktopIcon icon = new JInternalFrame.JDesktopIcon(
188                     new JInternalFrame());
189             Dimension iconSize = icon.getPreferredSize();
190             iconWidth = iconSize.width;
191             iconHeight = iconSize.height;
192 
193             JInternalFrame[] frames = desktop.getAllFrames();
194             for (int i=0; i<frames.length; i++) {
195                 icon = frames[i].getDesktopIcon();
196                 Point ip = icon.getLocation();
197                 adjustBoundsForIcon(icon, ip.x, ip.y);
198             }
199         }
200 
201         /**
202          * Change positions of icon so that it doesn't overlap
203          * other icons.
204          */
adjustBoundsForIcon(JInternalFrame.JDesktopIcon icon, int x, int y)205         protected void adjustBoundsForIcon(JInternalFrame.JDesktopIcon icon,
206                 int x, int y) {
207             JDesktopPane c = icon.getDesktopPane();
208 
209             int maxy = c.getHeight();
210             int w = iconWidth;
211             int h = iconHeight;
212             c.repaint(x, y, w, h);
213             x = x < 0 ? 0 : x;
214             y = y < 0 ? 0 : y;
215 
216             /* Fix for disappearing icons. If the y value is maxy then this
217              * algorithm would place the icon in a non-displayed cell.  Never
218              * to be ssen again.*/
219             y = y >= maxy ? (maxy - 1) : y;
220 
221             /* Compute the offset for the cell we are trying to go in. */
222             int lx = (x / w) * w;
223             int ygap = maxy % h;
224             int ly = ((y-ygap) / h) * h + ygap;
225 
226             /* How far are we into the cell we dropped the icon in. */
227             int dx = x - lx;
228             int dy = y - ly;
229 
230             /* Set coordinates for the icon. */
231             x = dx < w/2 ? lx: lx + w;
232             y = dy < h/2 ? ly: ((ly + h) < maxy ? ly + h: ly);
233 
234             while (getIconAt(c, icon, x, y) != null) {
235                 x += w;
236             }
237 
238             /* Cancel the move if the x value was moved off screen. */
239             if (x > c.getWidth()) {
240                 return;
241             }
242             if (icon.getParent() != null) {
243                 setBoundsForFrame(icon, x, y, w, h);
244             } else {
245                 icon.setLocation(x, y);
246             }
247         }
248 
249         protected JInternalFrame.JDesktopIcon getIconAt(JDesktopPane desktop,
250             JInternalFrame.JDesktopIcon icon, int x, int y) {
251 
252             JInternalFrame.JDesktopIcon currentIcon = null;
253             Component[] components = desktop.getComponents();
254 
255             for (int i=0; i<components.length; i++) {
256                 Component comp = components[i];
257                 if (comp instanceof JInternalFrame.JDesktopIcon &&
258                     comp != icon) {
259 
260                     Point p = comp.getLocation();
261                     if (p.x == x && p.y == y) {
262                         return (JInternalFrame.JDesktopIcon)comp;
263                     }
264                 }
265             }
266             return null;
267         }
268     }; /// END of MotifDesktopManager
269 }
270