Statistics
| Revision:

root / branches / v2_0_0_prep / libraries / libFMap_mapcontext / src / org / gvsig / fmap / mapcontext / rendering / symbols / impl / DefaultSymbolManager.java @ 38551

History | View | Annotate | Download (12.9 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

    
23
/*
24
 * AUTHORS (In addition to CIT):
25
 * 2009 {DiSiD Technologies}  {{Task}}
26
 * 
27
 **************************************************************
28
 * Colors from www.ColorBrewer.org by Cynthia A. Brewer,
29
 * Geography, Pennsylvania State University.
30
 * Using groups of 4 colors from the 9 Diverging Schemes
31
 * 4 * 9 = 36 colors
32
 **************************************************************
33
 * 
34
 */
35
package org.gvsig.fmap.mapcontext.rendering.symbols.impl;
36

    
37
import java.awt.Color;
38
import java.io.File;
39
import java.io.FileFilter;
40
import java.io.FileInputStream;
41
import java.io.FileOutputStream;
42
import java.io.IOException;
43
import java.util.Collections;
44
import java.util.HashMap;
45
import java.util.Map;
46
import java.util.Random;
47

    
48
import org.gvsig.fmap.mapcontext.MapContextRuntimeException;
49
import org.gvsig.fmap.mapcontext.impl.InvalidRegisteredClassException;
50
import org.gvsig.fmap.mapcontext.impl.RegisteredClassInstantiationException;
51
import org.gvsig.fmap.mapcontext.rendering.symbols.IMultiLayerSymbol;
52
import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
53
import org.gvsig.fmap.mapcontext.rendering.symbols.IWarningSymbol;
54
import org.gvsig.fmap.mapcontext.rendering.symbols.SymbolException;
55
import org.gvsig.fmap.mapcontext.rendering.symbols.SymbolManager;
56
import org.gvsig.fmap.mapcontext.rendering.symbols.SymbolPreferences;
57
import org.gvsig.tools.ToolsLocator;
58
import org.gvsig.tools.persistence.PersistenceManager;
59
import org.gvsig.tools.persistence.PersistentState;
60
import org.gvsig.tools.persistence.exception.PersistenceException;
61

    
62
/**
63
 * Default {@link SymbolManager} implementation.
64
 * 
65
 * @author gvSIG team
66
 */
67
public class DefaultSymbolManager implements SymbolManager {
68

    
69
        private SymbolPreferences symbolPreferences =
70
                        new DefaultSymbolPreferences();
71

    
72
        private Map symbolsByName = Collections.synchronizedMap(new HashMap());
73

    
74
        private Map symbolsByShapeType = Collections.synchronizedMap(new HashMap());
75

    
76
        private Map multiLineSymbolsByName =
77
                        Collections.synchronizedMap(new HashMap());
78

    
79
        private Map multiLineSymbolsByShapeType =
80
                        Collections.synchronizedMap(new HashMap());
81

    
82
        private IWarningSymbol warningSymbol;
83

    
84
        private Object warningSymbolLock = new Object();
85

    
86
        public ISymbol[] loadSymbols(File folder) throws SymbolException {
87
                return loadSymbols(folder, null);
88
        }
89

    
90
        public ISymbol[] loadSymbols(File folder, FileFilter fileFilter)
91
                        throws SymbolException {
92
                // TODO: add symbol caching
93

    
94
                if (folder.exists()) {
95

    
96
                        File[] symbolFiles = null;
97
                        if (fileFilter == null) {
98
                                symbolFiles = folder.listFiles();
99
                        } else {
100
                                symbolFiles = folder.listFiles(fileFilter);
101
                        }
102

    
103
                        if (symbolFiles != null) {
104
                                ISymbol[] symbols = new ISymbol[symbolFiles.length];
105
                                for (int i = 0; i < symbolFiles.length; i++) {
106
                                        symbols[i] = loadSymbol(symbolFiles[i]);
107
                                }
108
                                return symbols;
109
                        }
110
                }
111

    
112
                return null;
113
        }
114

    
115
        public void saveSymbol(ISymbol symbol, String fileName, File folder)
116
                        throws SymbolException {
117
                saveSymbol(symbol, fileName, folder, false);
118
        }
119

    
120
        public void saveSymbol(ISymbol symbol, String fileName, File folder,
121
                        boolean overwrite) throws SymbolException {
122
                // TODO: add symbol caching
123

    
124
                PersistenceManager persistenceManager = ToolsLocator
125
                                .getPersistenceManager();
126

    
127
                File symbolFile = new File(folder, fileName);
128
                if (!overwrite && symbolFile.exists()) {
129
                        throw new SymbolFileAlreadyExistsException(symbolFile);
130
                }
131

    
132
                try {
133
                        FileOutputStream fos = new FileOutputStream(symbolFile);
134

    
135
                        persistenceManager.saveState(persistenceManager.getState(symbol),
136
                                        fos);
137

    
138
                        fos.flush();
139
                        fos.close();
140
                } catch (PersistenceException e) {
141
                        throw new SaveSymbolException(e);
142
                } catch (IOException e) {
143
                        throw new SaveSymbolException(e);
144
                }
145
        }
146

    
147
        /**
148
         * Loads a persisted symbol from the given file.
149
         */
150
        private ISymbol loadSymbol(File file) throws SymbolException {
151
                if (file.exists()) {
152
                        try {
153
                                FileInputStream fis = new FileInputStream(file);
154

    
155
                                PersistenceManager persistenceManager = ToolsLocator
156
                                                .getPersistenceManager();
157

    
158
                                PersistentState state = persistenceManager.loadState(fis);
159
                                ISymbol symbol = (ISymbol) persistenceManager.create(state);
160

    
161
                                fis.close();
162
                                return symbol;
163
                        } catch (PersistenceException e) {
164
                                throw new LoadSymbolException(e);
165
                        } catch (IOException e) {
166
                                throw new LoadSymbolException(e);
167
                        }
168
                }
169

    
170
                return null;
171
        }
172

    
173
        public SymbolPreferences getSymbolPreferences() {
174
                return symbolPreferences;
175
        }
176

    
177
        public ISymbol createSymbol(String symbolName)
178
                        throws MapContextRuntimeException {
179
                return createSymbol(symbolName, (Class) symbolsByName.get(symbolName),
180
                                ISymbol.class);
181
        }
182

    
183
        public ISymbol createSymbol(int shapeType)
184
                        throws MapContextRuntimeException {
185
                String symbolName =
186
                                (String) symbolsByShapeType.get(new Integer(shapeType));
187

    
188
                return symbolName == null ? null : createSymbol(symbolName);
189
        }
190

    
191
        public ISymbol createSymbol(String symbolName, Color color)
192
                        throws MapContextRuntimeException {
193
                ISymbol symbol = createSymbol(symbolName);
194

    
195
                if (symbol != null) {
196
                        symbol.setColor(color);
197
                }
198

    
199
                return symbol;
200
        }
201

    
202
        public ISymbol createSymbol(int shapeType, Color color)
203
                        throws MapContextRuntimeException {
204
                String symbolName =
205
                                (String) symbolsByShapeType.get(new Integer(shapeType));
206

    
207
                return symbolName == null ? null : createSymbol(symbolName, color);
208
        }
209

    
210
        public IMultiLayerSymbol createMultiLayerSymbol(String symbolName)
211
                        throws MapContextRuntimeException {
212
                return (IMultiLayerSymbol) createSymbol(symbolName,
213
                                (Class) multiLineSymbolsByName.get(symbolName),
214
                                IMultiLayerSymbol.class);
215
        }
216

    
217
        public IMultiLayerSymbol createMultiLayerSymbol(int shapeType)
218
                        throws MapContextRuntimeException {
219
                String symbolName =
220
                                (String) multiLineSymbolsByShapeType.get(new Integer(shapeType));
221

    
222
                return symbolName == null ? null : createMultiLayerSymbol(symbolName);
223
        }
224

    
225
        public void registerSymbol(String symbolName, Class symbolClass)
226
                        throws MapContextRuntimeException {
227
                if (symbolClass == null || !ISymbol.class.isAssignableFrom(symbolClass)) {
228
                        throw new InvalidRegisteredClassException(ISymbol.class,
229
                                        symbolClass, symbolName);
230
                }
231
                symbolsByName.put(symbolName, symbolClass);
232
        }
233

    
234
        public void registerSymbol(String symbolName, int[] shapeTypes,
235
                        Class symbolClass) throws MapContextRuntimeException {
236
                registerSymbol(symbolName, symbolClass);
237
                if (shapeTypes != null) {
238
                        for (int i = 0; i < shapeTypes.length; i++) {
239
                                symbolsByShapeType.put(new Integer(shapeTypes[i]), symbolName);
240
                        }
241
                }
242
        }
243

    
244
        public void registerMultiLayerSymbol(String symbolName, Class symbolClass)
245
                        throws MapContextRuntimeException {
246
                if (symbolClass == null
247
                                || !IMultiLayerSymbol.class.isAssignableFrom(symbolClass)) {
248
                        throw new InvalidRegisteredClassException(IMultiLayerSymbol.class,
249
                                        symbolClass, symbolName);
250
                }
251

    
252
                multiLineSymbolsByName.put(symbolName, symbolClass);
253
        }
254

    
255
        public void registerMultiLayerSymbol(String symbolName, int[] shapeTypes,
256
                        Class symbolClass) throws MapContextRuntimeException {
257
                registerMultiLayerSymbol(symbolName, symbolClass);
258
                if (shapeTypes != null) {
259
                        for (int i = 0; i < shapeTypes.length; i++) {
260
                                multiLineSymbolsByShapeType.put(new Integer(shapeTypes[i]),
261
                                                symbolName);
262
                        }
263
                }
264
        }
265

    
266
        public IWarningSymbol getWarningSymbol(String message, String symbolDesc,
267
                        int symbolDrawExceptionType) throws MapContextRuntimeException {
268
                synchronized (warningSymbolLock) {
269
                        if (warningSymbol == null) {
270
                                warningSymbol = (IWarningSymbol) createSymbol("warning");
271
                        }
272
                }
273

    
274
                // TODO: set those values as parameter values in the draw method.
275
                warningSymbol.setDescription(symbolDesc);
276
                warningSymbol.setMessage(message);
277
                warningSymbol.setDrawExceptionType(symbolDrawExceptionType);
278

    
279
                return warningSymbol;
280
        }
281

    
282
        private ISymbol createSymbol(String symbolName, Class symbolClass,
283
                        Class expectedType) throws MapContextRuntimeException {
284
                ISymbol symbol;
285
                try {
286
                        symbol =
287
                                        (ISymbol) (symbolClass == null ? null
288
                                                        : symbolClass.newInstance());
289
                } catch (InstantiationException e) {
290
                        throw new RegisteredClassInstantiationException(expectedType,
291
                                        symbolClass, symbolName, e);
292
                } catch (IllegalAccessException e) {
293
                        throw new RegisteredClassInstantiationException(expectedType,
294
                                        symbolClass, symbolName, e);
295
                }
296

    
297
                Color the_color = null;
298
                
299
        if (getSymbolPreferences().isDefaultSymbolFillColorAleatory()) {
300
            
301
            the_color = brewerBasedColor();
302
            
303
        } else {
304
            // not random
305
            the_color = getSymbolPreferences().getDefaultSymbolFillColor();
306
        }
307
        symbol.setColor(the_color);
308
                // Perform this initialization into the Symbol implementation
309
                // if (symbol instanceof CartographicSupport) {
310
                // CartographicSupport cs = (CartographicSupport) symbol;
311
                // cs.setUnit(getDefaultCartographicSupportMeasureUnit());
312
                // cs
313
                // .setReferenceSystem(getDefaultCartographicSupportReferenceSystem();
314
                // }
315

    
316
                return symbol;
317
        }
318
        
319
        public void setSymbolPreferences(SymbolPreferences symbolPreferences) {
320
                this.symbolPreferences = symbolPreferences;
321
        }
322
        
323
        /**
324
         * 
325
         * @param col
326
         * @return color 1/3 closer to black
327
         */
328
        public static Color darker(Color col) {
329
            return new Color(
330
                (2 * col.getRed()) / 3,
331
                (2 * col.getGreen()) / 3,
332
                (2 * col.getBlue()) / 3,
333
                col.getAlpha());
334
        }
335

    
336
        /**
337
         * 
338
         * @param col
339
         * @return color 1/3 closer to white
340
         */
341
        public static Color lighter(Color col) {
342
            Color resp = invert(col);
343
            resp = darker(resp);
344
            return invert(resp);
345
        }
346
        
347
        /**
348
         * 
349
         * @param col
350
         * @return inverted color (inverts each band, same alpha)
351
         */
352
        public static Color invert(Color col) {
353
        return new Color(
354
            255 - col.getRed(),
355
            255 - col.getGreen(),
356
            255 - col.getBlue(),
357
            col.getAlpha());
358
        }
359
        
360
        private static Color brewerBasedColor() {
361
            
362
            int ind = rnd.nextInt(BREWER_COLOR.length);
363
            Color base = BREWER_COLOR[ind]; 
364
            ind = rnd.nextInt(100);
365
            if (ind > 66) {
366
                return darker(base);
367
            } else {
368
                if (ind > 33) {
369
                    return lighter(base);
370
                } else {
371
                    return base;
372
                }
373
            }
374
        }
375
        
376
    private static Color[] BREWER_COLOR = new Color[36];
377
    private static final Random rnd = new Random();
378
        
379
        static {
380
            /**
381
             * Colors from www.ColorBrewer.org by Cynthia A. Brewer,
382
             * Geography, Pennsylvania State University.
383
             *
384
             * Using groups of 4 colors from the 9 Diverging Schemes
385
             * 4 * 9 = 36 colors
386
             */
387
            BREWER_COLOR[0] = new Color(230, 97, 1);
388
            BREWER_COLOR[1] = new Color(253, 184, 99);
389
            BREWER_COLOR[2] = new Color(178, 171, 210);
390
            BREWER_COLOR[3] = new Color(94, 60, 153);
391
            BREWER_COLOR[4] = new Color(166, 97, 26);
392
            BREWER_COLOR[5] = new Color(223, 194, 125);
393
            BREWER_COLOR[6] = new Color(128, 205, 193);
394
            BREWER_COLOR[7] = new Color(1, 133, 113);
395
            BREWER_COLOR[8] = new Color(123, 50, 148);
396
            BREWER_COLOR[9] = new Color(194, 165, 207);
397
            BREWER_COLOR[10] = new Color(166, 219, 160);
398
            BREWER_COLOR[11] = new Color(0, 136, 55);
399
            BREWER_COLOR[12] = new Color(208, 28, 139);
400
            BREWER_COLOR[13] = new Color(241, 182, 218);
401
            BREWER_COLOR[14] = new Color(184, 225, 134);
402
            BREWER_COLOR[15] = new Color(77, 172, 38);
403
            BREWER_COLOR[16] = new Color(202, 0, 32);
404
            BREWER_COLOR[17] = new Color(244, 165, 130);
405
            BREWER_COLOR[18] = new Color(146, 197, 222);
406
            BREWER_COLOR[19] = new Color(5, 113, 176);
407
            BREWER_COLOR[20] = new Color(202, 0, 32);
408
            BREWER_COLOR[21] = new Color(244, 165, 130);
409
            BREWER_COLOR[22] = new Color(186, 186, 186);
410
            BREWER_COLOR[23] = new Color(64, 64, 64);
411
            BREWER_COLOR[24] = new Color(215, 25, 28);
412
            BREWER_COLOR[25] = new Color(253, 174, 97);
413
            BREWER_COLOR[26] = new Color(171, 217, 233);
414
            BREWER_COLOR[27] = new Color(44, 123, 182);
415
            BREWER_COLOR[28] = new Color(215, 25, 28);
416
            BREWER_COLOR[29] = new Color(253, 174, 97);
417
            BREWER_COLOR[30] = new Color(171, 221, 164);
418
            BREWER_COLOR[31] = new Color(43, 131, 186);
419
            BREWER_COLOR[32] = new Color(215, 25, 28);
420
            BREWER_COLOR[33] = new Color(253, 174, 97);
421
            BREWER_COLOR[34] = new Color(166, 217, 106);
422
            BREWER_COLOR[35] = new Color(26, 150, 65);
423
        }
424

    
425
        
426
}