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

History | View | Annotate | Download (42.3 KB)

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

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

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

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

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

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

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

    
118
    private MapContext mapContext;
119

    
120
    private DnDJTree m_Tree;
121

    
122
    private DefaultTreeModel m_TreeModel;
123

    
124
    private DefaultMutableTreeNode m_Root;
125

    
126
    private TOCRenderer m_TocRenderer;
127

    
128
    private JScrollPane m_Scroller;
129

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

    
134
    private NodeSelectionListener nodeSelectionListener = null;
135

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

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

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

    
153
        m_Tree.setRootVisible(false);
154

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

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

    
167
        this.addComponentListener(this);
168

    
169
        m_Tree.addTreeExpansionListener(this);
170

    
171
        m_Tree.addOrderListener(this);
172

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

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

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

    
188
        // refresh();
189
    }
190

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

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

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

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

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

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

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

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

    
256
        refresh();
257
    }
258

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

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

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

    
284
                return;
285
            }
286

    
287
            if (b.booleanValue()) {
288
                m_Tree.expandPath(path);
289
            } else {
290
                m_Tree.collapsePath(path);
291
            }
292
        }
293
    }
294

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

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

    
315
        m_TreeModel.reload();
316

    
317
        setExpandedNodes(m_Root);
318
    }
319

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

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

    
340
            DefaultMutableTreeNode nodeLayer =
341
                new DefaultMutableTreeNode(elTema);
342

    
343
            m_TreeModel.insertNodeInto(nodeLayer, parentNode,
344
                parentNode.getChildCount());
345

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

    
353
                    Classifiable classifiable = (Classifiable) lyr;
354
                    ILegend legendInfo = classifiable.getLegend();
355

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

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

    
370
                                DefaultMutableTreeNode nodeValue =
371
                                    new DefaultMutableTreeNode(itemLeaf);
372
                                m_TreeModel.insertNodeInto(nodeValue,
373
                                    nodeLayer, nodeLayer.getChildCount());
374

    
375
                            }
376
                        }
377

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

    
387
                            DefaultMutableTreeNode nodeValue =
388
                                new DefaultMutableTreeNode(itemLeaf);
389
                            m_TreeModel.insertNodeInto(nodeValue, nodeLayer,
390
                                nodeLayer.getChildCount());
391
                        }
392
                        
393
                        if (legendInfo instanceof IHasImageLegend) {
394
                            TocItemLeaf itemLeaf;
395
                            IHasImageLegend imageLegend = (IHasImageLegend) legendInfo;
396
                            Image image = imageLegend.getImageLegend();
397
                            
398
                            int w = 0;
399
                            int h = 0;
400
                            
401
                            if(image != null) {
402
                                    w = image.getWidth(null);
403
                                    h = image.getHeight(null);
404
                            }
405
                            
406
                            if (image != null && w > 0 && h > 0) {
407
                                itemLeaf = new TocItemLeaf();
408
                                itemLeaf.setImageLegend(image, "", new Dimension(w, h));
409

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

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

    
439
    public void parentChanged(FLayers lpo, FLayers lpd, FLayer ls) {
440
        lpo.move(ls, lpd);
441
        mapContext.invalidate();
442
    }
443

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

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

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

    
474
        while (enumeration.hasMoreElements()) {
475
            n = (DefaultMutableTreeNode) enumeration.nextElement();
476

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

    
483
        }
484
    }
485

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

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

    
507
                public void run() {
508
                    legendChanged(e);
509
                }
510
            });
511
            return;
512
        }
513
        refresh();
514
    }
515

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

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

    
549
    public boolean symbolChanged(SymbolLegendEvent e) {
550
        refresh();
551
        return true;
552
    }
553

    
554
    public void legendCleared(LegendClearEvent event) {
555
        refresh();
556
    }
557
    
558
    /*
559
     * (non-Javadoc)
560
     * 
561
     * @see
562
     * com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#layerMoved(com
563
     * .iver.cit.gvsig.fmap.layers.LayerPositionEvent)
564
     */
565
    public void layerMoved(final LayerPositionEvent e) {
566
        if (!SwingUtilities.isEventDispatchThread()) {
567
            SwingUtilities.invokeLater(new Runnable() {
568

    
569
                public void run() {
570
                    layerMoved(e);
571
                }
572
            });
573
            return;
574
        }
575
        refresh();
576
    }
577

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

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

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

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

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

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

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

    
654
                public void run() {
655
                    visibilityChanged(e);
656
                }
657
            });
658
            return;
659
        }
660
        repaint();
661
    }
662

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

    
675
        if (n.getUserObject() instanceof ITocItem) {
676
            ITocItem item = (ITocItem) n.getUserObject();
677
            Boolean b = Boolean.FALSE;
678

    
679
            m_ItemsExpanded.put(item.getLabel(), b);
680
        }
681
    }
682

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

    
695
        if (n.getUserObject() instanceof ITocItem) {
696
            ITocItem item = (ITocItem) n.getUserObject();
697
            Boolean b = Boolean.TRUE;
698

    
699
            m_ItemsExpanded.put(item.getLabel(), b);
700
        }
701
    }
702

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

    
712
    /**
713
     * DOCUMENT ME!
714
     * 
715
     * @return DOCUMENT ME!
716
     */
717
    public DnDJTree getTree() {
718
        return m_Tree;
719
    }
720

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

    
727
        JTree tree;
728

    
729
        JDialog dlg;
730

    
731
        JColorChooser colorChooser;
732

    
733
        FPopupMenu popmenu = null;
734

    
735
        DefaultMutableTreeNode node;
736

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

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

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

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

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

    
791
                                TocItemBranch owner =
792
                                    (TocItemBranch) node.getUserObject();
793

    
794
                                FLayer masterLayer = owner.getLayer();
795
                                targetLayers.add(masterLayer);
796
                                FLayer[] actives =
797
                                    mapContext.getLayers().getActives();
798
                                for (int i = 0; i < actives.length; i++) {
799
                                    if (actives[i].getClass().equals(
800
                                        masterLayer.getClass())) {
801
                                        if (actives[i] instanceof FLyrVect) {
802
                                            FLyrVect vectorLayer =
803
                                                (FLyrVect) actives[i];
804
                                            FLyrVect vectorMaster =
805
                                                (FLyrVect) masterLayer;
806
                                            if (vectorLayer.getShapeType() == vectorMaster
807
                                                .getShapeType()) {
808
                                                targetLayers.add(vectorLayer);
809
                                            } else {
810
                                                vectorLayer.setActive(false);
811
                                            }
812
                                        }
813
                                        // TODO for the rest of layer types
814
                                        // (i.e. FLyrRaster)
815
                                    } else {
816
                                        actives[i].setActive(false);
817
                                    }
818
                                }
819
                                
820
                                // Do nothing if there is a non-available layer
821
                                for (int k=0; k<targetLayers.size(); k++) {
822
                                    if (!targetLayers.get(k).isAvailable()) {
823
                                        return;
824
                                    }
825
                                }
826
                                
827
                                action.execute(leaf,
828
                                    targetLayers.toArray(new FLayer[0]));
829
                            }
830
                        } catch (Exception ex) {
831
                            NotificationManager.addError(ex);
832
                        } finally {
833
                            PluginServices.getMDIManager().restoreCursor();
834
                        }
835
                        return;
836
                    }
837

    
838
                    TocItemBranch elTema = (TocItemBranch) node.getUserObject();
839
                    FLayer lyr = elTema.getLayer();
840
                    lyr.getMapContext().beginAtomicEvent();
841

    
842
                    if (((e.getModifiers() & InputEvent.SHIFT_MASK) != 0)
843
                        && (e.getButton() == MouseEvent.BUTTON1)) {
844
                        FLayer[] activeLayers = layers.getActives();
845
                        if (activeLayers.length > 0) {
846
                            selectInterval(layers, lyr);
847
                        } else {
848
                            updateActive(lyr, !lyr.isActive());
849
                        }
850

    
851
                    } else {
852
                        if (!((e.getModifiers() & InputEvent.CTRL_MASK) != 0)
853
                            && (e.getButton() == MouseEvent.BUTTON1)) {
854
                            layers.setAllActives(false);
855
                        }
856
                        if (e.getButton() == MouseEvent.BUTTON1) {
857
                            // lyr.setActive(true);
858
                            updateActive(lyr, !lyr.isActive());
859
                        }
860
                    }
861
                    // Si pertenece a un grupo, lo ponemos activo tambi?n.
862
                    // FLayer parentLayer = lyr.getParentLayer();
863

    
864
                    /*
865
                     * if (parentLayer != null) { parentLayer.setActive(true); }
866
                     */
867
                    Point layerNodeLocation =
868
                        tree.getUI().getPathBounds(tree, path).getLocation();
869

    
870
                    // Rect?ngulo que representa el checkbox
871
                    Rectangle checkBoxBounds =
872
                        m_TocRenderer.getCheckBoxBounds();
873
                    checkBoxBounds.translate((int) layerNodeLocation.getX(),
874
                        (int) layerNodeLocation.getY());
875

    
876
                    if (checkBoxBounds.contains(e.getPoint())) {
877
                        updateVisible(lyr);
878
                    }
879

    
880
                    // }
881
                    if (e.getButton() == MouseEvent.BUTTON3) {
882
                        // Boton derecho sobre un nodo del arbol
883
                        // if ((e.getModifiers() & InputEvent.META_MASK) != 0) {
884
                        popmenu = new FPopupMenu(mapContext, node);
885
                        tree.add(popmenu);
886

    
887
                        popmenu.show(e.getComponent(), e.getX(), e.getY());
888

    
889
                        // }
890
                    }
891

    
892
                    lyr.getMapContext().endAtomicEvent();
893
                }
894

    
895
                if (node != null && node.getUserObject() instanceof TocItemLeaf) {
896
                    // double click with left button ON A LEAF (ISymbol)
897
                    if (e.getClickCount() >= 2
898
                        && e.getButton() == MouseEvent.BUTTON1) {
899
                        e.consume();
900

    
901
                        PluginServices.getMDIManager().setWaitCursor();
902
                        try {
903
                            TocItemLeaf leaf =
904
                                (TocItemLeaf) node.getUserObject();
905
                            IContextMenuAction action =
906
                                leaf.getDoubleClickAction();
907
                            if (action != null) {
908
                                /*
909
                                 * if there is an action associated with the
910
                                 * double-clicked element it will be fired for
911
                                 * it and FOR ALL OTHER COMPATIBLES THAT HAVE
912
                                 * BEEN ACTIVATED.
913
                                 */
914
                                ArrayList<FLayer> targetLayers =
915
                                    new ArrayList<FLayer>();
916

    
917
                                TocItemBranch owner =
918
                                    (TocItemBranch) ((DefaultMutableTreeNode) node
919
                                        .getParent()).getUserObject();
920

    
921
                                FLayer masterLayer = owner.getLayer();
922
                                targetLayers.add(masterLayer);
923
                                FLayer[] actives =
924
                                    mapContext.getLayers().getActives();
925
                                for (int i = 0; i < actives.length; i++) {
926
                                    if (actives[i].getClass().equals(
927
                                        masterLayer.getClass())) {
928
                                        if (actives[i] instanceof FLyrVect) {
929
                                            FLyrVect vectorLayer =
930
                                                (FLyrVect) actives[i];
931
                                            FLyrVect vectorMaster =
932
                                                (FLyrVect) masterLayer;
933
                                            int masterLayerShapetypeOF_THE_LEGEND =
934
                                                ((IVectorLegend) vectorMaster
935
                                                    .getLegend())
936
                                                    .getShapeType();
937
                                            int anotherVectorLayerShapetypeOF_THE_LEGEND =
938
                                                ((IVectorLegend) vectorLayer
939
                                                    .getLegend())
940
                                                    .getShapeType();
941
                                            if (masterLayerShapetypeOF_THE_LEGEND == anotherVectorLayerShapetypeOF_THE_LEGEND) {
942
                                                targetLayers.add(vectorLayer);
943
                                            } else {
944
                                                vectorLayer.setActive(false);
945
                                            }
946
                                        }
947
                                        // TODO for the rest of layer types
948
                                        // (i.e. FLyrRaster)
949
                                    } else {
950
                                        actives[i].setActive(false);
951
                                    }
952
                                }
953
                                action.execute(leaf,
954
                                    targetLayers.toArray(new FLayer[0]));
955
                            }
956
                        } catch (Exception ex) {
957
                            NotificationManager.addError(ex);
958
                        } finally {
959
                            PluginServices.getMDIManager().restoreCursor();
960
                        }
961
                        return;
962
                    }
963

    
964
                    // Boton derecho sobre un Simbolo
965
                    // TocItemLeaf auxLeaf = (TocItemLeaf) node.getUserObject();
966
                    // FSymbol theSym = auxLeaf.getSymbol();
967
                    if ((e.getModifiers() & InputEvent.META_MASK) != 0) {
968
                        popmenu = new FPopupMenu(mapContext, node);
969
                        tree.add(popmenu);
970
                        popmenu.show(e.getComponent(), e.getX(), e.getY());
971
                    }
972
                }
973

    
974
                ((DefaultTreeModel) tree.getModel()).nodeChanged(node);
975

    
976
                if (row == 0) {
977
                    tree.revalidate();
978
                    tree.repaint();
979
                }
980

    
981
                if (PluginServices.getMainFrame() != null) {
982
                    PluginServices.getMainFrame().enableControls();
983
                }
984
            } else {
985
                if (e.getButton() == MouseEvent.BUTTON3) {
986
                    popmenu = new FPopupMenu(mapContext, null);
987
                    tree.add(popmenu);
988
                    popmenu.show(e.getComponent(), e.getX(), e.getY());
989
                }
990

    
991
            }
992
        }
993

    
994
        private void selectInterval(LayerCollection layers, FLayer lyr) {
995
            FLayer[] activeLayers = layers.getActives();
996
            // if (activeLayers[0].getParentLayer() instanceof FLayers &&
997
            // activeLayers[0].getParentLayer().getParentLayer()!=null) {
998
            // selectInterval((LayerCollection)activeLayers[0].getParentLayer(),lyr);
999
            // }
1000
            for (int j = 0; j < layers.getLayersCount(); j++) {
1001
                FLayer layerAux = layers.getLayer(j);
1002
                // Si se cumple esta condici?n es porque la primera capa que nos
1003
                // encontramos en el TOC es la que estaba activa
1004
                if (activeLayers[0].equals(layerAux)) {
1005
                    boolean isSelected = false;
1006
                    for (int i = 0; i < layers.getLayersCount(); i++) {
1007
                        FLayer layer = layers.getLayer(i);
1008
                        if (!isSelected) {
1009
                            isSelected = layer.isActive();
1010
                        } else {
1011
                            updateActive(layer, true);
1012
                            if (lyr.equals(layer)) {
1013
                                isSelected = false;
1014
                            }
1015
                        }
1016
                    }
1017
                    break;
1018
                } else
1019
                    // Si se cumple esta condici?n es porque la primera capa que
1020
                    // nos
1021
                    // encontramos en el TOC es la que acabamos de seleccionar
1022
                    if (lyr.equals(layerAux)) {
1023
                        boolean isSelected = false;
1024
                        for (int i = layers.getLayersCount() - 1; i >= 0; i--) {
1025
                            FLayer layer = layers.getLayer(i);
1026
                            if (!isSelected) {
1027
                                isSelected = layer.isActive();
1028
                            } else {
1029
                                updateActive(layer, true);
1030
                                if (lyr.equals(layer)) {
1031
                                    isSelected = false;
1032
                                }
1033
                            }
1034
                        }
1035
                        break;
1036
                    }
1037
            }
1038

    
1039
        }
1040

    
1041
        /**
1042
         * DOCUMENT ME!
1043
         * 
1044
         * @param lyr
1045
         *            DOCUMENT ME!
1046
         * @param active
1047
         *            DOCUMENT ME!
1048
         */
1049
        private void updateActive(FLayer lyr, boolean active) {
1050
            lyr.setActive(active);
1051
            updateActiveChild(lyr);
1052
        }
1053

    
1054
        /**
1055
         * DOCUMENT ME!
1056
         * 
1057
         * @param lyr
1058
         *            DOCUMENT ME!
1059
         */
1060
        private void updateActiveChild(FLayer lyr) {
1061
            if (lyr instanceof FLayers) { // Es la raiz de una rama o
1062
                // cualquier nodo intermedio.
1063

    
1064
                FLayers layergroup = (FLayers) lyr;
1065

    
1066
                for (int i = 0; i < layergroup.getLayersCount(); i++) {
1067
                    layergroup.getLayer(i).setActive(lyr.isActive());
1068
                    updateActiveChild(layergroup.getLayer(i));
1069
                }
1070
            }
1071
        }
1072

    
1073
        /**
1074
         * Actualiza la visibilidad de la capas.
1075
         * 
1076
         * @param lyr
1077
         *            Capa sobre la que se est? clickando.
1078
         */
1079
        private void updateVisible(FLayer lyr) {
1080
            if (lyr.isAvailable()) {
1081
                lyr.setVisible(!lyr.visibleRequired());
1082
                updateVisibleChild(lyr);
1083
                updateVisibleParent(lyr);
1084
            }
1085
        }
1086

    
1087
        /**
1088
         * Actualiza de forma recursiva la visibilidad de los hijos de la capa
1089
         * que se pasa como par?metro.
1090
         * 
1091
         * @param lyr
1092
         *            Capa a actualizar.
1093
         */
1094
        private void updateVisibleChild(FLayer lyr) {
1095
            if (lyr instanceof FLayers) { // Es la raiz de una rama o
1096
                                          // cualquier nodo intermedio.
1097

    
1098
                FLayers layergroup = (FLayers) lyr;
1099

    
1100
                for (int i = 0; i < layergroup.getLayersCount(); i++) {
1101
                    layergroup.getLayer(i).setVisible(lyr.visibleRequired());
1102
                    updateVisibleChild(layergroup.getLayer(i));
1103
                }
1104
            }
1105
        }
1106

    
1107
        /**
1108
         * Actualiza de forma recursiva la visibilidad del padre de la capa que
1109
         * se pasa como par?metro.
1110
         * 
1111
         * @param lyr
1112
         *            Capa a actualizar.
1113
         */
1114
        private void updateVisibleParent(FLayer lyr) {
1115
            FLayers parent = lyr.getParentLayer();
1116

    
1117
            if (parent != null) {
1118
                boolean parentVisible = false;
1119

    
1120
                for (int i = 0; i < parent.getLayersCount(); i++) {
1121
                    if (parent.getLayer(i).visibleRequired()) {
1122
                        parentVisible = true;
1123
                    }
1124
                }
1125

    
1126
                parent.setVisible(parentVisible);
1127
                updateVisibleParent(parent);
1128
            }
1129
        }
1130

    
1131
        /**
1132
         * DOCUMENT ME!
1133
         * 
1134
         * @param arg0
1135
         *            DOCUMENT ME!
1136
         */
1137
        public void actionPerformed(ActionEvent arg0) {
1138
        }
1139

    
1140
        /**
1141
         * DOCUMENT ME!
1142
         * 
1143
         * @param arg0
1144
         *            DOCUMENT ME!
1145
         */
1146
        public void mouseReleased(MouseEvent arg0) {
1147
            super.mouseReleased(arg0);
1148
        }
1149

    
1150
        /**
1151
         * DOCUMENT ME!
1152
         * 
1153
         * @param arg0
1154
         *            DOCUMENT ME!
1155
         */
1156
        public void mouseEntered(MouseEvent arg0) {
1157
            super.mouseEntered(arg0);
1158
        }
1159
    }
1160
    
1161
    private boolean invisibilityIsForced() {
1162
        
1163
        PluginServices ps = PluginServices.getPluginServices(this);
1164
        XMLEntity xml = ps.getPersistentXML();
1165

    
1166
        if (xml.contains(ViewPage.ADD_NEW_LAYERS_IN_INVISIBLE_MODE_KEY_NAME)) {
1167
            // Get invisibility value
1168
            return xml.getBooleanProperty(ViewPage.ADD_NEW_LAYERS_IN_INVISIBLE_MODE_KEY_NAME);
1169
        } else {
1170
            // not found in preferences
1171
            return false;
1172
        }
1173
    }
1174

    
1175
}