Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.plugin / org.gvsig.app / org.gvsig.app.mainplugin / src / main / java / org / gvsig / app / project / documents / view / toc / gui / TOC.java @ 41081

History | View | Annotate | Download (40.7 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
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 3
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
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
24
package org.gvsig.app.project.documents.view.toc.gui;
25

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

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

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

    
97
/**
98
 * 
99
 * @author fjp
100
 */
101
public class TOC extends JComponent implements ITocOrderListener,
102
    LegendListener, LayerCollectionListener, TreeExpansionListener,
103
    ComponentListener {
104

    
105
    /**
106
     * 
107
     */
108
    private static final long serialVersionUID = 5689047685537359038L;
109

    
110
    /**
111
     * Useful for debug the problems during the implementation.
112
     */
113
    private static Logger logger = LoggerFactory.getLogger(TOC.class);
114

    
115
    private MapContext mapContext;
116

    
117
    private DnDJTree m_Tree;
118

    
119
    private DefaultTreeModel m_TreeModel;
120

    
121
    private DefaultMutableTreeNode m_Root;
122

    
123
    private TOCRenderer m_TocRenderer;
124

    
125
    private JScrollPane m_Scroller;
126

    
127
    // private ArrayList m_Listeners;
128
    private Map<String, Boolean> m_ItemsExpanded =
129
        new HashMap<String, Boolean>();
130

    
131
    private NodeSelectionListener nodeSelectionListener = null;
132

    
133
    /**
134
     * Crea un nuevo TOC.
135
     */
136
    public TOC() {
137
        this.setName("TOC");
138
        this.setLayout(new BorderLayout());
139
        this.setMinimumSize(new Dimension(100, 80));
140
        this.setPreferredSize(new Dimension(100, 80));
141

    
142
        // Construct the tree.
143
        m_Root = new DefaultMutableTreeNode(java.lang.Object.class);
144
        m_TreeModel = new DefaultTreeModel(m_Root);
145
        m_Tree = new DnDJTree(m_TreeModel);
146

    
147
        m_TocRenderer = new TOCRenderer(m_Tree.getBackground());
148
        m_Tree.setCellRenderer(m_TocRenderer);
149

    
150
        m_Tree.setRootVisible(false);
151

    
152
        // m_Tree.setExpandsSelectedPaths(true);
153
        // m_Tree.setAutoscrolls(true);
154
        m_Tree.setShowsRootHandles(true);
155

    
156
        // Posibilidad de seleccionar de forma aleatoria nodos de la leyenda.
157
        m_Tree.getSelectionModel().setSelectionMode(
158
            TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
159
        nodeSelectionListener = new NodeSelectionListener(m_Tree);
160
        m_Tree.addMouseListener(nodeSelectionListener);
161
        // m_Tree.setBackground(UIManager.getColor("Button.background"));
162
        // m_Tree.setBorder(BorderFactory.createEtchedBorder());
163

    
164
        this.addComponentListener(this);
165

    
166
        m_Tree.addTreeExpansionListener(this);
167

    
168
        m_Tree.addOrderListener(this);
169

    
170
        m_Tree.setRowHeight(0); // Para que lo determine el renderer
171

    
172
        m_Scroller = new JScrollPane(m_Tree);
173
        m_Scroller.setBorder(BorderFactory.createEmptyBorder());
174

    
175
        // scrollPane.setPreferredSize(new Dimension(80,80));
176
        // Add everything to this panel.
177
        /*
178
         * GridBagLayout gridbag = new GridBagLayout(); GridBagConstraints c =
179
         * new GridBagConstraints(); setLayout(gridbag); c.fill =
180
         * GridBagConstraints.BOTH; c.weightx = 1.0;
181
         * gridbag.setConstraints(check,c);
182
         */
183
        add(m_Scroller); // , BorderLayout.WEST);
184

    
185
        // refresh();
186
    }
187

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

    
197
    /**
198
     * Inserta el FMap.
199
     * 
200
     * @param mc
201
     *            FMap.
202
     */
203
    public void setMapContext(MapContext mc) {
204
        mapContext = mc;
205
        mapContext.addAtomicEventListener(new AtomicEventListener() {
206

    
207
            /**
208
             * @see org.gvsig.fmap.mapcontext.events.listeners.AtomicEventListener#atomicEvent(org.gvsig.fmap.mapcontext.events.AtomicEvent)
209
             */
210
            public void atomicEvent(final AtomicEvent e) {
211
                if (!SwingUtilities.isEventDispatchThread()) {
212
                    SwingUtilities.invokeLater(new Runnable() {
213

    
214
                        public void run() {
215
                            atomicEvent(e);
216
                        }
217
                    });
218
                    return;
219
                }
220

    
221
                if ((e.getLayerCollectionEvents().length > 0)
222
                    || (e.getLegendEvents().length > 0)) {
223
                    refresh();
224
                }
225

    
226
                if (e.getLayerEvents().length > 0) {
227
                    repaint();
228
                }
229

    
230
                if (e.getExtentEvents().length > 0) {
231
                    repaint();
232
                }
233
                LayerCollectionEvent[] events = e.getLayerCollectionEvents();
234
                for( int i=0; i<events.length ; i++ ) {
235
                   if( events[i].getEventType() == LayerCollectionEvent.LAYER_ADDED ) { 
236
                       if (PluginServices.getMainFrame() != null) {
237
                           PluginServices.getMainFrame().enableControls();
238
                       }
239
                   }
240
                   // ===================================================
241
                   // Change visibility of layer before adding, according to app preferences
242
                   if( events[i].getEventType() == LayerCollectionEvent.LAYER_ADDING ) {
243

    
244
                       if (invisibilityIsForced()) {
245
                           events[i].getAffectedLayer().setVisible(false);
246
                       }
247
                   }
248
                   // ===================================================
249
                }
250
            }
251
        });
252

    
253
        refresh();
254
    }
255

    
256
    /**
257
     * DOCUMENT ME!
258
     */
259
    private void setExpandedNodes(DefaultMutableTreeNode node) {
260
        // int i = 0;
261
        // Las claves sobrantes de m_ItemsExpanded (provocadas
262
        // por layerRemove, se quitan en el evento layerRemoved
263
        // de este TOC
264
        DefaultMutableTreeNode n;
265
        @SuppressWarnings("rawtypes")
266
        Enumeration enumeration = node.children();
267

    
268
        while (enumeration.hasMoreElements()) {
269
            n = (DefaultMutableTreeNode) enumeration.nextElement();
270
            if (n.getChildCount() > 0) {
271
                setExpandedNodes(n);
272
            }
273
            TreePath path = new TreePath(m_TreeModel.getPathToRoot(n));
274
            ITocItem item = (ITocItem) n.getUserObject();
275
            Boolean b = (Boolean) m_ItemsExpanded.get(item.getLabel());
276

    
277
            if (b == null) // No estaba en el hash todav?a: valor por defecto
278
            {
279
                m_Tree.expandPath(path);
280

    
281
                return;
282
            }
283

    
284
            if (b.booleanValue()) {
285
                m_Tree.expandPath(path);
286
            } else {
287
                m_Tree.collapsePath(path);
288
            }
289
        }
290
    }
291

    
292
    /*
293
     * (non-Javadoc)
294
     * 
295
     * @see com.iver.cit.opensig.gui.IToc#refresh()
296
     */
297
    public void refresh() {
298
        if (!SwingUtilities.isEventDispatchThread()) {
299
            SwingUtilities.invokeLater(new Runnable() {
300

    
301
                public void run() {
302
                    refresh();
303
                }
304
            });
305
            return;
306
        }
307
        LayerCollection theLayers = mapContext.getLayers();
308
        m_Root.removeAllChildren();
309
        m_Root.setAllowsChildren(true);
310
        doRefresh(theLayers, m_Root);
311

    
312
        m_TreeModel.reload();
313

    
314
        setExpandedNodes(m_Root);
315
    }
316

    
317
    private void doRefresh(LayerCollection theLayers,
318
        DefaultMutableTreeNode parentNode) {
319
        int width = m_Tree.getWidth();
320
        if (width == 0) {
321
            width = 300;
322
        }
323
        Dimension sizeLeaf = new Dimension(width, 15);
324
        // Get the tree font height
325
        Font font = m_Tree.getFont();
326
        FontMetrics metrics = this.getFontMetrics(font);
327
        Dimension sizeBranch = new Dimension(width, metrics.getHeight() + 4);
328

    
329
        for (int i = theLayers.getLayersCount() - 1; i >= 0; i--) {
330
            FLayer lyr = theLayers.getLayer(i);
331
            if (!lyr.isInTOC()) {
332
                continue;
333
            }
334
            TocItemBranch elTema = new TocItemBranch(lyr);
335
            elTema.setSize(sizeBranch);
336

    
337
            DefaultMutableTreeNode nodeLayer =
338
                new DefaultMutableTreeNode(elTema);
339

    
340
            m_TreeModel.insertNodeInto(nodeLayer, parentNode,
341
                parentNode.getChildCount());
342

    
343
            if (lyr instanceof LayerCollection) {
344
                LayerCollection group = (LayerCollection) lyr;
345
                doRefresh(group, nodeLayer);
346
            } else {
347
                if (lyr instanceof Classifiable) {// && !(lyr instanceof
348
                                                  // FLyrAnnotation)) {
349

    
350
                    Classifiable classifiable = (Classifiable) lyr;
351
                    ILegend legendInfo = classifiable.getLegend();
352

    
353
                    try {
354
                        if (legendInfo instanceof IClassifiedLegend) {
355
                            IClassifiedLegend cl =
356
                                (IClassifiedLegend) legendInfo;
357
                            String[] descriptions = cl.getDescriptions();
358
                            ISymbol[] symbols = cl.getSymbols();
359

    
360
                            for (int j = 0; j < descriptions.length; j++) {
361
                                TocItemLeaf itemLeaf;
362
                                itemLeaf =
363
                                    new TocItemLeaf(symbols[j],
364
                                        descriptions[j], classifiable.getShapeType());
365
                                itemLeaf.setSize(sizeLeaf);
366

    
367
                                DefaultMutableTreeNode nodeValue =
368
                                    new DefaultMutableTreeNode(itemLeaf);
369
                                m_TreeModel.insertNodeInto(nodeValue,
370
                                    nodeLayer, nodeLayer.getChildCount());
371

    
372
                            }
373
                        }
374

    
375
                        if (legendInfo instanceof ISingleSymbolLegend
376
                            && (legendInfo.getDefaultSymbol() != null)) {
377
                            TocItemLeaf itemLeaf;
378
                            itemLeaf =
379
                                new TocItemLeaf(legendInfo.getDefaultSymbol(),
380
                                    legendInfo.getDefaultSymbol()
381
                                        .getDescription(), classifiable.getShapeType());
382
                            itemLeaf.setSize(sizeLeaf);
383

    
384
                            DefaultMutableTreeNode nodeValue =
385
                                new DefaultMutableTreeNode(itemLeaf);
386
                            m_TreeModel.insertNodeInto(nodeValue, nodeLayer,
387
                                nodeLayer.getChildCount());
388
                        }
389
                        
390
                        if (legendInfo instanceof IHasImageLegend) {
391
                            TocItemLeaf itemLeaf;
392
                            IHasImageLegend imageLegend = (IHasImageLegend) legendInfo;
393
                            Image image = imageLegend.getImageLegend();
394

    
395
                            if (image != null) {
396
                                itemLeaf = new TocItemLeaf();
397
                                itemLeaf.setImageLegend(image, "", new Dimension(
398
                                    image.getWidth(null), image.getHeight(null)));// new
399
                                                                                  // Dimension(150,200));
400

    
401
                                DefaultMutableTreeNode nodeValue =
402
                                    new DefaultMutableTreeNode(itemLeaf);
403
                                m_TreeModel.insertNodeInto(nodeValue, nodeLayer,
404
                                    nodeLayer.getChildCount());
405
                            }
406
                        }
407
                    } catch (ReadException e) {
408
                        logger.error(MessageFormat.format(
409
                            "Can't add leyend of layer {0} to the TOC.", lyr),
410
                            e);
411
                    }
412
                } 
413
            } // if instanceof layers
414
        }
415
    }
416

    
417
    /**
418
     * @see com.iver.cit.opensig.gui.toc.ITocOrderListener#orderChanged(int,
419
     *      int)
420
     */
421
    public void orderChanged(int oldPos, int newPos, FLayers lpd) {
422
        try {
423
            lpd.moveTo(oldPos, newPos);
424
        } catch (CancelationException e) {
425
            logger.error("Can't change order of layers in TOC", e);
426
        }
427
        mapContext.invalidate();
428
    }
429

    
430
    public void parentChanged(FLayers lpo, FLayers lpd, FLayer ls) {
431
        lpo.move(ls, lpd);
432
        mapContext.invalidate();
433
    }
434

    
435
    /*
436
     * (non-Javadoc)
437
     * 
438
     * @see java.awt.event.ComponentListener#componentHidden(java.awt.event.
439
     * ComponentEvent)
440
     */
441
    public void componentHidden(ComponentEvent e) {
442
    }
443

    
444
    /*
445
     * (non-Javadoc)
446
     * 
447
     * @see
448
     * java.awt.event.ComponentListener#componentMoved(java.awt.event.ComponentEvent
449
     * )
450
     */
451
    public void componentMoved(ComponentEvent e) {
452
    }
453

    
454
    /*
455
     * (non-Javadoc)
456
     * 
457
     * @see java.awt.event.ComponentListener#componentResized(java.awt.event.
458
     * ComponentEvent)
459
     */
460
    public void componentResized(ComponentEvent e) {
461
        DefaultMutableTreeNode n;
462
        @SuppressWarnings("rawtypes")
463
        Enumeration enumeration = m_Root.children();
464

    
465
        while (enumeration.hasMoreElements()) {
466
            n = (DefaultMutableTreeNode) enumeration.nextElement();
467

    
468
            if (n.getUserObject() instanceof TocItemBranch) {
469
                ITocItem item = (ITocItem) n.getUserObject();
470
                Dimension szAnt = item.getSize();
471
                item.setSize(new Dimension(this.getWidth() - 40, szAnt.height));
472
            }
473

    
474
        }
475
    }
476

    
477
    /*
478
     * (non-Javadoc)
479
     * 
480
     * @see
481
     * java.awt.event.ComponentListener#componentShown(java.awt.event.ComponentEvent
482
     * )
483
     */
484
    public void componentShown(ComponentEvent e) {
485
    }
486

    
487
    /*
488
     * (non-Javadoc)
489
     * 
490
     * @see
491
     * com.iver.cit.gvsig.fmap.layers.LayerListener#legendChanged(com.iver.cit
492
     * .gvsig.fmap.rendering.LegendChangedEvent)
493
     */
494
    public void legendChanged(final LegendChangedEvent e) {
495
        if (!SwingUtilities.isEventDispatchThread()) {
496
            SwingUtilities.invokeLater(new Runnable() {
497

    
498
                public void run() {
499
                    legendChanged(e);
500
                }
501
            });
502
            return;
503
        }
504
        refresh();
505
    }
506

    
507
    /*
508
     * (non-Javadoc)
509
     * 
510
     * @see
511
     * com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#layerAdded(com
512
     * .iver.cit.gvsig.fmap.layers.LayerCollectionEvent)
513
     */
514
    public void layerAdded(final LayerCollectionEvent e) {
515
        if (!SwingUtilities.isEventDispatchThread()) {
516
            SwingUtilities.invokeLater(new Runnable() {
517

    
518
                public void run() {
519
                    layerAdded(e);
520
                }
521
            });
522
            return;
523
        }
524
        refresh();
525
    }
526

    
527
    /*
528
     * (non-Javadoc)
529
     * 
530
     * @see
531
     * com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#layerMoved(com
532
     * .iver.cit.gvsig.fmap.layers.LayerPositionEvent)
533
     */
534
    public void layerMoved(final LayerPositionEvent e) {
535
        if (!SwingUtilities.isEventDispatchThread()) {
536
            SwingUtilities.invokeLater(new Runnable() {
537

    
538
                public void run() {
539
                    layerMoved(e);
540
                }
541
            });
542
            return;
543
        }
544
        refresh();
545
    }
546

    
547
    /*
548
     * (non-Javadoc)
549
     * 
550
     * @see
551
     * com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#layerRemoved(com
552
     * .iver.cit.gvsig.fmap.layers.LayerCollectionEvent)
553
     */
554
    public void layerRemoved(final LayerCollectionEvent e) {
555
        if (!SwingUtilities.isEventDispatchThread()) {
556
            SwingUtilities.invokeLater(new Runnable() {
557

    
558
                public void run() {
559
                    layerRemoved(e);
560
                }
561
            });
562
            return;
563
        }
564
        m_ItemsExpanded.remove(e.getAffectedLayer().getName());
565
        refresh();
566
    }
567

    
568
    /*
569
     * (non-Javadoc)
570
     * 
571
     * @see
572
     * com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#layerAdding(com
573
     * .iver.cit.gvsig.fmap.layers.LayerCollectionEvent)
574
     */
575
    public void layerAdding(LayerCollectionEvent e) throws CancelationException {
576
    }
577

    
578
    /*
579
     * (non-Javadoc)
580
     * 
581
     * @see
582
     * com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#layerMoving(com
583
     * .iver.cit.gvsig.fmap.layers.LayerPositionEvent)
584
     */
585
    public void layerMoving(LayerPositionEvent e) throws CancelationException {
586
    }
587

    
588
    /*
589
     * (non-Javadoc)
590
     * 
591
     * @see
592
     * com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#layerRemoving(
593
     * com.iver.cit.gvsig.fmap.layers.LayerCollectionEvent)
594
     */
595
    public void layerRemoving(LayerCollectionEvent e)
596
        throws CancelationException {
597
    }
598

    
599
    /*
600
     * (non-Javadoc)
601
     * 
602
     * @see
603
     * com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#activationChanged
604
     * (com.iver.cit.gvsig.fmap.layers.LayerCollectionEvent)
605
     */
606
    public void activationChanged(LayerCollectionEvent e)
607
        throws CancelationException {
608
        repaint();
609
    }
610

    
611
    /*
612
     * (non-Javadoc)
613
     * 
614
     * @see
615
     * com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#visibilityChanged
616
     * (com.iver.cit.gvsig.fmap.layers.LayerCollectionEvent)
617
     */
618
    public void visibilityChanged(final LayerCollectionEvent e)
619
        throws CancelationException {
620
        if (!SwingUtilities.isEventDispatchThread()) {
621
            SwingUtilities.invokeLater(new Runnable() {
622

    
623
                public void run() {
624
                    visibilityChanged(e);
625
                }
626
            });
627
            return;
628
        }
629
        repaint();
630
    }
631

    
632
    /*
633
     * (non-Javadoc)
634
     * 
635
     * @see
636
     * javax.swing.event.TreeExpansionListener#treeCollapsed(javax.swing.event
637
     * .TreeExpansionEvent)
638
     */
639
    public void treeCollapsed(TreeExpansionEvent event) {
640
        TreePath path = event.getPath();
641
        DefaultMutableTreeNode n =
642
            (DefaultMutableTreeNode) path.getLastPathComponent();
643

    
644
        if (n.getUserObject() instanceof ITocItem) {
645
            ITocItem item = (ITocItem) n.getUserObject();
646
            Boolean b = Boolean.FALSE;
647

    
648
            m_ItemsExpanded.put(item.getLabel(), b);
649
        }
650
    }
651

    
652
    /*
653
     * (non-Javadoc)
654
     * 
655
     * @see
656
     * javax.swing.event.TreeExpansionListener#treeExpanded(javax.swing.event
657
     * .TreeExpansionEvent)
658
     */
659
    public void treeExpanded(TreeExpansionEvent event) {
660
        TreePath path = event.getPath();
661
        DefaultMutableTreeNode n =
662
            (DefaultMutableTreeNode) path.getLastPathComponent();
663

    
664
        if (n.getUserObject() instanceof ITocItem) {
665
            ITocItem item = (ITocItem) n.getUserObject();
666
            Boolean b = Boolean.TRUE;
667

    
668
            m_ItemsExpanded.put(item.getLabel(), b);
669
        }
670
    }
671

    
672
    /**
673
     * Obtiene el JScrollPane que contiene el TOC
674
     * 
675
     * @return JScrollPane que contiene el TOC
676
     */
677
    public JScrollPane getJScrollPane() {
678
        return this.m_Scroller;
679
    }
680

    
681
    /**
682
     * DOCUMENT ME!
683
     * 
684
     * @return DOCUMENT ME!
685
     */
686
    public DnDJTree getTree() {
687
        return m_Tree;
688
    }
689

    
690
    /**
691
     * Clase Listener que reacciona al pulsar sobre el checkbox de un nodo y
692
     * crea un popupmenu al pulsar el bot?n derecho.
693
     */
694
    class NodeSelectionListener extends MouseAdapter implements ActionListener {
695

    
696
        JTree tree;
697

    
698
        JDialog dlg;
699

    
700
        JColorChooser colorChooser;
701

    
702
        FPopupMenu popmenu = null;
703

    
704
        DefaultMutableTreeNode node;
705

    
706
        /**
707
         * Crea un nuevo NodeSelectionListener.
708
         * 
709
         * @param tree
710
         *            DOCUMENT ME!
711
         */
712
        NodeSelectionListener(JTree tree) {
713
            this.tree = tree;
714
        }
715

    
716
        /**
717
         * DOCUMENT ME!
718
         * 
719
         * @param e
720
         *            DOCUMENT ME!
721
         */
722
        public void mouseClicked(MouseEvent e) {
723
            int x = e.getX();
724
            int y = e.getY();
725
            int row = tree.getRowForLocation(x, y);
726
            TreePath path = tree.getPathForRow(row);
727
            LayerCollection layers = mapContext.getLayers();
728

    
729
            if (path != null) {
730
                if (e.getClickCount() == 1) {
731
                    // this fixes a bug when double-clicking. JTree by default
732
                    // expands the tree when double-clicking, so we capture a
733
                    // different node in the second click than in the first
734
                    node = (DefaultMutableTreeNode) path.getLastPathComponent();
735
                }
736

    
737
                if (node != null
738
                    && node.getUserObject() instanceof TocItemBranch) {
739
                    // double click with left button ON A BRANCH/NODE (layer)
740
                    if (e.getClickCount() >= 2
741
                        && e.getButton() == MouseEvent.BUTTON1) {
742
                        e.consume();
743
                        PluginServices.getMDIManager().setWaitCursor();
744
                        try {
745
                            TocItemBranch leaf =
746
                                (TocItemBranch) node.getUserObject();
747

    
748
                            IContextMenuAction action =
749
                                leaf.getDoubleClickAction();
750
                            if (action != null) {
751
                                /*
752
                                 * if there is an action associated with the
753
                                 * double-clicked element it will be fired for
754
                                 * it and FOR ALL OTHER COMPATIBLES THAT HAVE
755
                                 * BEEN ACTIVATED.
756
                                 */
757
                                ArrayList<FLayer> targetLayers =
758
                                    new ArrayList<FLayer>();
759

    
760
                                TocItemBranch owner =
761
                                    (TocItemBranch) node.getUserObject();
762

    
763
                                FLayer masterLayer = owner.getLayer();
764
                                targetLayers.add(masterLayer);
765
                                FLayer[] actives =
766
                                    mapContext.getLayers().getActives();
767
                                for (int i = 0; i < actives.length; i++) {
768
                                    if (actives[i].getClass().equals(
769
                                        masterLayer.getClass())) {
770
                                        if (actives[i] instanceof FLyrVect) {
771
                                            FLyrVect vectorLayer =
772
                                                (FLyrVect) actives[i];
773
                                            FLyrVect vectorMaster =
774
                                                (FLyrVect) masterLayer;
775
                                            if (vectorLayer.getShapeType() == vectorMaster
776
                                                .getShapeType()) {
777
                                                targetLayers.add(vectorLayer);
778
                                            } else {
779
                                                vectorLayer.setActive(false);
780
                                            }
781
                                        }
782
                                        // TODO for the rest of layer types
783
                                        // (i.e. FLyrRaster)
784
                                    } else {
785
                                        actives[i].setActive(false);
786
                                    }
787
                                }
788
                                action.execute(leaf,
789
                                    targetLayers.toArray(new FLayer[0]));
790
                            }
791
                        } catch (Exception ex) {
792
                            NotificationManager.addError(ex);
793
                        } finally {
794
                            PluginServices.getMDIManager().restoreCursor();
795
                        }
796
                        return;
797
                    }
798

    
799
                    TocItemBranch elTema = (TocItemBranch) node.getUserObject();
800
                    FLayer lyr = elTema.getLayer();
801
                    lyr.getMapContext().beginAtomicEvent();
802

    
803
                    if (((e.getModifiers() & InputEvent.SHIFT_MASK) != 0)
804
                        && (e.getButton() == MouseEvent.BUTTON1)) {
805
                        FLayer[] activeLayers = layers.getActives();
806
                        if (activeLayers.length > 0) {
807
                            selectInterval(layers, lyr);
808
                        } else {
809
                            updateActive(lyr, !lyr.isActive());
810
                        }
811

    
812
                    } else {
813
                        if (!((e.getModifiers() & InputEvent.CTRL_MASK) != 0)
814
                            && (e.getButton() == MouseEvent.BUTTON1)) {
815
                            layers.setAllActives(false);
816
                        }
817
                        if (e.getButton() == MouseEvent.BUTTON1) {
818
                            // lyr.setActive(true);
819
                            updateActive(lyr, !lyr.isActive());
820
                        }
821
                    }
822
                    // Si pertenece a un grupo, lo ponemos activo tambi?n.
823
                    // FLayer parentLayer = lyr.getParentLayer();
824

    
825
                    /*
826
                     * if (parentLayer != null) { parentLayer.setActive(true); }
827
                     */
828
                    Point layerNodeLocation =
829
                        tree.getUI().getPathBounds(tree, path).getLocation();
830

    
831
                    // Rect?ngulo que representa el checkbox
832
                    Rectangle checkBoxBounds =
833
                        m_TocRenderer.getCheckBoxBounds();
834
                    checkBoxBounds.translate((int) layerNodeLocation.getX(),
835
                        (int) layerNodeLocation.getY());
836

    
837
                    if (checkBoxBounds.contains(e.getPoint())) {
838
                        updateVisible(lyr);
839
                    }
840

    
841
                    // }
842
                    if (e.getButton() == MouseEvent.BUTTON3) {
843
                        // Boton derecho sobre un nodo del arbol
844
                        // if ((e.getModifiers() & InputEvent.META_MASK) != 0) {
845
                        popmenu = new FPopupMenu(mapContext, node);
846
                        tree.add(popmenu);
847

    
848
                        popmenu.show(e.getComponent(), e.getX(), e.getY());
849

    
850
                        // }
851
                    }
852

    
853
                    lyr.getMapContext().endAtomicEvent();
854
                }
855

    
856
                if (node != null && node.getUserObject() instanceof TocItemLeaf) {
857
                    // double click with left button ON A LEAF (ISymbol)
858
                    if (e.getClickCount() >= 2
859
                        && e.getButton() == MouseEvent.BUTTON1) {
860
                        e.consume();
861

    
862
                        PluginServices.getMDIManager().setWaitCursor();
863
                        try {
864
                            TocItemLeaf leaf =
865
                                (TocItemLeaf) node.getUserObject();
866
                            IContextMenuAction action =
867
                                leaf.getDoubleClickAction();
868
                            if (action != null) {
869
                                /*
870
                                 * if there is an action associated with the
871
                                 * double-clicked element it will be fired for
872
                                 * it and FOR ALL OTHER COMPATIBLES THAT HAVE
873
                                 * BEEN ACTIVATED.
874
                                 */
875
                                ArrayList<FLayer> targetLayers =
876
                                    new ArrayList<FLayer>();
877

    
878
                                TocItemBranch owner =
879
                                    (TocItemBranch) ((DefaultMutableTreeNode) node
880
                                        .getParent()).getUserObject();
881

    
882
                                FLayer masterLayer = owner.getLayer();
883
                                targetLayers.add(masterLayer);
884
                                FLayer[] actives =
885
                                    mapContext.getLayers().getActives();
886
                                for (int i = 0; i < actives.length; i++) {
887
                                    if (actives[i].getClass().equals(
888
                                        masterLayer.getClass())) {
889
                                        if (actives[i] instanceof FLyrVect) {
890
                                            FLyrVect vectorLayer =
891
                                                (FLyrVect) actives[i];
892
                                            FLyrVect vectorMaster =
893
                                                (FLyrVect) masterLayer;
894
                                            int masterLayerShapetypeOF_THE_LEGEND =
895
                                                ((IVectorLegend) vectorMaster
896
                                                    .getLegend())
897
                                                    .getShapeType();
898
                                            int anotherVectorLayerShapetypeOF_THE_LEGEND =
899
                                                ((IVectorLegend) vectorLayer
900
                                                    .getLegend())
901
                                                    .getShapeType();
902
                                            if (masterLayerShapetypeOF_THE_LEGEND == anotherVectorLayerShapetypeOF_THE_LEGEND) {
903
                                                targetLayers.add(vectorLayer);
904
                                            } else {
905
                                                vectorLayer.setActive(false);
906
                                            }
907
                                        }
908
                                        // TODO for the rest of layer types
909
                                        // (i.e. FLyrRaster)
910
                                    } else {
911
                                        actives[i].setActive(false);
912
                                    }
913
                                }
914
                                action.execute(leaf,
915
                                    targetLayers.toArray(new FLayer[0]));
916
                            }
917
                        } catch (Exception ex) {
918
                            NotificationManager.addError(ex);
919
                        } finally {
920
                            PluginServices.getMDIManager().restoreCursor();
921
                        }
922
                        return;
923
                    }
924

    
925
                    // Boton derecho sobre un Simbolo
926
                    // TocItemLeaf auxLeaf = (TocItemLeaf) node.getUserObject();
927
                    // FSymbol theSym = auxLeaf.getSymbol();
928
                    if ((e.getModifiers() & InputEvent.META_MASK) != 0) {
929
                        popmenu = new FPopupMenu(mapContext, node);
930
                        tree.add(popmenu);
931
                        popmenu.show(e.getComponent(), e.getX(), e.getY());
932
                    }
933
                }
934

    
935
                ((DefaultTreeModel) tree.getModel()).nodeChanged(node);
936

    
937
                if (row == 0) {
938
                    tree.revalidate();
939
                    tree.repaint();
940
                }
941

    
942
                if (PluginServices.getMainFrame() != null) {
943
                    PluginServices.getMainFrame().enableControls();
944
                }
945
            } else {
946
                if (e.getButton() == MouseEvent.BUTTON3) {
947
                    popmenu = new FPopupMenu(mapContext, null);
948
                    tree.add(popmenu);
949
                    popmenu.show(e.getComponent(), e.getX(), e.getY());
950
                }
951

    
952
            }
953
        }
954

    
955
        private void selectInterval(LayerCollection layers, FLayer lyr) {
956
            FLayer[] activeLayers = layers.getActives();
957
            // if (activeLayers[0].getParentLayer() instanceof FLayers &&
958
            // activeLayers[0].getParentLayer().getParentLayer()!=null) {
959
            // selectInterval((LayerCollection)activeLayers[0].getParentLayer(),lyr);
960
            // }
961
            for (int j = 0; j < layers.getLayersCount(); j++) {
962
                FLayer layerAux = layers.getLayer(j);
963
                // Si se cumple esta condici?n es porque la primera capa que nos
964
                // encontramos en el TOC es la que estaba activa
965
                if (activeLayers[0].equals(layerAux)) {
966
                    boolean isSelected = false;
967
                    for (int i = 0; i < layers.getLayersCount(); i++) {
968
                        FLayer layer = layers.getLayer(i);
969
                        if (!isSelected) {
970
                            isSelected = layer.isActive();
971
                        } else {
972
                            updateActive(layer, true);
973
                            if (lyr.equals(layer)) {
974
                                isSelected = false;
975
                            }
976
                        }
977
                    }
978
                    break;
979
                } else
980
                    // Si se cumple esta condici?n es porque la primera capa que
981
                    // nos
982
                    // encontramos en el TOC es la que acabamos de seleccionar
983
                    if (lyr.equals(layerAux)) {
984
                        boolean isSelected = false;
985
                        for (int i = layers.getLayersCount() - 1; i >= 0; i--) {
986
                            FLayer layer = layers.getLayer(i);
987
                            if (!isSelected) {
988
                                isSelected = layer.isActive();
989
                            } else {
990
                                updateActive(layer, true);
991
                                if (lyr.equals(layer)) {
992
                                    isSelected = false;
993
                                }
994
                            }
995
                        }
996
                        break;
997
                    }
998
            }
999

    
1000
        }
1001

    
1002
        /**
1003
         * DOCUMENT ME!
1004
         * 
1005
         * @param lyr
1006
         *            DOCUMENT ME!
1007
         * @param active
1008
         *            DOCUMENT ME!
1009
         */
1010
        private void updateActive(FLayer lyr, boolean active) {
1011
            lyr.setActive(active);
1012
            updateActiveChild(lyr);
1013
        }
1014

    
1015
        /**
1016
         * DOCUMENT ME!
1017
         * 
1018
         * @param lyr
1019
         *            DOCUMENT ME!
1020
         */
1021
        private void updateActiveChild(FLayer lyr) {
1022
            if (lyr instanceof FLayers) { // Es la raiz de una rama o
1023
                // cualquier nodo intermedio.
1024

    
1025
                FLayers layergroup = (FLayers) lyr;
1026

    
1027
                for (int i = 0; i < layergroup.getLayersCount(); i++) {
1028
                    layergroup.getLayer(i).setActive(lyr.isActive());
1029
                    updateActiveChild(layergroup.getLayer(i));
1030
                }
1031
            }
1032
        }
1033

    
1034
        /**
1035
         * Actualiza la visibilidad de la capas.
1036
         * 
1037
         * @param lyr
1038
         *            Capa sobre la que se est? clickando.
1039
         */
1040
        private void updateVisible(FLayer lyr) {
1041
            if (lyr.isAvailable()) {
1042
                lyr.setVisible(!lyr.visibleRequired());
1043
                updateVisibleChild(lyr);
1044
                updateVisibleParent(lyr);
1045
            }
1046
        }
1047

    
1048
        /**
1049
         * Actualiza de forma recursiva la visibilidad de los hijos de la capa
1050
         * que se pasa como par?metro.
1051
         * 
1052
         * @param lyr
1053
         *            Capa a actualizar.
1054
         */
1055
        private void updateVisibleChild(FLayer lyr) {
1056
            if (lyr instanceof FLayers) { // Es la raiz de una rama o
1057
                                          // cualquier nodo intermedio.
1058

    
1059
                FLayers layergroup = (FLayers) lyr;
1060

    
1061
                for (int i = 0; i < layergroup.getLayersCount(); i++) {
1062
                    layergroup.getLayer(i).setVisible(lyr.visibleRequired());
1063
                    updateVisibleChild(layergroup.getLayer(i));
1064
                }
1065
            }
1066
        }
1067

    
1068
        /**
1069
         * Actualiza de forma recursiva la visibilidad del padre de la capa que
1070
         * se pasa como par?metro.
1071
         * 
1072
         * @param lyr
1073
         *            Capa a actualizar.
1074
         */
1075
        private void updateVisibleParent(FLayer lyr) {
1076
            FLayers parent = lyr.getParentLayer();
1077

    
1078
            if (parent != null) {
1079
                boolean parentVisible = false;
1080

    
1081
                for (int i = 0; i < parent.getLayersCount(); i++) {
1082
                    if (parent.getLayer(i).visibleRequired()) {
1083
                        parentVisible = true;
1084
                    }
1085
                }
1086

    
1087
                parent.setVisible(parentVisible);
1088
                updateVisibleParent(parent);
1089
            }
1090
        }
1091

    
1092
        /**
1093
         * DOCUMENT ME!
1094
         * 
1095
         * @param arg0
1096
         *            DOCUMENT ME!
1097
         */
1098
        public void actionPerformed(ActionEvent arg0) {
1099
        }
1100

    
1101
        /**
1102
         * DOCUMENT ME!
1103
         * 
1104
         * @param arg0
1105
         *            DOCUMENT ME!
1106
         */
1107
        public void mouseReleased(MouseEvent arg0) {
1108
            super.mouseReleased(arg0);
1109
        }
1110

    
1111
        /**
1112
         * DOCUMENT ME!
1113
         * 
1114
         * @param arg0
1115
         *            DOCUMENT ME!
1116
         */
1117
        public void mouseEntered(MouseEvent arg0) {
1118
            super.mouseEntered(arg0);
1119
        }
1120
    }
1121
    
1122
    private boolean invisibilityIsForced() {
1123
        
1124
        PluginServices ps = PluginServices.getPluginServices(this);
1125
        XMLEntity xml = ps.getPersistentXML();
1126

    
1127
        if (xml.contains(ViewPage.ADD_NEW_LAYERS_IN_INVISIBLE_MODE_KEY_NAME)) {
1128
            // Get invisibility value
1129
            return xml.getBooleanProperty(ViewPage.ADD_NEW_LAYERS_IN_INVISIBLE_MODE_KEY_NAME);
1130
        } else {
1131
            // not found in preferences
1132
            return false;
1133
        }
1134
    }
1135

    
1136
}