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 / legend / gui / LegendManager.java @ 40927

History | View | Annotate | Download (39 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.legend.gui;
25

    
26
import java.awt.BorderLayout;
27
import java.awt.Color;
28
import java.awt.Component;
29
import java.awt.Dimension;
30
import java.awt.FlowLayout;
31
import java.awt.event.ActionListener;
32
import java.io.File;
33
import java.io.FileInputStream;
34
import java.io.FileNotFoundException;
35
import java.io.FileOutputStream;
36
import java.io.InputStream;
37
import java.io.OutputStream;
38
import java.util.ArrayList;
39
import java.util.Enumeration;
40
import java.util.Hashtable;
41
import java.util.List;
42
import java.util.prefs.Preferences;
43

    
44
import javax.swing.ImageIcon;
45
import javax.swing.JButton;
46
import javax.swing.JComponent;
47
import javax.swing.JFileChooser;
48
import javax.swing.JLabel;
49
import javax.swing.JOptionPane;
50
import javax.swing.JPanel;
51
import javax.swing.JScrollPane;
52
import javax.swing.JSplitPane;
53
import javax.swing.JTextArea;
54
import javax.swing.JTree;
55
import javax.swing.filechooser.FileFilter;
56
import javax.swing.tree.DefaultMutableTreeNode;
57
import javax.swing.tree.DefaultTreeCellRenderer;
58
import javax.swing.tree.DefaultTreeModel;
59
import javax.swing.tree.MutableTreeNode;
60
import javax.swing.tree.TreePath;
61
import javax.swing.tree.TreeSelectionModel;
62

    
63
import org.slf4j.Logger;
64
import org.slf4j.LoggerFactory;
65

    
66
import org.gvsig.andami.PluginServices;
67
import org.gvsig.andami.messages.NotificationManager;
68
import org.gvsig.app.ApplicationLocator;
69
import org.gvsig.fmap.geom.Geometry;
70
import org.gvsig.fmap.mapcontext.MapContextLocator;
71
import org.gvsig.fmap.mapcontext.MapContextManager;
72
import org.gvsig.fmap.mapcontext.exceptions.LegendLayerException;
73
import org.gvsig.fmap.mapcontext.exceptions.WriteLegendException;
74
import org.gvsig.fmap.mapcontext.layers.FLayer;
75
import org.gvsig.fmap.mapcontext.layers.FLayers;
76
import org.gvsig.fmap.mapcontext.layers.operations.Classifiable;
77
import org.gvsig.fmap.mapcontext.layers.operations.ClassifiableVectorial;
78
import org.gvsig.fmap.mapcontext.layers.vectorial.FLyrVect;
79
import org.gvsig.fmap.mapcontext.rendering.legend.IClassifiedVectorLegend;
80
import org.gvsig.fmap.mapcontext.rendering.legend.ILegend;
81
import org.gvsig.fmap.mapcontext.rendering.legend.IVectorLegend;
82
import org.gvsig.fmap.mapcontext.rendering.legend.driver.ILegendReader;
83
import org.gvsig.fmap.mapcontext.rendering.legend.driver.ILegendWriter;
84
import org.gvsig.fmap.mapcontext.rendering.symbols.SymbolManager;
85
import org.gvsig.i18n.Messages;
86
import org.gvsig.tools.ToolsLocator;
87
import org.gvsig.tools.persistence.PersistenceManager;
88

    
89
/**
90
 * Implements the panel which allows the user to control all the information
91
 * about the
92
 * legends of a layer in order to improve the information that it offers to the
93
 * user.
94
 * There are options to create, save or load an existing legend.
95
 * 
96
 * @author jaume dominguez faus - jaume.dominguez@iver.es
97
 */
98
public class LegendManager extends AbstractThemeManagerPage {
99

    
100
    private static final Logger logger =
101
        LoggerFactory.getLogger(LegendManager.class);
102
    
103
    private static final long serialVersionUID = 7989057553773181019L;
104
    private static ArrayList<Class<? extends ILegendPanel>> legendPool =
105
        new ArrayList<Class<? extends ILegendPanel>>();
106
    // private static ArrayList<Class<? extends IFMapLegendDriver>>
107
    // legendDriverPool = new ArrayList<Class<? extends IFMapLegendDriver>>();
108

    
109
    private FLayer layer;
110
    private ILegend legend; // Le asignaremos la leyenda del primer tema activo.
111
    private Hashtable<Class<? extends ILegendPanel>, ILegendPanel> pages =
112
        new Hashtable<Class<? extends ILegendPanel>, ILegendPanel>();
113
    private JPanel topPanel = null;
114
    private JTextArea titleArea = null;
115
    private JPanel preview = null;
116
    private JScrollPane jTitleScrollPane = null;
117
    private JTree jTreeLegends;
118
    private ILegendPanel activePanel;
119
    private JScrollPane legendTreeScrollPane;
120
    private boolean dirtyTree_;
121
    private DefaultMutableTreeNode root = new DefaultMutableTreeNode();
122
    private DefaultTreeModel treeModel;
123
    private JScrollPane jPanelContainer;
124
    private JPanel jCentralPanel;
125
    private JSplitPane jSplitPane;
126
    private boolean isTreeListenerDisabled;
127
    private JButton btnSaveLegend;
128
    private JButton btnLoadLegend;
129
    private Hashtable<FLayer, ILegend> table = null;
130
    private boolean empty = true;
131
    private JLabel iconLabel;
132

    
133
    public static String defaultLegendFolderPath;
134
    {
135

    
136
        Preferences prefs = Preferences.userRoot().node("gvsig.foldering");
137
        defaultLegendFolderPath = prefs.get("LegendsFolder", "");
138
    }
139
    
140
    private ActionListener loadSaveLegendAction = new ActionListener() {
141

    
142
        public void actionPerformed(java.awt.event.ActionEvent e) {
143
            JComponent c = (JComponent) e.getSource();
144
            if (c.equals(getBtnSaveLegend())) {
145
                
146
                try {
147
                    saveLegend();
148
                } catch (Exception exc) {
149
                    JOptionPane.showMessageDialog(
150
                        ApplicationLocator.getManager().getRootComponent(),
151
                        Messages.getText("_Unable_to_save_legend")
152
                        + "\n\n" + exc.getMessage(),
153
                        Messages.getText("legend"),
154
                        JOptionPane.WARNING_MESSAGE);
155
                    return;
156
                }
157

    
158
            } else
159
                if (c.equals(getBtnLoadLegend())) {
160
                    try {
161
                        loadLegend();
162
                    } catch (Exception e1) {
163
                        JOptionPane.showMessageDialog(
164
                            ApplicationLocator.getManager().getRootComponent(),
165
                            Messages.getText("_Unable_to_read_legend")
166
                            + "\n\n" + e1.getMessage(),
167
                            Messages.getText("legend"),
168
                            JOptionPane.WARNING_MESSAGE);
169
                        return;
170
                    }
171
                }
172
        }
173

    
174
        private void saveLegend() throws Exception {
175
            
176
            List<LegendFileFilter> filters = getLegendFileFilters(true);
177
            if (filters.size() == 0) {
178
                JOptionPane.showMessageDialog(
179
                    ApplicationLocator.getManager().getRootComponent(),
180
                    Messages.getText("_No_output_format_available"),
181
                    Messages.getText("legend"),
182
                    JOptionPane.WARNING_MESSAGE);
183
                return;
184
            }
185

    
186
            ILegend legend = activePanel.getLegend();
187
            MapContextManager mcoman = MapContextLocator.getMapContextManager();
188
            
189
            JFileChooser fileChooser = new JFileChooser();
190
            fileChooser.setAcceptAllFileFilterUsed(false);
191
            
192
            for (int i=0; i<filters.size(); i++) {
193
                fileChooser.addChoosableFileFilter(filters.get(i));
194
            }
195

    
196
            if (fileChooser.showSaveDialog(
197
                ApplicationLocator.getManager().getRootComponent())
198
                == JFileChooser.APPROVE_OPTION) {
199
                
200
                LegendFileFilter lff = (LegendFileFilter) fileChooser.getFileFilter();
201
                
202
                File selfile = fileChooser.getSelectedFile();
203
                if (!selfile.getAbsolutePath().toLowerCase().endsWith(
204
                    "." + lff.getFileExtension().toLowerCase())) {
205
                    
206
                    selfile = new File(selfile.getAbsolutePath() +
207
                        "." + lff.getFileExtension().toLowerCase());
208
                }
209
                
210
                ILegendWriter lw = null;
211
                lw = mcoman.createLegendWriter(legend.getClass(), lff.getFileExtension());
212
                
213
                if (lw == null) {
214
                    throw new WriteLegendException(legend,
215
                        new Exception("Unable to create legend writer."));
216
                } else {
217
                    lw.write(legend, selfile, lff.getFileExtension());
218
                }
219
            }
220
        }
221

    
222
        /**
223
         * 
224
         * @param writing true for writing; false for reading
225
         * @return
226
         */
227
        private List<LegendFileFilter> getLegendFileFilters(boolean writing) {
228
            
229
            List<LegendFileFilter> resp = new ArrayList<LegendFileFilter>();
230
            MapContextManager mcoman = MapContextLocator.getMapContextManager();
231
            List wformats = null;
232
            
233
            if (writing) {
234
                wformats = mcoman.getLegendWritingFormats();
235
            } else {
236
                wformats = mcoman.getLegendReadingFormats();
237
            }
238
            
239
            String fmt = null;
240
            for (int i=0; i<wformats.size(); i++) {
241
                fmt = (String) wformats.get(i);
242
                fmt = getFileExtension(fmt);
243
                if (fmt != null) {
244
                    resp.add(new LegendFileFilter(fmt));
245
                }
246
            }
247
            return resp;
248
        }
249
        
250
        
251
        /**
252
         * Returns null if mime format is not parsed properly
253
         * 
254
         * @param fmt MIME format
255
         * 
256
         * @return
257
         */
258
        private String getFileExtension(String fmt) {
259
            // Example: "text/xml; subtype=gml/2.1.2" => "gml"
260
            if (fmt == null) {
261
                return null;
262
            }
263
            String[] parts = fmt.split(";");
264
            String aux = "";
265
            if (parts.length > 1) {
266
                aux = parts[1].trim();
267
            } else {
268
                aux = parts[0].trim();
269
            }
270
            parts = aux.split("=");
271
            if (parts.length > 1) {
272
                aux = parts[1].trim();
273
                // Example: aux = "gml/2.1.2"
274
                parts = aux.split("/");
275
                return parts[0].length() == 0 ? null : parts[0].toLowerCase();
276
            } else {
277
                aux = parts[0].trim();
278
                // Example: "text/xml"
279
                parts = aux.split("/");
280
                if (parts.length > 1) {
281
                    return parts[1].length() == 0 ? null : parts[1].toLowerCase();
282
                } else {
283
                    return aux.length() == 0 ? null : aux.toLowerCase();
284
                }
285
            }
286
        }        
287

    
288
        private void loadLegend() throws Exception {
289
            
290
            List<LegendFileFilter> filters = getLegendFileFilters(false);
291
            if (filters.size() == 0) {
292
                JOptionPane.showMessageDialog(
293
                    ApplicationLocator.getManager().getRootComponent(),
294
                    Messages.getText("_No_input_format_available"),
295
                    Messages.getText("legend"),
296
                    JOptionPane.WARNING_MESSAGE);
297
                return;
298
            }
299

    
300
            JFileChooser fileChooser = new JFileChooser();
301
            fileChooser.setAcceptAllFileFilterUsed(false);
302
            
303
            for (int i=0; i<filters.size(); i++) {
304
                fileChooser.addChoosableFileFilter(filters.get(i));
305
            }
306

    
307
            // open a file
308
            if (fileChooser.showOpenDialog((Component) PluginServices
309
                .getMainFrame()) == JFileChooser.APPROVE_OPTION) {
310
                
311
                File file = fileChooser.getSelectedFile();
312
                LegendFileFilter lff = (LegendFileFilter) fileChooser.getFileFilter();
313
                MapContextManager mcoman = MapContextLocator.getMapContextManager();
314
                ILegendReader lr = mcoman.createLegendReader(lff.getFileExtension());
315
                
316
                ILegend leg = lr.read(file, Geometry.TYPES.GEOMETRY);
317
                applyLegend(leg);
318
            }
319
        }
320
    };
321

    
322
    //
323
    // JLegendFileChooser jfc = new
324
    // JLegendFileChooser(getLegendDrivers(),true);
325
    // jfc.setAcceptAllFileFilterUsed(false);
326
    //
327
    //
328
    // File basedir = null;
329
    // jfc.setCurrentDirectory(basedir);
330
    // if (jfc.showSaveDialog((Component) PluginServices.getMainFrame())
331
    // == JFileChooser.APPROVE_OPTION) {
332
    //
333
    // File file = jfc.getSelectedFile();
334
    // String version = jfc.getDriverVersion();
335
    // IFMapLegendDriver driver = jfc.getSuitableDriver();
336
    //
337
    // if(!(driver instanceof FMapGVLDriver)){
338
    // Object[] options = {PluginServices.getText(this, "yes"),
339
    // PluginServices.getText(this, "no")};
340
    //
341
    // int answer =
342
    // JOptionPane.showOptionDialog((Component)PluginServices.getMainFrame(),
343
    // PluginServices.getText(this, "not_GVSLEG_save_question")+"\n"+ //GVL
344
    // changed to GVSLEG, be aware
345
    // PluginServices.getText(this, "desea_continuar"),
346
    // PluginServices.getText(this, "confirmation_dialog"),
347
    // JOptionPane.YES_NO_OPTION,
348
    // JOptionPane.QUESTION_MESSAGE,
349
    // null,
350
    // options, options[1]);
351
    // if (answer!=JOptionPane.OK_OPTION) {
352
    // // 'Cancel' pressed or window closed: don't save anythig, exit
353
    // save dialog
354
    // return;
355
    // }
356
    // }
357
    //
358
    // if (file.exists()) {
359
    // Object[] options = {PluginServices.getText(this, "yes"),
360
    // PluginServices.getText(this, "no"),
361
    // PluginServices.getText(this, "Cancel")};
362
    //
363
    // int answer =
364
    // JOptionPane.showOptionDialog((Component)PluginServices.getMainFrame(),
365
    // PluginServices.getText(this,
366
    // "fichero_ya_existe_seguro_desea_guardarlo"),
367
    // PluginServices.getText(this, "confirmation_dialog"),
368
    // JOptionPane.YES_NO_CANCEL_OPTION,
369
    // JOptionPane.QUESTION_MESSAGE,
370
    // null,
371
    // options, options[1]);
372
    // if (answer!=JOptionPane.OK_OPTION) {
373
    // // 'Cancel' pressed or window closed: don't save anythig, exit
374
    // save dialog
375
    // return;
376
    // }
377
    // }
378
    //
379
    //
380
    // try {
381
    // driver.write(layer.getMapContext().getLayers(),layer,
382
    // activePanel.getLegend(), file, version);
383
    //
384
    // } catch (LegendDriverException e1) {
385
    // int type = e1.getType();
386
    // String message=PluginServices.getText(this,
387
    // "could_not_save_legend")+":\n";
388
    //
389
    // if ((type & LegendDriverException.SAVE_LEGEND_ERROR) != 0){
390
    // type = type & ~LegendDriverException.SAVE_LEGEND_ERROR;
391
    // message += PluginServices.getText(this,
392
    // "error_writing_file")+".\n";
393
    // }
394
    // if ((type & LegendDriverException.UNSUPPORTED_LEGEND_CREATION) !=
395
    // 0){
396
    // type = type & ~LegendDriverException.UNSUPPORTED_LEGEND_CREATION;
397
    // message += "-"+ PluginServices.getText(this,
398
    // "legend_format_not_yet_supported")+"\n";
399
    // }
400
    // if (type != 0) {
401
    // message = "-"+PluginServices.getText(this, "unknown_error")+"\n";
402
    // }
403
    // JOptionPane.showMessageDialog((Component)PluginServices.getMainFrame(),
404
    // message);
405
    // }
406
    // }
407
    // } else if (c.equals(getBtnLoadLegend())) {
408
    //
409
    // JLegendFileChooser jfc = new
410
    // JLegendFileChooser(getLegendDrivers());
411
    // jfc.setAcceptAllFileFilterUsed(false);
412
    //
413
    // if (jfc.showOpenDialog((Component) PluginServices.getMainFrame())
414
    // == JFileChooser.APPROVE_OPTION) {
415
    // File file=jfc.getSelectedFile();
416
    // IFMapLegendDriver driver = jfc.getSuitableDriver();
417
    // String path = file.getAbsolutePath();
418
    // defaultLegendFolderPath = path.substring(0,
419
    // path.lastIndexOf(File.separator));
420
    //
421
    // try {
422
    // table = driver.read(layer.getMapContext().getLayers(),layer,
423
    // file);
424
    //
425
    // if(table.containsKey(layer))
426
    // applyLegend((ILegend) table.get(layer));
427
    //
428
    //
429
    // } catch (LegendDriverException e1) {
430
    // int type = e1.getType();
431
    // String message = PluginServices.getText(this,
432
    // "the_legend_will_not_be_applied")+":\n";
433
    // boolean hasReason = false;
434
    //
435
    // if ((type &
436
    // LegendDriverException.CLASSIFICATION_FIELDS_NOT_FOUND) != 0){
437
    // type = type &
438
    // ~LegendDriverException.CLASSIFICATION_FIELDS_NOT_FOUND;
439
    // message +="-"+ PluginServices.getText(this,
440
    // "classification_field_does_not_exists")+"\n";
441
    // hasReason = true;
442
    // }
443
    // if ((type & LegendDriverException.LEGEND_TYPE_NOT_YET_SUPPORTED)
444
    // != 0){
445
    // type = type &
446
    // ~LegendDriverException.LEGEND_TYPE_NOT_YET_SUPPORTED;
447
    // message += "-"+ PluginServices.getText(this,
448
    // "legend_type_not_yet_supported")+"\n";
449
    // hasReason = true;
450
    // }
451
    // if ((type & LegendDriverException.SYMBOL_TYPE_NOT_YET_SUPPORTED)
452
    // != 0){
453
    // type = type &
454
    // ~LegendDriverException.SYMBOL_TYPE_NOT_YET_SUPPORTED;
455
    // message += "-"+ PluginServices.getText(this,
456
    // "unsupported_symbol_type")+"\n";
457
    // hasReason = true;
458
    // }
459
    // if ((type & LegendDriverException.LAYER_SHAPETYPE_MISMATCH) !=
460
    // 0){
461
    // type = type & ~LegendDriverException.LAYER_SHAPETYPE_MISMATCH;
462
    // message += "-"+ PluginServices.getText(this,
463
    // "layer_geometry_and_legend_types_are_incompatible")+"\n";
464
    // hasReason = true;
465
    // }
466
    // if ((type & LegendDriverException.PARSE_LEGEND_FILE_ERROR) != 0){
467
    // type = type & ~LegendDriverException.PARSE_LEGEND_FILE_ERROR;
468
    // message += "-"+ PluginServices.getText(this,
469
    // "failed_reading_file")+"\n";
470
    // hasReason = true;
471
    // }
472
    // if ((type &
473
    // LegendDriverException.UNSUPPORTED_LEGEND_FILE_VERSION) != 0){
474
    // type = type &
475
    // ~LegendDriverException.UNSUPPORTED_LEGEND_FILE_VERSION;
476
    // message += "-"+ PluginServices.getText(this,
477
    // "unsupported_legend_file_version")+"\n";
478
    // hasReason = true;
479
    // }
480
    // if ((type & LegendDriverException.UNSUPPORTED_LEGEND_READING) !=
481
    // 0){
482
    // type = type & ~LegendDriverException.UNSUPPORTED_LEGEND_READING;
483
    // message +="-"+ PluginServices.getText(this,
484
    // "unsupported_legend_file_format")+"\n";
485
    // hasReason = true;
486
    // }
487
    // if ((type & LegendDriverException.LAYER_NAME_NOT_FOUND) != 0){
488
    // type = type & ~LegendDriverException.UNSUPPORTED_LEGEND_READING;
489
    // message +="-"+ PluginServices.getText(this,
490
    // "could_not_find_layer")+"\n";
491
    // hasReason = true;
492
    // }
493
    // if (!hasReason) {
494
    // message = "-"+ PluginServices.getText(this,
495
    // "unknown_error")+"\n";
496
    // }
497
    // JOptionPane.showMessageDialog((Component)PluginServices.getMainFrame(),
498
    // message);
499
    // }
500
    // }
501
    // }
502

    
503
    // private IFMapLegendDriver[] getLegendDrivers() {
504
    // Class<?>[] legendDriverClasses = legendDriverPool.toArray(new Class[0]);
505
    // ArrayList<IFMapLegendDriver> drivers = new
506
    // ArrayList<IFMapLegendDriver>();
507
    // for (int i = 0; i < legendDriverClasses.length; i++) {
508
    // String message = PluginServices.getText(this,
509
    // "adding_legend_file_format_support")+": ";
510
    // try {
511
    // Class<?> c = legendDriverClasses[i];
512
    // drivers.add((IFMapLegendDriver) c.newInstance());
513
    // } catch (Exception e) {
514
    // NotificationManager.addError(message+PluginServices.getText(this,
515
    // "failed"), e);
516
    // }
517
    // NotificationManager.addInfo(message+PluginServices.getText(this, "OK"));
518
    //
519
    // }
520
    // return (IFMapLegendDriver[]) drivers.toArray(new IFMapLegendDriver[0]);
521
    // };
522

    
523
    private String getExtension(File f) {
524
        String ext = null;
525
        String s = f.getName();
526
        int i = s.lastIndexOf('.');
527

    
528
        if (i > 0 && i < s.length() - 1) {
529
            // ext = s.substring(i + 1).toLowerCase();
530
            ext = s.substring(i).toLowerCase();
531
        }
532
        return ext;
533
    }
534

    
535
    public LegendManager() {
536
        initialize();
537
    }
538

    
539
    private void initialize() {
540
        setLayout(new BorderLayout());
541
        add(getTopPanel(), BorderLayout.NORTH);
542
        add(getSplitPane(), BorderLayout.CENTER);
543
        setSize(500, 360);
544
        treeModel = new DefaultTreeModel(root);
545
    }
546

    
547
    private JSplitPane getSplitPane() {
548
        if (jSplitPane == null) {
549
            jSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
550
            JPanel aux = new JPanel(new BorderLayout(0, 5));
551
            aux.add(getLegendTreeScrollPane(), BorderLayout.CENTER);
552
            aux.add(getPreviewPanel(), BorderLayout.SOUTH);
553
            jSplitPane.setLeftComponent(aux);
554
            jSplitPane.setRightComponent(getCentralPanel());
555
            jSplitPane.setDividerLocation(150);
556
        }
557
        return jSplitPane;
558
    }
559

    
560
    private JPanel getCentralPanel() {
561
        if (jCentralPanel == null) {
562
            jCentralPanel = new JPanel(new BorderLayout(0, 10));
563
            jCentralPanel.add(getTitleScroll(), BorderLayout.NORTH);
564
            jCentralPanel.add(getJPanelContainer(), BorderLayout.CENTER);
565
        }
566
        return jCentralPanel;
567
    }
568

    
569
    private JScrollPane getJPanelContainer() {
570
        if (jPanelContainer == null) {
571
            jPanelContainer = new JScrollPane();
572
        }
573
        return jPanelContainer;
574
    }
575

    
576
    /**
577
     * This method initializes jPanel
578
     * 
579
     * @return javax.swing.JPanel
580
     */
581
    private JPanel getTopPanel() {
582
        if (topPanel == null) {
583
            topPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT, 5, 0));
584
            topPanel.setPreferredSize(new Dimension(638, 31));
585
            topPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(
586
                null, "",
587
                javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION,
588
                javax.swing.border.TitledBorder.DEFAULT_POSITION, null, null));
589
            topPanel.add(getBtnSaveLegend(), null);
590
            topPanel.add(getBtnLoadLegend(), null);
591
        }
592
        return topPanel;
593
    }
594

    
595
    private JButton getBtnSaveLegend() {
596
        if (btnSaveLegend == null) {
597
            btnSaveLegend =
598
                new JButton(PluginServices.getText(this, "Guardar_leyenda")
599
                    + "...");
600
            btnSaveLegend.addActionListener(loadSaveLegendAction);
601
        }
602
        return btnSaveLegend;
603
    }
604

    
605
    private JButton getBtnLoadLegend() {
606
        if (btnLoadLegend == null) {
607
            btnLoadLegend =
608
                new JButton(PluginServices.getText(this, "Recuperar_leyenda")
609
                    + "...");
610
            btnLoadLegend.addActionListener(loadSaveLegendAction);
611
        }
612
        return btnLoadLegend;
613
    }
614

    
615
    /**
616
     * This method initializes jTextArea
617
     * 
618
     * @return javax.swing.JTextArea
619
     */
620
    private JTextArea getTitleArea() {
621
        if (titleArea == null) {
622
            titleArea = new JTextArea();
623
            titleArea.setBackground(java.awt.SystemColor.control);
624
            titleArea.setLineWrap(true);
625
            titleArea.setRows(0);
626
            titleArea.setWrapStyleWord(false);
627
            titleArea.setEditable(false);
628
            titleArea.setPreferredSize(new java.awt.Dimension(495, 40));
629
        }
630
        return titleArea;
631
    }
632

    
633
    /**
634
     * This method initializes jPanel1
635
     * 
636
     * @return javax.swing.JPanel
637
     */
638
    private JPanel getPreviewPanel() {
639
        if (preview == null) {
640
            preview = new JPanel();
641
            preview.setBorder(javax.swing.BorderFactory
642
                .createBevelBorder(javax.swing.border.BevelBorder.LOWERED));
643
            preview.setBackground(java.awt.SystemColor.text);
644
            preview.setLayout(new BorderLayout(5, 5));
645
            preview.add(getIconLabel());
646
            preview.setPreferredSize(new Dimension(getSplitPane()
647
                .getDividerLocation(), 130));
648
            preview.setBackground(Color.white);
649
        }
650
        return preview;
651
    }
652

    
653
    private JLabel getIconLabel() {
654
        if (iconLabel == null) {
655
            iconLabel = new JLabel();
656
            iconLabel.setVerticalAlignment(JLabel.CENTER);
657
            iconLabel.setHorizontalAlignment(JLabel.CENTER);
658
        }
659

    
660
        return iconLabel;
661
    }
662

    
663
    /**
664
     * This method initializes jScrollPane
665
     * 
666
     * @return javax.swing.JScrollPane
667
     */
668
    private JScrollPane getLegendTreeScrollPane() {
669
        if (legendTreeScrollPane == null) {
670
            legendTreeScrollPane = new JScrollPane();
671
            legendTreeScrollPane.setViewportView(getJTreeLegends());
672
        }
673
        return legendTreeScrollPane;
674
    }
675

    
676
    /**
677
     * <p>
678
     * Adds a new fully-featured legend panel to the LegendManager.<br>
679
     * </p>
680
     * 
681
     * <p>
682
     * <b>CAUTION:</b> Trying to add a child page whose parent hasn't been added
683
     * yet causes the application to fall in an infinite loop. This is a known
684
     * bug, sorry. Just avoid this case or try to fix it (lol).<br>
685
     * </p>
686
     * 
687
     * <p>
688
     * <b>Notice</b> that there is no type check so if you add a
689
     * non-ILegendPanel class, you'll have a runtime error later.
690
     * </p>
691
     * 
692
     * @param page
693
     *            , Class of type ILegendPanel
694
     */
695
    public static void addLegendPage(
696
        Class<? extends ILegendPanel> iLegendPanelClass) {
697
        if (!legendPool.contains(iLegendPanelClass)) {
698
            legendPool.add(iLegendPanelClass);
699
        }
700
    }
701

    
702
    /**
703
     * Causes the component to be autofilled with the legend pages that
704
     * were added through the static method addLegendPage(ILegendPanel page)
705
     */
706
    private void fillDialog() {
707
        if (empty) {
708
            
709
            Class<?> pageClass = null;
710
            ILegendPanel page = null;
711
            
712
            for (int i = 0; i < legendPool.size(); i++) {
713
                pageClass = (Class<?>) legendPool.get(i);
714
                try {
715
                    page = (ILegendPanel) pageClass.newInstance();
716
                } catch (Exception e) {
717
                    logger.info("Unable to instantiate legend panel.", e);
718
                }
719
                if (page != null && page.isSuitableFor(layer)) {
720
                    pages.put(page.getClass(), page); // this legend can be applied
721
                }
722
            }
723
            
724
            Enumeration<ILegendPanel> enume = pages.elements();
725
            while (enume.hasMoreElements()) {
726
                page = enume.nextElement();
727
                doInsertNode(treeModel, page);
728
            }
729

    
730
            getJTreeLegends().setModel(treeModel);
731
            getJTreeLegends().repaint();
732
            empty = false;
733
        }
734
    }
735

    
736
    @SuppressWarnings("unchecked")
737
    private DefaultMutableTreeNode findNode(Class searchID) {
738
        String title;
739
        try {
740
            title =
741
                ((ILegendPanel) Class.forName(searchID.getName()).newInstance())
742
                    .getTitle();
743
        } catch (Exception e) {
744
            // this should be impossible, but anyway this case will be treat as
745
            // the node does not
746
            // exist.
747
            return null;
748
        }
749

    
750
        Enumeration e = root.breadthFirstEnumeration();
751
        while (e.hasMoreElements()) {
752
            DefaultMutableTreeNode nodeAux =
753
                (DefaultMutableTreeNode) e.nextElement();
754
            if (nodeAux != null) {
755
                ILegendPanel legend = (ILegendPanel) nodeAux.getUserObject();
756
                if (legend == null)
757
                    continue; // Root node
758
                if (legend.getTitle().equals(title)) {
759
                    return nodeAux;
760
                }
761
            }
762
        }
763
        return null;
764
    }
765

    
766
    /**
767
     * If parent_node == null, add to root.
768
     * Returns added node
769
     * 
770
     * @param tm
771
     * @param parent_node
772
     * @param item
773
     */
774
    private MutableTreeNode insertNodeHere(
775
        DefaultTreeModel tm,
776
        MutableTreeNode parent_node,
777
        ILegendPanel item) {
778
        
779
        MutableTreeNode pn = null;
780
        
781
        if (parent_node == null) {
782
            pn = root;
783
        } else {
784
            pn = parent_node;
785
        }
786
        
787
        DefaultMutableTreeNode nodeValue = new DefaultMutableTreeNode(item);
788
        int children = pn.getChildCount();
789
        int pos = 0;
790
        String pTitle = null;
791
        
792
        for (int i = 0; i < children; i++) {
793
            DefaultMutableTreeNode node =
794
                (DefaultMutableTreeNode) tm.getChild(pn, i);
795
            if (node.getUserObject() instanceof ILegendPanel) {
796
                pTitle = ((ILegendPanel) node.getUserObject()).getTitle();
797
                if (pTitle.compareTo(item.getTitle()) < 0) {
798
                    pos++;
799
                }
800
            }
801
        }
802
        tm.insertNodeInto(nodeValue, pn, pos);
803
        return nodeValue;
804
    }
805
    
806
    /**
807
     * Returns inserted node
808
     * 
809
     * @param tm
810
     * @param page
811
     * @return
812
     */
813
    private MutableTreeNode doInsertNode(DefaultTreeModel tm, ILegendPanel page) {
814
        
815
        if (tm == null || page == null) {
816
            return null;
817
        }
818
        
819
        MutableTreeNode aux = findNode(page.getClass()); 
820
        if (aux != null) {
821
            return aux;
822
        }
823

    
824
        Class parent_class = page.getParentClass();
825
        
826
        if (parent_class != null) {
827
            if (pages.containsKey(parent_class)) {
828
                ILegendPanel parent = (ILegendPanel) pages.get(parent_class);
829
                
830
                aux = doInsertNode(tm, parent); 
831
                if (aux != null) {
832
                    return insertNodeHere(tm, aux, page);
833
                } else {
834
                    return null;
835
                }
836
                
837
            } else {
838
                return null;
839
            }
840
        } else {
841
            // add to root
842
            return insertNodeHere(tm, null, page);
843
        }
844
        
845

    
846
    }
847
    
848
    
849
    
850
    
851

    
852
    private JScrollPane getTitleScroll() {
853
        if (jTitleScrollPane == null) {
854
            jTitleScrollPane = new JScrollPane();
855
            jTitleScrollPane.setBounds(2, 2, 498, 42);
856
            jTitleScrollPane.setViewportView(getTitleArea());
857
        }
858
        return jTitleScrollPane;
859
    }
860

    
861
    private JTree getJTreeLegends() {
862
        if (jTreeLegends == null) {
863
            jTreeLegends = new JTree();
864
            jTreeLegends.setRootVisible(false);
865
            MyTreeCellRenderer treeCellRenderer = new MyTreeCellRenderer();
866
            treeCellRenderer.setOpenIcon(null);
867
            treeCellRenderer.setClosedIcon(null);
868
            treeCellRenderer.setLeafIcon(null);
869

    
870
            jTreeLegends.setCellRenderer(treeCellRenderer);
871
            jTreeLegends.setShowsRootHandles(true);
872
            jTreeLegends
873
                .addTreeSelectionListener(new javax.swing.event.TreeSelectionListener() {
874

    
875
                    public void valueChanged(
876
                        javax.swing.event.TreeSelectionEvent e) {
877
                        if (isTreeListenerDisabled)
878
                            return;
879
                        DefaultMutableTreeNode node =
880
                            (DefaultMutableTreeNode) jTreeLegends
881
                                .getLastSelectedPathComponent();
882

    
883
                        if (node == null)
884
                            return;
885
                        setActivePage((ILegendPanel) node.getUserObject());
886
                    }
887
                });
888
            jTreeLegends.putClientProperty("JTree.linestyle", "Angled");
889
            jTreeLegends.getSelectionModel().setSelectionMode(
890
                TreeSelectionModel.SINGLE_TREE_SELECTION);
891
        }
892
        return jTreeLegends;
893
    }
894

    
895
    private void setActivePage(ILegendPanel page) {
896
        if (page.getPanel() == null) {
897
            // this is what happens when the user clicked in a parent node
898
            // which only acts as a folder, and does not manage any legend
899
            // then it expands and selects the first child
900
            DefaultMutableTreeNode node = findNode(page.getClass());
901
            if (treeModel.getChildCount(node) > 0) {
902
                DefaultMutableTreeNode dmn =
903
                    (DefaultMutableTreeNode) treeModel.getChild(node, 0);
904
                page = (ILegendPanel) dmn.getUserObject();
905
                setActivePage(page);
906
                expandAndSelect(page);
907
            }
908
        } else {
909
            // show the page
910
            activePanel = page;
911
            setIcon(activePanel.getIcon());
912

    
913
            activePanel.setData(layer, legend);
914
            getTitleArea().setText(activePanel.getDescription());
915
            jPanelContainer.setViewportView(activePanel.getPanel());
916
        }
917
    }
918

    
919
    private void setIcon(ImageIcon icon) {
920
        getIconLabel().setIcon(icon);
921
    }
922

    
923
    private class MyTreeCellRenderer extends DefaultTreeCellRenderer {
924

    
925
        private static final long serialVersionUID = -6013698992263578041L;
926

    
927
        public MyTreeCellRenderer() {
928
        }
929

    
930
        public Component getTreeCellRendererComponent(JTree tree, Object value,
931
            boolean sel, boolean expanded, boolean leaf, int row,
932
            boolean hasFocus) {
933

    
934
            super.getTreeCellRendererComponent(tree, value, sel, expanded,
935
                leaf, row, hasFocus);
936
            if (value instanceof DefaultMutableTreeNode) {
937
                DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
938
                if (node.getUserObject() instanceof ILegendPanel) {
939
                    ILegendPanel legend = (ILegendPanel) node.getUserObject();
940
                    this
941
                        .setText(legend.getPanel() == null ? "<html><b>"
942
                            + legend.getTitle() + "</b></html>" : legend
943
                            .getTitle());
944
                }
945
            }
946
            return this;
947
        }
948

    
949
    }
950

    
951
    private void expandAndSelect(Object node) {
952
        isTreeListenerDisabled = true;
953
        // will expand the tree and select the node
954
        int i = 0;
955
        boolean exit = false;
956

    
957
        TreePath tp = null;
958
        // find the page in the tree
959
        while (i < jTreeLegends.getRowCount() && !exit) {
960
            // see if this row is the node that we are looking for
961

    
962
            tp = jTreeLegends.getPathForRow(i);
963
            Object[] obj = tp.getPath();
964
            for (int j = 0; j < obj.length && !exit; j++) {
965
                Object o = ((DefaultMutableTreeNode) obj[j]).getUserObject();
966

    
967
                if (o != null && o.getClass().equals(node.getClass())
968
                    && o.equals(node)) {
969
                    // found it! collapse the tree
970
                    while (i >= 0) {
971
                        jTreeLegends.collapseRow(i);
972
                        i--;
973
                    }
974
                    exit = true;
975
                }
976
            }
977
            jTreeLegends.expandRow(i);
978
            i++;
979
        }
980

    
981
        // expand the tree and set the selection
982
        if (tp != null) {
983
            jTreeLegends.expandPath(tp);
984
            jTreeLegends.setSelectionPath(tp);
985
        }
986
        isTreeListenerDisabled = false;
987
    }
988

    
989
    public String getName() {
990
        return PluginServices.getText(this, "Simbologia");
991
    }
992

    
993
    public void acceptAction() {
994
        // automatically handled by the ThemeManagerWindow
995
    }
996

    
997
    public void cancelAction() {
998
        // does nothing
999
    }
1000

    
1001
    public void applyAction() {
1002
        legend = activePanel.getLegend();
1003

    
1004
        if (table != null && table.size() > 1)
1005
            applyRestOfLegends(table, layer.getMapContext().getLayers());
1006

    
1007
        /*
1008
         * try to apply the legend to all the active layers that
1009
         * can accept it
1010
         */
1011
        FLayer[] activeLyrs = layer.getMapContext().getLayers().getActives();
1012
        for (int i = 0; i < activeLyrs.length; i++) {
1013
            FLayer laux = activeLyrs[i];
1014

    
1015
            if (activeLyrs[i] instanceof FLayers) {
1016
                laux = getFirstActiveLayerVect((FLayers) activeLyrs[i]);
1017
            }
1018

    
1019
            if (laux instanceof ClassifiableVectorial) {
1020
                ClassifiableVectorial aux2 = (ClassifiableVectorial) laux;
1021
                try {
1022
                    if (legend instanceof IClassifiedVectorLegend) {
1023
                        // Es una leyenda que necesita un recordset con un
1024
                        // nombre de campo. Comprobamos que ese recordset
1025
                        // tiene ese nombre de campo y es del tipo esperado
1026
                        IClassifiedVectorLegend cl =
1027
                            (IClassifiedVectorLegend) legend;
1028

    
1029
                        if (aux2 instanceof FLyrVect) {
1030

    
1031
                            if (cl.getValues().length == 0) {
1032
                                JOptionPane.showMessageDialog(
1033
                                    (Component) PluginServices.getMainFrame(),
1034
                                    PluginServices.getText(this,
1035
                                        "no_es_posible_aplicar_leyenda_vacia"));
1036
                                return;
1037
                            }
1038

    
1039
                            aux2.setLegend((IVectorLegend) legend);
1040
                        }
1041
                    } else
1042
                        if (legend instanceof IVectorLegend) {
1043
                            aux2.setLegend((IVectorLegend) legend);
1044
                        }
1045
                } catch (LegendLayerException e) {
1046
                    NotificationManager.addError(PluginServices.getText(this,
1047
                        "legend_exception"), e);
1048
                }
1049
            }
1050
        }
1051
    }
1052

    
1053
    private void applyRestOfLegends(Hashtable<FLayer, ILegend> table2,
1054
        FLayers layers) {
1055

    
1056
        for (int i = 0; i < layers.getLayersCount(); i++) {
1057
            FLayer my_layer = layers.getLayer(i);
1058

    
1059
            if (!(my_layer instanceof FLayers)) {
1060
                if (my_layer instanceof ClassifiableVectorial) {
1061
                    try {
1062
                        if (table.containsKey(my_layer)) {
1063
                            ClassifiableVectorial lyr =
1064
                                (ClassifiableVectorial) my_layer;
1065
                            lyr.setLegend((IVectorLegend) table.get(my_layer));
1066
                        }
1067

    
1068
                    } catch (LegendLayerException e) {
1069
                        // TODO Auto-generated catch block
1070
                        e.printStackTrace();
1071
                    }
1072
                }
1073
            } else
1074
                applyRestOfLegends(table, (FLayers) my_layer);
1075
        }
1076
    }
1077

    
1078
    @Override
1079
    public void setModel(FLayer layer) {
1080
        this.layer = layer;
1081
        applyLegend(((Classifiable) layer).getLegend());
1082
    }
1083

    
1084
    /**
1085
     * Applies the legend to the layer.
1086
     * 
1087
     * @param aLegend
1088
     *            , legend that the user wants to apply
1089
     */
1090
    private void applyLegend(ILegend aLegend) {
1091
        this.legend = aLegend;
1092
        fillDialog();
1093
        Enumeration<Class<? extends ILegendPanel>> en = pages.keys();
1094
        while (en.hasMoreElements()) {
1095
            ILegendPanel page = (ILegendPanel) pages.get(en.nextElement());
1096
            if (legend.getClass().equals(page.getLegendClass())) {
1097
                setActivePage(page);
1098
                expandAndSelect(page);
1099
                return;
1100
            }
1101
        }
1102
        NotificationManager.addWarning(PluginServices.getText(this,
1103
            "caution_no_registered_panel_associated_to_"
1104
                + "loaded_legend_the_legend_wont_be_applied"));
1105
    }
1106

    
1107
    // public static void addLegendDriver(Class<? extends IFMapLegendDriver>
1108
    // legendDriverClass) {
1109
    // if (!legendDriverPool.contains(legendDriverClass)) {
1110
    // legendDriverPool.add(legendDriverClass);
1111
    // }
1112
    // }
1113
}