package com.baselet.gui.menu; import static com.baselet.control.constants.MenuConstants.ABOUT_PROGRAM; import static com.baselet.control.constants.MenuConstants.ALIGN; import static com.baselet.control.constants.MenuConstants.CLOSE; import static com.baselet.control.constants.MenuConstants.COPY; import static com.baselet.control.constants.MenuConstants.CUSTOM_ELEMENTS_TUTORIAL; import static com.baselet.control.constants.MenuConstants.CUT; import static com.baselet.control.constants.MenuConstants.DELETE; import static com.baselet.control.constants.MenuConstants.EDIT_CURRENT_PALETTE; import static com.baselet.control.constants.MenuConstants.EDIT_SELECTED; import static com.baselet.control.constants.MenuConstants.EXIT; import static com.baselet.control.constants.MenuConstants.EXPORT_AS; import static com.baselet.control.constants.MenuConstants.GENERATE_CLASS; import static com.baselet.control.constants.MenuConstants.GENERATE_CLASS_OPTIONS; import static com.baselet.control.constants.MenuConstants.GROUP; import static com.baselet.control.constants.MenuConstants.LAYER; import static com.baselet.control.constants.MenuConstants.LAYER_DOWN; import static com.baselet.control.constants.MenuConstants.LAYER_UP; import static com.baselet.control.constants.MenuConstants.MAIL_TO; import static com.baselet.control.constants.MenuConstants.NEW; import static com.baselet.control.constants.MenuConstants.NEW_CE; import static com.baselet.control.constants.MenuConstants.NEW_FROM_TEMPLATE; import static com.baselet.control.constants.MenuConstants.ONLINE_HELP; import static com.baselet.control.constants.MenuConstants.ONLINE_SAMPLE_DIAGRAMS; import static com.baselet.control.constants.MenuConstants.OPEN; import static com.baselet.control.constants.MenuConstants.OPTIONS; import static com.baselet.control.constants.MenuConstants.PASTE; import static com.baselet.control.constants.MenuConstants.PRINT; import static com.baselet.control.constants.MenuConstants.PROGRAM_HOMEPAGE; import static com.baselet.control.constants.MenuConstants.RATE_PROGRAM; import static com.baselet.control.constants.MenuConstants.RECENT_FILES; import static com.baselet.control.constants.MenuConstants.REDO; import static com.baselet.control.constants.MenuConstants.SAVE; import static com.baselet.control.constants.MenuConstants.SAVE_AS; import static com.baselet.control.constants.MenuConstants.SELECT_ALL; import static com.baselet.control.constants.MenuConstants.SET_BACKGROUND_COLOR; import static com.baselet.control.constants.MenuConstants.SET_FOREGROUND_COLOR; import static com.baselet.control.constants.MenuConstants.UNDO; import static com.baselet.control.constants.MenuConstants.UNGROUP; import static com.baselet.control.constants.MenuConstants.VIDEO_TUTORIAL; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import javax.swing.AbstractAction; import javax.swing.JComponent; import javax.swing.JMenu; import javax.swing.JMenuItem; import javax.swing.KeyStroke; import javax.swing.event.MenuEvent; import javax.swing.event.MenuListener; import com.baselet.control.Main; import com.baselet.control.constants.Constants; import com.baselet.control.constants.SystemInfo; import com.baselet.control.enums.Os; import com.baselet.control.util.RecentlyUsedFilesList; import com.baselet.diagram.draw.helper.ColorOwn; import com.baselet.gui.helper.PlainColorIcon; public class MenuFactorySwing extends MenuFactory { private static MenuFactorySwing instance = null; public static MenuFactorySwing getInstance() { if (instance == null) { instance = new MenuFactorySwing(); } return instance; } public JMenuItem createNew() { return createJMenuItem(false, NEW, KeyEvent.VK_N, true, null); } public JMenuItem createOpen() { return createJMenuItem(false, OPEN, KeyEvent.VK_O, true, null); } public JMenuItem createClose() { return createJMenuItem(false, CLOSE, KeyEvent.VK_W, true, null); } public JMenu createRecentFiles() { final JMenu recentFiles = new JMenu(); recentFiles.setText(RECENT_FILES); recentFiles.addMenuListener(new MenuListener() { @Override public void menuDeselected(MenuEvent e) {} @Override public void menuCanceled(MenuEvent e) {} @Override public void menuSelected(MenuEvent e) { recentFiles.removeAll(); for (String file : RecentlyUsedFilesList.getInstance()) { recentFiles.add(createJMenuItem(false, file, RECENT_FILES, file)); } } }); return recentFiles; } public JMenuItem createGenerate() { return createJMenuItem(false, GENERATE_CLASS, null); } public JMenuItem createGenerateOptions() { return createJMenuItem(false, GENERATE_CLASS_OPTIONS, null); } public JMenuItem createSave() { return createJMenuItem(true, SAVE, KeyEvent.VK_S, true, null); } public JMenuItem createSaveAs() { return createJMenuItem(true, SAVE_AS, null); } public JMenu createExportAs() { final JMenu export = new JMenu(); export.setText(EXPORT_AS); diagramDependendComponents.add(export); for (final String format : Constants.exportFormatList) { export.add(createJMenuItem(true, format.toUpperCase() + "...", EXPORT_AS, format)); } return export; } public JMenuItem createMailTo() { return createJMenuItem(true, MAIL_TO, KeyEvent.VK_M, true, null); } public JMenuItem createEditCurrentPalette() { return createJMenuItem(false, EDIT_CURRENT_PALETTE, null); } public JMenuItem createOptions() { return createJMenuItem(false, OPTIONS, null); } public JMenuItem createPrint() { return createJMenuItem(true, PRINT, KeyEvent.VK_P, true, null); } public JMenuItem createExit() { return createJMenuItem(false, EXIT, null); } public JMenuItem createUndo() { return createJMenuItem(false, UNDO, KeyEvent.VK_Z, true, null); } public JMenuItem createRedo() { return createJMenuItem(false, REDO, KeyEvent.VK_Y, true, null); } public JMenuItem createDelete() { int[] keys = new int[] { KeyEvent.VK_BACK_SPACE, KeyEvent.VK_DELETE }; // backspace AND delete both work for deleting elements if (SystemInfo.OS == Os.MAC) { // MacOS shows the backspace key mapping because it's the only one working - see http://stackoverflow.com/questions/4881262/java-keystroke-for-delete/4881606#4881606 return createJMenuItem(false, DELETE, keys, KeyEvent.VK_BACK_SPACE); } else { return createJMenuItem(false, DELETE, keys, KeyEvent.VK_DELETE); } } public JMenuItem createSelectAll() { return createJMenuItem(false, SELECT_ALL, KeyEvent.VK_A, true, null); } public JMenuItem createGroup() { return createJMenuItem(false, GROUP, KeyEvent.VK_G, true, null); } public JMenuItem createUngroup() { return createJMenuItem(false, UNGROUP, KeyEvent.VK_U, true, null); } public JMenuItem createCut() { return createJMenuItem(false, CUT, KeyEvent.VK_X, true, null); } public JMenuItem createCopy() { return createJMenuItem(false, COPY, KeyEvent.VK_C, true, null); } public JMenuItem createPaste() { return createJMenuItem(false, PASTE, KeyEvent.VK_V, true, null); } public JMenuItem createNewCustomElement() { return createJMenuItem(false, NEW_CE, null); } public JMenu createNewCustomElementFromTemplate() { JMenu menu = new JMenu(NEW_FROM_TEMPLATE); for (String template : Main.getInstance().getTemplateNames()) { menu.add(createJMenuItem(false, template, NEW_FROM_TEMPLATE, template)); } return menu; } public JMenuItem createEditSelected() { return createJMenuItem(false, EDIT_SELECTED, null); } public JMenuItem createCustomElementTutorial() { return createJMenuItem(false, CUSTOM_ELEMENTS_TUTORIAL, null); } public JMenuItem createOnlineHelp() { return createJMenuItem(false, ONLINE_HELP, null); } public JMenuItem createOnlineSampleDiagrams() { return createJMenuItem(false, ONLINE_SAMPLE_DIAGRAMS, null); } public JMenuItem createVideoTutorials() { return createJMenuItem(false, VIDEO_TUTORIAL, null); } public JMenuItem createProgramHomepage() { return createJMenuItem(false, PROGRAM_HOMEPAGE, null); } public JMenuItem createRateProgram() { return createJMenuItem(false, RATE_PROGRAM, null); } public JMenu createSetColor(boolean fg) { String name = fg ? SET_FOREGROUND_COLOR : SET_BACKGROUND_COLOR; JMenu menu = new JMenu(name); menu.add(createJMenuItem(false, "default", name, null)); for (String color : ColorOwn.COLOR_MAP.keySet()) { JMenuItem item = createJMenuItem(false, color, name, color); menu.add(item); item.setIcon(new PlainColorIcon(color)); } return menu; } public JMenuItem createAboutProgram() { return createJMenuItem(false, ABOUT_PROGRAM, null); } public JMenu createAlign() { JMenu alignMenu = new JMenu(ALIGN); for (String direction : new String[] { "Left", "Right", "Top", "Bottom" }) { alignMenu.add(createJMenuItem(false, direction, ALIGN, direction)); } return alignMenu; } public JMenu createLayerUp() { JMenu alignMenu = new JMenu(LAYER); for (String direction : new String[] { LAYER_DOWN, LAYER_UP }) { alignMenu.add(createJMenuItem(false, direction, LAYER, direction)); } return alignMenu; } private JMenuItem createJMenuItem(boolean grayWithoutDiagram, final String name, Object param) { return createJMenuItem(grayWithoutDiagram, name, name, null, null, param); } private JMenuItem createJMenuItem(boolean grayWithoutDiagram, final String name, Integer mnemonic, Boolean meta, Object param) { return createJMenuItem(grayWithoutDiagram, name, name, mnemonic, meta, param); } private JMenuItem createJMenuItem(boolean grayWithoutDiagram, final String menuName, final String actionName, final Object param) { return createJMenuItem(grayWithoutDiagram, menuName, actionName, null, null, param); } private JMenuItem createJMenuItem(boolean grayWithoutDiagram, final String menuName, final String actionName, Integer mnemonic, Boolean meta, final Object param) { JMenuItem menuItem = new JMenuItem(menuName); if (mnemonic != null) { menuItem.setMnemonic(mnemonic); menuItem.setAccelerator(KeyStroke.getKeyStroke(mnemonic, !meta ? 0 : SystemInfo.META_KEY.getMask())); } menuItem.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { doAction(actionName, param); } }); if (grayWithoutDiagram) { diagramDependendComponents.add(menuItem); } return menuItem; } /** * Create a JMenuItem with multiple key bindings (only one mnemonic can be set at any time). * @see "http://docs.oracle.com/javase/tutorial/uiswing/misc/action.html" */ private JMenuItem createJMenuItem(boolean grayWithoutDiagram, final String name, int[] keyEvents, int preferredMnemonic) { JMenuItem menuItem = new JMenuItem(name); MultipleKeyBindingsAction action = new MultipleKeyBindingsAction(name, preferredMnemonic); for (int keyEvent : keyEvents) { addKeyBinding(menuItem, keyEvent, name); } menuItem.getActionMap().put(name, action); menuItem.setAction(action); if (grayWithoutDiagram) { diagramDependendComponents.add(menuItem); } return menuItem; } private void addKeyBinding(JMenuItem menuItem, int keyEvent, String actionName) { menuItem.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(keyEvent, 0), actionName); } @SuppressWarnings("serial") private class MultipleKeyBindingsAction extends AbstractAction { public MultipleKeyBindingsAction(String menuName, int preferredMnemonic) { super(menuName); putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(preferredMnemonic, 0)); } @Override public void actionPerformed(ActionEvent e) { doAction(getValue(NAME).toString(), null); } } }