001/* BasicDesktopPaneUI.java --
002   Copyright (C) 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.plaf.basic;
040
041import java.awt.Color;
042import java.awt.Dimension;
043import java.awt.event.ActionEvent;
044import java.beans.PropertyVetoException;
045
046import javax.swing.AbstractAction;
047import javax.swing.DefaultDesktopManager;
048import javax.swing.DesktopManager;
049import javax.swing.JComponent;
050import javax.swing.JDesktopPane;
051import javax.swing.JInternalFrame;
052import javax.swing.KeyStroke;
053import javax.swing.UIManager;
054import javax.swing.plaf.ComponentUI;
055import javax.swing.plaf.DesktopPaneUI;
056import javax.swing.plaf.UIResource;
057
058/**
059 * This class is the UI delegate for JDesktopPane for the Basic look and feel.
060 */
061public class BasicDesktopPaneUI extends DesktopPaneUI
062{
063  /**
064   * This helper class is used to handle key events that cause JInternalFrames
065   * to be closed.
066   */
067  protected class CloseAction extends AbstractAction
068  {
069    /**
070     * This method is called when the action is performed.
071     *
072     * @param e The ActionEvent.
073     */
074    public void actionPerformed(ActionEvent e)
075    {
076      if (desktop.getSelectedFrame() != null)
077        {
078          try
079            {
080              desktop.getSelectedFrame().setClosed(true);
081            }
082          catch (PropertyVetoException pve)
083            {
084              // We do nothing if the attempts has been vetoed.
085            }
086        }
087    }
088
089    /**
090     * This method returns whether the action is enabled.
091     *
092     * @return Whether the action is enabled.
093     */
094    public boolean isEnabled()
095    {
096      if (desktop.getSelectedFrame() != null)
097        return desktop.getSelectedFrame().isClosable();
098      return false;
099    }
100  }
101
102  /**
103   * This helper class is used to handle key events that cause JInternalFrames
104   * to be maximized.
105   */
106  protected class MaximizeAction extends AbstractAction
107  {
108    /**
109     * This method is called when the action is performed.
110     *
111     * @param e The ActionEvent.
112     */
113    public void actionPerformed(ActionEvent e)
114    {
115      if (desktop.getSelectedFrame() != null)
116        {
117          try
118            {
119              desktop.getSelectedFrame().setMaximum(true);
120            }
121          catch (PropertyVetoException pve)
122            {
123              // We do nothing if the attempts has been vetoed.
124            }
125        }
126    }
127
128    /**
129     * This method returns whether the action is enabled.
130     *
131     * @return Whether the action is enabled.
132     */
133    public boolean isEnabled()
134    {
135      if (desktop.getSelectedFrame() != null)
136        return desktop.getSelectedFrame().isMaximizable();
137      return false;
138    }
139  }
140
141  /**
142   * This helper class is used to handle key events that cause JInternalFrames
143   * to be minimized.
144   */
145  protected class MinimizeAction extends AbstractAction
146  {
147    /**
148     * This method is called when the action is performed.
149     *
150     * @param e The ActionEvent.
151     */
152    public void actionPerformed(ActionEvent e)
153    {
154      if (desktop.getSelectedFrame() != null)
155        {
156          try
157            {
158              desktop.getSelectedFrame().setIcon(true);
159            }
160          catch (PropertyVetoException pve)
161            {
162              // We do nothing if the attempt has been vetoed.
163            }
164        }
165    }
166
167    /**
168     * This method returns whether the action is enabled.
169     *
170     * @return Whether the action is enabled.
171     */
172    public boolean isEnabled()
173    {
174      if (desktop.getSelectedFrame() != null)
175        return desktop.getSelectedFrame().isIconifiable();
176      return false;
177    }
178  }
179
180  /**
181   * This helper class is used to handle key events that pass the SELECTED
182   * property to the next JInternalFrame in the JDesktopPane's list of
183   * children.
184   */
185  protected class NavigateAction extends AbstractAction
186  {
187    /**
188     * This method is called when the action is performed.
189     *
190     * @param e The ActionEvent.
191     */
192    public void actionPerformed(ActionEvent e)
193    {
194      // This is supposed to set the next selected frame.
195      JInternalFrame[] frames = desktop.getAllFrames();
196      if (frames.length == 0)
197        return;
198
199      JInternalFrame sFrame = frames[0];
200      if (desktop.getSelectedFrame() != null)
201        sFrame = desktop.getSelectedFrame();
202
203      int i = 0;
204      for (; i < frames.length; i++)
205        if (frames[i] == sFrame)
206          break;
207
208      // FIXME: Navigate actions go reverse too.
209      if (i == frames.length)
210        i = 0;
211
212      desktop.setSelectedFrame(frames[i]);
213    }
214
215    /**
216     * This method returns whether the action is enabled.
217     *
218     * @return Whether this action is enabled.
219     */
220    public boolean isEnabled()
221    {
222      // Always true.
223      return true;
224    }
225  }
226
227  /**
228   * This helper class is used to restore the JInternalFrame to its original
229   * size before maximizing or iconifying.
230   */
231  protected class OpenAction extends AbstractAction
232  {
233    /**
234     * This method is called when the action is performed.
235     *
236     * @param e The ActionEvent.
237     */
238    public void actionPerformed(ActionEvent e)
239    {
240      JInternalFrame frame = desktop.getSelectedFrame();
241      if (frame != null)
242        {
243          try
244            {
245              if (frame.isIcon())
246                frame.setIcon(false);
247              else if (frame.isMaximum())
248                frame.setMaximum(false);
249            }
250          catch (PropertyVetoException pve)
251            {
252              // We do nothing if the attempt has been vetoed.
253            }
254        }
255    }
256
257    /**
258     * This method returns whether the action is enabled.
259     *
260     * @return Whether this action is enabled.
261     */
262    public boolean isEnabled()
263    {
264      // JInternalFrames are always restorable.
265      return true;
266    }
267  }
268
269  /**
270   * The KeyStroke associated with closing JInternalFrames.
271   * @deprecated
272   */
273  protected KeyStroke closeKey;
274
275  /**
276   * The KeyStroke associated with maximizing JInternalFrames.
277   * @deprecated
278   */
279  protected KeyStroke maximizeKey;
280
281  /**
282   * The KeyStroke associated with minimizing JInternalFrames.
283   * @deprecated
284   */
285  protected KeyStroke minimizeKey;
286
287  /**
288   * The KeyStroke associated with navigating (forward?) through
289   * JInternalFrames.
290   * @deprecated
291   */
292  protected KeyStroke navigateKey;
293
294  /**
295   * The KeyStroke associated with navigating (backward?) through
296   * JInternalFrames.
297   * @deprecated
298   */
299  protected KeyStroke navigateKey2;
300
301  /** The default desktop manager used with JDesktopPane. */
302  protected DesktopManager desktopManager;
303
304  /** The JDesktopPane this UI is used with. */
305  protected JDesktopPane desktop;
306
307  /**
308   * Creates a new BasicDesktopPaneUI object.
309   */
310  public BasicDesktopPaneUI()
311  {
312    // Nothing to do here.
313  }
314
315  /**
316   * This method creates a BasicDesktopPaneUI for the given JComponent.
317   *
318   * @param c The JComponent to create a UI for.
319   *
320   * @return A new BasicDesktopPaneUI.
321   */
322  public static ComponentUI createUI(JComponent c)
323  {
324    return new BasicDesktopPaneUI();
325  }
326
327  /**
328   * This method returns the maximum size for the given JComponent.
329   *
330   * @param c The JComponent to find a maximum size for.
331   *
332   * @return The maximum size for the given JComponent.
333   */
334  public Dimension getMaximumSize(JComponent c)
335  {
336    return getPreferredSize(c);
337  }
338
339  /**
340   * This method returns the minimum size for the given JComponent.
341   *
342   * @param c The JComponent to find a minimum size for.
343   *
344   * @return The minimum size for the given JComponent.
345   */
346  public Dimension getMinimumSize(JComponent c)
347  {
348    return getPreferredSize(c);
349  }
350
351  /**
352   * This method returns the preferred size for the given JComponent.
353   *
354   * @param c The JComponent to find a preferred size for.
355   *
356   * @return The preferred size for the given JComponent.
357   */
358  public Dimension getPreferredSize(JComponent c)
359  {
360    // return null because JDesktopPanes don't have preferred sizes.
361    return null;
362  }
363
364  /**
365   * This method installs the defaults for the JDesktopPane provided by the
366   * current look and feel.
367   */
368  protected void installDefaults()
369  {
370    Color bg = desktop.getBackground();
371    if (bg == null || bg instanceof UIResource)
372      desktop.setBackground(UIManager.getColor("desktop"));
373  }
374
375  /**
376   * This method installs the desktop manager for the JDesktopPane.
377   */
378  protected void installDesktopManager()
379  {
380    desktopManager = new DefaultDesktopManager();
381    desktop.setDesktopManager(desktopManager);
382  }
383
384  /**
385   * This method installs the keyboard actions for the JDesktopPane.
386   */
387  protected void installKeyboardActions()
388  {
389    // FIXME: create actions and keystrokes.
390    registerKeyboardActions();
391  }
392
393  /**
394   * This method installs the UI for the given JComponent.
395   *
396   * @param c The JComponent to install this UI for.
397   */
398  public void installUI(JComponent c)
399  {
400    if (c instanceof JDesktopPane)
401      {
402        desktop = (JDesktopPane) c;
403
404        installDefaults();
405        installDesktopManager();
406        installKeyboardActions();
407      }
408  }
409
410  /**
411   * This method registers the actions to the appropriate Action and Input
412   * maps.
413   */
414  protected void registerKeyboardActions()
415  {
416    // FIXME: Do the binding.
417    // XXX: the gtk windows tend to intercept a lot of the
418    // key events for themselves. must figure a way past that
419    // before binding
420  }
421
422  /**
423   * This method reverses the work done by the installDefaults method.
424   */
425  protected void uninstallDefaults()
426  {
427    desktop.setBackground(null);
428  }
429
430  /**
431   * This method reverses the work done by the installDesktopManager method.
432   */
433  protected void uninstallDesktopManager()
434  {
435    desktopManager = null;
436    desktop.setDesktopManager(null);
437  }
438
439  /**
440   * This method reverses the work done by the installKeyboardActions method.
441   */
442  protected void uninstallKeyboardActions()
443  {
444    unregisterKeyboardActions();
445    // FIXME: null the actions and keystrokes.
446  }
447
448  /**
449   * This method reverses the work done by the registerKeyboardActions method.
450   */
451  protected void unregisterKeyboardActions()
452  {
453    // FIXME: unmap the keystrokes
454  }
455
456  /**
457   * This method uninstalls the UI for the given JComponent. It should reverse
458   * all the work done by the installUI method.
459   *
460   * @param c The JComponent to uninstall this UI for.
461   */
462  public void uninstallUI(JComponent c)
463  {
464    uninstallKeyboardActions();
465    uninstallDesktopManager();
466    uninstallDefaults();
467
468    desktop = null;
469  }
470}