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 @ 44216

History | View | Annotate | Download (34.6 KB)

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