Statistics
| Revision:

root / trunk / extensions / extSymbology / src / org / gvsig / symbology / fmap / rendering / QuantityByCategoryLegend.java @ 24374

History | View | Annotate | Download (11.3 KB)

1
package org.gvsig.symbology.fmap.rendering;
2

    
3
import java.util.ArrayList;
4

    
5
import org.apache.log4j.Logger;
6
import org.gvsig.symbology.fmap.styles.SimpleMarkerFillPropertiesStyle;
7
import org.gvsig.symbology.fmap.symbols.MarkerFillSymbol;
8

    
9
import com.hardcode.gdbms.driver.exceptions.ReadDriverException;
10
import com.hardcode.gdbms.engine.data.DataSource;
11
import com.hardcode.gdbms.engine.instruction.FieldNotFoundException;
12
import com.hardcode.gdbms.engine.values.Value;
13
import com.iver.cit.gvsig.fmap.core.FShape;
14
import com.iver.cit.gvsig.fmap.core.IFeature;
15
import com.iver.cit.gvsig.fmap.core.SymbologyFactory;
16
import com.iver.cit.gvsig.fmap.core.symbols.IFillSymbol;
17
import com.iver.cit.gvsig.fmap.core.symbols.IMarkerSymbol;
18
import com.iver.cit.gvsig.fmap.core.symbols.IMultiLayerSymbol;
19
import com.iver.cit.gvsig.fmap.core.symbols.ISymbol;
20
import com.iver.cit.gvsig.fmap.layers.FLyrVect;
21
import com.iver.cit.gvsig.fmap.layers.XMLException;
22
import com.iver.cit.gvsig.fmap.rendering.AbstractClassifiedVectorLegend;
23
import com.iver.cit.gvsig.fmap.rendering.IClassifiedVectorLegend;
24
import com.iver.cit.gvsig.fmap.rendering.IInterval;
25
import com.iver.cit.gvsig.fmap.rendering.ILegend;
26
import com.iver.cit.gvsig.fmap.rendering.LegendFactory;
27
import com.iver.cit.gvsig.fmap.rendering.SymbolLegendEvent;
28
import com.iver.cit.gvsig.fmap.rendering.VectorialIntervalLegend;
29
import com.iver.utiles.XMLEntity;
30
/**
31
 * Implements a legend where the user can compare two different characteristics
32
 * of a region in the map. These two "fields" will be compared, on one side,
33
 * using a color for the region and , on the other side, using a graduated symbol.
34
 * Both methods will change (the color or the size of the symbol) depending on
35
 * the value of the fields.
36
 *
37
 * @author jaume dominguez faus - jaume.dominguez@iver.es
38
 */
39
public class QuantityByCategoryLegend extends AbstractClassifiedVectorLegend implements IClassifiedVectorLegend  {
40
        private GraduatedSymbolLegend graduatedSymbol;
41
        private VectorialIntervalLegend colorRamp;
42
        private ISymbol defaultSymbol = SymbologyFactory.createDefaultSymbolByShapeType(FShape.POLYGON);
43
        private int shapeType;
44
        private boolean isUseDefaultSymbol;
45
        private DataSource ds;
46

    
47
        public QuantityByCategoryLegend() {
48
                graduatedSymbol = new GraduatedSymbolLegend();
49
                colorRamp = new VectorialIntervalLegend();
50
        }
51

    
52

    
53
        public void clear() {
54
                colorRamp.clear();
55
                graduatedSymbol.clear();
56
        }
57

    
58
        public String[] getClassifyingFieldNames() {
59
                ArrayList<String> l = new ArrayList<String>();
60
                for (int i = 0; i < graduatedSymbol.getClassifyingFieldNames().length; i++) {
61
                        l.add(graduatedSymbol.getClassifyingFieldNames()[i]);
62
                }
63

    
64
                for (int i = 0; i < colorRamp.getClassifyingFieldNames().length; i++) {
65
                        l.add(colorRamp.getClassifyingFieldNames()[i]);
66
                }
67
                return l.toArray(new String[l.size()]);
68
        }
69

    
70

    
71
        @Override
72
        public int[] getClassifyingFieldTypes() {
73
                return null;
74
        }
75

    
76
        public void setClassifyingFieldTypes(int[] fieldTypes) {
77
                if (fieldTypes.length!=2) {
78

    
79
                }
80
                colorRamp.setClassifyingFieldTypes(new int[] {fieldTypes[1]});
81
                graduatedSymbol.setClassifyingFieldTypes(new int[] {fieldTypes[0]});
82
        }
83

    
84

    
85
        /**
86
         * Sets the field names required to build this legend. In this case
87
         * fieldNames is an array of length 2 where the first element is
88
         * the field name for the embedded GraduatedSymbolLegend, and the
89
         * second is the field name for the embedded colorRamp (VectorialIntervalLegend)
90
         * legend.
91
         */
92
        public void setClassifyingFieldNames(String[] fieldNames) {
93

    
94
                if (fieldNames.length!=2) {
95

    
96
                }
97
                colorRamp.setClassifyingFieldNames(new String[] {fieldNames[1]});
98
                graduatedSymbol.setClassifyingFieldNames(new String[] {fieldNames[0]});
99
        }
100

    
101
        public void addSymbol(Object key, ISymbol symbol) {
102
//                System.out.println("adding "+key+"["+symbol+"]");
103

    
104
                if(symbol instanceof IFillSymbol)
105
                        colorRamp.addSymbol(key, symbol);
106
                else if(symbol instanceof IMarkerSymbol)
107
                        graduatedSymbol.addSymbol(key, symbol);
108

    
109
                fireClassifiedSymbolChangeEvent(new SymbolLegendEvent(null, symbol));
110
        }
111

    
112
        public void delSymbol(Object key) {
113
                colorRamp.delSymbol(key);
114
                graduatedSymbol.delSymbol(key);
115
                fireClassifiedSymbolChangeEvent(
116
                                new SymbolLegendEvent(
117
                                                null,
118
                                                null));
119
        }
120

    
121
        public String[] getDescriptions() {
122
                String[] desc1 = colorRamp.getDescriptions();
123
                String[] desc2 = graduatedSymbol.getDescriptions();
124

    
125
                String[] descriptions = new String[desc1.length + desc2.length];
126

    
127
                if(desc1.length == 0)
128
                        return desc2;
129
                else {
130
                        for (int i = 0; i < descriptions.length; i++) {
131
                                descriptions[i] = (i <desc1.length) ? desc1[i] : desc2[i - desc1.length];
132
                        }
133
                        return descriptions;
134
                }
135
        }
136

    
137
        public ISymbol[] getSymbols() {
138
                ISymbol[] symbols1 = colorRamp.getSymbols();
139
                ISymbol[] symbols2 = graduatedSymbol.getSymbols();
140

    
141
                ISymbol[] symbols = new ISymbol[symbols1.length + symbols2.length];
142

    
143
                if(symbols1.length == 0)
144
                        return symbols2;
145
                else {
146
                        for (int i = 0; i < symbols.length; i++) {
147
                                symbols[i] = (i < symbols1.length) ? symbols1[i] : symbols2[i - symbols1.length];
148
                        }
149
                }
150
                return symbols;
151
        }
152

    
153
        public Object[] getValues() {
154
                Object[] objects1 = colorRamp.getValues();
155
                Object[] objects2 = graduatedSymbol.getValues();
156

    
157
                Object[] objects = new IInterval[objects1.length + objects2.length];
158

    
159
                if(objects1.length == 0)
160
                        return objects2;
161

    
162

    
163
                else {
164
                        for (int i = 0; i < objects.length; i++) {
165
                                objects[i] = (i < objects1.length) ? objects1[i] : objects2[i - objects1.length];
166
                        }
167
                        return objects;
168
                }
169

    
170
        }
171

    
172

    
173

    
174
        public XMLEntity getXMLEntity() {
175
                XMLEntity xml = new XMLEntity();
176
                xml.putProperty("className", getClass().getName());
177
                xml.putProperty("shapeType", shapeType);
178
                xml.putProperty("isUseDefaultSymbol", isUseDefaultSymbol);
179

    
180
                xml.addChild(colorRamp.getXMLEntity());
181
                xml.addChild(graduatedSymbol.getXMLEntity());
182

    
183
                return xml;
184
        }
185

    
186
        public ILegend cloneLegend() throws XMLException {
187
                return LegendFactory.createFromXML(getXMLEntity());
188

    
189
        }
190
        /**
191
         * Obtains the GraduatedSymbolLegend
192
         *
193
         * @return GraduatedSymbolLegend
194
         */
195
        public GraduatedSymbolLegend getGraduatedSymbolLegend() {
196
                return graduatedSymbol;
197
        }
198
        /**
199
         * Obtains the VectorialIntervalLegend
200
         *
201
         * @return VectorialIntervalLegend
202
         */
203
        public VectorialIntervalLegend getColorRampLegend() {
204
                return colorRamp;
205
        }
206

    
207
        public void setDataSource(DataSource ds) throws FieldNotFoundException, ReadDriverException {
208
                // TODO remove it when FLyrVect.forTestOnlyVariableUseIterators_REMOVE_THIS_FIELD is removed
209
//                if (FLyrVect.forTestOnlyVariableUseIterators_REMOVE_THIS_FIELD) {
210
                        this.ds = ds;
211
//                }
212
                graduatedSymbol.setDataSource(ds);
213
                colorRamp.setDataSource(ds);
214
        }
215

    
216
        public ISymbol getSymbol(int i) throws ReadDriverException {
217
                IMarkerSymbol sym1 = (IMarkerSymbol) graduatedSymbol.getSymbol(i);
218
                ISymbol sym2 =  colorRamp.getSymbol(i);
219
                IMultiLayerSymbol multiSym = null;
220
                switch (shapeType) {
221
                case FShape.POLYGON:
222
                        /*
223
                         * symbol from the GraduatedSymbolLegend is a marker, but
224
                         * what we need is a fill symbol. Will use a MarkerFillSymbol
225
                         * to enable support for Polygons
226
                         */
227
                        MarkerFillSymbol aux = new MarkerFillSymbol();
228
                        // tell the fill style to draw the IMarkerSymbol
229
                        // as a IFillSymbol centering it in the shape polygon
230
                        // centroid and applying offset (if any).
231
                        aux.setMarker(sym1);
232
                        SimpleMarkerFillPropertiesStyle p = new SimpleMarkerFillPropertiesStyle();
233
                        p.setFillStyle(SimpleMarkerFillPropertiesStyle.SINGLE_CENTERED_SYMBOL);
234
                        aux.setMarkerFillProperties(p);
235

    
236
                        multiSym = SymbologyFactory.
237
                        createEmptyMultiLayerSymbol(FShape.POLYGON);
238
                        multiSym.addLayer(sym2);
239
                        multiSym.addLayer(aux);
240
                        break;
241
                case FShape.LINE:
242
                        throw new Error("Shape type not yet supported");
243
                default:
244
                        throw new Error("Unsupported shape type");
245

    
246
                }
247

    
248
                return multiSym;
249
        }
250

    
251
        public ISymbol getSymbolByFeature(IFeature feat) {
252
                ISymbol sym1 = null, sym2 = null;
253
//                try {
254
                        Value gsVal;
255
//                        if (!FLyrVect.forTestOnlyVariableUseIterators_REMOVE_THIS_FIELD) {
256
//                                gsVal = feat.getAttribute(ds.getFieldIndexByName(getClassifyingFieldNames()[0]));
257
//
258
//                        } else {
259
                                gsVal = feat.getAttribute(0);
260
//                        }
261
                        sym1 = graduatedSymbol.getSymbolByInterval(graduatedSymbol.getInterval(gsVal));
262

    
263
//                } catch (ReadDriverException e) {
264
//                        Logger.getLogger(getClass()).error("Graduated Symbol Legend failed", e);
265
//                }
266

    
267

    
268
//                try {
269
                        Value crVal;
270
//                        if (!FLyrVect.forTestOnlyVariableUseIterators_REMOVE_THIS_FIELD) {
271
//                                crVal = feat.getAttribute(ds.getFieldIndexByName(getClassifyingFieldNames()[1]));
272
//                        } else {
273
                                crVal = feat.getAttribute(1);
274
//                        }
275
                        sym2 = colorRamp.getSymbolByInterval(colorRamp.getInterval(crVal));
276

    
277
//                } catch (ReadDriverException e) {
278
//                        Logger.getLogger(getClass()).error("Color Ramp Symbol Legend failed", e);
279
//                }
280

    
281
                IMultiLayerSymbol multiSym = null;
282
                switch (shapeType) {
283
                case FShape.POLYGON:
284
                        multiSym = SymbologyFactory.
285
                        createEmptyMultiLayerSymbol(FShape.POLYGON);
286
                        if (sym2 != null) multiSym.addLayer(sym2);
287
                        if (sym1 != null) multiSym.addLayer(sym1);
288
                        break;
289
                case FShape.LINE:
290
                        throw new Error("Shape type not yet supported");
291
                default:
292
                        throw new Error("Unsupported shape type");
293

    
294
                }
295

    
296
                return multiSym;
297
        }
298

    
299
        public int getShapeType() {
300
                return shapeType;
301
        }
302

    
303
        public void setShapeType(int shapeType) {
304
                this.shapeType = shapeType;
305
                graduatedSymbol.setShapeType(FShape.POINT);
306
                graduatedSymbol.setDefaultSymbol(SymbologyFactory.createDefaultSymbolByShapeType(FShape.POINT));
307
                colorRamp.setShapeType(shapeType);
308
                colorRamp.setDefaultSymbol(SymbologyFactory.createDefaultSymbolByShapeType(shapeType));
309
        }
310

    
311

    
312
        public void setXMLEntity(XMLEntity xml) {
313
                shapeType = xml.getIntProperty("shapeType");
314
                isUseDefaultSymbol = xml.getBooleanProperty("isUseDefaultSymbol");
315
                try {
316
                        colorRamp = (VectorialIntervalLegend) LegendFactory.createFromXML(xml.getChild(0));
317
                        graduatedSymbol = (GraduatedSymbolLegend) LegendFactory.createFromXML(xml.getChild(1));
318
                        colorRamp.setShapeType(shapeType);
319
                        graduatedSymbol.setShapeType(shapeType);
320
                } catch (XMLException e) {
321
                        // TODO Auto-generated catch block
322
                        Logger.getLogger(getClass()).error(e.getFormatString());
323
                }
324
        }
325

    
326
        public void setXMLEntity03(XMLEntity xml) {
327
                // nothing to do here
328
        }
329

    
330
        public boolean isUseDefaultSymbol() {
331
                return isUseDefaultSymbol;
332
        }
333

    
334
        public void useDefaultSymbol(boolean b) {
335
                this.isUseDefaultSymbol = b;
336
        }
337

    
338
        public String[] getUsedFields() {
339
                // TODO Implement it
340
                throw new Error("Not yet implemented!");
341
        }
342

    
343
        public void setGraduateSymbolLegend(ILegend legend) {
344
                this.graduatedSymbol = (GraduatedSymbolLegend) legend;
345
        }
346

    
347
        public void setColorRampLegend(ILegend legend) {
348
                this.colorRamp = (VectorialIntervalLegend) legend;
349
        }
350

    
351
        public String getClassName() {
352
                return getClass().getName();
353
        }
354

    
355
        public void replace(ISymbol oldSymbol, ISymbol newSymbol) {
356
                ISymbol[] symbols;
357
                // look first in the graduated symbol legend
358
                symbols = graduatedSymbol.getSymbols();
359

    
360
                for (int i = 0; i < symbols.length; i++) {
361
                        if (symbols[i].equals(oldSymbol)) {
362
                                graduatedSymbol.replace(oldSymbol, newSymbol);
363
                                return;
364
                        }
365
                }
366

    
367
                // if the symbol wasn't found yet, proceed with color ramp
368
                symbols = colorRamp.getSymbols();
369

    
370
                for (int i = 0; i < symbols.length; i++) {
371
                        if (symbols[i].equals(oldSymbol)) {
372
                                colorRamp.replace(oldSymbol, newSymbol);
373
                                return;
374
                        }
375
                }
376

    
377
        }
378

    
379
        public ISymbol getDefaultSymbol() {
380
                return defaultSymbol;
381
        }
382

    
383
        public void setDefaultSymbol(ISymbol s) throws IllegalArgumentException {
384
                this.defaultSymbol = s;
385
        }
386

    
387
}