2004-08-12 Janis Johnson <janis187@us.ibm.com>
[official-gcc.git] / libjava / javax / swing / DefaultDesktopManager.java
blob6678c931c6e7177df9f53d88ee74c0edfcebcc2d
1 /* DefaultDesktopManager.java --
2 Copyright (C) 2002, 2004 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. */
38 package javax.swing;
40 import java.awt.Color;
41 import java.awt.Component;
42 import java.awt.Container;
43 import java.awt.Dimension;
44 import java.awt.Graphics;
45 import java.awt.Insets;
46 import java.awt.Rectangle;
47 import java.beans.PropertyVetoException;
48 import java.io.Serializable;
49 import javax.swing.JDesktopPane;
50 import javax.swing.JInternalFrame;
51 import javax.swing.JInternalFrame.JDesktopIcon;
54 /**
55 * DefaultDesktopManager is the default implementation of DesktopManager for
56 * swing. It implements the basic beaviours for JInternalFrames in arbitrary
57 * parents. The methods provided by the class are not meant to be called by
58 * the user, instead, the JInternalFrame methods will call these methods.
60 public class DefaultDesktopManager implements DesktopManager, Serializable
62 /** DOCUMENT ME! */
63 static final long serialVersionUID = 4657624909838017887L;
65 /** The property change event fired when the wasIcon property changes. */
66 static final String WAS_ICON_ONCE_PROPERTY = "wasIconOnce";
68 /**
69 * The method of dragging used by the JDesktopPane that parents the
70 * JInternalFrame that is being dragged.
72 private int currentDragMode = 0;
74 /**
75 * The cache of the bounds used to draw the outline rectangle when
76 * OUTLINE_DRAG_MODE is used.
78 private transient Rectangle dragCache = new Rectangle();
80 /**
81 * A cached JDesktopPane that is stored when the JInternalFrame is initially
82 * dragged.
84 private transient Container pane;
86 /**
87 * An array of Rectangles that holds the bounds of the JDesktopIcons in the
88 * JDesktopPane when looking for where to place a new icon.
90 private transient Rectangle[] iconRects;
92 /**
93 * This creates a new DefaultDesktopManager object.
95 public DefaultDesktopManager()
97 } // DefaultDesktopManager()
99 /**
100 * This method is not normally called since the user will typically add the
101 * JInternalFrame to a Container. If this is called, it will try to
102 * determine the parent of the JInternalFrame and remove any icon that
103 * represents this JInternalFrame and add this JInternalFrame.
105 * @param frame The JInternalFrame to open.
107 public void openFrame(JInternalFrame frame)
109 Container c = frame.getParent();
110 if (c == null)
111 c = frame.getDesktopIcon().getParent();
112 if (c == null)
113 return;
115 c.remove(frame.getDesktopIcon());
116 c.add(frame);
117 frame.setVisible(true);
118 } // openFrame()
121 * This method removes the JInternalFrame and JDesktopIcon (if one is
122 * present) from their parents.
124 * @param frame The JInternalFrame to close.
126 public void closeFrame(JInternalFrame frame)
128 Container c = frame.getParent();
129 frame.doDefaultCloseAction();
131 if (c != null)
133 if (frame.isIcon())
134 c.remove(frame.getDesktopIcon());
135 else
136 c.remove(frame);
137 c.repaint();
139 } // closeFrame()
142 * This method resizes the JInternalFrame to match its parent's bounds.
144 * @param frame The JInternalFrame to maximize.
146 public void maximizeFrame(JInternalFrame frame)
148 // Can't maximize from iconified state.
149 // It can only return to maximized state, but that would fall under
150 // deiconify.
151 if (frame.isIcon())
152 return;
153 frame.setNormalBounds(frame.getBounds());
155 Container p = frame.getParent();
156 if (p != null)
158 Rectangle pBounds = p.getBounds();
159 Insets insets = p.getInsets();
160 pBounds.width -= insets.left + insets.right;
161 pBounds.height -= insets.top + insets.bottom;
163 setBoundsForFrame(frame, 0, 0, pBounds.width, pBounds.height);
165 if (p instanceof JDesktopPane)
166 ((JDesktopPane) p).setSelectedFrame(frame);
167 else
171 frame.setSelected(true);
173 catch (PropertyVetoException e)
175 // Do nothing.
178 } // maximizeFrame()
181 * This method restores the JInternalFrame's bounds to what they were
182 * previous to the setMaximize call.
184 * @param frame The JInternalFrame to minimize.
186 public void minimizeFrame(JInternalFrame frame)
188 Rectangle normalBounds = frame.getNormalBounds();
190 JDesktopPane p = frame.getDesktopPane();
191 if (p != null)
192 p.setSelectedFrame(frame);
193 else
197 frame.setSelected(true);
199 catch (PropertyVetoException e)
201 // Do nothing.
205 setBoundsForFrame(frame, normalBounds.x, normalBounds.y,
206 normalBounds.width, normalBounds.height);
207 } // minimizeFrame()
210 * This method removes the JInternalFrame from its parent and adds its
211 * JDesktopIcon representation.
213 * @param frame The JInternalFrame to iconify.
215 public void iconifyFrame(JInternalFrame frame)
217 JDesktopPane p = frame.getDesktopPane();
218 JDesktopIcon icon = frame.getDesktopIcon();
219 if (p != null && p.getSelectedFrame() == frame)
220 p.setSelectedFrame(null);
221 else
225 frame.setSelected(false);
227 catch (PropertyVetoException e)
232 Container c = frame.getParent();
234 if (! wasIcon(frame))
236 Rectangle r = getBoundsForIconOf(frame);
237 icon.setBounds(r);
238 setWasIcon(frame, true);
241 if (c != null)
243 if (icon != null)
245 c.add(icon);
246 icon.setVisible(true);
248 c.remove(frame);
250 } // iconifyFrame()
253 * This method removes the JInternalFrame's JDesktopIcon representation and
254 * adds the JInternalFrame back to its parent.
256 * @param frame The JInternalFrame to deiconify.
258 public void deiconifyFrame(JInternalFrame frame)
260 JDesktopIcon icon = frame.getDesktopIcon();
261 Container c = icon.getParent();
263 removeIconFor(frame);
264 c.add(frame);
265 frame.setVisible(true);
267 if (! frame.isSelected())
269 JDesktopPane p = frame.getDesktopPane();
270 if (p != null)
271 p.setSelectedFrame(frame);
272 else
276 frame.setSelected(true);
278 catch (PropertyVetoException e)
280 // Do nothing.
285 c.invalidate();
286 } // deiconifyFrame()
289 * This method activates the JInternalFrame by moving it to the front and
290 * selecting it.
292 * @param frame The JInternalFrame to activate.
294 public void activateFrame(JInternalFrame frame)
296 JDesktopPane p = frame.getDesktopPane();
298 if (p != null)
299 p.setSelectedFrame(frame);
300 else
304 frame.setSelected(true);
306 catch (PropertyVetoException e)
311 frame.toFront();
312 } // activateFrame()
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)
337 } // deactivateFrame()
340 * This method is called to indicate that the DesktopManager should prepare
341 * to drag the JInternalFrame. Any state information needed to drag the
342 * frame will be prepared now.
344 * @param component The JComponent to drag, usually a JInternalFrame.
346 public void beginDraggingFrame(JComponent component)
348 if (component instanceof JDesktopIcon)
349 pane = ((JDesktopIcon) component).getInternalFrame().getDesktopPane();
350 else
351 pane = ((JInternalFrame) component).getDesktopPane();
352 if (pane == null)
353 return;
355 dragCache = component.getBounds();
357 if (! (pane instanceof JDesktopPane))
358 currentDragMode = JDesktopPane.LIVE_DRAG_MODE;
359 else
360 currentDragMode = ((JDesktopPane) pane).getDragMode();
361 } // beginDraggingFrame()
364 * This method is called to drag the JInternalFrame to a new location.
366 * @param component The JComponent to drag, usually a JInternalFrame.
367 * @param newX The new x coordinate.
368 * @param newY The new y coordinate.
370 public void dragFrame(JComponent component, int newX, int newY)
372 if (currentDragMode == JDesktopPane.OUTLINE_DRAG_MODE)
374 // FIXME: Do outline drag mode painting.
376 else
378 Rectangle b = component.getBounds();
379 if (component instanceof JDesktopIcon)
380 component.setBounds(newX, newY, b.width, b.height);
381 else
382 setBoundsForFrame((JInternalFrame) component, newX, newY, b.width,
383 b.height);
385 } // dragFrame()
388 * This method indicates that the dragging is done. Any state information
389 * stored by the DesktopManager can be cleared.
391 * @param component The JComponent that has finished dragging.
393 public void endDraggingFrame(JComponent component)
395 if (currentDragMode == JDesktopPane.OUTLINE_DRAG_MODE)
397 setBoundsForFrame((JInternalFrame) component, dragCache.x,
398 dragCache.y, dragCache.width, dragCache.height);
399 pane = null;
400 dragCache = null;
402 component.repaint();
403 } // endDraggingFrame()
406 * This method is called to indicate that the given JComponent will be
407 * resized. Any state information necessary to resize the JComponent will
408 * be prepared now.
410 * @param component The JComponent to resize, usually a JInternalFrame.
411 * @param direction The direction to drag in (a SwingConstant).
413 public void beginResizingFrame(JComponent component, int direction)
415 pane = ((JInternalFrame) component).getDesktopPane();
416 if (pane == null)
417 return;
419 dragCache = component.getBounds();
420 if (! (pane instanceof JDesktopPane))
421 currentDragMode = JDesktopPane.LIVE_DRAG_MODE;
422 else
423 currentDragMode = ((JDesktopPane) pane).getDragMode();
424 } // beginResizingFrame()
427 * This method resizes the give JComponent.
429 * @param component The JComponent to resize.
430 * @param newX The new x coordinate.
431 * @param newY The new y coordinate.
432 * @param newWidth The new width.
433 * @param newHeight The new height.
435 public void resizeFrame(JComponent component, int newX, int newY,
436 int newWidth, int newHeight)
438 dragCache.setBounds(newX, newY, newWidth, newHeight);
440 if (currentDragMode == JDesktopPane.OUTLINE_DRAG_MODE)
442 // FIXME: Do outline drag painting.
444 else
445 setBoundsForFrame(component, dragCache.x, dragCache.y, dragCache.width,
446 dragCache.height);
447 } // resizeFrame()
450 * This method is called to indicate that the given JComponent has finished
451 * dragging. Any state information stored by the DesktopManager can be
452 * cleared.
454 * @param component The JComponent that finished resizing.
456 public void endResizingFrame(JComponent component)
458 if (currentDragMode == JDesktopPane.OUTLINE_DRAG_MODE)
460 setBoundsForFrame((JInternalFrame) component, dragCache.x,
461 dragCache.y, dragCache.width, dragCache.height);
462 pane = null;
463 dragCache = null;
465 component.repaint();
466 } // endResizingFrame()
469 * This method calls setBounds with the given parameters and repaints the
470 * JComponent.
472 * @param component The JComponent to set bounds for.
473 * @param newX The new x coordinate.
474 * @param newY The new y coordinate.
475 * @param newWidth The new width.
476 * @param newHeight The new height.
478 public void setBoundsForFrame(JComponent component, int newX, int newY,
479 int newWidth, int newHeight)
481 component.setBounds(newX, newY, newWidth, newHeight);
482 component.revalidate();
484 // If not null, I'd rather repaint the parent
485 if (component.getParent() != null)
486 component.getParent().repaint();
487 else
488 component.repaint();
489 } // setBoundsForFrame()
492 * This is a helper method that removes the JDesktopIcon of the given
493 * JInternalFrame from the parent.
495 * @param frame The JInternalFrame to remove an icon for.
497 protected void removeIconFor(JInternalFrame frame)
499 JDesktopIcon icon = frame.getDesktopIcon();
500 Container c = icon.getParent();
501 if (c != null && icon != null)
502 c.remove(icon);
503 } // removeIconFor()
506 * This method is called by iconifyFrame to determine the bounds of the
507 * JDesktopIcon for the given JInternalFrame.
509 * @param frame The JInternalFrame to find the bounds of its JDesktopIcon
510 * for.
512 * @return The bounds of the JDesktopIcon.
514 protected Rectangle getBoundsForIconOf(JInternalFrame frame)
516 // IconRects has no order to it.
517 // The icon _must_ be placed in the first free slot (working from
518 // the bottom left corner)
519 // The icon also must not be placed where another icon is placed
520 // (regardless whether that frame is an icon currently or not)
521 JDesktopPane desktopPane = frame.getDesktopPane();
522 Rectangle paneBounds = desktopPane.getBounds();
523 Insets insets = desktopPane.getInsets();
524 Dimension pref = frame.getDesktopIcon().getPreferredSize();
526 if (desktopPane == null)
527 return frame.getDesktopIcon().getBounds();
529 Component[] frames = desktopPane.getComponents();
531 int count = 0;
532 for (int i = 0, j = 0; i < frames.length; i++)
533 if (frames[i] instanceof JDesktopIcon
534 || frames[i] instanceof JInternalFrame
535 && ((JInternalFrame) frames[i]).getWasIcon() && frames[i] != frame)
536 count++;
537 iconRects = new Rectangle[count];
538 for (int i = 0, j = 0; i < frames.length; i++)
539 if (frames[i] instanceof JDesktopIcon)
540 iconRects[--count] = frames[i].getBounds();
541 else if (frames[i] instanceof JInternalFrame
542 && ((JInternalFrame) frames[i]).getWasIcon()
543 && frames[i] != frame)
544 iconRects[--count] = ((JInternalFrame) frames[i]).getDesktopIcon()
545 .getBounds();
547 int startingX = insets.left;
548 int startingY = paneBounds.height - insets.bottom - pref.height;
549 Rectangle ideal = new Rectangle(startingX, startingY, pref.width,
550 pref.height);
551 boolean clear = true;
553 while (iconRects.length > 0)
555 clear = true;
556 for (int i = 0; i < iconRects.length; i++)
558 if (iconRects[i] != null && iconRects[i].intersects(ideal))
560 clear = false;
561 break;
564 if (clear)
565 return ideal;
567 startingX += pref.width;
568 if (startingX + pref.width > paneBounds.width - insets.right)
570 startingX = insets.left;
571 startingY -= pref.height;
573 ideal.setBounds(startingX, startingY, pref.width, pref.height);
576 return ideal;
577 } // getBoundsForIconOf()
580 * This method sets the bounds of the JInternalFrame right before the
581 * maximizeFrame call.
583 * @param frame The JInternalFrame being maximized.
584 * @param rect The normal bounds.
586 protected void setPreviousBounds(JInternalFrame frame, Rectangle rect)
588 frame.setNormalBounds(rect);
589 } // setPreviousBounds()
592 * This method returns the normal bounds of the JInternalFrame from before
593 * the maximize call.
595 * @param frame The JInternalFrame that is being restored.
597 * @return The previous bounds of the JInternalFrame.
599 protected Rectangle getPreviousBounds(JInternalFrame frame)
601 return frame.getNormalBounds();
602 } // getPreviousBounds()
605 * This method sets the value to true if the given JInternalFrame has been
606 * iconized and the bounds of its DesktopIcon are valid.
608 * @param frame The JInternalFrame for the JDesktopIcon.
609 * @param value True if the JInternalFrame has been iconized and the bounds
610 * of the JDesktopIcon are valid.
612 protected void setWasIcon(JInternalFrame frame, boolean value)
614 frame.setWasIcon(value, WAS_ICON_ONCE_PROPERTY);
615 } // setWasIcon()
618 * This method returns true if the given JInternalFrame has been iconized
619 * and the bounds of its DesktopIcon are valid.
621 * @param frame The JInternalFrame for the JDesktopIcon.
623 * @return True if the given JInternalFrame has been iconized and the bounds
624 * of its DesktopIcon are valid.
626 protected boolean wasIcon(JInternalFrame frame)
628 return frame.getWasIcon();
629 } // wasIcon()
630 } // DefaultDesktopManager