001package apps;
002
003import java.awt.event.ActionEvent;
004import java.util.EventObject;
005import java.util.ResourceBundle;
006
007import javax.swing.*;
008import javax.swing.text.DefaultEditorKit;
009
010import apps.jmrit.DebugMenu;
011import apps.plaf.macosx.Application;
012
013import jmri.InstanceManager;
014import jmri.UserPreferencesManager;
015import jmri.jmrit.ToolsMenu;
016import jmri.jmrit.beantable.TablesMenu;
017import jmri.jmrit.decoderdefn.PrintDecoderListAction;
018import jmri.jmrit.display.PanelMenu;
019import jmri.jmrit.operations.OperationsMenu;
020import jmri.jmrit.roster.swing.RosterMenu;
021import jmri.jmrix.ActiveSystemsMenu;
022import jmri.util.HelpUtil;
023import jmri.util.SystemType;
024import jmri.util.WindowMenu;
025import jmri.util.swing.WindowInterface;
026
027/**
028  * Create the main menu for PanelPro and related apps.  Includes opening PanelPro from
029  * DecoderPro3.
030  * <p>
031  * Redundant menu code was removed from {@link apps.Apps} and {@link apps.AppsLaunchFrame}.
032  *
033  * @author Dave Sand Copyright (C) 2021
034  */
035public class AppsMainMenu {
036
037    static final ResourceBundle rb = ResourceBundle.getBundle("jmri.jmrit.jython.Bundle");      // Link for script menu items  // NOI18N
038    static Action prefsAction;
039
040    public AppsMainMenu() {
041    }
042
043    /**
044    * Add menus to a menu bar.
045    * <p>
046    * This does not include the development menu.
047    *
048    * @param menuBar The existing menu bar
049    * @param wi      The WindowInterface to associate actions in menus with
050    * @param pane    The JPanel to associate actions in menus with
051    * @param windowHelpID The the help id to be assigned to Help / Window Help...
052    */
053    protected static void createMenus(JMenuBar menuBar, WindowInterface wi, JPanel pane, String windowHelpID) {
054        fileMenu(menuBar, wi);
055        editMenu(menuBar, wi);
056        toolsMenu(menuBar, wi);
057        
058        UserPreferencesManager prefMgr = InstanceManager.getNullableDefault(UserPreferencesManager.class);
059        if (prefMgr != null) {
060            Object pref = prefMgr.getProperty("jmri.jmrit.ToolsMenu", "showTablesMenu");
061            boolean showMenu = false; // Default to false
062            if (pref instanceof Boolean) {
063                showMenu = (Boolean) pref;
064            }
065            if (showMenu) {
066                tablesMenu(menuBar, wi);
067            }
068        }
069
070        rosterMenu(menuBar, wi, pane);
071        panelMenu(menuBar, wi);
072        scriptMenu(menuBar, wi);
073        // check to see if operations should be in the main menu
074        if (jmri.jmrit.operations.setup.Setup.isMainMenuEnabled()) {
075            operationsMenu(menuBar, wi);
076        }
077        systemsMenu(menuBar, wi);
078        debugMenu(menuBar, wi, pane);
079        menuBar.add(new WindowMenu(wi));
080        helpMenu(menuBar, wi, pane, windowHelpID);
081    }
082
083    private static void fileMenu(JMenuBar menuBar, WindowInterface wi) {
084        JMenu fileMenu = new JMenu(Bundle.getMessage("MenuFile"));  // NOI18N
085        menuBar.add(fileMenu);
086
087        fileMenu.add(new jmri.configurexml.LoadXmlUserAction(Bundle.getMessage("FileMenuItemLoad")));  // NOI18N
088        fileMenu.add(new jmri.configurexml.StoreXmlUserAction(Bundle.getMessage("FileMenuItemStore")));  // NOI18N
089        fileMenu.add(new jmri.jmrit.revhistory.swing.FileHistoryAction(Bundle.getMessage("FileMenuItemHistory")));  // NOI18N
090
091        fileMenu.add(new JSeparator());
092
093        if (jmri.InstanceManager.getDefault(jmri.PermissionManager.class).isEnabled()) {
094            fileMenu.add(new jmri.jmrit.permission.swing.LoginAction());
095            fileMenu.add(new jmri.jmrit.permission.swing.LogoutAction());
096            fileMenu.add(new jmri.jmrit.permission.swing.ChangePasswordAction());
097            fileMenu.add(new JSeparator());
098        }
099
100        fileMenu.add(new PrintDecoderListAction(Bundle.getMessage("MenuPrintDecoderDefinitions"), wi.getFrame(), false));  // NOI18N
101        fileMenu.add(new PrintDecoderListAction(Bundle.getMessage("MenuPrintPreviewDecoderDefinitions"), wi.getFrame(), true));  // NOI18N
102
103        // Use Mac OS X native Quit if using Aqua look and feel
104        if (!(SystemType.isMacOSX() && UIManager.getLookAndFeel().isNativeLookAndFeel())) {
105            fileMenu.add(new JSeparator());
106            fileMenu.add(new AbstractAction(Bundle.getMessage("MenuItemQuit")) {  // NOI18N
107                @Override
108                public void actionPerformed(ActionEvent e) {
109                    handleQuit();
110                }
111            });
112        }
113    }
114
115    private static void editMenu(JMenuBar menuBar, WindowInterface wi) {
116
117        JMenu editMenu = new JMenu(Bundle.getMessage("MenuEdit"));  // NOI18N
118        menuBar.add(editMenu);
119
120        // cut, copy, paste
121        AbstractAction a;
122        a = new DefaultEditorKit.CutAction();
123        a.putValue(Action.NAME, Bundle.getMessage("MenuItemCut"));  // NOI18N
124        editMenu.add(a);
125        a = new DefaultEditorKit.CopyAction();
126        a.putValue(Action.NAME, Bundle.getMessage("MenuItemCopy"));  // NOI18N
127        editMenu.add(a);
128        a = new DefaultEditorKit.PasteAction();
129        a.putValue(Action.NAME, Bundle.getMessage("MenuItemPaste"));  // NOI18N
130        editMenu.add(a);
131
132        // prefs
133        prefsAction = new apps.gui3.tabbedpreferences.TabbedPreferencesAction(Bundle.getMessage("MenuItemPreferences"));  // NOI18N
134
135        // Put prefs in Apple's prefered area on Mac OS X
136        if (SystemType.isMacOSX()) {
137            Application.getApplication().setPreferencesHandler((EventObject eo) -> {
138                prefsAction.actionPerformed(null);
139            });
140        }
141        // Include prefs in Edit menu if not on Mac OS X or not using Aqua Look and Feel
142        if (!SystemType.isMacOSX() || !UIManager.getLookAndFeel().isNativeLookAndFeel()) {
143            editMenu.addSeparator();
144            editMenu.add(prefsAction);
145        }
146
147    }
148
149    private static void toolsMenu(JMenuBar menuBar, WindowInterface wi) {
150        menuBar.add(new ToolsMenu(Bundle.getMessage("MenuTools")));  // NOI18N
151    }
152
153    private static void tablesMenu(JMenuBar menuBar, WindowInterface wi) {
154        menuBar.add(new TablesMenu());
155    }
156
157    /**
158     * Add a script menu to the main menu bar.
159     *
160     * @param menuBar the menu bar to add the script menu to
161     * @param wi      the window interface containing menuBar
162     */
163    private static void scriptMenu(JMenuBar menuBar, WindowInterface wi) {
164        JMenu scriptMenu = new JMenu(rb.getString("MenuScripting"));  // NOI18N
165        scriptMenu.add(new jmri.jmrit.jython.RunJythonScript(rb.getString("MenuItemScript")));  // NOI18N
166        scriptMenu.add(new jmri.jmrit.automat.monitor.AutomatTableAction(rb.getString("MenuItemMonitor")));  // NOI18N
167        scriptMenu.add(new jmri.jmrit.jython.JythonWindow(rb.getString("MenuItemScriptLog")));  // NOI18N
168        scriptMenu.add(new jmri.script.swing.InputWindowAction(rb.getString("MenuItemScriptInput")));  // NOI18N
169        menuBar.add(scriptMenu);
170    }
171
172    private static void operationsMenu(JMenuBar menuBar, WindowInterface wi) {
173        menuBar.add(new OperationsMenu());
174    }
175
176    private static void rosterMenu(JMenuBar menuBar, WindowInterface wi, JPanel pane) {
177        menuBar.add(new RosterMenu(Bundle.getMessage("MenuRoster"), RosterMenu.MAINMENU, pane));  // NOI18N
178    }
179
180    private static void panelMenu(JMenuBar menuBar, WindowInterface wi) {
181        menuBar.add(new PanelMenu());
182    }
183
184    /**
185     * Show only active systems in the menu bar.
186     *
187     * @param menuBar the menu to attach systems menus to
188     * @param wi      ignored, but available for overriding methods to use if
189     *                needed
190     */
191    private static void systemsMenu(JMenuBar menuBar, WindowInterface wi) {
192        ActiveSystemsMenu.addItems(menuBar);
193    }
194
195    private static void debugMenu(JMenuBar menuBar, WindowInterface wi, JPanel pane) {
196        menuBar.add(new DebugMenu(pane));
197    }
198
199//     protected void developmentMenu(JMenuBar menuBar, WindowInterface wi) {
200//         JMenu devMenu = new JMenu("Development");
201//         menuBar.add(devMenu);
202//         devMenu.add(new jmri.jmrit.symbolicprog.autospeed.AutoSpeedAction("Auto-speed tool"));
203//         devMenu.add(new JSeparator());
204//         devMenu.add(new jmri.jmrit.automat.SampleAutomatonAction("Sample automaton 1"));
205//         devMenu.add(new jmri.jmrit.automat.SampleAutomaton2Action("Sample automaton 2"));
206//         devMenu.add(new jmri.jmrit.automat.SampleAutomaton3Action("Sample automaton 3"));
207//         //devMenu.add(new JSeparator());
208//         //devMenu.add(new jmri.jmrix.serialsensor.SerialSensorAction("Serial port sensors"));
209//     }
210
211    private static void helpMenu(JMenuBar menuBar, WindowInterface wi, JPanel containedPane, String windowHelpID) {
212        // create menu and standard items
213        JMenu helpMenu = HelpUtil.makeHelpMenu(windowHelpID, true);
214
215        // use as main help menu
216        menuBar.add(helpMenu);
217    }
218
219    /**
220     * The application decided to quit, handle that.
221     */
222    private static void handleQuit() {
223        AppsBase.handleQuit();
224    }
225
226//     private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(AppsMainMenu.class);
227}