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 @ 42352

History | View | Annotate | Download (24.7 KB)

1 40559 jjdelcerro
/**
2
 * gvSIG. Desktop Geographic Information System.
3 40435 jjdelcerro
 *
4 40559 jjdelcerro
 * Copyright (C) 2007-2013 gvSIG Association.
5
 *
6 41397 jjdelcerro
 * This program is free software; you can redistribute it and/or modify it under
7
 * the terms of the GNU General Public License as published by the Free Software
8
 * Foundation; either version 3 of the License, or (at your option) any later
9
 * version.
10 40559 jjdelcerro
 *
11 41397 jjdelcerro
 * This program is distributed in the hope that it will be useful, but WITHOUT
12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14
 * details.
15 40559 jjdelcerro
 *
16 41397 jjdelcerro
 * You should have received a copy of the GNU General Public License along with
17
 * this program; if not, write to the Free Software Foundation, Inc., 51
18
 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 40559 jjdelcerro
 *
20 41397 jjdelcerro
 * For any additional information, do not hesitate to contact us at info AT
21
 * gvsig.com, or visit our website www.gvsig.com.
22 40435 jjdelcerro
 */
23 42023 jjdelcerro
package org.gvsig.fmap.mapcontext.rendering.symbols.impl;
24
25 40435 jjdelcerro
/*
26 42023 jjdelcerro
 * Based on portions of code from www.ColorBrewer.org
27
 *
28 40435 jjdelcerro
 * 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 42023 jjdelcerro
35 40435 jjdelcerro
import java.awt.Color;
36
import java.io.File;
37
import java.io.FileFilter;
38
import java.io.FileInputStream;
39
import java.io.FileOutputStream;
40
import java.io.IOException;
41 41397 jjdelcerro
import java.util.ArrayList;
42 40435 jjdelcerro
import java.util.Arrays;
43 41397 jjdelcerro
import java.util.Collection;
44 40435 jjdelcerro
import java.util.Collections;
45
import java.util.Comparator;
46
import java.util.HashMap;
47 42352 fdiaz
import java.util.Iterator;
48 41397 jjdelcerro
import java.util.List;
49 40435 jjdelcerro
import java.util.Map;
50
import java.util.Random;
51 42352 fdiaz
52 41397 jjdelcerro
import org.apache.commons.io.FileUtils;
53
import org.apache.commons.io.FilenameUtils;
54
import org.apache.commons.io.filefilter.FileFilterUtils;
55
import org.apache.commons.lang3.StringUtils;
56 42352 fdiaz
import org.slf4j.Logger;
57
import org.slf4j.LoggerFactory;
58
59
import org.gvsig.fmap.geom.Geometry;
60
import org.gvsig.fmap.geom.GeometryLocator;
61
import org.gvsig.fmap.geom.GeometryManager;
62
import org.gvsig.fmap.geom.type.GeometryType;
63
import org.gvsig.fmap.geom.type.GeometryTypeNotSupportedException;
64
import org.gvsig.fmap.geom.type.GeometryTypeNotValidException;
65 40435 jjdelcerro
import org.gvsig.fmap.mapcontext.MapContextRuntimeException;
66
import org.gvsig.fmap.mapcontext.impl.InvalidRegisteredClassException;
67
import org.gvsig.fmap.mapcontext.impl.RegisteredClassInstantiationException;
68
import org.gvsig.fmap.mapcontext.rendering.symbols.IMultiLayerSymbol;
69
import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
70 41397 jjdelcerro
import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol_v2;
71 40435 jjdelcerro
import org.gvsig.fmap.mapcontext.rendering.symbols.IWarningSymbol;
72
import org.gvsig.fmap.mapcontext.rendering.symbols.SymbolException;
73
import org.gvsig.fmap.mapcontext.rendering.symbols.SymbolManager;
74
import org.gvsig.fmap.mapcontext.rendering.symbols.SymbolPreferences;
75
import org.gvsig.tools.ToolsLocator;
76 40970 jjdelcerro
import org.gvsig.tools.exception.BaseException;
77 40435 jjdelcerro
import org.gvsig.tools.persistence.PersistenceManager;
78
import org.gvsig.tools.persistence.PersistentState;
79
import org.gvsig.tools.persistence.exception.PersistenceException;
80 40970 jjdelcerro
import org.gvsig.tools.task.AbstractMonitorableTask;
81 41046 jjdelcerro
import org.gvsig.tools.task.CancellableTask;
82 40435 jjdelcerro
import org.gvsig.tools.task.SimpleTaskStatus;
83
import org.gvsig.tools.task.TaskStatusManager;
84 40970 jjdelcerro
import org.gvsig.tools.visitor.VisitCanceledException;
85
import org.gvsig.tools.visitor.Visitor;
86 40435 jjdelcerro
87
/**
88
 * Default {@link SymbolManager} implementation.
89 41397 jjdelcerro
 *
90 40435 jjdelcerro
 * @author gvSIG team
91
 */
92
public class DefaultSymbolManager implements SymbolManager {
93
94 41397 jjdelcerro
    private static final Logger logger = LoggerFactory.getLogger(DefaultSymbolManager.class);
95 40435 jjdelcerro
96 41397 jjdelcerro
    private SymbolPreferences symbolPreferences
97
            = new DefaultSymbolPreferences();
98 40435 jjdelcerro
99 41397 jjdelcerro
    private Map symbolsByName = Collections.synchronizedMap(new HashMap());
100 40435 jjdelcerro
101 41397 jjdelcerro
    private Map symbolsByShapeType = Collections.synchronizedMap(new HashMap());
102 40435 jjdelcerro
103 41397 jjdelcerro
    private Map multiLineSymbolsByName
104
            = Collections.synchronizedMap(new HashMap());
105 40435 jjdelcerro
106 41397 jjdelcerro
    private Map multiLineSymbolsByShapeType
107
            = Collections.synchronizedMap(new HashMap());
108 40435 jjdelcerro
109 41397 jjdelcerro
    private IWarningSymbol warningSymbol;
110 40435 jjdelcerro
111 41397 jjdelcerro
    private Object warningSymbolLock = new Object();
112 40435 jjdelcerro
113 41397 jjdelcerro
    public ISymbol[] loadSymbols(File folder) throws SymbolException {
114
        return loadSymbols(folder, null);
115
    }
116 40435 jjdelcerro
117 41397 jjdelcerro
    public ISymbol[] loadSymbols(File folder, FileFilter fileFilter)
118
            throws SymbolException {
119
        // TODO: add symbol caching
120 40435 jjdelcerro
121 41397 jjdelcerro
        if (folder.exists()) {
122 40435 jjdelcerro
123 41397 jjdelcerro
            File[] symbolFiles = null;
124
            if (fileFilter == null) {
125
                symbolFiles = folder.listFiles();
126
            } else {
127
                symbolFiles = folder.listFiles(fileFilter);
128
            }
129
130
            if (symbolFiles != null) {
131
                TaskStatusManager tm = ToolsLocator.getTaskStatusManager();
132
                SimpleTaskStatus status = tm.createDefaultSimpleTaskStatus("Load symbols");
133
                status.setRangeOfValues(0, symbolFiles.length);
134
                status.setAutoremove(true);
135
                status.add();
136
137
                /*
138
                 * Sorting by file name before loading.
139
                 * The problem here is that some
140
                 * descriptions can be empty, so sorting using description
141
                 * can have strange behavior. Sorting by file name is not
142
                 * very elegant, though.
143
                 */
144 40611 jldominguez
                status.message("sorting symbols");
145 41397 jjdelcerro
                Arrays.sort(symbolFiles, new Comparator() {
146
                    public int compare(Object o1, Object o2) {
147
                        File f1 = (File) o1;
148
                        File f2 = (File) o2;
149
                        return f1.getName().compareTo(f2.getName());
150
                    }
151
                });
152 40435 jjdelcerro
153 41397 jjdelcerro
                ISymbol[] symbols = null;
154
                try {
155
                    symbols = new ISymbol[symbolFiles.length];
156
                    for (int i = 0; i < symbolFiles.length; i++) {
157
                        status.setCurValue(i);
158 41550 jjdelcerro
                        File symbolFile = symbolFiles[i];
159
                        try {
160
                            symbols[i] = loadSymbol(symbolFile);
161
                        } catch(Throwable th) {
162
                            logger.warn("Can't load symbol '"+symbolFile.getAbsolutePath()+"'.",th);
163
                        }
164 41397 jjdelcerro
                    }
165 40435 jjdelcerro
166 41397 jjdelcerro
                } finally {
167
                    status.terminate();
168
                }
169
                return symbols;
170
            }
171
        }
172 40435 jjdelcerro
173 41397 jjdelcerro
        return null;
174
    }
175 40970 jjdelcerro
176 41397 jjdelcerro
    public class SymbolsLoaderTask extends AbstractMonitorableTask {
177 40970 jjdelcerro
178 41397 jjdelcerro
        private File folder;
179
        private FileFilter filter;
180
        private Visitor visitor;
181 40970 jjdelcerro
182 41397 jjdelcerro
        public SymbolsLoaderTask(File folder, FileFilter filter, Visitor visitor) {
183
            super("Load symbols", true);
184
            this.folder = folder;
185
            this.filter = filter;
186
            this.visitor = visitor;
187
            if (folder == null) {
188
                throw new IllegalArgumentException("folder is null");
189
            }
190
            if (visitor == null) {
191
                throw new IllegalArgumentException("visitor is null");
192
            }
193
        }
194 40970 jjdelcerro
195 41397 jjdelcerro
        private File[] getFiles() {
196
            if (filter == null) {
197
                return folder.listFiles();
198
            } else {
199
                return folder.listFiles(filter);
200
            }
201
        }
202 40970 jjdelcerro
203 41397 jjdelcerro
        private String getVisitorName() {
204
            String s = visitor.toString() + "/" + visitor.getClass().getName();
205
            return s;
206
        }
207 40970 jjdelcerro
208 41397 jjdelcerro
        private void visit(final File file, final ISymbol symbol) throws VisitCanceledException {
209
            try {
210
                visitor.visit(symbol);
211
            } catch (BaseException e) {
212
                logger.warn("Can't call visit '" + getVisitorName() + "' to offer the symbol '" + file.getAbsolutePath() + "'.", e);
213
            }
214
        }
215 40970 jjdelcerro
216 41397 jjdelcerro
        public void run() {
217
            // TODO: add symbol caching
218
            try {
219
                logger.info("[SymbolsLoaderTask" + this.getId() + "] process initited.");
220
                if (folder.exists()) {
221
                    taskStatus.setAutoremove(true);
222
                    taskStatus.message("preparing");
223
                    File[] symbolFiles = getFiles();
224 40970 jjdelcerro
225 41397 jjdelcerro
                    if (symbolFiles != null) {
226
                        taskStatus.setRangeOfValues(0, symbolFiles.length);
227 40970 jjdelcerro
228 41397 jjdelcerro
                        /*
229
                         * Sorting by file name before loading. The problem here
230
                         * is that some descriptions can be empty, so sorting
231
                         * using description can have strange behavior. Sorting
232
                         * by file name is not very elegant, though.
233
                         */
234
                        taskStatus.message("sorting");
235
                        Arrays.sort(symbolFiles, new Comparator() {
236
                            public int compare(Object o1, Object o2) {
237
                                File f1 = (File) o1;
238
                                File f2 = (File) o2;
239
                                return f1.getName().compareTo(f2.getName());
240
                            }
241
                        });
242 40435 jjdelcerro
243 41397 jjdelcerro
                        taskStatus.message("loading");
244
                        for (int i = 0; i < symbolFiles.length; i++) {
245
                            taskStatus.setCurValue(i);
246
                            if (taskStatus.isCancellationRequested()) {
247
                                logger.info("[SymbolsLoaderTask" + this.getId() + "] process canceled.");
248
                                break;
249
                            }
250
                            ISymbol symbol = null;
251
                            try {
252
                                symbol = loadSymbol(symbolFiles[i]);
253
                                visit(symbolFiles[i], symbol);
254
                            } catch (VisitCanceledException e) {
255
                                break;
256 41550 jjdelcerro
                            } catch (Throwable e) {
257 41397 jjdelcerro
                                logger.warn("Can't load symbol '"
258
                                        + symbolFiles[i].getAbsolutePath()
259
                                        + "'.", e);
260
                            }
261
                        }
262
                        taskStatus.message("");
263 40435 jjdelcerro
264 41397 jjdelcerro
                    }
265
                }
266 40435 jjdelcerro
267 41397 jjdelcerro
            } finally {
268
                taskStatus.terminate();
269
            }
270
            logger.info("[SymbolsLoaderTask" + this.getId() + "] process terminated.");
271 40435 jjdelcerro
272 41397 jjdelcerro
        }
273
    }
274 40435 jjdelcerro
275 41397 jjdelcerro
    public CancellableTask loadSymbols(File folder, FileFilter filter, Visitor visitor) {
276
        SymbolsLoaderTask task = new SymbolsLoaderTask(folder, filter, visitor);
277
        task.start();
278
        return task;
279
    }
280 40435 jjdelcerro
281 41397 jjdelcerro
    public void saveSymbol(ISymbol symbol, String fileName, File folder)
282
            throws SymbolException {
283
        saveSymbol(symbol, fileName, folder, false);
284 40435 jjdelcerro
285 41397 jjdelcerro
    }
286 40435 jjdelcerro
287 41397 jjdelcerro
    public void saveSymbol(ISymbol symbol, String fileName, File folder,
288
            boolean overwrite) throws SymbolException {
289
        // TODO: add symbol caching
290 40435 jjdelcerro
291 41397 jjdelcerro
        PersistenceManager persistenceManager = ToolsLocator
292
                .getPersistenceManager();
293 40435 jjdelcerro
294 41397 jjdelcerro
        File symbolFile = new File(folder, fileName);
295
        if (!overwrite && symbolFile.exists()) {
296
            throw new SymbolFileAlreadyExistsException(symbolFile);
297
        }
298 40435 jjdelcerro
299 41397 jjdelcerro
        try {
300
            FileOutputStream fos = new FileOutputStream(symbolFile);
301 40435 jjdelcerro
302 41397 jjdelcerro
            persistenceManager.saveState(persistenceManager.getState(symbol),
303
                    fos);
304 40435 jjdelcerro
305 41397 jjdelcerro
            fos.flush();
306
            fos.close();
307
        } catch (PersistenceException e) {
308
            throw new SaveSymbolException(e);
309
        } catch (IOException e) {
310
            throw new SaveSymbolException(e);
311
        }
312
        if (symbol instanceof ISymbol_v2) {
313
            ISymbol_v2 symbolv2 = (ISymbol_v2) symbol;
314
            if (StringUtils.isBlank(symbolv2.getID())) {
315
                symbolv2.setID(FilenameUtils.getBaseName(fileName));
316
            }
317
        }
318
    }
319 40435 jjdelcerro
320 41397 jjdelcerro
    /**
321
     * Loads a persisted symbol from the given file.
322
     */
323
    private ISymbol loadSymbol(File file) throws SymbolException {
324
        if (file.exists()) {
325
            try {
326
                FileInputStream fis = new FileInputStream(file);
327 40435 jjdelcerro
328 41397 jjdelcerro
                PersistenceManager persistenceManager = ToolsLocator
329
                        .getPersistenceManager();
330 40435 jjdelcerro
331 41397 jjdelcerro
                PersistentState state = persistenceManager.loadState(fis);
332
                ISymbol symbol = (ISymbol) persistenceManager.create(state);
333 40435 jjdelcerro
334 41397 jjdelcerro
                fis.close();
335
                if (symbol instanceof ISymbol_v2) {
336
                    ISymbol_v2 symbolv2 = (ISymbol_v2) symbol;
337
                    symbolv2.setID(FilenameUtils.getBaseName(file.getName()));
338
                }
339
                return symbol;
340
            } catch (PersistenceException e) {
341
                throw new LoadSymbolException(e);
342
            } catch (IOException e) {
343
                throw new LoadSymbolException(e);
344
            }
345
        }
346 40435 jjdelcerro
347 41397 jjdelcerro
        return null;
348
    }
349 40435 jjdelcerro
350 41397 jjdelcerro
    public SymbolPreferences getSymbolPreferences() {
351
        return symbolPreferences;
352
    }
353 40435 jjdelcerro
354 41397 jjdelcerro
    public ISymbol createSymbol(String symbolName)
355
            throws MapContextRuntimeException {
356
        return createSymbol(symbolName, (Class) symbolsByName.get(symbolName),
357
                ISymbol.class);
358
    }
359 40435 jjdelcerro
360 41397 jjdelcerro
    public ISymbol createSymbol(int shapeType)
361
            throws MapContextRuntimeException {
362 42352 fdiaz
        String symbolName = getSymbolName(symbolsByShapeType, shapeType);
363 40435 jjdelcerro
364 41397 jjdelcerro
        return symbolName == null ? null : createSymbol(symbolName);
365
    }
366 40435 jjdelcerro
367 41397 jjdelcerro
    public ISymbol createSymbol(String symbolName, Color color)
368
            throws MapContextRuntimeException {
369
        ISymbol symbol = createSymbol(symbolName);
370 40435 jjdelcerro
371 41397 jjdelcerro
        if (symbol != null) {
372
            symbol.setColor(color);
373
        }
374 40435 jjdelcerro
375 41397 jjdelcerro
        return symbol;
376
    }
377 40435 jjdelcerro
378 41397 jjdelcerro
    public ISymbol createSymbol(int shapeType, Color color)
379
            throws MapContextRuntimeException {
380 42352 fdiaz
        String symbolName = getSymbolName(symbolsByShapeType, shapeType);
381 40435 jjdelcerro
382 41397 jjdelcerro
        return symbolName == null ? null : createSymbol(symbolName, color);
383
    }
384 40435 jjdelcerro
385 41397 jjdelcerro
    public IMultiLayerSymbol createMultiLayerSymbol(String symbolName)
386
            throws MapContextRuntimeException {
387
        return (IMultiLayerSymbol) createSymbol(symbolName,
388
                (Class) multiLineSymbolsByName.get(symbolName),
389
                IMultiLayerSymbol.class);
390
    }
391 40435 jjdelcerro
392 41397 jjdelcerro
    public IMultiLayerSymbol createMultiLayerSymbol(int shapeType)
393
            throws MapContextRuntimeException {
394 42352 fdiaz
        String symbolName = getSymbolName(multiLineSymbolsByShapeType, shapeType);
395 40435 jjdelcerro
396 41397 jjdelcerro
        return symbolName == null ? null : createMultiLayerSymbol(symbolName);
397
    }
398 40435 jjdelcerro
399 42352 fdiaz
    /**
400
     * @param shapeType
401
     * @return
402
     */
403
    private String getSymbolName(Map symbols, int shapeType) {
404
        String symbolName
405
                = (String) symbols.get(new Integer(shapeType));
406
        if (symbolName == null) {
407
            GeometryManager geomManager = GeometryLocator.getGeometryManager();
408
            GeometryType shapeGeometryType;
409
            try {
410
                shapeGeometryType = geomManager.getGeometryType(shapeType, Geometry.SUBTYPES.UNKNOWN);
411
                Iterator it = symbols.keySet().iterator();
412
                while (it.hasNext()) {
413
                    Integer geomType = (Integer) it.next();
414
                    GeometryType geomGeometryType =
415
                        geomManager.getGeometryType(geomType.intValue(), Geometry.SUBTYPES.UNKNOWN);
416
                    if (shapeGeometryType.isSubTypeOf(geomGeometryType)) {
417
                        symbolName = (String) symbols.get(geomType);
418
                        break;
419
                    }
420
                }
421
            } catch (GeometryTypeNotSupportedException e) {
422
                // do nothing
423
            } catch (GeometryTypeNotValidException e) {
424
                // do nothing
425
            }
426
        }
427
        return symbolName;
428
    }
429
430 41397 jjdelcerro
    public void registerSymbol(String symbolName, Class symbolClass)
431
            throws MapContextRuntimeException {
432
        if (symbolClass == null || !ISymbol.class.isAssignableFrom(symbolClass)) {
433
            throw new InvalidRegisteredClassException(ISymbol.class,
434
                    symbolClass, symbolName);
435
        }
436
        symbolsByName.put(symbolName, symbolClass);
437
    }
438 40435 jjdelcerro
439 41397 jjdelcerro
    public void registerSymbol(String symbolName, int[] shapeTypes,
440
            Class symbolClass) throws MapContextRuntimeException {
441
        registerSymbol(symbolName, symbolClass);
442
        if (shapeTypes != null) {
443
            for (int i = 0; i < shapeTypes.length; i++) {
444
                symbolsByShapeType.put(new Integer(shapeTypes[i]), symbolName);
445
            }
446
        }
447
    }
448 40435 jjdelcerro
449 41397 jjdelcerro
    public void registerMultiLayerSymbol(String symbolName, Class symbolClass)
450
            throws MapContextRuntimeException {
451
        if (symbolClass == null
452
                || !IMultiLayerSymbol.class.isAssignableFrom(symbolClass)) {
453
            throw new InvalidRegisteredClassException(IMultiLayerSymbol.class,
454
                    symbolClass, symbolName);
455
        }
456
457
        multiLineSymbolsByName.put(symbolName, symbolClass);
458
    }
459
460
    public void registerMultiLayerSymbol(String symbolName, int[] shapeTypes,
461
            Class symbolClass) throws MapContextRuntimeException {
462
        registerMultiLayerSymbol(symbolName, symbolClass);
463
        if (shapeTypes != null) {
464
            for (int i = 0; i < shapeTypes.length; i++) {
465
                multiLineSymbolsByShapeType.put(new Integer(shapeTypes[i]),
466
                        symbolName);
467
            }
468
        }
469
    }
470
471
    public IWarningSymbol getWarningSymbol(String message, String symbolDesc,
472
            int symbolDrawExceptionType) throws MapContextRuntimeException {
473
        synchronized (warningSymbolLock) {
474
            if (warningSymbol == null) {
475
                warningSymbol = (IWarningSymbol) createSymbol("warning");
476
            }
477
        }
478
479
        // TODO: set those values as parameter values in the draw method.
480
        warningSymbol.setDescription(symbolDesc);
481
        warningSymbol.setMessage(message);
482
        warningSymbol.setDrawExceptionType(symbolDrawExceptionType);
483
484
        return warningSymbol;
485
    }
486
487
    private ISymbol createSymbol(String symbolName, Class symbolClass,
488
            Class expectedType) throws MapContextRuntimeException {
489
        ISymbol symbol;
490
        try {
491
            symbol
492
                    = (ISymbol) (symbolClass == null ? null
493
                    : symbolClass.newInstance());
494
        } catch (InstantiationException e) {
495
            throw new RegisteredClassInstantiationException(expectedType,
496
                    symbolClass, symbolName, e);
497
        } catch (IllegalAccessException e) {
498
            throw new RegisteredClassInstantiationException(expectedType,
499
                    symbolClass, symbolName, e);
500
        }
501
502
        Color the_color = null;
503
504 40435 jjdelcerro
        if (getSymbolPreferences().isDefaultSymbolFillColorAleatory()) {
505 41397 jjdelcerro
506 40435 jjdelcerro
            the_color = getRandomBrewerBasedColor();
507 41397 jjdelcerro
508 40435 jjdelcerro
        } else {
509
            // not random
510
            the_color = getSymbolPreferences().getDefaultSymbolFillColor();
511
        }
512
        symbol.setColor(the_color);
513 41397 jjdelcerro
        // Perform this initialization into the Symbol implementation
514
        // if (symbol instanceof CartographicSupport) {
515
        // CartographicSupport cs = (CartographicSupport) symbol;
516
        // cs.setUnit(getDefaultCartographicSupportMeasureUnit());
517
        // cs
518
        // .setReferenceSystem(getDefaultCartographicSupportReferenceSystem();
519
        // }
520 40435 jjdelcerro
521 41397 jjdelcerro
        return symbol;
522
    }
523 40435 jjdelcerro
524 41397 jjdelcerro
    public void setSymbolPreferences(SymbolPreferences symbolPreferences) {
525
        this.symbolPreferences = symbolPreferences;
526
    }
527
528
    public List getSymbolLibraryNames() {
529
        File rootfolder = new File(this.getSymbolPreferences().getSymbolLibraryPath());
530
        Collection libraries = FileUtils.listFiles(rootfolder, FileFilterUtils.directoryFileFilter(), null);
531
        List l = new ArrayList();
532
        l.addAll(libraries);
533
        return l;
534
    }
535
536
    public ISymbol getSymbol(String libraryName, String symbolID) throws SymbolException {
537 41416 jjdelcerro
        Collection symbols = null;
538
        File rootfolder = null;
539
        try {
540
            rootfolder = new File(this.getSymbolPreferences().getSymbolLibraryPath());
541
            symbols = FileUtils.listFiles(rootfolder,
542
                    FileFilterUtils.nameFileFilter(symbolID + getSymbolPreferences().getSymbolFileExtension()),
543
                    FileFilterUtils.trueFileFilter()
544
            );
545
        } catch(Exception ex) {
546
            logger.warn("Can't get symbol from symbol library (library:'"+libraryName+"', symbol:'"+symbolID+"', symbolLibraryPath'"+rootfolder+"')", ex);
547
        }
548 41397 jjdelcerro
        if (symbols == null) {
549
            return null;
550
        }
551
        if (symbols.isEmpty()) {
552
            return null;
553
        }
554
555 41416 jjdelcerro
        File f = null;
556
        try {
557
            f = (File) symbols.iterator().next();
558
            ISymbol symbol = loadSymbol(f);
559
            return symbol;
560
        } catch(Exception ex) {
561
            String fname = ((f==null)?"Null":f.getAbsolutePath());
562
            logger.warn("Can't load symbol from symbol library (library:'"+libraryName+"', symbol:'"+symbolID+"', symbolLibraryPath'"+rootfolder+"', symbolFile:'"+fname+"')", ex);
563
        }
564
        return null;
565 41397 jjdelcerro
    }
566
567
    /**
568
     *
569
     * @param col
570
     * @return color 1/3 closer to black
571
     */
572
    public static Color darker(Color col) {
573 40435 jjdelcerro
        return new Color(
574 41397 jjdelcerro
                (2 * col.getRed()) / 3,
575
                (2 * col.getGreen()) / 3,
576
                (2 * col.getBlue()) / 3,
577
                col.getAlpha());
578
    }
579
580
    /**
581
     *
582
     * @param col
583
     * @return color 1/3 closer to white
584
     */
585
    public static Color lighter(Color col) {
586
        Color resp = invert(col);
587
        resp = darker(resp);
588
        return invert(resp);
589
    }
590
591
    /**
592
     *
593
     * @param col
594
     * @return inverted color (inverts each band, same alpha)
595
     */
596
    public static Color invert(Color col) {
597
        return new Color(
598
                255 - col.getRed(),
599
                255 - col.getGreen(),
600
                255 - col.getBlue(),
601
                col.getAlpha());
602
    }
603
604
    private static Color getRandomBrewerBasedColor() {
605
606
        int ind = rnd.nextInt(BREWER_COLOR.length);
607
        Color resp = BREWER_COLOR[ind];
608
        ind = rnd.nextInt(100);
609
        if (ind > 66) {
610
            resp = darker(resp);
611
        } else {
612
            if (ind > 33) {
613
                resp = lighter(resp);
614
            }
615
            // ...else resp remains the same
616
        }
617
618 42352 fdiaz
        // finally add some dark noise
619 41397 jjdelcerro
        resp = addDarkNoise(resp);
620
        return resp;
621
    }
622
623 40435 jjdelcerro
    private static Color addDarkNoise(Color c) {
624
        int r = Math.max(0, c.getRed() - rnd.nextInt(30));
625
        int g = Math.max(0, c.getGreen() - rnd.nextInt(30));
626
        int b = Math.max(0, c.getBlue() - rnd.nextInt(30));
627
        return new Color(r, g, b, c.getAlpha());
628
    }
629
630
    private static Color[] BREWER_COLOR = new Color[36];
631
    private static final Random rnd = new Random();
632
633 41397 jjdelcerro
    static {
634
        /**
635
         * Colors from www.ColorBrewer.org by Cynthia A. Brewer, Geography,
636
         * Pennsylvania State University.
637
         *
638
         * Using groups of 4 colors from the 9 Diverging Schemes 4 * 9 = 36
639
         * colors
640
         */
641
        BREWER_COLOR[0] = new Color(230, 97, 1);
642
        BREWER_COLOR[1] = new Color(253, 184, 99);
643
        BREWER_COLOR[2] = new Color(178, 171, 210);
644
        BREWER_COLOR[3] = new Color(94, 60, 153);
645
        BREWER_COLOR[4] = new Color(166, 97, 26);
646
        BREWER_COLOR[5] = new Color(223, 194, 125);
647
        BREWER_COLOR[6] = new Color(128, 205, 193);
648
        BREWER_COLOR[7] = new Color(1, 133, 113);
649
        BREWER_COLOR[8] = new Color(123, 50, 148);
650
        BREWER_COLOR[9] = new Color(194, 165, 207);
651
        BREWER_COLOR[10] = new Color(166, 219, 160);
652
        BREWER_COLOR[11] = new Color(0, 136, 55);
653
        BREWER_COLOR[12] = new Color(208, 28, 139);
654
        BREWER_COLOR[13] = new Color(241, 182, 218);
655
        BREWER_COLOR[14] = new Color(184, 225, 134);
656
        BREWER_COLOR[15] = new Color(77, 172, 38);
657
        BREWER_COLOR[16] = new Color(202, 0, 32);
658
        BREWER_COLOR[17] = new Color(244, 165, 130);
659
        BREWER_COLOR[18] = new Color(146, 197, 222);
660
        BREWER_COLOR[19] = new Color(5, 113, 176);
661
        BREWER_COLOR[20] = new Color(202, 0, 32);
662
        BREWER_COLOR[21] = new Color(244, 165, 130);
663
        BREWER_COLOR[22] = new Color(186, 186, 186);
664
        BREWER_COLOR[23] = new Color(64, 64, 64);
665
        BREWER_COLOR[24] = new Color(215, 25, 28);
666
        BREWER_COLOR[25] = new Color(253, 174, 97);
667
        BREWER_COLOR[26] = new Color(171, 217, 233);
668
        BREWER_COLOR[27] = new Color(44, 123, 182);
669
        BREWER_COLOR[28] = new Color(215, 25, 28);
670
        BREWER_COLOR[29] = new Color(253, 174, 97);
671
        BREWER_COLOR[30] = new Color(171, 221, 164);
672
        BREWER_COLOR[31] = new Color(43, 131, 186);
673
        BREWER_COLOR[32] = new Color(215, 25, 28);
674
        BREWER_COLOR[33] = new Color(253, 174, 97);
675
        BREWER_COLOR[34] = new Color(166, 217, 106);
676
        BREWER_COLOR[35] = new Color(26, 150, 65);
677
    }
678
679
}