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

History | View | Annotate | Download (34 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
            private JLabel JPanel() {
416
                throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
417
            }
418
        });
419
        
420
        this.treeElements.addTreeSelectionListener(new TreeSelectionListener() {
421
            @Override
422
            public void valueChanged(TreeSelectionEvent e) {
423
                TreePath path = e.getPath();
424
                Element element = (Element) path.getLastPathComponent();
425
                doSelectElement(element);
426
                updateSimpleElementsList(element);
427
            }
428
        });
429
        this.treeElements.addMouseListener(new MouseAdapter() {
430
            @Override
431
            public void mouseClicked(MouseEvent e) {
432
                if( e.getButton()==MouseEvent.BUTTON1 && e.getClickCount()==2 ) {
433
                    TreePath path = treeElements.getSelectionPath();
434
                    if( path!=null ) {
435
                        Element element = (Element) path.getLastPathComponent();
436
                        if( element instanceof SimpleElement ) {
437
                            doInsert((SimpleElement) element);
438
                        }
439
                    }
440
                }
441
            }
442
        });
443
        this.btnGroupElementInsert.addActionListener(new ActionListener() {
444
            @Override
445
            public void actionPerformed(ActionEvent e) {
446
                if( currentElement!=null ) {
447
                    doInsert(currentElement.getRenderedValue());
448
                } else {
449
                    doInsert(txtGroupElement.getText());
450
                }
451
            }
452
        });
453
        this.btnSimpleElementInsert.addActionListener(new ActionListener() {
454
            @Override
455
            public void actionPerformed(ActionEvent e) {
456
                Element element = (Element) lstSimpleElement.getSelectedValue();
457
                if (element != null) {
458
                    doInsert(element);
459
                }
460
            }
461
        });
462
        this.btnSimpleElementFilter.addActionListener(new ActionListener() {
463
            @Override
464
            public void actionPerformed(ActionEvent e) {
465
                doFilter();
466
            }
467
        });
468
        
469
        this.lstSimpleElement.setModel(new FilteredListModel());
470
        this.lstSimpleElement.setCellRenderer(new DefaultListCellRenderer() {
471
            @Override
472
            public java.awt.Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
473
                JLabel label = (JLabel)super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
474
                if( value instanceof Element ) {
475
                    Element element = (Element) value;
476
                    if( element.getIconName()==null ) {
477
                        if( element instanceof GroupElement ) {
478
                            label.setIcon(defaultIconGroup);
479
                        } else {
480
                            label.setIcon(defaultIconElement);
481
                        }
482
                    } else {
483
                        label.setIcon(element.getIcon());
484
                    }
485
                    label.setText(element.getLabel());
486
                    label.setEnabled(element.isEnabled());
487
                } else {
488
                    label.setIcon(null);
489
                    label.setText(Objects.toString(value, ""));
490
                }
491
                return label;
492
            }
493
        });
494
        this.lstSimpleElement.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
495
            @Override
496
            public void valueChanged(ListSelectionEvent e) {
497
                Element element = (Element) lstSimpleElement.getSelectedValue();
498
                if (element != null) {
499
                    doSelectElement(element);
500
                }
501
            }
502
        });
503
        this.lstSimpleElement.addMouseListener(new MouseAdapter() {
504
            @Override
505
            public void mouseClicked(MouseEvent e) {
506
                if( e.getButton()==MouseEvent.BUTTON1 && e.getClickCount()==2 ) {
507
                    Element element = (Element) lstSimpleElement.getSelectedValue();
508
                    if (element != null) {
509
                        doSelectElement(element);
510
                        doInsert(element);
511
                    }
512
                }
513
            }
514
        });
515
        this.lstSimpleElement.addKeyListener(new KeyAdapter() {
516
            @Override
517
            public void keyReleased(KeyEvent e) {
518
                if( e.getKeyCode()==KeyEvent.VK_ENTER ) {
519
                    Element element = (Element) lstSimpleElement.getSelectedValue();
520
                    if (element != null) {
521
                        doSelectElement(element);
522
                        doInsert(element);
523
                    }
524
                }
525
            }
526
        });
527

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

    
629
            @Override
630
            public Expression getExpressionWithOutHistory() {
631
                    return DefaultJExpressionBuilder.this.getExpressionWithOutHistory();
632
            }
633
        };
634
        
635
        
636
        this.infoPanel.repaint();
637
        
638
        this.setPreferredSize(new Dimension(750, 450));
639
        
640

    
641
        Dimension dim = this.getPreferredSize();
642
        this.spnlExpression.setDividerLocation(dim.height/5);
643
        this.spnlBottom.setDividerLocation(dim.width/3);
644
        this.spnlItem.setDividerLocation(dim.width/3);
645
    }
646

    
647
    private String removeCursorMark(String s) {
648
        if( s == null ) {
649
            return null;
650
        }
651
        s = s.replace("{{", "");
652
        s = s.replace("}}", "");
653
        return s;
654
    }
655

    
656
    @Override
657
    public void insertText(String text) {
658
        doInsert(text);
659
    }
660

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

    
685
    private void doInsert(Element element) {
686
        doInsert(element.getRenderedValue());
687
        element.used();
688
    }
689

    
690
    private void doFilter() {
691
        FilteredListModel model = (FilteredListModel) this.lstSimpleElement.getModel();
692
        model.setFilter(this.txtSimpleElementFilter.getText());
693
    }
694

    
695
    private void doSelectElement(Element element) {
696
//        if( !element.isEnabled() ) {
697
//            this.infoPanel.clean();
698
//        } else {
699
            this.infoPanel.setDescription(removeCursorMark(element.getDescription()));
700
            this.infoPanel.setAdditionalPanel(element.getAditionalPanel(this));
701
            this.infoPanel.repaint();
702
//        }        
703
    }
704

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

    
721
        Thread th = new Thread(new Runnable() {
722
            @Override
723
            public void run() {
724
                simpleElementsUpdater();
725
            }
726
        }, "ExpressionBuilderSimpleElementsUpdater");
727
        th.start();
728
    }
729

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

    
760
    }
761

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

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

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

    
833
    @Override
834
    public void removeAllSymbolTables() {
835
        this.builderConfig.removeAllSymbolTables();
836
    }
837

    
838
    @Override
839
    public void removeSymbolTable(String name) {
840
        this.builderConfig.removeSymbolTable(name);
841
    }
842

    
843
    @Override
844
    public SymbolTable getPreviewSymbolTable() {
845
        return this.builderConfig.getPreviewSymbolTable();
846
    }
847

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

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

    
929
    @Override
930
    public Object getProperty(String name) {
931
        return this.builderConfig.getProperty(name);
932
    }
933

    
934
    @Override
935
    public void setProperty(String name, Object value) {
936
        this.builderConfig.setProperty(name, value);
937
    }
938

    
939
    @Override
940
    public Map<String, Object> getProperties() {
941
        return this.builderConfig.getProperties();
942
    }
943
}