Statistics
| Revision:

root / tags / v2_0_0_Build_2049 / applications / appgvSIG / src / org / gvsig / app / project / documents / view / toc / gui / TOC.java @ 38460

History | View | Annotate | Download (39.5 KB)

1
/* gvSIG. Desktop Geographic Information System.
2
 *
3
 * Copyright ? 2007-2012 gvSIG Association
4
 *
5
 * This program is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU General Public License
7
 * as published by the Free Software Foundation; either version 2
8
 * of the License, or (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18
 * MA  02110-1301, USA.
19
 *
20
 * For any additional information, do not hesitate to contact us
21
 * at info AT gvsig.com, or visit our website www.gvsig.com.
22
 */
23
package org.gvsig.app.project.documents.view.toc.gui;
24

    
25
import java.awt.BorderLayout;
26
import java.awt.Dimension;
27
import java.awt.Font;
28
import java.awt.FontMetrics;
29
import java.awt.Image;
30
import java.awt.Point;
31
import java.awt.Rectangle;
32
import java.awt.event.ActionEvent;
33
import java.awt.event.ActionListener;
34
import java.awt.event.ComponentEvent;
35
import java.awt.event.ComponentListener;
36
import java.awt.event.InputEvent;
37
import java.awt.event.MouseAdapter;
38
import java.awt.event.MouseEvent;
39
import java.text.MessageFormat;
40
import java.util.ArrayList;
41
import java.util.Enumeration;
42
import java.util.HashMap;
43
import java.util.Map;
44

    
45
import javax.swing.BorderFactory;
46
import javax.swing.JColorChooser;
47
import javax.swing.JComponent;
48
import javax.swing.JDialog;
49
import javax.swing.JScrollPane;
50
import javax.swing.JTree;
51
import javax.swing.SwingUtilities;
52
import javax.swing.event.TreeExpansionEvent;
53
import javax.swing.event.TreeExpansionListener;
54
import javax.swing.tree.DefaultMutableTreeNode;
55
import javax.swing.tree.DefaultTreeModel;
56
import javax.swing.tree.TreePath;
57
import javax.swing.tree.TreeSelectionModel;
58

    
59
import org.slf4j.Logger;
60
import org.slf4j.LoggerFactory;
61

    
62
import org.gvsig.andami.PluginServices;
63
import org.gvsig.andami.messages.NotificationManager;
64
import org.gvsig.app.project.documents.view.IContextMenuAction;
65
import org.gvsig.app.project.documents.view.toc.DnDJTree;
66
import org.gvsig.app.project.documents.view.toc.ITocItem;
67
import org.gvsig.app.project.documents.view.toc.ITocOrderListener;
68
import org.gvsig.app.project.documents.view.toc.TocItemBranch;
69
import org.gvsig.app.project.documents.view.toc.TocItemLeaf;
70
import org.gvsig.fmap.dal.exception.ReadException;
71
import org.gvsig.fmap.mapcontext.MapContext;
72
import org.gvsig.fmap.mapcontext.events.AtomicEvent;
73
import org.gvsig.fmap.mapcontext.events.listeners.AtomicEventListener;
74
import org.gvsig.fmap.mapcontext.layers.CancelationException;
75
import org.gvsig.fmap.mapcontext.layers.FLayer;
76
import org.gvsig.fmap.mapcontext.layers.FLayers;
77
import org.gvsig.fmap.mapcontext.layers.LayerCollectionEvent;
78
import org.gvsig.fmap.mapcontext.layers.LayerCollectionListener;
79
import org.gvsig.fmap.mapcontext.layers.LayerPositionEvent;
80
import org.gvsig.fmap.mapcontext.layers.operations.Classifiable;
81
import org.gvsig.fmap.mapcontext.layers.operations.IHasImageLegend;
82
import org.gvsig.fmap.mapcontext.layers.operations.LayerCollection;
83
import org.gvsig.fmap.mapcontext.layers.vectorial.FLyrVect;
84
import org.gvsig.fmap.mapcontext.rendering.legend.IClassifiedLegend;
85
import org.gvsig.fmap.mapcontext.rendering.legend.ILegend;
86
import org.gvsig.fmap.mapcontext.rendering.legend.ISingleSymbolLegend;
87
import org.gvsig.fmap.mapcontext.rendering.legend.IVectorLegend;
88
import org.gvsig.fmap.mapcontext.rendering.legend.events.LegendChangedEvent;
89
import org.gvsig.fmap.mapcontext.rendering.legend.events.listeners.LegendListener;
90
import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
91

    
92
/**
93
 * 
94
 * @author fjp
95
 */
96
public class TOC extends JComponent implements ITocOrderListener,
97
    LegendListener, LayerCollectionListener, TreeExpansionListener,
98
    ComponentListener {
99

    
100
    /**
101
     * 
102
     */
103
    private static final long serialVersionUID = 5689047685537359038L;
104

    
105
    /**
106
     * Useful for debug the problems during the implementation.
107
     */
108
    private static Logger logger = LoggerFactory.getLogger(TOC.class);
109

    
110
    private MapContext mapContext;
111

    
112
    private DnDJTree m_Tree;
113

    
114
    private DefaultTreeModel m_TreeModel;
115

    
116
    private DefaultMutableTreeNode m_Root;
117

    
118
    private TOCRenderer m_TocRenderer;
119

    
120
    private JScrollPane m_Scroller;
121

    
122
    // private ArrayList m_Listeners;
123
    private Map<String, Boolean> m_ItemsExpanded =
124
        new HashMap<String, Boolean>();
125

    
126
    private NodeSelectionListener nodeSelectionListener = null;
127

    
128
    /**
129
     * Crea un nuevo TOC.
130
     */
131
    public TOC() {
132
        this.setName("TOC");
133
        this.setLayout(new BorderLayout());
134
        this.setMinimumSize(new Dimension(100, 80));
135
        this.setPreferredSize(new Dimension(100, 80));
136

    
137
        // Construct the tree.
138
        m_Root = new DefaultMutableTreeNode(java.lang.Object.class);
139
        m_TreeModel = new DefaultTreeModel(m_Root);
140
        m_Tree = new DnDJTree(m_TreeModel);
141

    
142
        m_TocRenderer = new TOCRenderer();
143
        m_Tree.setCellRenderer(m_TocRenderer);
144

    
145
        m_Tree.setRootVisible(false);
146

    
147
        // m_Tree.setExpandsSelectedPaths(true);
148
        // m_Tree.setAutoscrolls(true);
149
        m_Tree.setShowsRootHandles(true);
150

    
151
        // Posibilidad de seleccionar de forma aleatoria nodos de la leyenda.
152
        m_Tree.getSelectionModel().setSelectionMode(
153
            TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
154
        nodeSelectionListener = new NodeSelectionListener(m_Tree);
155
        m_Tree.addMouseListener(nodeSelectionListener);
156
        // m_Tree.setBackground(UIManager.getColor("Button.background"));
157
        // m_Tree.setBorder(BorderFactory.createEtchedBorder());
158

    
159
        this.addComponentListener(this);
160

    
161
        m_Tree.addTreeExpansionListener(this);
162

    
163
        m_Tree.addOrderListener(this);
164

    
165
        m_Tree.setRowHeight(0); // Para que lo determine el renderer
166

    
167
        m_Scroller = new JScrollPane(m_Tree);
168
        m_Scroller.setBorder(BorderFactory.createEmptyBorder());
169

    
170
        // scrollPane.setPreferredSize(new Dimension(80,80));
171
        // Add everything to this panel.
172
        /*
173
         * GridBagLayout gridbag = new GridBagLayout(); GridBagConstraints c =
174
         * new GridBagConstraints(); setLayout(gridbag); c.fill =
175
         * GridBagConstraints.BOTH; c.weightx = 1.0;
176
         * gridbag.setConstraints(check,c);
177
         */
178
        add(m_Scroller); // , BorderLayout.WEST);
179

    
180
        // refresh();
181
    }
182

    
183
    /**
184
     * Elimina los listeners que actuan sobre el TOC, lo ?nico que deja hacer es
185
     * desplegar la leyenda de las capas.
186
     */
187
    public void removeListeners() {
188
        m_Tree.removeMouseListener(nodeSelectionListener);
189
        m_Tree.invalidateListeners();
190
    }
191

    
192
    /**
193
     * Inserta el FMap.
194
     * 
195
     * @param mc
196
     *            FMap.
197
     */
198
    public void setMapContext(MapContext mc) {
199
        mapContext = mc;
200
        mapContext.addAtomicEventListener(new AtomicEventListener() {
201

    
202
            /**
203
             * @see org.gvsig.fmap.mapcontext.events.listeners.AtomicEventListener#atomicEvent(org.gvsig.fmap.mapcontext.events.AtomicEvent)
204
             */
205
            public void atomicEvent(final AtomicEvent e) {
206
                if (!SwingUtilities.isEventDispatchThread()) {
207
                    SwingUtilities.invokeLater(new Runnable() {
208

    
209
                        public void run() {
210
                            atomicEvent(e);
211
                        }
212
                    });
213
                    return;
214
                }
215

    
216
                if ((e.getLayerCollectionEvents().length > 0)
217
                    || (e.getLegendEvents().length > 0)) {
218
                    refresh();
219
                }
220

    
221
                if (e.getLayerEvents().length > 0) {
222
                    repaint();
223
                }
224

    
225
                if (e.getExtentEvents().length > 0) {
226
                    repaint();
227
                }
228
                LayerCollectionEvent[] events = e.getLayerCollectionEvents();
229
                for( int i=0; i<events.length ; i++ ) {
230
                   if( events[i].getEventType() == 0 ) { // LayerCollectionEvent.LAYER_ADDED ?? is private
231
                       if (PluginServices.getMainFrame() != null) {
232
                           PluginServices.getMainFrame().enableControls();
233
                       }
234
                   }
235
                }
236
            }
237
        });
238

    
239
        refresh();
240
    }
241

    
242
    /**
243
     * DOCUMENT ME!
244
     */
245
    private void setExpandedNodes(DefaultMutableTreeNode node) {
246
        // int i = 0;
247
        // Las claves sobrantes de m_ItemsExpanded (provocadas
248
        // por layerRemove, se quitan en el evento layerRemoved
249
        // de este TOC
250
        DefaultMutableTreeNode n;
251
        @SuppressWarnings("rawtypes")
252
        Enumeration enumeration = node.children();
253

    
254
        while (enumeration.hasMoreElements()) {
255
            n = (DefaultMutableTreeNode) enumeration.nextElement();
256
            if (n.getChildCount() > 0) {
257
                setExpandedNodes(n);
258
            }
259
            TreePath path = new TreePath(m_TreeModel.getPathToRoot(n));
260
            ITocItem item = (ITocItem) n.getUserObject();
261
            Boolean b = (Boolean) m_ItemsExpanded.get(item.getLabel());
262

    
263
            if (b == null) // No estaba en el hash todav?a: valor por defecto
264
            {
265
                m_Tree.expandPath(path);
266

    
267
                return;
268
            }
269

    
270
            if (b.booleanValue()) {
271
                m_Tree.expandPath(path);
272
            } else {
273
                m_Tree.collapsePath(path);
274
            }
275
        }
276
    }
277

    
278
    /*
279
     * (non-Javadoc)
280
     * 
281
     * @see com.iver.cit.opensig.gui.IToc#refresh()
282
     */
283
    public void refresh() {
284
        if (!SwingUtilities.isEventDispatchThread()) {
285
            SwingUtilities.invokeLater(new Runnable() {
286

    
287
                public void run() {
288
                    refresh();
289
                }
290
            });
291
            return;
292
        }
293
        LayerCollection theLayers = mapContext.getLayers();
294
        m_Root.removeAllChildren();
295
        m_Root.setAllowsChildren(true);
296
        doRefresh(theLayers, m_Root);
297

    
298
        m_TreeModel.reload();
299

    
300
        setExpandedNodes(m_Root);
301
    }
302

    
303
    private void doRefresh(LayerCollection theLayers,
304
        DefaultMutableTreeNode parentNode) {
305
        int width = m_Tree.getWidth();
306
        if (width == 0) {
307
            width = 300;
308
        }
309
        Dimension sizeLeaf = new Dimension(width, 15);
310
        // Get the tree font height
311
        Font font = m_Tree.getFont();
312
        FontMetrics metrics = this.getFontMetrics(font);
313
        Dimension sizeBranch = new Dimension(width, metrics.getHeight() + 4);
314

    
315
        for (int i = theLayers.getLayersCount() - 1; i >= 0; i--) {
316
            FLayer lyr = theLayers.getLayer(i);
317
            if (!lyr.isInTOC()) {
318
                continue;
319
            }
320
            TocItemBranch elTema = new TocItemBranch(lyr);
321
            elTema.setSize(sizeBranch);
322

    
323
            DefaultMutableTreeNode nodeLayer =
324
                new DefaultMutableTreeNode(elTema);
325

    
326
            m_TreeModel.insertNodeInto(nodeLayer, parentNode,
327
                parentNode.getChildCount());
328

    
329
            if (lyr instanceof LayerCollection) {
330
                LayerCollection group = (LayerCollection) lyr;
331
                doRefresh(group, nodeLayer);
332
            } else {
333
                if (lyr instanceof Classifiable) {// && !(lyr instanceof
334
                                                  // FLyrAnnotation)) {
335

    
336
                    Classifiable classifiable = (Classifiable) lyr;
337
                    ILegend legendInfo = classifiable.getLegend();
338

    
339
                    try {
340
                        if (legendInfo instanceof IClassifiedLegend) {
341
                            IClassifiedLegend cl =
342
                                (IClassifiedLegend) legendInfo;
343
                            String[] descriptions = cl.getDescriptions();
344
                            ISymbol[] symbols = cl.getSymbols();
345

    
346
                            for (int j = 0; j < descriptions.length; j++) {
347
                                TocItemLeaf itemLeaf;
348
                                itemLeaf =
349
                                    new TocItemLeaf(symbols[j],
350
                                        descriptions[j], classifiable.getShapeType());
351
                                itemLeaf.setSize(sizeLeaf);
352

    
353
                                DefaultMutableTreeNode nodeValue =
354
                                    new DefaultMutableTreeNode(itemLeaf);
355
                                m_TreeModel.insertNodeInto(nodeValue,
356
                                    nodeLayer, nodeLayer.getChildCount());
357

    
358
                            }
359
                        }
360

    
361
                        if (legendInfo instanceof ISingleSymbolLegend
362
                            && (legendInfo.getDefaultSymbol() != null)) {
363
                            TocItemLeaf itemLeaf;
364
                            itemLeaf =
365
                                new TocItemLeaf(legendInfo.getDefaultSymbol(),
366
                                    legendInfo.getDefaultSymbol()
367
                                        .getDescription(), classifiable.getShapeType());
368
                            itemLeaf.setSize(sizeLeaf);
369

    
370
                            DefaultMutableTreeNode nodeValue =
371
                                new DefaultMutableTreeNode(itemLeaf);
372
                            m_TreeModel.insertNodeInto(nodeValue, nodeLayer,
373
                                nodeLayer.getChildCount());
374
                        }
375
                        
376
                        if (legendInfo instanceof IHasImageLegend) {
377
                            TocItemLeaf itemLeaf;
378
                            IHasImageLegend imageLegend = (IHasImageLegend) legendInfo;
379
                            Image image = imageLegend.getImageLegend();
380

    
381
                            if (image != null) {
382
                                itemLeaf = new TocItemLeaf();
383
                                itemLeaf.setImageLegend(image, "", new Dimension(
384
                                    image.getWidth(null), image.getHeight(null)));// new
385
                                                                                  // Dimension(150,200));
386

    
387
                                DefaultMutableTreeNode nodeValue =
388
                                    new DefaultMutableTreeNode(itemLeaf);
389
                                m_TreeModel.insertNodeInto(nodeValue, nodeLayer,
390
                                    nodeLayer.getChildCount());
391
                            }
392
                        }
393
                    } catch (ReadException e) {
394
                        logger.error(MessageFormat.format(
395
                            "Can't add leyend of layer {0} to the TOC.", lyr),
396
                            e);
397
                    }
398
                } 
399
            } // if instanceof layers
400
        }
401
    }
402

    
403
    /**
404
     * @see com.iver.cit.opensig.gui.toc.ITocOrderListener#orderChanged(int,
405
     *      int)
406
     */
407
    public void orderChanged(int oldPos, int newPos, FLayers lpd) {
408
        try {
409
            lpd.moveTo(oldPos, newPos);
410
        } catch (CancelationException e) {
411
            logger.error("Can't change order of layers in TOC", e);
412
        }
413
        mapContext.invalidate();
414
    }
415

    
416
    public void parentChanged(FLayers lpo, FLayers lpd, FLayer ls) {
417
        lpo.move(ls, lpd);
418
        mapContext.invalidate();
419
    }
420

    
421
    /*
422
     * (non-Javadoc)
423
     * 
424
     * @see java.awt.event.ComponentListener#componentHidden(java.awt.event.
425
     * ComponentEvent)
426
     */
427
    public void componentHidden(ComponentEvent e) {
428
    }
429

    
430
    /*
431
     * (non-Javadoc)
432
     * 
433
     * @see
434
     * java.awt.event.ComponentListener#componentMoved(java.awt.event.ComponentEvent
435
     * )
436
     */
437
    public void componentMoved(ComponentEvent e) {
438
    }
439

    
440
    /*
441
     * (non-Javadoc)
442
     * 
443
     * @see java.awt.event.ComponentListener#componentResized(java.awt.event.
444
     * ComponentEvent)
445
     */
446
    public void componentResized(ComponentEvent e) {
447
        DefaultMutableTreeNode n;
448
        @SuppressWarnings("rawtypes")
449
        Enumeration enumeration = m_Root.children();
450

    
451
        while (enumeration.hasMoreElements()) {
452
            n = (DefaultMutableTreeNode) enumeration.nextElement();
453

    
454
            if (n.getUserObject() instanceof TocItemBranch) {
455
                ITocItem item = (ITocItem) n.getUserObject();
456
                Dimension szAnt = item.getSize();
457
                item.setSize(new Dimension(this.getWidth() - 40, szAnt.height));
458
            }
459

    
460
        }
461
    }
462

    
463
    /*
464
     * (non-Javadoc)
465
     * 
466
     * @see
467
     * java.awt.event.ComponentListener#componentShown(java.awt.event.ComponentEvent
468
     * )
469
     */
470
    public void componentShown(ComponentEvent e) {
471
    }
472

    
473
    /*
474
     * (non-Javadoc)
475
     * 
476
     * @see
477
     * com.iver.cit.gvsig.fmap.layers.LayerListener#legendChanged(com.iver.cit
478
     * .gvsig.fmap.rendering.LegendChangedEvent)
479
     */
480
    public void legendChanged(final LegendChangedEvent e) {
481
        if (!SwingUtilities.isEventDispatchThread()) {
482
            SwingUtilities.invokeLater(new Runnable() {
483

    
484
                public void run() {
485
                    legendChanged(e);
486
                }
487
            });
488
            return;
489
        }
490
        refresh();
491
    }
492

    
493
    /*
494
     * (non-Javadoc)
495
     * 
496
     * @see
497
     * com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#layerAdded(com
498
     * .iver.cit.gvsig.fmap.layers.LayerCollectionEvent)
499
     */
500
    public void layerAdded(final LayerCollectionEvent e) {
501
        if (!SwingUtilities.isEventDispatchThread()) {
502
            SwingUtilities.invokeLater(new Runnable() {
503

    
504
                public void run() {
505
                    layerAdded(e);
506
                }
507
            });
508
            return;
509
        }
510
        refresh();
511
    }
512

    
513
    /*
514
     * (non-Javadoc)
515
     * 
516
     * @see
517
     * com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#layerMoved(com
518
     * .iver.cit.gvsig.fmap.layers.LayerPositionEvent)
519
     */
520
    public void layerMoved(final LayerPositionEvent e) {
521
        if (!SwingUtilities.isEventDispatchThread()) {
522
            SwingUtilities.invokeLater(new Runnable() {
523

    
524
                public void run() {
525
                    layerMoved(e);
526
                }
527
            });
528
            return;
529
        }
530
        refresh();
531
    }
532

    
533
    /*
534
     * (non-Javadoc)
535
     * 
536
     * @see
537
     * com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#layerRemoved(com
538
     * .iver.cit.gvsig.fmap.layers.LayerCollectionEvent)
539
     */
540
    public void layerRemoved(final LayerCollectionEvent e) {
541
        if (!SwingUtilities.isEventDispatchThread()) {
542
            SwingUtilities.invokeLater(new Runnable() {
543

    
544
                public void run() {
545
                    layerRemoved(e);
546
                }
547
            });
548
            return;
549
        }
550
        m_ItemsExpanded.remove(e.getAffectedLayer().getName());
551
        refresh();
552
    }
553

    
554
    /*
555
     * (non-Javadoc)
556
     * 
557
     * @see
558
     * com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#layerAdding(com
559
     * .iver.cit.gvsig.fmap.layers.LayerCollectionEvent)
560
     */
561
    public void layerAdding(LayerCollectionEvent e) throws CancelationException {
562
    }
563

    
564
    /*
565
     * (non-Javadoc)
566
     * 
567
     * @see
568
     * com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#layerMoving(com
569
     * .iver.cit.gvsig.fmap.layers.LayerPositionEvent)
570
     */
571
    public void layerMoving(LayerPositionEvent e) throws CancelationException {
572
    }
573

    
574
    /*
575
     * (non-Javadoc)
576
     * 
577
     * @see
578
     * com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#layerRemoving(
579
     * com.iver.cit.gvsig.fmap.layers.LayerCollectionEvent)
580
     */
581
    public void layerRemoving(LayerCollectionEvent e)
582
        throws CancelationException {
583
    }
584

    
585
    /*
586
     * (non-Javadoc)
587
     * 
588
     * @see
589
     * com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#activationChanged
590
     * (com.iver.cit.gvsig.fmap.layers.LayerCollectionEvent)
591
     */
592
    public void activationChanged(LayerCollectionEvent e)
593
        throws CancelationException {
594
        repaint();
595
    }
596

    
597
    /*
598
     * (non-Javadoc)
599
     * 
600
     * @see
601
     * com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#visibilityChanged
602
     * (com.iver.cit.gvsig.fmap.layers.LayerCollectionEvent)
603
     */
604
    public void visibilityChanged(final LayerCollectionEvent e)
605
        throws CancelationException {
606
        if (!SwingUtilities.isEventDispatchThread()) {
607
            SwingUtilities.invokeLater(new Runnable() {
608

    
609
                public void run() {
610
                    visibilityChanged(e);
611
                }
612
            });
613
            return;
614
        }
615
        repaint();
616
    }
617

    
618
    /*
619
     * (non-Javadoc)
620
     * 
621
     * @see
622
     * javax.swing.event.TreeExpansionListener#treeCollapsed(javax.swing.event
623
     * .TreeExpansionEvent)
624
     */
625
    public void treeCollapsed(TreeExpansionEvent event) {
626
        TreePath path = event.getPath();
627
        DefaultMutableTreeNode n =
628
            (DefaultMutableTreeNode) path.getLastPathComponent();
629

    
630
        if (n.getUserObject() instanceof ITocItem) {
631
            ITocItem item = (ITocItem) n.getUserObject();
632
            Boolean b = Boolean.FALSE;
633

    
634
            m_ItemsExpanded.put(item.getLabel(), b);
635
        }
636
    }
637

    
638
    /*
639
     * (non-Javadoc)
640
     * 
641
     * @see
642
     * javax.swing.event.TreeExpansionListener#treeExpanded(javax.swing.event
643
     * .TreeExpansionEvent)
644
     */
645
    public void treeExpanded(TreeExpansionEvent event) {
646
        TreePath path = event.getPath();
647
        DefaultMutableTreeNode n =
648
            (DefaultMutableTreeNode) path.getLastPathComponent();
649

    
650
        if (n.getUserObject() instanceof ITocItem) {
651
            ITocItem item = (ITocItem) n.getUserObject();
652
            Boolean b = Boolean.TRUE;
653

    
654
            m_ItemsExpanded.put(item.getLabel(), b);
655
        }
656
    }
657

    
658
    /**
659
     * Obtiene el JScrollPane que contiene el TOC
660
     * 
661
     * @return JScrollPane que contiene el TOC
662
     */
663
    public JScrollPane getJScrollPane() {
664
        return this.m_Scroller;
665
    }
666

    
667
    /**
668
     * DOCUMENT ME!
669
     * 
670
     * @return DOCUMENT ME!
671
     */
672
    public DnDJTree getTree() {
673
        return m_Tree;
674
    }
675

    
676
    /**
677
     * Clase Listener que reacciona al pulsar sobre el checkbox de un nodo y
678
     * crea un popupmenu al pulsar el bot?n derecho.
679
     */
680
    class NodeSelectionListener extends MouseAdapter implements ActionListener {
681

    
682
        JTree tree;
683

    
684
        JDialog dlg;
685

    
686
        JColorChooser colorChooser;
687

    
688
        FPopupMenu popmenu = null;
689

    
690
        DefaultMutableTreeNode node;
691

    
692
        /**
693
         * Crea un nuevo NodeSelectionListener.
694
         * 
695
         * @param tree
696
         *            DOCUMENT ME!
697
         */
698
        NodeSelectionListener(JTree tree) {
699
            this.tree = tree;
700
        }
701

    
702
        /**
703
         * DOCUMENT ME!
704
         * 
705
         * @param e
706
         *            DOCUMENT ME!
707
         */
708
        public void mouseClicked(MouseEvent e) {
709
            int x = e.getX();
710
            int y = e.getY();
711
            int row = tree.getRowForLocation(x, y);
712
            TreePath path = tree.getPathForRow(row);
713
            LayerCollection layers = mapContext.getLayers();
714

    
715
            if (path != null) {
716
                if (e.getClickCount() == 1) {
717
                    // this fixes a bug when double-clicking. JTree by default
718
                    // expands the tree when double-clicking, so we capture a
719
                    // different node in the second click than in the first
720
                    node = (DefaultMutableTreeNode) path.getLastPathComponent();
721
                }
722

    
723
                if (node != null
724
                    && node.getUserObject() instanceof TocItemBranch) {
725
                    // double click with left button ON A BRANCH/NODE (layer)
726
                    if (e.getClickCount() >= 2
727
                        && e.getButton() == MouseEvent.BUTTON1) {
728
                        e.consume();
729
                        PluginServices.getMDIManager().setWaitCursor();
730
                        try {
731
                            TocItemBranch leaf =
732
                                (TocItemBranch) node.getUserObject();
733

    
734
                            IContextMenuAction action =
735
                                leaf.getDoubleClickAction();
736
                            if (action != null) {
737
                                /*
738
                                 * if there is an action associated with the
739
                                 * double-clicked element it will be fired for
740
                                 * it and FOR ALL OTHER COMPATIBLES THAT HAVE
741
                                 * BEEN ACTIVATED.
742
                                 */
743
                                ArrayList<FLayer> targetLayers =
744
                                    new ArrayList<FLayer>();
745

    
746
                                TocItemBranch owner =
747
                                    (TocItemBranch) node.getUserObject();
748

    
749
                                FLayer masterLayer = owner.getLayer();
750
                                targetLayers.add(masterLayer);
751
                                FLayer[] actives =
752
                                    mapContext.getLayers().getActives();
753
                                for (int i = 0; i < actives.length; i++) {
754
                                    if (actives[i].getClass().equals(
755
                                        masterLayer.getClass())) {
756
                                        if (actives[i] instanceof FLyrVect) {
757
                                            FLyrVect vectorLayer =
758
                                                (FLyrVect) actives[i];
759
                                            FLyrVect vectorMaster =
760
                                                (FLyrVect) masterLayer;
761
                                            if (vectorLayer.getShapeType() == vectorMaster
762
                                                .getShapeType()) {
763
                                                targetLayers.add(vectorLayer);
764
                                            } else {
765
                                                vectorLayer.setActive(false);
766
                                            }
767
                                        }
768
                                        // TODO for the rest of layer types
769
                                        // (i.e. FLyrRaster)
770
                                    } else {
771
                                        actives[i].setActive(false);
772
                                    }
773
                                }
774
                                action.execute(leaf,
775
                                    targetLayers.toArray(new FLayer[0]));
776
                            }
777
                        } catch (Exception ex) {
778
                            NotificationManager.addError(ex);
779
                        } finally {
780
                            PluginServices.getMDIManager().restoreCursor();
781
                        }
782
                        return;
783
                    }
784

    
785
                    TocItemBranch elTema = (TocItemBranch) node.getUserObject();
786
                    FLayer lyr = elTema.getLayer();
787
                    lyr.getMapContext().beginAtomicEvent();
788

    
789
                    if (((e.getModifiers() & InputEvent.SHIFT_MASK) != 0)
790
                        && (e.getButton() == MouseEvent.BUTTON1)) {
791
                        FLayer[] activeLayers = layers.getActives();
792
                        if (activeLayers.length > 0) {
793
                            selectInterval(layers, lyr);
794
                        } else {
795
                            updateActive(lyr, !lyr.isActive());
796
                        }
797

    
798
                    } else {
799
                        if (!((e.getModifiers() & InputEvent.CTRL_MASK) != 0)
800
                            && (e.getButton() == MouseEvent.BUTTON1)) {
801
                            layers.setAllActives(false);
802
                        }
803
                        if (e.getButton() == MouseEvent.BUTTON1) {
804
                            // lyr.setActive(true);
805
                            updateActive(lyr, !lyr.isActive());
806
                        }
807
                    }
808
                    // Si pertenece a un grupo, lo ponemos activo tambi?n.
809
                    // FLayer parentLayer = lyr.getParentLayer();
810

    
811
                    /*
812
                     * if (parentLayer != null) { parentLayer.setActive(true); }
813
                     */
814
                    Point layerNodeLocation =
815
                        tree.getUI().getPathBounds(tree, path).getLocation();
816

    
817
                    // Rect?ngulo que representa el checkbox
818
                    Rectangle checkBoxBounds =
819
                        m_TocRenderer.getCheckBoxBounds();
820
                    checkBoxBounds.translate((int) layerNodeLocation.getX(),
821
                        (int) layerNodeLocation.getY());
822

    
823
                    if (checkBoxBounds.contains(e.getPoint())) {
824
                        updateVisible(lyr);
825
                    }
826

    
827
                    // }
828
                    if (e.getButton() == MouseEvent.BUTTON3) {
829
                        // Boton derecho sobre un nodo del arbol
830
                        // if ((e.getModifiers() & InputEvent.META_MASK) != 0) {
831
                        popmenu = new FPopupMenu(mapContext, node);
832
                        tree.add(popmenu);
833

    
834
                        popmenu.show(e.getComponent(), e.getX(), e.getY());
835

    
836
                        // }
837
                    }
838

    
839
                    lyr.getMapContext().endAtomicEvent();
840
                }
841

    
842
                if (node != null && node.getUserObject() instanceof TocItemLeaf) {
843
                    // double click with left button ON A LEAF (ISymbol)
844
                    if (e.getClickCount() >= 2
845
                        && e.getButton() == MouseEvent.BUTTON1) {
846
                        e.consume();
847

    
848
                        PluginServices.getMDIManager().setWaitCursor();
849
                        try {
850
                            TocItemLeaf leaf =
851
                                (TocItemLeaf) node.getUserObject();
852
                            IContextMenuAction action =
853
                                leaf.getDoubleClickAction();
854
                            if (action != null) {
855
                                /*
856
                                 * if there is an action associated with the
857
                                 * double-clicked element it will be fired for
858
                                 * it and FOR ALL OTHER COMPATIBLES THAT HAVE
859
                                 * BEEN ACTIVATED.
860
                                 */
861
                                ArrayList<FLayer> targetLayers =
862
                                    new ArrayList<FLayer>();
863

    
864
                                TocItemBranch owner =
865
                                    (TocItemBranch) ((DefaultMutableTreeNode) node
866
                                        .getParent()).getUserObject();
867

    
868
                                FLayer masterLayer = owner.getLayer();
869
                                targetLayers.add(masterLayer);
870
                                FLayer[] actives =
871
                                    mapContext.getLayers().getActives();
872
                                for (int i = 0; i < actives.length; i++) {
873
                                    if (actives[i].getClass().equals(
874
                                        masterLayer.getClass())) {
875
                                        if (actives[i] instanceof FLyrVect) {
876
                                            FLyrVect vectorLayer =
877
                                                (FLyrVect) actives[i];
878
                                            FLyrVect vectorMaster =
879
                                                (FLyrVect) masterLayer;
880
                                            int masterLayerShapetypeOF_THE_LEGEND =
881
                                                ((IVectorLegend) vectorMaster
882
                                                    .getLegend())
883
                                                    .getShapeType();
884
                                            int anotherVectorLayerShapetypeOF_THE_LEGEND =
885
                                                ((IVectorLegend) vectorLayer
886
                                                    .getLegend())
887
                                                    .getShapeType();
888
                                            if (masterLayerShapetypeOF_THE_LEGEND == anotherVectorLayerShapetypeOF_THE_LEGEND) {
889
                                                targetLayers.add(vectorLayer);
890
                                            } else {
891
                                                vectorLayer.setActive(false);
892
                                            }
893
                                        }
894
                                        // TODO for the rest of layer types
895
                                        // (i.e. FLyrRaster)
896
                                    } else {
897
                                        actives[i].setActive(false);
898
                                    }
899
                                }
900
                                action.execute(leaf,
901
                                    targetLayers.toArray(new FLayer[0]));
902
                            }
903
                        } catch (Exception ex) {
904
                            NotificationManager.addError(ex);
905
                        } finally {
906
                            PluginServices.getMDIManager().restoreCursor();
907
                        }
908
                        return;
909
                    }
910

    
911
                    // Boton derecho sobre un Simbolo
912
                    // TocItemLeaf auxLeaf = (TocItemLeaf) node.getUserObject();
913
                    // FSymbol theSym = auxLeaf.getSymbol();
914
                    if ((e.getModifiers() & InputEvent.META_MASK) != 0) {
915
                        popmenu = new FPopupMenu(mapContext, node);
916
                        tree.add(popmenu);
917
                        popmenu.show(e.getComponent(), e.getX(), e.getY());
918
                    }
919
                }
920

    
921
                ((DefaultTreeModel) tree.getModel()).nodeChanged(node);
922

    
923
                if (row == 0) {
924
                    tree.revalidate();
925
                    tree.repaint();
926
                }
927

    
928
                if (PluginServices.getMainFrame() != null) {
929
                    PluginServices.getMainFrame().enableControls();
930
                }
931
            } else {
932
                if (e.getButton() == MouseEvent.BUTTON3) {
933
                    popmenu = new FPopupMenu(mapContext, null);
934
                    tree.add(popmenu);
935
                    popmenu.show(e.getComponent(), e.getX(), e.getY());
936
                }
937

    
938
            }
939
        }
940

    
941
        private void selectInterval(LayerCollection layers, FLayer lyr) {
942
            FLayer[] activeLayers = layers.getActives();
943
            // if (activeLayers[0].getParentLayer() instanceof FLayers &&
944
            // activeLayers[0].getParentLayer().getParentLayer()!=null) {
945
            // selectInterval((LayerCollection)activeLayers[0].getParentLayer(),lyr);
946
            // }
947
            for (int j = 0; j < layers.getLayersCount(); j++) {
948
                FLayer layerAux = layers.getLayer(j);
949
                // Si se cumple esta condici?n es porque la primera capa que nos
950
                // encontramos en el TOC es la que estaba activa
951
                if (activeLayers[0].equals(layerAux)) {
952
                    boolean isSelected = false;
953
                    for (int i = 0; i < layers.getLayersCount(); i++) {
954
                        FLayer layer = layers.getLayer(i);
955
                        if (!isSelected) {
956
                            isSelected = layer.isActive();
957
                        } else {
958
                            updateActive(layer, true);
959
                            if (lyr.equals(layer)) {
960
                                isSelected = false;
961
                            }
962
                        }
963
                    }
964
                    break;
965
                } else
966
                    // Si se cumple esta condici?n es porque la primera capa que
967
                    // nos
968
                    // encontramos en el TOC es la que acabamos de seleccionar
969
                    if (lyr.equals(layerAux)) {
970
                        boolean isSelected = false;
971
                        for (int i = layers.getLayersCount() - 1; i >= 0; i--) {
972
                            FLayer layer = layers.getLayer(i);
973
                            if (!isSelected) {
974
                                isSelected = layer.isActive();
975
                            } else {
976
                                updateActive(layer, true);
977
                                if (lyr.equals(layer)) {
978
                                    isSelected = false;
979
                                }
980
                            }
981
                        }
982
                        break;
983
                    }
984
            }
985

    
986
        }
987

    
988
        /**
989
         * DOCUMENT ME!
990
         * 
991
         * @param lyr
992
         *            DOCUMENT ME!
993
         * @param active
994
         *            DOCUMENT ME!
995
         */
996
        private void updateActive(FLayer lyr, boolean active) {
997
            lyr.setActive(active);
998
            updateActiveChild(lyr);
999
        }
1000

    
1001
        /**
1002
         * DOCUMENT ME!
1003
         * 
1004
         * @param lyr
1005
         *            DOCUMENT ME!
1006
         */
1007
        private void updateActiveChild(FLayer lyr) {
1008
            if (lyr instanceof FLayers) { // Es la raiz de una rama o
1009
                // cualquier nodo intermedio.
1010

    
1011
                FLayers layergroup = (FLayers) lyr;
1012

    
1013
                for (int i = 0; i < layergroup.getLayersCount(); i++) {
1014
                    layergroup.getLayer(i).setActive(lyr.isActive());
1015
                    updateActiveChild(layergroup.getLayer(i));
1016
                }
1017
            }
1018
        }
1019

    
1020
        /**
1021
         * Actualiza la visibilidad de la capas.
1022
         * 
1023
         * @param lyr
1024
         *            Capa sobre la que se est? clickando.
1025
         */
1026
        private void updateVisible(FLayer lyr) {
1027
            if (lyr.isAvailable()) {
1028
                lyr.setVisible(!lyr.visibleRequired());
1029
                updateVisibleChild(lyr);
1030
                updateVisibleParent(lyr);
1031
            }
1032
        }
1033

    
1034
        /**
1035
         * Actualiza de forma recursiva la visibilidad de los hijos de la capa
1036
         * que se pasa como par?metro.
1037
         * 
1038
         * @param lyr
1039
         *            Capa a actualizar.
1040
         */
1041
        private void updateVisibleChild(FLayer lyr) {
1042
            if (lyr instanceof FLayers) { // Es la raiz de una rama o
1043
                                          // cualquier nodo intermedio.
1044

    
1045
                FLayers layergroup = (FLayers) lyr;
1046

    
1047
                for (int i = 0; i < layergroup.getLayersCount(); i++) {
1048
                    layergroup.getLayer(i).setVisible(lyr.visibleRequired());
1049
                    updateVisibleChild(layergroup.getLayer(i));
1050
                }
1051
            }
1052
        }
1053

    
1054
        /**
1055
         * Actualiza de forma recursiva la visibilidad del padre de la capa que
1056
         * se pasa como par?metro.
1057
         * 
1058
         * @param lyr
1059
         *            Capa a actualizar.
1060
         */
1061
        private void updateVisibleParent(FLayer lyr) {
1062
            FLayers parent = lyr.getParentLayer();
1063

    
1064
            if (parent != null) {
1065
                boolean parentVisible = false;
1066

    
1067
                for (int i = 0; i < parent.getLayersCount(); i++) {
1068
                    if (parent.getLayer(i).visibleRequired()) {
1069
                        parentVisible = true;
1070
                    }
1071
                }
1072

    
1073
                parent.setVisible(parentVisible);
1074
                updateVisibleParent(parent);
1075
            }
1076
        }
1077

    
1078
        /**
1079
         * DOCUMENT ME!
1080
         * 
1081
         * @param arg0
1082
         *            DOCUMENT ME!
1083
         */
1084
        public void actionPerformed(ActionEvent arg0) {
1085
        }
1086

    
1087
        /**
1088
         * DOCUMENT ME!
1089
         * 
1090
         * @param arg0
1091
         *            DOCUMENT ME!
1092
         */
1093
        public void mouseReleased(MouseEvent arg0) {
1094
            super.mouseReleased(arg0);
1095
        }
1096

    
1097
        /**
1098
         * DOCUMENT ME!
1099
         * 
1100
         * @param arg0
1101
         *            DOCUMENT ME!
1102
         */
1103
        public void mouseEntered(MouseEvent arg0) {
1104
            super.mouseEntered(arg0);
1105
        }
1106
    }
1107

    
1108
}