2004-12-27 Michael Koch <konqueror@gmx.de>
[official-gcc.git] / libjava / javax / swing / DefaultDesktopManager.java
blob126d643f19f419ae813a4b150ffbf3282dbcfce7
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.Component;
41 import java.awt.Container;
42 import java.awt.Dimension;
43 import java.awt.Insets;
44 import java.awt.Rectangle;
45 import java.beans.PropertyVetoException;
46 import java.io.Serializable;
48 import javax.swing.JInternalFrame.JDesktopIcon;
50 /**
51 * DefaultDesktopManager is the default implementation of DesktopManager for
52 * swing. It implements the basic beaviours for JInternalFrames in arbitrary
53 * parents. The methods provided by the class are not meant to be called by
54 * the user, instead, the JInternalFrame methods will call these methods.
56 public class DefaultDesktopManager implements DesktopManager, Serializable
58 /** DOCUMENT ME! */
59 private static final long serialVersionUID = 4657624909838017887L;
61 /** The property change event fired when the wasIcon property changes. */
62 static final String WAS_ICON_ONCE_PROPERTY = "wasIconOnce";
64 /**
65 * The method of dragging used by the JDesktopPane that parents the
66 * JInternalFrame that is being dragged.
68 private int currentDragMode = 0;
70 /**
71 * The cache of the bounds used to draw the outline rectangle when
72 * OUTLINE_DRAG_MODE is used.
74 private transient Rectangle dragCache = new Rectangle();
76 /**
77 * A cached JDesktopPane that is stored when the JInternalFrame is initially
78 * dragged.
80 private transient Container pane;
82 /**
83 * An array of Rectangles that holds the bounds of the JDesktopIcons in the
84 * JDesktopPane when looking for where to place a new icon.
86 private transient Rectangle[] iconRects;
88 /**
89 * This creates a new DefaultDesktopManager object.
91 public DefaultDesktopManager()
93 } // DefaultDesktopManager()
95 /**
96 * This method is not normally called since the user will typically add the
97 * JInternalFrame to a Container. If this is called, it will try to
98 * determine the parent of the JInternalFrame and remove any icon that
99 * represents this JInternalFrame and add this JInternalFrame.
101 * @param frame The JInternalFrame to open.
103 public void openFrame(JInternalFrame frame)
105 Container c = frame.getParent();
106 if (c == null)
107 c = frame.getDesktopIcon().getParent();
108 if (c == null)
109 return;
111 c.remove(frame.getDesktopIcon());
112 c.add(frame);
113 frame.setVisible(true);
114 } // openFrame()
117 * This method removes the JInternalFrame and JDesktopIcon (if one is
118 * present) from their parents.
120 * @param frame The JInternalFrame to close.
122 public void closeFrame(JInternalFrame frame)
124 Container c = frame.getParent();
125 frame.doDefaultCloseAction();
127 if (c != null)
129 if (frame.isIcon())
130 c.remove(frame.getDesktopIcon());
131 else
132 c.remove(frame);
133 c.repaint();
135 } // closeFrame()
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.
174 } // maximizeFrame()
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);
203 } // minimizeFrame()
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)
228 Container c = frame.getParent();
230 if (! wasIcon(frame))
232 Rectangle r = getBoundsForIconOf(frame);
233 icon.setBounds(r);
234 setWasIcon(frame, true);
237 if (c != null)
239 if (icon != null)
241 c.add(icon);
242 icon.setVisible(true);
244 c.remove(frame);
246 } // iconifyFrame()
249 * This method removes the JInternalFrame's JDesktopIcon representation and
250 * adds the JInternalFrame back to its parent.
252 * @param frame The JInternalFrame to deiconify.
254 public void deiconifyFrame(JInternalFrame frame)
256 JDesktopIcon icon = frame.getDesktopIcon();
257 Container c = icon.getParent();
259 removeIconFor(frame);
260 c.add(frame);
261 frame.setVisible(true);
263 if (! frame.isSelected())
265 JDesktopPane p = frame.getDesktopPane();
266 if (p != null)
267 p.setSelectedFrame(frame);
268 else
272 frame.setSelected(true);
274 catch (PropertyVetoException e)
276 // Do nothing.
281 c.invalidate();
282 } // deiconifyFrame()
285 * This method activates the JInternalFrame by moving it to the front and
286 * selecting it.
288 * @param frame The JInternalFrame to activate.
290 public void activateFrame(JInternalFrame frame)
292 JDesktopPane p = frame.getDesktopPane();
294 if (p != null)
295 p.setSelectedFrame(frame);
296 else
300 frame.setSelected(true);
302 catch (PropertyVetoException e)
307 frame.toFront();
308 } // activateFrame()
311 * This method is called when the JInternalFrame loses focus.
313 * @param frame The JInternalFram to deactivate.
315 public void deactivateFrame(JInternalFrame frame)
317 JDesktopPane p = frame.getDesktopPane();
318 if (p != null)
320 if (p.getSelectedFrame() == frame)
321 p.setSelectedFrame(null);
323 else
327 frame.setSelected(false);
329 catch (PropertyVetoException e)
333 } // deactivateFrame()
336 * This method is called to indicate that the DesktopManager should prepare
337 * to drag the JInternalFrame. Any state information needed to drag the
338 * frame will be prepared now.
340 * @param component The JComponent to drag, usually a JInternalFrame.
342 public void beginDraggingFrame(JComponent component)
344 if (component instanceof JDesktopIcon)
345 pane = ((JDesktopIcon) component).getInternalFrame().getDesktopPane();
346 else
347 pane = ((JInternalFrame) component).getDesktopPane();
348 if (pane == null)
349 return;
351 dragCache = component.getBounds();
353 if (! (pane instanceof JDesktopPane))
354 currentDragMode = JDesktopPane.LIVE_DRAG_MODE;
355 else
356 currentDragMode = ((JDesktopPane) pane).getDragMode();
357 } // beginDraggingFrame()
360 * This method is called to drag the JInternalFrame to a new location.
362 * @param component The JComponent to drag, usually a JInternalFrame.
363 * @param newX The new x coordinate.
364 * @param newY The new y coordinate.
366 public void dragFrame(JComponent component, int newX, int newY)
368 if (currentDragMode == JDesktopPane.OUTLINE_DRAG_MODE)
370 // FIXME: Do outline drag mode painting.
372 else
374 Rectangle b = component.getBounds();
375 if (component instanceof JDesktopIcon)
376 component.setBounds(newX, newY, b.width, b.height);
377 else
378 setBoundsForFrame((JInternalFrame) component, newX, newY, b.width,
379 b.height);
381 } // dragFrame()
384 * This method indicates that the dragging is done. Any state information
385 * stored by the DesktopManager can be cleared.
387 * @param component The JComponent that has finished dragging.
389 public void endDraggingFrame(JComponent component)
391 if (currentDragMode == JDesktopPane.OUTLINE_DRAG_MODE)
393 setBoundsForFrame((JInternalFrame) component, dragCache.x,
394 dragCache.y, dragCache.width, dragCache.height);
395 pane = null;
396 dragCache = null;
398 component.repaint();
399 } // endDraggingFrame()
402 * This method is called to indicate that the given JComponent will be
403 * resized. Any state information necessary to resize the JComponent will
404 * be prepared now.
406 * @param component The JComponent to resize, usually a JInternalFrame.
407 * @param direction The direction to drag in (a SwingConstant).
409 public void beginResizingFrame(JComponent component, int direction)
411 pane = ((JInternalFrame) component).getDesktopPane();
412 if (pane == null)
413 return;
415 dragCache = component.getBounds();
416 if (! (pane instanceof JDesktopPane))
417 currentDragMode = JDesktopPane.LIVE_DRAG_MODE;
418 else
419 currentDragMode = ((JDesktopPane) pane).getDragMode();
420 } // beginResizingFrame()
423 * This method resizes the give JComponent.
425 * @param component The JComponent to resize.
426 * @param newX The new x coordinate.
427 * @param newY The new y coordinate.
428 * @param newWidth The new width.
429 * @param newHeight The new height.
431 public void resizeFrame(JComponent component, int newX, int newY,
432 int newWidth, int newHeight)
434 dragCache.setBounds(newX, newY, newWidth, newHeight);
436 if (currentDragMode == JDesktopPane.OUTLINE_DRAG_MODE)
438 // FIXME: Do outline drag painting.
440 else
441 setBoundsForFrame(component, dragCache.x, dragCache.y, dragCache.width,
442 dragCache.height);
443 } // resizeFrame()
446 * This method is called to indicate that the given JComponent has finished
447 * dragging. Any state information stored by the DesktopManager can be
448 * cleared.
450 * @param component The JComponent that finished resizing.
452 public void endResizingFrame(JComponent component)
454 if (currentDragMode == JDesktopPane.OUTLINE_DRAG_MODE)
456 setBoundsForFrame((JInternalFrame) component, dragCache.x,
457 dragCache.y, dragCache.width, dragCache.height);
458 pane = null;
459 dragCache = null;
461 component.repaint();
462 } // endResizingFrame()
465 * This method calls setBounds with the given parameters and repaints the
466 * JComponent.
468 * @param component The JComponent to set bounds for.
469 * @param newX The new x coordinate.
470 * @param newY The new y coordinate.
471 * @param newWidth The new width.
472 * @param newHeight The new height.
474 public void setBoundsForFrame(JComponent component, int newX, int newY,
475 int newWidth, int newHeight)
477 component.setBounds(newX, newY, newWidth, newHeight);
478 component.revalidate();
480 // If not null, I'd rather repaint the parent
481 if (component.getParent() != null)
482 component.getParent().repaint();
483 else
484 component.repaint();
485 } // setBoundsForFrame()
488 * This is a helper method that removes the JDesktopIcon of the given
489 * JInternalFrame from the parent.
491 * @param frame The JInternalFrame to remove an icon for.
493 protected void removeIconFor(JInternalFrame frame)
495 JDesktopIcon icon = frame.getDesktopIcon();
496 Container c = icon.getParent();
497 if (c != null && icon != null)
498 c.remove(icon);
499 } // removeIconFor()
502 * This method is called by iconifyFrame to determine the bounds of the
503 * JDesktopIcon for the given JInternalFrame.
505 * @param frame The JInternalFrame to find the bounds of its JDesktopIcon
506 * for.
508 * @return The bounds of the JDesktopIcon.
510 protected Rectangle getBoundsForIconOf(JInternalFrame frame)
512 // IconRects has no order to it.
513 // The icon _must_ be placed in the first free slot (working from
514 // the bottom left corner)
515 // The icon also must not be placed where another icon is placed
516 // (regardless whether that frame is an icon currently or not)
517 JDesktopPane desktopPane = frame.getDesktopPane();
518 Rectangle paneBounds = desktopPane.getBounds();
519 Insets insets = desktopPane.getInsets();
520 Dimension pref = frame.getDesktopIcon().getPreferredSize();
522 if (desktopPane == null)
523 return frame.getDesktopIcon().getBounds();
525 Component[] frames = desktopPane.getComponents();
527 int count = 0;
528 for (int i = 0, j = 0; i < frames.length; i++)
529 if (frames[i] instanceof JDesktopIcon
530 || frames[i] instanceof JInternalFrame
531 && ((JInternalFrame) frames[i]).getWasIcon() && frames[i] != frame)
532 count++;
533 iconRects = new Rectangle[count];
534 for (int i = 0, j = 0; i < frames.length; i++)
535 if (frames[i] instanceof JDesktopIcon)
536 iconRects[--count] = frames[i].getBounds();
537 else if (frames[i] instanceof JInternalFrame
538 && ((JInternalFrame) frames[i]).getWasIcon()
539 && frames[i] != frame)
540 iconRects[--count] = ((JInternalFrame) frames[i]).getDesktopIcon()
541 .getBounds();
543 int startingX = insets.left;
544 int startingY = paneBounds.height - insets.bottom - pref.height;
545 Rectangle ideal = new Rectangle(startingX, startingY, pref.width,
546 pref.height);
547 boolean clear = true;
549 while (iconRects.length > 0)
551 clear = true;
552 for (int i = 0; i < iconRects.length; i++)
554 if (iconRects[i] != null && iconRects[i].intersects(ideal))
556 clear = false;
557 break;
560 if (clear)
561 return ideal;
563 startingX += pref.width;
564 if (startingX + pref.width > paneBounds.width - insets.right)
566 startingX = insets.left;
567 startingY -= pref.height;
569 ideal.setBounds(startingX, startingY, pref.width, pref.height);
572 return ideal;
573 } // getBoundsForIconOf()
576 * This method sets the bounds of the JInternalFrame right before the
577 * maximizeFrame call.
579 * @param frame The JInternalFrame being maximized.
580 * @param rect The normal bounds.
582 protected void setPreviousBounds(JInternalFrame frame, Rectangle rect)
584 frame.setNormalBounds(rect);
585 } // setPreviousBounds()
588 * This method returns the normal bounds of the JInternalFrame from before
589 * the maximize call.
591 * @param frame The JInternalFrame that is being restored.
593 * @return The previous bounds of the JInternalFrame.
595 protected Rectangle getPreviousBounds(JInternalFrame frame)
597 return frame.getNormalBounds();
598 } // getPreviousBounds()
601 * This method sets the value to true if the given JInternalFrame has been
602 * iconized and the bounds of its DesktopIcon are valid.
604 * @param frame The JInternalFrame for the JDesktopIcon.
605 * @param value True if the JInternalFrame has been iconized and the bounds
606 * of the JDesktopIcon are valid.
608 protected void setWasIcon(JInternalFrame frame, boolean value)
610 frame.setWasIcon(value, WAS_ICON_ONCE_PROPERTY);
611 } // setWasIcon()
614 * This method returns true if the given JInternalFrame has been iconized
615 * and the bounds of its DesktopIcon are valid.
617 * @param frame The JInternalFrame for the JDesktopIcon.
619 * @return True if the given JInternalFrame has been iconized and the bounds
620 * of its DesktopIcon are valid.
622 protected boolean wasIcon(JInternalFrame frame)
624 return frame.getWasIcon();
625 } // wasIcon()
626 } // DefaultDesktopManager