Merge from mainline (gomp-merge-2005-02-26).
[official-gcc.git] / libjava / javax / swing / DefaultDesktopManager.java
bloba0dd5e2d1a156a129f25a568990dd998f402b94b
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., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 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 * DefaultDesktopManager is 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()
96 /**
97 * This method is not normally called since the user will typically add the
98 * JInternalFrame to a Container. If this is called, it will try to
99 * determine the parent of the JInternalFrame and remove any icon that
100 * represents this JInternalFrame and add this JInternalFrame.
102 * @param frame The JInternalFrame to open.
104 public void openFrame(JInternalFrame frame)
106 Container c = frame.getParent();
107 if (c == null)
108 c = frame.getDesktopIcon().getParent();
109 if (c == null)
110 return;
112 c.remove(frame.getDesktopIcon());
113 c.add(frame);
114 frame.setVisible(true);
118 * This method removes the JInternalFrame and JDesktopIcon (if one is
119 * present) from their parents.
121 * @param frame The JInternalFrame to close.
123 public void closeFrame(JInternalFrame frame)
125 Container c = frame.getParent();
126 frame.doDefaultCloseAction();
128 if (c != null)
130 if (frame.isIcon())
131 c.remove(frame.getDesktopIcon());
132 else
133 c.remove(frame);
134 c.repaint();
139 * This method resizes the JInternalFrame to match its parent's bounds.
141 * @param frame The JInternalFrame to maximize.
143 public void maximizeFrame(JInternalFrame frame)
145 // Can't maximize from iconified state.
146 // It can only return to maximized state, but that would fall under
147 // deiconify.
148 if (frame.isIcon())
149 return;
150 frame.setNormalBounds(frame.getBounds());
152 Container p = frame.getParent();
153 if (p != null)
155 Rectangle pBounds = p.getBounds();
156 Insets insets = p.getInsets();
157 pBounds.width -= insets.left + insets.right;
158 pBounds.height -= insets.top + insets.bottom;
160 setBoundsForFrame(frame, 0, 0, pBounds.width, pBounds.height);
162 if (p instanceof JDesktopPane)
163 ((JDesktopPane) p).setSelectedFrame(frame);
164 else
168 frame.setSelected(true);
170 catch (PropertyVetoException e)
172 // Do nothing.
178 * This method restores the JInternalFrame's bounds to what they were
179 * previous to the setMaximize call.
181 * @param frame The JInternalFrame to minimize.
183 public void minimizeFrame(JInternalFrame frame)
185 Rectangle normalBounds = frame.getNormalBounds();
187 JDesktopPane p = frame.getDesktopPane();
188 if (p != null)
189 p.setSelectedFrame(frame);
190 else
194 frame.setSelected(true);
196 catch (PropertyVetoException e)
198 // Do nothing.
202 setBoundsForFrame(frame, normalBounds.x, normalBounds.y,
203 normalBounds.width, normalBounds.height);
207 * This method removes the JInternalFrame from its parent and adds its
208 * JDesktopIcon representation.
210 * @param frame The JInternalFrame to iconify.
212 public void iconifyFrame(JInternalFrame frame)
214 JDesktopPane p = frame.getDesktopPane();
215 JDesktopIcon icon = frame.getDesktopIcon();
216 if (p != null && p.getSelectedFrame() == frame)
217 p.setSelectedFrame(null);
218 else
222 frame.setSelected(false);
224 catch (PropertyVetoException e)
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 c.remove(frame);
250 * This method removes the JInternalFrame's JDesktopIcon representation and
251 * adds the JInternalFrame back to its parent.
253 * @param frame The JInternalFrame to deiconify.
255 public void deiconifyFrame(JInternalFrame frame)
257 JDesktopIcon icon = frame.getDesktopIcon();
258 Container c = icon.getParent();
260 removeIconFor(frame);
261 c.add(frame);
262 frame.setVisible(true);
264 if (! frame.isSelected())
266 JDesktopPane p = frame.getDesktopPane();
267 if (p != null)
268 p.setSelectedFrame(frame);
269 else
273 frame.setSelected(true);
275 catch (PropertyVetoException e)
277 // Do nothing.
282 c.invalidate();
286 * This method activates the JInternalFrame by moving it to the front and
287 * selecting it.
289 * @param frame The JInternalFrame to activate.
291 public void activateFrame(JInternalFrame frame)
293 JDesktopPane p = frame.getDesktopPane();
295 if (p != null)
296 p.setSelectedFrame(frame);
297 else
301 frame.setSelected(true);
303 catch (PropertyVetoException e)
308 frame.toFront();
312 * This method is called when the JInternalFrame loses focus.
314 * @param frame The JInternalFram to deactivate.
316 public void deactivateFrame(JInternalFrame frame)
318 JDesktopPane p = frame.getDesktopPane();
319 if (p != null)
321 if (p.getSelectedFrame() == frame)
322 p.setSelectedFrame(null);
324 else
328 frame.setSelected(false);
330 catch (PropertyVetoException e)
337 * This method is called to indicate that the DesktopManager should prepare
338 * to drag the JInternalFrame. Any state information needed to drag the
339 * frame will be prepared now.
341 * @param component The JComponent to drag, usually a JInternalFrame.
343 public void beginDraggingFrame(JComponent component)
345 if (component instanceof JDesktopIcon)
346 pane = ((JDesktopIcon) component).getInternalFrame().getDesktopPane();
347 else
348 pane = ((JInternalFrame) component).getDesktopPane();
349 if (pane == null)
350 return;
352 dragCache = component.getBounds();
354 if (! (pane instanceof JDesktopPane))
355 currentDragMode = JDesktopPane.LIVE_DRAG_MODE;
356 else
357 currentDragMode = ((JDesktopPane) pane).getDragMode();
361 * This method is called to drag the JInternalFrame to a new location.
363 * @param component The JComponent to drag, usually a JInternalFrame.
364 * @param newX The new x coordinate.
365 * @param newY The new y coordinate.
367 public void dragFrame(JComponent component, int newX, int newY)
369 if (currentDragMode == JDesktopPane.OUTLINE_DRAG_MODE)
371 // FIXME: Do outline drag mode painting.
373 else
375 Rectangle b = component.getBounds();
376 if (component instanceof JDesktopIcon)
377 component.setBounds(newX, newY, b.width, b.height);
378 else
379 setBoundsForFrame((JInternalFrame) component, newX, newY, b.width,
380 b.height);
385 * This method indicates that the dragging is done. Any state information
386 * stored by the DesktopManager can be cleared.
388 * @param component The JComponent that has finished dragging.
390 public void endDraggingFrame(JComponent component)
392 if (currentDragMode == JDesktopPane.OUTLINE_DRAG_MODE)
394 setBoundsForFrame((JInternalFrame) component, dragCache.x,
395 dragCache.y, dragCache.width, dragCache.height);
396 pane = null;
397 dragCache = null;
399 component.repaint();
403 * This method is called to indicate that the given JComponent will be
404 * resized. Any state information necessary to resize the JComponent will
405 * be prepared now.
407 * @param component The JComponent to resize, usually a JInternalFrame.
408 * @param direction The direction to drag in (a SwingConstant).
410 public void beginResizingFrame(JComponent component, int direction)
412 pane = ((JInternalFrame) component).getDesktopPane();
413 if (pane == null)
414 return;
416 dragCache = component.getBounds();
417 if (! (pane instanceof JDesktopPane))
418 currentDragMode = JDesktopPane.LIVE_DRAG_MODE;
419 else
420 currentDragMode = ((JDesktopPane) pane).getDragMode();
424 * This method resizes the give JComponent.
426 * @param component The JComponent to resize.
427 * @param newX The new x coordinate.
428 * @param newY The new y coordinate.
429 * @param newWidth The new width.
430 * @param newHeight The new height.
432 public void resizeFrame(JComponent component, int newX, int newY,
433 int newWidth, int newHeight)
435 dragCache.setBounds(newX, newY, newWidth, newHeight);
437 if (currentDragMode == JDesktopPane.OUTLINE_DRAG_MODE)
439 // FIXME: Do outline drag painting.
441 else
442 setBoundsForFrame(component, dragCache.x, dragCache.y, dragCache.width,
443 dragCache.height);
447 * This method is called to indicate that the given JComponent has finished
448 * dragging. Any state information stored by the DesktopManager can be
449 * cleared.
451 * @param component The JComponent that finished resizing.
453 public void endResizingFrame(JComponent component)
455 if (currentDragMode == JDesktopPane.OUTLINE_DRAG_MODE)
457 setBoundsForFrame((JInternalFrame) component, dragCache.x,
458 dragCache.y, dragCache.width, dragCache.height);
459 pane = null;
460 dragCache = null;
462 component.repaint();
466 * This method calls setBounds with the given parameters and repaints the
467 * JComponent.
469 * @param component The JComponent to set bounds for.
470 * @param newX The new x coordinate.
471 * @param newY The new y coordinate.
472 * @param newWidth The new width.
473 * @param newHeight The new height.
475 public void setBoundsForFrame(JComponent component, int newX, int newY,
476 int newWidth, int newHeight)
478 component.setBounds(newX, newY, newWidth, newHeight);
479 component.revalidate();
481 // If not null, I'd rather repaint the parent
482 if (component.getParent() != null)
483 component.getParent().repaint();
484 else
485 component.repaint();
489 * This is a helper method that removes the JDesktopIcon of the given
490 * JInternalFrame from the parent.
492 * @param frame The JInternalFrame to remove an icon for.
494 protected void removeIconFor(JInternalFrame frame)
496 JDesktopIcon icon = frame.getDesktopIcon();
497 Container c = icon.getParent();
498 if (c != null && icon != null)
499 c.remove(icon);
503 * This method is called by iconifyFrame to determine the bounds of the
504 * JDesktopIcon for the given JInternalFrame.
506 * @param frame The JInternalFrame to find the bounds of its JDesktopIcon
507 * for.
509 * @return The bounds of the JDesktopIcon.
511 protected Rectangle getBoundsForIconOf(JInternalFrame frame)
513 // IconRects has no order to it.
514 // The icon _must_ be placed in the first free slot (working from
515 // the bottom left corner)
516 // The icon also must not be placed where another icon is placed
517 // (regardless whether that frame is an icon currently or not)
518 JDesktopPane desktopPane = frame.getDesktopPane();
519 Rectangle paneBounds = desktopPane.getBounds();
520 Insets insets = desktopPane.getInsets();
521 Dimension pref = frame.getDesktopIcon().getPreferredSize();
523 if (desktopPane == null)
524 return frame.getDesktopIcon().getBounds();
526 Component[] frames = desktopPane.getComponents();
528 int count = 0;
529 for (int i = 0, j = 0; i < frames.length; i++)
530 if (frames[i] instanceof JDesktopIcon
531 || frames[i] instanceof JInternalFrame
532 && ((JInternalFrame) frames[i]).getWasIcon() && frames[i] != frame)
533 count++;
534 iconRects = new Rectangle[count];
535 for (int i = 0, j = 0; i < frames.length; i++)
536 if (frames[i] instanceof JDesktopIcon)
537 iconRects[--count] = frames[i].getBounds();
538 else if (frames[i] instanceof JInternalFrame
539 && ((JInternalFrame) frames[i]).getWasIcon()
540 && frames[i] != frame)
541 iconRects[--count] = ((JInternalFrame) frames[i]).getDesktopIcon()
542 .getBounds();
544 int startingX = insets.left;
545 int startingY = paneBounds.height - insets.bottom - pref.height;
546 Rectangle ideal = new Rectangle(startingX, startingY, pref.width,
547 pref.height);
548 boolean clear = true;
550 while (iconRects.length > 0)
552 clear = true;
553 for (int i = 0; i < iconRects.length; i++)
555 if (iconRects[i] != null && iconRects[i].intersects(ideal))
557 clear = false;
558 break;
561 if (clear)
562 return ideal;
564 startingX += pref.width;
565 if (startingX + pref.width > paneBounds.width - insets.right)
567 startingX = insets.left;
568 startingY -= pref.height;
570 ideal.setBounds(startingX, startingY, pref.width, pref.height);
573 return ideal;
577 * This method sets the bounds of the JInternalFrame right before the
578 * maximizeFrame call.
580 * @param frame The JInternalFrame being maximized.
581 * @param rect The normal bounds.
583 protected void setPreviousBounds(JInternalFrame frame, Rectangle rect)
585 frame.setNormalBounds(rect);
589 * This method returns the normal bounds of the JInternalFrame from before
590 * the maximize call.
592 * @param frame The JInternalFrame that is being restored.
594 * @return The previous bounds of the JInternalFrame.
596 protected Rectangle getPreviousBounds(JInternalFrame frame)
598 return frame.getNormalBounds();
602 * This method sets the value to true if the given JInternalFrame has been
603 * iconized and the bounds of its DesktopIcon are valid.
605 * @param frame The JInternalFrame for the JDesktopIcon.
606 * @param value True if the JInternalFrame has been iconized and the bounds
607 * of the JDesktopIcon are valid.
609 protected void setWasIcon(JInternalFrame frame, Boolean value)
611 frame.setWasIcon(value.booleanValue(), WAS_ICON_ONCE_PROPERTY);
615 * This method returns true if the given JInternalFrame has been iconized
616 * and the bounds of its DesktopIcon are valid.
618 * @param frame The JInternalFrame for the JDesktopIcon.
620 * @return True if the given JInternalFrame has been iconized and the bounds
621 * of its DesktopIcon are valid.
623 protected boolean wasIcon(JInternalFrame frame)
625 return frame.getWasIcon();