Statistics
| Revision:

gvsig-scripting / org.gvsig.scripting / trunk / org.gvsig.scripting / org.gvsig.scripting.swing / org.gvsig.scripting.swing.impl / src / main / java / org / gvsig / scripting / swing / impl / DefaultJScriptingBrowser.java @ 1200

History | View | Annotate | Download (16.3 KB)

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

    
3
import java.awt.Color;
4
import java.awt.Component;
5
import java.awt.Graphics;
6
import java.awt.GridLayout;
7
import java.awt.event.ActionEvent;
8
import java.awt.event.ActionListener;
9
import java.awt.event.KeyEvent;
10
import java.awt.event.MouseEvent;
11
import java.awt.event.MouseListener;
12
import java.net.URL;
13
import java.util.ArrayList;
14
import java.util.Enumeration;
15
import java.util.HashMap;
16
import java.util.Iterator;
17
import java.util.List;
18
import java.util.Map;
19
import javax.swing.AbstractAction;
20

    
21
import javax.swing.Icon;
22
import javax.swing.ImageIcon;
23
import javax.swing.JComponent;
24
import javax.swing.JLabel;
25
import javax.swing.JPanel;
26
import javax.swing.JScrollPane;
27
import javax.swing.JTree;
28
import javax.swing.KeyStroke;
29
import javax.swing.UIManager;
30
import javax.swing.event.TreeModelEvent;
31
import javax.swing.event.TreeModelListener;
32
import javax.swing.event.TreeSelectionEvent;
33
import javax.swing.event.TreeSelectionListener;
34
import javax.swing.tree.TreeCellRenderer;
35
import javax.swing.tree.TreeModel;
36
import javax.swing.tree.TreePath;
37
import javax.swing.tree.TreeSelectionModel;
38
import org.apache.commons.io.FilenameUtils;
39
import org.gvsig.scripting.ScriptingExternalFile;
40

    
41
import org.gvsig.scripting.ScriptingFolder;
42
import org.gvsig.scripting.ScriptingManager;
43
import org.gvsig.scripting.ScriptingUnit;
44
import org.gvsig.scripting.swing.api.JScriptingBrowser;
45
import static org.gvsig.scripting.swing.api.JScriptingBrowser.DEFAULT_ACTION;
46
import static org.gvsig.scripting.swing.api.JScriptingBrowser.SELECTION_ACTION;
47
import org.gvsig.scripting.swing.api.ScriptingUIManager;
48
import org.gvsig.tools.swing.api.ActionListenerSupport;
49
import org.gvsig.tools.swing.api.ToolsSwingLocator;
50
import org.slf4j.LoggerFactory;
51
import org.slf4j.Logger;
52

    
53
public class DefaultJScriptingBrowser extends JPanel implements JScriptingBrowser {
54

    
55
    private static final Logger logger = LoggerFactory.getLogger(DefaultJScriptingBrowser.class);
56
    private static final long serialVersionUID = 3140698910497806258L;
57

    
58
    protected ScriptingUIManager uimanager;
59
    protected ScriptingManager manager;
60
    protected TreeModel treeModel;
61
    protected JTree tree;
62
    protected ScriptingFolder root;
63
    protected ActionListenerSupport actionlisteners = null;
64
    private final boolean foldersOnly;
65

    
66
    public static class DefaultBrowserActionEvent extends ActionEvent implements BrowserActionEvent {
67

    
68
        /**
69
         *
70
         */
71
        private static final long serialVersionUID = -1474410768278633364L;
72
        private ScriptingUnit unit = null;
73

    
74
        public DefaultBrowserActionEvent(Object source, int id, String command,
75
                ScriptingUnit unit) {
76
            super(source, id, command);
77
            this.unit = unit;
78
        }
79

    
80
        @Override
81
        public ScriptingUnit getUnit() {
82
            return this.unit;
83
        }
84
    }
85

    
86
    class ScriptingFolderTreeModel implements TreeModel {
87

    
88
        protected final ScriptingFolder root;
89

    
90
        protected final List<TreeModelListener> listeners = new ArrayList();
91

    
92
        public ScriptingFolderTreeModel(ScriptingFolder root) {
93
            this.root = root;
94
        }
95

    
96
        @Override
97
        public Object getRoot() {
98
            return root;
99
        }
100

    
101
        @Override
102
        public Object getChild(Object parent, int index) {
103
            ScriptingFolder folder = (ScriptingFolder) parent;
104
            List<ScriptingUnit> children = folder.getUnits();
105
            return children.get(index);
106
        }
107

    
108
        @Override
109
        public int getChildCount(Object parent) {
110
            if (!(parent instanceof ScriptingFolder)) {
111
                return 0;
112
            }
113
            ScriptingFolder folder = (ScriptingFolder) parent;
114
            return folder.getUnits().size();
115
        }
116

    
117
        @Override
118
        public boolean isLeaf(Object node) {
119
            return !(node instanceof ScriptingFolder);
120
        }
121

    
122
        @Override
123
        public int getIndexOfChild(Object parent, Object child) {
124
            String childPath = ((ScriptingUnit) child).getFile().getAbsolutePath();
125
            ScriptingFolder folder = (ScriptingFolder) parent;
126
            List<ScriptingUnit> children = folder.getUnits();
127
            for (int i = 0; i < children.size(); i++) {
128
                ScriptingUnit aChild = children.get(i);
129
                if (aChild.getFile().getAbsolutePath().equals(childPath)) {
130
                    return i;
131
                }
132
            }
133
            return -1;
134
        }
135

    
136
        @Override
137
        public void valueForPathChanged(TreePath path, Object value) {
138
        }
139

    
140
        @Override
141
        public void addTreeModelListener(TreeModelListener listener) {
142
            listeners.add(listener);
143
        }
144

    
145
        @Override
146
        public void removeTreeModelListener(TreeModelListener listener) {
147
            listeners.remove(listener);
148
        }
149

    
150
        public void reload() {
151
            TreeModelEvent event = new TreeModelEvent(this, new TreePath(this.root));
152
            Iterator<TreeModelListener> iterator = listeners.iterator();
153
            TreeModelListener listener;
154
            while (iterator.hasNext()) {
155
                listener = iterator.next();
156
                listener.treeStructureChanged(event);
157
            }
158
        }
159
    }
160

    
161
    class ScriptingFolderTreeModelFoldersOnly extends ScriptingFolderTreeModel {
162

    
163
        public ScriptingFolderTreeModelFoldersOnly(ScriptingFolder root) {
164
            super(root);
165
        }
166

    
167
        @Override
168
        public Object getChild(Object parent, int index) {
169
            ScriptingFolder folder = (ScriptingFolder) parent;
170
            List<ScriptingFolder> children = folder.getUnitFolders();
171
            return children.get(index);
172
        }
173

    
174
        @Override
175
        public int getChildCount(Object parent) {
176
            if (!(parent instanceof ScriptingFolder)) {
177
                return 0;
178
            }
179
            ScriptingFolder folder = (ScriptingFolder) parent;
180
            return folder.getUnitFolders().size();
181
        }
182

    
183
        @Override
184
        public int getIndexOfChild(Object parent, Object child) {
185
            String childPath = ((ScriptingFolder) child).getFile().getAbsolutePath();
186
            ScriptingFolder folder = (ScriptingFolder) parent;
187
            List<ScriptingFolder> children = folder.getUnitFolders();
188
            for (int i = 0; i < children.size(); i++) {
189
                ScriptingUnit aChild = children.get(i);
190
                if (aChild.getFile().getAbsolutePath().equals(childPath)) {
191
                    return i;
192
                }
193
            }
194
            return -1;
195
        }
196

    
197
    }
198

    
199
    public DefaultJScriptingBrowser(ScriptingUIManager uimanager,
200
            ScriptingFolder root) {
201
        this(uimanager, root, false);
202
    }
203

    
204
    public DefaultJScriptingBrowser(ScriptingUIManager uimanager,
205
            ScriptingFolder root, boolean foldersOnly) {
206
        super(new GridLayout(1, 2));
207
        this.actionlisteners = ToolsSwingLocator.getToolsSwingManager().createActionListenerSupport();
208
        this.foldersOnly = foldersOnly;
209
        this.uimanager = uimanager;
210
        this.manager = uimanager.getManager();
211
        this.root = root;
212
        this.makeUI();
213
    }
214

    
215
    @Override
216
    public JComponent asJComponent() {
217
        return this;
218
    }
219

    
220
    public void refresh() {
221
        Enumeration<TreePath> x = tree.getExpandedDescendants(new TreePath(treeModel.getRoot()));
222
        ((ScriptingFolderTreeModel) this.treeModel).reload();
223
        if (x != null) {
224
            while (x.hasMoreElements()) {
225
                try {
226
                    TreePath treePath = (TreePath) x.nextElement();
227
                    tree.expandPath(treePath);
228
                } catch(Throwable th) {
229
                    
230
                }
231
            }
232
        }        
233
    }
234

    
235
    
236
    @Override
237
    public ScriptingManager getManager() {
238
        return this.manager;
239
    }
240

    
241
    @Override
242
    public ScriptingFolder getRoot() {
243
        return this.root;
244
    }
245

    
246
    @Override
247
    public void addActionListener(ActionListener actionlistener) {
248
        this.actionlisteners.addActionListener(actionlistener);
249
    }
250

    
251
    private void makeUI() {
252
        if (this.foldersOnly) {
253
            treeModel = new ScriptingFolderTreeModelFoldersOnly(root);
254
        } else {
255
            treeModel = new ScriptingFolderTreeModel(root);
256
        }
257

    
258
        tree = new JTree(treeModel);
259
        tree.setCellRenderer(new IconCellRenderer());
260
        tree.setEditable(false);
261
        tree.setShowsRootHandles(true);
262
        tree.getSelectionModel().setSelectionMode(
263
                TreeSelectionModel.SINGLE_TREE_SELECTION);
264

    
265
        tree.addTreeSelectionListener(new TreeSelectionListener() {
266
            @Override
267
            public void valueChanged(TreeSelectionEvent e) {
268
                JTree tree = (JTree) e.getSource();
269
                if (!tree.isSelectionEmpty()) {
270
                    fireSelectAction(tree.getSelectionPath());
271
                }
272
            }
273
        });
274
        tree.addMouseListener(new MouseListener() {
275
            @Override
276
            public void mouseClicked(MouseEvent arg0) {
277
                if (arg0.getClickCount() == 2) {
278
                    JTree tree = (JTree) arg0.getSource();
279
                    if (!tree.isSelectionEmpty()) {
280
                        fireDefaultAction(tree.getSelectionPath());
281
                    }
282
                }
283
            }
284

    
285
            @Override
286
            public void mouseEntered(MouseEvent arg0) {
287
            }
288

    
289
            @Override
290
            public void mouseExited(MouseEvent arg0) {
291
            }
292

    
293
            @Override
294
            public void mousePressed(MouseEvent arg0) {
295
            }
296

    
297
            @Override
298
            public void mouseReleased(MouseEvent arg0) {
299
            }
300
        });
301
        tree.getActionMap().put(
302
                KeyStroke.getKeyStroke("+"),
303
                new ExpandSelectedNodeAction()
304
        );
305
        tree.getActionMap().put(
306
                KeyStroke.getKeyStroke("SPACE"),
307
                new ExpandSelectedNodeAction()
308
        );
309
        tree.getActionMap().put(
310
                KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0),
311
                new EnterAction()
312
        );
313
        
314
        JScrollPane scrollPane = new JScrollPane(tree);
315
        add(scrollPane);
316
    }
317

    
318
    @Override
319
    public TreePath getSelectionPath() {
320
        return this.tree.getSelectionPath();
321
    }
322
    
323
    @Override
324
    public void setSelectionPath(TreePath path) {
325
        if( path == null ) {
326
            this.tree.clearSelection();
327
        } else {
328
            this.tree.setSelectionPath(path);
329
        }
330
    }
331
    
332
    @Override
333
    public ScriptingUnit getSelectedNode() {
334
        ScriptingUnit unit;
335
        if (tree.getSelectionPath() != null) {
336
            unit = (ScriptingUnit) tree.getSelectionPath().getLastPathComponent();
337
        } else {
338
            unit = (ScriptingUnit) this.treeModel.getRoot();
339
        }
340
        return unit;
341
    }
342

    
343
    private void fireDefaultAction(TreePath path) {
344
        ScriptingUnit unit = (ScriptingUnit) path.getLastPathComponent();
345
        unit.reload();
346
        ActionEvent ae = new DefaultBrowserActionEvent(
347
                this,
348
                DEFAULT_ACTION,
349
                "default",
350
                unit
351
        );
352
        this.actionlisteners.fireActionEvent(ae);
353
    }
354

    
355
    private void fireSelectAction(TreePath path) {
356
        ScriptingUnit unit = (ScriptingUnit) path.getLastPathComponent();
357
        ActionEvent ae = new DefaultJScriptingBrowser.DefaultBrowserActionEvent(
358
                this,
359
                SELECTION_ACTION,
360
                "select",
361
                unit
362
        );
363
        this.actionlisteners.fireActionEvent(ae);
364
    }
365

    
366
    private class EnterAction extends AbstractAction {
367
        private static final long serialVersionUID = -3673546098243190397L;
368

    
369
        @Override
370
        public void actionPerformed(ActionEvent ae) {
371
            TreePath selected = tree.getSelectionPath();
372
            fireDefaultAction(selected);
373
        }
374
        
375
    }
376

    
377
    private class ExpandSelectedNodeAction extends AbstractAction {
378
        private static final long serialVersionUID = -4121272513454221967L;
379

    
380
        @Override
381
        public void actionPerformed(ActionEvent ae) {
382
            try {
383
                TreePath selected = tree.getSelectionPath();
384
                if( tree.isCollapsed(selected) ) {
385
                    tree.expandPath(selected);
386
                } else {
387
                    tree.collapsePath(selected);
388
                }
389
            } catch(Throwable th) {
390
                // Do nothing, ignore errors
391
            }
392
        }
393
        
394
    }
395
    
396
    private class IconCellRenderer extends JLabel implements TreeCellRenderer {
397

    
398
        /**
399
         *
400
         */
401
        private static final long serialVersionUID = 1L;
402
        protected Color m_textSelectionColor;
403
        protected Color m_textNonSelectionColor;
404
        protected Color m_bkSelectionColor;
405
        protected Color m_bkNonSelectionColor;
406
        protected Color m_borderSelectionColor;
407

    
408
        protected boolean m_selected;
409

    
410
        public IconCellRenderer() {
411
            super();
412
            m_textSelectionColor = UIManager
413
                    .getColor("Tree.selectionForeground");
414
            m_textNonSelectionColor = UIManager.getColor("Tree.textForeground");
415
            m_bkSelectionColor = UIManager.getColor("Tree.selectionBackground");
416
            m_bkNonSelectionColor = UIManager.getColor("Tree.textBackground");
417
            m_borderSelectionColor = UIManager
418
                    .getColor("Tree.selectionBorderColor");
419
            setOpaque(false);
420
        }
421

    
422
        private final Map<String, ImageIcon> icons = new HashMap<>();
423

    
424
        private ImageIcon getIcon(String iconName) {
425
            ImageIcon img = this.icons.get(iconName);
426
            if (img == null) {
427
                img = uimanager.getIcon(iconName);
428
                this.icons.put(iconName, img);
429
            }
430
            return img;
431
        }
432

    
433
        private ImageIcon getExpandedIcon(ScriptingUnit unit) {
434
            if( unit instanceof ScriptingExternalFile) {
435
              ScriptingExternalFile extfile = (ScriptingExternalFile) unit;
436
              String ext = FilenameUtils.getExtension(extfile.getExternalFile().getName());
437
              ClassLoader loader = this.getClass().getClassLoader();
438
              URL res = loader.getResource("org/gvsig/scripting/i18n/images/16x16/extensions/"+ext+"-icon-16x16.png");
439
              if( res!=null ) {
440
                return new ImageIcon(res);
441
              }
442
            }
443
            return getIcon(unit.getIconNames()[1]);
444
        }
445

    
446
        private ImageIcon getCollapsedIcon(ScriptingUnit unit) {
447
            if( unit instanceof ScriptingExternalFile) {
448
              ScriptingExternalFile extfile = (ScriptingExternalFile) unit;
449
              String ext = FilenameUtils.getExtension(extfile.getExternalFile().getName());
450
              ClassLoader loader = this.getClass().getClassLoader();
451
              URL res = loader.getResource("org/gvsig/scripting/images/16x16/extensions/"+ext+"-icon-16x16.png");
452
              if( res!=null ) {
453
                return new ImageIcon(res);
454
              }
455
            }
456
            return getIcon(unit.getIconNames()[0]);
457
        }
458

    
459
        @Override
460
        public Component getTreeCellRendererComponent(JTree tree, Object value,
461
                boolean sel, boolean expanded, boolean leaf, int row,
462
                boolean hasFocus) {
463
            ScriptingUnit unit = (ScriptingUnit) value;
464
            setText(unit.getName());
465
            if (expanded) {
466
                setIcon(this.getExpandedIcon(unit));
467
            } else {
468
                setIcon(this.getCollapsedIcon(unit));
469
            }
470

    
471
            setFont(tree.getFont());
472
            setForeground(sel ? m_textSelectionColor : m_textNonSelectionColor);
473
            setBackground(sel ? m_bkSelectionColor : m_bkNonSelectionColor);
474
            m_selected = sel;
475
            return this;
476
        }
477

    
478
        @Override
479
        public void paintComponent(Graphics g) {
480
            Color bColor = getBackground();
481
            Icon icon = getIcon();
482

    
483
            g.setColor(bColor);
484
            int offset = 0;
485
            if (icon != null && getText() != null) {
486
                offset = (icon.getIconWidth() + getIconTextGap());
487
            }
488
            g.fillRect(offset, 0, getWidth() - 1 - offset, getHeight() - 1);
489

    
490
            if (m_selected) {
491
                g.setColor(m_borderSelectionColor);
492
                g.drawRect(offset, 0, getWidth() - 1 - offset, getHeight() - 1);
493
            }
494
            super.paintComponent(g);
495
        }
496
    }
497

    
498
}