Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.library / org.gvsig.symbology / org.gvsig.symbology.lib / org.gvsig.symbology.lib.impl / src / main / java / org / gvsig / symbology / fmap / mapcontext / rendering / legend / impl / VectorialUniqueValueLegend.java @ 40560

History | View | Annotate | Download (14.4 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.symbology.fmap.mapcontext.rendering.legend.impl;
25

    
26
import java.awt.Color;
27
import java.util.ArrayList;
28
import java.util.Comparator;
29
import java.util.Iterator;
30
import java.util.List;
31
import java.util.Map;
32
import java.util.Map.Entry;
33
import java.util.TreeMap;
34

    
35
import org.slf4j.Logger;
36
import org.slf4j.LoggerFactory;
37

    
38
import org.gvsig.fmap.dal.feature.Feature;
39
import org.gvsig.fmap.mapcontext.MapContextException;
40
import org.gvsig.fmap.mapcontext.MapContextLocator;
41
import org.gvsig.fmap.mapcontext.MapContextManager;
42
import org.gvsig.fmap.mapcontext.rendering.legend.IVectorialUniqueValueLegend;
43
import org.gvsig.fmap.mapcontext.rendering.legend.events.LegendClearEvent;
44
import org.gvsig.fmap.mapcontext.rendering.legend.events.LegendContentsChangedListener;
45
import org.gvsig.fmap.mapcontext.rendering.legend.events.SymbolLegendEvent;
46
import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
47
import org.gvsig.tools.ToolsLocator;
48
import org.gvsig.tools.dynobject.DynStruct;
49
import org.gvsig.tools.persistence.PersistenceManager;
50
import org.gvsig.tools.persistence.PersistentState;
51
import org.gvsig.tools.persistence.exception.PersistenceException;
52
import org.gvsig.tools.util.Callable;
53

    
54
/**
55
 * Vectorial legend for unique values
56
 * 
57
 * @author Vicente Caballero Navarro
58
 * @author 2009- <a href="cordinyana@gvsig.org">C?sar Ordi?ana</a> - gvSIG team
59
 */
60
public class VectorialUniqueValueLegend extends AbstractClassifiedVectorLegend implements IVectorialUniqueValueLegend {
61
        final static private Logger LOG = LoggerFactory.getLogger(VectorialUniqueValueLegend.class);
62

    
63
        public static final String VECTORIAL_UNIQUE_VALUE_LEGEND_PERSISTENCE_DEFINITION_NAME =
64
                        "VectorialUniqueValueLegend";
65

    
66
        private static final String FIELD_KEYS = "keys";
67
        private static final String FIELD_NULL_VALUE_SYMBOL = "nullValueSymbol";
68
        private static final String FIELD_SELECTED_COLORS = "selectedColors";
69
        private static final String FIELD_SYMBOLS = "symbols";
70
        private static final String FIELD_USE_DEFAULT_SYMBOL = "useDefaultSymbol";
71

    
72
        private Map<Object, ISymbol> symbols = createSymbolMap();
73

    
74
        private List<Object> keys = new ArrayList<Object>();
75

    
76
    private ISymbol defaultSymbol;
77
    private int shapeType;
78
    private boolean useDefaultSymbol = false;
79
    private Color[] selectedColors=null;
80
    
81
    private ISymbol nullValueSymbol = null;
82
    
83
    public VectorialUniqueValueLegend() {
84
                super();
85
        }
86

    
87
    /**
88
     * Constructor method
89
     *
90
     * @param shapeType Type of the shape.
91
     */
92
    public VectorialUniqueValueLegend(int shapeType) {
93
                super();
94
            setShapeType(shapeType);
95
    }
96

    
97
    public void setShapeType(int shapeType) {
98
            if (this.shapeType != shapeType) {
99
                    if(defaultSymbol==null || defaultSymbol.getSymbolType()!=shapeType){
100
                            ISymbol old = defaultSymbol;
101
                            defaultSymbol = getSymbolManager().createSymbol(shapeType);
102
                            fireDefaultSymbolChangedEvent(new SymbolLegendEvent(old, defaultSymbol));
103
                    }
104
                    this.shapeType = shapeType;
105
            }
106
    }
107

    
108
    public void setValueSymbolByID(int id, ISymbol symbol) {
109
        ISymbol old = (ISymbol)symbols.put(keys.get(id), symbol);
110
        fireClassifiedSymbolChangeEvent(new SymbolLegendEvent(old, symbol));
111
    }
112

    
113
    public Object[] getValues() {
114
        return symbols.keySet().toArray(new Object[0]);
115
    }
116

    
117
    public void addSymbol(Object key, ISymbol symbol) {
118
            ISymbol resul;
119
            if (key == null) {
120
                    resul = nullValueSymbol;
121
                    nullValueSymbol = symbol;
122
            }
123
            else {
124
                        resul = (ISymbol) symbols.put(key, symbol);
125

    
126
                        if (resul != null) {
127
                                LOG.error("Error: la clave " + key + " ya exist?a. Resul = "
128
                                                + resul);
129
                                LOG.warn("symbol nuevo:" + symbol.getDescription()
130
                                                + " Sviejo= " + resul.getDescription());
131
                        } else {
132
                                keys.add(key);
133
                        }
134
            }
135
            
136
        fireClassifiedSymbolChangeEvent(new SymbolLegendEvent(resul, symbol));
137
    }
138

    
139
    public void clear() {
140
        keys.clear();
141
        ISymbol[] olds = (ISymbol[])symbols.values().toArray(new ISymbol[0]);
142
        symbols.clear();
143
        removeLegendListener(getZSort());
144
        setZSort(null);
145

    
146
        fireLegendClearEvent(new LegendClearEvent(olds));
147
    }
148

    
149
    public String[] getDescriptions() {
150
        String[] descriptions = new String[symbols.size()];
151
        ISymbol[] auxSym = getSymbols();
152

    
153
        for (int i = 0; i < descriptions.length; i++) {
154
                        descriptions[i] = auxSym[i].getDescription();
155
                }
156

    
157
        return descriptions;
158
    }
159

    
160
     public ISymbol[] getSymbols() {
161
                 ISymbol[] symbolList;
162
                if (nullValueSymbol == null) {
163
                        symbolList = new ISymbol[symbols.size()];
164
                        return (ISymbol[]) symbols.values().toArray(symbolList);
165
                }
166
                else {
167
                        symbolList = new ISymbol[symbols.size() + 1];
168
                        symbolList[0] = nullValueSymbol;
169
                        int i = 1;
170
                        for (Iterator<ISymbol> iterator = symbols.values().iterator(); iterator
171
                                        .hasNext();) {
172
                                symbolList[i] = iterator.next();
173
                                i++;
174
                        }
175
                        return symbolList;
176
                }
177
    }
178

    
179
    public void setClassifyingFieldNames(String[] fNames) {
180
        // TODO: Check if need more process
181
        super.setClassifyingFieldNames(fNames);
182
    }
183

    
184
    /**
185
         * Devuelve un s?mbolo a partir de una IFeature. OJO!! Cuando usamos un
186
         * feature iterator de base de datos el ?nico campo que vendr? rellenado es
187
         * el de fieldID. Los dem?s vendr?n a nulos para ahorra tiempo de creaci?n.
188
         *
189
         * @param feat
190
         *            IFeature
191
         *
192
         * @return S?mbolo.
193
     * @throws MapContextException 
194
         */
195
    public ISymbol getSymbolByFeature(Feature feat) throws MapContextException {
196

    
197
            Object val = feat.get(getClassifyingFieldNames()[0]);
198
//        Object val = feat.get(fieldId);
199
        ISymbol theSymbol = getSymbolByValue(val);
200

    
201
        if (theSymbol != null) {
202
                return theSymbol;
203

    
204
        }
205

    
206
        if (isUseDefaultSymbol()) {
207
                        return defaultSymbol;
208
                }
209

    
210
        return null;
211
    }
212

    
213

    
214
    public ISymbol getDefaultSymbol() {
215

    
216
            if(defaultSymbol==null) {
217
                        defaultSymbol = getSymbolManager().createSymbol(shapeType);
218
                    fireDefaultSymbolChangedEvent(new SymbolLegendEvent(null, defaultSymbol));
219
            }
220
            return defaultSymbol;
221
    }
222

    
223
        public void setDefaultSymbol(ISymbol s) {
224
            ISymbol mySymbol = defaultSymbol;
225

    
226
            if (s == null) {
227
                        throw new NullPointerException("Default symbol cannot be null");
228
                }
229

    
230
            ISymbol old = mySymbol;
231
            defaultSymbol = s;
232
            fireDefaultSymbolChangedEvent(new SymbolLegendEvent(old, s));
233
    }
234

    
235

    
236
    /*
237
     * (non-Javadoc)
238
     *
239
     * @see com.iver.cit.gvsig.fmap.rendering.UniqueValueLegend#getSymbolByValue(com.hardcode.gdbms.engine.values.Value)
240
     */
241
    public ISymbol getSymbolByValue(Object key) {
242
            ISymbol symbol = null; 
243
            if (key == null) {
244
                    symbol = nullValueSymbol;
245
            }
246
            else {
247
                    symbol = (ISymbol)symbols.get(key);
248
            }
249
            if (symbol == null && useDefaultSymbol) {
250
                    symbol = getDefaultSymbol();
251
            }
252
            return symbol;
253

    
254
    }
255

    
256
        public Object getSymbolKey(ISymbol symbol) {
257
                if (symbol != null) {
258
                        for (Iterator<Entry<Object, ISymbol>> iterator = symbols.entrySet()
259
                                        .iterator(); iterator.hasNext();) {
260
                                Entry<Object, ISymbol> entry = iterator.next();
261
                                if (symbol.equals(entry.getValue())) {
262
                                        return entry.getKey();
263
                                }
264
                        }
265
                }
266
                return null;
267
        }
268

    
269
    public int getShapeType() {
270
        return shapeType;
271
    }
272

    
273
    public void useDefaultSymbol(boolean b) {
274
        useDefaultSymbol = b;
275
    }
276

    
277
    /**
278
         * Devuelve si se utiliza o no el resto de valores para representarse.
279
         * @return  True si se utiliza el resto de valores.
280
         */
281
    public boolean isUseDefaultSymbol() {
282
        return useDefaultSymbol;
283
    }
284

    
285
    public void delSymbol(Object key) {
286
        keys.remove(key);
287

    
288
                ISymbol removedSymbol = (ISymbol) symbols.remove(key);
289
                if (removedSymbol != null){
290
                        fireClassifiedSymbolChangeEvent(new SymbolLegendEvent(removedSymbol, null));
291
                }
292
    }
293

    
294
        public String getClassName() {
295
                return getClass().getName();
296
        }
297

    
298
        public void replace(ISymbol oldSymbol, ISymbol newSymbol) {
299
                if (symbols.containsValue(oldSymbol)) {
300
                        Iterator<Object> it = symbols.keySet().iterator();
301
                        while (it.hasNext()) {
302
                                Object key = it.next();
303
                                if (symbols.get(key).equals(oldSymbol)) {
304
                                        fireClassifiedSymbolChangeEvent(new SymbolLegendEvent(
305
                                                        (ISymbol)symbols.put(key, newSymbol), newSymbol));
306
                                }
307

    
308
                        }
309
                }
310
        }
311
        public Color[] getColorScheme() {
312
                return selectedColors;
313
        }
314

    
315
        public void setColorScheme(Color[] cc) {
316
                 this.selectedColors = cc;
317
        }
318

    
319
        public Object clone() throws CloneNotSupportedException {
320
                VectorialUniqueValueLegend clone =
321
                                (VectorialUniqueValueLegend) super.clone();
322

    
323
                // Clone default symbol
324
                if (defaultSymbol != null) {
325
                        clone.defaultSymbol = (ISymbol) defaultSymbol.clone();
326
                }
327
                // Clone keys
328
                clone.keys = new ArrayList<Object>();
329
                
330
        // ====================================================
331
                // Temporarily remove listeners to prevent
332
                // cascade of notifications
333
                LegendContentsChangedListener[] list = this.getListeners();
334
                removeListeners(list);
335
        // ====================================================
336

    
337
                // Clone symbols
338
                if (symbols != null) {
339
                        clone.symbols = createSymbolMap();
340
                        for (Iterator<Entry<Object, ISymbol>> iterator =
341
                                        symbols.entrySet().iterator(); iterator.hasNext();) {
342
                                Entry<Object, ISymbol> entry = iterator.next();
343
                                ISymbol symbolClone =
344
                                                (ISymbol) ((ISymbol) entry.getValue()).clone();
345
                                // Map keys are of type Number or String, so being
346
                                // immutable objects, don't clone them
347
                                clone.addSymbol(entry.getKey(), symbolClone);
348
                        }
349
                }
350
                
351
        // ====================================================
352
        // Restore listeners
353
        addListeners(list);
354
        // ====================================================
355
                return clone;
356
        }
357

    
358

    
359
    private void addListeners(LegendContentsChangedListener[] list) {
360
        int len = list.length;
361
        for (int i=0; i<len; i++) {
362
            addLegendListener(list[i]);
363
        }
364
    }
365

    
366
    private void removeListeners(LegendContentsChangedListener[] list) {
367
        int len = list.length;
368
        for (int i=0; i<len; i++) {
369
            removeLegendListener(list[i]);
370
        }
371
    }
372

    
373
    private Map<Object, ISymbol> createSymbolMap() {
374
                return new TreeMap<Object, ISymbol>(
375
                                new Comparator<Object>() { 
376
                                        public int compare(Object o1, Object o2) {
377
                                                if ((o1 != null) && (o2 != null)) {
378
                                                        Object v2 = o2;
379
                                                        Object v1 = o1;
380
                                                        if (v1 instanceof Number && v2 instanceof Number) {
381
                                                                return ((Number) v1).intValue()
382
                                                                                - ((Number) v2).intValue();
383
                                                        }
384
                                                        if (v1 instanceof String && v2 instanceof String) {
385
                                                                return ((String) v1).compareTo(((String) v2));
386
                                                        }
387
                                                }
388

    
389
                                                return 0;
390
                                        }
391
                                });
392

    
393
        }
394

    
395
        @SuppressWarnings({ "unchecked", "rawtypes" })
396
        public void loadFromState(PersistentState state)
397
                        throws PersistenceException {
398
                // Set parent properties
399
                super.loadFromState(state);
400
                // Set own properties
401
                keys = new ArrayList<Object>((List) state.get(FIELD_KEYS));
402
                nullValueSymbol = (ISymbol) state.get(FIELD_NULL_VALUE_SYMBOL);
403
                selectedColors =
404
                                (Color[]) state.getArray(FIELD_SELECTED_COLORS, Color.class);
405
                Map persistedSymbolMap = (Map) state.get(FIELD_SYMBOLS);
406
                if (persistedSymbolMap != null) {
407
                        symbols.putAll(persistedSymbolMap);
408
                }
409
                useDefaultSymbol(state.getBoolean(FIELD_USE_DEFAULT_SYMBOL));
410
        }
411

    
412
        public void saveToState(PersistentState state) throws PersistenceException {
413
                // Save parent properties
414
                super.saveToState(state);
415
                // Save own properties
416
                state.set(FIELD_KEYS, keys);
417
                state.set(FIELD_NULL_VALUE_SYMBOL, nullValueSymbol);
418
                state.set(FIELD_SELECTED_COLORS, selectedColors);
419
                state.set(FIELD_USE_DEFAULT_SYMBOL, isUseDefaultSymbol());
420
                state.set(FIELD_SYMBOLS, symbols);
421
        }
422

    
423
        public static class RegisterPersistence implements Callable {
424

    
425
                public Object call() throws Exception {
426
                        PersistenceManager manager = ToolsLocator.getPersistenceManager();
427
                        if( manager.getDefinition(VECTORIAL_UNIQUE_VALUE_LEGEND_PERSISTENCE_DEFINITION_NAME)==null ) {
428
                                DynStruct definition = manager.addDefinition(
429
                                                VectorialUniqueValueLegend.class,
430
                                                VECTORIAL_UNIQUE_VALUE_LEGEND_PERSISTENCE_DEFINITION_NAME,
431
                                                VECTORIAL_UNIQUE_VALUE_LEGEND_PERSISTENCE_DEFINITION_NAME+" Persistence definition",
432
                                                null, 
433
                                                null
434
                                );
435
                                // Extend the Classified Vector Legend base definition
436
                                definition.extend(manager.getDefinition(CLASSIFIED_VECTOR_LEGEND_PERSISTENCE_DEFINITION_NAME));
437

    
438
                                // Keys
439
                                definition.addDynFieldList(FIELD_KEYS).setClassOfItems(Object.class);
440
                                // Null interval symbol
441
                                definition.addDynFieldObject(FIELD_NULL_VALUE_SYMBOL).setClassOfValue(ISymbol.class);
442
                                // Selected colors
443
                                definition.addDynFieldList(FIELD_SELECTED_COLORS).setClassOfItems(Color.class);
444
                                // Symbols
445
                                definition.addDynFieldMap(FIELD_SYMBOLS).setClassOfItems(ISymbol.class);
446
                                // Use default symbol?
447
                                definition.addDynFieldBoolean(FIELD_USE_DEFAULT_SYMBOL);
448
                        }
449
                        return Boolean.TRUE;
450
                }
451
                
452
        }
453

    
454
        public static class RegisterLegend implements Callable {
455

    
456
                public Object call() throws Exception {
457
                MapContextManager manager = MapContextLocator.getMapContextManager();
458
                
459
            manager.registerLegend(IVectorialUniqueValueLegend.LEGEND_NAME,
460
                    VectorialUniqueValueLegend.class);
461

    
462
                        return Boolean.TRUE;
463
                }
464
                
465
        }
466
}