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

History | View | Annotate | Download (44.8 KB)

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

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

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

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

    
101
/**
102
 *
103
 * @author fjp
104
 */
105
public class TOC extends JComponent implements ITocOrderListener,
106
    LegendListener, LayerCollectionListener, TreeExpansionListener,
107
    ComponentListener, LegendContentsChangedListener {
108

    
109
    /**
110
     *
111
     */
112
    private static final long serialVersionUID = 5689047685537359038L;
113

    
114
    /**
115
     * Useful for debug the problems during the implementation.
116
     */
117
    private static Logger logger = LoggerFactory.getLogger(TOC.class);
118

    
119
    private MapContext mapContext;
120

    
121
    private DnDJTree m_Tree;
122

    
123
    private DefaultTreeModel m_TreeModel;
124

    
125
    private DefaultMutableTreeNode m_Root;
126

    
127
    private TOCRenderer m_TocRenderer;
128

    
129
    private JScrollPane m_Scroller;
130

    
131
    // private ArrayList m_Listeners;
132
    private Map<String, Boolean> m_ItemsExpanded =
133
        new HashMap<String, Boolean>();
134

    
135
    private NodeSelectionListener nodeSelectionListener = null;
136

    
137
    /**
138
     * Crea un nuevo TOC.
139
     */
140
    public TOC() {
141
        this.setName("TOC");
142
        this.setLayout(new BorderLayout());
143
        this.setMinimumSize(new Dimension(100, 80));
144
        this.setPreferredSize(new Dimension(100, 80));
145

    
146
        // Construct the tree.
147
        m_Root = new DefaultMutableTreeNode(java.lang.Object.class);
148
        m_TreeModel = new DefaultTreeModel(m_Root);
149
        m_Tree = new DnDJTree(m_TreeModel);
150

    
151
        m_TocRenderer = new TOCRenderer(m_Tree.getBackground());
152
        m_Tree.setCellRenderer(m_TocRenderer);
153

    
154
        m_Tree.setRootVisible(false);
155

    
156
        // m_Tree.setExpandsSelectedPaths(true);
157
        // m_Tree.setAutoscrolls(true);
158
        m_Tree.setShowsRootHandles(true);
159

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

    
168
        this.addComponentListener(this);
169

    
170
        m_Tree.addTreeExpansionListener(this);
171

    
172
        m_Tree.addOrderListener(this);
173

    
174
        m_Tree.setRowHeight(0); // Para que lo determine el renderer
175

    
176
        m_Scroller = new JScrollPane(m_Tree);
177
        m_Scroller.setBorder(BorderFactory.createEmptyBorder());
178

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

    
189
        // refresh();
190
    }
191

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

    
201
    /**
202
     * Inserta el FMap.
203
     *
204
     * @param mc
205
     *            FMap.
206
     */
207
    public void setMapContext(MapContext mc) {
208
        mapContext = mc;
209
        mapContext.addAtomicEventListener(new AtomicEventListener() {
210

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

    
218
                        public void run() {
219
                            atomicEvent(e);
220
                        }
221
                    });
222
                    return;
223
                }
224

    
225
                if ((e.getLayerCollectionEvents().length > 0)
226
                    || (e.getLegendEvents().length > 0)) {
227
                    refresh();
228
                }
229

    
230
                if (e.getLayerEvents().length > 0) {
231
                    repaint();
232
                }
233

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

    
248
                       if (invisibilityIsForced()) {
249
                           events[i].getAffectedLayer().setVisible(false);
250
                       }
251
                   }
252
                   // ===================================================
253
                }
254
            }
255
        });
256

    
257
        refresh();
258
    }
259

    
260
    /**
261
     * DOCUMENT ME!
262
     */
263
    private void setExpandedNodes(DefaultMutableTreeNode node) {
264
        // int i = 0;
265
        // Las claves sobrantes de m_ItemsExpanded (provocadas
266
        // por layerRemove, se quitan en el evento layerRemoved
267
        // de este TOC
268
        DefaultMutableTreeNode n;
269
        @SuppressWarnings("rawtypes")
270
        Enumeration enumeration = node.children();
271
        //Copia necesaria para que los cambios no adulteren el estado inicial del TOC
272
        Map<String, Boolean> itemsExpanded_copy = new HashMap<String, Boolean>(m_ItemsExpanded);
273

    
274
        while (enumeration.hasMoreElements()) {
275
            n = (DefaultMutableTreeNode) enumeration.nextElement();
276
            if (n.getChildCount() > 0) {
277
                setExpandedNodes(n);
278
            }
279
            TreePath path = new TreePath(m_TreeModel.getPathToRoot(n));
280
            ITocItem item = (ITocItem) n.getUserObject();
281
            Boolean b = (Boolean) itemsExpanded_copy.get(item.getLabel());
282

    
283
            if (b == null) // No estaba en el hash todav?a: valor por defecto
284
            {
285
                m_Tree.expandPath(path);
286

    
287
                return;
288
            }
289

    
290
            if (b.booleanValue()) {
291
                m_Tree.expandPath(path);
292
            } else {
293
                m_Tree.collapsePath(path);
294
            }
295
        }
296
    }
297

    
298
    /*
299
     * (non-Javadoc)
300
     *
301
     * @see com.iver.cit.opensig.gui.IToc#refresh()
302
     */
303
    public void refresh() {
304
        if (!SwingUtilities.isEventDispatchThread()) {
305
            SwingUtilities.invokeLater(new Runnable() {
306

    
307
                public void run() {
308
                    refresh();
309
                }
310
            });
311
            return;
312
        }
313
        LayerCollection theLayers = mapContext.getLayers();
314
        m_Root.removeAllChildren();
315
        m_Root.setAllowsChildren(true);
316
        doRefresh(theLayers, m_Root);
317

    
318
        m_TreeModel.reload();
319

    
320
        setExpandedNodes(m_Root);
321
    }
322

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

    
335
        for (int i = theLayers.getLayersCount() - 1; i >= 0; i--) {
336
            FLayer lyr = theLayers.getLayer(i);
337
            if (!lyr.isInTOC()) {
338
                continue;
339
            }
340
            TocItemBranch elTema = new TocItemBranch(lyr);
341
            elTema.setSize(sizeBranch);
342

    
343
            DefaultMutableTreeNode nodeLayer =
344
                new DefaultMutableTreeNode(elTema);
345

    
346
            m_TreeModel.insertNodeInto(nodeLayer, parentNode,
347
                parentNode.getChildCount());
348

    
349
            if (lyr instanceof LayerCollection) {
350
                LayerCollection group = (LayerCollection) lyr;
351
                doRefresh(group, nodeLayer);
352
            } else {
353
                if (lyr instanceof Classifiable) {// && !(lyr instanceof
354
                                                  // FLyrAnnotation)) {
355

    
356
                    Classifiable classifiable = (Classifiable) lyr;
357
                    ILegend legendInfo = classifiable.getLegend();
358

    
359
                    try {
360
                        if (legendInfo instanceof IClassifiedLegend) {
361
                            IClassifiedLegend cl =
362
                                (IClassifiedLegend) legendInfo;
363
                            String[] descriptions = cl.getDescriptions();
364
                            ISymbol[] symbols = cl.getSymbols();
365

    
366
                            for (int j = 0; j < descriptions.length; j++) {
367
                                TocItemLeaf itemLeaf;
368
                                itemLeaf =
369
                                    new TocItemLeaf(symbols[j],
370
                                        descriptions[j], classifiable.getShapeType());
371
                                itemLeaf.setSize(sizeLeaf);
372

    
373
                                DefaultMutableTreeNode nodeValue =
374
                                    new DefaultMutableTreeNode(itemLeaf);
375
                                m_TreeModel.insertNodeInto(nodeValue,
376
                                    nodeLayer, nodeLayer.getChildCount());
377

    
378
                            }
379
                        }
380

    
381
                        if (legendInfo instanceof ISingleSymbolLegend
382
                            && (legendInfo.getDefaultSymbol() != null)) {
383
                            TocItemLeaf itemLeaf;
384
                            itemLeaf =
385
                                new TocItemLeaf(legendInfo.getDefaultSymbol(),
386
                                    legendInfo.getDefaultSymbol()
387
                                        .getDescription(), classifiable.getShapeType());
388
                            itemLeaf.setSize(sizeLeaf);
389

    
390
                            DefaultMutableTreeNode nodeValue =
391
                                new DefaultMutableTreeNode(itemLeaf);
392
                            m_TreeModel.insertNodeInto(nodeValue, nodeLayer,
393
                                nodeLayer.getChildCount());
394
                        }
395

    
396
                        if (legendInfo instanceof IHasImageLegend) {
397
                            TocItemLeaf itemLeaf;
398
                            IHasImageLegend imageLegend = (IHasImageLegend) legendInfo;
399
                            Image image = imageLegend.getImageLegend();
400

    
401
                            int w = 0;
402
                            int h = 0;
403

    
404
                            if(image != null) {
405
                                    w = image.getWidth(null);
406
                                    h = image.getHeight(null);
407
                            }
408

    
409
                            if (image != null && w > 0 && h > 0) {
410
                                itemLeaf = new TocItemLeaf();
411
                                itemLeaf.setImageLegend(image, "", new Dimension(w, h));
412

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

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

    
442
    public void parentChanged(FLayers lpo, FLayers lpd, FLayer ls) {
443
        lpo.move(ls, lpd);
444
        mapContext.invalidate();
445
    }
446

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

    
456
    /*
457
     * (non-Javadoc)
458
     *
459
     * @see
460
     * java.awt.event.ComponentListener#componentMoved(java.awt.event.ComponentEvent
461
     * )
462
     */
463
    public void componentMoved(ComponentEvent e) {
464
    }
465

    
466
    /*
467
     * (non-Javadoc)
468
     *
469
     * @see java.awt.event.ComponentListener#componentResized(java.awt.event.
470
     * ComponentEvent)
471
     */
472
    public void componentResized(ComponentEvent e) {
473
        DefaultMutableTreeNode n;
474
        @SuppressWarnings("rawtypes")
475
        Enumeration enumeration = m_Root.children();
476

    
477
        while (enumeration.hasMoreElements()) {
478
            n = (DefaultMutableTreeNode) enumeration.nextElement();
479

    
480
            if (n.getUserObject() instanceof TocItemBranch) {
481
                ITocItem item = (ITocItem) n.getUserObject();
482
                Dimension szAnt = item.getSize();
483
                item.setSize(new Dimension(this.getWidth() - 40, szAnt.height));
484
            }
485

    
486
        }
487
    }
488

    
489
    /*
490
     * (non-Javadoc)
491
     *
492
     * @see
493
     * java.awt.event.ComponentListener#componentShown(java.awt.event.ComponentEvent
494
     * )
495
     */
496
    public void componentShown(ComponentEvent e) {
497
    }
498

    
499
    /*
500
     * (non-Javadoc)
501
     *
502
     * @see
503
     * com.iver.cit.gvsig.fmap.layers.LayerListener#legendChanged(com.iver.cit
504
     * .gvsig.fmap.rendering.LegendChangedEvent)
505
     */
506
    public void legendChanged(final LegendChangedEvent e) {
507
        if (!SwingUtilities.isEventDispatchThread()) {
508
            SwingUtilities.invokeLater(new Runnable() {
509

    
510
                public void run() {
511
                    legendChanged(e);
512
                }
513
            });
514
            return;
515
        }
516
        refresh();
517
    }
518

    
519
    /*
520
     * (non-Javadoc)
521
     *
522
     * @see
523
     * com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#layerAdded(com
524
     * .iver.cit.gvsig.fmap.layers.LayerCollectionEvent)
525
     */
526
    public void layerAdded(final LayerCollectionEvent e) {
527
        if (!SwingUtilities.isEventDispatchThread()) {
528
            SwingUtilities.invokeLater(new Runnable() {
529

    
530
                public void run() {
531
                    layerAdded(e);
532
                }
533
            });
534
            return;
535
        }
536
        FLayer layer = e.getAffectedLayer();
537
        if( layer instanceof FLyrVect ) {
538
            FLyrVect layerVect = (FLyrVect)layer;
539
            ILegend legend = layerVect.getLegend();
540
            switch( e.getEventType() ) {
541
                case LayerCollectionEvent.LAYER_ADDED :
542
                    legend.addLegendListener(this);
543
                    break;
544
                case LayerCollectionEvent.LAYER_REMOVED :
545
                    legend.removeLegendListener(this);
546
                    break;
547
            }
548
        }
549
        refresh();
550
    }
551

    
552
    public boolean symbolChanged(SymbolLegendEvent e) {
553
        refresh();
554
        return true;
555
    }
556

    
557
    public void legendCleared(LegendClearEvent event) {
558
        refresh();
559
    }
560

    
561
    /*
562
     * (non-Javadoc)
563
     *
564
     * @see
565
     * com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#layerMoved(com
566
     * .iver.cit.gvsig.fmap.layers.LayerPositionEvent)
567
     */
568
    public void layerMoved(final LayerPositionEvent e) {
569
        if (!SwingUtilities.isEventDispatchThread()) {
570
            SwingUtilities.invokeLater(new Runnable() {
571

    
572
                public void run() {
573
                    layerMoved(e);
574
                }
575
            });
576
            return;
577
        }
578
        refresh();
579
    }
580

    
581
    /*
582
     * (non-Javadoc)
583
     *
584
     * @see
585
     * com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#layerRemoved(com
586
     * .iver.cit.gvsig.fmap.layers.LayerCollectionEvent)
587
     */
588
    public void layerRemoved(final LayerCollectionEvent e) {
589
        if (!SwingUtilities.isEventDispatchThread()) {
590
            SwingUtilities.invokeLater(new Runnable() {
591

    
592
                public void run() {
593
                    layerRemoved(e);
594
                }
595
            });
596
            return;
597
        }
598
        m_ItemsExpanded.remove(e.getAffectedLayer().getName());
599
        refresh();
600
    }
601

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

    
612
    /*
613
     * (non-Javadoc)
614
     *
615
     * @see
616
     * com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#layerMoving(com
617
     * .iver.cit.gvsig.fmap.layers.LayerPositionEvent)
618
     */
619
    public void layerMoving(LayerPositionEvent e) throws CancelationException {
620
    }
621

    
622
    /*
623
     * (non-Javadoc)
624
     *
625
     * @see
626
     * com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#layerRemoving(
627
     * com.iver.cit.gvsig.fmap.layers.LayerCollectionEvent)
628
     */
629
    public void layerRemoving(LayerCollectionEvent e)
630
        throws CancelationException {
631
    }
632

    
633
    /*
634
     * (non-Javadoc)
635
     *
636
     * @see
637
     * com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#activationChanged
638
     * (com.iver.cit.gvsig.fmap.layers.LayerCollectionEvent)
639
     */
640
    public void activationChanged(LayerCollectionEvent e)
641
        throws CancelationException {
642
        repaint();
643
    }
644

    
645
    /*
646
     * (non-Javadoc)
647
     *
648
     * @see
649
     * com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#visibilityChanged
650
     * (com.iver.cit.gvsig.fmap.layers.LayerCollectionEvent)
651
     */
652
    public void visibilityChanged(final LayerCollectionEvent e)
653
        throws CancelationException {
654
        if (!SwingUtilities.isEventDispatchThread()) {
655
            SwingUtilities.invokeLater(new Runnable() {
656

    
657
                public void run() {
658
                    visibilityChanged(e);
659
                }
660
            });
661
            return;
662
        }
663
        repaint();
664
    }
665

    
666
    /*
667
     * (non-Javadoc)
668
     *
669
     * @see
670
     * javax.swing.event.TreeExpansionListener#treeCollapsed(javax.swing.event
671
     * .TreeExpansionEvent)
672
     */
673
    public void treeCollapsed(TreeExpansionEvent event) {
674
        TreePath path = event.getPath();
675
        DefaultMutableTreeNode n =
676
            (DefaultMutableTreeNode) path.getLastPathComponent();
677

    
678
        if (n.getUserObject() instanceof ITocItem) {
679
            ITocItem item = (ITocItem) n.getUserObject();
680
            Boolean b = Boolean.FALSE;
681

    
682
            m_ItemsExpanded.put(item.getLabel(), b);
683
        }
684
    }
685

    
686
    /*
687
     * (non-Javadoc)
688
     *
689
     * @see
690
     * javax.swing.event.TreeExpansionListener#treeExpanded(javax.swing.event
691
     * .TreeExpansionEvent)
692
     */
693
    public void treeExpanded(TreeExpansionEvent event) {
694
        TreePath path = event.getPath();
695
        DefaultMutableTreeNode n =
696
            (DefaultMutableTreeNode) path.getLastPathComponent();
697

    
698
        if (n.getUserObject() instanceof ITocItem) {
699
            ITocItem item = (ITocItem) n.getUserObject();
700
            Boolean b = Boolean.TRUE;
701

    
702
            m_ItemsExpanded.put(item.getLabel(), b);
703
        }
704
    }
705

    
706
    /**
707
     * Obtiene el JScrollPane que contiene el TOC
708
     *
709
     * @return JScrollPane que contiene el TOC
710
     */
711
    public JScrollPane getJScrollPane() {
712
        return this.m_Scroller;
713
    }
714

    
715
    /**
716
     * DOCUMENT ME!
717
     *
718
     * @return DOCUMENT ME!
719
     */
720
    public DnDJTree getTree() {
721
        return m_Tree;
722
    }
723

    
724
    /**
725
     * Clase Listener que reacciona al pulsar sobre el checkbox de un nodo y
726
     * crea un popupmenu al pulsar el bot?n derecho.
727
     */
728
    class NodeSelectionListener extends MouseAdapter implements ActionListener {
729

    
730
        JTree tree;
731

    
732
        JDialog dlg;
733

    
734
        JColorChooser colorChooser;
735

    
736
        FPopupMenu popmenu = null;
737

    
738
        DefaultMutableTreeNode node;
739

    
740
        /**
741
         * Crea un nuevo NodeSelectionListener.
742
         *
743
         * @param tree
744
         *            DOCUMENT ME!
745
         */
746
        NodeSelectionListener(JTree tree) {
747
            this.tree = tree;
748
        }
749

    
750
        /**
751
         * DOCUMENT ME!
752
         *
753
         * @param e
754
         *            DOCUMENT ME!
755
         */
756
        public void mouseClicked(MouseEvent e) {
757
            int x = e.getX();
758
            int y = e.getY();
759
            int row = tree.getRowForLocation(x, y);
760
            TreePath path = tree.getPathForRow(row);
761
            LayerCollection layers = mapContext.getLayers();
762

    
763
            if (path != null) {
764
                if (e.getClickCount() == 1) {
765
                    // this fixes a bug when double-clicking. JTree by default
766
                    // expands the tree when double-clicking, so we capture a
767
                    // different node in the second click than in the first
768
                    node = (DefaultMutableTreeNode) path.getLastPathComponent();
769
                }
770

    
771
                if (node != null
772
                    && node.getUserObject() instanceof TocItemBranch) {
773
                    // double click with left button ON A BRANCH/NODE (layer)
774
                    if (e.getClickCount() >= 2
775
                        && e.getButton() == MouseEvent.BUTTON1) {
776
                        e.consume();
777
                        PluginServices.getMDIManager().setWaitCursor();
778
                        try {
779
                            TocItemBranch leaf =
780
                                (TocItemBranch) node.getUserObject();
781

    
782
                            IContextMenuAction action =
783
                                leaf.getDoubleClickAction();
784
                            if (action != null) {
785
                                /*
786
                                 * if there is an action associated with the
787
                                 * double-clicked element it will be fired for
788
                                 * it and FOR ALL OTHER COMPATIBLES THAT HAVE
789
                                 * BEEN ACTIVATED.
790
                                 */
791
                                ArrayList<FLayer> targetLayers =
792
                                    new ArrayList<FLayer>();
793

    
794
                                TocItemBranch owner =
795
                                    (TocItemBranch) node.getUserObject();
796

    
797
                                FLayer masterLayer = owner.getLayer();
798
                                targetLayers.add(masterLayer);
799
                                FLayer[] actives =
800
                                    mapContext.getLayers().getActives();
801
                                for (int i = 0; i < actives.length; i++) {
802
                                    if (actives[i].getClass().equals(
803
                                        masterLayer.getClass())) {
804
                                        if (actives[i] instanceof FLyrVect) {
805
                                            FLyrVect vectorLayer =
806
                                                (FLyrVect) actives[i];
807
                                            FLyrVect vectorMaster =
808
                                                (FLyrVect) masterLayer;
809
                                            if (vectorLayer.getShapeType() == vectorMaster
810
                                                .getShapeType()) {
811
                                                targetLayers.add(vectorLayer);
812
                                            } else {
813
                                                vectorLayer.setActive(false);
814
                                            }
815
                                        }
816
                                        // TODO for the rest of layer types
817
                                        // (i.e. FLyrRaster)
818
                                    } else {
819
                                        actives[i].setActive(false);
820
                                    }
821
                                }
822

    
823
                                // Do nothing if there is a non-available layer
824
                                for (int k=0; k<targetLayers.size(); k++) {
825
                                    if (!targetLayers.get(k).isAvailable()) {
826
                                        return;
827
                                    }
828
                                }
829

    
830
                                action.execute(leaf,
831
                                    targetLayers.toArray(new FLayer[0]));
832
                            }
833
                        } catch (Exception ex) {
834
                            NotificationManager.addError(ex);
835
                        } finally {
836
                            PluginServices.getMDIManager().restoreCursor();
837
                        }
838
                        return;
839
                    }
840

    
841
                    TocItemBranch elTema = (TocItemBranch) node.getUserObject();
842
                    FLayer lyr = elTema.getLayer();
843
                    lyr.getMapContext().beginAtomicEvent();
844

    
845
                    if (((e.getModifiers() & InputEvent.SHIFT_MASK) != 0)
846
                        && (
847
                            e.getButton() == MouseEvent.BUTTON1 ||
848
                            e.getButton() == MouseEvent.BUTTON3
849
                            )
850
                       ) {
851
                        FLayer[] activeLayers = layers.getActives();
852
                        if (activeLayers.length > 0) {
853
                            selectInterval(layers, lyr);
854
                        } else {
855
                            updateActive(lyr, !lyr.isActive());
856
                        }
857

    
858
                    } else {
859
                        if (!((e.getModifiers() & InputEvent.CTRL_MASK) != 0)
860
                            && (
861
                                e.getButton() == MouseEvent.BUTTON1 ||
862
                                e.getButton() == MouseEvent.BUTTON3
863
                                )
864
                           ) {
865
                            layers.setAllActives(false);
866
                        }
867
                        if (e.getButton() == MouseEvent.BUTTON1
868
                            ||e.getButton() == MouseEvent.BUTTON3) {
869
                            // lyr.setActive(true);
870
                            updateActive(lyr, !lyr.isActive());
871
                        }
872
                    }
873
                    // Si pertenece a un grupo, lo ponemos activo tambi?n.
874
                    // FLayer parentLayer = lyr.getParentLayer();
875

    
876
                    /*
877
                     * if (parentLayer != null) { parentLayer.setActive(true); }
878
                     */
879
                    Point layerNodeLocation =
880
                        tree.getUI().getPathBounds(tree, path).getLocation();
881

    
882
                    // Rect?ngulo que representa el checkbox
883
                    Rectangle checkBoxBounds =
884
                        m_TocRenderer.getCheckBoxBounds();
885
                    checkBoxBounds.translate((int) layerNodeLocation.getX(),
886
                        (int) layerNodeLocation.getY());
887

    
888
                    if (checkBoxBounds.contains(e.getPoint())) {
889
                        updateVisible(lyr);
890
                    }
891

    
892
                    // }
893
                    if (e.getButton() == MouseEvent.BUTTON3) {
894
                        // Boton derecho sobre un nodo del arbol
895
                        // if ((e.getModifiers() & InputEvent.META_MASK) != 0) {
896
                        //***** Change selection
897
//                        if(!lyr.isActive()){
898
//                            layers.setAllActives(false);
899
//                            updateActive(lyr, true);
900
//                        }
901
                        //*****
902
                        popmenu = new FPopupMenu(mapContext, node);
903
                        tree.add(popmenu);
904

    
905
                        popmenu.show(e.getComponent(), e.getX(), e.getY());
906

    
907
                        // }
908
                    }
909

    
910
                    lyr.getMapContext().endAtomicEvent();
911
                }
912

    
913
                if (node != null && node.getUserObject() instanceof TocItemLeaf) {
914
                    TocItemBranch owner =
915
                        (TocItemBranch) ((DefaultMutableTreeNode) node
916
                            .getParent()).getUserObject();
917

    
918
                    FLayer masterLayer = owner.getLayer();
919

    
920
                    if (((e.getModifiers() & InputEvent.SHIFT_MASK) != 0)
921
                        && (
922
                            e.getButton() == MouseEvent.BUTTON1 ||
923
                            e.getButton() == MouseEvent.BUTTON3
924
                            )
925
                       ) {
926
                        FLayer[] activeLayers = layers.getActives();
927
                        if (activeLayers.length > 0) {
928
                            selectInterval(layers, masterLayer);
929
                        } else {
930
                            updateActive(masterLayer, !masterLayer.isActive());
931
                        }
932

    
933
                    } else {
934
                        if (!((e.getModifiers() & InputEvent.CTRL_MASK) != 0)
935
                            && (
936
                                e.getButton() == MouseEvent.BUTTON1 ||
937
                                e.getButton() == MouseEvent.BUTTON3
938
                                )
939
                           ) {
940
                            layers.setAllActives(false);
941
                        }
942
                        if (e.getButton() == MouseEvent.BUTTON1
943
                            ||e.getButton() == MouseEvent.BUTTON3) {
944
                            // lyr.setActive(true);
945
                            updateActive(masterLayer, !masterLayer.isActive());
946
                        }
947
                    }
948

    
949
                    // double click with left button ON A LEAF (ISymbol)
950
                    if (e.getClickCount() >= 2
951
                        && e.getButton() == MouseEvent.BUTTON1) {
952
                        e.consume();
953

    
954
                        PluginServices.getMDIManager().setWaitCursor();
955
                        try {
956
                            TocItemLeaf leaf =
957
                                (TocItemLeaf) node.getUserObject();
958
                            IContextMenuAction action =
959
                                leaf.getDoubleClickAction();
960
                            if (action != null) {
961
                                /*
962
                                 * if there is an action associated with the
963
                                 * double-clicked element it will be fired for
964
                                 * it and FOR ALL OTHER COMPATIBLES THAT HAVE
965
                                 * BEEN ACTIVATED.
966
                                 */
967
                                /*
968
                                 * #3035: Symbology is applied to active layers too
969
                                 * Now it will be done only on the double-clicked one
970
                                 */
971
                                ArrayList<FLayer> targetLayers =
972
                                    new ArrayList<FLayer>();
973

    
974

    
975
                                targetLayers.add(masterLayer);
976
//                                FLayer[] actives =
977
//                                    mapContext.getLayers().getActives();
978
//                                for (int i = 0; i < actives.length; i++) {
979
//                                    if (actives[i].getClass().equals(
980
//                                        masterLayer.getClass())) {
981
//                                        if (actives[i] instanceof FLyrVect) {
982
//                                            FLyrVect vectorLayer =
983
//                                                (FLyrVect) actives[i];
984
//                                            FLyrVect vectorMaster =
985
//                                                (FLyrVect) masterLayer;
986
//                                            int masterLayerShapetypeOF_THE_LEGEND =
987
//                                                ((IVectorLegend) vectorMaster
988
//                                                    .getLegend())
989
//                                                    .getShapeType();
990
//                                            int anotherVectorLayerShapetypeOF_THE_LEGEND =
991
//                                                ((IVectorLegend) vectorLayer
992
//                                                    .getLegend())
993
//                                                    .getShapeType();
994
//                                            if (masterLayerShapetypeOF_THE_LEGEND == anotherVectorLayerShapetypeOF_THE_LEGEND) {
995
//                                                targetLayers.add(vectorLayer);
996
//                                            } else {
997
//                                                vectorLayer.setActive(false);
998
//                                            }
999
//                                        }
1000
//                                        // TODO for the rest of layer types
1001
//                                        // (i.e. FLyrRaster)
1002
//                                    } else {
1003
//                                        actives[i].setActive(false);
1004
//                                    }
1005
//                                }
1006
                                action.execute(leaf,
1007
                                    targetLayers.toArray(new FLayer[0]));
1008
                            }
1009
                        } catch (Exception ex) {
1010
                            NotificationManager.addError(ex);
1011
                        } finally {
1012
                            PluginServices.getMDIManager().restoreCursor();
1013
                        }
1014
                        return;
1015
                    }
1016

    
1017
                    // Boton derecho sobre un Simbolo
1018
                    // TocItemLeaf auxLeaf = (TocItemLeaf) node.getUserObject();
1019
                    // FSymbol theSym = auxLeaf.getSymbol();
1020
                    if ((e.getModifiers() & InputEvent.META_MASK) != 0) {
1021
                        //***** Change selection
1022
                        if (!masterLayer.isActive()){
1023
                            layers.setAllActives(false);
1024
                            updateActive(masterLayer, true);
1025
                        }
1026
                        //*****
1027
                        popmenu = new FPopupMenu(mapContext, node);
1028
                        tree.add(popmenu);
1029
                        popmenu.show(e.getComponent(), e.getX(), e.getY());
1030
                    }
1031
                }
1032

    
1033
                ((DefaultTreeModel) tree.getModel()).nodeChanged(node);
1034

    
1035
                if (row == 0) {
1036
                    tree.revalidate();
1037
                    tree.repaint();
1038
                }
1039

    
1040
                //FIXME Is it really necessary?
1041
                if (PluginServices.getMainFrame() != null) {
1042
                    PluginServices.getMainFrame().enableControls();
1043
                }
1044
            } else {
1045
                if (e.getButton() == MouseEvent.BUTTON3) {
1046
                    popmenu = new FPopupMenu(mapContext, null);
1047
                    tree.add(popmenu);
1048
                    popmenu.show(e.getComponent(), e.getX(), e.getY());
1049
                }
1050

    
1051
            }
1052
        }
1053

    
1054
        private void selectInterval(LayerCollection layers, FLayer lyr) {
1055
            FLayer[] activeLayers = layers.getActives();
1056
            // if (activeLayers[0].getParentLayer() instanceof FLayers &&
1057
            // activeLayers[0].getParentLayer().getParentLayer()!=null) {
1058
            // selectInterval((LayerCollection)activeLayers[0].getParentLayer(),lyr);
1059
            // }
1060
            for (int j = 0; j < layers.getLayersCount(); j++) {
1061
                FLayer layerAux = layers.getLayer(j);
1062
                // Si se cumple esta condici?n es porque la primera capa que nos
1063
                // encontramos en el TOC es la que estaba activa
1064
                if (activeLayers[0].equals(layerAux)) {
1065
                    boolean isSelected = false;
1066
                    for (int i = 0; i < layers.getLayersCount(); i++) {
1067
                        FLayer layer = layers.getLayer(i);
1068
                        if (!isSelected) {
1069
                            isSelected = layer.isActive();
1070
                        } else {
1071
                            updateActive(layer, true);
1072
                            if (lyr.equals(layer)) {
1073
                                isSelected = false;
1074
                            }
1075
                        }
1076
                    }
1077
                    break;
1078
                } else
1079
                    // Si se cumple esta condici?n es porque la primera capa que
1080
                    // nos
1081
                    // encontramos en el TOC es la que acabamos de seleccionar
1082
                    if (lyr.equals(layerAux)) {
1083
                        boolean isSelected = false;
1084
                        for (int i = layers.getLayersCount() - 1; i >= 0; i--) {
1085
                            FLayer layer = layers.getLayer(i);
1086
                            if (!isSelected) {
1087
                                isSelected = layer.isActive();
1088
                            } else {
1089
                                updateActive(layer, true);
1090
                                if (lyr.equals(layer)) {
1091
                                    isSelected = false;
1092
                                }
1093
                            }
1094
                        }
1095
                        break;
1096
                    }
1097
            }
1098

    
1099
        }
1100

    
1101
        /**
1102
         * DOCUMENT ME!
1103
         *
1104
         * @param lyr
1105
         *            DOCUMENT ME!
1106
         * @param active
1107
         *            DOCUMENT ME!
1108
         */
1109
        private void updateActive(FLayer lyr, boolean active) {
1110
            lyr.setActive(active);
1111
            updateActiveChild(lyr);
1112
        }
1113

    
1114
        /**
1115
         * DOCUMENT ME!
1116
         *
1117
         * @param lyr
1118
         *            DOCUMENT ME!
1119
         */
1120
        private void updateActiveChild(FLayer lyr) {
1121
            if (lyr instanceof FLayers) { // Es la raiz de una rama o
1122
                // cualquier nodo intermedio.
1123

    
1124
                FLayers layergroup = (FLayers) lyr;
1125

    
1126
                for (int i = 0; i < layergroup.getLayersCount(); i++) {
1127
                    layergroup.getLayer(i).setActive(lyr.isActive());
1128
                    updateActiveChild(layergroup.getLayer(i));
1129
                }
1130
            }
1131
        }
1132

    
1133
        /**
1134
         * Actualiza la visibilidad de la capas.
1135
         *
1136
         * @param lyr
1137
         *            Capa sobre la que se est? clickando.
1138
         */
1139
        private void updateVisible(FLayer lyr) {
1140
            if (lyr.isAvailable()) {
1141
                lyr.setVisible(!lyr.visibleRequired());
1142
                updateVisibleChild(lyr);
1143
                updateVisibleParent(lyr);
1144
            }
1145
        }
1146

    
1147
        /**
1148
         * Actualiza de forma recursiva la visibilidad de los hijos de la capa
1149
         * que se pasa como par?metro.
1150
         *
1151
         * @param lyr
1152
         *            Capa a actualizar.
1153
         */
1154
        private void updateVisibleChild(FLayer lyr) {
1155
            if (lyr instanceof FLayers) { // Es la raiz de una rama o
1156
                                          // cualquier nodo intermedio.
1157

    
1158
                FLayers layergroup = (FLayers) lyr;
1159

    
1160
                for (int i = 0; i < layergroup.getLayersCount(); i++) {
1161
                    layergroup.getLayer(i).setVisible(lyr.visibleRequired());
1162
                    updateVisibleChild(layergroup.getLayer(i));
1163
                }
1164
            }
1165
        }
1166

    
1167
        /**
1168
         * Actualiza de forma recursiva la visibilidad del padre de la capa que
1169
         * se pasa como par?metro.
1170
         *
1171
         * @param lyr
1172
         *            Capa a actualizar.
1173
         */
1174
        private void updateVisibleParent(FLayer lyr) {
1175
            FLayers parent = lyr.getParentLayer();
1176

    
1177
            if (parent != null) {
1178
                boolean parentVisible = false;
1179

    
1180
                for (int i = 0; i < parent.getLayersCount(); i++) {
1181
                    if (parent.getLayer(i).visibleRequired()) {
1182
                        parentVisible = true;
1183
                    }
1184
                }
1185

    
1186
                parent.setVisible(parentVisible);
1187
                updateVisibleParent(parent);
1188
            }
1189
        }
1190

    
1191
        /**
1192
         * DOCUMENT ME!
1193
         *
1194
         * @param arg0
1195
         *            DOCUMENT ME!
1196
         */
1197
        public void actionPerformed(ActionEvent arg0) {
1198
        }
1199

    
1200
        /**
1201
         * DOCUMENT ME!
1202
         *
1203
         * @param arg0
1204
         *            DOCUMENT ME!
1205
         */
1206
        public void mouseReleased(MouseEvent arg0) {
1207
            super.mouseReleased(arg0);
1208
        }
1209

    
1210
        /**
1211
         * DOCUMENT ME!
1212
         *
1213
         * @param arg0
1214
         *            DOCUMENT ME!
1215
         */
1216
        public void mouseEntered(MouseEvent arg0) {
1217
            super.mouseEntered(arg0);
1218
        }
1219
    }
1220

    
1221
    private boolean invisibilityIsForced() {
1222

    
1223
        PluginServices ps = PluginServices.getPluginServices(this);
1224
        XMLEntity xml = ps.getPersistentXML();
1225

    
1226
        if (xml.contains(ViewPage.ADD_NEW_LAYERS_IN_INVISIBLE_MODE_KEY_NAME)) {
1227
            // Get invisibility value
1228
            return xml.getBooleanProperty(ViewPage.ADD_NEW_LAYERS_IN_INVISIBLE_MODE_KEY_NAME);
1229
        } else {
1230
            // not found in preferences
1231
            return false;
1232
        }
1233
    }
1234

    
1235
}