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

History | View | Annotate | Download (33.8 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.expressionevaluator.Expression;
52
import org.gvsig.expressionevaluator.ExpressionEvaluatorLocator;
53
import org.gvsig.expressionevaluator.ExpressionEvaluatorManager;
54
import org.gvsig.expressionevaluator.SymbolTable;
55
import org.gvsig.expressionevaluator.swing.Element;
56
import org.gvsig.expressionevaluator.swing.Element.GroupElement;
57
import org.gvsig.expressionevaluator.swing.Element.SimpleElement;
58
import org.gvsig.expressionevaluator.swing.ExpressionBuilderConfig;
59
import org.gvsig.expressionevaluator.swing.ExpressionEvaluatorSwingManager;
60
import org.gvsig.expressionevaluator.swing.JExpressionBuilder;
61
import org.gvsig.tools.ToolsLocator;
62
import org.gvsig.tools.i18n.I18nManager;
63
import org.gvsig.tools.script.Script;
64
import org.gvsig.tools.swing.api.Component;
65
import org.gvsig.tools.swing.api.ToolsSwingLocator;
66
import org.gvsig.tools.swing.api.ToolsSwingManager;
67
import org.gvsig.tools.swing.api.pickercontroller.PickerController;
68
import org.gvsig.tools.swing.api.script.ScriptSwingManager;
69
import org.gvsig.tools.swing.api.threadsafedialogs.ThreadSafeDialogsManager;
70
import org.gvsig.tools.swing.icontheme.IconTheme;
71

    
72
/**
73
 *
74
 * @author jjdelcerro
75
 */
76
@SuppressWarnings("UseSpecificCatch")
77
public class DefaultJExpressionBuilder
78
        extends DefaultJExpressionBuilderView2
79
        implements JExpressionBuilder {
80

    
81
    private final ExpressionEvaluatorSwingManager manager;
82
    private Element currentElement;
83
    private PickerController<List<Script>> scriptPicker;
84
    private ScriptSwingManager.ScriptEditor scriptEditor;
85
    
86
    private final ExpressionBuilderConfig builderConfig;
87
    private ElementsTreeModel treeModel;
88
    private ImageIcon defaultIconGroup;
89
    private ImageIcon defaultIconElement;
90
    private InfoPanel infoPanel;
91
    private AbstractAutomaticExpressionChecker automaticExpressionChecker;
92
    private HistoryController historyController;
93
    private BookmarksController bookmarksController;
94

    
95
    private static class InfoPanel implements Component {
96

    
97
        private final JEditorPane txtDescription;
98
        private final JScrollPane scrDescription;
99
        private final JTabbedPane tab;
100

    
101
        private final String labelDescription;
102
        private final String labelAdditionalPanel;
103
        private final JPanel pnlContainer;
104
        
105
        private final String defautltDescription;
106

    
107
        private String description; 
108
        private Component additionalPanel;
109
        
110
        public InfoPanel(JPanel pnlContainer, String defautltDescription) {
111
            ToolsSwingManager toolsSwingManager = ToolsSwingLocator.getToolsSwingManager();
112
            I18nManager i18n = ToolsLocator.getI18nManager();
113
            
114
            this.defautltDescription = defautltDescription;
115
            this.pnlContainer = pnlContainer;
116
            this.labelDescription = i18n.getTranslation("_Description");
117
            this.labelAdditionalPanel = i18n.getTranslation("_Assistant");
118
            
119
            this.txtDescription = new JEditorPane();
120
            this.scrDescription = new JScrollPane(this.txtDescription);
121
            this.tab = new JTabbedPane();
122
            
123
            toolsSwingManager.setDefaultPopupMenu(this.txtDescription);
124
            this.txtDescription.setPreferredSize(new Dimension(200,200));
125
        }
126
        
127
        public void clean() {
128
            this.description = null;
129
            this.additionalPanel = null;
130
        }
131
        
132
        public void setDescription(String description) {
133
            this.description = description;
134
        }
135
        
136
        public void setAdditionalPanel(Component panel) {
137
            this.additionalPanel = panel;
138
        }
139

    
140
        @Override
141
        public JComponent asJComponent() {
142
            this.txtDescription.setContentType("text/html");
143
            this.txtDescription.setText(this.description);
144
            this.txtDescription.setCaretPosition(0);
145

    
146
            if( StringUtils.isBlank(this.description) ) {
147
                if( this.additionalPanel==null ) {
148
                    // Sin descripcion ni panel adicional, mostramos
149
                    // la descripcion por defecto.
150
                    this.txtDescription.setText(this.defautltDescription);
151
                    this.txtDescription.setCaretPosition(0);
152
                    return this.scrDescription;
153
                }
154
                // Sin descripcion pero con panel adicional, mostramos el 
155
                // panel adicional.
156
                return this.additionalPanel.asJComponent();
157
            }
158
            if( this.additionalPanel==null ) {
159
                // Con descripcion y sin panel adicional, mostramos
160
                // la descripcion.
161
                return this.scrDescription;                
162
            } 
163
            // Con descripcion y panel adicional, mostramos un tab con los dos.
164
            this.tab.removeAll();
165
            this.tab.add(
166
                    this.labelDescription, 
167
                    this.scrDescription
168
            );
169
            this.tab.add(
170
                    this.labelAdditionalPanel, 
171
                    this.additionalPanel.asJComponent()
172
            );
173
            this.tab.setSelectedIndex(1);
174
            return this.tab;
175
        }
176

    
177
        public void repaint() {
178
            this.pnlContainer.removeAll();
179
            this.pnlContainer.add(this.asJComponent(), BorderLayout.CENTER);
180
            this.pnlContainer.revalidate();
181
            this.pnlContainer.repaint();
182
        }
183
    }
184

    
185
    private class ElementsTreeModel implements TreeModel {
186

    
187
        private final GroupElement root;
188
        private final HashSet<TreeModelListener> listeners;
189

    
190
        public ElementsTreeModel(GroupElement root) {
191
            this.root = root;
192
            this.listeners = new HashSet<>();
193
        }
194

    
195
        @Override
196
        public Object getRoot() {
197
            return this.root;
198
        }
199

    
200
        public void reload() {
201
            this.reload(this.root);
202
            this.fireTreeChanged();
203
        }
204
        
205
        private void reload(Element element) {
206
            if (element instanceof Element) {
207
//                if (element instanceof GroupElement) {
208
                    reload(element);
209
//                }
210
                element.reload();
211
            }
212
        }
213
        
214
        private List<Element> getChilds(final GroupElement node) {
215
            List<Element> x = new ArrayList<>();
216
            for (Element element : node.getElements()) {
217
//                if (element instanceof GroupElement) {
218
                    x.add(element);
219
//                }
220
            }
221
            return x; //node.getElements();
222
        }
223

    
224
        @Override
225
        public Object getChild(Object parent, int index) {
226
            List<Element> childs = getChilds((GroupElement) parent);
227
            Element child = childs.get(index);
228
            return child;
229
        }
230

    
231
        @Override
232
        public int getChildCount(Object parent) {
233
            List<Element> childs = getChilds((GroupElement) parent);
234
            return childs.size();
235
        }
236

    
237
        @Override
238
        public boolean isLeaf(Object node) {
239
            return !(node instanceof GroupElement);
240
        }
241

    
242
        @Override
243
        public void valueForPathChanged(TreePath path, Object newValue) {
244
        }
245

    
246
        @Override
247
        public int getIndexOfChild(Object parent, Object child) {
248
            List<Element> childs = getChilds((GroupElement) parent);
249
            int n = childs.indexOf(child);
250
            return n;
251
        }
252

    
253
        @Override
254
        public void addTreeModelListener(TreeModelListener l) {
255
            this.listeners.add(l);
256
        }
257

    
258
        @Override
259
        public void removeTreeModelListener(TreeModelListener l) {
260
            this.listeners.remove(l);
261
        }
262

    
263
        protected void fireTreeChanged() {
264
            for (TreeModelListener listener : listeners) {
265
                TreeModelEvent e = new TreeModelEvent(this, new Object[] {this.root});
266
                listener.treeNodesChanged(e);
267
            }
268
        }
269
    }
270
  
271
    @SuppressWarnings("OverridableMethodCallInConstructor")
272
    public DefaultJExpressionBuilder(ExpressionEvaluatorSwingManager manager, ExpressionBuilderConfig config) {
273
        this.manager = manager;
274
        if( config == null ) {
275
            this.builderConfig = new DefaultExpressionBuilderConfig(manager);
276
        } else {
277
            this.builderConfig = config;
278
        }
279
        this.initComponents();
280
    }
281
    
282
    @Override
283
    public ImageIcon loadImage(String imageName) {
284
        String name = FilenameUtils.getBaseName(imageName);
285
        IconTheme theme = ToolsSwingLocator.getIconThemeManager().getDefault();
286
        if (theme.exists(name)) {
287
            return theme.get(name);
288
        }
289
        URL url = this.getClass().getResource(name + ".png");
290
        if (url == null) {
291
            return null;
292
        }
293
        return new ImageIcon(url);
294
    }
295

    
296
    private void initComponents() {
297
        final ToolsSwingManager toolsSwingManager = ToolsSwingLocator.getToolsSwingManager();
298
        final IconTheme theme = ToolsSwingLocator.getIconThemeManager().getCurrent();
299
        final I18nManager i18n = ToolsLocator.getI18nManager();
300
        
301
        this.automaticExpressionChecker = new AbstractAutomaticExpressionChecker(
302
                builderConfig, txtExpression
303
            ) {
304
            @Override
305
            protected Expression getExpression() {
306
                return DefaultJExpressionBuilder.this.getExpressionWithOutHistory();
307
            }
308

    
309
            @Override
310
            protected void setMessage(int mode, String text) {
311
                super.setMessage(mode, text); 
312
                lblMsg.setText("<html>"+StringUtils.abbreviate(text,100)+"</html>");
313
            }
314

    
315
            @Override
316
            protected void setPreview(Object value) {
317
                super.setPreview(value);
318
                lblMsg.setText("<html>"+StringUtils.abbreviate(this.getPreview(),100)+"</html>");
319
            }
320

    
321
            @Override
322
            protected void setTip(String theTip) {
323
                super.setTip(theTip); 
324
                btnTip.setToolTipText(this.getTip());
325
                btnTip.setVisible(this.isTipEnabled());
326
            }
327
            
328
        };
329
        this.infoPanel = new InfoPanel(this.pnlDescription, load_description_from_resource());
330
        
331
        this.btnTip.setVisible(false);
332
        this.btnTip.addActionListener(new ActionListener() {
333
            @Override
334
            public void actionPerformed(ActionEvent e) {
335
                ThreadSafeDialogsManager dialogs = ToolsSwingLocator.getThreadSafeDialogsManager();
336
                dialogs.messageDialog(
337
                        btnTip.getToolTipText(), 
338
                        "Tip", 
339
                        JOptionPane.INFORMATION_MESSAGE
340
                );
341
            }
342
        });
343

    
344
        this.defaultIconGroup = theme.get("expressionbuilder-element-group");
345
        this.defaultIconElement = theme.get("expressionbuilder-element");
346
        
347
        toolsSwingManager.translate(this.tabExpressionBuilder);
348
        toolsSwingManager.setDefaultPopupMenu(this.txtGroupElement);
349
        toolsSwingManager.setDefaultPopupMenu(this.txtSimpleElementFilter);
350
        toolsSwingManager.addClearButton(this.txtSimpleElementFilter, new ActionListener() {
351
            @Override
352
            public void actionPerformed(ActionEvent e) {
353
                txtSimpleElementFilter.setText("");
354
                doFilter();
355
            }
356
        });
357
        JMenuItem msgMenuTextEditor = new JMenuItem(i18n.getTranslation("text_editor"));
358
        msgMenuTextEditor.addActionListener(new ActionListener() {
359
            @Override
360
            public void actionPerformed(ActionEvent e) {
361
                automaticExpressionChecker.showMessageDialog();
362
            }
363
        });
364
        JMenuItem msgMenuCopy = new JMenuItem(i18n.getTranslation("copy"));
365
        msgMenuTextEditor.addActionListener(new ActionListener() {
366
            @Override
367
            public void actionPerformed(ActionEvent e) {
368
                StringSelection selection = new StringSelection(automaticExpressionChecker.getMessage());
369
                Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
370
                clipboard.setContents(selection, selection);                
371
            }
372
        });
373
        
374
        JPopupMenu msgMenu = new JPopupMenu();
375
        msgMenu.add(msgMenuTextEditor);
376
        msgMenu.addSeparator();
377
        msgMenu.add(msgMenuCopy);
378
        this.lblMsg.setComponentPopupMenu(msgMenu);
379

    
380
        this.pnlDescription.setLayout(new BorderLayout());
381
        this.txtExpression.addCaretListener(new CaretListener() {
382
            @Override
383
            public void caretUpdate(CaretEvent e) {
384
                lblColumn.setText(Integer.toString(e.getDot()));
385
            }
386
        });
387
        this.treeElements.setRowHeight(0);
388
        this.treeElements.setCellRenderer(new DefaultTreeCellRenderer() {
389
            @Override
390
            public java.awt.Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
391
                JLabel component = (JLabel) super.getTreeCellRendererComponent(tree,value, selected, expanded, leaf, row, hasFocus);
392
                JLabel text = component;
393
                JLabel icon = component;
394
                
395
                if( value instanceof Element ) {
396
                    Element element = (Element) value;
397
                    if( element.getIconName()==null ) {
398
                        if( element instanceof GroupElement ) {
399
                            icon.setIcon(defaultIconGroup);
400
                        } else {
401
                            icon.setIcon(defaultIconElement);
402
                        }
403
                    } else {
404
                        icon.setIcon(element.getIcon());
405
                    }
406
                    text.setText(element.getLabel());
407
                    text.setEnabled(element.isEnabled());
408
                } else {
409
                    icon.setIcon(null);
410
                    text.setText(Objects.toString(value, ""));
411
                }
412
                return component;
413
            }
414
        });
415
        
416
        this.treeElements.addTreeSelectionListener(new TreeSelectionListener() {
417
            @Override
418
            public void valueChanged(TreeSelectionEvent e) {
419
                TreePath path = e.getPath();
420
                Element element = (Element) path.getLastPathComponent();
421
                doSelectElement(element);
422
                updateSimpleElementsList(element);
423
            }
424
        });
425
        this.treeElements.addMouseListener(new MouseAdapter() {
426
            @Override
427
            public void mouseClicked(MouseEvent e) {
428
                if( e.getButton()==MouseEvent.BUTTON1 && e.getClickCount()==2 ) {
429
                    TreePath path = treeElements.getSelectionPath();
430
                    if( path!=null ) {
431
                        Element element = (Element) path.getLastPathComponent();
432
                        if( element instanceof SimpleElement ) {
433
                            doInsert((SimpleElement) element);
434
                        }
435
                    }
436
                }
437
            }
438
        });
439
        this.btnGroupElementInsert.addActionListener(new ActionListener() {
440
            @Override
441
            public void actionPerformed(ActionEvent e) {
442
                if( currentElement!=null ) {
443
                    doInsert(currentElement.getRenderedValue());
444
                } else {
445
                    doInsert(txtGroupElement.getText());
446
                }
447
            }
448
        });
449
        this.btnSimpleElementInsert.addActionListener(new ActionListener() {
450
            @Override
451
            public void actionPerformed(ActionEvent e) {
452
                Element element = (Element) lstSimpleElement.getSelectedValue();
453
                if (element != null) {
454
                    doInsert(element);
455
                }
456
            }
457
        });
458
        this.btnSimpleElementFilter.addActionListener(new ActionListener() {
459
            @Override
460
            public void actionPerformed(ActionEvent e) {
461
                doFilter();
462
            }
463
        });
464
        
465
        this.lstSimpleElement.setModel(new FilteredListModel());
466
        this.lstSimpleElement.setCellRenderer(new DefaultListCellRenderer() {
467
            @Override
468
            public java.awt.Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
469
                JLabel label = (JLabel)super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
470
                if( value instanceof Element ) {
471
                    Element element = (Element) value;
472
                    if( element.getIconName()==null ) {
473
                        if( element instanceof GroupElement ) {
474
                            label.setIcon(defaultIconGroup);
475
                        } else {
476
                            label.setIcon(defaultIconElement);
477
                        }
478
                    } else {
479
                        label.setIcon(element.getIcon());
480
                    }
481
                    label.setText(element.getLabel());
482
                    label.setEnabled(element.isEnabled());
483
                } else {
484
                    label.setIcon(null);
485
                    label.setText(Objects.toString(value, ""));
486
                }
487
                return label;
488
            }
489
        });
490
        this.lstSimpleElement.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
491
            @Override
492
            public void valueChanged(ListSelectionEvent e) {
493
                Element element = (Element) lstSimpleElement.getSelectedValue();
494
                if (element != null) {
495
                    doSelectElement(element);
496
                }
497
            }
498
        });
499
        this.lstSimpleElement.addMouseListener(new MouseAdapter() {
500
            @Override
501
            public void mouseClicked(MouseEvent e) {
502
                if( e.getButton()==MouseEvent.BUTTON1 && e.getClickCount()==2 ) {
503
                    Element element = (Element) lstSimpleElement.getSelectedValue();
504
                    if (element != null) {
505
                        doSelectElement(element);
506
                        doInsert(element);
507
                    }
508
                }
509
            }
510
        });
511
        this.lstSimpleElement.addKeyListener(new KeyAdapter() {
512
            @Override
513
            public void keyReleased(KeyEvent e) {
514
                if( e.getKeyCode()==KeyEvent.VK_ENTER ) {
515
                    Element element = (Element) lstSimpleElement.getSelectedValue();
516
                    if (element != null) {
517
                        doSelectElement(element);
518
                        doInsert(element);
519
                    }
520
                }
521
            }
522
        });
523

    
524
        this.btnSimpleElementTimeLimit.addActionListener(new ActionListener() {
525
            @Override
526
            public void actionPerformed(ActionEvent e) {
527
                doSetTimeLimit();
528
            }
529
        });
530
        this.btnSimpleElementSortDown.addActionListener(new ActionListener() {
531
            @Override
532
            public void actionPerformed(ActionEvent e) {
533
                FilteredListModel model = (FilteredListModel) lstSimpleElement.getModel();
534
                model.sort(false);
535
            }
536
        });
537
        this.btnSimpleElementSortUp.addActionListener(new ActionListener() {
538
            @Override
539
            public void actionPerformed(ActionEvent e) {
540
                FilteredListModel model = (FilteredListModel) lstSimpleElement.getModel();
541
                model.sort(true);
542
            }
543
        });
544
        this.txtSimpleElementFilter.addKeyListener(new KeyAdapter() {
545
            @Override
546
            public void keyTyped(KeyEvent e) {
547
                if (e.getKeyChar() == '\n') {
548
                    doFilter();
549
                }
550
            }
551
        });
552
        this.btnAdd.addActionListener(new ActionListener() {
553
            @Override
554
            public void actionPerformed(ActionEvent e) {
555
                doInsert(" + ");
556
            }
557
        });
558
        this.btnDiv.addActionListener(new ActionListener() {
559
            @Override
560
            public void actionPerformed(ActionEvent e) {
561
                doInsert(" / ");
562
            }
563
        });
564
        this.btnEq.addActionListener(new ActionListener() {
565
            @Override
566
            public void actionPerformed(ActionEvent e) {
567
                doInsert(" = ");
568
            }
569
        });
570
        this.btnMult.addActionListener(new ActionListener() {
571
            @Override
572
            public void actionPerformed(ActionEvent e) {
573
                doInsert(" * ");
574
            }
575
        });
576
        this.btnNeq.addActionListener(new ActionListener() {
577
            @Override
578
            public void actionPerformed(ActionEvent e) {
579
                doInsert(" <> ");
580
            }
581
        });
582
        this.btnParentClose.addActionListener(new ActionListener() {
583
            @Override
584
            public void actionPerformed(ActionEvent e) {
585
                doInsert(" ) ");
586
            }
587
        });
588
        this.btnParentOpen.addActionListener(new ActionListener() {
589
            @Override
590
            public void actionPerformed(ActionEvent e) {
591
                doInsert(" ( ");
592
            }
593
        });
594
        this.btnSubst.addActionListener(new ActionListener() {
595
            @Override
596
            public void actionPerformed(ActionEvent e) {
597
                doInsert(" - ");
598
            }
599
        });
600
        ScriptSwingManager scriptSwingManager = ToolsSwingLocator.getScriptSwingManager();
601
        this.scriptPicker = scriptSwingManager.createListScriptPickerController(
602
                cboPickerScripts,
603
                btnPickerRemove,
604
                btnPickerSelectScript
605
        );
606
        this.scriptEditor = scriptSwingManager.createScriptEditor();
607
        this.pnlScriptEditorContainer.setLayout(new BorderLayout());
608
        this.pnlScriptEditorContainer.add(this.scriptEditor.asJComponent(), BorderLayout.CENTER);
609
    
610
        this.tabExpressionBuilder.setEnabledAt(0, this.builderConfig.getPreferences().getScriptsEnabled());
611
        
612
        this.historyController = new HistoryController(btnHistory) {
613
            @Override
614
            public void updateExpression(Expression expression) {
615
                setExpression(expression);
616
            }
617
        };
618
        
619
        this.bookmarksController = new BookmarksController(btnBookmarks) {
620
            @Override
621
            public void updateExpression(Expression expression) {
622
                setExpression(expression);
623
            }
624

    
625
            @Override
626
            public Expression getExpressionWithOutHistory() {
627
                    return DefaultJExpressionBuilder.this.getExpressionWithOutHistory();
628
            }
629
        };
630
        
631
        
632
        this.infoPanel.repaint();
633
        
634
        this.setPreferredSize(new Dimension(750, 450));
635
        
636

    
637
        Dimension dim = this.getPreferredSize();
638
        this.spnlExpression.setDividerLocation(dim.height/5);
639
        this.spnlBottom.setDividerLocation(dim.width/3);
640
        this.spnlItem.setDividerLocation(dim.width/3);
641
    }
642

    
643
    private String removeCursorMark(String s) {
644
        if( s == null ) {
645
            return null;
646
        }
647
        s = s.replace("{{", "");
648
        s = s.replace("}}", "");
649
        return s;
650
    }
651

    
652
    @Override
653
    public void insertText(String text) {
654
        doInsert(text);
655
    }
656

    
657
    @Override
658
    public String getText() {
659
        return this.txtExpression.getText();
660
    }
661
    
662
    @Override
663
    public void setText(String text) {
664
        this.txtExpression.setText(text);
665
    }
666
    
667
    private void doInsert(String s) {
668
        this.txtExpression.replaceSelection(s);
669
        String ss = this.txtExpression.getText();
670
        int start = ss.indexOf("{{");
671
        int end = ss.indexOf("}}");
672
        if (start > 0 && end > 0) {
673
            this.txtExpression.replaceRange("", end, end + 2);
674
            this.txtExpression.replaceRange("", start, start + 2);
675
            this.txtExpression.setSelectionStart(start);
676
            this.txtExpression.setSelectionEnd(end - 2);
677
        }
678
        this.txtExpression.requestFocusInWindow();
679
    }
680

    
681
    private void doInsert(Element element) {
682
        doInsert(element.getRenderedValue());
683
        element.used();
684
    }
685

    
686
    private void doFilter() {
687
        FilteredListModel model = (FilteredListModel) this.lstSimpleElement.getModel();
688
        model.setFilter(this.txtSimpleElementFilter.getText());
689
    }
690

    
691
    private void doSelectElement(Element element) {
692
//        if( !element.isEnabled() ) {
693
//            this.infoPanel.clean();
694
//        } else {
695
            this.infoPanel.setDescription(removeCursorMark(element.getDescription()));
696
            this.infoPanel.setAdditionalPanel(element.getAditionalPanel(this));
697
            this.infoPanel.repaint();
698
//        }        
699
    }
700

    
701
    private void updateSimpleElementsList(Element element) {
702
        FilteredListModel model = new FilteredListModel();
703
        model.addElement("Loading...");
704
        this.currentElement = element;
705
        this.txtGroupElement.setText(element.getName());
706
        this.txtSimpleElementFilter.setText("");
707
//        this.infoPanel.clean();
708
//        this.infoPanel.repaint();
709
        if (element instanceof SimpleElement) {
710
            this.btnGroupElementInsert.setEnabled(true);
711
        } else {
712
            this.btnGroupElementInsert.setEnabled(false);
713
        }
714
        this.lstSimpleElement.setEnabled(false);
715
        this.lstSimpleElement.setModel(model);
716

    
717
        Thread th = new Thread(new Runnable() {
718
            @Override
719
            public void run() {
720
                simpleElementsUpdater();
721
            }
722
        }, "ExpressionBuilderSimpleElementsUpdater");
723
        th.start();
724
    }
725

    
726
    private void simpleElementsUpdater() {
727
        final Element element = this.currentElement;
728
        final FilteredListModel model = new FilteredListModel();
729
        for (Element value : element.getValues()) {
730
            if (element != this.currentElement) {
731
                // Como estamos en otro hilo, cuando el usuario cambia de elemento,
732
                // cancelamos las actualizaciones que teniamos en curso.
733
                return;
734
            }
735
            if (value instanceof SimpleElement) {
736
                model.addElement(value);
737
            }
738
        }
739
        model.sort(true);
740
        SwingUtilities.invokeLater(new Runnable() {
741
            @Override
742
            public void run() {
743
                if (element != currentElement) {
744
                    return;
745
                }
746
                if( element.hasMoreValues()) {
747
                    lblSimpleElementsMsg.setText("More elements...");
748
                } else {
749
                    lblSimpleElementsMsg.setText("");
750
                }
751
                lstSimpleElement.setEnabled(true);
752
                lstSimpleElement.setModel(model);
753
            }
754
        });
755

    
756
    }
757

    
758
    @Override
759
    public Expression getExpression() {
760
        Expression expression = this.getExpressionWithOutHistory();
761
        ExpressionEvaluatorManager theManager = ExpressionEvaluatorLocator.getManager();
762
        theManager.getHistory().add(expression);
763
        return expression;
764
    }
765
    
766
    @Override
767
    public Expression getExpressionWithOutHistory() {
768
        String phrase = this.txtExpression.getText();
769
        if (StringUtils.isEmpty(phrase)) {
770
            return null;
771
        }
772
        Expression expression = ExpressionEvaluatorLocator.getManager().createExpression();
773
        expression.setPhrase(phrase);
774
        Script script = ToolsLocator.getScriptManager().createScript("UserScript", "", "python");
775
        this.scriptEditor.fetch(script);
776
        if( !StringUtils.isEmpty(script.getCode()) ) {
777
            expression.setUserScript(script);
778
        }
779
        return expression;
780
    }
781

    
782
    @Override
783
    public void setExpression(Expression expression) {
784
        if( expression==null ) {
785
            this.txtExpression.setText("");
786
            try { this.scriptEditor.set(null); } catch(Exception ex) {}
787
            this.scriptPicker.set(null);
788
        } else {
789
            this.txtExpression.setText(expression.getPhrase());
790
            if( expression.getUserScript()!=null ) {
791
                this.scriptEditor.set(expression.getUserScript());
792
            }
793
            if( expression.getScripts()!=null ) {
794
                this.scriptPicker.set(expression.getScripts().toList());
795
            }
796
        }
797
    }
798

    
799
    @Override
800
    public Preferences getPreferences() {
801
        return this.builderConfig.getPreferences();
802
    }
803
    
804
    @Override
805
    public List<Element> getElements() {
806
        return this.builderConfig.getElements();
807
    }
808
    
809
    @Override
810
    public void addElement(Element element) {
811
        this.builderConfig.addElement(element);
812
    }
813
    
814
    @Override
815
    public Collection<SymbolTable> getSymbolTables() {
816
        return this.builderConfig.getSymbolTables();
817
    }
818
    
819
    @Override
820
    public void addSymbolTable(String name) {
821
        this.builderConfig.addSymbolTable(name);
822
    }
823
    
824
    @Override
825
    public void addSymbolTable(SymbolTable symbolTable) {
826
        this.builderConfig.addSymbolTable(symbolTable);
827
    }
828

    
829
    @Override
830
    public void removeAllSymbolTables() {
831
        this.builderConfig.removeAllSymbolTables();
832
    }
833

    
834
    @Override
835
    public void removeSymbolTable(String name) {
836
        this.builderConfig.removeSymbolTable(name);
837
    }
838

    
839
    @Override
840
    public SymbolTable getPreviewSymbolTable() {
841
        return this.builderConfig.getPreviewSymbolTable();
842
    }
843

    
844
    @Override
845
    public void setPreviewSymbolTable(SymbolTable symbolTable) {
846
        this.builderConfig.setPreviewSymbolTable(symbolTable);
847
    }
848
    
849
    @Override
850
    public JComponent asJComponent() {
851
        this.initializeTree();
852
        return this;
853
    }
854
    
855
    private void initializeTree() {
856
        if( this.treeModel == null ) {
857
            I18nManager i18n = ToolsLocator.getI18nManager();
858
            this.treeModel = new ElementsTreeModel( (GroupElement)
859
                    this.manager.createGroupElement(
860
                            i18n.getTranslation("_Elements"),
861
                            this.getElements()
862
                    ).setConfig(this));
863
            this.treeElements.setModel(this.treeModel);
864
        }
865
    }
866
    
867
    private void doSetTimeLimit() {
868
        ThreadSafeDialogsManager dialogs = ToolsSwingLocator.getThreadSafeDialogsManager();
869
        String s = dialogs.inputDialog(
870
                "Indicate the time limit in seconds for calculating the elements", 
871
                "Time limit", 
872
                JOptionPane.QUESTION_MESSAGE, 
873
                String.valueOf(this.builderConfig.getPreferences().getSimpleElementsLimit())
874
        );
875
        if( StringUtils.isBlank(s) ) {
876
            return;
877
        }
878
        try {
879
            int n = Integer.parseInt(s);
880
            this.builderConfig.getPreferences().setSimpleElementsLimit(n);
881
            this.treeModel.reload();
882
        } catch(Exception ex) {
883
            dialogs.messageDialog(
884
                "Invalid time limit '"+s+"'.", 
885
                "Time limit", 
886
                JOptionPane.WARNING_MESSAGE
887
            );                    
888
        }
889
    }
890

    
891
    private String load_description_from_resource() {
892
        String lang = Locale.getDefault().getLanguage();
893
        URL url = this.getClass().getResource("/org/gvsig/expressionevaluator/swing/jexpressionbuilder/"+lang+"/description.html");
894
        if( url == null ) {
895
            url = this.getClass().getResource("/org/gvsig/expressionevaluator/swing/jexpressionbuilder/en/description.html");
896
            if( url == null ) {
897
                return null;
898
            }
899
        }
900
        InputStream is = null;
901
        try {
902
            is = url.openStream();
903
            List<String> lines = IOUtils.readLines(is);
904
            return StringUtils.join(lines,  "\n");
905
        } catch (Exception ex) {
906
            return null;
907
        } finally {
908
            IOUtils.closeQuietly(is);
909
        }
910
    }
911
    
912
    @Override
913
    public void expandElement(Element element) {
914
        this.initializeTree();
915
        for (int i = 0; i < this.treeElements.getRowCount(); i++) {
916
            TreePath path = this.treeElements.getPathForRow(i);
917
            if( path.getLastPathComponent()==element ) {
918
                // FIXME: habria que expandir los padres hasta llegar a este.
919
                this.treeElements.expandPath(path);
920
                return;
921
            }
922
        }
923
    }
924

    
925
    @Override
926
    public Object getProperty(String name) {
927
        return this.builderConfig.getProperty(name);
928
    }
929

    
930
    @Override
931
    public void setProperty(String name, Object value) {
932
        this.builderConfig.setProperty(name, value);
933
    }
934

    
935
    @Override
936
    public Map<String, Object> getProperties() {
937
        return this.builderConfig.getProperties();
938
    }
939
}