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

History | View | Annotate | Download (39.1 KB)

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

    
3
import java.awt.BorderLayout;
4
import java.awt.Dimension;
5
import java.awt.Point;
6
import java.awt.Toolkit;
7
import java.awt.datatransfer.Clipboard;
8
import java.awt.datatransfer.StringSelection;
9
import java.awt.event.ActionEvent;
10
import java.awt.event.ActionListener;
11
import java.awt.event.KeyAdapter;
12
import java.awt.event.KeyEvent;
13
import java.awt.event.MouseAdapter;
14
import java.awt.event.MouseEvent;
15
import java.io.InputStream;
16
import java.net.URL;
17
import java.util.ArrayList;
18
import java.util.Collection;
19
import java.util.HashSet;
20
import java.util.List;
21
import java.util.Locale;
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.Bookmark;
52
import org.gvsig.expressionevaluator.Bookmarks;
53
import org.gvsig.expressionevaluator.Expression;
54
import org.gvsig.expressionevaluator.ExpressionEvaluatorLocator;
55
import org.gvsig.expressionevaluator.ExpressionEvaluatorManager;
56
import org.gvsig.expressionevaluator.History;
57
import org.gvsig.expressionevaluator.SymbolTable;
58
import org.gvsig.expressionevaluator.swing.Element;
59
import org.gvsig.expressionevaluator.swing.Element.GroupElement;
60
import org.gvsig.expressionevaluator.swing.Element.SimpleElement;
61
import org.gvsig.expressionevaluator.swing.ExpressionBuilderConfig;
62
import org.gvsig.expressionevaluator.swing.ExpressionEvaluatorSwingManager;
63
import org.gvsig.expressionevaluator.swing.JExpressionBuilder;
64
import org.gvsig.tools.ToolsLocator;
65
import org.gvsig.tools.i18n.I18nManager;
66
import org.gvsig.tools.script.Script;
67
import org.gvsig.tools.swing.api.Component;
68
import org.gvsig.tools.swing.api.ToolsSwingLocator;
69
import org.gvsig.tools.swing.api.ToolsSwingManager;
70
import org.gvsig.tools.swing.api.pickercontroller.PickerController;
71
import org.gvsig.tools.swing.api.script.ScriptSwingManager;
72
import org.gvsig.tools.swing.api.threadsafedialogs.ThreadSafeDialogsManager;
73
import org.gvsig.tools.swing.api.windowmanager.Dialog;
74
import org.gvsig.tools.swing.api.windowmanager.WindowManager;
75
import org.gvsig.tools.swing.api.windowmanager.WindowManager_v2;
76
import org.gvsig.tools.swing.icontheme.IconTheme;
77

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

    
87
    private final ExpressionEvaluatorSwingManager manager;
88
    private Element currentElement;
89
    private PickerController<List<Script>> scriptPicker;
90
    private ScriptSwingManager.ScriptEditor scriptEditor;
91
    
92
    private final ExpressionBuilderConfig builderConfig;
93
    private ElementsTreeModel treeModel;
94
    private ImageIcon defaultIconGroup;
95
    private ImageIcon defaultIconElement;
96
    private InfoPanel infoPanel;
97
    private AbstractAutomaticExpressionChecker automaticExpressionChecker;
98
    
99
    private static class InfoPanel implements Component {
100

    
101
        private final JEditorPane txtDescription;
102
        private final JScrollPane scrDescription;
103
        private final JTabbedPane tab;
104

    
105
        private final String labelDescription;
106
        private final String labelAdditionalPanel;
107
        private final JPanel pnlContainer;
108
        
109
        private final String defautltDescription;
110

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

    
144
        @Override
145
        public JComponent asJComponent() {
146
            this.txtDescription.setContentType("text/html");
147
            this.txtDescription.setText(this.description);
148
            this.txtDescription.setCaretPosition(0);
149

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

    
181
        public void repaint() {
182
            this.pnlContainer.removeAll();
183
            this.pnlContainer.add(this.asJComponent(), BorderLayout.CENTER);
184
            this.pnlContainer.revalidate();
185
            this.pnlContainer.repaint();
186
        }
187
    }
188

    
189
    private class ElementsTreeModel implements TreeModel {
190

    
191
        private final GroupElement root;
192
        private final HashSet<TreeModelListener> listeners;
193

    
194
        public ElementsTreeModel(GroupElement root) {
195
            this.root = root;
196
            this.listeners = new HashSet<>();
197
        }
198

    
199
        @Override
200
        public Object getRoot() {
201
            return this.root;
202
        }
203

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

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

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

    
241
        @Override
242
        public boolean isLeaf(Object node) {
243
            return !(node instanceof GroupElement);
244
        }
245

    
246
        @Override
247
        public void valueForPathChanged(TreePath path, Object newValue) {
248
        }
249

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

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

    
262
        @Override
263
        public void removeTreeModelListener(TreeModelListener l) {
264
            this.listeners.remove(l);
265
        }
266

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

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

    
313
            @Override
314
            protected void setMessage(int mode, String text) {
315
                super.setMessage(mode, text); 
316
                lblMsg.setText("<html>"+StringUtils.abbreviate(text,100)+"</html>");
317
            }
318

    
319
            @Override
320
            protected void setPreview(Object value) {
321
                super.setPreview(value);
322
                lblMsg.setText("<html>"+StringUtils.abbreviate(this.getPreview(),100)+"</html>");
323
            }
324

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

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

    
384
        this.pnlDescription.setLayout(new BorderLayout());
385
//        this.pnlDescription.setBackground(this.txtDescription.getBackground());
386
        this.txtExpression.addCaretListener(new CaretListener() {
387
            @Override
388
            public void caretUpdate(CaretEvent e) {
389
                lblColumn.setText(Integer.toString(e.getDot()));
390
            }
391
        });
392
        this.treeElements.setRowHeight(0);
393
        this.treeElements.setCellRenderer(new DefaultTreeCellRenderer() {
394
            @Override
395
            public java.awt.Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
396
                JLabel component = (JLabel) super.getTreeCellRendererComponent(tree,value, selected, expanded, leaf, row, hasFocus);
397
                JLabel text = component;
398
                JLabel icon = component;
399

    
400
//                JPanel component = new JPanel();
401
//                JLabel text = new JLabel();
402
//                JLabel icon = new JLabel();
403
//                component.setLayout(new FlowLayout());
404
//                component.add(icon);
405
//                component.add(text);
406
//                component.setLayout(new GridBagLayout());
407
//                component.add(icon, new GridBagConstraints(0,0,0,0,0,0,GridBagConstraints.NORTH,GridBagConstraints.BOTH,new Insets(1,1,1,1),1,1));
408
//                component.add(text, new GridBagConstraints(1,0,0,0,0,0,GridBagConstraints.NORTH,GridBagConstraints.BOTH,new Insets(1,1,1,1),1,1));
409
                
410
                if( value instanceof Element ) {
411
                    Element element = (Element) value;
412
                    if( element.getIconName()==null ) {
413
                        if( element instanceof GroupElement ) {
414
                            icon.setIcon(defaultIconGroup);
415
                        } else {
416
                            icon.setIcon(defaultIconElement);
417
                        }
418
                    } else {
419
                        icon.setIcon(element.getIcon());
420
                    }
421
                    text.setText(element.getLabel());
422
                    text.setEnabled(element.isEnabled());
423
                } else {
424
                    icon.setIcon(null);
425
                    text.setText(Objects.toString(value, ""));
426
                }
427
                return component;
428
            }
429

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

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

    
651
        Dimension dim = this.getPreferredSize();
652
        this.spnlExpression.setDividerLocation(dim.height/5);
653
        this.spnlBottom.setDividerLocation(dim.width/3);
654
        this.spnlItem.setDividerLocation(dim.width/3);
655
    }
656

    
657
    private String removeCursorMark(String s) {
658
        if( s == null ) {
659
            return null;
660
        }
661
        s = s.replace("{{", "");
662
        s = s.replace("}}", "");
663
        return s;
664
    }
665

    
666
    @Override
667
    public void insertText(String text) {
668
        doInsert(text);
669
    }
670

    
671
    @Override
672
    public String getText() {
673
        return this.txtExpression.getText();
674
    }
675
    
676
    @Override
677
    public void setText(String text) {
678
        this.txtExpression.setText(text);
679
    }
680
    
681
    private void doInsert(String s) {
682
        this.txtExpression.replaceSelection(s);
683
        String ss = this.txtExpression.getText();
684
        int start = ss.indexOf("{{");
685
        int end = ss.indexOf("}}");
686
        if (start > 0 && end > 0) {
687
            this.txtExpression.replaceRange("", end, end + 2);
688
            this.txtExpression.replaceRange("", start, start + 2);
689
            this.txtExpression.setSelectionStart(start);
690
            this.txtExpression.setSelectionEnd(end - 2);
691
        }
692
        this.txtExpression.requestFocusInWindow();
693
    }
694

    
695
    private void doInsert(Element element) {
696
        doInsert(element.getRenderedValue());
697
        element.used();
698
    }
699

    
700
    private void doFilter() {
701
        FilteredListModel model = (FilteredListModel) this.lstSimpleElement.getModel();
702
        model.setFilter(this.txtSimpleElementFilter.getText());
703
    }
704

    
705
    private void doSelectElement(Element element) {
706
//        if( !element.isEnabled() ) {
707
//            this.infoPanel.clean();
708
//        } else {
709
            this.infoPanel.setDescription(removeCursorMark(element.getDescription()));
710
            this.infoPanel.setAdditionalPanel(element.getAditionalPanel(this));
711
            this.infoPanel.repaint();
712
//        }        
713
    }
714

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

    
731
        Thread th = new Thread(new Runnable() {
732
            @Override
733
            public void run() {
734
                simpleElementsUpdater();
735
            }
736
        }, "ExpressionBuilderSimpleElementsUpdater");
737
        th.start();
738
    }
739

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

    
770
    }
771

    
772
    @Override
773
    public Expression getExpression() {
774
        Expression expression = this.getExpressionWithOutHistory();
775
        ExpressionEvaluatorManager theManager = ExpressionEvaluatorLocator.getManager();
776
        theManager.getHistory().add(expression);
777
        return expression;
778
    }
779
    
780
    @Override
781
    public Expression getExpressionWithOutHistory() {
782
        String phrase = this.txtExpression.getText();
783
        if (StringUtils.isEmpty(phrase)) {
784
            return null;
785
        }
786
        Expression expression = ExpressionEvaluatorLocator.getManager().createExpression();
787
        expression.setPhrase(phrase);
788
        Script script = ToolsLocator.getScriptManager().createScript("UserScript", "", "python");
789
        this.scriptEditor.fetch(script);
790
        if( !StringUtils.isEmpty(script.getCode()) ) {
791
            expression.setUserScript(script);
792
        }
793
        return expression;
794
    }
795

    
796
    @Override
797
    public void setExpression(Expression expression) {
798
        if( expression==null ) {
799
            this.txtExpression.setText("");
800
            try { this.scriptEditor.set(null); } catch(Exception ex) {}
801
            this.scriptPicker.set(null);
802
        } else {
803
            this.txtExpression.setText(expression.getPhrase());
804
            if( expression.getUserScript()!=null ) {
805
                this.scriptEditor.set(expression.getUserScript());
806
            }
807
            if( expression.getScripts()!=null ) {
808
                this.scriptPicker.set(expression.getScripts().toList());
809
            }
810
        }
811
    }
812

    
813
    @Override
814
    public Preferences getPreferences() {
815
        return this.builderConfig.getPreferences();
816
    }
817
    
818
    @Override
819
    public List<Element> getElements() {
820
        return this.builderConfig.getElements();
821
    }
822
    
823
    @Override
824
    public void addElement(Element element) {
825
        this.builderConfig.addElement(element);
826
    }
827
    
828
    @Override
829
    public Collection<SymbolTable> getSymbolTables() {
830
        return this.builderConfig.getSymbolTables();
831
    }
832
    
833
    @Override
834
    public void addSymbolTable(String name) {
835
        this.builderConfig.addSymbolTable(name);
836
    }
837
    
838
    @Override
839
    public void addSymbolTable(SymbolTable symbolTable) {
840
        this.builderConfig.addSymbolTable(symbolTable);
841
    }
842

    
843
    @Override
844
    public void removeAllSymbolTables() {
845
        this.builderConfig.removeAllSymbolTables();
846
    }
847

    
848
    @Override
849
    public void removeSymbolTable(String name) {
850
        this.builderConfig.removeSymbolTable(name);
851
    }
852

    
853
    @Override
854
    public SymbolTable getPreviewSymbolTable() {
855
        return this.builderConfig.getPreviewSymbolTable();
856
    }
857

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

    
905
    private String load_description_from_resource() {
906
        String lang = Locale.getDefault().getLanguage();
907
        URL url = this.getClass().getResource("/org/gvsig/expressionevaluator/swing/jexpressionbuilder/"+lang+"/description.html");
908
        if( url == null ) {
909
            url = this.getClass().getResource("/org/gvsig/expressionevaluator/swing/jexpressionbuilder/en/description.html");
910
            if( url == null ) {
911
                return null;
912
            }
913
        }
914
        InputStream is = null;
915
        try {
916
            is = url.openStream();
917
            List<String> lines = IOUtils.readLines(is);
918
            return StringUtils.join(lines,  "\n");
919
        } catch (Exception ex) {
920
            return null;
921
        } finally {
922
            IOUtils.closeQuietly(is);
923
        }
924
    }
925
    
926
    @Override
927
    public void expandElement(Element element) {
928
        this.initializeTree();
929
        for (int i = 0; i < this.treeElements.getRowCount(); i++) {
930
            TreePath path = this.treeElements.getPathForRow(i);
931
            if( path.getLastPathComponent()==element ) {
932
                // FIXME: habria que expandir los padres hasta llegar a este.
933
                this.treeElements.expandPath(path);
934
                return;
935
            }
936
        }
937
    }
938
    
939
    private void doHistory() {
940
        I18nManager i18n = ToolsLocator.getI18nManager();
941
        ExpressionEvaluatorManager theManager = ExpressionEvaluatorLocator.getManager();
942
        JPopupMenu popup = new JPopupMenu();
943
        History history = theManager.getHistory();
944
        if( !history.isEmpty() ) {
945
            for (Expression expression : history) {
946
                popup.add(createHistoryMenuItem(expression));
947
            }
948
            popup.addSeparator();
949
        }
950
        JMenuItem showAllHistory = new JMenuItem(i18n.getTranslation("_Show_all_history"));
951
        showAllHistory.addActionListener(new ActionListener() {
952
            @Override
953
            public void actionPerformed(ActionEvent e) {
954
                doShowHistoryDialog();
955
            }
956
        });
957
        popup.add(showAllHistory);
958
        Point p = this.btnHistory.getLocationOnScreen();
959
        popup.show(this.btnHistory, 0, this.btnHistory.getHeight());
960
    }
961
    
962
    private JMenuItem createHistoryMenuItem(final Expression expression) {
963
        JMenuItem item = new JMenuItem(StringUtils.abbreviate(expression.getPhrase(), 45));
964
        item.addActionListener(new ActionListener() {
965
            @Override
966
            public void actionPerformed(ActionEvent e) {
967
                setExpression(expression);
968
            }
969
        });
970
        return item;
971
    }
972
    
973
    private void doShowHistoryDialog() {
974
        WindowManager_v2 winManager = (WindowManager_v2) ToolsSwingLocator.getWindowManager();
975
        final DefaultHistoryPanel panel = new DefaultHistoryPanel();
976
        final Dialog dialog = winManager.createDialog(
977
                panel,
978
                "History",
979
                null, 
980
                WindowManager_v2.BUTTONS_OK_CANCEL
981
        );
982
        dialog.addActionListener(new ActionListener() {
983
            @Override
984
            public void actionPerformed(ActionEvent e) {
985
                if( dialog.getAction()!=WindowManager_v2.BUTTON_OK ) {
986
                    return;
987
                }
988
                setExpression(panel.getExpression());
989
            }
990
        });
991
        dialog.show(WindowManager.MODE.DIALOG);
992
    }
993

    
994
    private void doBookmarks() {
995
        I18nManager i18n = ToolsLocator.getI18nManager();
996
        ExpressionEvaluatorManager theManager = ExpressionEvaluatorLocator.getManager();
997
        JPopupMenu popup = new JPopupMenu();
998
        JMenuItem addToBookmarks = new JMenuItem(i18n.getTranslation("_Add_to_bookmarks"));
999
        addToBookmarks.addActionListener(new ActionListener() {
1000
            @Override
1001
            public void actionPerformed(ActionEvent e) {
1002
                doShowBookmarksDialog(getExpressionWithOutHistory());
1003
            }
1004
        });
1005
        popup.add(addToBookmarks);
1006
        Bookmarks bookmarks = theManager.getBookmarks();
1007
        if( !bookmarks.isEmpty() ) {
1008
            popup.addSeparator();
1009
            for (Bookmark bookmark : bookmarks) {
1010
                popup.add(createBookmarkMenuItem(bookmark));
1011
            }
1012
            popup.addSeparator();
1013
            JMenuItem showAllBookmarks = new JMenuItem(i18n.getTranslation("_Show_all_bookmarks"));
1014
            showAllBookmarks.addActionListener(new ActionListener() {
1015
                @Override
1016
                public void actionPerformed(ActionEvent e) {
1017
                    doShowBookmarksDialog(null);
1018
                }
1019
            });
1020
            popup.add(showAllBookmarks);
1021
        }
1022
        Point p = this.btnBookmarks.getLocationOnScreen();
1023
        popup.show(this.btnBookmarks, 0, this.btnBookmarks.getHeight());
1024
    }
1025
    
1026
    private JMenuItem createBookmarkMenuItem(final Bookmark bookmark) {
1027
        JMenuItem item = new JMenuItem(StringUtils.abbreviate(bookmark.getName(), 45));
1028
        item.addActionListener(new ActionListener() {
1029
            @Override
1030
            public void actionPerformed(ActionEvent e) {
1031
                setExpression(bookmark.getValue());
1032
            }
1033
        });
1034
        return item;
1035
    }
1036
    
1037
    private void doShowBookmarksDialog(Expression expression) {
1038
        WindowManager_v2 winManager = (WindowManager_v2) ToolsSwingLocator.getWindowManager();
1039
        final DefaultBookmarksPanel panel = new DefaultBookmarksPanel(expression);
1040
        final Dialog dialog = winManager.createDialog(
1041
                panel,
1042
                "Bookmarks",
1043
                null, 
1044
                WindowManager_v2.BUTTONS_OK_CANCEL
1045
        );
1046
        dialog.addActionListener(new ActionListener() {
1047
            @Override
1048
            public void actionPerformed(ActionEvent e) {
1049
                if( dialog.getAction()!=WindowManager_v2.BUTTON_OK ) {
1050
                    return;
1051
                }
1052
                Bookmark bookmark = panel.getCurrentBookmark();
1053
                if( bookmark!=null ) {
1054
                    setExpression(bookmark.getValue());
1055
                }
1056
            }
1057
        });
1058
        dialog.show(WindowManager.MODE.DIALOG);
1059
    }
1060
}