001    /* BasicDesktopPaneUI.java --
002       Copyright (C) 2004 Free Software Foundation, Inc.
003    
004    This file is part of GNU Classpath.
005    
006    GNU Classpath is free software; you can redistribute it and/or modify
007    it under the terms of the GNU General Public License as published by
008    the Free Software Foundation; either version 2, or (at your option)
009    any later version.
010    
011    GNU Classpath is distributed in the hope that it will be useful, but
012    WITHOUT ANY WARRANTY; without even the implied warranty of
013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014    General Public License for more details.
015    
016    You should have received a copy of the GNU General Public License
017    along with GNU Classpath; see the file COPYING.  If not, write to the
018    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
019    02110-1301 USA.
020    
021    Linking this library statically or dynamically with other modules is
022    making a combined work based on this library.  Thus, the terms and
023    conditions of the GNU General Public License cover the whole
024    combination.
025    
026    As a special exception, the copyright holders of this library give you
027    permission to link this library with independent modules to produce an
028    executable, regardless of the license terms of these independent
029    modules, and to copy and distribute the resulting executable under
030    terms of your choice, provided that you also meet, for each linked
031    independent module, the terms and conditions of the license of that
032    module.  An independent module is a module which is not derived from
033    or based on this library.  If you modify this library, you may extend
034    this exception to your version of the library, but you are not
035    obligated to do so.  If you do not wish to do so, delete this
036    exception statement from your version. */
037    
038    
039    package javax.swing.plaf.basic;
040    
041    import java.awt.Color;
042    import java.awt.Dimension;
043    import java.awt.event.ActionEvent;
044    import java.beans.PropertyVetoException;
045    
046    import javax.swing.AbstractAction;
047    import javax.swing.DefaultDesktopManager;
048    import javax.swing.DesktopManager;
049    import javax.swing.JComponent;
050    import javax.swing.JDesktopPane;
051    import javax.swing.JInternalFrame;
052    import javax.swing.KeyStroke;
053    import javax.swing.UIManager;
054    import javax.swing.plaf.ComponentUI;
055    import javax.swing.plaf.DesktopPaneUI;
056    import javax.swing.plaf.UIResource;
057    
058    /**
059     * This class is the UI delegate for JDesktopPane for the Basic look and feel.
060     */
061    public 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    }