Statistics
| Revision:

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

History | View | Annotate | Download (11.5 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.IMarkerSymbol;
17
import com.iver.cit.gvsig.fmap.core.symbols.IMultiLayerSymbol;
18
import com.iver.cit.gvsig.fmap.core.symbols.ISymbol;
19
import com.iver.cit.gvsig.fmap.layers.FLyrVect;
20
import com.iver.cit.gvsig.fmap.layers.XMLException;
21
import com.iver.cit.gvsig.fmap.rendering.AbstractClassifiedVectorLegend;
22
import com.iver.cit.gvsig.fmap.rendering.FInterval;
23
import com.iver.cit.gvsig.fmap.rendering.IClassifiedVectorLegend;
24
import com.iver.cit.gvsig.fmap.rendering.ILegend;
25
import com.iver.cit.gvsig.fmap.rendering.LegendFactory;
26
import com.iver.cit.gvsig.fmap.rendering.VectorialIntervalLegend;
27
import com.iver.cit.gvsig.fmap.rendering.ZSort;
28
import com.iver.utiles.XMLEntity;
29
/**
30
 * Implements a legend where the user can compare two different characteristics
31
 * of a region in the map. These two "fields" will be compared, on one side, 
32
 * using a color for the region and , on the other side, using a graduated symbol.
33
 * Both methods will change (the color or the size of the symbol) depending on 
34
 * the value of the fields.  
35
 * 
36
 * @author jaume dominguez faus - jaume.dominguez@iver.es
37
 */
38
public class QuantityByCategoryLegend extends AbstractClassifiedVectorLegend implements IClassifiedVectorLegend  {
39
        private GraduatedSymbolLegend graduatedSymbol = new GraduatedSymbolLegend();
40
        private VectorialIntervalLegend colorRamp = new VectorialIntervalLegend();
41
        private ISymbol defaultSymbol;
42
        private int shapeType;
43
        private boolean isUseDefaultSymbol;
44
        private DataSource ds;
45

    
46
    public void clear() {
47
        colorRamp.clear();
48
        graduatedSymbol.clear();
49
    }
50

    
51
    public String[] getClassifyingFieldNames() {
52
            ArrayList<String> l = new ArrayList<String>();
53
            for (int i = 0; i < graduatedSymbol.getClassifyingFieldNames().length; i++) {
54
                        l.add(graduatedSymbol.getClassifyingFieldNames()[i]);
55
                }
56

    
57
            for (int i = 0; i < colorRamp.getClassifyingFieldNames().length; i++) {
58
                        l.add(colorRamp.getClassifyingFieldNames()[i]);
59
                }
60
            return l.toArray(new String[l.size()]);
61
    }
62

    
63
    //////////////////////////////////////////////PEPE
64
    @Override
65
    public int[] getClassifyingFieldTypes() {
66
            int[] l = new int [graduatedSymbol.getClassifyingFieldNames().length + colorRamp.getClassifyingFieldNames().length] ;
67
            int i = 0;
68
            for (i = 0; i < graduatedSymbol.getClassifyingFieldNames().length; i++) {
69
                    l[i]=(graduatedSymbol.getClassifyingFieldTypes()[i]);
70
            }
71

    
72
            for (int j = i; j < colorRamp.getClassifyingFieldNames().length; j++) {
73
                    l[j]=(colorRamp.getClassifyingFieldTypes()[j]);
74
            }
75
            return l;
76
    }
77
    /////////////////////////////////////////////PEPE
78
    
79
    ////////////////////////////////////////PEPE
80
    public void setClassifyingFieldTypes(int[] fieldTypes) {
81
            if (fieldTypes.length!=2) {
82

    
83
            }
84
            colorRamp.setClassifyingFieldTypes(new int[] {fieldTypes[1]});
85
            graduatedSymbol.setClassifyingFieldTypes(new int[] {fieldTypes[0]});
86
    }
87

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

    
98
            if (fieldNames.length!=2) {
99

    
100
            }
101
        colorRamp.setClassifyingFieldNames(new String[] {fieldNames[1]});
102
        graduatedSymbol.setClassifyingFieldNames(new String[] {fieldNames[0]});
103
    }
104

    
105
    public void addSymbol(Object key, ISymbol symbol) {
106
            System.out.println("adding "+key+"["+symbol+"]");
107
//        // TODO Implement it
108
//        throw new Error("Not yet implemented!");
109
    }
110

    
111
    public void delSymbol(Object key) {
112
            colorRamp.delSymbol(key);
113
            graduatedSymbol.delSymbol(key);
114
    }
115

    
116
    public String[] getDescriptions() {
117
            String[] desc1 = colorRamp.getDescriptions();
118
            String[] desc2 = graduatedSymbol.getDescriptions();
119

    
120
            String[] descriptions = new String[desc1.length + desc2.length];
121
            for (int i = 0; i < descriptions.length; i++) {
122
                    descriptions[i] = (i <desc1.length) ? desc1[i] : desc2[i % desc1.length];
123
                }
124
            return descriptions;
125
    }
126

    
127
    public ISymbol[] getSymbols() {
128
            ISymbol[] symbols1 = colorRamp.getSymbols();
129
            ISymbol[] symbols2 = graduatedSymbol.getSymbols();
130

    
131
            ISymbol[] symbols = new ISymbol[symbols1.length + symbols2.length];
132
            for (int i = 0; i < symbols.length; i++) {
133
                    symbols[i] = (i < symbols1.length) ? symbols1[i] : symbols2[i % symbols1.length];
134
                }
135
            return symbols;
136
    }
137

    
138
    public Object[] getValues() {
139
            Object[] objects1 = colorRamp.getValues();
140
            Object[] objects2 = graduatedSymbol.getValues();
141

    
142
            Object[] objects = new FInterval[objects1.length + objects2.length];
143
            for (int i = 0; i < objects.length; i++) {
144
                    objects[i] = (i < objects1.length) ? objects1[i] : objects2[i % objects1.length];
145
                }
146
            return objects;
147
    }
148

    
149
    public ISymbol getDefaultSymbol() {
150
            return defaultSymbol;
151
    }
152

    
153
    public XMLEntity getXMLEntity() {
154
        XMLEntity xml = new XMLEntity();
155
        xml.putProperty("className", getClass().getName());
156
        xml.putProperty("shapeType", shapeType);
157
        xml.putProperty("isUseDefaultSymbol", isUseDefaultSymbol);
158
        xml.addChild(graduatedSymbol.getXMLEntity());
159

    
160
        xml.addChild(colorRamp.getXMLEntity());
161
        if (defaultSymbol != null)
162
                xml.addChild(defaultSymbol.getXMLEntity());
163
        return xml;
164
    }
165

    
166
    public ILegend cloneLegend() throws XMLException {
167
            return LegendFactory.createFromXML(getXMLEntity());
168

    
169
    }
170

    
171
        public GraduatedSymbolLegend getGraduatedSymbolLegend() {
172
                return graduatedSymbol;
173
        }
174

    
175
        public VectorialIntervalLegend getColorRampLegend() {
176
                return colorRamp;
177
        }
178

    
179
        public void setDataSource(DataSource ds) throws FieldNotFoundException, ReadDriverException {
180
                // TODO remove it when FLyrVect.forTestOnlyVariableUseIterators_REMOVE_THIS_FIELD is removed
181
                if (FLyrVect.forTestOnlyVariableUseIterators_REMOVE_THIS_FIELD) {
182
                        this.ds = ds;
183
                }
184
                graduatedSymbol.setDataSource(ds);
185
                colorRamp.setDataSource(ds);
186
        }
187

    
188
        public ISymbol getSymbol(int i) throws ReadDriverException {
189
                IMarkerSymbol sym1 = (IMarkerSymbol) graduatedSymbol.getSymbol(i);
190
                ISymbol sym2 =  colorRamp.getSymbol(i);
191
                IMultiLayerSymbol multiSym = null;
192
                switch (shapeType) {
193
                case FShape.POLYGON:
194
                        /*
195
                         * symbol from the GraduatedSymbolLegend is a marker, but
196
                         * what we need is a fill symbol. Will use a MarkerFillSymbol
197
                         * to enable support for Polygons
198
                         */
199
                        MarkerFillSymbol aux = new MarkerFillSymbol();
200
                        // tell the fill style to draw the IMarkerSymbol
201
                        // as a IFillSymbol centering it in the shape polygon
202
                        // centroid and applying offset (if any).
203
                        aux.setMarker(sym1);
204
                        SimpleMarkerFillPropertiesStyle p = new SimpleMarkerFillPropertiesStyle();
205
                        p.setFillStyle(SimpleMarkerFillPropertiesStyle.SINGLE_CENTERED_SYMBOL);
206
                        aux.setMarkerFillProperties(p);
207

    
208
                        multiSym = SymbologyFactory.
209
                                createEmptyMultiLayerSymbol(FShape.POLYGON);
210
                        multiSym.addLayer(sym2);
211
                        multiSym.addLayer(aux);
212
                break;
213
                case FShape.LINE:
214
                        throw new Error("Shape type not yet supported");
215
                default:
216
                        throw new Error("Unsupported shape type");
217

    
218
                }
219

    
220
                return multiSym;
221
        }
222

    
223
        public ISymbol getSymbolByFeature(IFeature feat) {
224

    
225
                ISymbol sym1 = null, sym2 = null;
226
                try {
227
                        Value gsVal;
228
                        if (FLyrVect.forTestOnlyVariableUseIterators_REMOVE_THIS_FIELD) {
229
                                gsVal = feat.getAttribute(ds.getFieldIndexByName(getClassifyingFieldNames()[0]));
230

    
231
                        } else {
232
                                gsVal = feat.getAttribute(0);
233
                        }
234
                        sym1 = graduatedSymbol.getSymbolByInterval(graduatedSymbol.getInterval(gsVal));
235
                } catch (ReadDriverException e) {
236
                        Logger.getLogger(getClass()).error("Graduated Symbol Legend failed", e);
237
                }
238

    
239
                
240
                try {
241
                        Value crVal;
242
                        if (FLyrVect.forTestOnlyVariableUseIterators_REMOVE_THIS_FIELD) {
243
                                crVal = feat.getAttribute(ds.getFieldIndexByName(getClassifyingFieldNames()[1]));
244
                        } else {
245
                                crVal = feat.getAttribute(1);
246
                        }
247
                        sym2 = colorRamp.getSymbolByInterval(
248
                                        colorRamp.getInterval(crVal));
249
                } catch (ReadDriverException e) {
250
                        Logger.getLogger(getClass()).error("Color Ramp Symbol Legend failed", e);
251
                }
252
                
253
                IMultiLayerSymbol multiSym = null;
254
                switch (shapeType) {
255
                case FShape.POLYGON:
256

    
257

    
258
                        multiSym = SymbologyFactory.
259
                        createEmptyMultiLayerSymbol(FShape.POLYGON);
260
                        if (sym2 != null) multiSym.addLayer(sym2);
261
                        if (sym1 != null) multiSym.addLayer(sym1);
262
                break;
263
                case FShape.LINE:
264
                        throw new Error("Shape type not yet supported");
265
                default:
266
                        throw new Error("Unsupported shape type");
267

    
268
                }
269

    
270
                return multiSym;
271
        }
272

    
273
        public int getShapeType() {
274
                return shapeType;
275
        }
276

    
277
        public void setShapeType(int shapeType) {
278
                this.shapeType = shapeType;
279
                graduatedSymbol.setShapeType(FShape.POINT);
280
                colorRamp.setShapeType(shapeType);
281
        }
282

    
283
        public void setDefaultSymbol(ISymbol s) throws IllegalArgumentException {
284
                if (s == null) throw new NullPointerException("Default symbol cannot be null");
285
                this.defaultSymbol = s;
286
        }
287

    
288
        public void setXMLEntity(XMLEntity xml) {
289
                shapeType = xml.getIntProperty("shapeType");
290
        isUseDefaultSymbol = xml.getBooleanProperty("isUseDefaultSymbol");
291
        try {
292
                        graduatedSymbol = (GraduatedSymbolLegend) LegendFactory.createFromXML(xml.getChild(0));
293
                        colorRamp = (VectorialIntervalLegend) LegendFactory.createFromXML(xml.getChild(1));
294
        } catch (XMLException e) {
295
                        // TODO Auto-generated catch block
296
                Logger.getLogger(getClass()).error(e.getFormatString());
297
                }
298

    
299
        if (defaultSymbol != null)
300
                xml.addChild(defaultSymbol.getXMLEntity());
301
        }
302

    
303
        public void setXMLEntity03(XMLEntity xml) {
304
                // nothing to do here
305
        }
306

    
307
        public boolean isUseDefaultSymbol() {
308
                return isUseDefaultSymbol;
309
        }
310

    
311
        public void useDefaultSymbol(boolean b) {
312
                this.isUseDefaultSymbol = b;
313
        }
314

    
315
        public String[] getUsedFields() {
316
                // TODO Implement it
317
                throw new Error("Not yet implemented!");
318

    
319
        }
320

    
321
        public void setGraduateSymbolLegend(ILegend legend) {
322
                this.graduatedSymbol = (GraduatedSymbolLegend) legend;
323
        }
324

    
325
        public void setColorRampLegend(ILegend legend) {
326
                this.colorRamp = (VectorialIntervalLegend) legend;
327
        }
328

    
329
        public ZSort getZSort() {
330
                // TODO Implement it
331
                throw new Error("Not yet implemented!");
332

    
333
        }
334
        public void setZSort(ZSort zSort) {
335
                // TODO Implement it
336
                throw new Error("Not yet implemented!");
337

    
338
        }
339

    
340
        public String getClassName() {
341
                return getClass().getName();
342
        }
343

    
344
        public void replace(ISymbol oldSymbol, ISymbol newSymbol) {
345
                ISymbol[] symbols;
346
                // look first in the graduated symbol legend
347
                symbols = graduatedSymbol.getSymbols();
348
                
349
                for (int i = 0; i < symbols.length; i++) {
350
                        if (symbols[i].equals(oldSymbol)) {
351
                                graduatedSymbol.replace(oldSymbol, newSymbol);
352
                                return;
353
                        }
354
                }
355
                
356
                // if the symbol wasn't found yet, proceed with color ramp
357
                symbols = colorRamp.getSymbols();
358
                
359
                for (int i = 0; i < symbols.length; i++) {
360
                        if (symbols[i].equals(oldSymbol)) {
361
                                colorRamp.replace(oldSymbol, newSymbol);
362
                                return;
363
                        }
364
                }
365
                
366
        }
367

    
368
}