Imported GNU Classpath 0.90
[official-gcc.git] / libjava / classpath / javax / swing / DefaultDesktopManager.java
blob0304461ad4ec071c5f37bf29d3c0a742e9513465
1 /* DefaultDesktopManager.java --
2 Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
39 package javax.swing;
41 import java.awt.Component;
42 import java.awt.Container;
43 import java.awt.Dimension;
44 import java.awt.Insets;
45 import java.awt.Rectangle;
46 import java.beans.PropertyVetoException;
47 import java.io.Serializable;
49 import javax.swing.JInternalFrame.JDesktopIcon;
51 /**
52 * The default implementation of DesktopManager for
53 * Swing. It implements the basic beaviours for JInternalFrames in arbitrary
54 * parents. The methods provided by the class are not meant to be called by
55 * the user, instead, the JInternalFrame methods will call these methods.
57 public class DefaultDesktopManager implements DesktopManager, Serializable
59 /** DOCUMENT ME! */
60 private static final long serialVersionUID = 4657624909838017887L;
62 /** The property change event fired when the wasIcon property changes. */
63 static final String WAS_ICON_ONCE_PROPERTY = "wasIconOnce";
65 /**
66 * The method of dragging used by the JDesktopPane that parents the
67 * JInternalFrame that is being dragged.
69 private int currentDragMode = 0;
71 /**
72 * The cache of the bounds used to draw the outline rectangle when
73 * OUTLINE_DRAG_MODE is used.
75 private transient Rectangle dragCache = new Rectangle();
77 /**
78 * A cached JDesktopPane that is stored when the JInternalFrame is initially
79 * dragged.
81 private transient Container pane;
83 /**
84 * An array of Rectangles that holds the bounds of the JDesktopIcons in the
85 * JDesktopPane when looking for where to place a new icon.
87 private transient Rectangle[] iconRects;
89 /**
90 * This creates a new DefaultDesktopManager object.
92 public DefaultDesktopManager()
94 // Nothing to do here.
97 /**
98 * This method is not normally called since the user will typically add the
99 * JInternalFrame to a Container. If this is called, it will try to
100 * determine the parent of the JInternalFrame and remove any icon that
101 * represents this JInternalFrame and add this JInternalFrame.
103 * @param frame The JInternalFrame to open.
105 public void openFrame(JInternalFrame frame)
107 Container c = frame.getParent();
108 if (c == null)
109 c = frame.getDesktopIcon().getParent();
110 if (c == null)
111 return;
113 c.remove(frame.getDesktopIcon());
114 c.add(frame);
115 frame.setVisible(true);
119 * This method removes the JInternalFrame and JDesktopIcon (if one is
120 * present) from their parents.
122 * @param frame The JInternalFrame to close.
124 public void closeFrame(JInternalFrame frame)
126 Container c = frame.getParent();
127 if (c != null)
129 if (frame.isIcon())
130 c.remove(frame.getDesktopIcon());
131 else
132 c.remove(frame);
133 c.repaint();
138 * This method resizes the JInternalFrame to match its parent's bounds.
140 * @param frame The JInternalFrame to maximize.
142 public void maximizeFrame(JInternalFrame frame)
144 // Can't maximize from iconified state.
145 // It can only return to maximized state, but that would fall under
146 // deiconify.
147 if (frame.isIcon())
148 return;
149 frame.setNormalBounds(frame.getBounds());
151 Container p = frame.getParent();
152 if (p != null)
154 Rectangle pBounds = p.getBounds();
155 Insets insets = p.getInsets();
156 pBounds.width -= insets.left + insets.right;
157 pBounds.height -= insets.top + insets.bottom;
159 setBoundsForFrame(frame, 0, 0, pBounds.width, pBounds.height);
161 if (p instanceof JDesktopPane)
162 ((JDesktopPane) p).setSelectedFrame(frame);
163 else
167 frame.setSelected(true);
169 catch (PropertyVetoException e)
171 // Do nothing.
177 * This method restores the JInternalFrame's bounds to what they were
178 * previous to the setMaximize call.
180 * @param frame The JInternalFrame to minimize.
182 public void minimizeFrame(JInternalFrame frame)
184 Rectangle normalBounds = frame.getNormalBounds();
186 JDesktopPane p = frame.getDesktopPane();
187 if (p != null)
188 p.setSelectedFrame(frame);
189 else
193 frame.setSelected(true);
195 catch (PropertyVetoException e)
197 // Do nothing.
201 setBoundsForFrame(frame, normalBounds.x, normalBounds.y,
202 normalBounds.width, normalBounds.height);
206 * This method removes the JInternalFrame from its parent and adds its
207 * JDesktopIcon representation.
209 * @param frame The JInternalFrame to iconify.
211 public void iconifyFrame(JInternalFrame frame)
213 JDesktopPane p = frame.getDesktopPane();
214 JDesktopIcon icon = frame.getDesktopIcon();
215 if (p != null && p.getSelectedFrame() == frame)
216 p.setSelectedFrame(null);
217 else
221 frame.setSelected(false);
223 catch (PropertyVetoException e)
225 // Do nothing if attempt is vetoed.
229 Container c = frame.getParent();
231 if (!wasIcon(frame))
233 Rectangle r = getBoundsForIconOf(frame);
234 icon.setBounds(r);
235 setWasIcon(frame, Boolean.TRUE);
238 if (c != null)
240 if (icon != null)
242 c.add(icon);
243 icon.setVisible(true);
245 Rectangle b = frame.getBounds();
246 c.remove(frame);
247 c.repaint(b.x, b.y, b.width, b.height);
252 * This method removes the JInternalFrame's JDesktopIcon representation and
253 * adds the JInternalFrame back to its parent.
255 * @param frame The JInternalFrame to deiconify.
257 public void deiconifyFrame(JInternalFrame frame)
259 JDesktopIcon icon = frame.getDesktopIcon();
260 Container c = icon.getParent();
262 removeIconFor(frame);
263 c.add(frame);
264 frame.setVisible(true);
266 if (!frame.isSelected())
268 JDesktopPane p = frame.getDesktopPane();
269 if (p != null)
270 p.setSelectedFrame(frame);
271 else
275 frame.setSelected(true);
277 catch (PropertyVetoException e)
279 // Do nothing.
284 c.invalidate();
288 * This method activates the JInternalFrame by moving it to the front and
289 * selecting it.
291 * @param frame The JInternalFrame to activate.
293 public void activateFrame(JInternalFrame frame)
295 JDesktopPane p = frame.getDesktopPane();
297 if (p != null)
298 p.setSelectedFrame(frame);
299 else
303 frame.setSelected(true);
305 catch (PropertyVetoException e)
307 // Do nothing if attempt is vetoed.
311 frame.toFront();
315 * This method is called when the JInternalFrame loses focus.
317 * @param frame The JInternalFram to deactivate.
319 public void deactivateFrame(JInternalFrame frame)
321 JDesktopPane p = frame.getDesktopPane();
322 if (p != null)
324 if (p.getSelectedFrame() == frame)
325 p.setSelectedFrame(null);
327 else
331 frame.setSelected(false);
333 catch (PropertyVetoException e)
335 // Do nothing if attempt is vetoed.
341 * This method is called to indicate that the DesktopManager should prepare
342 * to drag the JInternalFrame. Any state information needed to drag the
343 * frame will be prepared now.
345 * @param component The JComponent to drag, usually a JInternalFrame.
347 public void beginDraggingFrame(JComponent component)
349 if (component instanceof JDesktopIcon)
350 pane = ((JDesktopIcon) component).getInternalFrame().getDesktopPane();
351 else
352 pane = ((JInternalFrame) component).getDesktopPane();
353 if (pane == null)
354 return;
356 dragCache = component.getBounds();
358 if (! (pane instanceof JDesktopPane))
359 currentDragMode = JDesktopPane.LIVE_DRAG_MODE;
360 else
361 currentDragMode = ((JDesktopPane) pane).getDragMode();
365 * This method is called to drag the JInternalFrame to a new location.
367 * @param component The JComponent to drag, usually a JInternalFrame.
369 * @param newX The new x coordinate.
370 * @param newY The new y coordinate.
372 public void dragFrame(JComponent component, int newX, int newY)
374 if (currentDragMode == JDesktopPane.OUTLINE_DRAG_MODE)
376 // FIXME: Do outline drag mode painting.
378 else
380 Rectangle b = component.getBounds();
381 if (component instanceof JDesktopIcon)
382 component.setBounds(newX, newY, b.width, b.height);
383 else
384 setBoundsForFrame((JInternalFrame) component, newX, newY, b.width,
385 b.height);
390 * This method indicates that the dragging is done. Any state information
391 * stored by the DesktopManager can be cleared.
393 * @param component The JComponent that has finished dragging.
395 public void endDraggingFrame(JComponent component)
397 if (currentDragMode == JDesktopPane.OUTLINE_DRAG_MODE)
399 setBoundsForFrame((JInternalFrame) component, dragCache.x, dragCache.y,
400 dragCache.width, dragCache.height);
401 pane = null;
402 dragCache = null;
404 component.repaint();
408 * This method is called to indicate that the given JComponent will be
409 * resized. Any state information necessary to resize the JComponent will
410 * be prepared now.
412 * @param component The JComponent to resize, usually a JInternalFrame.
413 * @param direction The direction to drag in (a SwingConstant).
415 public void beginResizingFrame(JComponent component, int direction)
417 pane = ((JInternalFrame) component).getDesktopPane();
418 if (pane == null)
419 return;
421 dragCache = component.getBounds();
422 if (! (pane instanceof JDesktopPane))
423 currentDragMode = JDesktopPane.LIVE_DRAG_MODE;
424 else
425 currentDragMode = ((JDesktopPane) pane).getDragMode();
429 * This method resizes the give JComponent.
431 * @param component The JComponent to resize.
432 * @param newX The new x coordinate.
433 * @param newY The new y coordinate.
434 * @param newWidth The new width.
435 * @param newHeight The new height.
437 public void resizeFrame(JComponent component, int newX, int newY,
438 int newWidth, int newHeight)
440 dragCache.setBounds(newX, newY, newWidth, newHeight);
442 if (currentDragMode == JDesktopPane.OUTLINE_DRAG_MODE)
444 // FIXME: Do outline drag painting.
446 else
447 setBoundsForFrame(component, dragCache.x, dragCache.y, dragCache.width,
448 dragCache.height);
452 * This method is called to indicate that the given JComponent has finished
453 * dragging. Any state information stored by the DesktopManager can be
454 * cleared.
456 * @param component The JComponent that finished resizing.
458 public void endResizingFrame(JComponent component)
460 if (currentDragMode == JDesktopPane.OUTLINE_DRAG_MODE)
462 setBoundsForFrame((JInternalFrame) component, dragCache.x, dragCache.y,
463 dragCache.width, dragCache.height);
464 pane = null;
465 dragCache = null;
467 component.repaint();
471 * This method calls setBounds with the given parameters and repaints the
472 * JComponent.
474 * @param component The JComponent to set bounds for.
475 * @param newX The new x coordinate.
476 * @param newY The new y coordinate.
477 * @param newWidth The new width.
478 * @param newHeight The new height.
480 public void setBoundsForFrame(JComponent component, int newX, int newY,
481 int newWidth, int newHeight)
483 component.setBounds(newX, newY, newWidth, newHeight);
484 component.revalidate();
486 // If not null, I'd rather repaint the parent
487 if (component.getParent() != null)
488 component.getParent().repaint();
489 else
490 component.repaint();
494 * This is a helper method that removes the JDesktopIcon of the given
495 * JInternalFrame from the parent.
497 * @param frame The JInternalFrame to remove an icon for.
499 protected void removeIconFor(JInternalFrame frame)
501 JDesktopIcon icon = frame.getDesktopIcon();
502 Container c = icon.getParent();
503 if (c != null && icon != null)
505 Rectangle b = icon.getBounds();
506 c.remove(icon);
507 c.repaint(b.x, b.y, b.width, b.height);
512 * This method is called by iconifyFrame to determine the bounds of the
513 * JDesktopIcon for the given JInternalFrame.
515 * @param frame The JInternalFrame to find the bounds of its JDesktopIcon
516 * for.
518 * @return The bounds of the JDesktopIcon.
520 protected Rectangle getBoundsForIconOf(JInternalFrame frame)
522 // IconRects has no order to it.
523 // The icon _must_ be placed in the first free slot (working from
524 // the bottom left corner)
525 // The icon also must not be placed where another icon is placed
526 // (regardless whether that frame is an icon currently or not)
527 JDesktopPane desktopPane = frame.getDesktopPane();
529 if (desktopPane == null)
530 return frame.getDesktopIcon().getBounds();
532 Rectangle paneBounds = desktopPane.getBounds();
533 Insets insets = desktopPane.getInsets();
534 Dimension pref = frame.getDesktopIcon().getPreferredSize();
536 Component[] frames = desktopPane.getComponents();
538 int count = 0;
539 for (int i = 0, j = 0; i < frames.length; i++)
540 if (frames[i] instanceof JDesktopIcon
541 || frames[i] instanceof JInternalFrame
542 && ((JInternalFrame) frames[i]).getWasIcon() && frames[i] != frame)
543 count++;
544 iconRects = new Rectangle[count];
545 for (int i = 0, j = 0; i < frames.length; i++)
546 if (frames[i] instanceof JDesktopIcon)
547 iconRects[--count] = frames[i].getBounds();
548 else if (frames[i] instanceof JInternalFrame
549 && ((JInternalFrame) frames[i]).getWasIcon()
550 && frames[i] != frame)
551 iconRects[--count] = ((JInternalFrame) frames[i])
552 .getDesktopIcon().getBounds();
554 int startingX = insets.left;
555 int startingY = paneBounds.height - insets.bottom - pref.height;
556 Rectangle ideal = new Rectangle(startingX, startingY, pref.width,
557 pref.height);
558 boolean clear = true;
560 while (iconRects.length > 0)
562 clear = true;
563 for (int i = 0; i < iconRects.length; i++)
565 if (iconRects[i] != null && iconRects[i].intersects(ideal))
567 clear = false;
568 break;
571 if (clear)
572 return ideal;
574 startingX += pref.width;
575 if (startingX + pref.width > paneBounds.width - insets.right)
577 startingX = insets.left;
578 startingY -= pref.height;
580 ideal.setBounds(startingX, startingY, pref.width, pref.height);
583 return ideal;
587 * This method sets the bounds of the JInternalFrame right before the
588 * maximizeFrame call.
590 * @param frame The JInternalFrame being maximized.
591 * @param rect The normal bounds.
593 protected void setPreviousBounds(JInternalFrame frame, Rectangle rect)
595 frame.setNormalBounds(rect);
599 * This method returns the normal bounds of the JInternalFrame from before
600 * the maximize call.
602 * @param frame The JInternalFrame that is being restored.
604 * @return The previous bounds of the JInternalFrame.
606 protected Rectangle getPreviousBounds(JInternalFrame frame)
608 return frame.getNormalBounds();
612 * This method sets the value to true if the given JInternalFrame has been
613 * iconized and the bounds of its DesktopIcon are valid.
615 * @param frame The JInternalFrame for the JDesktopIcon.
616 * @param value True if the JInternalFrame has been iconized and the bounds
617 * of the JDesktopIcon are valid.
619 protected void setWasIcon(JInternalFrame frame, Boolean value)
621 frame.setWasIcon(value.booleanValue(), WAS_ICON_ONCE_PROPERTY);
625 * This method returns true if the given JInternalFrame has been iconized
626 * and the bounds of its DesktopIcon are valid.
628 * @param frame The JInternalFrame for the JDesktopIcon.
630 * @return True if the given JInternalFrame has been iconized and the bounds
631 * of its DesktopIcon are valid.
633 protected boolean wasIcon(JInternalFrame frame)
635 return frame.getWasIcon();