Statistics
| Revision:

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

History | View | Annotate | Download (40.6 KB)

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

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

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

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

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

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

    
102
    /**
103
     * 
104
     */
105
    private static final long serialVersionUID = 5689047685537359038L;
106

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

    
112
    private MapContext mapContext;
113

    
114
    private DnDJTree m_Tree;
115

    
116
    private DefaultTreeModel m_TreeModel;
117

    
118
    private DefaultMutableTreeNode m_Root;
119

    
120
    private TOCRenderer m_TocRenderer;
121

    
122
    private JScrollPane m_Scroller;
123

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

    
128
    private NodeSelectionListener nodeSelectionListener = null;
129

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

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

    
144
        m_TocRenderer = new TOCRenderer(m_Tree.getBackground());
145
        m_Tree.setCellRenderer(m_TocRenderer);
146

    
147
        m_Tree.setRootVisible(false);
148

    
149
        // m_Tree.setExpandsSelectedPaths(true);
150
        // m_Tree.setAutoscrolls(true);
151
        m_Tree.setShowsRootHandles(true);
152

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

    
161
        this.addComponentListener(this);
162

    
163
        m_Tree.addTreeExpansionListener(this);
164

    
165
        m_Tree.addOrderListener(this);
166

    
167
        m_Tree.setRowHeight(0); // Para que lo determine el renderer
168

    
169
        m_Scroller = new JScrollPane(m_Tree);
170
        m_Scroller.setBorder(BorderFactory.createEmptyBorder());
171

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

    
182
        // refresh();
183
    }
184

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

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

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

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

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

    
223
                if (e.getLayerEvents().length > 0) {
224
                    repaint();
225
                }
226

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

    
241
                       if (invisibilityIsForced()) {
242
                           events[i].getAffectedLayer().setVisible(false);
243
                       }
244
                   }
245
                   // ===================================================
246
                }
247
            }
248
        });
249

    
250
        refresh();
251
    }
252

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

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

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

    
278
                return;
279
            }
280

    
281
            if (b.booleanValue()) {
282
                m_Tree.expandPath(path);
283
            } else {
284
                m_Tree.collapsePath(path);
285
            }
286
        }
287
    }
288

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

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

    
309
        m_TreeModel.reload();
310

    
311
        setExpandedNodes(m_Root);
312
    }
313

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

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

    
334
            DefaultMutableTreeNode nodeLayer =
335
                new DefaultMutableTreeNode(elTema);
336

    
337
            m_TreeModel.insertNodeInto(nodeLayer, parentNode,
338
                parentNode.getChildCount());
339

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

    
347
                    Classifiable classifiable = (Classifiable) lyr;
348
                    ILegend legendInfo = classifiable.getLegend();
349

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

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

    
364
                                DefaultMutableTreeNode nodeValue =
365
                                    new DefaultMutableTreeNode(itemLeaf);
366
                                m_TreeModel.insertNodeInto(nodeValue,
367
                                    nodeLayer, nodeLayer.getChildCount());
368

    
369
                            }
370
                        }
371

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

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

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

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

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

    
427
    public void parentChanged(FLayers lpo, FLayers lpd, FLayer ls) {
428
        lpo.move(ls, lpd);
429
        mapContext.invalidate();
430
    }
431

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

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

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

    
462
        while (enumeration.hasMoreElements()) {
463
            n = (DefaultMutableTreeNode) enumeration.nextElement();
464

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

    
471
        }
472
    }
473

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

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

    
495
                public void run() {
496
                    legendChanged(e);
497
                }
498
            });
499
            return;
500
        }
501
        refresh();
502
    }
503

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

    
515
                public void run() {
516
                    layerAdded(e);
517
                }
518
            });
519
            return;
520
        }
521
        refresh();
522
    }
523

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

    
535
                public void run() {
536
                    layerMoved(e);
537
                }
538
            });
539
            return;
540
        }
541
        refresh();
542
    }
543

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

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

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

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

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

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

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

    
620
                public void run() {
621
                    visibilityChanged(e);
622
                }
623
            });
624
            return;
625
        }
626
        repaint();
627
    }
628

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

    
641
        if (n.getUserObject() instanceof ITocItem) {
642
            ITocItem item = (ITocItem) n.getUserObject();
643
            Boolean b = Boolean.FALSE;
644

    
645
            m_ItemsExpanded.put(item.getLabel(), b);
646
        }
647
    }
648

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

    
661
        if (n.getUserObject() instanceof ITocItem) {
662
            ITocItem item = (ITocItem) n.getUserObject();
663
            Boolean b = Boolean.TRUE;
664

    
665
            m_ItemsExpanded.put(item.getLabel(), b);
666
        }
667
    }
668

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

    
678
    /**
679
     * DOCUMENT ME!
680
     * 
681
     * @return DOCUMENT ME!
682
     */
683
    public DnDJTree getTree() {
684
        return m_Tree;
685
    }
686

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

    
693
        JTree tree;
694

    
695
        JDialog dlg;
696

    
697
        JColorChooser colorChooser;
698

    
699
        FPopupMenu popmenu = null;
700

    
701
        DefaultMutableTreeNode node;
702

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

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

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

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

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

    
757
                                TocItemBranch owner =
758
                                    (TocItemBranch) node.getUserObject();
759

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

    
796
                    TocItemBranch elTema = (TocItemBranch) node.getUserObject();
797
                    FLayer lyr = elTema.getLayer();
798
                    lyr.getMapContext().beginAtomicEvent();
799

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

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

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

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

    
834
                    if (checkBoxBounds.contains(e.getPoint())) {
835
                        updateVisible(lyr);
836
                    }
837

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

    
845
                        popmenu.show(e.getComponent(), e.getX(), e.getY());
846

    
847
                        // }
848
                    }
849

    
850
                    lyr.getMapContext().endAtomicEvent();
851
                }
852

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

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

    
875
                                TocItemBranch owner =
876
                                    (TocItemBranch) ((DefaultMutableTreeNode) node
877
                                        .getParent()).getUserObject();
878

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

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

    
932
                ((DefaultTreeModel) tree.getModel()).nodeChanged(node);
933

    
934
                if (row == 0) {
935
                    tree.revalidate();
936
                    tree.repaint();
937
                }
938

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

    
949
            }
950
        }
951

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

    
997
        }
998

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

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

    
1022
                FLayers layergroup = (FLayers) lyr;
1023

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

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

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

    
1056
                FLayers layergroup = (FLayers) lyr;
1057

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

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

    
1075
            if (parent != null) {
1076
                boolean parentVisible = false;
1077

    
1078
                for (int i = 0; i < parent.getLayersCount(); i++) {
1079
                    if (parent.getLayer(i).visibleRequired()) {
1080
                        parentVisible = true;
1081
                    }
1082
                }
1083

    
1084
                parent.setVisible(parentVisible);
1085
                updateVisibleParent(parent);
1086
            }
1087
        }
1088

    
1089
        /**
1090
         * DOCUMENT ME!
1091
         * 
1092
         * @param arg0
1093
         *            DOCUMENT ME!
1094
         */
1095
        public void actionPerformed(ActionEvent arg0) {
1096
        }
1097

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

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

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

    
1133
}