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

History | View | Annotate | Download (33 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.Objects;
22
import javax.swing.DefaultListCellRenderer;
23
import javax.swing.ImageIcon;
24
import javax.swing.JComponent;
25
import javax.swing.JEditorPane;
26
import javax.swing.JLabel;
27
import javax.swing.JList;
28
import javax.swing.JMenuItem;
29
import javax.swing.JOptionPane;
30
import javax.swing.JPanel;
31
import javax.swing.JPopupMenu;
32
import javax.swing.JScrollPane;
33
import javax.swing.JTabbedPane;
34
import javax.swing.JTree;
35
import javax.swing.SwingUtilities;
36
import javax.swing.event.CaretEvent;
37
import javax.swing.event.CaretListener;
38
import javax.swing.event.ListSelectionEvent;
39
import javax.swing.event.ListSelectionListener;
40
import javax.swing.event.TreeModelEvent;
41
import javax.swing.event.TreeModelListener;
42
import javax.swing.event.TreeSelectionEvent;
43
import javax.swing.event.TreeSelectionListener;
44
import javax.swing.tree.DefaultTreeCellRenderer;
45
import javax.swing.tree.TreeModel;
46
import javax.swing.tree.TreePath;
47
import org.apache.commons.io.FilenameUtils;
48
import org.apache.commons.io.IOUtils;
49
import org.apache.commons.lang3.StringUtils;
50
import org.gvsig.expressionevaluator.Expression;
51
import org.gvsig.expressionevaluator.ExpressionEvaluatorLocator;
52
import org.gvsig.expressionevaluator.SymbolTable;
53
import org.gvsig.expressionevaluator.swing.Element;
54
import org.gvsig.expressionevaluator.swing.Element.GroupElement;
55
import org.gvsig.expressionevaluator.swing.Element.SimpleElement;
56
import org.gvsig.expressionevaluator.swing.ExpressionBuilderConfig;
57
import org.gvsig.expressionevaluator.swing.ExpressionEvaluatorSwingManager;
58
import org.gvsig.expressionevaluator.swing.JExpressionBuilder;
59
import org.gvsig.tools.ToolsLocator;
60
import org.gvsig.tools.i18n.I18nManager;
61
import org.gvsig.tools.script.Script;
62
import org.gvsig.tools.swing.api.Component;
63
import org.gvsig.tools.swing.api.ToolsSwingLocator;
64
import org.gvsig.tools.swing.api.ToolsSwingManager;
65
import org.gvsig.tools.swing.api.pickercontroller.PickerController;
66
import org.gvsig.tools.swing.api.script.ScriptSwingManager;
67
import org.gvsig.tools.swing.api.threadsafedialogs.ThreadSafeDialogsManager;
68
import org.gvsig.tools.swing.icontheme.IconTheme;
69

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

    
79
    private final ExpressionEvaluatorSwingManager manager;
80
    private GroupElement currentGroup;
81
    private PickerController<List<Script>> scriptPicker;
82
    private ScriptSwingManager.ScriptEditor scriptEditor;
83
    
84
    private final ExpressionBuilderConfig bulderConfig;
85
    private ElementsTreeModel treeModel;
86
    private ImageIcon defaultIconGroup;
87
    private ImageIcon defaultIconElement;
88
    private InfoPanel infoPanel;
89
    private AbstractAutomaticExpressionChecker automaticExpressionChecker;
90
    
91
    private static class InfoPanel implements Component {
92

    
93
        private final JEditorPane txtDescription;
94
        private final JScrollPane scrDescription;
95
        private final JTabbedPane tab;
96

    
97
        private final String labelDescription;
98
        private final String labelAdditionalPanel;
99
        private final JPanel pnlContainer;
100
        
101
        private final String defautltDescription;
102

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

    
136
        @Override
137
        public JComponent asJComponent() {
138
            this.txtDescription.setContentType("text/html");
139
            this.txtDescription.setText(this.description);
140
            this.txtDescription.setCaretPosition(0);
141

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

    
173
        public void repaint() {
174
            this.pnlContainer.removeAll();
175
            this.pnlContainer.add(this.asJComponent(), BorderLayout.CENTER);
176
            this.pnlContainer.revalidate();
177
            this.pnlContainer.repaint();
178
        }
179
    }
180

    
181
    private class ElementsTreeModel implements TreeModel {
182

    
183
        private final GroupElement root;
184
        private final HashSet<TreeModelListener> listeners;
185

    
186
        public ElementsTreeModel(GroupElement root) {
187
            this.root = root;
188
            this.listeners = new HashSet<>();
189
        }
190

    
191
        @Override
192
        public Object getRoot() {
193
            return this.root;
194
        }
195

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

    
220
        @Override
221
        public Object getChild(Object parent, int index) {
222
            List<Element> childs = getChilds((GroupElement) parent);
223
            Element child = childs.get(index);
224
            return child;
225
        }
226

    
227
        @Override
228
        public int getChildCount(Object parent) {
229
            List<Element> childs = getChilds((GroupElement) parent);
230
            return childs.size();
231
        }
232

    
233
        @Override
234
        public boolean isLeaf(Object node) {
235
            if( node instanceof GroupElement ) {
236
                return !((GroupElement) node).hasSubgroups();
237
            }
238
            return false;
239
        }
240

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

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

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

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

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

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

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

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

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

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

    
379
        this.pnlDescription.setLayout(new BorderLayout());
380
//        this.pnlDescription.setBackground(this.txtDescription.getBackground());
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
//                JPanel component = new JPanel();
396
//                JLabel text = new JLabel();
397
//                JLabel icon = new JLabel();
398
//                component.setLayout(new FlowLayout());
399
//                component.add(icon);
400
//                component.add(text);
401
//                component.setLayout(new GridBagLayout());
402
//                component.add(icon, new GridBagConstraints(0,0,0,0,0,0,GridBagConstraints.NORTH,GridBagConstraints.BOTH,new Insets(1,1,1,1),1,1));
403
//                component.add(text, new GridBagConstraints(1,0,0,0,0,0,GridBagConstraints.NORTH,GridBagConstraints.BOTH,new Insets(1,1,1,1),1,1));
404
                
405
                if( value instanceof Element ) {
406
                    Element element = (Element) value;
407
                    if( element.getIconName()==null ) {
408
                        if( element instanceof GroupElement ) {
409
                            icon.setIcon(defaultIconGroup);
410
                        } else {
411
                            icon.setIcon(defaultIconElement);
412
                        }
413
                    } else {
414
                        icon.setIcon(element.getIcon());
415
                    }
416
                    text.setText(element.getLabel());
417
                    text.setEnabled(element.isEnabled());
418
                } else {
419
                    icon.setIcon(null);
420
                    text.setText(Objects.toString(value, ""));
421
                }
422
                return component;
423
            }
424

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

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

    
628
        Dimension dim = this.getPreferredSize();
629
        this.spnlExpression.setDividerLocation(dim.height/5);
630
        this.spnlBottom.setDividerLocation(dim.width/3);
631
        this.spnlItem.setDividerLocation(dim.width/3);
632
    }
633

    
634
    private String removeCursorMark(String s) {
635
        if( s == null ) {
636
            return null;
637
        }
638
        s = s.replace("{{", "");
639
        s = s.replace("}}", "");
640
        return s;
641
    }
642

    
643
    @Override
644
    public void insertText(String text) {
645
        doInsert(text);
646
    }
647

    
648
    @Override
649
    public String getText() {
650
        return this.txtExpression.getText();
651
    }
652
    
653
    public void setText(String text) {
654
        this.txtExpression.setText(text);
655
    }
656
    
657
    private void doInsert(String s) {
658
        this.txtExpression.replaceSelection(s);
659
        String ss = this.txtExpression.getText();
660
        int start = ss.indexOf("{{");
661
        int end = ss.indexOf("}}");
662
        if (start > 0 && end > 0) {
663
            this.txtExpression.replaceRange("", end, end + 2);
664
            this.txtExpression.replaceRange("", start, start + 2);
665
            this.txtExpression.setSelectionStart(start);
666
            this.txtExpression.setSelectionEnd(end - 2);
667
        }
668
        this.txtExpression.requestFocusInWindow();
669
    }
670

    
671
    private void doInsert(Element element) {
672
        doInsert(element.getRenderedValue());
673
        element.used();
674
    }
675

    
676
    private void doFilter() {
677
        FilteredListModel model = (FilteredListModel) this.lstSimpleElement.getModel();
678
        model.setFilter(this.txtSimpleElementFilter.getText());
679
    }
680

    
681
    private void doSelectElement(Element element) {
682
//        if( !element.isEnabled() ) {
683
//            this.infoPanel.clean();
684
//        } else {
685
            this.infoPanel.setDescription(removeCursorMark(element.getDescription()));
686
            this.infoPanel.setAdditionalPanel(element.getAditionalPanel(this));
687
            this.infoPanel.repaint();
688
//        }        
689
    }
690

    
691
    private void updateSimpleElementsList(GroupElement group) {
692
        FilteredListModel model = new FilteredListModel();
693
        model.addElement("Loading...");
694
        this.currentGroup = group;
695
        this.txtGroupElement.setText(group.getName());
696
        this.txtSimpleElementFilter.setText("");
697
        this.infoPanel.clean();
698
        this.infoPanel.repaint();
699
        if (group instanceof SimpleElement) {
700
            this.btnGroupElementInsert.setEnabled(true);
701
        } else {
702
            this.btnGroupElementInsert.setEnabled(false);
703
        }
704
        this.lstSimpleElement.setEnabled(false);
705
        this.lstSimpleElement.setModel(model);
706

    
707
        Thread th = new Thread(new Runnable() {
708
            @Override
709
            public void run() {
710
                simpleElementsUpdater();
711
            }
712
        }, "ExpressionBuilderSimpleElementsUpdater");
713
        th.start();
714
    }
715

    
716
    private void simpleElementsUpdater() {
717
        final GroupElement group = this.currentGroup;
718
        final FilteredListModel model = new FilteredListModel();
719
        for (Element child : group) {
720
            if (group != this.currentGroup) {
721
                return;
722
            }
723
            if (child instanceof SimpleElement) {
724
                model.addElement(child);
725
            }
726
        }
727
        model.sort(true);
728
        SwingUtilities.invokeLater(new Runnable() {
729
            @Override
730
            public void run() {
731
                if (group != currentGroup) {
732
                    return;
733
                }
734
                if( group.hasMoreElements() ) {
735
                    lblSimpleElementsMsg.setText("More elements...");
736
                } else {
737
                    lblSimpleElementsMsg.setText("");
738
                }
739
                lstSimpleElement.setEnabled(true);
740
                lstSimpleElement.setModel(model);
741
            }
742
        });
743

    
744
    }
745

    
746
    @Override
747
    public Expression getExpression() {
748
        String phrase = this.txtExpression.getText();
749
        if (StringUtils.isEmpty(phrase)) {
750
            return null;
751
        }
752
        Expression expression = ExpressionEvaluatorLocator.getManager().createExpression();
753
        expression.setPhrase(phrase);
754
        Script script = ToolsLocator.getScriptManager().createScript("UserScript", "", "python");
755
        this.scriptEditor.fetch(script);
756
        if( !StringUtils.isEmpty(script.getCode()) ) {
757
            expression.setUserScript(script);
758
        }
759
        return expression;
760
    }
761

    
762
    @Override
763
    public void setExpression(Expression expression) {
764
        if( expression==null ) {
765
            this.txtExpression.setText("");
766
            try { this.scriptEditor.set(null); } catch(Exception ex) {}
767
            this.scriptPicker.set(null);
768
        } else {
769
            this.txtExpression.setText(expression.getPhrase());
770
            if( expression.getUserScript()!=null ) {
771
                this.scriptEditor.set(expression.getUserScript());
772
            }
773
            if( expression.getScripts()!=null ) {
774
                this.scriptPicker.set(expression.getScripts().toList());
775
            }
776
        }
777
    }
778

    
779
    @Override
780
    public Preferences getPreferences() {
781
        return this.bulderConfig.getPreferences();
782
    }
783
    
784
    @Override
785
    public List<Element> getElements() {
786
        return this.bulderConfig.getElements();
787
    }
788
    
789
    @Override
790
    public void addElement(Element element) {
791
        this.bulderConfig.addElement(element);
792
    }
793
    
794
    @Override
795
    public Collection<SymbolTable> getSymbolTables() {
796
        return this.bulderConfig.getSymbolTables();
797
    }
798
    
799
    @Override
800
    public void addSymbolTable(String name) {
801
        this.bulderConfig.addSymbolTable(name);
802
    }
803
    
804
    @Override
805
    public void addSymbolTable(SymbolTable symbolTable) {
806
        this.bulderConfig.addSymbolTable(symbolTable);
807
    }
808

    
809
    @Override
810
    public void removeAllSymbolTables() {
811
        this.bulderConfig.removeAllSymbolTables();
812
    }
813

    
814
    @Override
815
    public void removeSymbolTable(String name) {
816
        this.bulderConfig.removeSymbolTable(name);
817
    }
818

    
819
    @Override
820
    public SymbolTable getPreviewSymbolTable() {
821
        return this.bulderConfig.getPreviewSymbolTable();
822
    }
823

    
824
    @Override
825
    public void setPreviewSymbolTable(SymbolTable symbolTable) {
826
        this.bulderConfig.setPreviewSymbolTable(symbolTable);
827
    }
828
    
829
    @Override
830
    public JComponent asJComponent() {
831
        this.initializeTree();
832
        return this;
833
    }
834
    
835
    private void initializeTree() {
836
        if( this.treeModel == null ) {
837
            I18nManager i18n = ToolsLocator.getI18nManager();
838
            this.treeModel = new ElementsTreeModel( (GroupElement)
839
                    this.manager.createGroupElement(
840
                            i18n.getTranslation("_Elements"),
841
                            this.getElements()
842
                    ).setConfig(this));
843
            this.treeElements.setModel(this.treeModel);
844
        }
845
    }
846
    
847
    private void doSetTimeLimit() {
848
        ThreadSafeDialogsManager dialogs = ToolsSwingLocator.getThreadSafeDialogsManager();
849
        String s = dialogs.inputDialog(
850
                "Indicate the time limit in seconds for calculating the elements", 
851
                "Time limit", 
852
                JOptionPane.QUESTION_MESSAGE, 
853
                String.valueOf(this.bulderConfig.getPreferences().getSimpleElementsLimit())
854
        );
855
        if( StringUtils.isBlank(s) ) {
856
            return;
857
        }
858
        try {
859
            int n = Integer.parseInt(s);
860
            this.bulderConfig.getPreferences().setSimpleElementsLimit(n);
861
            this.treeModel.reload();
862
        } catch(Exception ex) {
863
            dialogs.messageDialog(
864
                "Invalid time limit '"+s+"'.", 
865
                "Time limit", 
866
                JOptionPane.WARNING_MESSAGE
867
            );                    
868
        }
869
    }
870

    
871
    private String load_description_from_resource() {
872
        String lang = Locale.getDefault().getLanguage();
873
        URL url = this.getClass().getResource("/org/gvsig/expressionevaluator/swing/jexpressionbuilder/"+lang+"/description.html");
874
        if( url == null ) {
875
            url = this.getClass().getResource("/org/gvsig/expressionevaluator/swing/jexpressionbuilder/en/description.html");
876
            if( url == null ) {
877
                return null;
878
            }
879
        }
880
        InputStream is = null;
881
        try {
882
            is = url.openStream();
883
            List<String> lines = IOUtils.readLines(is);
884
            return StringUtils.join(lines,  "\n");
885
        } catch (Exception ex) {
886
            return null;
887
        } finally {
888
            IOUtils.closeQuietly(is);
889
        }
890
    }
891
    
892
    @Override
893
    public void expandElement(Element element) {
894
        this.initializeTree();
895
        for (int i = 0; i < this.treeElements.getRowCount(); i++) {
896
            TreePath path = this.treeElements.getPathForRow(i);
897
            if( path.getLastPathComponent()==element ) {
898
                // FIXME: habria que expandir los padres hasta llegar a este.
899
                this.treeElements.expandPath(path);
900
                return;
901
            }
902
        }
903
    }
904
}