Statistics
| Revision:

root / branches / v2_0_0_prep / extensions / org.gvsig.symbology / src / main / java / org / gvsig / symbology / fmap / mapcontext / rendering / symbol / fill / impl / MultiLayerFillSymbol.java @ 32880

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

    
23
package org.gvsig.symbology.fmap.mapcontext.rendering.symbol.fill.impl;
24

    
25
import java.awt.Color;
26
import java.awt.Graphics2D;
27
import java.awt.Rectangle;
28
import java.awt.geom.AffineTransform;
29
import java.util.ArrayList;
30
import java.util.List;
31

    
32
import org.gvsig.compat.print.PrintAttributes;
33
import org.gvsig.fmap.dal.feature.Feature;
34
import org.gvsig.fmap.geom.Geometry;
35
import org.gvsig.fmap.mapcontext.MapContext;
36
import org.gvsig.fmap.mapcontext.ViewPort;
37
import org.gvsig.fmap.mapcontext.rendering.symbols.IMultiLayerSymbol;
38
import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
39
import org.gvsig.fmap.mapcontext.rendering.symbols.SymbolDrawingException;
40
import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.fill.IFillSymbol;
41
import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.line.ILineSymbol;
42
import org.gvsig.tools.ToolsLocator;
43
import org.gvsig.tools.dynobject.DynStruct;
44
import org.gvsig.tools.persistence.PersistenceManager;
45
import org.gvsig.tools.persistence.PersistentState;
46
import org.gvsig.tools.persistence.exception.PersistenceException;
47
import org.gvsig.tools.task.Cancellable;
48

    
49

    
50
/**
51
 * MultiLayerFillSymbol is a symbol which allows to group several kind of fill symbols
52
 * (xxxFillSymbol implementing IFillSymbol)in one and treats it like single symbol.
53
 * @author 2009-     <a href="cordinyana@gvsig.org">C?sar Ordi?ana</a> - gvSIG team
54
 */
55
public class MultiLayerFillSymbol extends AbstractFillSymbol implements IFillSymbol, IMultiLayerSymbol{
56
    
57
    public static final String MULTILAYER_FILL_SYMBOL_DYNCLASS_NAME = "MultiLayerFillSymbol";
58
//    private static final String FIELD_SYMBOL_FOR_SELECTION = "symbolForSelection";
59
    private static final String FIELD_LAYERS = "layers";
60
    
61
        private static final double OPACITY_SELECTION_FACTOR = .8;
62
        private IFillSymbol[] layers = new IFillSymbol[0];
63
        private MultiLayerFillSymbol selectionSymbol;
64
//        private Object symbolType;
65

    
66
        public Color getFillColor() {
67
                /*
68
                 * a multilayer symbol does not define any color, the color
69
                 * of each layer is defined by the layer itself
70
                 */
71
                return null;
72
        }
73

    
74
        public int getOnePointRgb() {
75
                // will paint only the last layer pixel
76
                return layers[layers.length-1].getOnePointRgb();
77
        }
78

    
79
        public ILineSymbol getOutline() {
80
                /*
81
                 * a multilayer symbol does not define any outline, the outline
82
                 * of each layer is defined by the layer it self
83
                 */
84
                return null;
85
        }
86

    
87
        public boolean isSuitableFor(Geometry geom) {
88
                return geom.getType() == Geometry.TYPES.SURFACE;
89
        }
90

    
91
        public void setFillColor(Color color) {
92
                /*
93
                 * Will apply the color to each layer
94
                 */
95
                for (int i = 0; layers != null && i < layers.length; i++) {
96
                        layers[i].setFillColor(color);
97
                }
98
        }
99

    
100
        public void setOutline(ILineSymbol outline) {
101
                if (layers != null && layers.length > 0) {
102
                        for (int i = 0; i < layers.length - 1; i++) {
103
                                layers[i].setOutline(null);
104
                        }
105
                        layers[layers.length - 1].setOutline(outline);
106
                }
107
        }
108

    
109
        public void draw(Graphics2D g, AffineTransform affineTransform,
110
                        Geometry geom, Feature feature, Cancellable cancel) {
111
                for (int i = 0; (cancel == null || !cancel.isCanceled())
112
                                && layers != null && i < layers.length; i++) {
113
                        layers[i].draw(g, affineTransform, geom, feature, cancel);
114
                }
115
        }
116

    
117
        public void drawInsideRectangle(Graphics2D g,
118
                        AffineTransform scaleInstance, Rectangle r, PrintAttributes properties) throws SymbolDrawingException {
119
                for (int i = 0; layers != null && i < layers.length; i++) {
120
                        layers[i].drawInsideRectangle(g, scaleInstance, r, properties);
121
                }
122
        }
123

    
124
        public void getPixExtentPlus(Geometry geom, float[] distances,
125
                        ViewPort viewPort, int dpi) {
126
                float[] myDistances = new float[] {0,0};
127
                distances[0] = 0;
128
                distances[1] = 0;
129
                for (int i = 0; layers != null && i < layers.length; i++) {
130
                        layers[i].getPixExtentPlus(geom, myDistances, viewPort, dpi);
131
                        distances[0] = Math.max(myDistances[0], distances[0]);
132
                        distances[1] = Math.max(myDistances[1], distances[1]);
133
                }
134
        }
135

    
136
        public ISymbol getSymbolForSelection() {
137
            // TODO: revisar
138
            
139
                if (selectionSymbol == null) {
140
                            MultiLayerFillSymbol selectionSymbol = 
141
                                new MultiLayerFillSymbol();
142
                        selectionSymbol.setDescription(getDescription());
143
//                        selectionSymbol.symbolType = symbolType;
144
                        for (int i = 0; layers != null && i < layers.length; i++) {
145
                                selectionSymbol.addLayer(layers[i].getSymbolForSelection());
146
                        }
147
                        SimpleFillSymbol selLayer = new SimpleFillSymbol();
148
                        Color c = MapContext.getSelectionColor();
149
                        c = new Color(
150
                                        c.getRed(),
151
                                        c.getGreen(),
152
                                        c.getBlue(),
153
                                        (int) (255*OPACITY_SELECTION_FACTOR));
154
                        selLayer.setFillColor(c);
155
                        selLayer.setOutline(getOutline());
156
                        selectionSymbol.addLayer(selLayer);
157
                        setSymbolForSelection(selectionSymbol);
158
                }
159
                return selectionSymbol;
160

    
161
        }
162

    
163
        public int getSymbolType() {
164
                return Geometry.TYPES.SURFACE;
165
        }
166

    
167
        public void setPrintingProperties(PrintAttributes printProperties) {
168
                // TODO Implement it
169
                throw new Error("Not yet implemented!");
170

    
171
        }
172

    
173
        public String getClassName() {
174
                return getClass().getName();
175
        }
176

    
177
        public void print(Graphics2D g, AffineTransform at, Geometry geom, PrintAttributes properties) {
178
                for (int i = 0; layers != null && i < layers.length; i++) {
179
                        layers[i].print(g, at, geom, properties);
180
                }
181
        }
182

    
183
        public void setLayer(int index, ISymbol layer) throws IndexOutOfBoundsException {
184
                layers[index] = (IFillSymbol) layer;
185
        }
186

    
187
        public void swapLayers(int index1, int index2) {
188
                ISymbol aux1 = getLayer(index1), aux2 = getLayer(index2);
189
                layers[index2] = (IFillSymbol) aux1;
190
                layers[index1] = (IFillSymbol) aux2;
191
        }
192

    
193
        public ISymbol getLayer(int layerIndex) {
194
//                try{
195
                        return layers[layerIndex];
196
//                } catch (Exception e) {
197
//                        return null;
198
//                }
199
        }
200

    
201
        public int getLayerCount() {
202
                return layers.length;
203
        }
204

    
205
        public void addLayer(ISymbol newLayer) {
206
                addLayer(newLayer, layers.length);
207
        }
208

    
209
        public void addLayer(ISymbol newLayer, int layerIndex) throws IndexOutOfBoundsException {
210
                if (newLayer == null ) {
211
                        /*|| newLayer instanceof ILabelStyle)*/ return; // null or symbols that are styles are not allowed
212
                }
213

    
214
                selectionSymbol = null; /* forces the selection symbol to be re-created
215
                                                                  * next time it is required
216
                                                                  */
217
                if (layerIndex < 0 || layers.length < layerIndex) {
218
                        throw new IndexOutOfBoundsException(layerIndex+" < 0 or "+layerIndex+" > "+layers.length);
219
                }
220
                List<ISymbol> newLayers = new ArrayList<ISymbol>();
221
                for (int i = 0; i < layers.length; i++) {
222
                        newLayers.add(layers[i]);
223
                }
224
                try {
225
                        newLayers.add(layerIndex, newLayer);
226
                        layers = (IFillSymbol[]) newLayers.toArray(new IFillSymbol[0]);
227
                } catch (ArrayStoreException asEx) {
228
                        throw new ClassCastException(newLayer.getClass().getName() + " is not an IFillSymbol");
229
                }
230
        }
231

    
232
        public boolean removeLayer(ISymbol layer) {
233

    
234
                int capacity = 0;
235
                capacity = layers.length;
236
                List<IFillSymbol> lst = new ArrayList<IFillSymbol>(capacity);
237
                for (int i = 0; layers != null && i < capacity; i++) {
238
                        lst.add(layers[i]);
239
                }
240
                boolean contains = lst.remove(layer);
241
                layers = (IFillSymbol[])lst.toArray(new IFillSymbol[0]);
242
                return contains;
243
        }
244
        
245
        public void setUnit(int unitIndex) {
246
                super.setUnit(unitIndex);
247
                for (int i = 0; layers != null && i < layers.length; i++) {
248
                        layers[i].setUnit(unitIndex);
249
                }
250
        }
251

    
252
        public void setReferenceSystem(int system) {
253
                super.setReferenceSystem(system);
254
                for (int i = 0; layers != null && i < layers.length; i++) {
255
                        layers[i].setReferenceSystem(system);
256
                }
257
        }
258

    
259
        /**
260
         *Returns the transparency of the multi layer fill symbol created
261
         */
262
        public int getFillAlpha() {
263
                // will compute the acumulated opacity
264
                double myAlpha = 0;
265
                for (int i = 0; layers != null && i < layers.length; i++) {
266
                        double layerAlpha = layers[i].getFillAlpha()/255D;
267
                        myAlpha += (1-myAlpha)*layerAlpha;
268
                }
269
                int result = (int) Math.round(myAlpha * 255);
270
                return (result>255) ? 255 : result;
271
        }
272

    
273

    
274
        public double toCartographicSize(ViewPort viewPort, double dpi, Geometry geom) {
275
                double size = 0;
276
                for (int i = 0; layers != null && i < layers.length; i++) {
277
                        size = Math.max(size, layers[i].toCartographicSize(viewPort, dpi, geom));
278
                }
279
                return size;
280
        }
281
        
282
        public Object clone() throws CloneNotSupportedException {
283
                MultiLayerFillSymbol copy = (MultiLayerFillSymbol) super.clone();
284

    
285
                // Clone layers
286
                if (layers != null) {
287
                        IFillSymbol[] layersCopy = new IFillSymbol[layers.length];
288
                        for (int i = 0; i < layers.length; i++) {
289
                                layersCopy[i] = (IFillSymbol) layers[i].clone();
290
                        }
291
                        copy.layers = layersCopy;
292
                }
293

    
294
                // Clone selection
295
                if (selectionSymbol != null) {
296
                        copy.selectionSymbol = (MultiLayerFillSymbol) selectionSymbol
297
                                        .clone();
298
                }
299

    
300
                return copy;
301
        }
302

    
303
        private void setSymbolForSelection(MultiLayerFillSymbol symbolForSelection) {
304
                this.selectionSymbol = symbolForSelection;
305
        }
306

    
307
        @SuppressWarnings("unchecked")
308
        public void loadFromState(PersistentState state)
309
                        throws PersistenceException {
310
                // Set parent fill symbol properties
311
                super.loadFromState(state);
312
                // Set own properties
313
                // setSymbolForSelection((MultiLayerFillSymbol)
314
                // state.get(FIELD_SYMBOL_FOR_SELECTION));
315
                List layers = state.getList(FIELD_LAYERS);
316
                if (layers != null) {
317
                        for (int i = 0; i < layers.size(); i++) {
318
                                addLayer((ISymbol) layers.get(i));
319
                        }
320
                }
321

    
322
        }
323

    
324
        public void saveToState(PersistentState state) throws PersistenceException {
325
                // Save parent fill symbol properties
326
                super.saveToState(state);
327
                // Save own properties
328

    
329
                // Don't use the getSymbolForSelection method, as it will create it
330
                // if it does not exist, and persistence will enter an infinite loop
331
                // state.set(FIELD_SYMBOL_FOR_SELECTION, selectionSymbol);
332
                state.set(FIELD_LAYERS, layers);
333
        }
334

    
335
        public static void registerPersistence() {
336
                // Add the MultiLayerFillSymbol DynClass definition.
337
                PersistenceManager manager = ToolsLocator.getPersistenceManager();
338
                DynStruct definition = manager.addDefinition(
339
                                MultiLayerFillSymbol.class,
340
                                MULTILAYER_FILL_SYMBOL_DYNCLASS_NAME,
341
                                MULTILAYER_FILL_SYMBOL_DYNCLASS_NAME+" Persistence definition",
342
                                null, 
343
                                null
344
                );
345

    
346
                // Extend the FillSymbol base definition
347
                definition.extend(FILL_SYMBOL_DYNCLASS_NAME);
348

    
349
                // Selection Symbol
350
                // definition.addDynFieldSingle(FIELD_SYMBOL_FOR_SELECTION).setType(
351
                // DataTypes.OBJECT);
352

    
353
                // Layers
354
                definition.addDynFieldList(FIELD_LAYERS);
355
        }
356

    
357
}