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

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