View Javadoc

1   /**
2    * This program is free software: you can redistribute it and/or modify
3    * it under the terms of the GNU General Public License as published by
4    * the Free Software Foundation, version 3.
5    *
6    * This program is distributed in the hope that it will be useful,
7    * but WITHOUT ANY WARRANTY; without even the implied warranty of
8    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9    * GNU General Public License for more details.
10   *
11   * You should have received a copy of the GNU General Public License
12   * along with this program. If not, see <http://www.gnu.org/licenses/>.
13   */
14  
15  package net.curre.prefcount.gui.menu;
16  
17  import java.awt.*;
18  import java.awt.event.ActionEvent;
19  import java.awt.event.ActionListener;
20  import java.util.HashMap;
21  import java.util.Map;
22  import java.util.ResourceBundle;
23  
24  import javax.swing.*;
25  
26  import net.curre.prefcount.PrefCountRegistry;
27  import net.curre.prefcount.bean.Settings;
28  import net.curre.prefcount.event.ChangeLanguageActionListener;
29  import net.curre.prefcount.event.ComputeButtonActionListener;
30  import net.curre.prefcount.event.LafMenuItemListener;
31  import net.curre.prefcount.event.SaveResetSettingsActionListener;
32  import net.curre.prefcount.event.AboutActionListener;
33  import net.curre.prefcount.gui.theme.skin.PrefSkin;
34  import net.curre.prefcount.service.LafThemeService;
35  import net.curre.prefcount.service.SettingsService;
36  import net.curre.prefcount.util.LocaleExt;
37  import net.curre.prefcount.util.Utilities;
38  
39  import static net.curre.prefcount.gui.menu.PrefCountMenuBar.MenuBarType.*;
40  
41  /**
42   * Object of this class represents a menu bar for Mac OS.
43   * This menu bar is assumed to be  placed at the top fo the
44   * screen. Other platforms are not supported by this class
45   * just because swing menu bar is a better option when not
46   * on Mac OS.
47   * <p/>
48   * Note that we are using awt menu bar because swing menu bar
49   * is not compatible with the substance look-and-feel library
50   * when running on Mac.
51   * <p/>
52   * Created date: Jan 24, 2008
53   *
54   * @author Yevgeny Nyden
55   */
56  public class AwtMenuBar extends MenuBar implements PrefCountMenuBar {
57  
58    /**
59     * Map that holds menu items and items label resource
60     * keys to button mappings for all menu items and buttons.
61     */
62    private Map<String, MenuItem> itemsResouceKeysMap;
63  
64    /** Reference to the action menu (initialized only on Mac OS). */
65    private Menu actionMenu;
66  
67    /** Menu item 'next' on the action menu. */
68    private MenuItem actonNextMenuItem;
69  
70    /** Menu item 'back' on the action menu. */
71    private MenuItem actonBackMenuItem;
72  
73    /** Menu item 'compute' on the action menu. */
74    private MenuItem actonComputeMenuItem;
75  
76    /** Reference to the language menu. */
77    private Menu languageMenu;
78  
79    /** Reference to the language label. */
80    private JLabel languageLabel;
81  
82    /**
83     * Constructor that sets the type of this menu bar,
84     * initializes necessary data structures, and creates the menus.
85     *
86     * @param menuBarType Type of this menu bar (for which frame it was created).
87     * @param topPanel    Reference to the main window top panel -
88     *                    the language indicator icon will be added there if
89     *                    menu bar type is MAIN_WINDOW.
90     * @throws IllegalArgumentException      If menu bar type is not supported.
91     * @throws UnsupportedOperationException When running on not Mac OS.
92     */
93    public AwtMenuBar(MenuBarType menuBarType, JPanel topPanel) {
94      if (menuBarType != MAIN_WINDOW && menuBarType != PLAYER_DIALOG) {
95        throw new IllegalArgumentException("Unsupported menu bar type: " + menuBarType);
96      }
97      if (!Utilities.isMacOs()) {
98        throw new UnsupportedOperationException("AwtMenuBar should only be created for Mac OS");
99      }
100     itemsResouceKeysMap = new HashMap<String, MenuItem>();
101     createMenus(menuBarType);
102 
103     // adding language indicator if necessary
104     // language icon (to the right of buttons) only if on Mac OS
105     if (menuBarType == MAIN_WINDOW) {
106       addLanguageIconToPanel(topPanel);
107     }
108   }
109 
110   /** {@inheritDoc} */
111   public void refreshMenuItemsLabels() {
112     ResourceBundle bundle = ResourceBundle.getBundle("default");
113     for (Map.Entry<String, MenuItem> entry : itemsResouceKeysMap.entrySet()) {
114       entry.getValue().setLabel(bundle.getString(entry.getKey()));
115     }
116     languageLabel.setIcon(PrefCountRegistry.getCurrentLocale().getEnabledIcon());
117   }
118 
119   /** {@inheritDoc} */
120   public void disableLanguageMenu() {
121     LocaleExt loc = PrefCountRegistry.getCurrentLocale();
122     languageLabel.setIcon(loc.getDisabledIcon());
123     languageMenu.setEnabled(false);
124     for (int i = 0; i < languageMenu.getItemCount(); ++i) {
125       languageMenu.getItem(i).setEnabled(false);
126     }
127   }
128 
129   /** {@inheritDoc} */
130   public void disableActionMenu() {
131     actionMenu.setEnabled(false);
132     for (int i = 0; i < actionMenu.getItemCount(); ++i) {
133       actionMenu.getItem(i).setEnabled(false);
134     }
135   }
136 
137   /** {@inheritDoc} */
138   public void toggleNextAction(boolean enabled) {
139     actonNextMenuItem.setEnabled(enabled);
140   }
141 
142   /** {@inheritDoc} */
143   public void toggleBackAction(boolean enabled) {
144     actonBackMenuItem.setEnabled(enabled);
145   }
146 
147   /** {@inheritDoc} */
148   public void toggleComputeAction(boolean enabled) {
149     actonComputeMenuItem.setEnabled(enabled);
150   }
151 
152   /** Private methods ***********************/
153 
154   /**
155    * Creates all necessary menus and menu items.
156    *
157    * @param menuBarType Type of the menu bar to create
158    *                    (indicates for which window).
159    */
160   private void createMenus(MenuBarType menuBarType) {
161     ResourceBundle bundle = ResourceBundle.getBundle("default");
162 
163     // CREATING MAIN MENU
164     Menu mainMenu = new Menu(bundle.getString("pref.mainMenu.main"));
165     itemsResouceKeysMap.put("pref.mainMenu.main", mainMenu);
166 
167     // ..... creating Look and Feel submenu
168     Settings settings = SettingsService.getSettings();
169     Menu lafMenu = new Menu(bundle.getString("pref.mainMenu.look"));
170     itemsResouceKeysMap.put("pref.mainMenu.look", lafMenu);
171 
172     AwtCheckboxMenuGroup group = new AwtCheckboxMenuGroup();
173     for (final PrefSkin skin : LafThemeService.AVAILABLE_SKINS) {
174       CheckboxMenuItem lafItem = new CheckboxMenuItem(bundle.getString(skin.getNameResourceKey()));
175       itemsResouceKeysMap.put(skin.getNameResourceKey(), lafItem);
176       if (skin.getNameResourceKey().equals(settings.getLafSkinId())) {
177         lafItem.setState(true);
178       }
179       lafItem.addItemListener(new LafMenuItemListener(skin));
180       group.addItemToGroup(lafItem);
181       lafMenu.add(lafItem);
182     }
183     mainMenu.add(lafMenu);
184 
185     // .....  creating other menu items on the main menu
186     MenuItem menuItem = new MenuItem(bundle.getString("pref.mainMenu.print"));
187     menuItem.setEnabled(false);
188     menuItem.setShortcut(new MenuShortcut(
189         bundle.getString("pref.mainMenu.settings.print.shortcut").charAt(0), false));
190     itemsResouceKeysMap.put("pref.mainMenu.print", menuItem);
191     mainMenu.add(menuItem);
192     mainMenu.addSeparator();
193     menuItem = new MenuItem(bundle.getString("pref.mainMenu.settings.save"));
194     menuItem.addActionListener(new SaveResetSettingsActionListener(true));
195     menuItem.setShortcut(new MenuShortcut(
196         bundle.getString("pref.mainMenu.settings.save.shortcut").charAt(0), false));
197     itemsResouceKeysMap.put("pref.mainMenu.settings.save", menuItem);
198     mainMenu.add(menuItem);
199 
200     menuItem = new MenuItem(bundle.getString("pref.mainMenu.settings.reset"));
201     menuItem.addActionListener(new SaveResetSettingsActionListener(false));
202     menuItem.setShortcut(new MenuShortcut(
203         bundle.getString("pref.mainMenu.settings.reset.shortcut").charAt(0), false));
204     itemsResouceKeysMap.put("pref.mainMenu.settings.reset", menuItem);
205     mainMenu.add(menuItem);
206     super.add(mainMenu);
207 
208     // CREATING ACTION MENU
209     actionMenu = new Menu(bundle.getString("pref.actionMenu.name"));
210     itemsResouceKeysMap.put("pref.actionMenu.name", actionMenu);
211 
212     // action menu is different depending on the window
213     switch (menuBarType) {
214       case MAIN_WINDOW:
215         MenuItem acton3PlayersMenuItem = new MenuItem(bundle.getString("pref.actionMenu.player3"));
216         acton3PlayersMenuItem.setShortcut(new MenuShortcut(
217             bundle.getString("pref.actionMenu.player3.shortcut").charAt(0), false));
218         acton3PlayersMenuItem.addActionListener(new ActionListener() {
219           public void actionPerformed(ActionEvent actionEvent) {
220             PrefCountRegistry.getInstance().getMainWindow().startPlayerDialog(3);
221           }
222         });
223         itemsResouceKeysMap.put("pref.actionMenu.player3", acton3PlayersMenuItem);
224         actionMenu.add(acton3PlayersMenuItem);
225         MenuItem acton4PlayersMenuItem = new MenuItem(bundle.getString("pref.actionMenu.player4"));
226         acton4PlayersMenuItem.setShortcut(new MenuShortcut(
227             bundle.getString("pref.actionMenu.player4.shortcut").charAt(0), false));
228         acton4PlayersMenuItem.addActionListener(new ActionListener() {
229           public void actionPerformed(ActionEvent actionEvent) {
230             PrefCountRegistry.getInstance().getMainWindow().startPlayerDialog(4);
231           }
232         });
233         itemsResouceKeysMap.put("pref.actionMenu.player4", acton4PlayersMenuItem);
234         actionMenu.add(acton4PlayersMenuItem);
235         break;
236       case PLAYER_DIALOG:
237         actonNextMenuItem = new MenuItem(bundle.getString("pref.actionMenu.next"));
238         actonNextMenuItem.setShortcut(new MenuShortcut(
239             bundle.getString("pref.actionMenu.next.shortcut").charAt(0), false));
240         actonNextMenuItem.addActionListener(new ActionListener() {
241           public void actionPerformed(ActionEvent actionEvent) {
242             PrefCountRegistry.getInstance().getMainWindow().playerDialogFrame.nextQuestionEventHelper(true);
243           }
244         });
245         itemsResouceKeysMap.put("pref.actionMenu.next", actonNextMenuItem);
246         actionMenu.add(actonNextMenuItem);
247         actonBackMenuItem = new MenuItem(bundle.getString("pref.actionMenu.back"));
248         actonBackMenuItem.setShortcut(new MenuShortcut(
249             bundle.getString("pref.actionMenu.back.shortcut").charAt(0), false));
250         actonBackMenuItem.addActionListener(new ActionListener() {
251           public void actionPerformed(ActionEvent actionEvent) {
252             PrefCountRegistry.getInstance().getMainWindow().playerDialogFrame.nextQuestionEventHelper(false);
253           }
254         });
255         itemsResouceKeysMap.put("pref.actionMenu.back", actonBackMenuItem);
256         actonBackMenuItem.setEnabled(false);
257         actionMenu.add(actonBackMenuItem);
258         actonComputeMenuItem = new MenuItem(bundle.getString("pref.actionMenu.compute"));
259         actonComputeMenuItem.addActionListener(new ComputeButtonActionListener());
260         actonComputeMenuItem.setShortcut(new MenuShortcut(
261             bundle.getString("pref.actionMenu.compute.shortcut").charAt(0), false));
262         itemsResouceKeysMap.put("pref.actionMenu.compute", actonComputeMenuItem);
263         actonComputeMenuItem.setEnabled(false);
264         actionMenu.addSeparator();
265         actionMenu.add(actonComputeMenuItem);
266         break;
267     }
268     super.add(actionMenu);
269 
270     // CREATING LANGUAGE MENU (for main window only)
271     if (menuBarType == MAIN_WINDOW) {
272       languageMenu = new Menu(bundle.getString("pref.langMenu.name"));
273       itemsResouceKeysMap.put("pref.langMenu.name", languageMenu);
274       LocaleExt loc = PrefCountRegistry.getCurrentLocale();
275       group = new AwtCheckboxMenuGroup();
276       for (final LocaleExt currLoc : PrefCountRegistry.AVAILABLE_LOCALES) {
277         CheckboxMenuItem rbMenuItem = new CheckboxMenuItem(currLoc.getDisplayLanguage());
278         if (currLoc.equals(loc)) {
279           rbMenuItem.setState(true);
280         }
281         rbMenuItem.addItemListener(new ChangeLanguageActionListener(currLoc.getLocale().getLanguage()));
282         group.addItemToGroup(rbMenuItem);
283         languageMenu.add(rbMenuItem);
284       }
285       super.add(languageMenu);
286     }
287 
288     // CREATING HELP MENU
289     Menu helpMenu = new Menu(bundle.getString("pref.helpMenu.name"));
290     itemsResouceKeysMap.put("pref.helpMenu.name", helpMenu);
291     menuItem = new MenuItem(bundle.getString("pref.helpMenu.count"));
292     menuItem.setEnabled(false);
293     itemsResouceKeysMap.put("pref.helpMenu.count", menuItem);
294     helpMenu.add(menuItem);
295     menuItem = new MenuItem(bundle.getString("pref.helpMenu.about"));
296     itemsResouceKeysMap.put("pref.helpMenu.about", menuItem);
297     menuItem.addActionListener(new AboutActionListener());
298     helpMenu.add(menuItem);
299     super.add(helpMenu);
300   }
301 
302   /**
303    * Adds language indicator to the right of the
304    * players number buttons provided the main window
305    * top panel reference.
306    *
307    * @param topPanel Reference to the main window top panel.
308    */
309   private void addLanguageIconToPanel(JPanel topPanel) {
310     LocaleExt loc = PrefCountRegistry.getCurrentLocale();
311     JPanel langIconPanel = new JPanel();
312     languageLabel = new JLabel(loc.getEnabledIcon());
313     langIconPanel.add(languageLabel);
314     JPanel phonyPanel = new JPanel();
315     phonyPanel.add(new JLabel(""));
316     phonyPanel.add(Box.createHorizontalStrut(16));
317     topPanel.add(langIconPanel, BorderLayout.EAST);
318     topPanel.add(phonyPanel, BorderLayout.WEST); // to center the buttons panel
319   }
320 
321 }