Statistics
| Revision:

root / tags / v2_0_0_Build_2051 / libraries / 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 @ 38760

History | View | Annotate | Download (14.4 KB)

1
/* gvSIG. Geographic Information System of the Valencian Government
2
 *
3
 * Copyright (C) 2007-2008 Infrastructures and Transports Department
4
 * of the Valencian Government (CIT)
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 2
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
 */
22
package org.gvsig.symbology.fmap.mapcontext.rendering.legend.impl;
23

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

    
33
import org.slf4j.Logger;
34
import org.slf4j.LoggerFactory;
35

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

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

    
61
        public static final String VECTORIAL_UNIQUE_VALUE_LEGEND_PERSISTENCE_DEFINITION_NAME =
62
                        "VectorialUniqueValueLegend";
63

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

    
70
        private Map<Object, ISymbol> symbols = createSymbolMap();
71

    
72
        private List<Object> keys = new ArrayList<Object>();
73

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

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

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

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

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

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

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

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

    
144
        fireLegendClearEvent(new LegendClearEvent(olds));
145
    }
146

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

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

    
155
        return descriptions;
156
    }
157

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

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

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

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

    
199
        if (theSymbol != null) {
200
                return theSymbol;
201

    
202
        }
203

    
204
        if (isUseDefaultSymbol()) {
205
                        return defaultSymbol;
206
                }
207

    
208
        return null;
209
    }
210

    
211

    
212
    public ISymbol getDefaultSymbol() {
213

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

    
221
        public void setDefaultSymbol(ISymbol s) {
222
            ISymbol mySymbol = defaultSymbol;
223

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

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

    
233

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

    
252
    }
253

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

    
267
    public int getShapeType() {
268
        return shapeType;
269
    }
270

    
271
    public void useDefaultSymbol(boolean b) {
272
        useDefaultSymbol = b;
273
    }
274

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

    
283
    public void delSymbol(Object key) {
284
        keys.remove(key);
285

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

    
292
        public String getClassName() {
293
                return getClass().getName();
294
        }
295

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

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

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

    
317
        public Object clone() throws CloneNotSupportedException {
318
                VectorialUniqueValueLegend clone =
319
                                (VectorialUniqueValueLegend) super.clone();
320

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

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

    
356

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

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

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

    
387
                                                return 0;
388
                                        }
389
                                });
390

    
391
        }
392

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

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

    
421
        public static class RegisterPersistence implements Callable {
422

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

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

    
452
        public static class RegisterLegend implements Callable {
453

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

    
460
                        return Boolean.TRUE;
461
                }
462
                
463
        }
464
}