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 30838 cordinyana
/* gvSIG. Geographic Information System of the Valencian Government
2
 *
3
 * Copyright (C) 2007-2008 Infrastructures and Transports Department
4 31544 cordinyana
 * of the Valencian Government (CIT)
5 30838 cordinyana
 *
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 38551 jldominguez
 *
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 30838 cordinyana
 */
35
package org.gvsig.fmap.mapcontext.rendering.symbols.impl;
36
37 30892 cordinyana
import java.awt.Color;
38 30838 cordinyana
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 30892 cordinyana
import java.util.Collections;
44
import java.util.HashMap;
45
import java.util.Map;
46 36666 cordinyana
import java.util.Random;
47 30838 cordinyana
48 30892 cordinyana
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 30838 cordinyana
import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
53 30892 cordinyana
import org.gvsig.fmap.mapcontext.rendering.symbols.IWarningSymbol;
54 30838 cordinyana
import org.gvsig.fmap.mapcontext.rendering.symbols.SymbolException;
55
import org.gvsig.fmap.mapcontext.rendering.symbols.SymbolManager;
56 30892 cordinyana
import org.gvsig.fmap.mapcontext.rendering.symbols.SymbolPreferences;
57 30838 cordinyana
import org.gvsig.tools.ToolsLocator;
58
import org.gvsig.tools.persistence.PersistenceManager;
59
import org.gvsig.tools.persistence.PersistentState;
60 32880 jjdelcerro
import org.gvsig.tools.persistence.exception.PersistenceException;
61 30838 cordinyana
62
/**
63
 * Default {@link SymbolManager} implementation.
64
 *
65
 * @author gvSIG team
66
 */
67
public class DefaultSymbolManager implements SymbolManager {
68
69 30892 cordinyana
        private SymbolPreferences symbolPreferences =
70
                        new DefaultSymbolPreferences();
71 30838 cordinyana
72 30892 cordinyana
        private Map symbolsByName = Collections.synchronizedMap(new HashMap());
73 30838 cordinyana
74 30892 cordinyana
        private Map symbolsByShapeType = Collections.synchronizedMap(new HashMap());
75 30838 cordinyana
76 30892 cordinyana
        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 30838 cordinyana
        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 30892 cordinyana
        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 38551 jldominguez
                Color the_color = null;
298
299 36666 cordinyana
        if (getSymbolPreferences().isDefaultSymbolFillColorAleatory()) {
300 38551 jldominguez
301
            the_color = brewerBasedColor();
302
303
        } else {
304
            // not random
305
            the_color = getSymbolPreferences().getDefaultSymbolFillColor();
306 36666 cordinyana
        }
307 38551 jldominguez
        symbol.setColor(the_color);
308 30892 cordinyana
                // 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 38442 nbrodin
319
        public void setSymbolPreferences(SymbolPreferences symbolPreferences) {
320
                this.symbolPreferences = symbolPreferences;
321
        }
322 38551 jldominguez
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 30838 cordinyana
}