View Javadoc
1   /*
2   
3       dsh-identify  Lightweight components for identifiable beans.
4       Copyright (c) 2003-2019 held jointly by the individual authors.
5   
6       This library is free software; you can redistribute it and/or modify it
7       under the terms of the GNU Lesser General Public License as published
8       by the Free Software Foundation; either version 3 of the License, or (at
9       your option) any later version.
10  
11      This library is distributed in the hope that it will be useful, but WITHOUT
12      ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
13      FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
14      License for more details.
15  
16      You should have received a copy of the GNU Lesser General Public License
17      along with this library;  if not, write to the Free Software Foundation,
18      Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA.
19  
20      > http://www.fsf.org/licensing/licenses/lgpl.html
21      > http://www.opensource.org/licenses/lgpl-license.php
22  
23  */
24  package org.dishevelled.identify;
25  
26  import java.awt.Component;
27  
28  import java.awt.event.ActionEvent;
29  
30  import java.util.Arrays;
31  import java.util.ArrayList;
32  import java.util.Collections;
33  import java.util.HashMap;
34  import java.util.List;
35  import java.util.Map;
36  
37  import javax.swing.AbstractAction;
38  import javax.swing.Action;
39  import javax.swing.ButtonGroup;
40  import javax.swing.JCheckBoxMenuItem;
41  import javax.swing.JPopupMenu;
42  import javax.swing.JToolBar;
43  import javax.swing.SwingConstants;
44  import javax.swing.UIManager;
45  
46  import org.dishevelled.iconbundle.IconSize;
47  import org.dishevelled.iconbundle.IconTextDirection;
48  
49  /**
50   * An extension of JToolBar that accepts identifiable actions
51   * and provides actions for changing display properties and
52   * icon sizes.
53   *
54   * @author  Michael Heuer
55   */
56  public final class IdToolBar
57      extends JToolBar
58  {
59      /** Display icons action. */
60      private final AbstractAction displayIcons = new AbstractAction("Display icons")
61          {
62              @Override
63              public void actionPerformed(final ActionEvent event)
64              {
65                  displayIcons();
66              }
67          };
68  
69      /** Display text action. */
70      private final AbstractAction displayText = new AbstractAction("Display text")
71          {
72              @Override
73              public void actionPerformed(final ActionEvent event)
74              {
75                  displayText();
76              }
77          };
78  
79      /** Display icons and text action. */
80      private final AbstractAction displayIconsAndText = new AbstractAction("Display icons and text")
81          {
82              @Override
83              public void actionPerformed(final ActionEvent event)
84              {
85                  displayIconsAndText();
86              }
87          };
88  
89      /** Display. */
90      private int display = DISPLAY_ICONS;
91  
92      /** Icon size. */
93      private IconSize iconSize = DEFAULT_ICON_SIZE;
94  
95      /** Icon text direction. */
96      private IconTextDirection iconTextDirection = DEFAULT_ICON_TEXT_DIRECTION;
97  
98      /** Display icons. */
99      private static final int DISPLAY_ICONS = 0;
100 
101     /** Display text. */
102     private static final int DISPLAY_TEXT = 1;
103 
104     /** Display icons and text. */
105     private static final int DISPLAY_ICONS_AND_TEXT = 2;
106 
107     /** Default icon size, <code>IconSize.DEFAULT_16X16</code>. */
108     public static final IconSize DEFAULT_ICON_SIZE = IconSize.DEFAULT_16X16;
109 
110     /** Default icon text direction, <code>IconTextDirection.LEFT_TO_RIGHT</code>. */
111     public static final IconTextDirection DEFAULT_ICON_TEXT_DIRECTION = IconTextDirection.LEFT_TO_RIGHT;
112 
113     /** List of display actions. */
114     private final List<AbstractAction> displayActions = Arrays.asList(new AbstractAction[] { displayIcons, displayText, displayIconsAndText });
115 
116     /** List of display menu items. */
117     private final List<JCheckBoxMenuItem> displayMenuItems = new ArrayList<JCheckBoxMenuItem>(displayActions.size());
118 
119     /** Map of icon size actions keyed by icon size. */
120     private final Map<IconSize, AbstractAction> iconSizeActions = new HashMap<IconSize, AbstractAction>();
121 
122     /** Map of icon size menu items keyed by icon size. */
123     private final Map<IconSize, JCheckBoxMenuItem> iconSizeMenuItems = new HashMap<IconSize, JCheckBoxMenuItem>();
124 
125     /** Icon size menu item button group. */
126     private final ButtonGroup iconSizeButtonGroup = new ButtonGroup();
127 
128 
129     /**
130      * Create a new tool bar.
131      */
132     public IdToolBar()
133     {
134         super();
135         // clear gradient for Metal/Ocean L&F
136         UIManager.put("MenuBar.gradient", null);
137         UIManager.getDefaults().put("MenuBar.gradient", null);
138         UIManager.getLookAndFeelDefaults().put("MenuBar.gradient", null);
139         // todo: remove style in GTK L&F
140 
141         createDisplayMenuItems();
142         displayIcons();
143         setIconSize(iconSize);
144     }
145 
146     /**
147      * Create a new tool bar with the specified orientation.
148      *
149      * @param orientation orientation, must be either <code>HORIZONTAL</code>
150      *    or <code>VERTICAL</code>
151      */
152     public IdToolBar(final int orientation)
153     {
154         super(orientation);
155         // clear gradient for Metal/Ocean L&F
156         UIManager.put("MenuBar.gradient", null);
157         UIManager.getDefaults().put("MenuBar.gradient", null);
158         UIManager.getLookAndFeelDefaults().put("MenuBar.gradient", null);
159 
160         createDisplayMenuItems();
161         displayIcons();
162         setIconSize(iconSize);
163     }
164 
165     /**
166      * Create a new tool bar with the specified name.
167      *
168      * @param name name of this tool bar
169      */
170     public IdToolBar(final String name)
171     {
172         super(name);
173         createDisplayMenuItems();
174         displayIcons();
175         setIconSize(iconSize);
176     }
177 
178     /**
179      * Create a new tool bar with the specified name and orientation.
180      *
181      * @param name name of this tool bar
182      * @param orientation orientation, must be either <code>HORIZONTAL</code>
183      *    or <code>VERTICAL</code>
184      */
185     public IdToolBar(final String name, final int orientation)
186     {
187         super(name, orientation);
188         createDisplayMenuItems();
189         displayIcons();
190         setIconSize(iconSize);
191     }
192 
193 
194     /**
195      * Create the display menu items.
196      */
197     private void createDisplayMenuItems() {
198         ButtonGroup buttonGroup = new ButtonGroup();
199         for (AbstractAction displayAction : displayActions)
200         {
201             JCheckBoxMenuItem menuItem = new JCheckBoxMenuItem(displayAction);
202             displayMenuItems.add(menuItem);
203             buttonGroup.add(menuItem);
204         }
205     }
206 
207     /**
208      * Add and return a new context menu button to this tool bar which raises the specified
209      * context menu.  The context menu button will not be null.
210      *
211      * @param contextMenu context menu to add to this tool bar, must not be null
212      * @return a new context menu button which raises the specified context menu
213      */
214     public ContextMenuButton add(final JPopupMenu contextMenu)
215     {
216         ContextMenuButtonxtMenuButton">ContextMenuButton contextMenuButton = new ContextMenuButton(contextMenu);
217 
218         // tweak visual settings; might be L&F dependent
219         contextMenuButton.setBorderPainted(false);
220         contextMenuButton.setFocusPainted(false);
221 
222         super.add(contextMenuButton);
223         return contextMenuButton;
224     }
225 
226     /**
227      * Add and return a new identifiable button to this tool bar which dispatches the specified
228      * identifiable action.  The identifiable button will not be null.
229      *
230      * @param identifiableAction identifiable action to add to this tool bar, must not be null
231      * @return a new identifiable button which dispatches the specified identifiable action
232      */
233     public IdButton add(final IdentifiableAction identifiableAction)
234     {
235         IdButtontml#IdButton">IdButton idButton = new IdButton(identifiableAction);
236         idButton.setIconSize(iconSize);
237         switch (display)
238         {
239             case DISPLAY_ICONS:
240                 idButton.displayIcon();
241                 break;
242             case DISPLAY_TEXT:
243                 idButton.displayText();
244                 break;
245             case DISPLAY_ICONS_AND_TEXT:
246                 idButton.displayIconAndText();
247                 break;
248             default:
249                 break;
250         }
251 
252         if (IdentifyUtils.isGTKLookAndFeel())
253         {
254             idButton.setHorizontalAlignment(SwingConstants.LEFT);
255             idButton.setHorizontalTextPosition(SwingConstants.TRAILING);
256             idButton.setVerticalTextPosition(SwingConstants.CENTER);
257         }
258         else
259         {
260             // default to icon over centered text layout
261             idButton.setHorizontalAlignment(SwingConstants.CENTER);
262             idButton.setHorizontalTextPosition(SwingConstants.CENTER);
263             idButton.setVerticalTextPosition(SwingConstants.BOTTOM);
264         }
265 
266         // tweak visual settings; might be L&F dependent
267         idButton.setBorderPainted(false);
268         idButton.setFocusPainted(false);
269 
270         super.add(idButton);
271         return idButton;
272     }
273 
274     /**
275      * Remove the identifiable button for the specified identifiable action from
276      * this tool bar, if such exists.
277      *
278      * @param identifiableAction identifiable action to remove from this tool bar
279      * @return the identifiable button removed from this tool bar, or null if no such button exists
280      */
281     public IdButton remove(final IdentifiableAction identifiableAction)
282     {
283         for (int i = 0; i < getComponentCount(); i++)
284         {
285             Component c = getComponent(i);
286             if (c instanceof IdButton)
287             {
288                 IdButton./../org/dishevelled/identify/IdButton.html#IdButton">IdButton idButton = (IdButton) c;
289                 Action action = idButton.getAction();
290                 if (action != null && action.equals(identifiableAction))
291                 {
292                     remove(idButton);
293                     return idButton;
294                 }
295             }
296         }
297         return null;
298     }
299 
300     /**
301      * Display icons only for the buttons in this tool bar.
302      */
303     public void displayIcons()
304     {
305         display = DISPLAY_ICONS;
306         displayIcons.putValue(Action.SELECTED_KEY, Boolean.TRUE);
307 
308         for (int i = 0, size = getComponentCount(); i < size; i++)
309         {
310             Component component = getComponentAtIndex(i);
311             if (component instanceof IdButton)
312             {
313                 IdButton./../org/dishevelled/identify/IdButton.html#IdButton">IdButton idButton = (IdButton) component;
314                 idButton.displayIcon();
315             }
316         }
317     }
318 
319     /**
320      * Display text only for the buttons in this tool bar.
321      */
322     public void displayText()
323     {
324         display = DISPLAY_TEXT;
325         displayText.putValue(Action.SELECTED_KEY, Boolean.TRUE);
326 
327         for (int i = 0, size = getComponentCount(); i < size; i++)
328         {
329             Component component = getComponentAtIndex(i);
330             if (component instanceof IdButton)
331             {
332                 IdButton./../org/dishevelled/identify/IdButton.html#IdButton">IdButton idButton = (IdButton) component;
333                 idButton.displayText();
334             }
335         }
336     }
337 
338     /**
339      * Display icons and text for the buttons in this tool bar.
340      */
341     public void displayIconsAndText()
342     {
343         display = DISPLAY_ICONS_AND_TEXT;
344         displayIconsAndText.putValue(Action.SELECTED_KEY, Boolean.TRUE);
345 
346         for (int i = 0, size = getComponentCount(); i < size; i++)
347         {
348             Component component = getComponentAtIndex(i);
349             if (component instanceof IdButton)
350             {
351                 IdButton./../org/dishevelled/identify/IdButton.html#IdButton">IdButton idButton = (IdButton) component;
352                 idButton.displayIconAndText();
353             }
354         }
355     }
356 
357     /**
358      * Return the icon size for all identifiable buttons in this tool bar.
359      *
360      * @return the icon size for all identifiable buttons in this tool bar
361      */
362     public IconSize getIconSize()
363     {
364         return iconSize;
365     }
366 
367     /**
368      * Set the icon size for all identifiable buttons in this tool bar to <code>iconSize</code>.
369      *
370      * @param iconSize icon size for all identifiable buttons in this tool bar, must not be null
371      */
372     public void setIconSize(final IconSize iconSize)
373     {
374         if (iconSize == null)
375         {
376             throw new IllegalArgumentException("iconSize must not be null");
377         }
378         Action iconSizeAction = createIconSizeAction(iconSize);
379         iconSizeAction.putValue(Action.SELECTED_KEY, Boolean.TRUE);
380 
381         for (int i = 0, size = getComponentCount(); i < size; i++)
382         {
383             Component component = getComponentAtIndex(i);
384             if (component instanceof IdButton)
385             {
386                 IdButton./../org/dishevelled/identify/IdButton.html#IdButton">IdButton idButton = (IdButton) component;
387                 idButton.setIconSize(iconSize);
388             }
389         }
390     }
391 
392     /**
393      * Return the icon text direction for all identifiable buttons in this tool bar.
394      *
395      * @return the icon text direction for all identifiable buttons in this tool bar
396      */
397     public IconTextDirection getIconTextDirection()
398     {
399         return iconTextDirection;
400     }
401 
402     /**
403      * Return an unmodifiable list of display actions.  The list will not be null.
404      *
405      * @return an unmodifiable list of display actions
406      */
407     public List<AbstractAction> getDisplayActions()
408     {
409         return displayActions;
410     }
411 
412     /**
413      * Return an unmodifiable list of check box menu items for the display actions.  The list
414      * will not be null.
415      *
416      * @return an unmodifiable list of check box menu items for the display actions
417      */
418     public List<JCheckBoxMenuItem> getDisplayMenuItems()
419     {
420         return Collections.unmodifiableList(displayMenuItems);
421     }
422 
423     /**
424      * Create and return a new icon size action for this tool bar for the specified icon size.
425      * The new icon size action will not be null.
426      *
427      * @param iconSize icon size for the new icon size action, must not be null
428      * @return a new icon size action for the specified icon size
429      */
430     public Action createIconSizeAction(final IconSize iconSize)
431     {
432         if (iconSize == null)
433         {
434             throw new IllegalArgumentException("iconSize must not be null");
435         }
436         if (!iconSizeActions.containsKey(iconSize))
437         {
438             iconSizeActions.put(iconSize, new IconSizeAction(iconSize));
439         }
440         return iconSizeActions.get(iconSize);
441     }
442 
443     /**
444      * Create and return a new icon size menu item for this tool bar for the specified icon size.
445      * The new icon size menu item will not be null.
446      *
447      * @param iconSize icon size for the new icon size menu item, must not be null
448      * @return a new icon size menu item for the specified icon size
449      */
450     public JCheckBoxMenuItem createIconSizeMenuItem(final IconSize iconSize)
451     {
452         if (iconSize == null)
453         {
454             throw new IllegalArgumentException("iconSize must not be null");
455         }
456         if (!iconSizeMenuItems.containsKey(iconSize))
457         {
458             AbstractAction iconSizeAction = (AbstractAction) createIconSizeAction(iconSize);
459             JCheckBoxMenuItem menuItem = new JCheckBoxMenuItem(iconSizeAction);
460             iconSizeButtonGroup.add(menuItem);
461             iconSizeMenuItems.put(iconSize, menuItem);
462         }
463         return iconSizeMenuItems.get(iconSize);
464     }
465 
466     /**
467      * Return an unmodifiable list of the default icon size actions.  The list will not be null.
468      *
469      * @return an unmodifiable list of the default icon size actions
470      */
471     public List<AbstractAction> getDefaultIconSizeActions()
472     {
473         List<AbstractAction> actions = new ArrayList<AbstractAction>(IconSize.VALUES.size());
474         for (int i = 0, size = IconSize.VALUES.size(); i < size; i++)
475         {
476             AbstractAction iconSizeAction = (AbstractAction) createIconSizeAction((IconSize) IconSize.VALUES.get(i));
477             actions.add(iconSizeAction);
478         }
479         return Collections.unmodifiableList(actions);
480     }
481 
482     /**
483      * Return an unmodifiable list of check box menu items for the default icon size actions.  The list
484      * will not be null.
485      *
486      * @return an unmodifiable list of check box menu items for the default icon size actions
487      */
488     public List<JCheckBoxMenuItem> getDefaultIconSizeMenuItems()
489     {
490         List<JCheckBoxMenuItem> menuItems = new ArrayList<JCheckBoxMenuItem>(IconSize.VALUES.size());
491         for (int i = 0, size = IconSize.VALUES.size(); i < size; i++)
492         {
493             JCheckBoxMenuItem iconSizeMenuItem = createIconSizeMenuItem((IconSize) IconSize.VALUES.get(i));
494             menuItems.add(iconSizeMenuItem);
495         }
496         return Collections.unmodifiableList(menuItems);
497     }
498 
499     /**
500      * Icon size action.
501      */
502     private class IconSizeAction extends AbstractAction
503     {
504         /** Icon size. */
505         private final IconSize iconSize;
506 
507 
508         /**
509          * Create a new icon size action for the specified icon size.
510          *
511          * @param iconSize icon size, must not be null
512          */
513         IconSizeAction(final IconSize iconSize)
514         {
515             super();
516             if (iconSize == null)
517             {
518                 throw new IllegalArgumentException("iconSize must not be null");
519             }
520             this.iconSize = iconSize;
521             putValue(Action.NAME, "Use icon size " + iconSize);
522         }
523 
524 
525         @Override
526         public void actionPerformed(final ActionEvent event)
527         {
528             setIconSize(iconSize);
529         }
530     }
531 }