Refactorization of the management of the actions in menus, button, shortcuts
[scilab.git] / scilab / modules / scinotes / src / java / org / scilab / modules / scinotes / SciNotesGUI.java
1 /* Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
2  * Copyright (C) 2009 - DIGITEO
3  * Copyright (C) 2010 - Calixte DENIZET
4  *
5  * This file must be used under the terms of the CeCILL.
6  * This source file is licensed as described in the file COPYING, which
7  * you should have received as part of this distribution.  The terms
8  * are also available at
9  * http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
10  *
11  */
12
13 package org.scilab.modules.scinotes;
14
15 import java.lang.reflect.InvocationTargetException;
16 import java.lang.reflect.Method;
17 import java.util.Map;
18 import java.util.HashMap;
19 import java.io.File;
20 import java.io.IOException;
21
22 import javax.swing.JPopupMenu;
23 import javax.swing.KeyStroke;
24 import javax.xml.parsers.DocumentBuilder;
25 import javax.xml.parsers.DocumentBuilderFactory;
26 import javax.xml.parsers.ParserConfigurationException;
27
28 import org.w3c.dom.Document;
29 import org.w3c.dom.Element;
30 import org.w3c.dom.Node;
31 import org.w3c.dom.NodeList;
32 import org.xml.sax.SAXException;
33
34 import org.scilab.modules.gui.menu.Menu;
35 import org.scilab.modules.gui.menu.ScilabMenu;
36 import org.scilab.modules.gui.bridge.menu.SwingScilabMenu;
37 import org.scilab.modules.gui.menubar.MenuBar;
38 import org.scilab.modules.gui.menubar.ScilabMenuBar;
39 import org.scilab.modules.gui.bridge.menuitem.SwingScilabMenuItem;
40 import org.scilab.modules.gui.menuitem.MenuItem;
41 import org.scilab.modules.gui.checkboxmenuitem.CheckBoxMenuItem;
42 import org.scilab.modules.gui.bridge.checkboxmenuitem.SwingScilabCheckBoxMenuItem;
43 import org.scilab.modules.gui.pushbutton.PushButton;
44 import org.scilab.modules.gui.textbox.ScilabTextBox;
45 import org.scilab.modules.gui.textbox.TextBox;
46 import org.scilab.modules.gui.toolbar.ScilabToolBar;
47 import org.scilab.modules.gui.toolbar.ToolBar;
48 import org.scilab.modules.gui.window.Window;
49 import org.scilab.modules.localization.Messages;
50 import org.scilab.modules.scinotes.utils.ConfigSciNotesManager;
51
52 /**
53  * Class SciNotesGUI handles menus, bar, ...
54  */
55 public final class SciNotesGUI {
56
57     private static final String MENU_CONF = System.getenv("SCI") + "/modules/scinotes/etc/scinotesGUIConfiguration.xml";
58     private static final String ERROR_READ = "Could not load file: ";
59     private static final String MENUBAR = "MenuBar";
60     private static final String TOOLBAR = "ToolBar";
61     private static final String RIGHTCLICKMENU = "RightClickMenu";
62     private static final String MENU = "menu";
63     private static final String MNEMONIC = "mnemonic";
64     private static final String LABEL = "label";
65     private static final String MENUITEM = "menuitem";
66     private static final String ACTION = "action";
67     private static final String SEPARATOR = "separator";
68     private static final String TOOLTIP = "tooltip";
69     private static final String ICON = "icon";
70     private static final String BUTTON = "button";
71     private static final String DOT = ".";
72
73     private static final String DEFAULTACTIONPATH = "org.scilab.modules.scinotes.actions";
74
75     private static TextBox infoBar;
76     private static Map<String, KeyStroke> map = new HashMap();
77     private static Document menuConf;
78
79     static {
80         ConfigSciNotesManager.addMapActionNameKeys(map);
81     }
82
83     /**
84      * initialize the window
85      * @param mainWindow Windows
86      * @param editorInstance SciNotes
87      * @param title the title
88      */
89     public static void init(Window mainWindow, final SciNotes editorInstance, String title) {
90         mainWindow.setTitle(title);
91         mainWindow.addTab(editorInstance);
92
93         // Set SciNotes Window position /size
94         mainWindow.setPosition(ConfigSciNotesManager.getMainWindowPosition());
95         mainWindow.setDims(ConfigSciNotesManager.getMainWindowSize());
96
97         infoBar = ScilabTextBox.createTextBox();
98
99         editorInstance.setMenuBar(generateMenuBar(editorInstance));
100         editorInstance.setToolBar(generateToolBar(editorInstance));
101         editorInstance.setInfoBar(infoBar);
102         mainWindow.setTitle(title);
103         mainWindow.setVisible(true);
104     }
105
106     /**
107      * @return the Map containing the pairs (Action, KeyStroke).
108      */
109     public static Map<String, KeyStroke> getActionKeyMap() {
110         return map;
111     }
112
113     /**
114      * @param editor the editor
115      * @return the JPopupMenu read in the conf file
116      */
117     public static JPopupMenu generateRightClickPopup(SciNotes editor) {
118         readMenusConf();
119         JPopupMenu popup = new JPopupMenu();
120         Element root = menuConf.getDocumentElement();
121         Element rightmenu = (Element) root.getElementsByTagName(RIGHTCLICKMENU).item(0);
122         NodeList menus = rightmenu.getChildNodes();
123         for (int i = 0; i < menus.getLength(); i++) {
124             Node item = menus.item(i);
125             if (MENUITEM.equals(item.getNodeName())) {
126                 Element elem = (Element) item;
127                 Object menuitem = getMenuItem(elem.getAttribute(ACTION), elem.getAttribute(LABEL), editor);
128                 if (menuitem != null) {
129                     if (menuitem instanceof CheckBoxMenuItem) {
130                         SwingScilabCheckBoxMenuItem checkbox = (SwingScilabCheckBoxMenuItem) ((CheckBoxMenuItem) menuitem).getAsSimpleCheckBoxMenuItem();
131                         popup.add(checkbox);
132                     } else if (menuitem instanceof MenuItem) {
133                         SwingScilabMenuItem smi = (SwingScilabMenuItem) ((MenuItem) menuitem).getAsSimpleMenuItem();
134                         popup.add(smi);
135                     } else if (menuitem instanceof Menu) {
136                         SwingScilabMenu sm = (SwingScilabMenu) ((Menu) menuitem).getAsSimpleMenu();
137                         popup.add(sm);
138                     }
139                 }
140             } else if (SEPARATOR.equals(item.getNodeName())) {
141                 popup.addSeparator();
142             } else if (MENU.equals(item.getNodeName())) {
143                 SwingScilabMenu sm = (SwingScilabMenu) getMenu(editor, (Element) item).getAsSimpleMenu();
144                 popup.add(sm);
145             }
146         }
147
148         return popup;
149     }
150
151     /**
152      * @param editor the editor
153      * @return the ToolBar read in the conf file
154      */
155     public static ToolBar generateToolBar(SciNotes editor) {
156         readMenusConf();
157         ToolBar toolBar = ScilabToolBar.createToolBar();
158         Element root = menuConf.getDocumentElement();
159         Element toolbar = (Element) root.getElementsByTagName(TOOLBAR).item(0);
160         NodeList buttons = toolbar.getChildNodes();
161         for (int i = 0; i < buttons.getLength(); i++) {
162             Node node = buttons.item(i);
163             if (BUTTON.equals(node.getNodeName())) {
164                 Element elem = (Element) node;
165                 PushButton pb = (PushButton) getButton(elem.getAttribute(ACTION), elem.getAttribute(TOOLTIP), elem.getAttribute(ICON), editor);
166                 toolBar.add(pb);
167             } else if (SEPARATOR.equals(node.getNodeName())) {
168                 toolBar.addSeparator();
169             }
170         }
171
172         return toolBar;
173     }
174
175     /**
176      * @param editor the editor
177      * @return the MenuBar read in the conf file
178      */
179     public static MenuBar generateMenuBar(SciNotes editor) {
180         readMenusConf();
181         MenuBar menuBar = ScilabMenuBar.createMenuBar();
182         Element root = menuConf.getDocumentElement();
183         Element menubar = (Element) root.getElementsByTagName(MENUBAR).item(0);
184         NodeList menus = menubar.getChildNodes();
185         for (int i = 0; i < menus.getLength(); i++) {
186             Node node = menus.item(i);
187             if (MENU.equals(node.getNodeName())) {
188                 menuBar.add(getMenu(editor, (Element) node));
189             }
190         }
191
192         return menuBar;
193     }
194
195     /**
196      * Read the conf file
197      */
198     private static void readMenusConf() {
199         File xml = null;
200         DocumentBuilder docBuilder = null;
201
202         try {
203             if (menuConf == null) {
204                 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
205                 docBuilder = factory.newDocumentBuilder();
206                 xml = new File(MENU_CONF);
207                 menuConf = docBuilder.parse(xml);
208             }
209         } catch (ParserConfigurationException pce) {
210             System.err.println(ERROR_READ + MENU_CONF);
211         } catch (SAXException se) {
212             System.err.println(ERROR_READ + MENU_CONF);
213         } catch (IOException ioe) {
214             System.err.println(ERROR_READ + MENU_CONF);
215         }
216     }
217
218     /**
219      * @param editor the editor
220      * @param node the node containing the informations
221      * @return the Menu
222      */
223     private static Menu getMenu(SciNotes editor, Element node) {
224         Menu menu = ScilabMenu.createMenu();
225         menu.setText(Messages.gettext(node.getAttribute(LABEL)));
226         String mnemonic = node.getAttribute(MNEMONIC);
227         if (mnemonic != null && mnemonic.length() != 0) {
228             menu.setMnemonic(mnemonic.charAt(0));
229         }
230         NodeList elements = node.getChildNodes();
231         for (int i = 0; i < elements.getLength(); i++) {
232             Node item = elements.item(i);
233             if (MENUITEM.equals(item.getNodeName())) {
234                 Element elem = (Element) item;
235                 Object menuitem = getMenuItem(elem.getAttribute(ACTION), elem.getAttribute(LABEL), editor);
236                 if (menuitem != null) {
237                     if (menuitem instanceof CheckBoxMenuItem) {
238                         menu.add((CheckBoxMenuItem) menuitem);
239                     } else if (menuitem instanceof MenuItem) {
240                         menu.add((MenuItem) menuitem);
241                     } else if (menuitem instanceof Menu) {
242                         menu.add((Menu) menuitem);
243                     }
244                 }
245             } else if (SEPARATOR.equals(item.getNodeName())) {
246                 menu.addSeparator();
247             } else if (MENU.equals(item.getNodeName())) {
248                 menu.add(getMenu(editor, (Element) item));
249             }
250         }
251
252         return menu;
253     }
254
255     /**
256      * @param action a string with the action associated with the button
257      * @param label the title of the menu
258      * @param editor the editor
259      * @return a MenuItem or a CheckBoxMenuItem or a Menu
260      */
261     private static Object getMenuItem(String action, String label, SciNotes editor) {
262         ClassLoader loader = ClassLoader.getSystemClassLoader();
263         String className = "";
264         try {
265             if (action.lastIndexOf(DOT) != -1)  {
266                 className = action;
267             } else {
268                 className = DEFAULTACTIONPATH + DOT + action;
269             }
270             Class clazz = loader.loadClass(className);
271             Method method = clazz.getMethod("createMenu", new Class[]{String.class, SciNotes.class, KeyStroke.class});
272             return method.invoke(null, new Object[]{Messages.gettext(label), editor, map.get(action)});
273         } catch (ClassNotFoundException e) {
274             System.err.println("No action: " + className);
275         } catch (NoSuchMethodException e) {
276             System.err.println("No valid method createMenu in action: " + className);
277         } catch (IllegalAccessException e) {
278             System.err.println("The method createMenu must be public: " + className);
279         } catch (InvocationTargetException e) {
280             System.err.println("The method createMenu in " + className + " threw an exception :");
281             e.printStackTrace();
282         }
283
284         return null;
285     }
286
287     /**
288      * @param action a string with the action associated with the button
289      * @param tooltip a string with the tooltip
290      * @param icon the icon name
291      * @param editor the editor
292      * @return the button
293      */
294     private static Object getButton(String action, String tooltip, String icon, SciNotes editor) {
295         ClassLoader loader = ClassLoader.getSystemClassLoader();
296         String className = "";
297         try {
298             if (action.lastIndexOf(DOT) != -1)  {
299                 className = action;
300             } else {
301                 className = DEFAULTACTIONPATH + DOT + action;
302             }
303             Class clazz = loader.loadClass(className);
304             Method method = clazz.getMethod("createButton", new Class[]{String.class, String.class, SciNotes.class});
305             return method.invoke(null, new Object[]{Messages.gettext(tooltip), icon, editor});
306         } catch (ClassNotFoundException e) {
307             System.err.println("No action: " + className);
308         } catch (NoSuchMethodException e) {
309             System.err.println("No valid method createButton in action: " + className);
310         } catch (IllegalAccessException e) {
311             System.err.println("The method createButton must be public: " + className);
312         } catch (InvocationTargetException e) {
313             System.err.println("The method createButton in " + className + " threw an exception :");
314             e.printStackTrace();
315         }
316
317         return null;
318     }
319 }