Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.mapcontext / org.gvsig.fmap.mapcontext.api / src / main / java / org / gvsig / fmap / mapcontext / rendering / symbols / impl / DefaultSymbolManager.java @ 40559

History | View | Annotate | Download (14.2 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
/*
25
 * AUTHORS (In addition to CIT):
26
 * 2009 {DiSiD Technologies}  {{Task}}
27
 * 
28
 **************************************************************
29
 * Colors from www.ColorBrewer.org by Cynthia A. Brewer,
30
 * Geography, Pennsylvania State University.
31
 * Using groups of 4 colors from the 9 Diverging Schemes
32
 * 4 * 9 = 36 colors
33
 **************************************************************
34
 * 
35
 */
36
package org.gvsig.fmap.mapcontext.rendering.symbols.impl;
37

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

    
51
import org.gvsig.fmap.mapcontext.MapContextRuntimeException;
52
import org.gvsig.fmap.mapcontext.impl.InvalidRegisteredClassException;
53
import org.gvsig.fmap.mapcontext.impl.RegisteredClassInstantiationException;
54
import org.gvsig.fmap.mapcontext.rendering.symbols.IMultiLayerSymbol;
55
import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
56
import org.gvsig.fmap.mapcontext.rendering.symbols.IWarningSymbol;
57
import org.gvsig.fmap.mapcontext.rendering.symbols.SymbolException;
58
import org.gvsig.fmap.mapcontext.rendering.symbols.SymbolManager;
59
import org.gvsig.fmap.mapcontext.rendering.symbols.SymbolPreferences;
60
import org.gvsig.tools.ToolsLocator;
61
import org.gvsig.tools.persistence.PersistenceManager;
62
import org.gvsig.tools.persistence.PersistentState;
63
import org.gvsig.tools.persistence.exception.PersistenceException;
64
import org.gvsig.tools.task.SimpleTaskStatus;
65
import org.gvsig.tools.task.TaskStatusManager;
66

    
67
/**
68
 * Default {@link SymbolManager} implementation.
69
 * 
70
 * @author gvSIG team
71
 */
72
public class DefaultSymbolManager implements SymbolManager {
73

    
74
        private SymbolPreferences symbolPreferences =
75
                        new DefaultSymbolPreferences();
76

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

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

    
81
        private Map multiLineSymbolsByName =
82
                        Collections.synchronizedMap(new HashMap());
83

    
84
        private Map multiLineSymbolsByShapeType =
85
                        Collections.synchronizedMap(new HashMap());
86

    
87
        private IWarningSymbol warningSymbol;
88

    
89
        private Object warningSymbolLock = new Object();
90

    
91
        public ISymbol[] loadSymbols(File folder) throws SymbolException {
92
                return loadSymbols(folder, null);
93
        }
94

    
95
        public ISymbol[] loadSymbols(File folder, FileFilter fileFilter)
96
                        throws SymbolException {
97
                // TODO: add symbol caching
98

    
99
                if (folder.exists()) {
100

    
101
                        File[] symbolFiles = null;
102
                        if (fileFilter == null) {
103
                                symbolFiles = folder.listFiles();
104
                        } else {
105
                                symbolFiles = folder.listFiles(fileFilter);
106
                        }
107

    
108
                        if (symbolFiles != null) {
109
                            TaskStatusManager tm = ToolsLocator.getTaskStatusManager();
110
                            SimpleTaskStatus status = tm.createDefaultSimpleTaskStatus("Load symbols");
111
                            status.setRangeOfValues(0, symbolFiles.length);
112
                            status.setAutoremove(true);
113
                            status.add();
114

    
115
                            ISymbol[] symbols = null;
116
                            try {
117
                        symbols = new ISymbol[symbolFiles.length];
118
                        for (int i = 0; i < symbolFiles.length; i++) {
119
                            status.setCurValue(i);
120
                            symbols[i] = loadSymbol(symbolFiles[i]);
121
                            
122
                        }
123
                        status.message("sorting symbols");
124
                                        Arrays.sort(symbols, new Comparator() {
125
                                                public int compare( Object o1, Object o2) {
126
                                                        ISymbol s1 = (ISymbol)o1;
127
                                                        ISymbol s2 = (ISymbol)o2;
128
                                                        return s1.getDescription().compareTo(s2.getDescription());
129
                                                }
130
                                        });
131

    
132
                            } finally {
133
                                status.terminate();
134
                            }
135
                                return symbols;
136
                        }
137
                }
138

    
139
                return null;
140
        }
141

    
142
        public void saveSymbol(ISymbol symbol, String fileName, File folder)
143
                        throws SymbolException {
144
                saveSymbol(symbol, fileName, folder, false);
145
        }
146

    
147
        public void saveSymbol(ISymbol symbol, String fileName, File folder,
148
                        boolean overwrite) throws SymbolException {
149
                // TODO: add symbol caching
150

    
151
                PersistenceManager persistenceManager = ToolsLocator
152
                                .getPersistenceManager();
153

    
154
                File symbolFile = new File(folder, fileName);
155
                if (!overwrite && symbolFile.exists()) {
156
                        throw new SymbolFileAlreadyExistsException(symbolFile);
157
                }
158

    
159
                try {
160
                        FileOutputStream fos = new FileOutputStream(symbolFile);
161

    
162
                        persistenceManager.saveState(persistenceManager.getState(symbol),
163
                                        fos);
164

    
165
                        fos.flush();
166
                        fos.close();
167
                } catch (PersistenceException e) {
168
                        throw new SaveSymbolException(e);
169
                } catch (IOException e) {
170
                        throw new SaveSymbolException(e);
171
                }
172
        }
173

    
174
        /**
175
         * Loads a persisted symbol from the given file.
176
         */
177
        private ISymbol loadSymbol(File file) throws SymbolException {
178
                if (file.exists()) {
179
                        try {
180
                                FileInputStream fis = new FileInputStream(file);
181

    
182
                                PersistenceManager persistenceManager = ToolsLocator
183
                                                .getPersistenceManager();
184

    
185
                                PersistentState state = persistenceManager.loadState(fis);
186
                                ISymbol symbol = (ISymbol) persistenceManager.create(state);
187

    
188
                                fis.close();
189
                                return symbol;
190
                        } catch (PersistenceException e) {
191
                                throw new LoadSymbolException(e);
192
                        } catch (IOException e) {
193
                                throw new LoadSymbolException(e);
194
                        }
195
                }
196

    
197
                return null;
198
        }
199

    
200
        public SymbolPreferences getSymbolPreferences() {
201
                return symbolPreferences;
202
        }
203

    
204
        public ISymbol createSymbol(String symbolName)
205
                        throws MapContextRuntimeException {
206
                return createSymbol(symbolName, (Class) symbolsByName.get(symbolName),
207
                                ISymbol.class);
208
        }
209

    
210
        public ISymbol createSymbol(int shapeType)
211
                        throws MapContextRuntimeException {
212
                String symbolName =
213
                                (String) symbolsByShapeType.get(new Integer(shapeType));
214

    
215
                return symbolName == null ? null : createSymbol(symbolName);
216
        }
217

    
218
        public ISymbol createSymbol(String symbolName, Color color)
219
                        throws MapContextRuntimeException {
220
                ISymbol symbol = createSymbol(symbolName);
221

    
222
                if (symbol != null) {
223
                        symbol.setColor(color);
224
                }
225

    
226
                return symbol;
227
        }
228

    
229
        public ISymbol createSymbol(int shapeType, Color color)
230
                        throws MapContextRuntimeException {
231
                String symbolName =
232
                                (String) symbolsByShapeType.get(new Integer(shapeType));
233

    
234
                return symbolName == null ? null : createSymbol(symbolName, color);
235
        }
236

    
237
        public IMultiLayerSymbol createMultiLayerSymbol(String symbolName)
238
                        throws MapContextRuntimeException {
239
                return (IMultiLayerSymbol) createSymbol(symbolName,
240
                                (Class) multiLineSymbolsByName.get(symbolName),
241
                                IMultiLayerSymbol.class);
242
        }
243

    
244
        public IMultiLayerSymbol createMultiLayerSymbol(int shapeType)
245
                        throws MapContextRuntimeException {
246
                String symbolName =
247
                                (String) multiLineSymbolsByShapeType.get(new Integer(shapeType));
248

    
249
                return symbolName == null ? null : createMultiLayerSymbol(symbolName);
250
        }
251

    
252
        public void registerSymbol(String symbolName, Class symbolClass)
253
                        throws MapContextRuntimeException {
254
                if (symbolClass == null || !ISymbol.class.isAssignableFrom(symbolClass)) {
255
                        throw new InvalidRegisteredClassException(ISymbol.class,
256
                                        symbolClass, symbolName);
257
                }
258
                symbolsByName.put(symbolName, symbolClass);
259
        }
260

    
261
        public void registerSymbol(String symbolName, int[] shapeTypes,
262
                        Class symbolClass) throws MapContextRuntimeException {
263
                registerSymbol(symbolName, symbolClass);
264
                if (shapeTypes != null) {
265
                        for (int i = 0; i < shapeTypes.length; i++) {
266
                                symbolsByShapeType.put(new Integer(shapeTypes[i]), symbolName);
267
                        }
268
                }
269
        }
270

    
271
        public void registerMultiLayerSymbol(String symbolName, Class symbolClass)
272
                        throws MapContextRuntimeException {
273
                if (symbolClass == null
274
                                || !IMultiLayerSymbol.class.isAssignableFrom(symbolClass)) {
275
                        throw new InvalidRegisteredClassException(IMultiLayerSymbol.class,
276
                                        symbolClass, symbolName);
277
                }
278

    
279
                multiLineSymbolsByName.put(symbolName, symbolClass);
280
        }
281

    
282
        public void registerMultiLayerSymbol(String symbolName, int[] shapeTypes,
283
                        Class symbolClass) throws MapContextRuntimeException {
284
                registerMultiLayerSymbol(symbolName, symbolClass);
285
                if (shapeTypes != null) {
286
                        for (int i = 0; i < shapeTypes.length; i++) {
287
                                multiLineSymbolsByShapeType.put(new Integer(shapeTypes[i]),
288
                                                symbolName);
289
                        }
290
                }
291
        }
292

    
293
        public IWarningSymbol getWarningSymbol(String message, String symbolDesc,
294
                        int symbolDrawExceptionType) throws MapContextRuntimeException {
295
                synchronized (warningSymbolLock) {
296
                        if (warningSymbol == null) {
297
                                warningSymbol = (IWarningSymbol) createSymbol("warning");
298
                        }
299
                }
300

    
301
                // TODO: set those values as parameter values in the draw method.
302
                warningSymbol.setDescription(symbolDesc);
303
                warningSymbol.setMessage(message);
304
                warningSymbol.setDrawExceptionType(symbolDrawExceptionType);
305

    
306
                return warningSymbol;
307
        }
308

    
309
        private ISymbol createSymbol(String symbolName, Class symbolClass,
310
                        Class expectedType) throws MapContextRuntimeException {
311
                ISymbol symbol;
312
                try {
313
                        symbol =
314
                                        (ISymbol) (symbolClass == null ? null
315
                                                        : symbolClass.newInstance());
316
                } catch (InstantiationException e) {
317
                        throw new RegisteredClassInstantiationException(expectedType,
318
                                        symbolClass, symbolName, e);
319
                } catch (IllegalAccessException e) {
320
                        throw new RegisteredClassInstantiationException(expectedType,
321
                                        symbolClass, symbolName, e);
322
                }
323

    
324
                Color the_color = null;
325
                
326
        if (getSymbolPreferences().isDefaultSymbolFillColorAleatory()) {
327
            
328
            the_color = getRandomBrewerBasedColor();
329
            
330
        } else {
331
            // not random
332
            the_color = getSymbolPreferences().getDefaultSymbolFillColor();
333
        }
334
        symbol.setColor(the_color);
335
                // Perform this initialization into the Symbol implementation
336
                // if (symbol instanceof CartographicSupport) {
337
                // CartographicSupport cs = (CartographicSupport) symbol;
338
                // cs.setUnit(getDefaultCartographicSupportMeasureUnit());
339
                // cs
340
                // .setReferenceSystem(getDefaultCartographicSupportReferenceSystem();
341
                // }
342

    
343
                return symbol;
344
        }
345
        
346
        public void setSymbolPreferences(SymbolPreferences symbolPreferences) {
347
                this.symbolPreferences = symbolPreferences;
348
        }
349
        
350
        /**
351
         * 
352
         * @param col
353
         * @return color 1/3 closer to black
354
         */
355
        public static Color darker(Color col) {
356
            return new Color(
357
                (2 * col.getRed()) / 3,
358
                (2 * col.getGreen()) / 3,
359
                (2 * col.getBlue()) / 3,
360
                col.getAlpha());
361
        }
362

    
363
        /**
364
         * 
365
         * @param col
366
         * @return color 1/3 closer to white
367
         */
368
        public static Color lighter(Color col) {
369
            Color resp = invert(col);
370
            resp = darker(resp);
371
            return invert(resp);
372
        }
373
        
374
        /**
375
         * 
376
         * @param col
377
         * @return inverted color (inverts each band, same alpha)
378
         */
379
        public static Color invert(Color col) {
380
        return new Color(
381
            255 - col.getRed(),
382
            255 - col.getGreen(),
383
            255 - col.getBlue(),
384
            col.getAlpha());
385
        }
386
        
387
        private static Color getRandomBrewerBasedColor() {
388
            
389
            int ind = rnd.nextInt(BREWER_COLOR.length);
390
            Color resp = BREWER_COLOR[ind]; 
391
            ind = rnd.nextInt(100);
392
            if (ind > 66) {
393
                resp = darker(resp);
394
            } else {
395
                if (ind > 33) {
396
                    resp = lighter(resp);
397
                }
398
                // ...else resp remains the same
399
            }
400
            
401
            // finally add some dark noise 
402
            resp = addDarkNoise(resp);
403
            return resp;
404
        }
405
        
406
    private static Color addDarkNoise(Color c) {
407
        int r = Math.max(0, c.getRed() - rnd.nextInt(30));
408
        int g = Math.max(0, c.getGreen() - rnd.nextInt(30));
409
        int b = Math.max(0, c.getBlue() - rnd.nextInt(30));
410
        return new Color(r, g, b, c.getAlpha());
411
    }
412

    
413
    private static Color[] BREWER_COLOR = new Color[36];
414
    private static final Random rnd = new Random();
415
        
416
        static {
417
            /**
418
             * Colors from www.ColorBrewer.org by Cynthia A. Brewer,
419
             * Geography, Pennsylvania State University.
420
             *
421
             * Using groups of 4 colors from the 9 Diverging Schemes
422
             * 4 * 9 = 36 colors
423
             */
424
            BREWER_COLOR[0] = new Color(230, 97, 1);
425
            BREWER_COLOR[1] = new Color(253, 184, 99);
426
            BREWER_COLOR[2] = new Color(178, 171, 210);
427
            BREWER_COLOR[3] = new Color(94, 60, 153);
428
            BREWER_COLOR[4] = new Color(166, 97, 26);
429
            BREWER_COLOR[5] = new Color(223, 194, 125);
430
            BREWER_COLOR[6] = new Color(128, 205, 193);
431
            BREWER_COLOR[7] = new Color(1, 133, 113);
432
            BREWER_COLOR[8] = new Color(123, 50, 148);
433
            BREWER_COLOR[9] = new Color(194, 165, 207);
434
            BREWER_COLOR[10] = new Color(166, 219, 160);
435
            BREWER_COLOR[11] = new Color(0, 136, 55);
436
            BREWER_COLOR[12] = new Color(208, 28, 139);
437
            BREWER_COLOR[13] = new Color(241, 182, 218);
438
            BREWER_COLOR[14] = new Color(184, 225, 134);
439
            BREWER_COLOR[15] = new Color(77, 172, 38);
440
            BREWER_COLOR[16] = new Color(202, 0, 32);
441
            BREWER_COLOR[17] = new Color(244, 165, 130);
442
            BREWER_COLOR[18] = new Color(146, 197, 222);
443
            BREWER_COLOR[19] = new Color(5, 113, 176);
444
            BREWER_COLOR[20] = new Color(202, 0, 32);
445
            BREWER_COLOR[21] = new Color(244, 165, 130);
446
            BREWER_COLOR[22] = new Color(186, 186, 186);
447
            BREWER_COLOR[23] = new Color(64, 64, 64);
448
            BREWER_COLOR[24] = new Color(215, 25, 28);
449
            BREWER_COLOR[25] = new Color(253, 174, 97);
450
            BREWER_COLOR[26] = new Color(171, 217, 233);
451
            BREWER_COLOR[27] = new Color(44, 123, 182);
452
            BREWER_COLOR[28] = new Color(215, 25, 28);
453
            BREWER_COLOR[29] = new Color(253, 174, 97);
454
            BREWER_COLOR[30] = new Color(171, 221, 164);
455
            BREWER_COLOR[31] = new Color(43, 131, 186);
456
            BREWER_COLOR[32] = new Color(215, 25, 28);
457
            BREWER_COLOR[33] = new Color(253, 174, 97);
458
            BREWER_COLOR[34] = new Color(166, 217, 106);
459
            BREWER_COLOR[35] = new Color(26, 150, 65);
460
        }
461

    
462
        
463
}