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

History | View | Annotate | Download (36 KB)

1
package org.gvsig.expressionevaluator.swing.impl;
2

    
3
import java.awt.BorderLayout;
4
import java.awt.Dimension;
5
import java.awt.Toolkit;
6
import java.awt.datatransfer.Clipboard;
7
import java.awt.datatransfer.StringSelection;
8
import java.awt.event.ActionEvent;
9
import java.awt.event.ActionListener;
10
import java.awt.event.KeyAdapter;
11
import java.awt.event.KeyEvent;
12
import java.awt.event.MouseAdapter;
13
import java.awt.event.MouseEvent;
14
import java.io.InputStream;
15
import java.net.URL;
16
import java.util.ArrayList;
17
import java.util.Collection;
18
import java.util.HashSet;
19
import java.util.List;
20
import java.util.Locale;
21
import java.util.Map;
22
import java.util.Objects;
23
import javax.swing.DefaultListCellRenderer;
24
import javax.swing.ImageIcon;
25
import javax.swing.JComponent;
26
import javax.swing.JEditorPane;
27
import javax.swing.JLabel;
28
import javax.swing.JList;
29
import javax.swing.JMenuItem;
30
import javax.swing.JOptionPane;
31
import javax.swing.JPanel;
32
import javax.swing.JPopupMenu;
33
import javax.swing.JScrollPane;
34
import javax.swing.JTabbedPane;
35
import javax.swing.JTree;
36
import javax.swing.SwingUtilities;
37
import javax.swing.event.CaretEvent;
38
import javax.swing.event.CaretListener;
39
import javax.swing.event.ListSelectionEvent;
40
import javax.swing.event.ListSelectionListener;
41
import javax.swing.event.TreeModelEvent;
42
import javax.swing.event.TreeModelListener;
43
import javax.swing.event.TreeSelectionEvent;
44
import javax.swing.event.TreeSelectionListener;
45
import javax.swing.tree.DefaultTreeCellRenderer;
46
import javax.swing.tree.TreeModel;
47
import javax.swing.tree.TreePath;
48
import org.apache.commons.io.FilenameUtils;
49
import org.apache.commons.io.IOUtils;
50
import org.apache.commons.lang3.StringUtils;
51
import org.gvsig.configurableactions.ConfigurableActionsMamager;
52
import org.gvsig.expressionevaluator.Expression;
53
import org.gvsig.expressionevaluator.ExpressionEvaluatorLocator;
54
import org.gvsig.expressionevaluator.ExpressionEvaluatorManager;
55
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
import org.gvsig.expressionevaluator.swing.ExpressionEvaluatorSwingManager;
61
import org.gvsig.expressionevaluator.swing.JExpressionBuilder;
62
import org.gvsig.tools.ToolsLocator;
63
import org.gvsig.tools.i18n.I18nManager;
64
import org.gvsig.tools.script.Script;
65
import org.gvsig.tools.swing.api.Component;
66
import org.gvsig.tools.swing.api.ToolsSwingLocator;
67
import org.gvsig.tools.swing.api.ToolsSwingManager;
68
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
import org.gvsig.tools.swing.api.pickercontroller.PickerController;
74
import org.gvsig.tools.swing.api.script.ScriptSwingManager;
75
import org.gvsig.tools.swing.api.threadsafedialogs.ThreadSafeDialogsManager;
76
import org.gvsig.tools.swing.icontheme.IconTheme;
77
import org.gvsig.tools.util.ToolsUtilLocator;
78

    
79
/**
80
 *
81
 * @author jjdelcerro
82
 */
83
@SuppressWarnings("UseSpecificCatch")
84
public class DefaultJExpressionBuilder
85
        extends DefaultJExpressionBuilderView2
86
        implements JExpressionBuilder {
87

    
88
    private final ExpressionEvaluatorSwingManager manager;
89
    private Element currentElement;
90
    private PickerController<List<Script>> scriptPicker;
91
    private ScriptSwingManager.ScriptEditor scriptEditor;
92
    
93
    private final ExpressionBuilderConfig builderConfig;
94
    private ElementsTreeModel treeModel;
95
    private ImageIcon defaultIconGroup;
96
    private ImageIcon defaultIconElement;
97
    private InfoPanel infoPanel;
98
    private AbstractAutomaticExpressionChecker automaticExpressionChecker;
99
    private HistoryController<Expression> historyController;
100
    private BookmarksController<Expression> bookmarksController;
101

    
102
    private static class InfoPanel implements Component {
103

    
104
        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
        
112
        private final String defautltDescription;
113

    
114
        private String description; 
115
        private Component additionalPanel;
116
        
117
        public InfoPanel(JPanel pnlContainer, String defautltDescription) {
118
            ToolsSwingManager toolsSwingManager = ToolsSwingLocator.getToolsSwingManager();
119
            I18nManager i18n = ToolsLocator.getI18nManager();
120
            
121
            this.defautltDescription = defautltDescription;
122
            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
                    // la descripcion por defecto.
157
                    this.txtDescription.setText(this.defautltDescription);
158
                    this.txtDescription.setCaretPosition(0);
159
                    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
    private class ElementsTreeModel implements TreeModel {
193

    
194
        private final GroupElement root;
195
        private final HashSet<TreeModelListener> listeners;
196

    
197
        public ElementsTreeModel(GroupElement root) {
198
            this.root = root;
199
            this.listeners = new HashSet<>();
200
        }
201

    
202
        @Override
203
        public Object getRoot() {
204
            return this.root;
205
        }
206

    
207
        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
//                if (element instanceof GroupElement) {
215
                    reload(element);
216
//                }
217
                element.reload();
218
            }
219
        }
220
        
221
        private List<Element> getChilds(final GroupElement node) {
222
            List<Element> x = new ArrayList<>();
223
            for (Element element : node.getElements()) {
224
//                if (element instanceof GroupElement) {
225
                    x.add(element);
226
//                }
227
            }
228
            return x; //node.getElements();
229
        }
230

    
231
        @Override
232
        public Object getChild(Object parent, int index) {
233
            List<Element> childs = getChilds((GroupElement) parent);
234
            Element child = childs.get(index);
235
            return child;
236
        }
237

    
238
        @Override
239
        public int getChildCount(Object parent) {
240
            List<Element> childs = getChilds((GroupElement) parent);
241
            return childs.size();
242
        }
243

    
244
        @Override
245
        public boolean isLeaf(Object node) {
246
            return !(node instanceof GroupElement);
247
        }
248

    
249
        @Override
250
        public void valueForPathChanged(TreePath path, Object newValue) {
251
        }
252

    
253
        @Override
254
        public int getIndexOfChild(Object parent, Object child) {
255
            List<Element> childs = getChilds((GroupElement) parent);
256
            int n = childs.indexOf(child);
257
            return n;
258
        }
259

    
260
        @Override
261
        public void addTreeModelListener(TreeModelListener l) {
262
            this.listeners.add(l);
263
        }
264

    
265
        @Override
266
        public void removeTreeModelListener(TreeModelListener l) {
267
            this.listeners.remove(l);
268
        }
269

    
270
        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
    }
277
  
278
    @SuppressWarnings("OverridableMethodCallInConstructor")
279
    public DefaultJExpressionBuilder(ExpressionEvaluatorSwingManager manager, ExpressionBuilderConfig config) {
280
        this.manager = manager;
281
        if( config == null ) {
282
            this.builderConfig = new DefaultExpressionBuilderConfig(manager);
283
        } else {
284
            this.builderConfig = config;
285
        }
286
        this.initComponents();
287
    }
288
    
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

    
303
    @SuppressWarnings("Convert2Lambda")
304
    private void initComponents() {
305
        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
        final ToolsSwingManager toolsSwingManager = ToolsSwingLocator.getToolsSwingManager();
311
        final IconTheme theme = ToolsSwingLocator.getIconThemeManager().getCurrent();
312
        final I18nManager i18n = ToolsLocator.getI18nManager();
313
        
314
        this.automaticExpressionChecker = new AbstractAutomaticExpressionChecker(
315
                builderConfig, txtExpression
316
            ) {
317
            @Override
318
            protected Expression getExpression() {
319
                return DefaultJExpressionBuilder.this.getExpressionWithOutHistory();
320
            }
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
        this.infoPanel = new InfoPanel(this.pnlDescription, load_description_from_resource());
343
        
344
        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
        this.defaultIconGroup = theme.get("expressionbuilder-element-group");
358
        this.defaultIconElement = theme.get("expressionbuilder-element");
359
        
360
        toolsSwingManager.translate(this.tabExpressionBuilder);
361
        toolsSwingManager.setDefaultPopupMenu(this.txtGroupElement);
362
        toolsSwingManager.setDefaultPopupMenu(this.txtSimpleElementFilter);
363
        toolsSwingManager.addClearButton(this.txtSimpleElementFilter, new ActionListener() {
364
            @Override
365
            public void actionPerformed(ActionEvent e) {
366
                txtSimpleElementFilter.setText("");
367
                doFilter();
368
            }
369
        });
370
        JMenuItem msgMenuTextEditor = new JMenuItem(i18n.getTranslation("text_editor"));
371
        msgMenuTextEditor.addActionListener(new ActionListener() {
372
            @Override
373
            public void actionPerformed(ActionEvent e) {
374
                automaticExpressionChecker.showMessageDialog();
375
            }
376
        });
377
        JMenuItem msgMenuCopy = new JMenuItem(i18n.getTranslation("copy"));
378
        msgMenuTextEditor.addActionListener(new ActionListener() {
379
            @Override
380
            public void actionPerformed(ActionEvent e) {
381
                StringSelection selection = new StringSelection(automaticExpressionChecker.getMessage());
382
                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
        this.pnlDescription.setLayout(new BorderLayout());
394
        this.txtExpression.addCaretListener(new CaretListener() {
395
            @Override
396
            public void caretUpdate(CaretEvent e) {
397
                lblColumn.setText(Integer.toString(e.getDot()));
398
            }
399
        });
400
        this.treeElements.setRowHeight(0);
401
        this.treeElements.setCellRenderer(new DefaultTreeCellRenderer() {
402
            @Override
403
            public java.awt.Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
404
                JLabel component = (JLabel) super.getTreeCellRendererComponent(tree,value, selected, expanded, leaf, row, hasFocus);
405
                JLabel text = component;
406
                JLabel icon = component;
407
                
408
                if( value instanceof Element ) {
409
                    Element element = (Element) value;
410
                    if( element.getIconName()==null ) {
411
                        if( element instanceof GroupElement ) {
412
                            icon.setIcon(defaultIconGroup);
413
                        } else {
414
                            icon.setIcon(defaultIconElement);
415
                        }
416
                    } else {
417
                        icon.setIcon(element.getIcon());
418
                    }
419
                    text.setText(element.getLabel());
420
                    text.setEnabled(element.isEnabled());
421
                } else {
422
                    icon.setIcon(null);
423
                    text.setText(Objects.toString(value, ""));
424
                }
425
                return component;
426
            }
427
        });
428
        
429
        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
                doSelectElement(element);
435
                updateSimpleElementsList(element);
436
            }
437
        });
438
        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
                    if( path!=null ) {
444
                        Element element = (Element) path.getLastPathComponent();
445
                        if( element instanceof SimpleElement ) {
446
                            doInsert((SimpleElement) element);
447
                        }
448
                    }
449
                }
450
            }
451
        });
452
        this.btnGroupElementInsert.addActionListener(new ActionListener() {
453
            @Override
454
            public void actionPerformed(ActionEvent e) {
455
                if( currentElement!=null ) {
456
                    doInsert(currentElement.getRenderedValue());
457
                } else {
458
                    doInsert(txtGroupElement.getText());
459
                }
460
            }
461
        });
462
        this.btnSimpleElementInsert.addActionListener(new ActionListener() {
463
            @Override
464
            public void actionPerformed(ActionEvent e) {
465
                Element element = (Element) lstSimpleElement.getSelectedValue();
466
                if (element != null) {
467
                    doInsert(element);
468
                }
469
            }
470
        });
471
        this.btnSimpleElementFilter.addActionListener(new ActionListener() {
472
            @Override
473
            public void actionPerformed(ActionEvent e) {
474
                doFilter();
475
            }
476
        });
477
        
478
        this.lstSimpleElement.setModel(new FilteredListModel());
479
        this.lstSimpleElement.setCellRenderer(new DefaultListCellRenderer() {
480
            @Override
481
            public java.awt.Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
482
                JLabel label = (JLabel)super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
483
                if( value instanceof Element ) {
484
                    Element element = (Element) value;
485
                    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
                    label.setText(element.getLabel());
495
                    label.setEnabled(element.isEnabled());
496
                } else {
497
                    label.setIcon(null);
498
                    label.setText(Objects.toString(value, ""));
499
                }
500
                return label;
501
            }
502
        });
503
        this.lstSimpleElement.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
504
            @Override
505
            public void valueChanged(ListSelectionEvent e) {
506
                Element element = (Element) lstSimpleElement.getSelectedValue();
507
                if (element != null) {
508
                    doSelectElement(element);
509
                }
510
            }
511
        });
512
        this.lstSimpleElement.addMouseListener(new MouseAdapter() {
513
            @Override
514
            public void mouseClicked(MouseEvent e) {
515
                if( e.getButton()==MouseEvent.BUTTON1 && e.getClickCount()==2 ) {
516
                    Element element = (Element) lstSimpleElement.getSelectedValue();
517
                    if (element != null) {
518
                        doSelectElement(element);
519
                        doInsert(element);
520
                    }
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
                    Element element = (Element) lstSimpleElement.getSelectedValue();
529
                    if (element != null) {
530
                        doSelectElement(element);
531
                        doInsert(element);
532
                    }
533
                }
534
            }
535
        });
536

    
537
        this.btnSimpleElementTimeLimit.addActionListener(new ActionListener() {
538
            @Override
539
            public void actionPerformed(ActionEvent e) {
540
                doSetTimeLimit();
541
            }
542
        });
543
        this.btnSimpleElementSortDown.addActionListener(new ActionListener() {
544
            @Override
545
            public void actionPerformed(ActionEvent e) {
546
                FilteredListModel model = (FilteredListModel) lstSimpleElement.getModel();
547
                model.sort(false);
548
            }
549
        });
550
        this.btnSimpleElementSortUp.addActionListener(new ActionListener() {
551
            @Override
552
            public void actionPerformed(ActionEvent e) {
553
                FilteredListModel model = (FilteredListModel) lstSimpleElement.getModel();
554
                model.sort(true);
555
            }
556
        });
557
        this.txtSimpleElementFilter.addKeyListener(new KeyAdapter() {
558
            @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
//        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
        
625
        ActionListener historyAndBookmarkListener = new ActionListener() {
626
            @Override
627
            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
            }
638
        };
639
        this.historyController = toolsSwingManager.createHistoryController(
640
                ExpressionEvaluatorLocator.getManager().getHistory(), 
641
                btnHistory
642
        );
643
        this.historyController.addActionListener(historyAndBookmarkListener);
644
        
645
        this.bookmarksController = toolsSwingManager.createBookmarksController(
646
                ExpressionEvaluatorLocator.getManager().getBookmarks(), 
647
                btnBookmarks
648
        );
649
        this.bookmarksController.addActionListener(historyAndBookmarkListener);        
650
        
651
        this.infoPanel.repaint();
652
        
653
        this.setPreferredSize(new Dimension(750, 450));
654
        
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
    }
661

    
662
    private String removeCursorMark(String s) {
663
        if( s == null ) {
664
            return null;
665
        }
666
        s = s.replace("{{", "");
667
        s = s.replace("}}", "");
668
        return s;
669
    }
670

    
671
    @Override
672
    public void insertText(String text) {
673
        doInsert(text);
674
    }
675

    
676
    @Override
677
    public String getText() {
678
        return this.txtExpression.getText();
679
    }
680
    
681
    @Override
682
    public void setText(String text) {
683
        this.txtExpression.setText(text);
684
    }
685
    
686
    private void doInsert(String s) {
687
        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
    }
699

    
700
    private void doInsert(Element element) {
701
        doInsert(element.getRenderedValue());
702
        element.used();
703
    }
704

    
705
    private void doFilter() {
706
        FilteredListModel model = (FilteredListModel) this.lstSimpleElement.getModel();
707
        model.setFilter(this.txtSimpleElementFilter.getText());
708
    }
709

    
710
    private void doSelectElement(Element element) {
711
//        if( !element.isEnabled() ) {
712
//            this.infoPanel.clean();
713
//        } else {
714
            this.infoPanel.setDescription(removeCursorMark(element.getDescription()));
715
            this.infoPanel.setAdditionalPanel(element.getAditionalPanel(this));
716
            this.infoPanel.repaint();
717
//        }        
718
    }
719

    
720
    private void updateSimpleElementsList(Element element) {
721
        FilteredListModel model = new FilteredListModel();
722
        model.addElement("Loading...");
723
        this.currentElement = element;
724
        this.txtGroupElement.setText(element.getName());
725
        this.txtSimpleElementFilter.setText("");
726
//        this.infoPanel.clean();
727
//        this.infoPanel.repaint();
728
        if (element instanceof SimpleElement) {
729
            this.btnGroupElementInsert.setEnabled(true);
730
        } else {
731
            this.btnGroupElementInsert.setEnabled(false);
732
        }
733
        this.lstSimpleElement.setEnabled(false);
734
        this.lstSimpleElement.setModel(model);
735

    
736
        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
        final Element element = this.currentElement;
747
        final FilteredListModel model = new FilteredListModel();
748
        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
                return;
753
            }
754
            if (value instanceof SimpleElement) {
755
                model.addElement(value);
756
            }
757
        }
758
        model.sort(true);
759
        SwingUtilities.invokeLater(new Runnable() {
760
            @Override
761
            public void run() {
762
                if (element != currentElement) {
763
                    return;
764
                }
765
                if( element.hasMoreValues()) {
766
                    lblSimpleElementsMsg.setText("More elements...");
767
                } else {
768
                    lblSimpleElementsMsg.setText("");
769
                }
770
                lstSimpleElement.setEnabled(true);
771
                lstSimpleElement.setModel(model);
772
            }
773
        });
774

    
775
    }
776

    
777
    @Override
778
    public Expression getExpression() {
779
        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
        String phrase = this.txtExpression.getText();
788
        if (StringUtils.isEmpty(phrase)) {
789
            return null;
790
        }
791
        Expression expression = ExpressionEvaluatorLocator.getManager().createExpression();
792
        expression.setPhrase(phrase);
793
//        Script script = ToolsLocator.getScriptManager().createScript("UserScript", "", "python");
794
//        this.scriptEditor.fetch(script);
795
//        if( !StringUtils.isEmpty(script.getCode()) ) {
796
//            expression.setUserScript(script);
797
//        }
798
        return expression;
799
    }
800

    
801
    @Override
802
    public void setExpression(Expression expression) {
803
        if( expression==null ) {
804
            this.txtExpression.setText("");
805
        } else {
806
            this.txtExpression.setText(expression.getPhrase());
807
        }
808
//            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
    }
820

    
821
    @Override
822
    public Preferences getPreferences() {
823
        return this.builderConfig.getPreferences();
824
    }
825
    
826
    @Override
827
    public List<Element> getElements() {
828
        return this.builderConfig.getElements();
829
    }
830
    
831
    @Override
832
    public void addElement(Element element) {
833
        this.builderConfig.addElement(element);
834
    }
835
    
836
    @Override
837
    public Collection<SymbolTable> getSymbolTables() {
838
        return this.builderConfig.getSymbolTables();
839
    }
840
    
841
    @Override
842
    public void addSymbolTable(String name) {
843
        this.builderConfig.addSymbolTable(name);
844
    }
845
    
846
    @Override
847
    public void addSymbolTable(SymbolTable symbolTable) {
848
        this.builderConfig.addSymbolTable(symbolTable);
849
    }
850

    
851
    @Override
852
    public void removeAllSymbolTables() {
853
        this.builderConfig.removeAllSymbolTables();
854
    }
855

    
856
    @Override
857
    public void removeSymbolTable(String name) {
858
        this.builderConfig.removeSymbolTable(name);
859
    }
860

    
861
    @Override
862
    public SymbolTable getPreviewSymbolTable() {
863
        return this.builderConfig.getPreviewSymbolTable();
864
    }
865

    
866
    @Override
867
    public void setPreviewSymbolTable(SymbolTable symbolTable) {
868
        this.builderConfig.setPreviewSymbolTable(symbolTable);
869
    }
870
    
871
    @Override
872
    public JComponent asJComponent() {
873
        this.initializeTree();
874
        SwingUtilities.invokeLater(new Runnable() {
875
            @Override
876
            public void run() {
877
               txtExpression.requestFocusInWindow();
878
            }
879
        });
880
        return this;
881
    }
882
    
883
    private void initializeTree() {
884
        if( this.treeModel == null ) {
885
            I18nManager i18n = ToolsLocator.getI18nManager();
886
            this.treeModel = new ElementsTreeModel( (GroupElement)
887
                    this.manager.createGroupElement(
888
                            i18n.getTranslation("_Elements"),
889
                            this.getElements()
890
                    ).setConfig(this));
891
            this.treeElements.setModel(this.treeModel);
892
            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
        }
903
    }
904
    
905
    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
                String.valueOf(this.builderConfig.getPreferences().getSimpleElementsLimit())
912
        );
913
        if( StringUtils.isBlank(s) ) {
914
            return;
915
        }
916
        try {
917
            int n = Integer.parseInt(s);
918
            this.builderConfig.getPreferences().setSimpleElementsLimit(n);
919
            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

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

    
963
    @Override
964
    public Object getProperty(String name) {
965
        return this.builderConfig.getProperty(name);
966
    }
967

    
968
    @Override
969
    public void setProperty(String name, Object value) {
970
        this.builderConfig.setProperty(name, value);
971
    }
972

    
973
    @Override
974
    public Map<String, Object> getProperties() {
975
        return this.builderConfig.getProperties();
976
    }
977
}