Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.library / org.gvsig.symbology / org.gvsig.symbology.lib / org.gvsig.symbology.lib.impl / src / main / java / org / gvsig / symbology / fmap / mapcontext / rendering / symbol / style / SimpleLabelStyle.java @ 40687

History | View | Annotate | Download (13.3 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
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 3
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
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
24
package org.gvsig.symbology.fmap.mapcontext.rendering.symbol.style;
25

    
26
import java.awt.Color;
27
import java.awt.Dimension;
28
import java.awt.Graphics2D;
29
import java.awt.Rectangle;
30
import java.awt.geom.Point2D;
31
import java.awt.geom.Rectangle2D;
32
import java.util.ArrayList;
33
import java.util.List;
34

    
35
import org.gvsig.fmap.geom.Geometry.SUBTYPES;
36
import org.gvsig.fmap.geom.Geometry.TYPES;
37
import org.gvsig.fmap.geom.GeometryLocator;
38
import org.gvsig.fmap.geom.exception.CreateEnvelopeException;
39
import org.gvsig.fmap.geom.primitive.Envelope;
40
import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
41
import org.gvsig.fmap.mapcontext.rendering.symbols.SymbolDrawingException;
42
import org.gvsig.fmap.mapcontext.rendering.symbols.styles.IBackgroundFileStyle;
43
import org.gvsig.fmap.mapcontext.rendering.symbols.styles.ILabelStyle;
44
import org.gvsig.i18n.Messages;
45
import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.fill.impl.SimpleFillSymbol;
46
import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.line.impl.SimpleLineSymbol;
47
import org.gvsig.tools.ToolsLocator;
48
import org.gvsig.tools.dynobject.DynStruct;
49
import org.gvsig.tools.locator.LocatorException;
50
import org.gvsig.tools.persistence.PersistenceManager;
51
import org.gvsig.tools.persistence.PersistentState;
52
import org.gvsig.tools.persistence.exception.PersistenceException;
53
import org.gvsig.tools.util.Callable;
54
import org.slf4j.Logger;
55
import org.slf4j.LoggerFactory;
56

    
57

    
58
/**
59
 * Implements a style for the creation of simple labels.
60
 *
61
 * @author   jaume dominguez faus - jaume.dominguez@iver.es
62
 */
63
public class SimpleLabelStyle extends AbstractStyle implements ILabelStyle {
64
        
65
        private static Logger logger = LoggerFactory.getLogger(SimpleLabelStyle.class);
66
        
67
        public static final String SIMPLE_LABEL_STYLE_PERSISTENCE_NAME =
68
                        "SIMPLE_LABEL_STYLE_PERSISTENCE_NAME";
69
        
70
        private Point2D markerPoint = new Point2D.Double();
71
        // conertir a?? a Rectangle2D[] ja que pot arribar a gastar-se massivament
72
        // en el pintat
73
        private List<Rectangle2D> textFieldAreas = new ArrayList<Rectangle2D>();
74
        private IBackgroundFileStyle background;
75
        private Dimension defaultSize = new Dimension(32,32);
76
        private Dimension sz;
77

    
78

    
79

    
80
        public int getFieldCount() {
81
                return textFieldAreas.size();
82
        }
83

    
84
        public void setTextFields(String[] texts) {
85
                StringBuffer sb = new StringBuffer();
86
                for (int i = 0; texts != null && i < texts.length; i++) {
87
                        sb.append(texts[i]);
88
                        if (i<texts.length)
89
                                sb.append(" ");
90
                }
91
        }
92

    
93
        public boolean isSuitableFor(ISymbol symbol) {
94
                return true;
95
        }
96

    
97
        public String getClassName() {
98
                return getClass().getName();
99
        }
100

    
101
        /*
102
        public XMLEntity getXMLEntity() {
103
                XMLEntity xml = new XMLEntity();
104
                xml.putProperty("className", getClassName());
105
                xml.putProperty("desc", getDescription());
106
                xml.putProperty("markerPointX", markerPoint.getX());
107
                xml.putProperty("markerPointY", markerPoint.getY());
108

109
                int size = getFieldCount();
110
                String[] minx = new String[size];
111
                String[] miny = new String[size];
112
                String[] widths = new String[size];
113
                String[] heights = new String[size];
114

115
                Rectangle2D[] rects = getTextBounds();
116
                for (int i = 0; i < rects.length; i++) {
117
                        minx[i] = String.valueOf(rects[i].getMinX());
118
                        miny[i] = String.valueOf(rects[i].getMinY());
119
                        widths[i] = String.valueOf(rects[i].getWidth());
120
                        heights[i] = String.valueOf(rects[i].getHeight());
121
                }
122

123
                xml.putProperty("minXArray", minx);
124
                xml.putProperty("minYArray", miny);
125
                xml.putProperty("widthArray", widths);
126
                xml.putProperty("heightArray", heights);
127
                if(getBackgroundFileStyle() != null){
128
                        XMLEntity bgXML = getBackgroundFileStyle().getXMLEntity();
129
                        bgXML.putProperty("id", "LabelStyle");
130
                        xml.addChild(bgXML);
131
                }
132
                if (sz!=null){
133
                        xml.putProperty("sizeW",(int)sz.getWidth());
134
                        xml.putProperty("sizeH",(int)sz.getHeight());
135
                }
136
                return xml;
137
        }
138

139
        public void setXMLEntity(XMLEntity xml) {
140
                setDescription(xml.getStringProperty("desc"));
141

142
                double x = xml.getDoubleProperty("markerPointX");
143
                double y = xml.getDoubleProperty("markerPointY");
144

145
                double[] minx = xml.getDoubleArrayProperty("minXArray");
146
                double[] miny = xml.getDoubleArrayProperty("minYArray");
147
                double[] widths = xml.getDoubleArrayProperty("widthArray");
148
                double[] heights = xml.getDoubleArrayProperty("heightArray");
149

150
                textFieldAreas.clear();
151
                for (int i = 0; i < minx.length; i++) {
152
                        addTextFieldArea(new Rectangle2D.Double(
153
                                        minx[i],
154
                                        miny[i],
155
                                        widths[i],
156
                                        heights[i]));
157
                }
158
                markerPoint.setLocation(x, y);
159
                XMLEntity bgXML = xml.firstChild("id", "LabelStyle");
160
                if (bgXML!=null) {
161
                        background = (BackgroundFileStyle) SymbologyFactory.createStyleFromXML(xml.getChild(0), null);
162
                }
163
                if (xml.contains("sizeW"))
164
                        sz=new Dimension(xml.getIntProperty("sizeW"),xml.getIntProperty("sizeH"));
165
                
166
        }
167
        */
168

    
169
        public Rectangle2D[] getTextBounds() {
170
                return (Rectangle2D[]) textFieldAreas.toArray(new Rectangle2D[textFieldAreas.size()]);
171
        }
172

    
173
        public void drawInsideRectangle(Graphics2D g, Rectangle r)
174
                        throws SymbolDrawingException {
175
                if(getBackgroundFileStyle() != null)
176
                        getBackgroundFileStyle().drawInsideRectangle(g, r);
177
        }
178

    
179

    
180
        public Dimension getSize() {
181
                if (sz == null && getBackgroundFileStyle() != null) {
182
                        Rectangle bgBounds = getBackgroundFileStyle().getBounds();
183
                        setSize(bgBounds.getWidth(), bgBounds.getHeight());
184
                }else if (sz==null)
185
                        sz = defaultSize;
186
                return sz;
187
        }
188

    
189
        public Point2D getMarkerPoint() {
190
                return markerPoint;
191
        }
192

    
193
        public void setMarkerPoint(Point2D p) throws IllegalArgumentException {
194
                if (p.getX()<0 || p.getX()>1)
195
                        throw new IllegalArgumentException("X must be >=0 and <=1 ("+p.getX()+")");
196
                if (p.getY()<0 || p.getY()>1)
197
                        throw new IllegalArgumentException("Y must be >=0 and <=1 ("+p.getY()+")");
198
                // the marker represents the point labeled in relative percent units
199
                this.markerPoint = p;
200
        }
201

    
202

    
203
        public void drawOutline(Graphics2D g, Rectangle r) throws SymbolDrawingException {
204
                if(getBackgroundFileStyle() != null)
205
                        getBackgroundFileStyle().drawOutline(g, r);
206

    
207
                final double[] xy = new double[2];
208
                // draw the pointer
209
                {
210
                        xy[0] = markerPoint.getX();
211
                        xy[1] = markerPoint.getY();
212

    
213
                        int x = (int) Math.round(r.width * xy[0]);
214
                        int y = (int) Math.round(r.height * xy[1]);
215

    
216
                        int size = 7;
217
                        g.setColor(Color.ORANGE.darker());
218
                        g.fillOval(x, y, size, size);
219
                        g.setColor(Color.BLACK.brighter());
220
                        g.drawString(Messages.getText("labeled_point"), x + size + 10, y + size);
221
                        g.setColor(Color.BLACK);
222
                        g.drawLine(x-size, (int) (y+(size*0.5)), x+2*size-1, (int) (y+(size*0.5)));
223
                        g.drawLine((int) (x+(size*0.5)), y-size, (int) (x+(size*0.5)), y+2*size-1);
224
                }
225

    
226
                // draw the text fields
227
                if (textFieldAreas.size() > 0) {
228
                        SimpleFillSymbol sym = new SimpleFillSymbol();
229
                        Color c = Color.blue.brighter().brighter();
230

    
231
                        sym.setFillColor(new Color(c.getRed(), c.getGreen(), c.getBlue(), 100));
232
                        SimpleLineSymbol outline = new SimpleLineSymbol();
233
                        c = Color.BLACK;
234
                        outline.setLineColor(new Color(c.getRed(), c.getGreen(), c.getBlue(), 100));
235
                        sym.setOutline(outline);
236
                        for (int i = 0; i < textFieldAreas.size(); i++) {
237
                                //FIXME: Esto es un parche, habr?a que cambiar el API de los simbolos y/o estilos
238
                                //pero mientras tanto
239
                                if(getBackgroundFileStyle() == null){
240
                                        Rectangle2D textFieldArea = (Rectangle2D) textFieldAreas.get(i);
241
                                        xy[0] = textFieldArea.getX();
242
                                        xy[1] = textFieldArea.getY();
243

    
244
                                        int x = (int) Math.round(((r.width) * xy[0]));
245
                                        int y = (int) Math.round((r.height) * xy[1]);
246

    
247
                                        xy[0] = textFieldArea.getMaxX();
248
                                        xy[1] = textFieldArea.getMaxY();
249

    
250
                                        int width = (int) Math.round((r.width * xy[0]) -x);
251
                                        int height = (int) Math.round((r.height * xy[1]) - y) ;
252

    
253
                                        Envelope env = null;
254
                                        try {
255
                                                env = GeometryLocator.getGeometryManager().
256
                                                                createEnvelope(x, y, x+width, y+height, SUBTYPES.GEOM2D);
257
                                        } catch (Exception e) {
258
                                                logger.error("While creating envelope", e);
259
                                                throw new SymbolDrawingException(TYPES.SURFACE);
260
                                        }
261
                                        
262
                                        sym.draw(g, null, env.getGeometry(), null, null);
263
                                        g.setColor(Color.BLACK);
264
                                        g.drawString(String.valueOf(i+1), x+5, y + 10); // start with 1
265
                                } else {
266
                                        double xOffset = 0;
267
                                        double yOffset = 0;
268
                                        double scale = 1;
269
                                        Dimension backgroundBounds = getSize();
270
                                        if (backgroundBounds.getWidth()>backgroundBounds.getHeight()) {
271
                                                scale = r.getWidth()/backgroundBounds.getWidth();
272
                                                yOffset = 0.5*(r.getHeight() - backgroundBounds.getHeight()*scale);
273
                                        } else {
274
                                                scale = r.getHeight()/backgroundBounds.getHeight();
275
                                                xOffset = 0.5*(r.getWidth() - backgroundBounds.getWidth()*scale);
276
                                        }
277

    
278
                                        Rectangle2D textFieldArea = (Rectangle2D) textFieldAreas.get(i);
279
                                        xy[0] = textFieldArea.getX();
280
                                        xy[1] = textFieldArea.getY();
281

    
282
                                        int x = (int) Math.round(xy[0]*backgroundBounds.getWidth()*scale+xOffset);
283
                                        int y = (int) Math.round(xy[1]*backgroundBounds.getHeight()*scale+yOffset);
284

    
285
                                        xy[0] = textFieldArea.getMaxX();
286
                                        xy[1] = textFieldArea.getMaxY();
287

    
288
                                        int width = (int) Math.round((xy[0]*backgroundBounds.getWidth()*scale+xOffset)-x);
289
                                        int height = (int) Math.round((xy[1]*backgroundBounds.getHeight()*scale+yOffset)-y);
290

    
291
                                        Envelope env = null;
292
                                        try {
293
                                                env = GeometryLocator.getGeometryManager().
294
                                                                createEnvelope(x, y, x+width, y+height, SUBTYPES.GEOM2D);
295
                                        } catch (Exception e) {
296
                                                logger.error("While creating envelope", e);
297
                                                throw new SymbolDrawingException(TYPES.SURFACE);
298
                                        }
299
                                        
300
                                        sym.draw(g, null, env.getGeometry(), null, null);
301
                                        g.setColor(Color.BLACK);
302
                                        g.drawString(String.valueOf(i+1), x+5, y + 10); // start with 1
303

    
304
                                }
305
                        }
306
                }
307
        }
308

    
309
        public void setTextFieldArea(int index, Rectangle2D rect) {
310
                textFieldAreas.set(index, rect);
311
        }
312

    
313
        public void addTextFieldArea(Rectangle2D rect) {
314
                textFieldAreas.add(rect);
315
        }
316

    
317
        public void deleteTextFieldArea(int index) {
318
                textFieldAreas.remove(index);
319
        }
320

    
321
        public void setSize(double width, double height) {
322
                sz = new Dimension( (int) Math.round(width), (int) Math.round(height));
323
        }
324

    
325
        public IBackgroundFileStyle getBackgroundFileStyle() {
326
                return background;
327
        }
328

    
329
        public void setBackgroundFileStyle(IBackgroundFileStyle bg) {
330
                this.background = bg;
331
        }
332

    
333
        public static class RegisterPersistence implements Callable {
334

    
335
                public Object call() throws Exception {
336

    
337
                        PersistenceManager manager = ToolsLocator.getPersistenceManager();
338
                        DynStruct definition = manager.getDefinition(
339
                            SIMPLE_LABEL_STYLE_PERSISTENCE_NAME);
340

    
341
                        if (definition == null){
342
                                definition = manager.addDefinition(
343
                                SimpleLabelStyle.class,
344
                                SIMPLE_LABEL_STYLE_PERSISTENCE_NAME,
345
                                SIMPLE_LABEL_STYLE_PERSISTENCE_NAME + " Persistent definition", 
346
                                null, 
347
                                null);
348
                                definition.extend(manager.getDefinition(
349
                                                AbstractStyle.STYLE_PERSISTENCE_DEFINITION_NAME));
350
                                definition.addDynFieldObject("markerPoint").setClassOfValue(Point2D.class)
351
                                .setMandatory(true);
352
                                definition.addDynFieldList("textFieldAreas").setClassOfItems(Rectangle2D.class)
353
                                .setMandatory(true);
354
                                definition.addDynFieldObject("background").setClassOfValue(IBackgroundFileStyle.class)
355
                                .setMandatory(false);
356
                                definition.addDynFieldObject("defaultSize").setClassOfValue(Dimension.class)
357
                                .setMandatory(true);
358
                                definition.addDynFieldObject("size").setClassOfValue(Dimension.class)
359
                                .setMandatory(true);
360
                        }
361
                        return Boolean.TRUE;
362
                }
363
        }
364
        
365
        
366
        public void loadFromState(PersistentState state)
367
                        throws PersistenceException {
368
                
369
                super.loadFromState(state);
370
                
371
                this.markerPoint = (Point2D) state.get("markerPoint");
372
                this.textFieldAreas = (List<Rectangle2D>) state.get("textFieldAreas");
373
                
374
                if (state.hasValue("background")) {
375
                        this.background = (IBackgroundFileStyle) state.get("background");
376
                }
377
                
378
                this.defaultSize = (Dimension) state.get("defaultSize");
379
                this.sz = (Dimension) state.get("size");
380
        }
381

    
382
        public void saveToState(PersistentState state) throws PersistenceException {
383

    
384
                super.saveToState(state);
385
                
386
                state.set("markerPoint", this.markerPoint);
387
                state.set("textFieldAreas", this.textFieldAreas);
388
                
389
                if (this.background != null) {
390
                        state.set("background", this.background);
391
                }
392
                
393
                state.set("defaultSize", this.defaultSize);
394
                state.set("size", this.getSize());
395
        }
396
}