Statistics
| Revision:

root / trunk / libraries / libFMap / src / com / iver / cit / gvsig / fmap / rendering / styling / AttrInTableLabeling.java @ 11704

History | View | Annotate | Download (9.92 KB)

1
package com.iver.cit.gvsig.fmap.rendering.styling;
2

    
3
import java.awt.Color;
4
import java.awt.Font;
5
import java.awt.Graphics2D;
6
import java.awt.geom.NoninvertibleTransformException;
7
import java.awt.image.BufferedImage;
8
import java.util.ArrayList;
9
import java.util.Vector;
10
import java.util.logging.Level;
11
import java.util.logging.Logger;
12

    
13
import javax.print.attribute.PrintRequestAttributeSet;
14

    
15
import com.hardcode.gdbms.driver.exceptions.ReadDriverException;
16
import com.hardcode.gdbms.engine.values.NullValue;
17
import com.hardcode.gdbms.engine.values.NumericValue;
18
import com.hardcode.gdbms.engine.values.Value;
19
import com.iver.cit.gvsig.exceptions.expansionfile.ExpansionFileReadException;
20
import com.iver.cit.gvsig.exceptions.visitors.VisitorException;
21
import com.iver.cit.gvsig.fmap.ViewPort;
22
import com.iver.cit.gvsig.fmap.core.CartographicSupport;
23
import com.iver.cit.gvsig.fmap.core.FPoint2D;
24
import com.iver.cit.gvsig.fmap.core.FShape;
25
import com.iver.cit.gvsig.fmap.core.IGeometry;
26
import com.iver.cit.gvsig.fmap.core.symbols.SimpleTextSymbol;
27
import com.iver.cit.gvsig.fmap.core.v02.FConstant;
28
import com.iver.cit.gvsig.fmap.core.v02.FLabel;
29
import com.iver.cit.gvsig.fmap.layers.FBitSet;
30
import com.iver.cit.gvsig.fmap.layers.FLyrVect;
31
import com.iver.cit.gvsig.fmap.layers.ReadableVectorial;
32
import com.iver.cit.gvsig.fmap.layers.SelectableDataSource;
33
import com.iver.utiles.XMLEntity;
34
import com.iver.utiles.swing.threads.Cancellable;
35

    
36
/**
37
 * LabelingStrategy used when the user wants to use label sizes, rotations, etc. from
38
 * the values included in fields of the datasource's table
39
 *
40
 * @author jaume dominguez faus - jaume.dominguez@iver.es
41
 *
42
 */
43
public class AttrInTableLabeling implements ILabelingStrategy, CartographicSupport {
44
        public static final double MIN_TEXT_SIZE = 3;
45
        private ILabelingMethod method = new DefaultLabelingMethod();
46
        private IZoomConstraints zoom;
47
        private int idTextField;
48
        private int idHeightField;
49
        private int idRotationField;
50
        private FLyrVect layer;
51
//        private double unitFactor = 1D;
52
        private double fixedSize;
53
        private int unit = -1; //(pixel)
54
        private boolean useFixedSize;
55

    
56
        public ILabelingMethod getLabelingMethod() {
57
                return this.method;
58
        }
59

    
60
        public void setLabelingMethod(ILabelingMethod method) {
61
                this.method = method;
62
        }
63

    
64
        public IPlacementConstraints getPlacementConstraints() {
65
                return null; // (automatically handled by the driver)
66
        }
67

    
68
        public void setPlacementConstraints(IPlacementConstraints constraints) {
69
                // nothing
70
        }
71

    
72
        public IZoomConstraints getZoomConstraints() {
73
                return zoom;
74
        }
75

    
76
        public void setZoomConstraints(IZoomConstraints constraints) {
77
                this.zoom = constraints;
78
        }
79

    
80
        public void draw(BufferedImage image, Graphics2D g, ViewPort viewPort, Cancellable cancel)
81
        throws ReadDriverException {
82
                double scale = viewPort.getScale();
83
                double fontScaleFactor = FConstant.FONT_HEIGHT_SCALE_FACTOR;
84

    
85
                LabelClass lClass = method.getDefaultLabelClass();
86
                SimpleTextSymbol sym = (SimpleTextSymbol) lClass.getLabelSymbol();
87
                if (zoom==null ||
88
                        ( zoom.isUserDefined() && (scale >= zoom.getMaxScale())
89
                        && (scale <= zoom.getMinScale()) ) ) {
90
                        try {
91
                                // limit the labeling to the visible extent
92
                                FBitSet bs = layer.queryByRect(viewPort.getAdjustedExtent());
93

    
94
                                ReadableVectorial source = layer.getSource();
95
                                SelectableDataSource recordSet = source.getRecordset();
96

    
97
                                for(int i=bs.nextSetBit(0); i>=0 && !cancel.isCanceled(); i=bs.nextSetBit(i+1)) {
98
                                        Value[] vv = recordSet.getRow(i);
99
                                        double size;
100

    
101
                                        if (useFixedSize){
102
                                                // uses fixed size
103
                                                size = fixedSize * fontScaleFactor;
104
                                        } else if (idHeightField != -1) {
105
                                                // text size is defined in the table
106
                                                try {
107
                                                        size = ((NumericValue) vv[idHeightField]).doubleValue() * fontScaleFactor;
108
                                                } catch (ClassCastException ccEx) {
109
                                                        if (!NullValue.class.equals(vv[idHeightField].getClass())) {
110
                                                                throw new ReadDriverException("Unknown", ccEx);
111
                                                        }
112
                                                        // a null value
113
                                                        Logger.getAnonymousLogger().
114
                                                                warning("Null text height value for text '"+vv[idTextField].toString()+"'");
115
                                                        continue;
116
                                                }
117
                                        } else {
118
                                                // otherwise will use the size in the symbol
119
                                                size = sym.getFont().getSize();
120
                                        }
121

    
122
                                        size = CartographicSupportToolkit.
123
                                                                toScreenUnitYAxis(size,
124
                                                                                                  unit,
125
                                                                                                  viewPort
126
                                                                                                 );
127

    
128
                                        if (size <= MIN_TEXT_SIZE) {
129
                                                // label is too small to be readable, will be skipped
130
                                                // this speeds up the rendering in wider zooms
131
                                                continue;
132
                                        }
133

    
134
                                        sym.setFontSize(size);
135
                                        double rotation = 0D;
136
                                        if (idRotationField!= -1) {
137
                                                // text rotation is defined in the table
138
                                                rotation = -Math.toRadians(((NumericValue) vv[idRotationField]).doubleValue());
139
                                        }
140

    
141
                                        IGeometry geom = source.getShape(i);
142
                                        sym.setText(vv[idTextField].toString());
143
                                        sym.setRotation(rotation);
144

    
145
                                        FLabel[] aux = geom.createLabels(0, true);
146
                                        for (int j = 0; j < aux.length; j++) {
147
                                                FPoint2D p = new FPoint2D(aux[j].getOrig());
148
                                                p.transform(viewPort.getAffineTransform());
149
                                                sym.draw(g, null, p);
150
                                        }
151
                                }
152
                        } catch (VisitorException e) {
153
                                Logger.getAnonymousLogger().log(Level.SEVERE, "Could not get the layer extent.\n" +
154
                                                e.getMessage());
155
                        } catch (ExpansionFileReadException e) {
156
                                Logger.getAnonymousLogger().log(Level.SEVERE, "Could not draw annotation in the layer" +
157
                                                "\""+layer.getName()+"\".\nIs the layer being edited?.\n"+e.getMessage());
158
                        } catch (ReadDriverException e) {
159
                                Logger.getAnonymousLogger().log(Level.SEVERE, "Could not draw annotation in the layer.\n" +
160
                                                e.getMessage());
161
                        }
162

    
163
                }
164
        }
165

    
166
        public void setLayer(FLyrVect lyrVect) {
167
                this.layer = lyrVect;
168
        }
169

    
170
        public String getClassName() {
171
                return getClass().getName();
172
        }
173

    
174
        public XMLEntity getXMLEntity() {
175
                XMLEntity xml = new XMLEntity();
176
                xml.putProperty("className", getClassName());
177

    
178
                try {
179
                        xml.putProperty("HeightField", getHeightField());
180
                } catch (ReadDriverException e) {
181
                        Logger.getAnonymousLogger().log(Level.SEVERE, "Acessing TextHeight field.\n"+e.getMessage());
182
                }
183

    
184
                try {
185
                        xml.putProperty("TextField", getTextField());
186
                } catch (ReadDriverException e) {
187
                        Logger.getAnonymousLogger().log(Level.SEVERE, "Acessing TextField field.\n"+e.getMessage());
188
                }
189

    
190
                try {
191
                        xml.putProperty("RotationField", getRotationField());
192
                } catch (ReadDriverException e) {
193
                        Logger.getAnonymousLogger().log(Level.SEVERE, "Acessing RotationField field.\n"+e.getMessage());
194
                }
195

    
196
                xml.putProperty("Unit", unit);
197
                return xml;
198

    
199
        }
200

    
201
        public String getRotationField() throws ReadDriverException {
202
                if (idRotationField == -1) return null;
203
                return ((SelectableDataSource) layer.getRecordset())
204
                                .getFieldName(idRotationField);
205
        }
206

    
207
        public int getRotationFieldId() {
208
                return idRotationField;
209
        }
210

    
211
        public void setRotationFieldId(int fieldId) {
212
                this.idRotationField = fieldId;
213
        }
214

    
215
        public String getTextField() throws ReadDriverException {
216
                if (idTextField == -1) return null;
217
                return ((SelectableDataSource) layer.getRecordset())
218
                                .getFieldName(idTextField);
219
        }
220

    
221
        public int getTextFieldId() {
222
                return idTextField;
223
        }
224

    
225
        public void setTextFieldId(int fieldId) {
226
                this.idTextField = fieldId;
227
        }
228

    
229
        public String getHeightField() throws ReadDriverException {
230
                if (idHeightField == -1) return null;
231
                return ((SelectableDataSource) layer.getRecordset())
232
                                .getFieldName(idHeightField);
233
        }
234

    
235
        public int getHeightFieldId() {
236
                return idHeightField;
237
        }
238

    
239
        public void setHeightFieldId(int fieldId) {
240
                this.idHeightField = fieldId;
241
        }
242

    
243
        public void setXMLEntity(XMLEntity xml) {
244
                if (xml.contains("TextField" ))
245
                        setTextField(xml.getStringProperty("TextField"));
246

    
247
                if (xml.contains("HeightField"))
248
                        setHeightField("HeightField");
249

    
250
                if (xml.contains("RotationField"))
251
                        setRotationField("RotationField");
252

    
253
                if (xml.contains("UnitFactor"))
254
                        setUnit(xml.getIntProperty("Unit"));
255
        }
256

    
257
        public void setTextField(String textFieldName) {
258
                try {
259
                        idTextField = ((SelectableDataSource) layer.getRecordset())
260
                                                                .getFieldIndexByName(textFieldName);
261
                } catch (ReadDriverException e) {
262
                        Logger.getAnonymousLogger().log(Level.SEVERE, e.getMessage());
263
                }
264
        }
265

    
266
        public void setRotationField(String rotationFieldName) {
267
                if (rotationFieldName != null) {
268
                        try {
269
                                idRotationField = ((SelectableDataSource) layer.getRecordset())
270
                                .getFieldIndexByName(rotationFieldName);
271
                        } catch (ReadDriverException e) {
272
                                Logger.getAnonymousLogger().log(Level.SEVERE, e.getMessage());
273
                        }
274
                } else idRotationField = -1;
275
        }
276

    
277
        /**
278
         * Sets the field that contains the size of the text. The size is computed
279
         * in meters. To use any other unit, call setUnit(int) with the scale factor from meters
280
         * (for centimeters, call <b>setUnitFactor(0.01))</b>.
281
         * @param heightFieldName
282
         */
283
        public void setHeightField(String heightFieldName) {
284
                if (heightFieldName != null) {
285
                        try {
286
                                idHeightField = ((SelectableDataSource) layer.getRecordset())
287
                                .getFieldIndexByName(heightFieldName);
288
                        } catch (ReadDriverException e) {
289
                                Logger.getAnonymousLogger().log(Level.SEVERE, e.getMessage());
290
                        }
291
                } else idHeightField = -1;
292
        }
293

    
294

    
295
        public void print(Graphics2D g, ViewPort viewPort, Cancellable cancel, PrintRequestAttributeSet properties) throws ReadDriverException {
296
                draw(null, g, viewPort, cancel);
297
        }
298

    
299
        public void setUsesFixedSize(boolean b) {
300
                useFixedSize = b;
301
        }
302

    
303
        public boolean usesFixedSize() {
304
                return useFixedSize;
305
        }
306

    
307
        public double getFixedSize() {
308
                return fixedSize;
309
        }
310

    
311
        public void setFixedSize(double fixedSize) {
312
                this.fixedSize = fixedSize;
313
        }
314

    
315
        public void setUnit(int unitIndex) {
316
                unit = unitIndex;
317

    
318
        }
319

    
320
        public int getUnit() {
321
                return unit;
322
        }
323

    
324
        public String[] getUsedFields() {
325
                Vector v = new Vector();
326
                try {
327
                        if (getHeightField()!=null) v.add(getHeightField());
328
                        if (getRotationField()!=null) v.add(getRotationField());
329
                        if (getTextField()!=null) v.add(getTextField());
330
                        if (getHeightField()!=null) v.add(getHeightField());
331
                } catch (ReadDriverException e) {
332
                        Logger.getAnonymousLogger().log(Level.SEVERE, e.getMessage());
333
                }
334
                return (String[]) v.toArray(new String[v.size()]);
335
        }
336
}