Xcos: add "shift ENTER" as Context validator
[scilab.git] / scilab / modules / xcos / src / java / org / scilab / modules / xcos / actions / dialog / SetContextDialog.java
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2010 - DIGITEO - Clement DAVID
4  * Copyright (C) 2015 - Scilab Enterprises - Clement DAVID
5  *
6  * Copyright (C) 2012 - 2016 - Scilab Enterprises
7  *
8  * This file is hereby licensed under the terms of the GNU GPL v2.0,
9  * pursuant to article 5.3.4 of the CeCILL v.2.1.
10  * This file was originally licensed under the terms of the CeCILL v2.1,
11  * and continues to be available under such terms.
12  * For more information, see the COPYING file which you should have received
13  * along with this program.
14  *
15  */
16
17 package org.scilab.modules.xcos.actions.dialog;
18
19 import java.awt.Component;
20 import java.awt.Dimension;
21 import java.awt.GridBagConstraints;
22 import java.awt.GridBagLayout;
23 import java.awt.Image;
24 import java.awt.Insets;
25 import java.awt.event.ActionEvent;
26 import java.awt.event.ActionListener;
27 import java.awt.event.KeyEvent;
28 import java.beans.PropertyVetoException;
29 import java.io.File;
30 import java.io.FileWriter;
31 import java.io.IOException;
32 import java.io.OutputStreamWriter;
33 import java.io.Writer;
34 import java.io.FileOutputStream;
35 import java.util.logging.Logger;
36 import javax.swing.AbstractAction;
37
38 import javax.swing.BorderFactory;
39 import javax.swing.Box;
40 import javax.swing.BoxLayout;
41 import javax.swing.ImageIcon;
42 import javax.swing.JButton;
43 import javax.swing.JDialog;
44 import javax.swing.JLabel;
45 import javax.swing.JPanel;
46 import javax.swing.JScrollPane;
47 import javax.swing.JTextArea;
48 import javax.swing.KeyStroke;
49 import javax.swing.ScrollPaneConstants;
50 import org.scilab.modules.action_binding.highlevel.ScilabInterpreterManagement;
51
52 import org.scilab.modules.commons.gui.FindIconHelper;
53 import org.scilab.modules.gui.utils.ScilabSwingUtilities;
54 import org.scilab.modules.xcos.JavaController;
55 import org.scilab.modules.xcos.VectorOfString;
56 import org.scilab.modules.xcos.actions.SetContextAction;
57 import org.scilab.modules.xcos.graph.ScicosParameters;
58 import org.scilab.modules.xcos.graph.XcosDiagram;
59 import org.scilab.modules.xcos.io.scicos.ScilabDirectHandler;
60 import org.scilab.modules.xcos.utils.XcosMessages;
61
62 /**
63  * Dialog associated with the {@link SetContextAction}.
64  *
65  * Note that this dialog break the Data Abstraction Coupling metric because of
66  * the numbers of graphical components involved in the GUI creation. For the
67  * same reason (GUI class), constants are not used on this code.
68  */
69 // CSOFF: ClassDataAbstractionCoupling
70 // CSOFF: ClassFanOutComplexity
71 // CSOFF: MagicNumber
72 @SuppressWarnings(value = { "serial" })
73 public class SetContextDialog extends JDialog {
74     private static final Dimension PREFERRED_SIZE = new Dimension(480, 320);
75     private static final String SHARED_NEW_LINE = "\n";
76
77     private final ScicosParameters parameters;
78     private final XcosDiagram rootGraph;
79
80     private JTextArea contextArea;
81
82     /**
83      * Default constructor
84      *
85      * @param parent
86      *            the parent component
87      * @param graph
88      *            THe current graph
89      * @param parameters
90      *            the Scicos parameters
91      */
92     public SetContextDialog(Component parent, XcosDiagram graph, ScicosParameters parameters) {
93         this.parameters = parameters;
94
95         ImageIcon scilabIcon = new ImageIcon(FindIconHelper.findIcon("scilab"));
96         Image imageForIcon = scilabIcon.getImage();
97         setLayout(new GridBagLayout());
98         setIconImage(imageForIcon);
99         setTitle(XcosMessages.SET_CONTEXT);
100         setModal(true);
101         setLocationRelativeTo(parent);
102         rootGraph = graph;
103         setDefaultCloseOperation(DISPOSE_ON_CLOSE);
104         ScilabSwingUtilities.closeOnEscape(this);
105
106         initComponents();
107     }
108
109     /**
110      * Initialize the components
111      */
112     private void initComponents() {
113         JLabel textLabel = new JLabel(XcosMessages.SET_CONTEXT_LABEL_TEXT);
114         contextArea = new JTextArea();
115
116         /*
117          * Construct a text from a String array context
118          */
119         VectorOfString v = parameters.getContext(new JavaController());
120         final int len = v.size();
121         for (int i = 0; i < len; i++) {
122             contextArea.append(v.get(i) + SHARED_NEW_LINE);
123         }
124
125         JScrollPane contextAreaScroll = new JScrollPane(contextArea, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
126                 ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
127
128         JButton cancelButton = new JButton(XcosMessages.CANCEL);
129         JButton okButton = new JButton(XcosMessages.OK);
130         okButton.setMnemonic(KeyEvent.VK_ENTER);
131         okButton.setPreferredSize(cancelButton.getPreferredSize());
132
133         JPanel buttonPane = new JPanel();
134         buttonPane.setLayout(new BoxLayout(buttonPane, BoxLayout.LINE_AXIS));
135         buttonPane.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10));
136         buttonPane.add(okButton);
137         buttonPane.add(Box.createRigidArea(new Dimension(10, 0)));
138         buttonPane.add(cancelButton);
139
140         /*
141          * Perform layout
142          */
143         GridBagConstraints gbc = new GridBagConstraints();
144
145         gbc.gridwidth = GridBagConstraints.REMAINDER;
146         gbc.gridx = 0;
147         gbc.gridy = 1;
148         gbc.fill = GridBagConstraints.BOTH;
149         gbc.weightx = 1.0;
150         gbc.insets = new Insets(10, 10, 10, 10);
151
152         add(textLabel, gbc);
153
154         gbc.gridy = GridBagConstraints.RELATIVE;
155         gbc.fill = GridBagConstraints.BOTH;
156         gbc.weighty = 1.0;
157         add(contextAreaScroll, gbc);
158
159         gbc.gridheight = 1;
160         gbc.gridwidth = 1;
161
162         gbc.anchor = GridBagConstraints.LAST_LINE_END;
163         gbc.fill = GridBagConstraints.NONE;
164         gbc.weighty = 0;
165         gbc.insets = new Insets(5, 0, 10, 10);
166         add(buttonPane, gbc);
167
168         installActionListeners(cancelButton, okButton);
169
170         setPreferredSize(PREFERRED_SIZE);
171     }
172
173     /**
174      * Install the action listener on the buttons
175      *
176      * @param cancelButton
177      *            the cancel button
178      * @param okButton
179      *            the OK button
180      */
181     private void installActionListeners(JButton cancelButton, JButton okButton) {
182         /*
183          * The cancel button just exit without doing anything
184          */
185         cancelButton.addActionListener((ActionEvent e) -> {
186             dispose();
187         });
188
189         /*
190          * The ok button parse the contextArea, reconstruct the real context and
191          * set the scicosParameters before exiting.
192          */
193         
194         ActionImpl action = new ActionImpl();
195         
196         okButton.setAction(action);
197         KeyStroke shiftEnter = KeyStroke.getKeyStroke("shift ENTER");
198         contextArea.getInputMap().put(shiftEnter, "OK");
199         contextArea.getActionMap().put("OK", action);
200         
201     }
202
203     private class ActionImpl extends AbstractAction implements ActionListener {
204
205         public ActionImpl() {
206             super(XcosMessages.OK);
207         }
208         
209         @Override
210         public void actionPerformed(ActionEvent e) {
211             try {
212                 String context = contextArea.getText();
213                 final VectorOfString v = new VectorOfString();
214
215                 // Force a carriage return if needed so the last line is not ignored
216                 if (context.length() > 0 && !context.endsWith("\n")) {
217                     context += '\n';
218                 }
219                 int off = 0;
220                 int next;
221                 while ((next = context.indexOf('\n', off)) != -1) {
222                     v.add(context.substring(off, next));
223                     off = next + 1;
224                 }
225                 parameters.setContext(new JavaController(), v);
226
227                 /*
228                  * Validate the context
229                  */
230                 try {
231                     File f = File.createTempFile(ScilabDirectHandler.CONTEXT, ".sce");
232                     try (Writer writer =  new OutputStreamWriter(new FileOutputStream(f), "UTF-8")) {
233                         writer.write(context, 0, context.length());
234                     }
235
236                     ScilabInterpreterManagement.putCommandInScilabQueue("var = script2var(mgetl(\"" + f.getAbsolutePath() + "\"), struct()); mdelete(\"" + f.getAbsolutePath() + "\");");
237                 } catch (IOException ex) {
238                     Logger.getLogger(SetContextAction.class.getName()).severe(ex.toString());
239                 }
240
241                 dispose();
242             } catch (PropertyVetoException e2) {
243                 Logger.getLogger(SetContextAction.class.getName()).severe(e2.toString());
244             }
245         }
246     }
247 }
248 // CSON: ClassDataAbstractionCoupling
249 // CSON: ClassFanOutComplexity
250 // CSON: MagicNumber