Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.library / org.gvsig.expressionevaluator / org.gvsig.expressionevaluator.swing / org.gvsig.expressionevaluator.swing.impl / src / main / java / org / gvsig / expressionevaluator / swing / impl / DefaultJExpressionBuilder.java @ 44098

History | View | Annotate | Download (35.1 KB)

1 43939 jjdelcerro
package org.gvsig.expressionevaluator.swing.impl;
2
3 43983 jjdelcerro
import java.awt.BorderLayout;
4 44098 jjdelcerro
import java.awt.Color;
5 43983 jjdelcerro
import java.awt.Dimension;
6 43939 jjdelcerro
import java.awt.event.ActionEvent;
7
import java.awt.event.ActionListener;
8 43987 jjdelcerro
import java.awt.event.KeyAdapter;
9 43983 jjdelcerro
import java.awt.event.KeyEvent;
10 43987 jjdelcerro
import java.awt.event.MouseAdapter;
11
import java.awt.event.MouseEvent;
12 43983 jjdelcerro
import java.net.URL;
13
import java.util.ArrayList;
14
import java.util.Collection;
15 43987 jjdelcerro
import java.util.HashSet;
16 43939 jjdelcerro
import java.util.List;
17 43983 jjdelcerro
import java.util.Objects;
18
import javax.swing.DefaultListCellRenderer;
19
import javax.swing.ImageIcon;
20 43939 jjdelcerro
import javax.swing.JComponent;
21 44006 jjdelcerro
import javax.swing.JEditorPane;
22 43983 jjdelcerro
import javax.swing.JLabel;
23
import javax.swing.JList;
24 43987 jjdelcerro
import javax.swing.JOptionPane;
25 44008 jjdelcerro
import javax.swing.JScrollPane;
26 43983 jjdelcerro
import javax.swing.JTree;
27 43939 jjdelcerro
import javax.swing.SwingUtilities;
28 44098 jjdelcerro
import javax.swing.Timer;
29
import javax.swing.event.CaretEvent;
30
import javax.swing.event.CaretListener;
31
import javax.swing.event.DocumentEvent;
32
import javax.swing.event.DocumentListener;
33 43939 jjdelcerro
import javax.swing.event.ListSelectionEvent;
34
import javax.swing.event.ListSelectionListener;
35 43987 jjdelcerro
import javax.swing.event.TreeModelEvent;
36 43939 jjdelcerro
import javax.swing.event.TreeModelListener;
37
import javax.swing.event.TreeSelectionEvent;
38
import javax.swing.event.TreeSelectionListener;
39 43983 jjdelcerro
import javax.swing.tree.DefaultTreeCellRenderer;
40 43939 jjdelcerro
import javax.swing.tree.TreeModel;
41
import javax.swing.tree.TreePath;
42 43983 jjdelcerro
import org.apache.commons.io.FilenameUtils;
43 43939 jjdelcerro
import org.apache.commons.lang3.StringUtils;
44 43983 jjdelcerro
import org.gvsig.expressionevaluator.Expression;
45
import org.gvsig.expressionevaluator.ExpressionEvaluatorLocator;
46 44098 jjdelcerro
import org.gvsig.expressionevaluator.ExpressionEvaluatorManager;
47
import org.gvsig.expressionevaluator.ExpressionRuntimeException;
48
import org.gvsig.expressionevaluator.ExpressionSyntaxException;
49 43939 jjdelcerro
import org.gvsig.expressionevaluator.Function;
50 44098 jjdelcerro
import org.gvsig.expressionevaluator.MutableSymbolTable;
51 43983 jjdelcerro
import org.gvsig.expressionevaluator.SymbolTable;
52
import org.gvsig.expressionevaluator.swing.Element;
53 44006 jjdelcerro
import org.gvsig.expressionevaluator.swing.Element.CalculatedElement;
54 43983 jjdelcerro
import org.gvsig.expressionevaluator.swing.Element.ConstantElement;
55
import org.gvsig.expressionevaluator.swing.Element.FunctionElement;
56
import org.gvsig.expressionevaluator.swing.Element.GroupElement;
57
import org.gvsig.expressionevaluator.swing.Element.SimpleElement;
58
import org.gvsig.expressionevaluator.swing.Element.VariableElement;
59
import org.gvsig.expressionevaluator.swing.ExpressionBuilderConfig;
60 43939 jjdelcerro
import org.gvsig.expressionevaluator.swing.ExpressionEvaluatorSwingManager;
61
import org.gvsig.expressionevaluator.swing.JExpressionBuilder;
62 43983 jjdelcerro
import org.gvsig.tools.ToolsLocator;
63 44012 jjdelcerro
import org.gvsig.tools.i18n.I18nManager;
64 43983 jjdelcerro
import org.gvsig.tools.script.Script;
65 44006 jjdelcerro
import org.gvsig.tools.swing.api.Component;
66 43939 jjdelcerro
import org.gvsig.tools.swing.api.ListElement;
67
import org.gvsig.tools.swing.api.ToolsSwingLocator;
68
import org.gvsig.tools.swing.api.ToolsSwingManager;
69 43983 jjdelcerro
import org.gvsig.tools.swing.api.pickercontroller.PickerController;
70
import org.gvsig.tools.swing.api.script.ScriptSwingManager;
71 43987 jjdelcerro
import org.gvsig.tools.swing.api.threadsafedialogs.ThreadSafeDialogsManager;
72 43983 jjdelcerro
import org.gvsig.tools.swing.icontheme.IconTheme;
73 43939 jjdelcerro
74
/**
75
 *
76
 * @author jjdelcerro
77
 */
78 44012 jjdelcerro
@SuppressWarnings("UseSpecificCatch")
79 43939 jjdelcerro
public class DefaultJExpressionBuilder
80
        extends DefaultJExpressionBuilderView
81
        implements JExpressionBuilder {
82
83 44098 jjdelcerro
    private static final Color COLOR_ERROR = new Color(255,225,232);
84
85 43939 jjdelcerro
    private final ExpressionEvaluatorSwingManager manager;
86
    private GroupElement currentGroup;
87 43983 jjdelcerro
    private PickerController<List<Script>> scriptPicker;
88
    private ScriptSwingManager.ScriptEditor scriptEditor;
89 43939 jjdelcerro
90 43984 jjdelcerro
    private final ExpressionBuilderConfig config;
91 43987 jjdelcerro
    private ElementsTreeModel treeModel;
92 44006 jjdelcerro
    private java.awt.Component infoPanel = null;
93
    private JEditorPane txtDescription;
94 44098 jjdelcerro
    private Timer timerExpression;
95 44006 jjdelcerro
    private ImageIcon defaultIconGroup;
96
    private ImageIcon defaultIconElement;
97 44008 jjdelcerro
    private JScrollPane scrDescription;
98 44098 jjdelcerro
    private Color color_ok;
99
100 43939 jjdelcerro
    private class ElementsTreeModel implements TreeModel {
101
102 43970 jjdelcerro
        private final GroupElement root;
103 43987 jjdelcerro
        private final HashSet<TreeModelListener> listeners;
104 43983 jjdelcerro
105 43970 jjdelcerro
        public ElementsTreeModel(GroupElement root) {
106 43939 jjdelcerro
            this.root = root;
107 43987 jjdelcerro
            this.listeners = new HashSet<>();
108 43939 jjdelcerro
        }
109 43983 jjdelcerro
110 43939 jjdelcerro
        @Override
111
        public Object getRoot() {
112
            return this.root;
113
        }
114
115 43987 jjdelcerro
        public void reload() {
116
            this.reload(this.root);
117
            this.fireTreeChanged();
118
        }
119
120
        private void reload(Element element) {
121
            if (element instanceof Element) {
122
                if (element instanceof GroupElement) {
123
                    reload(element);
124
                }
125
                element.reload();
126
            }
127
        }
128
129 43970 jjdelcerro
        private List<Element> getChilds(final GroupElement node) {
130 43983 jjdelcerro
            List<Element> x = new ArrayList<>();
131
            for (Element element : node.getElements()) {
132
                if (element instanceof GroupElement) {
133
                    x.add(element);
134
                }
135
            }
136
            return x; //node.getElements();
137 43939 jjdelcerro
        }
138 43983 jjdelcerro
139 43939 jjdelcerro
        @Override
140
        public Object getChild(Object parent, int index) {
141 43983 jjdelcerro
            List<Element> childs = getChilds((GroupElement) parent);
142
            Element child = childs.get(index);
143
            return child;
144 43939 jjdelcerro
        }
145
146
        @Override
147
        public int getChildCount(Object parent) {
148 43983 jjdelcerro
            List<Element> childs = getChilds((GroupElement) parent);
149 43939 jjdelcerro
            return childs.size();
150
        }
151
152
        @Override
153
        public boolean isLeaf(Object node) {
154 43983 jjdelcerro
            if( node instanceof GroupElement ) {
155
                return !((GroupElement) node).hasSubgroups();
156
            }
157
            return false;
158 43939 jjdelcerro
        }
159
160
        @Override
161
        public void valueForPathChanged(TreePath path, Object newValue) {
162
        }
163
164
        @Override
165
        public int getIndexOfChild(Object parent, Object child) {
166 43983 jjdelcerro
            List<Element> childs = getChilds((GroupElement) parent);
167 43939 jjdelcerro
            int n = childs.indexOf(child);
168
            return n;
169
        }
170
171
        @Override
172
        public void addTreeModelListener(TreeModelListener l) {
173 43987 jjdelcerro
            this.listeners.add(l);
174 43939 jjdelcerro
        }
175
176
        @Override
177
        public void removeTreeModelListener(TreeModelListener l) {
178 43987 jjdelcerro
            this.listeners.remove(l);
179 43939 jjdelcerro
        }
180 43983 jjdelcerro
181 43987 jjdelcerro
        protected void fireTreeChanged() {
182
            for (TreeModelListener listener : listeners) {
183
                TreeModelEvent e = new TreeModelEvent(this, new Object[] {this.root});
184
                listener.treeNodesChanged(e);
185
            }
186
        }
187 43939 jjdelcerro
    }
188 43983 jjdelcerro
189 44034 jjdelcerro
    @SuppressWarnings("OverridableMethodCallInConstructor")
190 43983 jjdelcerro
    public DefaultJExpressionBuilder(ExpressionEvaluatorSwingManager manager, ExpressionBuilderConfig config) {
191 43939 jjdelcerro
        this.manager = manager;
192 43989 jjdelcerro
        if( config == null ) {
193
            this.config = new DefaultExpressionBuilderConfig(manager);
194
        } else {
195
            this.config = config;
196
        }
197 43939 jjdelcerro
        this.initComponents();
198
    }
199 43983 jjdelcerro
200
    @Override
201
    public ImageIcon loadImage(String imageName) {
202
        String name = FilenameUtils.getBaseName(imageName);
203
        IconTheme theme = ToolsSwingLocator.getIconThemeManager().getDefault();
204
        if (theme.exists(name)) {
205
            return theme.get(name);
206
        }
207
        URL url = this.getClass().getResource(name + ".png");
208
        if (url == null) {
209
            return null;
210
        }
211
        return new ImageIcon(url);
212
    }
213 43939 jjdelcerro
214
    private void initComponents() {
215
        ToolsSwingManager toolsSwingManager = ToolsSwingLocator.getToolsSwingManager();
216 43983 jjdelcerro
        final IconTheme theme = ToolsSwingLocator.getIconThemeManager().getCurrent();
217 43939 jjdelcerro
218 44098 jjdelcerro
        this.btnTip.setVisible(false);
219
        this.btnTip.addActionListener(new ActionListener() {
220
            @Override
221
            public void actionPerformed(ActionEvent e) {
222
                ThreadSafeDialogsManager dialogs = ToolsSwingLocator.getThreadSafeDialogsManager();
223
                dialogs.messageDialog(
224
                        btnTip.getToolTipText(),
225
                        "Tip",
226
                        JOptionPane.INFORMATION_MESSAGE
227
                );
228
            }
229
        });
230
231 44006 jjdelcerro
        this.defaultIconGroup = theme.get("expressionbuilder-element-group");
232
        this.defaultIconElement = theme.get("expressionbuilder-element");
233
234 44098 jjdelcerro
        this.timerExpression = new Timer(3000, new ActionListener() {
235
            @Override
236
            public void actionPerformed(ActionEvent e) {
237
                doCheckExpression();
238
            }
239
        });
240
        this.timerExpression.setRepeats(false);
241 44006 jjdelcerro
        this.txtDescription = new JEditorPane();
242 44008 jjdelcerro
        this.scrDescription = new JScrollPane(this.txtDescription);
243 44006 jjdelcerro
244 44012 jjdelcerro
        toolsSwingManager.translate(this.tabExpressionBuilder);
245 43939 jjdelcerro
        toolsSwingManager.setDefaultPopupMenu(this.txtExpression);
246
        toolsSwingManager.setDefaultPopupMenu(this.txtGroupElement);
247
        toolsSwingManager.setDefaultPopupMenu(this.txtSimpleElementFilter);
248
        toolsSwingManager.setDefaultPopupMenu(this.txtDescription);
249 43983 jjdelcerro
        toolsSwingManager.addClearButton(this.txtExpression);
250
        toolsSwingManager.addClearButton(this.txtSimpleElementFilter, new ActionListener() {
251
            @Override
252
            public void actionPerformed(ActionEvent e) {
253
                txtSimpleElementFilter.setText("");
254
                doFilter();
255
            }
256
        });
257 44006 jjdelcerro
        this.pnlDescription.setLayout(new BorderLayout());
258
        this.pnlDescription.setBackground(this.txtDescription.getBackground());
259 44098 jjdelcerro
        this.color_ok = this.txtExpression.getBackground();
260
        this.txtExpression.addCaretListener(new CaretListener() {
261
            @Override
262
            public void caretUpdate(CaretEvent e) {
263
                lblColumn.setText(Integer.toString(e.getDot()));
264
            }
265
        });
266
        this.txtExpression.getDocument().addDocumentListener(new DocumentListener() {
267
            @Override
268
            public void insertUpdate(DocumentEvent e) {
269
                timerExpression.restart();
270
            }
271
272
            @Override
273
            public void removeUpdate(DocumentEvent e) {
274
                timerExpression.restart();
275
            }
276
277
            @Override
278
            public void changedUpdate(DocumentEvent e) {
279
                timerExpression.restart();
280
            }
281
        });
282
        this.txtExpression.addKeyListener(new KeyAdapter() {
283
            @Override
284
            public void keyPressed(KeyEvent e) {
285
                   if( e.getKeyCode()==KeyEvent.VK_C && e.isControlDown() ) {
286
                       doCheckExpression();
287
                   }
288
            }
289
        });
290 43983 jjdelcerro
        this.treeElements.setCellRenderer(new DefaultTreeCellRenderer() {
291
            @Override
292 44006 jjdelcerro
            public java.awt.Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
293 43983 jjdelcerro
                JLabel label = (JLabel) super.getTreeCellRendererComponent(tree,value, selected, expanded, leaf, row, hasFocus);
294
                if( value instanceof Element ) {
295
                    Element element = (Element) value;
296 44006 jjdelcerro
                    if( element.getIconName()==null ) {
297
                        if( element instanceof GroupElement ) {
298
                            label.setIcon(defaultIconGroup);
299
                        } else {
300
                            label.setIcon(defaultIconElement);
301
                        }
302
                    } else {
303
                        label.setIcon(element.getIcon());
304
                    }
305 43983 jjdelcerro
                    label.setText(element.getName());
306
                } else {
307
                    label.setIcon(null);
308
                    label.setText(Objects.toString(value, ""));
309
                }
310
                return label;
311
            }
312
        });
313
314 43939 jjdelcerro
        this.treeElements.addTreeSelectionListener(new TreeSelectionListener() {
315
            @Override
316
            public void valueChanged(TreeSelectionEvent e) {
317
                TreePath path = e.getPath();
318
                Element element = (Element) path.getLastPathComponent();
319 43983 jjdelcerro
                if (element instanceof GroupElement) {
320
                    updateSimpleElementsList((GroupElement) element);
321 43939 jjdelcerro
                }
322
            }
323
        });
324 44098 jjdelcerro
        this.treeElements.addMouseListener(new MouseAdapter() {
325
            @Override
326
            public void mouseClicked(MouseEvent e) {
327
                if( e.getButton()==MouseEvent.BUTTON1 && e.getClickCount()==2 ) {
328
                    TreePath path = treeElements.getSelectionPath();
329
                    Element element = (Element) path.getLastPathComponent();
330
                    if( element instanceof SimpleElement ) {
331
                        doInsert((SimpleElement) element);
332
                    }
333
                }
334
            }
335
        });
336 43939 jjdelcerro
        this.btnGroupElementInsert.addActionListener(new ActionListener() {
337
            @Override
338
            public void actionPerformed(ActionEvent e) {
339
                doInsert(txtGroupElement.getText());
340
            }
341
        });
342
        this.btnSimpleElementInsert.addActionListener(new ActionListener() {
343
            @Override
344
            public void actionPerformed(ActionEvent e) {
345 43983 jjdelcerro
                ListElement<SimpleElement> element = (ListElement<SimpleElement>) lstSimpleElement.getSelectedValue();
346
                if (element != null) {
347
                    doInsert(element.getValue());
348
                }
349 43939 jjdelcerro
            }
350
        });
351
        this.btnSimpleElementFilter.addActionListener(new ActionListener() {
352
            @Override
353
            public void actionPerformed(ActionEvent e) {
354
                doFilter();
355
            }
356
        });
357 43989 jjdelcerro
358
        this.lstSimpleElement.setModel(new FilteredListModel());
359 43983 jjdelcerro
        this.lstSimpleElement.setCellRenderer(new DefaultListCellRenderer() {
360
            @Override
361 44006 jjdelcerro
            public java.awt.Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
362 43983 jjdelcerro
                JLabel label = (JLabel)super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
363
                Element element = null;
364
                if( value instanceof ListElement ) {
365
                    if( ((ListElement) value).getValue() instanceof Element ) {
366
                        element = (Element) ((ListElement) value).getValue();
367
                    }
368
                }
369
                if( element !=null ) {
370 44006 jjdelcerro
                    if( element.getIconName()==null ) {
371
                        if( element instanceof GroupElement ) {
372
                            label.setIcon(defaultIconGroup);
373
                        } else {
374
                            label.setIcon(defaultIconElement);
375
                        }
376
                    } else {
377
                        label.setIcon(element.getIcon());
378
                    }
379 43983 jjdelcerro
                    label.setText(element.getName());
380 44098 jjdelcerro
                    label.setEnabled(element.isEnabled());
381 43983 jjdelcerro
                } else {
382
                    label.setIcon(null);
383
                    label.setText(Objects.toString(value, ""));
384
                }
385
                return label;
386
            }
387
        });
388 43939 jjdelcerro
        this.lstSimpleElement.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
389
            @Override
390
            public void valueChanged(ListSelectionEvent e) {
391 43983 jjdelcerro
                ListElement<SimpleElement> element = (ListElement<SimpleElement>) lstSimpleElement.getSelectedValue();
392
                if (element != null) {
393
                    doSelectElement(element.getValue());
394
                }
395 43939 jjdelcerro
            }
396
        });
397 43987 jjdelcerro
        this.lstSimpleElement.addMouseListener(new MouseAdapter() {
398
            @Override
399
            public void mouseClicked(MouseEvent e) {
400
                if( e.getButton()==MouseEvent.BUTTON1 && e.getClickCount()==2 ) {
401
                    ListElement<SimpleElement> element = (ListElement<SimpleElement>) lstSimpleElement.getSelectedValue();
402
                    if (element != null) {
403
                        doSelectElement(element.getValue());
404
                        doInsert(element.getValue());
405
                    }
406
                }
407
            }
408
        });
409
        this.lstSimpleElement.addKeyListener(new KeyAdapter() {
410
            @Override
411
            public void keyReleased(KeyEvent e) {
412
                if( e.getKeyCode()==KeyEvent.VK_ENTER ) {
413
                    ListElement<SimpleElement> element = (ListElement<SimpleElement>) lstSimpleElement.getSelectedValue();
414
                    if (element != null) {
415
                        doSelectElement(element.getValue());
416
                        doInsert(element.getValue());
417
                    }
418
                }
419
            }
420
        });
421 43989 jjdelcerro
422 43987 jjdelcerro
        this.btnSimpleElementTimeLimit.addActionListener(new ActionListener() {
423
            @Override
424
            public void actionPerformed(ActionEvent e) {
425
                doSetTimeLimit();
426
            }
427
        });
428 43939 jjdelcerro
        this.btnSimpleElementSortDown.addActionListener(new ActionListener() {
429
            @Override
430
            public void actionPerformed(ActionEvent e) {
431
                FilteredListModel model = (FilteredListModel) lstSimpleElement.getModel();
432 43983 jjdelcerro
                model.sort(false);
433 43939 jjdelcerro
            }
434
        });
435
        this.btnSimpleElementSortUp.addActionListener(new ActionListener() {
436
            @Override
437
            public void actionPerformed(ActionEvent e) {
438
                FilteredListModel model = (FilteredListModel) lstSimpleElement.getModel();
439 43983 jjdelcerro
                model.sort(true);
440 43939 jjdelcerro
            }
441
        });
442 43987 jjdelcerro
        this.txtSimpleElementFilter.addKeyListener(new KeyAdapter() {
443 43983 jjdelcerro
            @Override
444
            public void keyTyped(KeyEvent e) {
445
                if (e.getKeyChar() == '\n') {
446
                    doFilter();
447
                }
448
            }
449
        });
450
        this.btnAdd.addActionListener(new ActionListener() {
451
            @Override
452
            public void actionPerformed(ActionEvent e) {
453
                doInsert(" + ");
454
            }
455
        });
456
        this.btnDiv.addActionListener(new ActionListener() {
457
            @Override
458
            public void actionPerformed(ActionEvent e) {
459
                doInsert(" / ");
460
            }
461
        });
462
        this.btnEq.addActionListener(new ActionListener() {
463
            @Override
464
            public void actionPerformed(ActionEvent e) {
465
                doInsert(" = ");
466
            }
467
        });
468
        this.btnMult.addActionListener(new ActionListener() {
469
            @Override
470
            public void actionPerformed(ActionEvent e) {
471
                doInsert(" * ");
472
            }
473
        });
474
        this.btnNeq.addActionListener(new ActionListener() {
475
            @Override
476
            public void actionPerformed(ActionEvent e) {
477
                doInsert(" <> ");
478
            }
479
        });
480
        this.btnParentClose.addActionListener(new ActionListener() {
481
            @Override
482
            public void actionPerformed(ActionEvent e) {
483
                doInsert(" ) ");
484
            }
485
        });
486
        this.btnParentOpen.addActionListener(new ActionListener() {
487
            @Override
488
            public void actionPerformed(ActionEvent e) {
489
                doInsert(" ( ");
490
            }
491
        });
492
        this.btnSubst.addActionListener(new ActionListener() {
493
            @Override
494
            public void actionPerformed(ActionEvent e) {
495
                doInsert(" - ");
496
            }
497
        });
498
        ScriptSwingManager scriptSwingManager = ToolsSwingLocator.getScriptSwingManager();
499
        this.scriptPicker = scriptSwingManager.createListScriptPickerController(
500
                cboPickerScripts,
501
                btnPickerRemove,
502
                btnPickerSelectScript
503
        );
504
        this.scriptEditor = scriptSwingManager.createScriptEditor();
505
        this.pnlScriptEditorContainer.setLayout(new BorderLayout());
506
        this.pnlScriptEditorContainer.add(this.scriptEditor.asJComponent(), BorderLayout.CENTER);
507
508 43984 jjdelcerro
        this.tabExpressionBuilder.setEnabledAt(0, this.config.getScriptsEnabled());
509 43987 jjdelcerro
        this.setPreferredSize(new Dimension(650, 350));
510
        this.txtDescription.setPreferredSize(new Dimension(200,200));
511 43939 jjdelcerro
    }
512 43983 jjdelcerro
513 44098 jjdelcerro
    private void doCheckExpression() {
514
        Expression expression = this.getExpression();
515
        this.btnTip.setVisible(false);
516
        if( expression == null ) {
517
            this.lblMsg.setText("");
518
            this.txtExpression.setBackground(this.color_ok);
519
            return;
520
        }
521
        try {
522
            expression.getCode();
523
            this.lblMsg.setText("");
524
            this.txtExpression.setBackground(this.color_ok);
525
        } catch(ExpressionSyntaxException ex) {
526
            this.lblMsg.setText("<html>"+ex.getDescription()+"</html>");
527
            this.txtExpression.setBackground(COLOR_ERROR);
528
            return;
529
        } catch(Exception ex) {
530
            this.lblMsg.setText("Syntax error in expression");
531
            this.txtExpression.setBackground(COLOR_ERROR);
532
            return;
533
        }
534
        if( this.config.getPreviewSymbolTable()==null ) {
535
            try {
536
                ExpressionEvaluatorManager theManager = ExpressionEvaluatorLocator.getManager();
537
                MutableSymbolTable symbolTable = theManager.createSymbolTable();
538
                Object value = expression.execute(symbolTable);
539
                this.lblMsg.setText("<html>"+StringUtils.abbreviate(Utils.toString(value),100)+"</html>");
540
                this.txtExpression.setBackground(this.color_ok);
541
            } catch(Exception ex) {
542
                this.lblMsg.setText("");
543
            }
544
        } else {
545
            try {
546
                Object value = expression.execute(this.config.getPreviewSymbolTable());
547
                this.lblMsg.setText("<html>"+StringUtils.abbreviate(Utils.toString(value),100)+"</html>");
548
                this.txtExpression.setBackground(this.color_ok);
549
            } catch(ExpressionRuntimeException ex) {
550
                if( !StringUtils.isBlank(ex.getTip()) ) {
551
                    this.btnTip.setToolTipText(ex.getTip());
552
                    this.btnTip.setVisible(true);
553
                }
554
                this.lblMsg.setText("<html>Runtime error. "+ex.getMessage()+"</html>");
555
                this.txtExpression.setBackground(COLOR_ERROR);
556
            } catch(Exception ex) {
557
                this.lblMsg.setText("<html>Runtime error. "+ex.getMessage()+"</html>");
558
                this.txtExpression.setBackground(COLOR_ERROR);
559
            }
560
        }
561
    }
562
563 43983 jjdelcerro
    private String removeCursorMark(String s) {
564
        s = s.replace("{{", "");
565
        s = s.replace("}}", "");
566
        return s;
567
    }
568
569 43939 jjdelcerro
    private void doInsert(String s) {
570 43983 jjdelcerro
        this.txtExpression.replaceSelection(s);
571
        String ss = this.txtExpression.getText();
572
        int start = ss.indexOf("{{");
573
        int end = ss.indexOf("}}");
574
        if (start > 0 && end > 0) {
575
            this.txtExpression.replaceRange("", end, end + 2);
576
            this.txtExpression.replaceRange("", start, start + 2);
577
            this.txtExpression.setSelectionStart(start);
578
            this.txtExpression.setSelectionEnd(end - 2);
579
        }
580
        this.txtExpression.requestFocusInWindow();
581 43939 jjdelcerro
    }
582 43983 jjdelcerro
583 43939 jjdelcerro
    private void doInsert(SimpleElement element) {
584 43983 jjdelcerro
        if( element instanceof FunctionElement ) {
585
            Function function = ((FunctionElement)element).getFunction();
586
            if (function == null) {
587
                doInsert(element.getName());
588
            } else {
589
                doInsert(function.template() == null ? function.name() + "({{}})" : function.template());
590
            }
591 44006 jjdelcerro
        } else if( element instanceof CalculatedElement) {
592
            Object value = ((CalculatedElement) element).getValue();
593
            if( value != null ) {
594
                doInsert(" "+value.toString()+" ");
595
            }
596 43983 jjdelcerro
        } else if( element instanceof ConstantElement) {
597 44006 jjdelcerro
            Object value = ((ConstantElement) element).getValue();
598 44098 jjdelcerro
            doInsert(" "+Utils.repr(value)+" ");
599 43939 jjdelcerro
        } else {
600 43983 jjdelcerro
            doInsert(" "+element.getName()+" ");
601 43939 jjdelcerro
        }
602
    }
603 43983 jjdelcerro
604 43939 jjdelcerro
    private void doFilter() {
605
        FilteredListModel model = (FilteredListModel) this.lstSimpleElement.getModel();
606
        model.setFilter(this.txtSimpleElementFilter.getText());
607
    }
608 43983 jjdelcerro
609 43939 jjdelcerro
    private void doSelectElement(SimpleElement element) {
610 44098 jjdelcerro
        if( !element.isEnabled() ) {
611
            this.cleanDescription();
612
            return;
613
        }
614 44012 jjdelcerro
        I18nManager i18n = ToolsLocator.getI18nManager();
615
616 44006 jjdelcerro
        Component aditionalPanel = element.getAditionalPanel();
617 44012 jjdelcerro
        java.awt.Component newInfoPanel;
618 44006 jjdelcerro
        if( aditionalPanel == null ) {
619
            StringBuilder html = new StringBuilder();
620
            html.append("<html>\n");
621
            if( element instanceof ConstantElement ) {
622
                Object value = ((ConstantElement)element).getValue();
623
                if( value == null ) {
624 44012 jjdelcerro
                    html.append("<b>").append(i18n.getTranslation("_Constant")).append("</b><br>\n<br>\n");
625
                    html.append("<b>").append(i18n.getTranslation("_Value")).append("</b> NULL<br>\n");
626 44006 jjdelcerro
                } else {
627 44012 jjdelcerro
                    html.append("<b>").append(i18n.getTranslation("_Constant")).append("</b><br>\n<br>\n");
628 44098 jjdelcerro
                    html.append("<b>").append(i18n.getTranslation("_Value")).append("</b> ").append(Utils.repr(value)).append("<br>\n");
629 44012 jjdelcerro
                    html.append("<b>").append(i18n.getTranslation("_Type")).append("</b> ").append(value.getClass().getSimpleName()).append("<br>\n");
630 44006 jjdelcerro
                }
631 43983 jjdelcerro
632 44006 jjdelcerro
            } else if( element instanceof VariableElement ) {
633
                    VariableElement var = (VariableElement)element;
634
                    html.append("<b>").append(var.getLabel()).append("</b><br>\n<br>\n");
635 44012 jjdelcerro
                    html.append("<b>").append(i18n.getTranslation("_Source")).append("</b> ").append(var.getSource()).append("<br>\n");
636
                    html.append("<b>").append(i18n.getTranslation("_Name")).append("</b> ").append(var.getName()).append("<br>\n");
637
                    html.append("<b>").append(i18n.getTranslation("_Type")).append("</b> ").append(var.getTypeName()).append("<br>\n");
638 44006 jjdelcerro
639
            } else if( element instanceof FunctionElement ) {
640
                Function function = ((FunctionElement)element).getFunction();
641
                if (function == null) {
642 44012 jjdelcerro
                    html.append("<b>").append(i18n.getTranslation("_Function")).append("</b> ").append(element.getName()).append("<br>\n<br>\n");
643
                    html.append("<b>").append(i18n.getTranslation("_Return")).append("</b> Object<br>\n<br>\n");
644
                    html.append("<b>").append(i18n.getTranslation("_Template")).append(":</b> ").append(element.getName()).append("()<br>\n");
645 44006 jjdelcerro
                } else {
646 44012 jjdelcerro
                    html.append("<b>").append(i18n.getTranslation("_Function")).append("</b> ").append(element.getName()).append("<br>\n<br>\n");
647
                    html.append("<b>").append(i18n.getTranslation("_Return")).append("</b> ");
648 44006 jjdelcerro
                    html.append(StringUtils.isEmpty(function.returnType())?"Objec": function.returnType());
649
                    html.append("<br>\n");
650 44012 jjdelcerro
                    html.append("<b>").append(i18n.getTranslation("_Template")).append("</b> ");
651 44006 jjdelcerro
                    html.append(StringUtils.isEmpty(function.template())?element.getName()+"()": removeCursorMark(function.template()));
652
                    html.append("<br>\n");
653
654
                    String[] args = function.descriptionArgs();
655
                    if (args != null) {
656 44012 jjdelcerro
                        html.append("<b>").append(i18n.getTranslation("_Arguments")).append(":</b> ").append("<ul>\n");
657 44006 jjdelcerro
                        for (String arg : args) {
658
                            html.append("<li>").append(arg).append("</li>\n");
659
                        }
660
                        html.append("</ul>\n");
661
                        html.append("<br>\n");
662 43939 jjdelcerro
                    }
663
                }
664 44006 jjdelcerro
            } else {
665 44012 jjdelcerro
                html.append("<b>").append(i18n.getTranslation("_Generic_element")).append("<br>\n<br>\n");
666
                html.append("<b>").append(i18n.getTranslation("_Name")).append("</b> ").append(element.getName()).append("</br>\n");
667 44006 jjdelcerro
668 43983 jjdelcerro
            }
669 44006 jjdelcerro
670
            if( element.getDescription()!=null ) {
671 44012 jjdelcerro
                html.append("<b>").append(i18n.getTranslation("_Description")).append("</b><br>\n");
672 44006 jjdelcerro
                html.append(element.getDescription().replace("\n", "<br>")).append("<br>\n");
673
            }
674
            html.append("</html>\n");
675
            this.txtDescription.setContentType("text/html");
676
            this.txtDescription.setText(html.toString());
677
            this.txtDescription.setCaretPosition(0);
678 44008 jjdelcerro
            newInfoPanel = this.scrDescription;
679 43983 jjdelcerro
        } else {
680 44006 jjdelcerro
            newInfoPanel = aditionalPanel.asJComponent();
681 43939 jjdelcerro
        }
682 44006 jjdelcerro
683
        if( this.infoPanel != newInfoPanel ) {
684
            this.pnlDescription.removeAll();
685
            this.pnlDescription.add(newInfoPanel, BorderLayout.CENTER);
686
            this.pnlDescription.revalidate();
687
            this.pnlDescription.repaint();
688
            this.infoPanel = newInfoPanel;
689 43983 jjdelcerro
        }
690 44006 jjdelcerro
691 43939 jjdelcerro
    }
692 43983 jjdelcerro
693 44098 jjdelcerro
    private void cleanDescription() {
694 43983 jjdelcerro
        this.txtDescription.setText("");
695 44008 jjdelcerro
        if( this.infoPanel != this.scrDescription ) {
696 44006 jjdelcerro
            this.pnlDescription.removeAll();
697 44008 jjdelcerro
            this.pnlDescription.add(this.scrDescription, BorderLayout.CENTER);
698
            this.pnlDescription.revalidate();
699 44006 jjdelcerro
            this.pnlDescription.repaint();
700 44008 jjdelcerro
            this.infoPanel = this.scrDescription;
701 44006 jjdelcerro
        }
702 44098 jjdelcerro
    }
703
704
    private void updateSimpleElementsList(GroupElement group) {
705
        FilteredListModel model = new FilteredListModel();
706
        model.addElement("Loading...");
707
        this.currentGroup = group;
708
        this.txtGroupElement.setText(group.getName());
709
        this.txtSimpleElementFilter.setText("");
710
        this.cleanDescription();
711 43983 jjdelcerro
        if (group instanceof SimpleElement) {
712 43939 jjdelcerro
            this.btnGroupElementInsert.setEnabled(true);
713
        } else {
714
            this.btnGroupElementInsert.setEnabled(false);
715
        }
716
        this.lstSimpleElement.setEnabled(false);
717
        this.lstSimpleElement.setModel(model);
718 43983 jjdelcerro
719 43939 jjdelcerro
        Thread th = new Thread(new Runnable() {
720
            @Override
721
            public void run() {
722
                simpleElementsUpdater();
723
            }
724
        }, "ExpressionBuilderSimpleElementsUpdater");
725
        th.start();
726
    }
727
728
    private void simpleElementsUpdater() {
729
        final GroupElement group = this.currentGroup;
730 43983 jjdelcerro
        final FilteredListModel model = new FilteredListModel();
731 43939 jjdelcerro
        for (Element child : group) {
732 43983 jjdelcerro
            if (group != this.currentGroup) {
733 43939 jjdelcerro
                return;
734
            }
735 43983 jjdelcerro
            if (child instanceof SimpleElement) {
736
                String label = child.getName();
737
                Function function = child instanceof FunctionElement?  ((FunctionElement)child).getFunction(): null;
738
                if (function != null && !StringUtils.isEmpty(function.returnType())) {
739
                    label = "<html><b>" + label + "</b> return " + function.returnType() + "</html>";
740
//                    label = label + " return " + function.returnType();
741 43939 jjdelcerro
                }
742 43983 jjdelcerro
                model.addElement(new ListElement<>(label, child));
743 43939 jjdelcerro
            }
744
        }
745 43983 jjdelcerro
        model.sort(true);
746 43939 jjdelcerro
        SwingUtilities.invokeLater(new Runnable() {
747
            @Override
748
            public void run() {
749 43983 jjdelcerro
                if (group != currentGroup) {
750 43939 jjdelcerro
                    return;
751
                }
752 43983 jjdelcerro
                if( group.hasMoreElements() ) {
753
                    lblSimpleElementsMsg.setText("More elements...");
754
                } else {
755
                    lblSimpleElementsMsg.setText("");
756
                }
757 43939 jjdelcerro
                lstSimpleElement.setEnabled(true);
758
                lstSimpleElement.setModel(model);
759
            }
760
        });
761 43983 jjdelcerro
762 43939 jjdelcerro
    }
763 43983 jjdelcerro
764 43939 jjdelcerro
    @Override
765 43983 jjdelcerro
    public Expression getExpression() {
766
        String phrase = this.txtExpression.getText();
767
        if (StringUtils.isEmpty(phrase)) {
768 43939 jjdelcerro
            return null;
769
        }
770 43983 jjdelcerro
        Expression expression = ExpressionEvaluatorLocator.getManager().createExpression();
771
        expression.setPhrase(phrase);
772
        Script script = ToolsLocator.getScriptManager().createScript("UserScript", "", "python");
773
        this.scriptEditor.fetch(script);
774
        if( !StringUtils.isEmpty(script.getCode()) ) {
775
            expression.setUserScript(script);
776
        }
777 43939 jjdelcerro
        return expression;
778
    }
779
780
    @Override
781 43983 jjdelcerro
    public void setExpression(Expression expression) {
782
        this.txtExpression.setText(expression.getPhrase());
783
        if( expression.getUserScript()!=null ) {
784
            this.scriptEditor.set(expression.getUserScript());
785 43939 jjdelcerro
        }
786 43983 jjdelcerro
        if( expression.getScripts()!=null ) {
787
            this.scriptPicker.set(expression.getScripts().toList());
788
        }
789 43939 jjdelcerro
    }
790
791
    @Override
792 43983 jjdelcerro
    public int getSimpleElementsLimit() {
793
        return this.config.getSimpleElementsLimit();
794
    }
795
796
    @Override
797
    public void setSimpleElementsLimit(int limit) {
798
        this.config.setSimpleElementsLimit(limit);
799
    }
800
801
    @Override
802
    public List<Element> getElements() {
803
        return this.config.getElements();
804
    }
805 44034 jjdelcerro
806 43983 jjdelcerro
    @Override
807 44034 jjdelcerro
    public void addElement(Element element) {
808
        this.config.addElement(element);
809
    }
810
811
    @Override
812 43983 jjdelcerro
    public Collection<SymbolTable> getSymbolTables() {
813
        return this.config.getSymbolTables();
814
    }
815
816
    @Override
817 43987 jjdelcerro
    public void addSymbolTable(String name) {
818
        this.config.addSymbolTable(name);
819
    }
820
821
    @Override
822 43983 jjdelcerro
    public void addSymbolTable(SymbolTable symbolTable) {
823
        this.config.addSymbolTable(symbolTable);
824
    }
825
826
    @Override
827
    public void removeAllSymbolTables() {
828
        this.config.removeAllSymbolTables();
829
    }
830
831 43984 jjdelcerro
    @Override
832
    public void removeSymbolTable(String name) {
833
        this.config.removeSymbolTable(name);
834
    }
835
836
    @Override
837 44098 jjdelcerro
    public SymbolTable getPreviewSymbolTable() {
838
        return this.config.getPreviewSymbolTable();
839
    }
840
841
    @Override
842
    public void setPreviewSymbolTable(SymbolTable symbolTable) {
843
        this.config.setPreviewSymbolTable(symbolTable);
844
    }
845
846
    @Override
847 43984 jjdelcerro
    public void setScriptsEnabled(boolean enabled) {
848
        this.config.setScriptsEnabled(enabled);
849
        this.tabExpressionBuilder.setEnabledAt(0, this.config.getScriptsEnabled());
850
    }
851
852
    @Override
853
    public boolean getScriptsEnabled() {
854
        return this.config.getScriptsEnabled();
855
    }
856 43983 jjdelcerro
857
    @Override
858 43939 jjdelcerro
    public JComponent asJComponent() {
859 43987 jjdelcerro
        if( this.treeModel == null ) {
860 44012 jjdelcerro
            I18nManager i18n = ToolsLocator.getI18nManager();
861 43987 jjdelcerro
            this.treeModel = new ElementsTreeModel(
862 44012 jjdelcerro
                    this.manager.createGroupElement(
863
                            i18n.getTranslation("_Elements"),
864
                            this.getElements()
865
                    )
866 43987 jjdelcerro
            );
867
            this.treeElements.setModel(this.treeModel);
868
        }
869 43939 jjdelcerro
        return this;
870
    }
871
872 43987 jjdelcerro
    private void doSetTimeLimit() {
873
        ThreadSafeDialogsManager dialogs = ToolsSwingLocator.getThreadSafeDialogsManager();
874
        String s = dialogs.inputDialog(
875
                "Indicate the time limit in seconds for calculating the elements",
876
                "Time limit",
877
                JOptionPane.QUESTION_MESSAGE,
878
                String.valueOf(this.config.getSimpleElementsLimit())
879
        );
880
        if( StringUtils.isBlank(s) ) {
881
            return;
882
        }
883
        try {
884
            int n = Integer.parseInt(s);
885
            this.config.setSimpleElementsLimit(n);
886
            this.treeModel.reload();
887
        } catch(Exception ex) {
888
            dialogs.messageDialog(
889
                "Invalid time limit '"+s+"'.",
890
                "Time limit",
891
                JOptionPane.WARNING_MESSAGE
892
            );
893
        }
894
    }
895 43983 jjdelcerro
}