1 /* BasicMenuBarUI.java --
2    Copyright (C) 2002, 2004, 2005  Free Software Foundation, Inc.
3 
4 This file is part of GNU Classpath.
5 
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.
10 
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.
15 
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., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
20 
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.
25 
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. */
37 
38 
39 package javax.swing.plaf.basic;
40 
41 import java.awt.Dimension;
42 import java.awt.event.ActionEvent;
43 import java.awt.event.ContainerEvent;
44 import java.awt.event.ContainerListener;
45 import java.awt.event.MouseEvent;
46 import java.beans.PropertyChangeEvent;
47 import java.beans.PropertyChangeListener;
48 
49 import javax.swing.AbstractAction;
50 import javax.swing.Action;
51 import javax.swing.ActionMap;
52 import javax.swing.BoxLayout;
53 import javax.swing.InputMap;
54 import javax.swing.JComponent;
55 import javax.swing.JMenu;
56 import javax.swing.JMenuBar;
57 import javax.swing.LookAndFeel;
58 import javax.swing.MenuElement;
59 import javax.swing.MenuSelectionManager;
60 import javax.swing.SwingUtilities;
61 import javax.swing.UIManager;
62 import javax.swing.event.ChangeEvent;
63 import javax.swing.event.ChangeListener;
64 import javax.swing.event.MouseInputListener;
65 import javax.swing.plaf.ActionMapUIResource;
66 import javax.swing.plaf.ComponentUI;
67 import javax.swing.plaf.MenuBarUI;
68 
69 /**
70  * UI Delegate for JMenuBar.
71  */
72 public class BasicMenuBarUI extends MenuBarUI
73 {
74 
75   /**
76    * This action is performed for the action command 'takeFocus'.
77    */
78   private static class FocusAction
79     extends AbstractAction
80   {
81 
82     /**
83      * Creates a new FocusAction.
84      */
FocusAction()85     FocusAction()
86     {
87       super("takeFocus");
88     }
89 
90     /**
91      * Performs the action.
92      */
actionPerformed(ActionEvent event)93     public void actionPerformed(ActionEvent event)
94     {
95       // In the JDK this action seems to pop up the first menu of the
96       // menu bar.
97       JMenuBar menuBar = (JMenuBar) event.getSource();
98       MenuSelectionManager defaultManager =
99         MenuSelectionManager.defaultManager();
100       MenuElement me[];
101       MenuElement subElements[];
102       JMenu menu = menuBar.getMenu(0);
103       if (menu != null)
104         {
105           me = new MenuElement[3];
106           me[0] = (MenuElement) menuBar;
107           me[1] = (MenuElement) menu;
108           me[2] = (MenuElement) menu.getPopupMenu();
109           defaultManager.setSelectedPath(me);
110         }
111     }
112 
113   }
114 
115   protected ChangeListener changeListener;
116 
117   /*ContainerListener that listens to the ContainerEvents fired from menu bar*/
118   protected ContainerListener containerListener;
119 
120   /*Property change listeners that listener to PropertyChangeEvent from menu bar*/
121   private PropertyChangeListener propertyChangeListener;
122 
123   /* menu bar for which this UI delegate is for*/
124   protected JMenuBar menuBar;
125 
126   /* MouseListener that listens to the mouseEvents fired from menu bar*/
127   private MouseInputListener mouseListener;
128 
129   /**
130    * Creates a new BasicMenuBarUI object.
131    */
BasicMenuBarUI()132   public BasicMenuBarUI()
133   {
134     changeListener = createChangeListener();
135     containerListener = createContainerListener();
136     propertyChangeListener = new PropertyChangeHandler();
137     mouseListener = new MouseInputHandler();
138   }
139 
140   /**
141    * Creates ChangeListener
142    *
143    * @return The ChangeListener
144    */
createChangeListener()145   protected ChangeListener createChangeListener()
146   {
147     return new ChangeHandler();
148   }
149 
150   /**
151    * Creates ContainerListener() to listen for ContainerEvents
152    * fired by JMenuBar.
153    *
154    * @return The ContainerListener
155    */
createContainerListener()156   protected ContainerListener createContainerListener()
157   {
158     return new ContainerHandler();
159   }
160 
161   /**
162    * Factory method to create a BasicMenuBarUI for the given {@link
163    * JComponent}, which should be a {@link JMenuBar}.
164    *
165    * @param x The {@link JComponent} a UI is being created for.
166    *
167    * @return A BasicMenuBarUI for the {@link JComponent}.
168    */
createUI(JComponent x)169   public static ComponentUI createUI(JComponent x)
170   {
171     return new BasicMenuBarUI();
172   }
173 
174   /**
175    * Returns maximum size for the specified menu bar
176    *
177    * @param c component for which to get maximum size
178    *
179    * @return  Maximum size for the specified menu bar
180    */
getMaximumSize(JComponent c)181   public Dimension getMaximumSize(JComponent c)
182   {
183     // let layout manager calculate its size
184     return null;
185   }
186 
187   /**
188    * Returns maximum allowed size of JMenuBar.
189    *
190    * @param c menuBar for which to return maximum size
191    *
192    * @return Maximum size of the give menu bar.
193    */
getMinimumSize(JComponent c)194   public Dimension getMinimumSize(JComponent c)
195   {
196     // let layout manager calculate its size
197     return null;
198   }
199 
200   /**
201    * Returns preferred size of JMenuBar.
202    *
203    * @param c menuBar for which to return preferred size
204    *
205    * @return Preferred size of the give menu bar.
206    */
getPreferredSize(JComponent c)207   public Dimension getPreferredSize(JComponent c)
208   {
209     // let layout manager calculate its size
210     return null;
211   }
212 
213   /**
214    * Initializes any default properties that this UI has from the defaults for
215    * the Basic look and feel.
216    */
installDefaults()217   protected void installDefaults()
218   {
219     LookAndFeel.installBorder(menuBar, "MenuBar.border");
220     LookAndFeel.installColorsAndFont(menuBar, "MenuBar.background",
221                                      "MenuBar.foreground", "MenuBar.font");
222     menuBar.setOpaque(true);
223   }
224 
225   /**
226    * This method installs the keyboard actions for the JMenuBar.
227    */
installKeyboardActions()228   protected void installKeyboardActions()
229   {
230     // Install InputMap.
231     Object[] bindings =
232       (Object[]) SharedUIDefaults.get("MenuBar.windowBindings");
233     InputMap inputMap = LookAndFeel.makeComponentInputMap(menuBar, bindings);
234     SwingUtilities.replaceUIInputMap(menuBar,
235                                      JComponent.WHEN_IN_FOCUSED_WINDOW,
236                                      inputMap);
237 
238     // Install ActionMap.
239     SwingUtilities.replaceUIActionMap(menuBar, getActionMap());
240   }
241 
242   /**
243    * Creates and returns the shared action map for JTrees.
244    *
245    * @return the shared action map for JTrees
246    */
getActionMap()247   private ActionMap getActionMap()
248   {
249     ActionMap am = (ActionMap) UIManager.get("MenuBar.actionMap");
250     if (am == null)
251       {
252         am = createDefaultActions();
253         UIManager.getLookAndFeelDefaults().put("MenuBar.actionMap", am);
254       }
255     return am;
256   }
257 
258   /**
259    * Creates the default actions when there are none specified by the L&F.
260    *
261    * @return the default actions
262    */
createDefaultActions()263   private ActionMap createDefaultActions()
264   {
265     ActionMapUIResource am = new ActionMapUIResource();
266     Action action = new FocusAction();
267     am.put(action.getValue(Action.NAME), action);
268     return am;
269   }
270 
271   /**
272    * This method installs the listeners needed for this UI to function.
273    */
installListeners()274   protected void installListeners()
275   {
276     menuBar.addContainerListener(containerListener);
277     menuBar.addPropertyChangeListener(propertyChangeListener);
278     menuBar.addMouseListener(mouseListener);
279   }
280 
281   /**
282   * Installs and initializes all fields for this UI delegate. Any properties
283   * of the UI that need to be initialized and/or set to defaults will be
284   * done now. It will also install any listeners necessary.
285   *
286   * @param c The {@link JComponent} that is having this UI installed.
287   */
installUI(JComponent c)288   public void installUI(JComponent c)
289   {
290     super.installUI(c);
291     menuBar = (JMenuBar) c;
292     menuBar.setLayout(new BoxLayout(menuBar, BoxLayout.X_AXIS));
293     installDefaults();
294     installListeners();
295     installKeyboardActions();
296   }
297 
298   /**
299    * This method uninstalls the defaults and nulls any objects created during
300    * install.
301    */
uninstallDefaults()302   protected void uninstallDefaults()
303   {
304     menuBar.setBackground(null);
305     menuBar.setBorder(null);
306     menuBar.setFont(null);
307     menuBar.setForeground(null);
308   }
309 
310   /**
311    * This method reverses the work done in installKeyboardActions.
312    */
uninstallKeyboardActions()313   protected void uninstallKeyboardActions()
314   {
315     SwingUtilities.replaceUIInputMap(menuBar,
316                                      JComponent.WHEN_IN_FOCUSED_WINDOW, null);
317     SwingUtilities.replaceUIActionMap(menuBar, null);
318   }
319 
320   /**
321    * Unregisters all the listeners that this UI delegate was using.
322    */
uninstallListeners()323   protected void uninstallListeners()
324   {
325     menuBar.removeContainerListener(containerListener);
326     menuBar.removePropertyChangeListener(propertyChangeListener);
327     menuBar.removeMouseListener(mouseListener);
328   }
329 
330   /**
331    * Performs the opposite of installUI. Any properties or resources that need
332    * to be cleaned up will be done now. It will also uninstall any listeners
333    * it has. In addition, any properties of this UI will be nulled.
334    *
335    * @param c The {@link JComponent} that is having this UI uninstalled.
336    */
uninstallUI(JComponent c)337   public void uninstallUI(JComponent c)
338   {
339     uninstallDefaults();
340     uninstallListeners();
341     uninstallKeyboardActions();
342     menuBar = null;
343   }
344 
345   private class ChangeHandler implements ChangeListener
346   {
stateChanged(ChangeEvent event)347     public void stateChanged(ChangeEvent event)
348     {
349       // TODO: What should be done here, if anything?
350     }
351   }
352 
353   /**
354    * This class handles ContainerEvents fired by JMenuBar. It revalidates
355    * and repaints menu bar whenever menu is added or removed from it.
356    */
357   private class ContainerHandler implements ContainerListener
358   {
359     /**
360      * This method is called whenever menu is added to the menu bar
361      *
362      * @param e The ContainerEvent.
363      */
componentAdded(ContainerEvent e)364     public void componentAdded(ContainerEvent e)
365     {
366       menuBar.revalidate();
367       menuBar.repaint();
368     }
369 
370     /**
371      * This method is called whenever menu is removed from the menu bar.
372      *
373      * @param e The ContainerEvent.
374      */
componentRemoved(ContainerEvent e)375     public void componentRemoved(ContainerEvent e)
376     {
377       menuBar.revalidate();
378       menuBar.repaint();
379     }
380   }
381 
382   /**
383    * This class handles PropertyChangeEvents fired from the JMenuBar
384    */
385   private class PropertyChangeHandler implements PropertyChangeListener
386   {
387     /**
388      * This method is called whenever one of the properties of the MenuBar
389      * changes.
390      *
391      * @param e The PropertyChangeEvent.
392      */
propertyChange(PropertyChangeEvent e)393     public void propertyChange(PropertyChangeEvent e)
394     {
395       if (e.getPropertyName().equals("borderPainted"))
396         menuBar.repaint();
397       if (e.getPropertyName().equals("margin"))
398         menuBar.repaint();
399     }
400   }
401 
402   private class MouseInputHandler implements MouseInputListener
403   {
404     /**
405      * Handles mouse clicked event
406      *
407      * @param e Mouse event
408      */
mouseClicked(MouseEvent e)409     public void mouseClicked(MouseEvent e)
410     {
411       MenuElement[] me = menuBar.getSubElements();
412 
413       for (int i = 0; i < me.length; i++)
414         {
415           JMenu menu = menuBar.getMenu(i);
416           if (menu != null)
417             menu.setSelected(false);
418         }
419     }
420 
421     /**
422      * Handles mouse pressed event
423      *
424      * @param e Mouse event
425      */
mousePressed(MouseEvent e)426     public void mousePressed(MouseEvent e)
427     {
428       // TODO: What should be done here, if anything?
429     }
430 
431     /**
432      * Handles mouse released event
433      *
434      * @param e Mouse event
435      */
mouseReleased(MouseEvent e)436     public void mouseReleased(MouseEvent e)
437     {
438       // TODO: What should be done here, if anything?
439     }
440 
441     /**
442      * Handles mouse exited event
443      *
444      * @param e Mouse event
445      */
mouseExited(MouseEvent e)446     public void mouseExited(MouseEvent e)
447     {
448       // TODO: What should be done here, if anything?
449     }
450 
451     /**
452      * Handles mouse dragged event
453      *
454      * @param e Mouse event
455      */
mouseDragged(MouseEvent e)456     public void mouseDragged(MouseEvent e)
457     {
458       // TODO: What should be done here, if anything?
459     }
460 
461     /**
462      * Handles mouse moved event
463      *
464      * @param e Mouse event
465      */
mouseMoved(MouseEvent e)466     public void mouseMoved(MouseEvent e)
467     {
468       // TODO: What should be done here, if anything?
469     }
470 
471     /**
472      * Handles mouse entered event
473      *
474      * @param e Mouse event
475      */
mouseEntered(MouseEvent e)476     public void mouseEntered(MouseEvent e)
477     {
478       // TODO: What should be done here, if anything?
479     }
480   }
481 }
482