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

History | View | Annotate | Download (40.6 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.slf4j.Logger;
61
import org.slf4j.LoggerFactory;
62

    
63
import org.gvsig.andami.PluginServices;
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

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

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

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

    
113
    private MapContext mapContext;
114

    
115
    private DnDJTree m_Tree;
116

    
117
    private DefaultTreeModel m_TreeModel;
118

    
119
    private DefaultMutableTreeNode m_Root;
120

    
121
    private TOCRenderer m_TocRenderer;
122

    
123
    private JScrollPane m_Scroller;
124

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

    
129
    private NodeSelectionListener nodeSelectionListener = null;
130

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

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

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

    
148
        m_Tree.setRootVisible(false);
149

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

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

    
162
        this.addComponentListener(this);
163

    
164
        m_Tree.addTreeExpansionListener(this);
165

    
166
        m_Tree.addOrderListener(this);
167

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

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

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

    
183
        // refresh();
184
    }
185

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

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

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

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

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

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

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

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

    
251
        refresh();
252
    }
253

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

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

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

    
279
                return;
280
            }
281

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

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

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

    
310
        m_TreeModel.reload();
311

    
312
        setExpandedNodes(m_Root);
313
    }
314

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

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

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

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

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

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

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

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

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

    
370
                            }
371
                        }
372

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

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

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

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

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

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

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

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

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

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

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

    
472
        }
473
    }
474

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
694
        JTree tree;
695

    
696
        JDialog dlg;
697

    
698
        JColorChooser colorChooser;
699

    
700
        FPopupMenu popmenu = null;
701

    
702
        DefaultMutableTreeNode node;
703

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
848
                        // }
849
                    }
850

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

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

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

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

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

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

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

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

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

    
950
            }
951
        }
952

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

    
998
        }
999

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

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

    
1023
                FLayers layergroup = (FLayers) lyr;
1024

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

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

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

    
1057
                FLayers layergroup = (FLayers) lyr;
1058

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

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

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

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

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

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

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

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

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

    
1134
}