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