add load as palette option in palette browser
[scilab.git] / scilab / modules / xcos / src / java / org / scilab / modules / xcos / palette / XcosPaletteManager.java
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2009 - DIGITEO - Antoine ELIAS
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.xcos.palette;
14
15 import java.awt.Component;
16 import java.awt.Dimension;
17 import java.awt.MouseInfo;
18 import java.awt.event.ActionEvent;
19 import java.awt.event.ActionListener;
20 import java.awt.event.MouseEvent;
21 import java.awt.event.MouseListener;
22
23 import javax.swing.ImageIcon;
24 import javax.swing.JMenuItem;
25 import javax.swing.JPopupMenu;
26 import javax.swing.JScrollPane;
27 import javax.swing.JSplitPane;
28 import javax.swing.JTree;
29 import javax.swing.SwingUtilities;
30 import javax.swing.event.TreeSelectionEvent;
31 import javax.swing.event.TreeSelectionListener;
32 import javax.swing.tree.DefaultMutableTreeNode;
33 import javax.swing.tree.DefaultTreeModel;
34 import javax.swing.tree.TreePath;
35 import javax.swing.tree.TreeSelectionModel;
36
37 import org.scilab.modules.gui.bridge.contextmenu.SwingScilabContextMenu;
38 import org.scilab.modules.gui.bridge.tab.SwingScilabTab;
39 import org.scilab.modules.gui.console.ScilabConsole;
40 import org.scilab.modules.gui.contextmenu.ContextMenu;
41 import org.scilab.modules.gui.contextmenu.ScilabContextMenu;
42 import org.scilab.modules.gui.events.callback.CallBack;
43 import org.scilab.modules.gui.menu.Menu;
44 import org.scilab.modules.gui.menu.ScilabMenu;
45 import org.scilab.modules.gui.menubar.MenuBar;
46 import org.scilab.modules.gui.menubar.ScilabMenuBar;
47 import org.scilab.modules.gui.menuitem.MenuItem;
48 import org.scilab.modules.gui.menuitem.ScilabMenuItem;
49 import org.scilab.modules.gui.tab.ScilabTab;
50 import org.scilab.modules.gui.tab.Tab;
51 import org.scilab.modules.gui.textbox.ScilabTextBox;
52 import org.scilab.modules.gui.toolbar.ScilabToolBar;
53 import org.scilab.modules.gui.toolbar.ToolBar;
54 import org.scilab.modules.gui.utils.Size;
55 import org.scilab.modules.gui.window.ScilabWindow;
56 import org.scilab.modules.gui.window.Window;
57 import org.scilab.modules.localization.Messages;
58 import org.scilab.modules.xcos.PaletteDiagram;
59 import org.scilab.modules.xcos.Xcos;
60 import org.scilab.modules.xcos.XcosDiagram;
61 import org.scilab.modules.xcos.actions.ClosePalettesAction;
62 import org.scilab.modules.xcos.actions.LoadAsPalAction;
63 import org.scilab.modules.xcos.block.BasicBlock;
64 import org.scilab.modules.xcos.utils.BlockPositioning;
65 import org.scilab.modules.xcos.utils.XcosComponent;
66 import org.scilab.modules.xcos.utils.XcosMessages;
67
68 import com.mxgraph.model.mxGeometry;
69
70 /**
71  * Manage all the Block Palettes.
72  */
73 public final class XcosPaletteManager {
74
75     private static Thread paletteThread;
76     private static boolean paletteLoadStarted;
77     private static Tab palettes;
78     private static JTree paletteTree = null;
79     private static DefaultMutableTreeNode rootNode = null; 
80     private static DefaultMutableTreeNode userDefinedNode = null; 
81     private static DefaultTreeModel paletteTreeModel = null;
82         /**
83      * Instantiate all the known names (default configuration)
84      */
85     private static final PaletteStringDescriptor[] allPalettesStringDescriptor = {
86             /** COMMONLY USED BLOCKS palette */
87             new PaletteStringDescriptor(XcosMessages.COMMONUSED_PAL,
88                     new String[] { "ANDBLK", "BIGSOM_f", "CMSCOPE", "CONST_m",
89                             "CONVERT", "CSCOPXY", "DEMUX", "DOLLAR_f",
90                             "INTEGRAL_f", "IN_f", "LOGICAL_OP", "MUX",
91                             "NRMSOM_f", "OUT_f", "PRODUCT", "RELATIONALOP",
92                             "SATURATION", "SWITCH2_m", "TEXT_f" }),
93
94             /** CONTINUOUS palette */
95             new PaletteStringDescriptor(XcosMessages.CONTINUOUS_PAL,
96                     new String[] { "CLINDUMMY_f", "CLR", "CLSS", "DERIV",
97                             "INTEGRAL_f", "INTEGRAL_m", "PID", "TCLSS",
98                             "TIME_DELAY", "VARIABLE_DELAY", "PDE" }),
99
100             /** DISCONTINUOUS palette */
101             new PaletteStringDescriptor(XcosMessages.DISCONTINUOUS_PAL,
102                     new String[] { "BACKLASH", "DEADBAND", "DELAYV_f",
103                             "HYSTHERESIS", "RATELIMITER", "QUANT_f",
104                             "SATURATION" }),
105
106             /** DISCRETE palette */
107             new PaletteStringDescriptor(XcosMessages.DISCRETE_PAL,
108                     new String[] { "AUTOMAT", "DELAYV_f", "DELAY_f", "DLR",
109                             "DLRADAPT_f", "DLSS", "DOLLAR_f", "SAMPHOLD_m",
110                             "TCLSS" }),
111
112             /** LOOKUP TABLES palette */
113             new PaletteStringDescriptor(XcosMessages.LOOKUPTABLES_PAL,
114                     new String[] { "INTRP2BLK_f", "INTRPLBLK_f", "LOOKUP_f" }),
115
116             /** EVENTS palette */
117             new PaletteStringDescriptor(XcosMessages.EVENTS_PAL, new String[] {
118                     "ANDBLK", "ANDLOG_f", "CEVENTSCOPE", "CLKFROM", "CLKGOTO",
119                     "CLKGotoTagVisibility", "CLKOUTV_f", "CLKSOMV_f",
120                     "CLOCK_c", "EDGE_TRIGGER", "ENDBLK", "END_c", "ESELECT_f",
121                     "EVTDLY_c", "EVTGEN_f", "EVTVARDLY", "Extract_Activation",
122                     "HALT_f", "IFTHEL_f", "M_freq", "MCLOCK_f", "MFCLCK_f",
123                     "REGISTER", "SampleCLK", "freq_div" }),
124
125             /** MATH OPERATIONS palette */
126             new PaletteStringDescriptor(XcosMessages.MATHSOPS_PAL,
127                     new String[] { "ABS_VALUE", "BIGSOM_f", "COSBLK_f",
128                             "EXPBLK_m", "GAINBLK_f", "INVBLK", "LOGBLK_f",
129                             "MATMAGPHI", "MATZREIM", "MAXMIN", "MAX_f",
130                             "MIN_f", "POWBLK_f", "PRODUCT", "PROD_f", "SIGNUM",
131                             "SINBLK_f", "SQRT", "SUMMATION", "SUM_f",
132                             "TANBLK_f", "TrigFun" }),
133
134             /** MATRIX palette */
135             new PaletteStringDescriptor(XcosMessages.MATRIX_PAL, new String[] {
136                     "CUMSUM", "EXTRACT", "EXTTRI", "MATBKSL", "MATCATH",
137                     "MATCATV", "MATDET", "MATDIAG", "MATDIV", "MATEIG",
138                     "MATEXPM", "MATINV", "MATLU", "MATMAGPHI", "MATMUL",
139                     "MATPINV", "MATRESH", "MATSING", "MATSUM", "MATTRAN",
140                     "MATZCONJ", "MATZREIM", "RICC", "ROOTCOEF", "SQRT",
141                     "SUBMAT" }),
142
143             /** ELECTRICAL palette */
144             new PaletteStringDescriptor(XcosMessages.ELECTRICAL_PAL,
145                     new String[] { "CCS", "CVS", "Capacitor",
146                             "ConstantVoltage", "CurrentSensor", "Diode",
147                             "Ground", "Gyrator", "IdealTransformer",
148                             "Inductor", "NMOS", "NPN", "OpAmp", "PMOS", "PNP",
149                             "PotentialSensor", "Resistor", "SineVoltage",
150                             "Switch", "VVsourceAC", "VariableResistor",
151                             "VoltageSensor", "VsourceAC" }),
152
153             /** INTEGER palette */
154             new PaletteStringDescriptor(XcosMessages.INTEGER_PAL, new String[] {
155                     "BITCLEAR", "BITSET", "CONVERT", "DFLIPFLOP", "DLATCH",
156                     "EXTRACTBITS", "INTMUL", "JKFLIPFLOP", "LOGIC", "SHIFT",
157                     "SRFLIPFLOP" }),
158
159             /** PORT ACTION palette */
160             new PaletteStringDescriptor(XcosMessages.PORTACTION_PAL,
161                     new String[] { "CLKINV_f", "CLKOUTV_f", "IN_f", "INIMPL_f",
162                             "OUTIMPL_f", "OUT_f", "SUPER_f" }),
163
164             /** THRESHOLD palette */
165             new PaletteStringDescriptor(XcosMessages.THRESHOLD_PAL,
166                     new String[] { "GENERAL_f", "NEGTOPOS_f", "POSTONEG_f",
167                             "ZCROSS_f" }),
168
169             /** Signal Routing palette */
170             new PaletteStringDescriptor(XcosMessages.SIGNALROUTING_PAL,
171                     new String[] { "DEMUX", "EXTRACTOR", "FROM", "FROMMO",
172                             "GOTO", "GOTOMO", "GotoTagVisibility",
173                             "GotoTagVisibilityMO", "ISELECT_m", "MUX",
174                             "M_SWITCH", "NRMSOM_f", "RELAY_f", "SELECT_m",
175                             "SWITCH2_m", "SWITCH_f" }),
176
177             /** SIGNAL PROCESSING palette */
178             new PaletteStringDescriptor(XcosMessages.SIGNALPROCESSING_PAL,
179                     new String[] { "QUANT_f", "SAMPHOLD_m" }),
180
181             /** IMPLICIT palette */
182             new PaletteStringDescriptor(XcosMessages.IMPLICIT_PAL,
183                     new String[] { "CONSTRAINT_f", "DIFF_f" }),
184
185             /** ANNOTATIONS palette */
186             new PaletteStringDescriptor(XcosMessages.ANNOTATIONS_PAL,
187                     new String[] { "TEXT_f" }),
188
189             /** SINKS palette */
190             new PaletteStringDescriptor(XcosMessages.SINKS_PAL, new String[] {
191                     "AFFICH_m", "CANIMXY", "CANIMXY3D", "CFSCOPE", "CLKOUTV_f",
192                     "CMAT3D", "CMATVIEW", "CMSCOPE", "CSCOPE", "CSCOPXY",
193                     "CSCOPXY3D", "ENDBLK", "END_c", "HALT_f", "OUTIMPL_f",
194                     "OUT_f", "TOWS_c", "TRASH_f", "WFILE_f", "WRITEAU_f",
195                     "WRITEC_f" }),
196
197             /** SOURCES palette */
198             new PaletteStringDescriptor(XcosMessages.SOURCES_PAL, new String[] {
199                     "CLKINV_f", "CLOCK_c", "CONST_m", "CURV_f", "Counter",
200                     "FROMWSB", "GENSIN_f", "GENSQR_f", "INIMPL_f", "IN_f",
201                     "Modulo_Count", "RAMP", "RAND_m", "READAU_f", "READC_f",
202                     "RFILE_f", "SAWTOOTH_f", "STEP_FUNCTION", "SampleCLK",
203                     "Sigbuilder", "TIME_f", "TKSCALE" }),
204
205             /** THERMO-HYDRAULICS palette */
206             new PaletteStringDescriptor(XcosMessages.THERMOHYDRAULICS_PAL,
207                     new String[] { "Bache", "PerteDP", "PuitsP", "SourceP",
208                             "VanneReglante" }),
209
210             /** DEMO-BLOCKS palette */
211             new PaletteStringDescriptor(XcosMessages.DEMOBLOCKS_PAL,
212                     new String[] { "BOUNCE", "BOUNCEXY", "BPLATFORM" }),
213
214             /** USER-DEFINED FUNCTIONS palette */
215             new PaletteStringDescriptor(XcosMessages.USERDEFINEDFUNCTIONS_PAL,
216                     new String[] { "CBLOCK", "EXPRESSION", "MBLOCK", "PDE",
217                             "SUPER_f", "c_block", "fortran_block",
218                             "generic_block3", "scifunc_block_m" }) };
219
220     /**
221      * Represent a palette configuration values
222      */
223     private static class PaletteStringDescriptor {
224         public String Name;
225         public String[] Components;
226
227         public PaletteStringDescriptor(String name, String[] components) {
228             Name = name;
229             Components = components;
230         }
231     }
232
233     /**
234      * Represent the instanciation of the configurations values
235      */
236     private static class PaletteDescriptor {
237         public String Name;
238         public PaletteData[] Components;
239
240         public PaletteDescriptor(String name, PaletteData[] components) {
241             Name = name;
242             Components = components;
243         }
244
245         public String toString() {
246             return Name;
247         }
248     }
249
250     /**
251      * Represent any block data
252      */
253     private static class PaletteData {
254         public String Name;
255         public ImageIcon Icon;
256
257         /**
258          * Any PaletteBlock data (arguments of the
259          * org.scilab.modules.xcos.palette.XcosPalette#addTemplate)
260          * 
261          * @param name
262          *            The name of the block
263          * @param icon
264          *            The icon of the block
265          * @param block
266          *            Extracted from PATH/BlockName.hf5
267          */
268         public PaletteData(String name, ImageIcon icon) {
269             Name = name;
270             Icon = icon;
271         }
272     }
273
274     /** Palette creation */
275     static {
276         paletteThread = new Thread() {
277             public void run() {
278
279                 final JSplitPane allpalettes = new JSplitPane(
280                         JSplitPane.HORIZONTAL_SPLIT);
281                 final XcosPalette rootPalette = new XcosPalette(
282                         XcosMessages.PALETTES);
283                 rootNode = new DefaultMutableTreeNode(
284                         rootPalette);
285                 paletteTreeModel = new DefaultTreeModel(rootNode);
286                 paletteTree = new JTree(paletteTreeModel);
287                 
288                 allpalettes.setRightComponent(rootPalette);
289                 allpalettes.setLeftComponent(new JScrollPane(paletteTree));
290
291                 paletteTree.getSelectionModel().setSelectionMode(
292                         TreeSelectionModel.SINGLE_TREE_SELECTION);
293                 
294                 paletteTree.addMouseListener(new MouseListener() {
295                     public void mouseReleased(MouseEvent arg0) {
296                     }
297
298                     public void mousePressed(MouseEvent arg0) {
299                     }
300
301                     public void mouseExited(MouseEvent arg0) {
302                     }
303
304                     public void mouseEntered(MouseEvent arg0) {
305                     }
306
307                     public void mouseClicked(MouseEvent arg0) {
308                         if ((arg0.getClickCount() == 1 && SwingUtilities.isRightMouseButton(arg0))
309                                 || arg0.isPopupTrigger()
310                                 || XcosMessages.isMacOsPopupTrigger(arg0)) {
311
312                             final TreePath path = XcosPaletteManager.paletteTree.getPathForLocation(arg0.getX(), arg0.getY());
313                             paletteTree.setSelectionPath(path);
314
315                             ContextMenu menu = ScilabContextMenu.createContextMenu();
316
317                             MenuItem addTo = ScilabMenuItem.createMenuItem();
318
319                             addTo.setText(XcosMessages.REMOVE_USER_DEFINED);
320                             addTo.setCallback(new CallBack(XcosMessages.REMOVE_USER_DEFINED) {
321                                 private static final long serialVersionUID = 2975508442133933904L;
322
323                                 public void callBack() {
324                                     DefaultMutableTreeNode currentNode = (DefaultMutableTreeNode)(path.getLastPathComponent());
325                                     paletteTreeModel.removeNodeFromParent(currentNode);
326                                     if(userDefinedNode != null && userDefinedNode.getChildCount() == 0) {
327                                         paletteTreeModel.removeNodeFromParent(userDefinedNode);
328                                         userDefinedNode = null;
329                                     }
330                                     paletteTree.setSelectionRow(0);
331                                 }
332                             });
333                             
334                                 addTo.setEnabled(false);
335                                 if(((DefaultMutableTreeNode)path.getPath()[1]).getUserObject() instanceof String) {
336                                 if(path.getPath().length > 2) {
337                                     if(((DefaultMutableTreeNode)path.getPath()[2]).getUserObject() instanceof XcosComponent) {
338                                         addTo.setEnabled(true);
339                                     }
340                                 }
341                             }
342
343                             menu.add(addTo);
344                             menu.setVisible(true);
345                             ((SwingScilabContextMenu) menu.getAsSimpleContextMenu()).setLocation(
346                                     MouseInfo.getPointerInfo().getLocation().x, MouseInfo.getPointerInfo().getLocation().y);
347
348                         }
349                     }
350                 });
351                 
352                 paletteTree.addTreeSelectionListener(new TreeSelectionListener() {
353
354                             public void valueChanged(TreeSelectionEvent tree) {
355                                 DefaultMutableTreeNode node = (DefaultMutableTreeNode) paletteTree.getLastSelectedPathComponent();
356
357                                 if (node == null || node.getUserObject() instanceof String) {
358                                     // Nothing is selected.
359                                     //allpalettes.setRightComponent(null);
360                                     return;
361                                 }
362                                 
363                                 //hide previous palette
364                                 Component oldComp = allpalettes.getRightComponent();
365                                 if(oldComp instanceof XcosComponent) {
366                                     XcosComponent comp = (XcosComponent)oldComp;
367                                     comp.setVisible(false);
368                                 }
369
370                                 Dimension size = allpalettes.getLeftComponent().getSize();
371                                 allpalettes.getLeftComponent().setPreferredSize(size);
372                                 JScrollPane nodeInfo = (JScrollPane) node.getUserObject();
373                                 
374                                 
375                                 //update
376                                 allpalettes.setRightComponent(nodeInfo);
377                                 
378                                 //show next palette
379                                 if(nodeInfo instanceof XcosComponent) {
380                                     XcosComponent comp = (XcosComponent)nodeInfo;
381                                     comp.setVisible(true);
382                                 }
383                             }
384
385                         });
386                 
387                 // Add a default Java bloc in HashMap
388                 ((SwingScilabTab) palettes.getAsSimpleTab()).setContentPane(allpalettes);
389
390                 allpalettes.setVisible(false);
391                 palettes.setVisible(true);
392
393                 for (PaletteStringDescriptor paletteStringDescriptor : allPalettesStringDescriptor) {
394                     /* Doesn't perform UI update */
395                     PaletteDescriptor currentDescriptor = new PaletteDescriptor(
396                             paletteStringDescriptor.Name,createPaletteData(paletteStringDescriptor.Components));
397
398                     /* Perform UI update */
399                     XcosPalette xcosPalette = new XcosPalette(
400                             paletteStringDescriptor.Name);
401                     for (PaletteData iter : currentDescriptor.Components) {
402                         xcosPalette.addTemplate(iter.Name, iter.Icon);
403                     }
404                     rootNode.add(new DefaultMutableTreeNode(xcosPalette));
405                 }
406
407                 paletteLoadStarted = true;
408                 palettes.getAsSimpleTab().getInfoBar().setText(XcosMessages.EMPTY_INFO);
409
410                 /* UI Layout specific operations */
411                 paletteTree.expandRow(0);
412                 allpalettes.getLeftComponent().setMinimumSize(paletteTree.getPreferredSize());
413                 paletteTree.setSelectionRow(1);
414                 paletteTree.setRootVisible(false);
415                 allpalettes.setContinuousLayout(true);
416                 allpalettes.setVisible(true);
417             }
418         };
419     }
420
421     private XcosPaletteManager() {
422     }
423
424      public static Tab loadPalette() {
425         synchronized (paletteThread) {
426             paletteThread.notifyAll();
427         }
428         if (paletteLoadStarted == false) {
429             createPaletteWindow();
430             palettes.getAsSimpleTab().getInfoBar().setText(XcosMessages.LOADING_PALETTES);
431             paletteThread.start();
432         }
433         return palettes;
434     }
435
436     private static PaletteData[] createPaletteData(String[] blocksNames) {
437
438         PaletteData[] xcosPalette = new PaletteData[blocksNames.length];
439
440         final String palImagesPath = System.getenv("SCI") + "/modules/xcos/images/palettes/";
441
442         // BasicBlock theBloc = null;
443
444         for (int kBlock = 0; kBlock < blocksNames.length; kBlock++) {
445             xcosPalette[kBlock] = new PaletteData(blocksNames[kBlock],new ImageIcon(palImagesPath + blocksNames[kBlock] + ".jpg"));
446
447         }
448
449         return xcosPalette;
450     }
451
452     public static Tab getPalettes() {
453         return palettes;
454     }
455
456     private static void createPaletteWindow() {
457         paletteLoadStarted = false;
458         // Add a default Java bloc in HashMap
459         // Xcos.getAllBlocks().put("TEXT_f", new TextBlock("TEXT_f"));
460
461         Window palWin = ScilabWindow.createWindow();
462         palWin.setDims(new Size(700, 600));
463         palWin.setVisible(true);
464         palettes = ScilabTab.createTab(XcosMessages.PALETTE_BROWSER);
465
466         palettes.setCallback(new ClosePalettesAction(null));
467
468         /** Create the menubar */
469         MenuBar palMenuBar = ScilabMenuBar.createMenuBar();
470         palettes.addMenuBar(palMenuBar);
471
472         Menu palMenu = ScilabMenu.createMenu();
473         palMenu.setText(XcosMessages.PALETTES);
474         palMenu.setMnemonic('P');
475         palMenuBar.add(palMenu);
476
477         palMenu.add(LoadAsPalAction.createMenu(null));
478         palMenu.addSeparator();
479         palMenu.add(ClosePalettesAction.createMenu(null));
480
481         /** Create the toolbar */
482         ToolBar palToolbar = ScilabToolBar.createToolBar();
483         palettes.addToolBar(palToolbar);
484
485         palToolbar.add(LoadAsPalAction.createButton(null));
486
487         /** Create the infobar */
488         palettes.getAsSimpleTab().setInfoBar(ScilabTextBox.createTextBox());
489
490         palWin.addTab(palettes);
491     }
492
493     public static boolean isVisible() {
494         if (palettes != null && palettes.isVisible() == true) {
495             return true;
496         }
497         return false;
498     }
499
500     public static void loadUserPalette(String newPal) {
501         palettes.getAsSimpleTab().getInfoBar().setText(XcosMessages.LOADING_USER_DEFINE);
502         PaletteDiagram paletteDiagram = new PaletteDiagram();
503         paletteDiagram.installListeners();
504         if(paletteDiagram.openDiagramAsPal(newPal) == true) {
505             if(userDefinedNode == null) {
506                 userDefinedNode = new DefaultMutableTreeNode(XcosMessages.USER_DEFINED);
507                 paletteTreeModel.insertNodeInto(userDefinedNode, rootNode, rootNode.getChildCount());
508             }
509             
510             DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(paletteDiagram.getAsComponent());
511             paletteTreeModel.insertNodeInto(newNode, userDefinedNode, userDefinedNode.getChildCount());
512             paletteDiagram.getAsComponent().setVisible(false);
513             paletteTree.expandRow(rootNode.getIndex(userDefinedNode));
514             paletteTree.setSelectionPath(new TreePath(newNode.getPath()));
515         }
516         palettes.getAsSimpleTab().getInfoBar().setText(XcosMessages.EMPTY_INFO);
517     }
518 }