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

History | View | Annotate | Download (41.3 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
                            int w = 0;
396
                            int h = 0;
397
                            
398
                            if(image != null) {
399
                                    w = image.getWidth(null);
400
                                    h = image.getHeight(null);
401
                            }
402
                            
403
                            if (image != null && w > 0 && h > 0) {
404
                                itemLeaf = new TocItemLeaf();
405
                                itemLeaf.setImageLegend(image, "", new Dimension(w, h));
406

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

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

    
436
    public void parentChanged(FLayers lpo, FLayers lpd, FLayer ls) {
437
        lpo.move(ls, lpd);
438
        mapContext.invalidate();
439
    }
440

    
441
    /*
442
     * (non-Javadoc)
443
     * 
444
     * @see java.awt.event.ComponentListener#componentHidden(java.awt.event.
445
     * ComponentEvent)
446
     */
447
    public void componentHidden(ComponentEvent e) {
448
    }
449

    
450
    /*
451
     * (non-Javadoc)
452
     * 
453
     * @see
454
     * java.awt.event.ComponentListener#componentMoved(java.awt.event.ComponentEvent
455
     * )
456
     */
457
    public void componentMoved(ComponentEvent e) {
458
    }
459

    
460
    /*
461
     * (non-Javadoc)
462
     * 
463
     * @see java.awt.event.ComponentListener#componentResized(java.awt.event.
464
     * ComponentEvent)
465
     */
466
    public void componentResized(ComponentEvent e) {
467
        DefaultMutableTreeNode n;
468
        @SuppressWarnings("rawtypes")
469
        Enumeration enumeration = m_Root.children();
470

    
471
        while (enumeration.hasMoreElements()) {
472
            n = (DefaultMutableTreeNode) enumeration.nextElement();
473

    
474
            if (n.getUserObject() instanceof TocItemBranch) {
475
                ITocItem item = (ITocItem) n.getUserObject();
476
                Dimension szAnt = item.getSize();
477
                item.setSize(new Dimension(this.getWidth() - 40, szAnt.height));
478
            }
479

    
480
        }
481
    }
482

    
483
    /*
484
     * (non-Javadoc)
485
     * 
486
     * @see
487
     * java.awt.event.ComponentListener#componentShown(java.awt.event.ComponentEvent
488
     * )
489
     */
490
    public void componentShown(ComponentEvent e) {
491
    }
492

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

    
504
                public void run() {
505
                    legendChanged(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#layerAdded(com
518
     * .iver.cit.gvsig.fmap.layers.LayerCollectionEvent)
519
     */
520
    public void layerAdded(final LayerCollectionEvent e) {
521
        if (!SwingUtilities.isEventDispatchThread()) {
522
            SwingUtilities.invokeLater(new Runnable() {
523

    
524
                public void run() {
525
                    layerAdded(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#layerMoved(com
538
     * .iver.cit.gvsig.fmap.layers.LayerPositionEvent)
539
     */
540
    public void layerMoved(final LayerPositionEvent e) {
541
        if (!SwingUtilities.isEventDispatchThread()) {
542
            SwingUtilities.invokeLater(new Runnable() {
543

    
544
                public void run() {
545
                    layerMoved(e);
546
                }
547
            });
548
            return;
549
        }
550
        refresh();
551
    }
552

    
553
    /*
554
     * (non-Javadoc)
555
     * 
556
     * @see
557
     * com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#layerRemoved(com
558
     * .iver.cit.gvsig.fmap.layers.LayerCollectionEvent)
559
     */
560
    public void layerRemoved(final LayerCollectionEvent e) {
561
        if (!SwingUtilities.isEventDispatchThread()) {
562
            SwingUtilities.invokeLater(new Runnable() {
563

    
564
                public void run() {
565
                    layerRemoved(e);
566
                }
567
            });
568
            return;
569
        }
570
        m_ItemsExpanded.remove(e.getAffectedLayer().getName());
571
        refresh();
572
    }
573

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

    
584
    /*
585
     * (non-Javadoc)
586
     * 
587
     * @see
588
     * com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#layerMoving(com
589
     * .iver.cit.gvsig.fmap.layers.LayerPositionEvent)
590
     */
591
    public void layerMoving(LayerPositionEvent e) throws CancelationException {
592
    }
593

    
594
    /*
595
     * (non-Javadoc)
596
     * 
597
     * @see
598
     * com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#layerRemoving(
599
     * com.iver.cit.gvsig.fmap.layers.LayerCollectionEvent)
600
     */
601
    public void layerRemoving(LayerCollectionEvent e)
602
        throws CancelationException {
603
    }
604

    
605
    /*
606
     * (non-Javadoc)
607
     * 
608
     * @see
609
     * com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#activationChanged
610
     * (com.iver.cit.gvsig.fmap.layers.LayerCollectionEvent)
611
     */
612
    public void activationChanged(LayerCollectionEvent e)
613
        throws CancelationException {
614
        repaint();
615
    }
616

    
617
    /*
618
     * (non-Javadoc)
619
     * 
620
     * @see
621
     * com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#visibilityChanged
622
     * (com.iver.cit.gvsig.fmap.layers.LayerCollectionEvent)
623
     */
624
    public void visibilityChanged(final LayerCollectionEvent e)
625
        throws CancelationException {
626
        if (!SwingUtilities.isEventDispatchThread()) {
627
            SwingUtilities.invokeLater(new Runnable() {
628

    
629
                public void run() {
630
                    visibilityChanged(e);
631
                }
632
            });
633
            return;
634
        }
635
        repaint();
636
    }
637

    
638
    /*
639
     * (non-Javadoc)
640
     * 
641
     * @see
642
     * javax.swing.event.TreeExpansionListener#treeCollapsed(javax.swing.event
643
     * .TreeExpansionEvent)
644
     */
645
    public void treeCollapsed(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.FALSE;
653

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

    
658
    /*
659
     * (non-Javadoc)
660
     * 
661
     * @see
662
     * javax.swing.event.TreeExpansionListener#treeExpanded(javax.swing.event
663
     * .TreeExpansionEvent)
664
     */
665
    public void treeExpanded(TreeExpansionEvent event) {
666
        TreePath path = event.getPath();
667
        DefaultMutableTreeNode n =
668
            (DefaultMutableTreeNode) path.getLastPathComponent();
669

    
670
        if (n.getUserObject() instanceof ITocItem) {
671
            ITocItem item = (ITocItem) n.getUserObject();
672
            Boolean b = Boolean.TRUE;
673

    
674
            m_ItemsExpanded.put(item.getLabel(), b);
675
        }
676
    }
677

    
678
    /**
679
     * Obtiene el JScrollPane que contiene el TOC
680
     * 
681
     * @return JScrollPane que contiene el TOC
682
     */
683
    public JScrollPane getJScrollPane() {
684
        return this.m_Scroller;
685
    }
686

    
687
    /**
688
     * DOCUMENT ME!
689
     * 
690
     * @return DOCUMENT ME!
691
     */
692
    public DnDJTree getTree() {
693
        return m_Tree;
694
    }
695

    
696
    /**
697
     * Clase Listener que reacciona al pulsar sobre el checkbox de un nodo y
698
     * crea un popupmenu al pulsar el bot?n derecho.
699
     */
700
    class NodeSelectionListener extends MouseAdapter implements ActionListener {
701

    
702
        JTree tree;
703

    
704
        JDialog dlg;
705

    
706
        JColorChooser colorChooser;
707

    
708
        FPopupMenu popmenu = null;
709

    
710
        DefaultMutableTreeNode node;
711

    
712
        /**
713
         * Crea un nuevo NodeSelectionListener.
714
         * 
715
         * @param tree
716
         *            DOCUMENT ME!
717
         */
718
        NodeSelectionListener(JTree tree) {
719
            this.tree = tree;
720
        }
721

    
722
        /**
723
         * DOCUMENT ME!
724
         * 
725
         * @param e
726
         *            DOCUMENT ME!
727
         */
728
        public void mouseClicked(MouseEvent e) {
729
            int x = e.getX();
730
            int y = e.getY();
731
            int row = tree.getRowForLocation(x, y);
732
            TreePath path = tree.getPathForRow(row);
733
            LayerCollection layers = mapContext.getLayers();
734

    
735
            if (path != null) {
736
                if (e.getClickCount() == 1) {
737
                    // this fixes a bug when double-clicking. JTree by default
738
                    // expands the tree when double-clicking, so we capture a
739
                    // different node in the second click than in the first
740
                    node = (DefaultMutableTreeNode) path.getLastPathComponent();
741
                }
742

    
743
                if (node != null
744
                    && node.getUserObject() instanceof TocItemBranch) {
745
                    // double click with left button ON A BRANCH/NODE (layer)
746
                    if (e.getClickCount() >= 2
747
                        && e.getButton() == MouseEvent.BUTTON1) {
748
                        e.consume();
749
                        PluginServices.getMDIManager().setWaitCursor();
750
                        try {
751
                            TocItemBranch leaf =
752
                                (TocItemBranch) node.getUserObject();
753

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

    
766
                                TocItemBranch owner =
767
                                    (TocItemBranch) node.getUserObject();
768

    
769
                                FLayer masterLayer = owner.getLayer();
770
                                targetLayers.add(masterLayer);
771
                                FLayer[] actives =
772
                                    mapContext.getLayers().getActives();
773
                                for (int i = 0; i < actives.length; i++) {
774
                                    if (actives[i].getClass().equals(
775
                                        masterLayer.getClass())) {
776
                                        if (actives[i] instanceof FLyrVect) {
777
                                            FLyrVect vectorLayer =
778
                                                (FLyrVect) actives[i];
779
                                            FLyrVect vectorMaster =
780
                                                (FLyrVect) masterLayer;
781
                                            if (vectorLayer.getShapeType() == vectorMaster
782
                                                .getShapeType()) {
783
                                                targetLayers.add(vectorLayer);
784
                                            } else {
785
                                                vectorLayer.setActive(false);
786
                                            }
787
                                        }
788
                                        // TODO for the rest of layer types
789
                                        // (i.e. FLyrRaster)
790
                                    } else {
791
                                        actives[i].setActive(false);
792
                                    }
793
                                }
794
                                
795
                                // Do nothing if there is a non-available layer
796
                                for (int k=0; k<targetLayers.size(); k++) {
797
                                    if (!targetLayers.get(k).isAvailable()) {
798
                                        return;
799
                                    }
800
                                }
801
                                
802
                                action.execute(leaf,
803
                                    targetLayers.toArray(new FLayer[0]));
804
                            }
805
                        } catch (Exception ex) {
806
                            NotificationManager.addError(ex);
807
                        } finally {
808
                            PluginServices.getMDIManager().restoreCursor();
809
                        }
810
                        return;
811
                    }
812

    
813
                    TocItemBranch elTema = (TocItemBranch) node.getUserObject();
814
                    FLayer lyr = elTema.getLayer();
815
                    lyr.getMapContext().beginAtomicEvent();
816

    
817
                    if (((e.getModifiers() & InputEvent.SHIFT_MASK) != 0)
818
                        && (e.getButton() == MouseEvent.BUTTON1)) {
819
                        FLayer[] activeLayers = layers.getActives();
820
                        if (activeLayers.length > 0) {
821
                            selectInterval(layers, lyr);
822
                        } else {
823
                            updateActive(lyr, !lyr.isActive());
824
                        }
825

    
826
                    } else {
827
                        if (!((e.getModifiers() & InputEvent.CTRL_MASK) != 0)
828
                            && (e.getButton() == MouseEvent.BUTTON1)) {
829
                            layers.setAllActives(false);
830
                        }
831
                        if (e.getButton() == MouseEvent.BUTTON1) {
832
                            // lyr.setActive(true);
833
                            updateActive(lyr, !lyr.isActive());
834
                        }
835
                    }
836
                    // Si pertenece a un grupo, lo ponemos activo tambi?n.
837
                    // FLayer parentLayer = lyr.getParentLayer();
838

    
839
                    /*
840
                     * if (parentLayer != null) { parentLayer.setActive(true); }
841
                     */
842
                    Point layerNodeLocation =
843
                        tree.getUI().getPathBounds(tree, path).getLocation();
844

    
845
                    // Rect?ngulo que representa el checkbox
846
                    Rectangle checkBoxBounds =
847
                        m_TocRenderer.getCheckBoxBounds();
848
                    checkBoxBounds.translate((int) layerNodeLocation.getX(),
849
                        (int) layerNodeLocation.getY());
850

    
851
                    if (checkBoxBounds.contains(e.getPoint())) {
852
                        updateVisible(lyr);
853
                    }
854

    
855
                    // }
856
                    if (e.getButton() == MouseEvent.BUTTON3) {
857
                        // Boton derecho sobre un nodo del arbol
858
                        // if ((e.getModifiers() & InputEvent.META_MASK) != 0) {
859
                        popmenu = new FPopupMenu(mapContext, node);
860
                        tree.add(popmenu);
861

    
862
                        popmenu.show(e.getComponent(), e.getX(), e.getY());
863

    
864
                        // }
865
                    }
866

    
867
                    lyr.getMapContext().endAtomicEvent();
868
                }
869

    
870
                if (node != null && node.getUserObject() instanceof TocItemLeaf) {
871
                    // double click with left button ON A LEAF (ISymbol)
872
                    if (e.getClickCount() >= 2
873
                        && e.getButton() == MouseEvent.BUTTON1) {
874
                        e.consume();
875

    
876
                        PluginServices.getMDIManager().setWaitCursor();
877
                        try {
878
                            TocItemLeaf leaf =
879
                                (TocItemLeaf) node.getUserObject();
880
                            IContextMenuAction action =
881
                                leaf.getDoubleClickAction();
882
                            if (action != null) {
883
                                /*
884
                                 * if there is an action associated with the
885
                                 * double-clicked element it will be fired for
886
                                 * it and FOR ALL OTHER COMPATIBLES THAT HAVE
887
                                 * BEEN ACTIVATED.
888
                                 */
889
                                ArrayList<FLayer> targetLayers =
890
                                    new ArrayList<FLayer>();
891

    
892
                                TocItemBranch owner =
893
                                    (TocItemBranch) ((DefaultMutableTreeNode) node
894
                                        .getParent()).getUserObject();
895

    
896
                                FLayer masterLayer = owner.getLayer();
897
                                targetLayers.add(masterLayer);
898
                                FLayer[] actives =
899
                                    mapContext.getLayers().getActives();
900
                                for (int i = 0; i < actives.length; i++) {
901
                                    if (actives[i].getClass().equals(
902
                                        masterLayer.getClass())) {
903
                                        if (actives[i] instanceof FLyrVect) {
904
                                            FLyrVect vectorLayer =
905
                                                (FLyrVect) actives[i];
906
                                            FLyrVect vectorMaster =
907
                                                (FLyrVect) masterLayer;
908
                                            int masterLayerShapetypeOF_THE_LEGEND =
909
                                                ((IVectorLegend) vectorMaster
910
                                                    .getLegend())
911
                                                    .getShapeType();
912
                                            int anotherVectorLayerShapetypeOF_THE_LEGEND =
913
                                                ((IVectorLegend) vectorLayer
914
                                                    .getLegend())
915
                                                    .getShapeType();
916
                                            if (masterLayerShapetypeOF_THE_LEGEND == anotherVectorLayerShapetypeOF_THE_LEGEND) {
917
                                                targetLayers.add(vectorLayer);
918
                                            } else {
919
                                                vectorLayer.setActive(false);
920
                                            }
921
                                        }
922
                                        // TODO for the rest of layer types
923
                                        // (i.e. FLyrRaster)
924
                                    } else {
925
                                        actives[i].setActive(false);
926
                                    }
927
                                }
928
                                action.execute(leaf,
929
                                    targetLayers.toArray(new FLayer[0]));
930
                            }
931
                        } catch (Exception ex) {
932
                            NotificationManager.addError(ex);
933
                        } finally {
934
                            PluginServices.getMDIManager().restoreCursor();
935
                        }
936
                        return;
937
                    }
938

    
939
                    // Boton derecho sobre un Simbolo
940
                    // TocItemLeaf auxLeaf = (TocItemLeaf) node.getUserObject();
941
                    // FSymbol theSym = auxLeaf.getSymbol();
942
                    if ((e.getModifiers() & InputEvent.META_MASK) != 0) {
943
                        popmenu = new FPopupMenu(mapContext, node);
944
                        tree.add(popmenu);
945
                        popmenu.show(e.getComponent(), e.getX(), e.getY());
946
                    }
947
                }
948

    
949
                ((DefaultTreeModel) tree.getModel()).nodeChanged(node);
950

    
951
                if (row == 0) {
952
                    tree.revalidate();
953
                    tree.repaint();
954
                }
955

    
956
                if (PluginServices.getMainFrame() != null) {
957
                    PluginServices.getMainFrame().enableControls();
958
                }
959
            } else {
960
                if (e.getButton() == MouseEvent.BUTTON3) {
961
                    popmenu = new FPopupMenu(mapContext, null);
962
                    tree.add(popmenu);
963
                    popmenu.show(e.getComponent(), e.getX(), e.getY());
964
                }
965

    
966
            }
967
        }
968

    
969
        private void selectInterval(LayerCollection layers, FLayer lyr) {
970
            FLayer[] activeLayers = layers.getActives();
971
            // if (activeLayers[0].getParentLayer() instanceof FLayers &&
972
            // activeLayers[0].getParentLayer().getParentLayer()!=null) {
973
            // selectInterval((LayerCollection)activeLayers[0].getParentLayer(),lyr);
974
            // }
975
            for (int j = 0; j < layers.getLayersCount(); j++) {
976
                FLayer layerAux = layers.getLayer(j);
977
                // Si se cumple esta condici?n es porque la primera capa que nos
978
                // encontramos en el TOC es la que estaba activa
979
                if (activeLayers[0].equals(layerAux)) {
980
                    boolean isSelected = false;
981
                    for (int i = 0; i < layers.getLayersCount(); i++) {
982
                        FLayer layer = layers.getLayer(i);
983
                        if (!isSelected) {
984
                            isSelected = layer.isActive();
985
                        } else {
986
                            updateActive(layer, true);
987
                            if (lyr.equals(layer)) {
988
                                isSelected = false;
989
                            }
990
                        }
991
                    }
992
                    break;
993
                } else
994
                    // Si se cumple esta condici?n es porque la primera capa que
995
                    // nos
996
                    // encontramos en el TOC es la que acabamos de seleccionar
997
                    if (lyr.equals(layerAux)) {
998
                        boolean isSelected = false;
999
                        for (int i = layers.getLayersCount() - 1; i >= 0; i--) {
1000
                            FLayer layer = layers.getLayer(i);
1001
                            if (!isSelected) {
1002
                                isSelected = layer.isActive();
1003
                            } else {
1004
                                updateActive(layer, true);
1005
                                if (lyr.equals(layer)) {
1006
                                    isSelected = false;
1007
                                }
1008
                            }
1009
                        }
1010
                        break;
1011
                    }
1012
            }
1013

    
1014
        }
1015

    
1016
        /**
1017
         * DOCUMENT ME!
1018
         * 
1019
         * @param lyr
1020
         *            DOCUMENT ME!
1021
         * @param active
1022
         *            DOCUMENT ME!
1023
         */
1024
        private void updateActive(FLayer lyr, boolean active) {
1025
            lyr.setActive(active);
1026
            updateActiveChild(lyr);
1027
        }
1028

    
1029
        /**
1030
         * DOCUMENT ME!
1031
         * 
1032
         * @param lyr
1033
         *            DOCUMENT ME!
1034
         */
1035
        private void updateActiveChild(FLayer lyr) {
1036
            if (lyr instanceof FLayers) { // Es la raiz de una rama o
1037
                // cualquier nodo intermedio.
1038

    
1039
                FLayers layergroup = (FLayers) lyr;
1040

    
1041
                for (int i = 0; i < layergroup.getLayersCount(); i++) {
1042
                    layergroup.getLayer(i).setActive(lyr.isActive());
1043
                    updateActiveChild(layergroup.getLayer(i));
1044
                }
1045
            }
1046
        }
1047

    
1048
        /**
1049
         * Actualiza la visibilidad de la capas.
1050
         * 
1051
         * @param lyr
1052
         *            Capa sobre la que se est? clickando.
1053
         */
1054
        private void updateVisible(FLayer lyr) {
1055
            if (lyr.isAvailable()) {
1056
                lyr.setVisible(!lyr.visibleRequired());
1057
                updateVisibleChild(lyr);
1058
                updateVisibleParent(lyr);
1059
            }
1060
        }
1061

    
1062
        /**
1063
         * Actualiza de forma recursiva la visibilidad de los hijos de la capa
1064
         * que se pasa como par?metro.
1065
         * 
1066
         * @param lyr
1067
         *            Capa a actualizar.
1068
         */
1069
        private void updateVisibleChild(FLayer lyr) {
1070
            if (lyr instanceof FLayers) { // Es la raiz de una rama o
1071
                                          // cualquier nodo intermedio.
1072

    
1073
                FLayers layergroup = (FLayers) lyr;
1074

    
1075
                for (int i = 0; i < layergroup.getLayersCount(); i++) {
1076
                    layergroup.getLayer(i).setVisible(lyr.visibleRequired());
1077
                    updateVisibleChild(layergroup.getLayer(i));
1078
                }
1079
            }
1080
        }
1081

    
1082
        /**
1083
         * Actualiza de forma recursiva la visibilidad del padre de la capa que
1084
         * se pasa como par?metro.
1085
         * 
1086
         * @param lyr
1087
         *            Capa a actualizar.
1088
         */
1089
        private void updateVisibleParent(FLayer lyr) {
1090
            FLayers parent = lyr.getParentLayer();
1091

    
1092
            if (parent != null) {
1093
                boolean parentVisible = false;
1094

    
1095
                for (int i = 0; i < parent.getLayersCount(); i++) {
1096
                    if (parent.getLayer(i).visibleRequired()) {
1097
                        parentVisible = true;
1098
                    }
1099
                }
1100

    
1101
                parent.setVisible(parentVisible);
1102
                updateVisibleParent(parent);
1103
            }
1104
        }
1105

    
1106
        /**
1107
         * DOCUMENT ME!
1108
         * 
1109
         * @param arg0
1110
         *            DOCUMENT ME!
1111
         */
1112
        public void actionPerformed(ActionEvent arg0) {
1113
        }
1114

    
1115
        /**
1116
         * DOCUMENT ME!
1117
         * 
1118
         * @param arg0
1119
         *            DOCUMENT ME!
1120
         */
1121
        public void mouseReleased(MouseEvent arg0) {
1122
            super.mouseReleased(arg0);
1123
        }
1124

    
1125
        /**
1126
         * DOCUMENT ME!
1127
         * 
1128
         * @param arg0
1129
         *            DOCUMENT ME!
1130
         */
1131
        public void mouseEntered(MouseEvent arg0) {
1132
            super.mouseEntered(arg0);
1133
        }
1134
    }
1135
    
1136
    private boolean invisibilityIsForced() {
1137
        
1138
        PluginServices ps = PluginServices.getPluginServices(this);
1139
        XMLEntity xml = ps.getPersistentXML();
1140

    
1141
        if (xml.contains(ViewPage.ADD_NEW_LAYERS_IN_INVISIBLE_MODE_KEY_NAME)) {
1142
            // Get invisibility value
1143
            return xml.getBooleanProperty(ViewPage.ADD_NEW_LAYERS_IN_INVISIBLE_MODE_KEY_NAME);
1144
        } else {
1145
            // not found in preferences
1146
            return false;
1147
        }
1148
    }
1149

    
1150
}