Bug #8761 fixed: Xcos masked superblocks had invalid names
[scilab.git] / scilab / modules / xcos / src / java / org / scilab / modules / xcos / block / actions / SuperblockMaskCustomizeAction.java
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2009 - DIGITEO - Vincent COUVERT
4  * Copyright (C) 2009 - DIGITEO - Clement DAVID
5  * Copyright (C) 2011-2015 - Scilab Enterprises - Clement DAVID
6  *
7  * Copyright (C) 2012 - 2016 - Scilab Enterprises
8  *
9  * This file is hereby licensed under the terms of the GNU GPL v2.0,
10  * pursuant to article 5.3.4 of the CeCILL v.2.1.
11  * This file was originally licensed under the terms of the CeCILL v2.1,
12  * and continues to be available under such terms.
13  * For more information, see the COPYING file which you should have received
14  * along with this program.
15  *
16  */
17
18 package org.scilab.modules.xcos.block.actions;
19
20 import java.awt.event.ActionEvent;
21 import java.awt.event.ActionListener;
22 import java.util.Arrays;
23 import java.util.Iterator;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.Set;
27 import java.util.logging.Level;
28 import java.util.logging.Logger;
29
30 import javax.swing.BorderFactory;
31 import javax.swing.DefaultCellEditor;
32 import javax.swing.ImageIcon;
33 import javax.swing.JComboBox;
34 import javax.swing.JFrame;
35 import javax.swing.WindowConstants;
36 import javax.swing.event.ChangeEvent;
37 import javax.swing.event.ChangeListener;
38 import javax.swing.event.ListSelectionEvent;
39 import javax.swing.event.ListSelectionListener;
40 import javax.swing.event.TableModelEvent;
41 import javax.swing.event.TableModelListener;
42 import javax.swing.table.DefaultTableModel;
43 import javax.swing.table.TableColumn;
44
45 import org.scilab.modules.commons.gui.FindIconHelper;
46 import org.scilab.modules.graph.ScilabComponent;
47 import org.scilab.modules.graph.ScilabGraph;
48 import org.scilab.modules.graph.actions.base.DefaultAction;
49 import org.scilab.modules.gui.menuitem.MenuItem;
50 import org.scilab.modules.types.ScilabDouble;
51 import org.scilab.modules.types.ScilabList;
52 import org.scilab.modules.types.ScilabString;
53 import org.scilab.modules.types.ScilabType;
54 import org.scilab.modules.xcos.JavaController;
55 import org.scilab.modules.xcos.ObjectProperties;
56 import org.scilab.modules.xcos.VectorOfDouble;
57 import org.scilab.modules.xcos.block.SuperBlock;
58 import org.scilab.modules.xcos.graph.XcosDiagram;
59 import org.scilab.modules.xcos.io.ScilabTypeCoder;
60 import org.scilab.modules.xcos.utils.XcosMessages;
61
62 /**
63  * Customize the mask of the {@link SuperBlock}.
64  */
65 @SuppressWarnings(value = { "serial" })
66 public final class SuperblockMaskCustomizeAction extends DefaultAction {
67     /** Name of the action */
68     public static final String NAME = XcosMessages.CUSTOMIZE;
69     /** Icon name of the action */
70     public static final String SMALL_ICON = "";
71     /** Mnemonic key of the action */
72     public static final int MNEMONIC_KEY = 0;
73     /** Accelerator key for the action */
74     public static final int ACCELERATOR_KEY = 0;
75
76     private static final String TERMINATE_EDIT_ON_FOCUS_LOST = "terminateEditOnFocusLost";
77
78     /**
79      * Private constructor
80      *
81      * @param scilabGraph
82      *            the associated graph
83      */
84     public SuperblockMaskCustomizeAction(ScilabGraph scilabGraph) {
85         super(scilabGraph);
86     }
87
88     /**
89      * Create the menu associated with this action
90      *
91      * @param scilabGraph
92      *            the associated graph
93      * @return the newly created menu
94      */
95     public static MenuItem createMenu(ScilabGraph scilabGraph) {
96         return createMenu(scilabGraph, SuperblockMaskCustomizeAction.class);
97     }
98
99     /**
100      * Function to be performed by this action.
101      *
102      * @param e
103      *            The associated event
104      */
105     @Override
106     public void actionPerformed(ActionEvent e) {
107         final XcosDiagram graph = (XcosDiagram) getGraph(e);
108
109         // action disabled when the cell is edited
110         final ScilabComponent comp = ((ScilabComponent) graph.getAsComponent());
111         if (comp.isEditing()) {
112             return;
113         }
114
115         SuperBlock block = (SuperBlock) graph.getSelectionCell();
116
117         CustomizeFrame frame = new CustomizeFrame(graph);
118         CustomizeFrame.CustomizeFrameModel model = frame.getController().getModel();
119         model.setBlock(block);
120         model.importFromBlock();
121         frame.setVisible(true);
122     }
123
124     /**
125      * Frame used to customize fields and variables default values. DAC: this
126      * class is tightly coupled to Swing
127      */
128     // CSOFF: ClassDataAbstractionCoupling
129     @SuppressWarnings(value = { "serial" })
130     private static class CustomizeFrame extends JFrame {
131
132         private final CustomizeFrameControler controler;
133
134         private javax.swing.JPanel buttonBlob;
135         private javax.swing.JButton cancelButton;
136         private javax.swing.JPanel customizeMainPanel;
137         private javax.swing.JScrollPane customizeScrollPane;
138         private javax.swing.JTabbedPane tabbedPane;
139         private javax.swing.JTable defaultValueTable;
140         private javax.swing.JPanel defaultValues;
141         private javax.swing.JScrollPane defaultValuesScrollPane;
142         private javax.swing.JButton delete;
143         private javax.swing.JButton insert;
144         private javax.swing.JPanel mainPanel;
145         private javax.swing.JButton moveDown;
146         private javax.swing.JButton moveUp;
147         private javax.swing.JButton okButton;
148         private javax.swing.JLabel rowLabel;
149         private javax.swing.JPanel rowManagement;
150         private javax.swing.JSpinner rowSpinner;
151         private javax.swing.JPanel tableManagement;
152         private javax.swing.JPanel validationPanel;
153         private javax.swing.JTable varCustomizeTable;
154         private javax.swing.JPanel varSettings;
155
156         /**
157          * Constructor
158          *
159          * @param diagram
160          *            the container diagram
161          */
162         public CustomizeFrame(XcosDiagram diagram) {
163             setTitle(XcosMessages.MASK_TITLE);
164             setDefaultCloseOperation(WindowConstants.HIDE_ON_CLOSE);
165             ImageIcon scilabIcon = new ImageIcon(FindIconHelper.findIcon("scilab"));
166             setIconImage(scilabIcon.getImage());
167             controler = new CustomizeFrameControler(diagram);
168             initComponents();
169         }
170
171         /**
172          * @return The associated controller
173          */
174         public CustomizeFrameControler getController() {
175             return controler;
176         }
177
178         /**
179          * Construct the UI and install the listeners.
180          */
181         // CSOFF: JavaNCSS
182         // CSOFF: MagicNumber
183         private void initComponents() {
184
185             /* Construct the components */
186             mainPanel = new javax.swing.JPanel();
187             tabbedPane = new javax.swing.JTabbedPane();
188             varSettings = new javax.swing.JPanel();
189             customizeMainPanel = new javax.swing.JPanel();
190             customizeScrollPane = new javax.swing.JScrollPane();
191             varCustomizeTable = new javax.swing.JTable();
192             tableManagement = new javax.swing.JPanel();
193             insert = new javax.swing.JButton();
194             delete = new javax.swing.JButton();
195             buttonBlob = new javax.swing.JPanel();
196             moveUp = new javax.swing.JButton();
197             moveDown = new javax.swing.JButton();
198             rowManagement = new javax.swing.JPanel();
199             rowLabel = new javax.swing.JLabel();
200             rowSpinner = new javax.swing.JSpinner();
201             defaultValues = new javax.swing.JPanel();
202             defaultValuesScrollPane = new javax.swing.JScrollPane();
203             defaultValueTable = new javax.swing.JTable();
204             validationPanel = new javax.swing.JPanel();
205             okButton = new javax.swing.JButton();
206             cancelButton = new javax.swing.JButton();
207
208             setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
209
210             /* Initialize the components */
211             mainPanel.setLayout(new java.awt.BorderLayout());
212             mainPanel.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
213
214             varSettings.setLayout(new javax.swing.BoxLayout(varSettings, javax.swing.BoxLayout.PAGE_AXIS));
215
216             varCustomizeTable.setModel(controler.getModel().customizeTableModel);
217             varCustomizeTable.putClientProperty(TERMINATE_EDIT_ON_FOCUS_LOST, Boolean.TRUE);
218             customizeScrollPane.setViewportView(varCustomizeTable);
219             // setAutoCreateRowSorter is java 1.6
220             // varCustomizeTable.setAutoCreateRowSorter(true);
221
222             /* Update the default value table */
223             varCustomizeTable.getModel().addTableModelListener(controler.updateValuesTable);
224
225             /*
226              * Activate and deactivate insertion/deletion sensible
227              * buttons/spinner
228              */
229             varCustomizeTable.getModel().addTableModelListener(controler.updateButtonsSensibleForModifications);
230
231             /* Activate and deactivate selection sensible buttons */
232             varCustomizeTable.getSelectionModel().addListSelectionListener(controler.updateButtonsSensibleForSelectionChange);
233
234             customizeMainPanel.add(customizeScrollPane);
235
236             tableManagement.setBorder(javax.swing.BorderFactory.createEmptyBorder(2, 2, 2, 2));
237             tableManagement.setLayout(new java.awt.GridLayout(5, 1));
238
239             /* Install the insert action */
240             insert.setMnemonic('n');
241             insert.setText(XcosMessages.MASK_INSERT);
242             tableManagement.add(insert);
243             insert.addActionListener(controler.insertActionListener);
244
245             /* Install the delete action */
246             delete.setMnemonic('l');
247             delete.setText(XcosMessages.MASK_DELETE);
248             tableManagement.add(delete);
249             delete.addActionListener(controler.deleteActionListener);
250
251             /* Install empty area */
252             tableManagement.add(buttonBlob);
253
254             /* Install the move-up action */
255             moveUp.setMnemonic('u');
256             moveUp.setText(XcosMessages.MASK_MOVEUP);
257             tableManagement.add(moveUp);
258             moveUp.addActionListener(controler.moveUpActionListener);
259
260             /* Install the move-down action */
261             moveDown.setMnemonic('w');
262             moveDown.setText(XcosMessages.MASK_MOVEDOWN);
263             tableManagement.add(moveDown);
264             moveDown.addActionListener(controler.moveDownActionListener);
265
266             /* add the table management */
267             customizeMainPanel.add(tableManagement);
268
269             varSettings.add(customizeMainPanel);
270
271             rowLabel.setText(XcosMessages.MASK_ROWS + " :");
272             rowManagement.add(rowLabel);
273
274             rowSpinner.setModel(new javax.swing.SpinnerNumberModel(1, 1, Integer.MAX_VALUE, 1));
275             rowSpinner.setEditor(new javax.swing.JSpinner.NumberEditor(rowSpinner, "######0"));
276             rowSpinner.setValue(varCustomizeTable.getModel().getRowCount());
277             rowManagement.add(rowSpinner);
278             rowSpinner.addChangeListener(controler.rowSpinnerChangeListener);
279
280             varSettings.add(rowManagement);
281
282             tabbedPane.addTab(XcosMessages.MASK_VARSETTINGS, varSettings);
283
284             defaultValueTable.setModel(controler.getModel().valuesTableModel);
285             defaultValueTable.putClientProperty(TERMINATE_EDIT_ON_FOCUS_LOST, Boolean.TRUE);
286             defaultValuesScrollPane.setViewportView(defaultValueTable);
287
288             // setAutoCreateRowSorter is java 1.6
289             // defaultValueTable.setAutoCreateRowSorter(false);
290
291             defaultValues.add(defaultValuesScrollPane);
292
293             tabbedPane.addTab(XcosMessages.MASK_DEFAULTVALUES, defaultValues);
294
295             mainPanel.add(tabbedPane, java.awt.BorderLayout.CENTER);
296
297             okButton.setText(XcosMessages.OK);
298             validationPanel.add(okButton);
299             okButton.addActionListener(controler.okActionListener);
300
301             cancelButton.setText(XcosMessages.CANCEL);
302             validationPanel.add(cancelButton);
303             cancelButton.addActionListener(controler.cancelActionListener);
304
305             mainPanel.add(validationPanel, java.awt.BorderLayout.PAGE_END);
306
307             add(mainPanel);
308
309             pack();
310             cancelButton.requestFocusInWindow();
311
312             /* Evaluate the context and set up the variable name selection */
313             TableColumn vars = varCustomizeTable.getColumnModel().getColumn(0);
314             JComboBox validVars = new JComboBox();
315             final Set<String> keys = controler.context.keySet();
316             for (String key : keys) {
317                 validVars.addItem(key);
318             }
319             vars.setCellEditor(new DefaultCellEditor(validVars));
320
321             insert.setEnabled(validVars.getModel().getSize() != 0);
322         }
323
324         // CSON: JavaNCSS
325         // CSON: MagicNumber
326
327         /**
328          * Implements the models used on the frame.
329          */
330         private class CustomizeFrameModel {
331             private SuperBlock block;
332
333             /**
334              * Model used on the customize table.
335              */
336             private final DefaultTableModel customizeTableModel = new DefaultTableModel(new Object[][] { new Object[] { XcosMessages.MASK_WINTITLEVAR,
337                         XcosMessages.MASK_WINTITLE, false
338                                                                                                                           }
339             }, new String[] { XcosMessages.MASK_VARNAME, XcosMessages.MASK_VARDESC, XcosMessages.MASK_EDITABLE }) {
340                 private final Class<?>[] types = new Class[] { java.lang.String.class, java.lang.String.class, java.lang.Boolean.class };
341                 private final boolean[] canEdit = new boolean[] { true, true, true };
342
343                 @Override
344                 public Class<?> getColumnClass(int columnIndex) {
345                     return types[columnIndex];
346                 }
347
348                 @Override
349                 public boolean isCellEditable(int rowIndex, int columnIndex) {
350                     if (rowIndex != 0) {
351                         return canEdit[columnIndex];
352                     }
353                     return false;
354                 }
355             };
356
357             /**
358              * Model used for the values table
359              */
360             private final DefaultTableModel valuesTableModel = new javax.swing.table.DefaultTableModel(new Object[][] { new Object[] {
361                     XcosMessages.MASK_WINTITLE, ""
362                 }
363             }, new String[] { XcosMessages.MASK_VARDESC, XcosMessages.MASK_VARVALUES }) {
364                 private final Class<?>[] types = new Class[] { java.lang.String.class, java.lang.String.class };
365                 private final boolean[] canEdit = new boolean[] { false, true };
366
367                 @Override
368                 public Class<?> getColumnClass(int columnIndex) {
369                     return types[columnIndex];
370                 }
371
372                 @Override
373                 public boolean isCellEditable(int rowIndex, int columnIndex) {
374                     return canEdit[columnIndex];
375                 }
376             };
377
378             /**
379              * Default constructor
380              */
381             protected CustomizeFrameModel() {
382                 // Does nothing as the fields are final.
383             }
384
385             /**
386              * @param block
387              *            This model associated block.
388              */
389             public void setBlock(SuperBlock block) {
390                 this.block = block;
391             }
392
393             /**
394              * @return This model associated block.
395              */
396             public SuperBlock getBlock() {
397                 return block;
398             }
399
400             /**
401              * Export the table models to the block exprs.
402              */
403             public void exportToBlock() {
404                 /** Data vectors are typed when parsing */
405                 final List<?> customModel = customizeTableModel.getDataVector();
406                 final List<?> valuesModel = valuesTableModel.getDataVector();
407
408                 /* We have one content that is not a variable : Window Title */
409                 final int nbOfVar = valuesModel.size() - 1;
410
411                 final String[][] values = new String[nbOfVar][1];
412                 final String[][] varNames = new String[nbOfVar][1];
413                 final String[][] varDesc = new String[nbOfVar + 1][1];
414                 final ScilabList polFields = new ScilabList();
415
416                 /* Title */
417                 varDesc[0][0] = (String) ((List<?>) valuesModel.get(0)).get(1);
418
419                 /* Other fields */
420                 for (int i = 0; i < nbOfVar; i++) {
421                     values[i][0] = (String) ((List<?>) valuesModel.get(i + 1)).get(1);
422                     varNames[i][0] = (String) ((List<?>) customModel.get(i + 1)).get(0);
423                     varDesc[i + 1][0] = (String) ((List<?>) customModel.get(i + 1)).get(1);
424
425                     /*
426                      * reconstruct pol fields. The default types of the values.
427                      *
428                      * This field indicate the dimension of each entry (-1.0 is
429                      * automatic). TODO: type the data there instead of using
430                      * the generic "pol".
431                      */
432                     polFields.add(new ScilabString("pol"));
433                     polFields.add(new ScilabDouble(-1.0));
434                 }
435
436                 /* Construct fields from data */
437                 final ScilabList exprs;
438                 if (nbOfVar == 0) {
439                     /* Set default values */
440                     exprs = new ScilabList(Arrays.asList(
441                                                new ScilabDouble(),
442                                                new ScilabList(Arrays.asList(new ScilabDouble(), new ScilabString(XcosMessages.MASK_DEFAULTWINDOWNAME),
443                                                        new ScilabList(Arrays.asList(new ScilabDouble()))))));
444                 } else {
445                     /* set the values */
446                     exprs = new ScilabList(Arrays.asList(new ScilabString(values),
447                                                          new ScilabList(Arrays.asList(new ScilabString(varNames), new ScilabString(varDesc), polFields))));
448                 }
449
450                 JavaController controller = new JavaController();
451                 VectorOfDouble vec = new ScilabTypeCoder().var2vec(exprs);
452                 controller.setObjectProperty(block.getUID(), block.getKind(), ObjectProperties.EXPRS, vec);
453
454                 /*
455                  * Trace the exprs update.
456                  */
457                 if (Logger.getLogger(SuperblockMaskCustomizeAction.class.getName()).isLoggable(Level.FINEST)) {
458                     Logger.getLogger(SuperblockMaskCustomizeAction.class.getName()).finest("exprs=" + exprs);
459                 }
460             }
461
462             /**
463              * Import the model exprs to the table models.
464              */
465             public void importFromBlock() {
466                 ScilabString values;
467                 ScilabString varNames;
468                 ScilabString varDesc;
469
470                 JavaController controller = new JavaController();
471                 VectorOfDouble vec = new VectorOfDouble();
472                 controller.getObjectProperty(block.getUID(), block.getKind(), ObjectProperties.EXPRS, vec);
473                 ScilabType rawExprs = new ScilabTypeCoder().vec2var(vec);
474
475                 // Xcos from Scilab 5.2.0 version
476                 // so set default values
477                 if (rawExprs instanceof ScilabDouble) {
478                     rawExprs = new ScilabList(Arrays.asList(
479                                                   new ScilabDouble(),
480                                                   new ScilabList(Arrays.asList(new ScilabDouble(), new ScilabString(XcosMessages.MASK_DEFAULTWINDOWNAME),
481                                                           new ScilabList(Arrays.asList(new ScilabDouble()))))));
482                 }
483                 DefaultTableModel customModel = customizeTableModel;
484                 DefaultTableModel valuesModel = valuesTableModel;
485
486                 /*
487                  * rawExprs have to be typed as
488                  * list([],list([],"Set block parameters",list())) or as
489                  * list([""],list([""],"Set block parameters",list([""])))
490                  */
491                 assert rawExprs instanceof ScilabList;
492                 ScilabList exprs = (ScilabList) rawExprs;
493
494                 assert (exprs.get(0) instanceof ScilabDouble) || (exprs.get(0) instanceof ScilabString);
495                 if (exprs.get(0) instanceof ScilabDouble) {
496                     values = new ScilabString("");
497                 } else { /* exprs.get(0) instanceof ScilabString) */
498                     values = (ScilabString) exprs.get(0);
499                 }
500
501                 assert exprs.get(1) instanceof ScilabList;
502                 ScilabList lvalues = (ScilabList) exprs.get(1);
503
504                 assert (lvalues.get(0) instanceof ScilabDouble) || (lvalues.get(0) instanceof ScilabString);
505                 if (lvalues.get(0) instanceof ScilabDouble) {
506                     varNames = new ScilabString();
507                 } else { /* exprs.get(0) instanceof ScilabString) */
508                     varNames = (ScilabString) lvalues.get(0);
509                 }
510
511                 assert lvalues.get(1) instanceof ScilabString;
512                 varDesc = (ScilabString) lvalues.get(1);
513
514                 /*
515                  * Check if the data are stored as columns or as row.
516                  */
517                 if (varDesc.getHeight() >= varDesc.getWidth()) {
518
519                     /* Title */
520                     valuesModel.setValueAt(varDesc.getData()[0][0], 0, 1);
521
522                     /* Loop all over the data */
523                     for (int i = 1; i < varDesc.getHeight(); i++) {
524                         customModel.addRow(new Object[] { varNames.getData()[i - 1][0], varDesc.getData()[i][0], true });
525                         valuesModel.setValueAt(values.getData()[i - 1][0], i, 1);
526                     }
527                 } else {
528                     /* Title */
529                     valuesModel.setValueAt(varDesc.getData()[0][0], 0, 1);
530
531                     /* Loop all over the data */
532                     for (int i = 1; i < varDesc.getHeight(); i++) {
533                         customModel.addRow(new Object[] { varNames.getData()[0][i - 1], varDesc.getData()[0][i], true });
534                         valuesModel.setValueAt(values.getData()[0][i - 1], i, 1);
535                     }
536                 }
537             }
538         }
539
540         /**
541          * Implement the action listeners for the frame
542          */
543         private class CustomizeFrameControler {
544             private final CustomizeFrameModel model;
545
546             private final ActionListener cancelActionListener = new ActionListener() {
547                 @Override
548                 public void actionPerformed(ActionEvent e) {
549                     dispose();
550                 }
551             };
552
553             private final ActionListener okActionListener = new ActionListener() {
554                 @Override
555                 public void actionPerformed(ActionEvent arg0) {
556                     model.exportToBlock();
557                     dispose();
558                 }
559             };
560
561             private final ChangeListener rowSpinnerChangeListener = new ChangeListener() {
562                 @Override
563                 public void stateChanged(ChangeEvent e) {
564                     int rowCount = varCustomizeTable.getRowCount();
565                     int value = (Integer) rowSpinner.getModel().getValue();
566
567                     for (; rowCount < value; rowCount++) {
568                         insertActionListener.actionPerformed(new ActionEvent(this, -1, ACTION_COMMAND_KEY));
569                     }
570
571                     for (; rowCount > value; rowCount--) {
572                         deleteActionListener.actionPerformed(new ActionEvent(this, -1, ACTION_COMMAND_KEY));
573                     }
574                 }
575             };
576
577             private final ActionListener moveDownActionListener = new ActionListener() {
578                 @Override
579                 public void actionPerformed(ActionEvent arg0) {
580                     int selectedRow = varCustomizeTable.getSelectedRow();
581
582                     swapTableRow(model.customizeTableModel, selectedRow, selectedRow + 1);
583                     swapTableRow(model.valuesTableModel, selectedRow, selectedRow + 1);
584
585                     /* Keep the same row selected */
586                     varCustomizeTable.changeSelection(selectedRow + 1, varCustomizeTable.getSelectedColumn(), false, false);
587                 }
588             };
589
590             private final ActionListener moveUpActionListener = new ActionListener() {
591                 @Override
592                 public void actionPerformed(ActionEvent arg0) {
593                     int selectedRow = varCustomizeTable.getSelectedRow();
594
595                     swapTableRow(model.customizeTableModel, selectedRow, selectedRow - 1);
596                     swapTableRow(model.valuesTableModel, selectedRow, selectedRow - 1);
597
598                     /* Keep the same row selected */
599                     varCustomizeTable.changeSelection(selectedRow - 1, varCustomizeTable.getSelectedColumn(), false, false);
600                 }
601             };
602
603             private final ActionListener deleteActionListener = new ActionListener() {
604                 @Override
605                 public void actionPerformed(ActionEvent e) {
606                     int selected = varCustomizeTable.getSelectedRow();
607                     int nbOfRows = varCustomizeTable.getRowCount();
608
609                     if (selected > 1) {
610                         model.customizeTableModel.removeRow(selected);
611                         varCustomizeTable.changeSelection(selected - 1, 1, false, false);
612                     } else if (nbOfRows > 1) {
613                         model.customizeTableModel.removeRow(nbOfRows - 1);
614                         varCustomizeTable.changeSelection(nbOfRows - 2, 1, false, false);
615                     }
616                 }
617             };
618
619             private final ActionListener insertActionListener = new ActionListener() {
620                 @Override
621                 public void actionPerformed(ActionEvent e) {
622                     final String nextKey;
623                     if (keyIterator.hasNext()) {
624                         nextKey = keyIterator.next();
625                     } else {
626                         // at the end of the iteration loop again
627                         keyIterator = context.keySet().iterator();
628
629                         if (keyIterator.hasNext()) {
630                             nextKey = keyIterator.next();
631                         } else {
632                             nextKey = ""; // no defined vars.
633                         }
634                     }
635
636                     model.customizeTableModel.addRow(new Object[] { nextKey, nextKey, true });
637                     varCustomizeTable.changeSelection(model.customizeTableModel.getRowCount() - 1, 1, false, false);
638                 }
639             };
640
641             /**
642              * Update the buttons on selection change.
643              */
644             private final ListSelectionListener updateButtonsSensibleForSelectionChange = new ListSelectionListener() {
645                 @Override
646                 public void valueChanged(ListSelectionEvent e) {
647                     /* We cannot move up anymore */
648                     final boolean isFirst;
649                     /* We cannot move down anymore */
650                     final boolean isLast;
651                     /* The second row is selected */
652                     final boolean isSecond;
653
654                     int selectedRow = varCustomizeTable.getSelectedRow();
655                     int rowCount = varCustomizeTable.getRowCount();
656
657                     isFirst = selectedRow < 1;
658                     isSecond = selectedRow == 1;
659                     isLast = selectedRow == rowCount - 1;
660
661                     moveUp.setEnabled(!isFirst && !isSecond);
662                     moveDown.setEnabled(!isFirst && !isLast);
663
664                     delete.setEnabled(!isFirst);
665                 }
666             };
667
668             /**
669              * Update the buttons/spinner on modifications
670              */
671             private final TableModelListener updateButtonsSensibleForModifications = new TableModelListener() {
672                 @Override
673                 public void tableChanged(TableModelEvent e) {
674                     int rowCount = model.customizeTableModel.getRowCount();
675                     rowSpinner.setValue(rowCount);
676                 }
677             };
678
679             /**
680              * Update the values table on change on the customize table.
681              */
682             private final TableModelListener updateValuesTable = new TableModelListener() {
683                 @Override
684                 public void tableChanged(TableModelEvent e) {
685                     final DefaultTableModel valuesModel = model.valuesTableModel;
686                     final DefaultTableModel customModel = model.customizeTableModel;
687                     int row = e.getFirstRow();
688                     int column = e.getColumn();
689
690                     switch (e.getType()) {
691                         case TableModelEvent.INSERT:
692                             String key = (String) customModel.getValueAt(row, 0);
693                             String value = context.get(key).toString();
694                             valuesModel.addRow(new Object[] { key, value });
695                             break;
696
697                         case TableModelEvent.DELETE:
698                             valuesModel.removeRow(row);
699                             break;
700
701                         case TableModelEvent.UPDATE:
702                             if (column == 0) {
703                                 // update the description when it was set to a var
704                                 // name and the variable change
705                                 // the description should not change when it is not
706                                 // the default.
707                                 String varName = (String) customModel.getValueAt(row, 0);
708                                 String varDesc = (String) customModel.getValueAt(row, 1);
709                                 if (context.containsKey(varDesc)) {
710                                     customModel.setValueAt(varName, row, 1);
711                                 }
712                             } else if (column == 1) {
713                                 // update the description on the default value table
714                                 valuesModel.setValueAt(customModel.getValueAt(row, 1), row, 0);
715                             }
716                             break;
717
718                         default:
719                             break;
720                     }
721                 }
722             };
723
724             private final Map<String, ScilabType> context;
725             private Iterator<String> keyIterator;
726
727             /**
728              * Cstr
729              *
730              * @param diagram
731              *            the calling diagram
732              */
733             public CustomizeFrameControler(XcosDiagram diagram) {
734                 model = new CustomizeFrameModel();
735                 context = diagram.evaluateContext();
736                 keyIterator = context.keySet().iterator();
737             }
738
739             /**
740              * @return the model
741              */
742             public CustomizeFrameModel getModel() {
743                 return model;
744             }
745
746             /**
747              * Swap two table rows
748              *
749              * @param model
750              *            the model
751              * @param row1
752              *            the first row
753              * @param row2
754              *            th second row
755              */
756             private void swapTableRow(DefaultTableModel model, int row1, int row2) {
757                 /*
758                  * doesn't need to be checked as the operation doesn't depend on
759                  * it
760                  */
761                 @SuppressWarnings("unchecked")
762                 final List < List<? >> data = model.getDataVector();
763
764                 /* Inverting data */
765                 List<?> tmp = data.get(row2);
766                 data.set(row2, data.get(row1));
767                 data.set(row1, tmp);
768             }
769         }
770     }
771     // CSON: ClassDataAbstractionCoupling
772 }