001/* JDesktopPane.java --
002   Copyright (C) 2002, 2004 Free Software Foundation, Inc.
003
004This file is part of GNU Classpath.
005
006GNU Classpath is free software; you can redistribute it and/or modify
007it under the terms of the GNU General Public License as published by
008the Free Software Foundation; either version 2, or (at your option)
009any later version.
010
011GNU Classpath is distributed in the hope that it will be useful, but
012WITHOUT ANY WARRANTY; without even the implied warranty of
013MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014General Public License for more details.
015
016You should have received a copy of the GNU General Public License
017along with GNU Classpath; see the file COPYING.  If not, write to the
018Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
01902110-1301 USA.
020
021Linking this library statically or dynamically with other modules is
022making a combined work based on this library.  Thus, the terms and
023conditions of the GNU General Public License cover the whole
024combination.
025
026As a special exception, the copyright holders of this library give you
027permission to link this library with independent modules to produce an
028executable, regardless of the license terms of these independent
029modules, and to copy and distribute the resulting executable under
030terms of your choice, provided that you also meet, for each linked
031independent module, the terms and conditions of the license of that
032module.  An independent module is a module which is not derived from
033or based on this library.  If you modify this library, you may extend
034this exception to your version of the library, but you are not
035obligated to do so.  If you do not wish to do so, delete this
036exception statement from your version. */
037
038
039package javax.swing;
040
041import gnu.java.lang.CPStringBuilder;
042
043import java.awt.Component;
044import java.beans.PropertyVetoException;
045
046import javax.accessibility.Accessible;
047import javax.accessibility.AccessibleContext;
048import javax.accessibility.AccessibleRole;
049import javax.swing.plaf.DesktopPaneUI;
050
051/**
052 * JDesktopPane is a container (usually for JInternalFrames) that simulates a
053 * desktop. Typically, the user will create JInternalFrames and place them in
054 * a JDesktopPane. The user can then interact with JInternalFrames like they
055 * usually would with JFrames. The actions (minimize, maximize, close, etc)
056 * are done by using a DesktopManager that is associated with the
057 * JDesktopPane.
058 */
059public class JDesktopPane extends JLayeredPane implements Accessible
060{
061  private static final long serialVersionUID = 766333777224038726L;
062
063  /**
064   * This specifies that when dragged, a JInternalFrame should be completely
065   * visible.
066   *
067   * @specnote final since 1.5.0.
068   */
069  public static final int LIVE_DRAG_MODE = 0;
070
071  /**
072   * This specifies that when dragged, a JInternalFrame should only be visible
073   * as an outline.
074   *
075   * @specnote final since 1.5.0.
076   */
077  public static final int OUTLINE_DRAG_MODE = 1;
078
079  /** The selected frame in the JDesktopPane. */
080  private transient JInternalFrame selectedFrame;
081
082  /** The JDesktopManager to use for acting on JInternalFrames. */
083  transient DesktopManager desktopManager;
084
085  /** The drag mode used by the JDesktopPane. */
086  private transient int dragMode = LIVE_DRAG_MODE;
087
088  /**
089   * Indicates if the dragMode property has been set by a client
090   * program or by the UI.
091   *
092   * @see #setUIProperty(String, Object)
093   * @see LookAndFeel#installProperty(JComponent, String, Object)
094   */
095  private boolean clientDragModeSet = false;
096
097  /**
098   * Provides the accessibility features for the <code>JDesktopPane</code>
099   * component.
100   */
101  protected class AccessibleJDesktopPane extends AccessibleJComponent
102  {
103    private static final long serialVersionUID = 6079388927946077570L;
104
105    /**
106     * Creates a new <code>AccessibleJDesktopPane</code> instance.
107     */
108    protected AccessibleJDesktopPane()
109    {
110      // Nothing to do here.
111    }
112
113    /**
114     * Returns the accessible role for the <code>JSlider</code> component.
115     *
116     * @return {@link AccessibleRole#DESKTOP_PANE}.
117     */
118    public AccessibleRole getAccessibleRole()
119    {
120      return AccessibleRole.DESKTOP_PANE;
121    }
122  }
123
124  /**
125   * Creates a new JDesktopPane object.
126   */
127  public JDesktopPane()
128  {
129    setLayout(null);
130    updateUI();
131  }
132
133  /**
134   * This method returns the UI used with the JDesktopPane.
135   *
136   * @return The UI used with the JDesktopPane.
137   */
138  public DesktopPaneUI getUI()
139  {
140    return (DesktopPaneUI) ui;
141  }
142
143  /**
144   * This method sets the UI used with the JDesktopPane.
145   *
146   * @param ui The UI to use with the JDesktopPane.
147   */
148  public void setUI(DesktopPaneUI ui)
149  {
150    super.setUI(ui);
151  }
152
153  /**
154   * This method sets the drag mode to use with the JDesktopPane.
155   *
156   * @param mode The drag mode to use.
157   *
158   * @throws IllegalArgumentException If the drag mode given is not
159   *         LIVE_DRAG_MODE or OUTLINE_DRAG_MODE.
160   */
161  public void setDragMode(int mode)
162  {
163    if ((mode != LIVE_DRAG_MODE) && (mode != OUTLINE_DRAG_MODE))
164      throw new IllegalArgumentException("Drag mode not valid.");
165
166    clientDragModeSet = true;
167
168    // FIXME: Unsupported mode.
169    if (mode == OUTLINE_DRAG_MODE)
170      // throw new IllegalArgumentException("Outline drag modes are
171      // unsupported.");
172      mode = LIVE_DRAG_MODE;
173
174    dragMode = mode;
175  }
176
177  /**
178   * This method returns the drag mode used with the JDesktopPane.
179   *
180   * @return The drag mode used with the JDesktopPane.
181   */
182  public int getDragMode()
183  {
184    return dragMode;
185  }
186
187  /**
188   * This method returns the DesktopManager used with the JDesktopPane.
189   *
190   * @return The DesktopManager to use with the JDesktopPane.
191   */
192  public DesktopManager getDesktopManager()
193  {
194    return desktopManager;
195  }
196
197  /**
198   * This method sets the DesktopManager to use with the JDesktopPane.
199   *
200   * @param manager The DesktopManager to use with the JDesktopPane.
201   */
202  public void setDesktopManager(DesktopManager manager)
203  {
204    desktopManager = manager;
205  }
206
207  /**
208   * This method restores the UI used with the JDesktopPane to the default.
209   */
210  public void updateUI()
211  {
212    setUI((DesktopPaneUI) UIManager.getUI(this));
213  }
214
215  /**
216   * This method returns a String identifier that allows the UIManager to know
217   * which class will act as JDesktopPane's UI.
218   *
219   * @return A String identifier for the UI class to use.
220   */
221  public String getUIClassID()
222  {
223    return "DesktopPaneUI";
224  }
225
226  /**
227   * This method returns all JInternalFrames that are in the JDesktopPane.
228   *
229   * @return All JInternalFrames that are in the JDesktopPane.
230   */
231  public JInternalFrame[] getAllFrames()
232  {
233    return getFramesFromComponents(getComponents());
234  }
235
236  /**
237   * This method returns the currently selected frame in the JDesktopPane.
238   *
239   * @return The currently selected frame in the JDesktopPane.
240   */
241  public JInternalFrame getSelectedFrame()
242  {
243    return selectedFrame;
244  }
245
246  /**
247   * This method sets the selected frame in the JDesktopPane.
248   *
249   * @param frame The selected frame in the JDesktopPane.
250   */
251  public void setSelectedFrame(JInternalFrame frame)
252  {
253    if (selectedFrame != null)
254      {
255        try
256          {
257            selectedFrame.setSelected(false);
258          }
259        catch (PropertyVetoException e)
260          {
261            // We do nothing when the attempt is vetoed.
262          }
263      }
264    selectedFrame = null;
265
266    try
267      {
268        if (frame != null)
269          frame.setSelected(true);
270
271        selectedFrame = frame;
272      }
273    catch (PropertyVetoException e)
274      {
275        // We do nothing when the attempt is vetoed.
276      }
277  }
278
279  /**
280   * This method returns all the JInternalFrames in the given layer.
281   *
282   * @param layer The layer to grab frames in.
283   *
284   * @return All JInternalFrames in the given layer.
285   */
286  public JInternalFrame[] getAllFramesInLayer(int layer)
287  {
288    return getFramesFromComponents(getComponentsInLayer(layer));
289  }
290
291  /**
292   * This method always returns true to indicate that it is not transparent.
293   *
294   * @return true.
295   */
296  public boolean isOpaque()
297  {
298    return true;
299  }
300
301  /**
302   * Returns an implementation-dependent string describing the attributes of
303   * this <code>JDesktopPane</code>.
304   *
305   * @return A string describing the attributes of this <code>JDesktopPane</code>
306   *         (never <code>null</code>).
307   */
308  protected String paramString()
309  {
310    String superParamStr = super.paramString();
311    CPStringBuilder sb = new CPStringBuilder();
312    sb.append(",isOptimizedDrawingPossible=");
313    sb.append(isOptimizedDrawingEnabled());
314    sb.append(",desktopManager=");
315    if (desktopManager != null)
316      sb.append(desktopManager);
317    return superParamStr + sb.toString();
318  }
319
320  /**
321   * This method returns all the JInternalFrames in the given Component array.
322   *
323   * @param components An array to search for JInternalFrames in.
324   *
325   * @return An array of JInternalFrames found in the Component array.
326   */
327  private static JInternalFrame[] getFramesFromComponents(Component[] components)
328  {
329    int count = 0;
330
331    for (int i = 0; i < components.length; i++)
332        if (components[i] instanceof JInternalFrame)
333          count++;
334
335    JInternalFrame[] value = new JInternalFrame[count];
336    for (int i = 0, j = 0; i < components.length && j != count; i++)
337      if (components[i] instanceof JInternalFrame)
338        value[j++] = (JInternalFrame) components[i];
339    return value;
340  }
341
342  /**
343   * Returns the object that provides accessibility features for this
344   * <code>JDesktopPane</code> component.
345   *
346   * @return The accessible context (an instance of
347   *     {@link AccessibleJDesktopPane}).
348   */
349  public AccessibleContext getAccessibleContext()
350  {
351    if (accessibleContext == null)
352      accessibleContext = new AccessibleJDesktopPane();
353
354    return accessibleContext;
355  }
356
357  /**
358   * Helper method for
359   * {@link LookAndFeel#installProperty(JComponent, String, Object)}.
360   *
361   * @param propertyName the name of the property
362   * @param value the value of the property
363   *
364   * @throws IllegalArgumentException if the specified property cannot be set
365   *         by this method
366   * @throws ClassCastException if the property value does not match the
367   *         property type
368   * @throws NullPointerException if <code>c</code> or
369   *         <code>propertyValue</code> is <code>null</code>
370   */
371  void setUIProperty(String propertyName, Object value)
372  {
373    if (propertyName.equals("dragMode"))
374      {
375        if (! clientDragModeSet)
376          {
377            setDragMode(((Integer) value).intValue());
378            clientDragModeSet = false;
379          }
380      }
381    else
382      {
383        super.setUIProperty(propertyName, value);
384      }
385  }
386}