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 / marker / impl / PictureMarkerSymbol.java @ 47790

History | View | Annotate | Download (13 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.marker.impl;
25

    
26
import java.awt.Color;
27
import java.awt.Graphics2D;
28
import java.awt.Rectangle;
29
import java.awt.geom.AffineTransform;
30
import java.awt.geom.Point2D;
31
import java.io.IOException;
32
import java.net.URL;
33
import org.gvsig.fmap.dal.exception.DataException;
34
import org.gvsig.fmap.dal.feature.Feature;
35
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
36
import org.gvsig.fmap.dal.feature.FeatureStore;
37
import org.gvsig.fmap.dal.feature.FeatureType;
38
import org.gvsig.fmap.geom.Geometry;
39
import org.gvsig.fmap.geom.primitive.Point;
40
import org.gvsig.fmap.mapcontext.MapContextLocator;
41
import org.gvsig.fmap.mapcontext.rendering.symbols.CartographicSupport;
42
import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
43
import org.gvsig.fmap.mapcontext.rendering.symbols.SymbolDrawingException;
44
import org.gvsig.fmap.mapcontext.rendering.symbols.SymbolManager;
45
import org.gvsig.i18n.Messages;
46
import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.marker.IPictureMarkerSymbol;
47
import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.style.BackgroundFileStyle;
48
import org.gvsig.tools.ToolsLocator;
49
import org.gvsig.tools.dynobject.DynStruct;
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.task.Cancellable;
54
import org.gvsig.tools.util.Callable;
55
import org.slf4j.Logger;
56
import org.slf4j.LoggerFactory;
57

    
58
/**
59
 * PictureMarkerSymbol allows to use an image file as a definition to be painted
60
 * instead of a marker symbol.
61
 */
62
@SuppressWarnings("UseSpecificCatch")
63
public class PictureMarkerSymbol extends AbstractMarkerSymbol implements IPictureMarkerSymbol {
64

    
65
    private final Logger LOG = LoggerFactory.getLogger(PictureMarkerSymbol.class);
66

    
67
    public static final String PICTURE_MARKER_SYMBOL_PERSISTENCE_DEFINITION_NAME
68
            = "PictureMarkerSymbol";
69
    private static final String SELECTED = "selected";
70
    private static final String SELECTION_SYMBOL = "selectionSym";
71
    private static final String BACKGROUND_IMAGE = "bgImage";
72
    private static final String BACKGROUND_SELECTION_IMAGE = "bgSelImage";
73

    
74
    private boolean selected;
75
    private PictureMarkerSymbol selectionSym;
76

    
77
    private BackgroundFileStyle bgImage;
78
    private BackgroundFileStyle bgSelImage;
79

    
80
    public PictureMarkerSymbol() {
81
        super();
82
        setSize(18);
83
    }
84

    
85
    /**
86
     * Constructor method
87
     *
88
     * @param imageURL , URL of the normal image
89
     * @param selImageURL , URL of the image when it is selected in the map
90
     * @throws IOException
91
     */
92
    public PictureMarkerSymbol(URL imageURL, URL selImageURL) throws IOException {
93
        setImage(imageURL);
94
        if (selImageURL != null) {
95
            setSelImage(selImageURL);
96
        } else {
97
            setSelImage(imageURL);
98
        }
99

    
100
    }
101

    
102
    /**
103
     * Sets the file for the image to be used as a marker symbol
104
     *
105
     * @param imageUrl
106
     * @throws IOException
107
     */
108
    @Override
109
    public final void setImage(URL imageUrl) throws IOException {
110
        bgImage = BackgroundFileStyle.createStyleByURL(imageUrl);
111
        bgImage.setSymbolTable(this.getSymbolTable(this.getFeature()));
112
    }
113

    
114
    /**
115
     * Sets the file for the image to be used as a marker symbol (when it is
116
     * selected in the map)
117
     *
118
     * @param imageFileUrl
119
     * @throws IOException
120
     */
121
    @Override
122
    public final void setSelImage(URL imageFileUrl) throws IOException {
123
        bgSelImage = BackgroundFileStyle.createStyleByURL(imageFileUrl);
124
        bgSelImage.setSymbolTable(this.getSymbolTable(this.getFeature()));
125
    }
126

    
127
    @Override
128
    public ISymbol getSymbolForSelection(Color selectionColor) {
129
        if (selectionSym == null) {
130
            try {
131
                selectionSym = (PictureMarkerSymbol) this.clone();
132
                selectionSym.setColor(selectionColor);
133
            } catch (CloneNotSupportedException e) {
134
                LOG.warn("Error creating the selection symbol for the symbol "+ this, e);
135
            }
136
            selectionSym.selected = true;
137
            selectionSym.selectionSym = selectionSym; // avoid too much lazy creations
138
        } else {
139
            selectionSym.setColor(selectionColor);
140
        }
141
        if (selectionSym instanceof CartographicSupport) {
142
            ((CartographicSupport) selectionSym).setUnit(this.getUnit());
143
        }
144

    
145
        return selectionSym;
146
    }
147

    
148
    @Override
149
    public void draw(Graphics2D g, AffineTransform affineTransform, Geometry geom, Feature f, Cancellable cancel, Rectangle r) {
150
        double size_d = getEfectiveSize(f);
151
//        size_d = this.getPrintSize(properties, size_d);
152
        size_d = this.getAdjustedSize(r, size_d);
153
        int size_i = (int) Math.round(size_d);
154
 
155
        if(r != null){
156
            geom = getSampleGeometry(r);
157
        }
158
        Point p;
159
        try {
160
            p = geom.centroid();
161
        } catch (Exception ex) {
162
            return;
163
        }
164
        if (affineTransform != null) {
165
            p.transform(affineTransform);
166
        }
167
        double x, y;
168
        double halfSize = size_d / 2;
169
        x = p.getX() - halfSize;
170
        y = p.getY() - halfSize;
171
        Point2D theOffset = this.getEfectiveOffset(f);
172
        int xOffset = (int) theOffset.getX();
173
        int yOffset = (int) theOffset.getY();
174

    
175
        if (size_i > 0) {
176
            if( isDrawLineToOffset() ) {
177
                g.setColor(this.getEfectiveLineToOffsetColor(f));
178
                g.drawLine((int)p.getX(), (int)p.getY(), (int)p.getX() + xOffset, (int)p.getY() + yOffset);
179
            }
180
            BackgroundFileStyle bg = (!selected) ? bgImage : bgSelImage;
181
            Rectangle rect = new Rectangle(size_i, size_i);
182
            g.translate(x + xOffset, y + yOffset);
183
            double auxRotation = getEfectiveRotationInRadians(f);
184
            g.rotate(auxRotation, halfSize, halfSize);
185
            if (bg != null) {
186
                try {
187
                    bg.setSymbolTable(this.getSymbolTable(f));
188
                    bg.drawInsideRectangle(g, rect);
189
                } catch (SymbolDrawingException e) {
190
                    LOG.warn(Messages.getText("label_style_could_not_be_painted")
191
                            + ": " + bg.getSource().toString(),
192
                            e);
193
                }
194
            } else {
195
                LOG.warn(Messages.getText("label_style_could_not_be_painted")
196
                        + ": bg is Null");
197
            }
198
            g.rotate(-auxRotation, halfSize, halfSize);
199
            g.translate(-(x + xOffset), -(y + yOffset));
200
            
201
        }
202

    
203
    }
204

    
205
//    @Override
206
//    public void drawInsideRectangle(Graphics2D g, AffineTransform scaleInstance, Rectangle r, PrintAttributes properties) throws SymbolDrawingException {
207
//
208
//        /*
209
//         * Marker symbols which are not simple (images, etc)
210
//         * are resized when drawn inside a rectangle
211
//         */
212
//        double saved_size = this.getSize();
213
//        if(this.getSize() > r.getHeight()){
214
//            this.setSize(r.getHeight());
215
//            super.drawInsideRectangle(g, scaleInstance, r, properties);
216
//            this.setSize(saved_size);
217
//        }  else {
218
//            super.drawInsideRectangle(g, scaleInstance, r, properties);
219
//        }
220
//   }
221

    
222
    public String getClassName() {
223
        return getClass().getName();
224
    }
225

    
226
    /**
227
     * Returns the URL of the image that is used as a marker symbol
228
     *
229
     * @return imagePath,URL
230
     */
231
    @Override
232
    public URL getSource() {
233
        return bgImage.getSource();
234
    }
235

    
236
    /**
237
     * Returns the URL of the image that is used as a marker symbol (when it is
238
     * selected in the map)
239
     *
240
     * @return selimagePath,URL
241
     */
242
    @Override
243
    public URL getSelectedSource() {
244
        return bgSelImage.getSource();
245
    }
246

    
247
    @Override
248
    public PictureMarkerSymbol clone() throws CloneNotSupportedException {
249
        PictureMarkerSymbol copy = (PictureMarkerSymbol) super.clone();
250

    
251
        // clone selection
252
        if (selectionSym != null) {
253
            //to avoid an infinite loop
254
            if (this == selectionSym) {
255
                copy.selectionSym = copy;
256
            } else {
257
                copy.selectionSym = (PictureMarkerSymbol) selectionSym.clone();
258
            }
259
        }
260

    
261
        // clone brackground image
262
        if (bgImage != null) {
263
            copy.bgImage = (BackgroundFileStyle) bgImage.clone();
264
        }
265

    
266
        // clone selection brackground image
267
        if (bgSelImage != null) {
268
            copy.bgSelImage = (BackgroundFileStyle) bgSelImage.clone();
269
        }
270
        return copy;
271
    }
272

    
273
    @Override
274
    public void loadFromState(PersistentState state) throws PersistenceException {
275
        // Set parent style properties
276
        super.loadFromState(state);
277

    
278
        this.selected = (Boolean) state.get(SELECTED);
279
        this.selectionSym = (PictureMarkerSymbol) state.get(SELECTION_SYMBOL);
280
        this.bgImage = (BackgroundFileStyle) state.get(BACKGROUND_IMAGE);
281
        this.bgSelImage = (BackgroundFileStyle) state.get(BACKGROUND_SELECTION_IMAGE);
282
    }
283

    
284
    @Override
285
    public void saveToState(PersistentState state) throws PersistenceException {
286
        // Save parent fill symbol properties
287
        super.saveToState(state);
288

    
289
        // Save own properties
290
        state.set(SELECTED, this.selected);
291
        state.set(SELECTION_SYMBOL, this.getSymbolForSelection());
292
        state.set(BACKGROUND_IMAGE, this.bgImage);
293
        state.set(BACKGROUND_SELECTION_IMAGE, this.bgSelImage);
294
    }
295

    
296
    public static class RegisterPersistence implements Callable {
297

    
298
        @Override
299
        public Object call() throws Exception {
300
            PersistenceManager manager = ToolsLocator.getPersistenceManager();
301
            if (manager.getDefinition(PICTURE_MARKER_SYMBOL_PERSISTENCE_DEFINITION_NAME) == null) {
302
                DynStruct definition
303
                        = manager.addDefinition(PictureMarkerSymbol.class,
304
                                PICTURE_MARKER_SYMBOL_PERSISTENCE_DEFINITION_NAME,
305
                                PICTURE_MARKER_SYMBOL_PERSISTENCE_DEFINITION_NAME
306
                                + " Persistence definition",
307
                                null,
308
                                null);
309

    
310
                // Extend the Style base definition
311
                definition.extend(manager.getDefinition(MARKER_SYMBOL_PERSISTENCE_DEFINITION_NAME));
312

    
313
                definition.addDynFieldBoolean(SELECTED).setMandatory(false);
314
                definition.addDynFieldObject(SELECTION_SYMBOL).setMandatory(false)
315
                        .setClassOfValue(PictureMarkerSymbol.class).setMandatory(false);
316
                definition.addDynFieldObject(BACKGROUND_IMAGE)
317
                        .setClassOfValue(BackgroundFileStyle.class).setMandatory(false);
318
                definition.addDynFieldObject(BACKGROUND_SELECTION_IMAGE)
319
                        .setClassOfValue(BackgroundFileStyle.class).setMandatory(false);
320
            }
321
            return true;
322
        }
323
    }
324

    
325
    public static class RegisterSymbol implements Callable {
326

    
327
        @Override
328
        public Object call() throws Exception {
329
            SymbolManager manager = MapContextLocator.getSymbolManager();
330

    
331
            manager.registerSymbol(PictureMarkerSymbol.PICTURE_MARKER_SYMBOL_PERSISTENCE_DEFINITION_NAME,
332
                    PictureMarkerSymbol.class);
333

    
334
            return true;
335
        }
336

    
337
    }
338
 
339
    @Override
340
    public String[] getRequiredFeatureAttributeNames(FeatureStore featureStore) throws DataException {
341
        // By default only need the default Geometry
342
        FeatureType ftype = featureStore.getDefaultFeatureTypeQuietly();
343
        String[] res = new String[ftype.size()];
344
        int cont = 0;
345
        for (FeatureAttributeDescriptor attr : ftype) {
346
            res[cont++]=attr.getName();
347
        }
348
        return res;
349
    }
350

    
351
    @Override
352
    public void setFeature(Feature feature) {
353
        super.setFeature(feature);
354
        if( this.bgImage!=null ) {
355
            this.bgImage.setSymbolTable(this.getSymbolTable(this.getFeature()));
356
        }
357
        if( this.bgSelImage!=null ) {
358
            this.bgSelImage.setSymbolTable(this.getSymbolTable(this.getFeature()));
359
        }
360
    }
361
}