Statistics
| Revision:

gvsig-educa / org.gvsig.educa.portableview / trunk / org.gvsig.educa.portableview / org.gvsig.educa.portableview.swing / org.gvsig.educa.portableview.swing.impl / src / main / java / org / gvsig / educa / portableview / swing / impl / viewer / DefaultPortableViewToc.java @ 267

History | View | Annotate | Download (20.4 KB)

1
/* gvSIG. Geographic Information System of the Valencian Government
2
 *
3
 * Copyright (C) 2007-2008 Infrastructures and Transports Department
4
 * of the Valencian Government (CIT)
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 2
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 */
22
package org.gvsig.educa.portableview.swing.impl.viewer;
23

    
24
import java.awt.BorderLayout;
25
import java.awt.Dimension;
26
import java.awt.Image;
27
import java.awt.Rectangle;
28
import java.awt.event.MouseEvent;
29
import java.awt.event.MouseListener;
30
import java.util.ArrayList;
31
import java.util.Arrays;
32
import java.util.List;
33

    
34
import javax.swing.JComponent;
35
import javax.swing.JPanel;
36
import javax.swing.JScrollPane;
37
import javax.swing.JTree;
38
import javax.swing.SwingUtilities;
39
import javax.swing.event.TreeSelectionEvent;
40
import javax.swing.event.TreeSelectionListener;
41
import javax.swing.tree.DefaultMutableTreeNode;
42
import javax.swing.tree.DefaultTreeModel;
43
import javax.swing.tree.TreePath;
44
import javax.swing.tree.TreeSelectionModel;
45

    
46
import org.gvsig.educa.portableview.swing.impl.viewer.TocTreeNode.TYPE;
47
import org.gvsig.educa.portableview.swing.PortableViewSwingLocator;
48
import org.gvsig.educa.portableview.swing.PortableViewSwingManager;
49
import org.gvsig.educa.portableview.swing.viewer.PortableViewToc;
50
import org.gvsig.educa.portableview.swing.viewer.PortableViewTocImageProvider;
51
import org.gvsig.educa.portableview.swing.viewer.PortableViewViewer;
52
import org.gvsig.fmap.mapcontext.MapContext;
53
import org.gvsig.fmap.mapcontext.layers.FLayer;
54
import org.gvsig.fmap.mapcontext.layers.FLayers;
55
import org.gvsig.fmap.mapcontext.layers.LayerEvent;
56
import org.gvsig.fmap.mapcontext.layers.LayerListener;
57
import org.gvsig.fmap.mapcontext.layers.operations.Classifiable;
58
import org.gvsig.fmap.mapcontext.layers.operations.IHasImageLegend;
59
import org.gvsig.fmap.mapcontext.layers.operations.LayerCollection;
60
import org.gvsig.fmap.mapcontext.layers.operations.SingleLayer;
61
import org.gvsig.fmap.mapcontext.rendering.legend.IClassifiedLegend;
62
import org.gvsig.fmap.mapcontext.rendering.legend.ILegend;
63
import org.gvsig.fmap.mapcontext.rendering.legend.ISingleSymbolLegend;
64
import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
65
import org.gvsig.fmap.swing.toc.TOCFactory;
66
import org.gvsig.fmap.swing.toc.event.ActiveLayerChangeEventListener;
67
import org.gvsig.fmap.swing.toc.event.LayerActionEventListener;
68
import org.gvsig.fmap.swing.toc.event.LegendActionEventListener;
69
import org.gvsig.tools.dynobject.DynObject;
70
import org.gvsig.tools.service.Manager;
71

    
72
/**
73
 * <p>
74
 * Default implementation of {@link PortableViewToc}
75
 * </p>
76
 *
77
 * @author gvSIG Team
78
 * @version $Id$
79
 *
80
 */
81
public class DefaultPortableViewToc extends JPanel implements PortableViewToc,
82
    LayerListener, TreeSelectionListener {
83

    
84
    /**
85
     *
86
     */
87
    private static final long serialVersionUID = 3761640139439674486L;
88

    
89
    @SuppressWarnings("unused")
90
    private static final org.slf4j.Logger LOG = org.slf4j.LoggerFactory
91
        .getLogger(DefaultPortableViewToc.class);
92

    
93
    private static final FLayer[] EMPTY_SELECTION = new FLayer[0];
94

    
95
    private PortableViewViewer viewer;
96

    
97
    private boolean initialized;
98

    
99
    private JTree tree;
100

    
101
    private FLayers rootLayer;
102

    
103
    private TocTreeNode rootNode;
104

    
105
    private DefaultTreeModel treeModel;
106

    
107
    private PortableViewTocImageProvider imageProvider;
108

    
109
    private TocTreeCellRenderer cellRenderer;
110

    
111
    private boolean internalSelectionChanging;
112

    
113
    private final PortableViewSwingManager swingManager;
114

    
115
    public DefaultPortableViewToc() {
116
        swingManager = PortableViewSwingLocator.getSwingManager();
117
        initialized = false;
118
        imageProvider = swingManager.getDefaultTocImageProvider();
119
    }
120

    
121
    public void setImageProvider(PortableViewTocImageProvider imageProvider) {
122
        this.imageProvider = imageProvider;
123

    
124
        if (cellRenderer != null) {
125
            cellRenderer.setImageProvider(imageProvider);
126
        }
127
    }
128

    
129
    /**
130
     * Load tree model from mapContext
131
     */
132
    private void loadTreeModel() {
133
        rootLayer = getMapContext().getLayers();
134
        // rootNode = new LayerTreeNode(rootLayer);
135
        // rootLayer.addLayerCollectionListener(this);
136
        loadLayerNode(rootLayer, null);
137
        treeModel = new DefaultTreeModel(rootNode);
138
        tree.setModel(treeModel);
139
        tree.invalidate();
140
        tree.getSelectionModel().addTreeSelectionListener(this);
141
    }
142

    
143
    /**
144
     * Load a layer Node
145
     *
146
     * @param layer
147
     * @param parent
148
     */
149
    private void loadLayerNode(FLayer layer, TocTreeNode parent) {
150
        layer.addLayerListener(this);
151
        TocTreeNode node;
152
        if (layer instanceof LayerCollection) {
153
            LayerCollection collection = (LayerCollection) layer;
154
            node = new TocTreeNode((LayerCollection) layer);
155
            // collection.addLayerCollectionListener(this);
156
            for (int i = collection.getLayersCount(); i > 0; i--) {
157
                loadLayerNode(collection.getLayer(i-1), node);
158
            }
159
            if (parent == null) {
160
                rootNode = node;
161
            } else {
162
                parent.add(node);
163
            }
164

    
165
        } else {
166
            loadSingleLayerNode((SingleLayer) layer, parent);
167
        }
168

    
169
    }
170

    
171
    private void loadSingleLayerNode(SingleLayer layer, TocTreeNode parent) {
172
        TocTreeNode node;
173
        if (layer instanceof Classifiable) {
174
            Classifiable classifLayer = (Classifiable) layer;
175
            if (classifLayer.getLegend() != null) {
176
                loadLayerWithLegendNode(layer, classifLayer.getLegend(), parent);
177
                return;
178
            }
179
        }
180
        if (layer instanceof IHasImageLegend) {
181
            Image imgLegend = ((IHasImageLegend) layer).getImageLegend();
182
            loadLayerWithImageLegendNode(layer, imgLegend, parent);
183
            return;
184
        }
185
        node = new TocTreeNode(layer);
186
        parent.add(node);
187
    }
188

    
189
    /**
190
     * @param layer
191
     * @param imgLegend
192
     * @param parent
193
     */
194
    private void loadLayerWithImageLegendNode(SingleLayer layer,
195
        Image imgLegend, TocTreeNode parent) {
196
        TocTreeNode node;
197
        if (imgLegend == null) {
198
            node = new TocTreeNode(layer);
199
        } else {
200
            node = new TocTreeNode(layer, imgLegend);
201
            TocTreeNode legendNode = new TocTreeNode(imgLegend, layer);
202
            node.add(legendNode);
203
        }
204
        parent.add(node);
205
    }
206

    
207
    /**
208
     * @param layer
209
     * @param legend
210
     * @param parent
211
     */
212
    private void loadLayerWithLegendNode(SingleLayer layer, ILegend legend,
213
        TocTreeNode parent) {
214
        TocTreeNode node;
215
        ISymbol defSymbol = legend.getDefaultSymbol();
216
        if (legend instanceof IClassifiedLegend) {
217
            node = new TocTreeNode(layer, true);
218
            IClassifiedLegend cl = (IClassifiedLegend) legend;
219
            String[] descriptions = cl.getDescriptions();
220
            ISymbol[] symbols = cl.getSymbols();
221

    
222
            TocTreeNode symNode;
223
            for (int j = 0; j < descriptions.length; j++) {
224
                symNode = new TocTreeNode(symbols[j], descriptions[j], layer);
225
                node.add(symNode);
226
            }
227
        } else
228
            if (legend instanceof ISingleSymbolLegend && defSymbol != null) {
229
                node = new TocTreeNode(layer, true);
230

    
231
                TocTreeNode symNode =
232
                    new TocTreeNode(defSymbol, defSymbol.getDescription(),
233
                        layer);
234
                node.add(symNode);
235

    
236
            } else {
237
                node = new TocTreeNode(layer, false);
238
            }
239
        parent.add(node);
240
    }
241

    
242
    private List<TocTreeNode> getNodesFromType(TYPE... types) {
243
        List<TocTreeNode> nodesFound = new ArrayList<TocTreeNode>();
244
        getNodesFromType(rootNode, nodesFound, types);
245

    
246
        return nodesFound;
247
    }
248

    
249
    private void getNodesFromType(TocTreeNode node,
250
        List<TocTreeNode> nodesFound, TYPE... types) {
251
        for (TYPE type : types) {
252
            if (node.getType() == type) {
253
                nodesFound.add(node);
254
            }
255
        }
256
        for (int index = 0; index < node.getChildCount(); index++) {
257
            getNodesFromType((TocTreeNode) node.getChildAt(index), nodesFound,
258
                types);
259
        }
260
    }
261

    
262
    /** {@inheridDoc} */
263
    public JComponent getSwingComponent() {
264
        if (viewer == null) {
265
            throw new IllegalStateException("Viewer not set yet");
266
        }
267
        return this;
268
    }
269

    
270
    /** {@inheridDoc} */
271
    public FLayer[] getSelectedLayers() {
272
        if (viewer == null) {
273
            throw new IllegalStateException("Viewer not set yet");
274
        }
275

    
276
        List<FLayer> selectedLayers = new ArrayList<FLayer>();
277
        TocTreeNode node;
278
        TreePath[] paths = tree.getSelectionPaths();
279

    
280
        if (paths != null && paths.length > 0) {
281
            for (TreePath path : paths) {
282
                node = (TocTreeNode) path.getLastPathComponent();
283
                if (node.isLayer()) {
284
                    selectedLayers.add(node.getLayer());
285
                }
286
            }
287
        } else {
288
            return EMPTY_SELECTION;
289
        }
290

    
291
        return selectedLayers.toArray(EMPTY_SELECTION);
292
    }
293

    
294
    /** {@inheridDoc} */
295
    public void attachTo(PortableViewViewer viewer) {
296
        if (this.viewer != null && !this.viewer.equals(viewer)) {
297
            throw new IllegalStateException("Viewer already attached");
298
        }
299
        this.viewer = viewer;
300
        initializeUI();
301
        loadTreeModel();
302
    }
303

    
304
    /** {@inheridDoc} */
305
    public PortableViewViewer getViewer() {
306
        return viewer;
307
    }
308

    
309
    /**
310
     * Initialize User Interface components
311
     */
312
    private void initializeUI() {
313
        if (initialized) {
314
            return;
315
        }
316
        setLayout(new BorderLayout());
317

    
318
        tree = new JTree();
319

    
320
        cellRenderer = new TocTreeCellRenderer();
321
        if (imageProvider != null) {
322
            cellRenderer.setImageProvider(imageProvider);
323
        }
324

    
325
        tree.setCellRenderer(cellRenderer);
326

    
327
        tree.setRootVisible(false);
328

    
329
        tree.getSelectionModel().setSelectionMode(
330
            TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
331

    
332
        add(new JScrollPane(tree), BorderLayout.CENTER);
333

    
334
        tree.addMouseListener(new MouseListener() {
335

    
336
            public void mouseReleased(MouseEvent e) {
337
                processTreeMouseEvent(e);
338
            }
339

    
340
            public void mousePressed(MouseEvent e) {
341
                processTreeMouseEvent(e);
342
            }
343

    
344
            public void mouseExited(MouseEvent e) {
345
                processTreeMouseEvent(e);
346
            }
347

    
348
            public void mouseEntered(MouseEvent e) {
349
                processTreeMouseEvent(e);
350
            }
351

    
352
            public void mouseClicked(MouseEvent e) {
353
                processTreeMouseEvent(e);
354
            }
355
        });
356

    
357
        setMinimumSize(new Dimension(200, 100));
358

    
359
        initialized = true;
360
    }
361

    
362
    /**
363
     * Locates the layer node in all tree structure from root
364
     *
365
     * @param layer
366
     * @return
367
     */
368
    private DefaultMutableTreeNode findLayerNode(FLayer layer) {
369
        if (rootNode == null) {
370
            return null;
371
        }
372
        return findLayerNode(rootNode, layer);
373
    }
374

    
375
    /**
376
     * Locates the layer node in all tree structure from root
377
     *
378
     * @param node
379
     * @param layer
380
     * @return
381
     */
382
    private TocTreeNode findLayerNode(TocTreeNode node, FLayer layer) {
383
        if (node.getLayer() == layer) {
384
            return node;
385
        }
386
        if (node.isLeaf()) {
387
            return null;
388
        }
389
        TocTreeNode aNode;
390
        TocTreeNode result;
391
        for (int i = 0; i < node.getChildCount(); i++) {
392
            aNode = (TocTreeNode) node.getChildAt(i);
393
            result = findLayerNode(aNode, layer);
394
            if (result != null) {
395
                return result;
396
            }
397
        }
398
        return null;
399

    
400
    }
401

    
402
    public DynObject getParameters() {
403
        // TODO Auto-generated method stub
404
        return null;
405
    }
406

    
407
    public TOCFactory getFactory() {
408
        // TODO Auto-generated method stub
409
        return null;
410
    }
411

    
412
    public JComponent getComponent() {
413
        return getSwingComponent();
414
    }
415

    
416
    public MapContext getMapContext() {
417
        if (viewer == null) {
418
            return null;
419
        }
420
        return viewer.getPortableView().getMapContext();
421
    }
422

    
423
    public void showAll() {
424
        List<TocTreeNode> nodes = getNodesFromType(TYPE.values());
425
        for (TocTreeNode node : nodes) {
426
            tree.expandPath(new TreePath(node.getPath()));
427
        }
428
    }
429

    
430
    public void hideAll() {
431
        DefaultMutableTreeNode node;
432
        for (int i = rootNode.getChildCount(); i < rootNode.getChildCount(); i++) {
433
            node = (DefaultMutableTreeNode) rootNode.getChildAt(i);
434
            tree.collapsePath(new TreePath(node.getPath()));
435
        }
436

    
437
    }
438

    
439
    public void showAllLegends() {
440
        List<TocTreeNode> nodes =
441
            getNodesFromType(TYPE.LAYER_WITH_LEGEND,
442
                TYPE.LAYER_WITH_IMAGE_LEGEND);
443
        for (TocTreeNode node : nodes) {
444
            tree.expandPath(new TreePath(node.getPath()));
445
        }
446
    }
447

    
448
    public void hideAllLegends() {
449
        List<TocTreeNode> nodes =
450
            getNodesFromType(TYPE.LAYER_WITH_LEGEND,
451
                TYPE.LAYER_WITH_IMAGE_LEGEND);
452
        for (TocTreeNode node : nodes) {
453
            tree.collapsePath(new TreePath(node.getPath()));
454
        }
455
    }
456

    
457
    public void show(FLayer lyr, boolean detailed) {
458
        DefaultMutableTreeNode node = findLayerNode(lyr);
459
        if (detailed && node.getChildCount() > 0) {
460
            node = (DefaultMutableTreeNode) node.getFirstChild();
461
        }
462
        tree.scrollPathToVisible(new TreePath(node.getPath()));
463
    }
464

    
465
    public void showLegend(FLayer lyr) {
466
        show(lyr, true);
467
    }
468

    
469
    public void hideLegend(FLayer lyr) {
470
        DefaultMutableTreeNode node = findLayerNode(lyr);
471
        tree.collapsePath(new TreePath(node.getPath()));
472
    }
473

    
474
    public void selectLayer(FLayer lyr) {
475
        DefaultMutableTreeNode node = findLayerNode(lyr);
476
        tree.getSelectionModel().addSelectionPath(new TreePath(node.getPath()));
477
    }
478

    
479
    public void unselectLayer(FLayer lyr) {
480
        DefaultMutableTreeNode node = findLayerNode(lyr);
481
        tree.getSelectionModel().removeSelectionPath(
482
            new TreePath(node.getPath()));
483
    }
484

    
485
    public void clearSelection() {
486
        tree.clearSelection();
487
    }
488

    
489
    public void setActiveLayer(FLayer lyr) {
490
        TocTreeNode node = (TocTreeNode) findLayerNode(lyr);
491
        tree.getSelectionModel().setSelectionPath(new TreePath(node.getPath()));
492
    }
493

    
494
    public FLayer getActiveLayer() {
495
        if (tree.getSelectionCount() < 1) {
496
            return null;
497
        }
498
        TocTreeNode node =
499
            (TocTreeNode) tree.getSelectionPath().getLastPathComponent();
500
        if (!node.isLayer()) {
501
            return null;
502
        }
503
        return node.getLayer();
504
    }
505

    
506
    public void invokeAction(FLayer lyr, String action) {
507
        throw new UnsupportedOperationException();
508
    }
509

    
510
    public void addLegendActionListener(LegendActionEventListener lel) {
511
        throw new UnsupportedOperationException();
512
    }
513

    
514
    public void removeLegendActionListener(LegendActionEventListener lel) {
515
        throw new UnsupportedOperationException();
516
    }
517

    
518
    public void addLayerActionListener(LayerActionEventListener lel) {
519
        throw new UnsupportedOperationException();
520
    }
521

    
522
    public void removeLayerActionListener(LayerActionEventListener lel) {
523
        throw new UnsupportedOperationException();
524
    }
525

    
526
    public void addActiveLayerChangeListener(
527
        ActiveLayerChangeEventListener alcel) {
528
        throw new UnsupportedOperationException();
529
    }
530

    
531
    public void removeActiveLayerChangeListener(
532
        ActiveLayerChangeEventListener alcel) {
533
        throw new UnsupportedOperationException();
534
    }
535

    
536
    public Manager getManager() {
537
        // Nothing to do
538
        return null;
539
    }
540

    
541
    public void visibilityChanged(LayerEvent e) {
542
        DefaultMutableTreeNode node = findLayerNode(e.getSource());
543
        treeModel.nodeChanged(node);
544
    }
545

    
546
    public void activationChanged(LayerEvent e) {
547
        if (internalSelectionChanging) {
548
            return;
549
        }
550
        FLayer layer = e.getSource();
551
        TocTreeNode node = (TocTreeNode) findLayerNode(layer);
552
        TreePath path = new TreePath(node.getPath());
553
        if (layer.isActive()) {
554
            tree.addSelectionPath(path);
555
        } else {
556
            tree.removeSelectionPath(path);
557
        }
558
    }
559

    
560
    public void nameChanged(LayerEvent e) {
561
        DefaultMutableTreeNode node = findLayerNode(e.getSource());
562
        treeModel.nodeChanged(node);
563
    }
564

    
565
    public void editionChanged(LayerEvent e) {
566
        // Nothing to do
567
    }
568

    
569
    public void drawValueChanged(LayerEvent e) {
570
        // Nothing to do
571
    }
572

    
573
    protected void processTreeMouseEvent(MouseEvent e) {
574
        if (!tree.isEnabled()) {
575
            return;
576
        }
577
        if (e.getID() != MouseEvent.MOUSE_CLICKED) {
578
            return;
579
        }
580
        int x = e.getX();
581
        int y = e.getY();
582
        int row = tree.getRowForLocation(x, y);
583
        if (row < 0) {
584
            return;
585
        }
586
        // click inside some node
587
        Rectangle rect = tree.getRowBounds(row);
588
        if (rect == null) {
589
            return;
590
        }
591

    
592
        // Get the node
593
        TreePath selPath = tree.getPathForLocation(e.getX(), e.getY());
594
        final TocTreeNode node = (TocTreeNode) selPath.getLastPathComponent();
595
        if (!node.isLayer() || !node.getLayer().isAvailable()) {
596
            // no layer or unavailable layer: do nothing
597
            return;
598
        }
599

    
600
        // click on a valid node
601
        TocTreeCellRenderer renderer =
602
            (TocTreeCellRenderer) tree.getCellRenderer();
603
        // adjust renderer for node and check box has been clicked
604
        renderer.getTreeCellRendererComponent(tree, node, false, false, false,
605
            row, false);
606
        if (!renderer.isOnCheck(x - rect.x, y - rect.y)) {
607
            return;
608
        }
609
        SwingUtilities.invokeLater(new Runnable() {
610

    
611
            public void run() {
612
                swichLayerVisibilid(node);
613
            }
614
        });
615
    }
616

    
617
    /**
618
     * @param node
619
     */
620
    private void swichLayerVisibilid(TocTreeNode node) {
621
        if (!node.isLayer()) {
622
            return;
623
        }
624
        FLayer layer = node.getLayer();
625
        setLayerVisibilid(node, !layer.isVisible());
626
    }
627

    
628
    private void setLayerVisibilid(TocTreeNode node, boolean newValue) {
629
        if (node.isLayer()) {
630
            FLayer layer = node.getLayer();
631
            layer.setVisible(newValue);
632
            treeModel.nodeChanged(node);
633
        }
634
        if (node.isLeaf()) {
635
            return;
636
        }
637
        TocTreeNode child;
638
        for (int index = 0; index < node.getChildCount(); index++) {
639
            child = (TocTreeNode) node.getChildAt(index);
640
            setLayerVisibilid(child, newValue);
641
        }
642
    }
643

    
644
    public void valueChanged(TreeSelectionEvent e) {
645
        internalSelectionChanging = true;
646

    
647
        getMapContext().beginAtomicEvent();
648

    
649
        List<FLayer> prevActives =
650
            new ArrayList<FLayer>(Arrays.asList(rootLayer.getActives()));
651

    
652
        TreePath[] selectedPaths = e.getPaths();
653

    
654
        List<FLayer> newActives = new ArrayList<FLayer>(selectedPaths.length);
655

    
656
        // mark new active
657
        TocTreeNode node;
658
        FLayer layer;
659
        for (TreePath path : selectedPaths) {
660
            node = (TocTreeNode) path.getLastPathComponent();
661
            if (node.isLayer()) {
662
                layer = node.getLayer();
663
                if (!layer.isActive()) {
664
                    layer.setActive(true);
665
                } else {
666
                    prevActives.remove(layer);
667
                }
668
                newActives.add(layer);
669
            }
670
        }
671

    
672
        // Clear the previous
673
        for (FLayer aLayer : prevActives) {
674
            aLayer.setActive(false);
675
        }
676

    
677
        getMapContext().endAtomicEvent();
678
        internalSelectionChanging = false;
679
    }
680
}