Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.plugin / org.gvsig.labeling.app / org.gvsig.labeling.app.mainplugin / src / main / java / org / gvsig / labeling / symbol / SmartTextSymbol.java @ 45526

History | View | Annotate | Download (20 KB)

1
package org.gvsig.labeling.symbol;
2

    
3
import java.awt.BasicStroke;
4
import java.awt.Color;
5
import java.awt.Font;
6
import java.awt.Graphics2D;
7
import java.awt.Rectangle;
8
import java.awt.RenderingHints;
9
import java.awt.Shape;
10
import java.awt.font.FontRenderContext;
11
import java.awt.font.GlyphVector;
12
import java.awt.font.LineMetrics;
13
import java.awt.geom.AffineTransform;
14
import org.apache.commons.lang3.StringUtils;
15

    
16
import org.gvsig.compat.print.PrintAttributes;
17
import org.gvsig.fmap.dal.feature.Feature;
18
import org.gvsig.fmap.geom.Geometry;
19
import org.gvsig.fmap.geom.Geometry.SUBTYPES;
20
import org.gvsig.fmap.geom.Geometry.TYPES;
21
import org.gvsig.fmap.geom.GeometryLocator;
22
import org.gvsig.fmap.geom.GeometryManager;
23
import org.gvsig.fmap.geom.exception.CreateGeometryException;
24
import org.gvsig.fmap.geom.primitive.Envelope;
25
import org.gvsig.fmap.geom.primitive.GeneralPathX;
26
import org.gvsig.fmap.geom.primitive.Point;
27
import org.gvsig.fmap.geom.primitive.Surface;
28
import org.gvsig.fmap.mapcontext.MapContextLocator;
29
import org.gvsig.fmap.mapcontext.ViewPort;
30
import org.gvsig.fmap.mapcontext.rendering.legend.styling.IPlacementConstraints;
31
import org.gvsig.fmap.mapcontext.rendering.symbols.CartographicSupport;
32
import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
33
import org.gvsig.fmap.mapcontext.rendering.symbols.ITextSymbol;
34
import org.gvsig.fmap.mapcontext.rendering.symbols.SymbolDrawingException;
35
import org.gvsig.fmap.mapcontext.rendering.symbols.SymbolPreferences;
36
import org.gvsig.labeling.placements.PointPlacementConstraints;
37
import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.fill.IFillSymbol;
38
import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.text.ISimpleTextSymbol;
39
import org.gvsig.tools.ToolsLocator;
40
import org.gvsig.tools.dynobject.DynStruct;
41
import org.gvsig.tools.persistence.PersistenceManager;
42
import org.gvsig.tools.persistence.PersistentState;
43
import org.gvsig.tools.persistence.exception.PersistenceException;
44
import org.gvsig.tools.task.Cancellable;
45
import org.slf4j.Logger;
46
import org.slf4j.LoggerFactory;
47

    
48
import org.gvsig.symbology.fmap.mapcontext.rendering.legend.styling.TextPath;
49

    
50
        
51
/**
52
 * Class used to create symbols composed using a text defined by
53
 * the user.This text can be edited (changing the color, the font of the characters, and
54
 * the rotation of the text)and has the property that can follow a path.If this path
55
 * does not exist, the text is treated as a simpletextsymbol (when is drawn).
56
 * @author   jaume dominguez faus - jaume.dominguez@iver.es
57
 */
58
public class SmartTextSymbol implements ISimpleTextSymbol, CartographicSupport {
59
        
60
        private static final Logger logger = LoggerFactory.getLogger(
61
                        SmartTextSymbol.class);
62
        // ===========================
63
        public static final String SMART_TEXT_SYMBOL_PERSISTENCE_DEFINITION_NAME =
64
                        "SMART_TEXT_SYMBOL_PERSISTENCE_DEFINITION_NAME";
65
        
66
        private static final String FIELD_UNIT = "unit";
67
        private static final String FIELD_REFERENCE_SYSTEM = "referenceSystem";
68
        private static final String FIELD_IS_SHAPE_VISIBLE = "isShapeVisible";
69
        private static final String FIELD_DESCRIPTION = "description";
70
        private static final String FIELD_TEXT = "text";
71
        private static final String FIELD_FONT = "font";
72
        private static final String FIELD_TEXT_COLOR = "textColor";
73
        private static final String FIELD_ROTATION = "rotation";
74
        private static final String FIELD_AUTO_RESIZE = "autoResize";
75
        // ====================================
76
        private static final String FIELD_HAS_HALO = "hasHalo";
77
        private static final String FIELD_HALO_COLOR = "haloColor";
78
        private static final String FIELD_HALO_WIDTH = "haloWidth";
79
        // ====================================
80
        /*
81
        public static final int SYMBOL_STYLE_TEXTALIGNMENT_LEFT = 0;
82
        public static final int SYMBOL_STYLE_TEXTALIGNMENT_RIGHT = 1;
83
        public static final int SYMBOL_STYLE_TEXTALIGNMENT_CENTERED = 2;
84
        */
85

    
86
        // ===========================
87
        private static GeometryManager geoman = GeometryLocator.getGeometryManager();
88
        
89
        private String text;
90
        private FontRenderContext frc = new FontRenderContext(
91
                        new AffineTransform(), false, true);
92
        
93
        // Background: ITextBackground
94
//        Case
95
        private double characterSpacing;
96
        private double characterWidth;
97
//        Direction
98
        private IFillSymbol fillSymbol;
99
        private double flipAngle;
100
//        boolean kerning;
101
        private double leading;
102
//        Position: textPosition
103
        private Color ShadowColor;
104
        private double ShadowXOffset;
105
        private double ShadowYOffset;
106
//        TypeSetting: Boolean
107
        private double wordSpacing;
108
//        ISimpleTextSymbol : ITextSymbol
109
//        BreakCharacter: Long
110
//        Clip: Boolean
111
        private TextPath textPath;
112
        private double xOffset;
113
        private double yOffset;
114
        private double angle;
115
//        Color: IColor
116

    
117
//        HorizontalAlignment:
118
//        esriTextHorizontalAlignment
119
        private boolean rightToLeft;
120
        //        VerticalAlignment
121
        private double maskSize;
122
//        MaskStyle
123
        private  IFillSymbol maskSymbol;
124
        private double margin;
125
        private int alignment;
126
        private boolean kerning = false;
127
        private TextPath tp;
128
        private IPlacementConstraints constraints;
129
        
130
        private boolean shapeVisible = true;
131
        private int unit = -1;
132
        private int referenceSystem = CartographicSupport.WORLD;
133
        private double rotation = 0;
134
        private String desc = "";
135
        private Color textColor = Color.BLACK;
136
        private Font font;
137
        private boolean autoresize = false;
138
        
139
        // =======================
140
        
141
        private boolean hasHalo = false;
142
        private Color haloColor = Color.WHITE;
143
        private float haloWidth = 3;
144
        private BasicStroke haloStroke = new BasicStroke(
145
                        6, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
146
        
147
        // =======================
148
        
149

    
150
        public SmartTextSymbol(ITextSymbol sym, IPlacementConstraints constraints) {
151

    
152
//                if(sym instanceof SimpleTextSymbol){
153
//                        SimpleTextSymbol mySym = (SimpleTextSymbol)sym;
154

    
155
                        this.setAutoresizeEnabled(sym.isAutoresizeEnabled());
156
                        this.setDescription(sym.getDescription());
157
                        this.setFont(sym.getFont());
158
                        this.setFontSize(sym.getFont().getSize());
159
                        this.setIsShapeVisible(sym.isShapeVisible());
160
                        this.setText(sym.getText());
161
                        this.setTextColor(sym.getTextColor());
162
                        
163
                        this.setDrawWithHalo(sym.isDrawWithHalo());
164
                        this.setHaloColor(sym.getHaloColor());
165
                        this.setHaloWidth(sym.getHaloWidth());
166
                        
167
                        this.constraints = constraints;
168

    
169
                        setCharacterSpacing(2); //???
170
                        setWordSpacing(TextPath.DEFAULT_WORD_SPACING);
171
                        boolean rtl = false; // right to left text
172
                        if (constraints.isAtTheBeginingOfLine()) {
173
                                if (rtl) {
174
                                    
175
                                        setAlignment(ITextSymbol.SYMBOL_STYLE_ALIGNMENT_RIGHT);
176
                                }
177
                                else {
178
                                        setAlignment(ITextSymbol.SYMBOL_STYLE_ALIGNMENT_LEFT);
179
                                }
180
                        }
181
                        else if (constraints.isAtTheEndOfLine()) {
182
                                if (rtl) {
183
                                        setAlignment(ITextSymbol.SYMBOL_STYLE_ALIGNMENT_LEFT);
184
                                }
185
                                else {
186
                                        setAlignment(ITextSymbol.SYMBOL_STYLE_ALIGNMENT_RIGHT);
187
                                }
188
                        }
189
                        else { //constraints.isInTheMiddleOfLine() or constraints.isAtBestOfLine()
190
                                setAlignment(ITextSymbol.SYMBOL_STYLE_ALIGNMENT_CENTERED);
191
                        }
192
                        setKerning(false);
193
                        setRightToLeft(rtl);
194
                // }
195
        }
196
        
197
        
198
        public void setIsShapeVisible(boolean v) {
199
                this.shapeVisible = v;
200
        }
201
        
202
        public boolean isShapeVisible() {
203
                return shapeVisible;
204
        }
205
        
206

    
207

    
208
        public SmartTextSymbol() {
209
                PointPlacementConstraints pc = new PointPlacementConstraints();
210
                this.constraints = pc;
211
                
212
                SymbolPreferences preferences =
213
                                MapContextLocator.getSymbolManager().getSymbolPreferences();
214
                font = preferences.getDefaultSymbolFont();
215
                textColor = preferences.getDefaultSymbolColor();
216
        }
217

    
218
        /**
219
         * Draws the text according. If this symbol has the text path set, then
220
         * it is used as the text line, otherwise shp <b>must be an FPoint2D</b>
221
         * indicating the starting point of the text and then the text will
222
         * be rendered from there and following the rotation previously set.
223
         */
224
        
225
        public void draw(Graphics2D g, AffineTransform affineTransform,
226
                        Geometry geom, Feature f, Cancellable cancel) {
227
        
228
                if (!isShapeVisible()) return;
229

    
230
                setMargin(0);
231
                if ( StringUtils.isEmpty(text) ) {
232
                    return;
233
                }
234

    
235
                char[] text_chars = text.toCharArray();
236
                tp = new TextPath(g, geom, text_chars, getFont(),
237
                                (float) characterSpacing, (float) characterWidth, kerning,
238
                                (float) leading, alignment, (float) wordSpacing, (float) margin, rightToLeft);
239
                Font font = getFont();
240
                g.setFont(font);
241
                FontRenderContext frc = g.getFontRenderContext();
242
                LineMetrics lineMetrics = font.getLineMetrics(getText(), frc);
243
                
244
//                GlyphVector glyph =  font.layoutGlyphVector(frc, charText, 0, charText.length, Font.LAYOUT_NO_START_CONTEXT);
245
                double cons = 0;
246

    
247
                /* Repartimos el leading (espacio de separaci?n entre lineas)
248
                 * arriba y abajo para que exista la misma separaci?n entre la
249
                 * caja de la letra y la linea tanto si se dibuja por abajo como
250
                 * si se dibuja por arriba. 
251
                 */
252
                if(this.constraints.isAboveTheLine()) {
253
                        cons = lineMetrics.getDescent()+lineMetrics.getLeading()/2;
254
                }
255
                else if (this.constraints.isBelowTheLine()) {
256
                        cons = -(lineMetrics.getAscent()+lineMetrics.getLeading()/2);
257
                }
258
                /* Dibujamos la letra de tal manera que el centro de la caja de letra
259
                 * coincida con la linea
260
                 */
261
                else if(this.constraints.isOnTheLine()) {
262
//                        cons = lineMetrics.getDescent()+(lineMetrics.getLeading()/2)-(lineMetrics.getHeight()/2);
263
                        cons = lineMetrics.getDescent()+lineMetrics.getLeading()-(lineMetrics.getHeight()/2);
264
                }
265
                
266
                double[] coords = null; // tp.nextPosForGlyph(0);
267

    
268
                for (int i = 0; i < tp.getGlyphCount(); i++) {
269
                        coords = tp.nextPosForGlyph(i);
270
                        if (coords[0] == TextPath.NO_POS || coords[1] == TextPath.NO_POS)
271
                                continue;
272

    
273
                        // move the label 'cons" units above/below the line
274
                        double xOffset = cons * Math.sin(coords[2]);
275
                        double yOffset = cons * Math.cos(coords[2]);
276

    
277
                        g.translate(coords[0]+xOffset, coords[1]-yOffset);
278
                        g.rotate(coords[2]);
279

    
280
                        char[] aux = new char[1];
281
                        aux[0] = text_chars[i];
282
                        if (isDrawWithHalo()) {
283
                                GlyphVector glyph = font.createGlyphVector(frc, aux);
284
                                Shape outlineChar = glyph.getOutline();
285
                                g.setStroke(haloStroke);
286
                                g.setColor(getHaloColor());
287
                                
288
                                g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
289
                                                RenderingHints.VALUE_ANTIALIAS_ON);
290
                                g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
291
                                                RenderingHints.VALUE_INTERPOLATION_BILINEAR);
292
                                // =============================
293
                                g.draw(outlineChar);
294
                                // =============================
295
                                g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
296
                                                RenderingHints.VALUE_ANTIALIAS_OFF);
297
                        }
298
                        
299
                        g.setColor(this.getTextColor());
300
                        g.drawString(String.valueOf(text_chars[i]), 0, 0);
301
                        g.rotate(-coords[2]);
302
                        g.translate(-coords[0]-xOffset, -coords[1]+yOffset);
303
                }
304
        }
305

    
306
        public void getPixExtentPlus(
307
                        Geometry shp, float[] distances, ViewPort viewPort, int dpi) {
308
                
309
                /*
310
                 * TODO Is this used?
311
                 */
312
                distances[0] = 0;
313
                distances[1] = 0;
314
                // throw new RuntimeException("Not yet implemented!");
315
        }
316

    
317
        public int getOnePointRgb() {
318
                return getTextColor().getRGB();
319
        }
320

    
321
        /*
322
        public XMLEntity getXMLEntity() {
323
                XMLEntity xml = new XMLEntity();
324
                xml.putProperty("className", getClassName());
325
                xml.putProperty("desc", getDescription());
326
                xml.putProperty("isShapeVisible", isShapeVisible());
327
                return xml;
328
        }
329
        */
330

    
331
        public int getSymbolType() {
332
                return Geometry.TYPES.GEOMETRY;
333
        }
334

    
335
        public boolean isSuitableFor(Geometry geom) {
336
                return geom.getGeometryType().isTypeOf(TYPES.CURVE);
337
        }
338
        
339
        public void drawInsideRectangle(
340
                        Graphics2D g,
341
                        AffineTransform scaleInstance,
342
                        Rectangle r,
343
                        PrintAttributes properties) throws SymbolDrawingException {
344
                // let's take the bottom segment of the rectangle as the line
345
                
346
                Surface surf = null;
347
                try {
348
                        surf = geoman.createSurface(SUBTYPES.GEOM2D);
349
                } catch (CreateGeometryException e) {
350
                        logger.info("Error while creating surface.", e);
351
                        throw new SymbolDrawingException(
352
                                        SymbolDrawingException.UNSUPPORTED_SET_OF_SETTINGS);
353
                }
354
                surf.addVertex(r.getX(), r.getY());
355
                surf.addVertex(r.getX() + r.getWidth(), r.getY());
356
                
357
                if (properties == null) {
358
                        draw(g, scaleInstance, surf, null, null);
359
                } else {
360
                        print(g, scaleInstance, surf, properties);
361
                }
362
        }
363

    
364

    
365
        /*
366
        public void setXMLEntity(XMLEntity xml) {
367
                setFont(new Font("Arial", Font.PLAIN, 18));
368
                setText("this is my TEST text that follows a line");
369
                setDescription(xml.getStringProperty("desc"));
370
                setIsShapeVisible(xml.getBooleanProperty("isShapeVisible"));
371

372
        }
373
        */
374

    
375
        public void setText(String txt) {
376
                this.text = txt;
377
        }
378

    
379
        public String getText() {
380
                return text;
381
        }
382

    
383
        public void setCharacterSpacing(double charSpacing) {
384
                this.characterSpacing = charSpacing;
385
        }
386

    
387
        public void setWordSpacing(double wordSpacing) {
388
                this.wordSpacing = wordSpacing;
389
        }
390

    
391
        public void setAlignment(int alignment) {
392
                this.alignment = alignment;
393
        }
394

    
395
        public void setKerning(boolean kerning) {
396
                this.kerning = kerning;
397
        }
398

    
399
        public void setMargin(double margin) {
400
                this.margin = margin;
401
        }
402

    
403
        public void setRightToLeft(boolean rightToLeft) {
404
                this.rightToLeft = rightToLeft;
405
        }
406
        
407
        // ==============================================
408
        // ==============================================
409
        // ==============================================
410

    
411
        
412
        public ISymbol getSymbolForSelection() {
413
                return this;
414
        }
415

    
416
        public boolean isOneDotOrPixel(Geometry geom,
417
                        double[] positionOfDotOrPixel, ViewPort viewPort, int dpi) {
418
                
419
                int type = geom.getType();
420
                switch (type) {
421
                case Geometry.TYPES.NULL:
422
                case Geometry.TYPES.POINT:
423
                case Geometry.TYPES.MULTIPOINT:
424
                        return false;
425
                default:
426
                        Envelope geomBounds = geom.getEnvelope();
427
                        double dist1Pixel = viewPort.getDist1pixel();
428

    
429
                        float[] distances = new float[2];
430
                        this.getPixExtentPlus(geom, distances, viewPort, dpi);
431

    
432
                        boolean onePoint =
433
                                        ((geomBounds.getLength(0) + distances[0] <= dist1Pixel)
434
                                        && (geomBounds.getLength(1) + distances[1] <= dist1Pixel));
435

    
436
                        if (onePoint) {
437
                                positionOfDotOrPixel[0] = geomBounds.getMinimum(0);
438
                                positionOfDotOrPixel[1] = geomBounds.getMinimum(1);
439
                        }
440
                        return onePoint;
441
                }
442
        }
443
        
444

    
445

    
446
        public String getDescription() {
447
                return desc;
448
        }
449

    
450

    
451
        public void setDescription(String d) {
452
                desc = d;
453
        }
454

    
455

    
456
        public Color getColor() {
457
                return this.getTextColor();
458
        }
459

    
460

    
461
        public void setColor(Color color) {
462
                this.setTextColor(color);
463
        }
464

    
465

    
466
        public void print(Graphics2D g, AffineTransform at, Geometry geom,
467
                        PrintAttributes properties) {
468
                
469
                /*
470
                 * TODO Use properties
471
                 * (perhaps when using things of CartographicSupport)
472
                 */
473
                this.draw(g,  at, geom, null, null);
474
        }
475

    
476

    
477
        public void setFont(Font fnt) {
478
                this.font = fnt;
479
        }
480

    
481

    
482
        public Font getFont() {
483
                return font;
484
        }
485

    
486

    
487
        public Color getTextColor() {
488
                return this.textColor;
489
        }
490

    
491

    
492
        public void setTextColor(Color color) {
493
                this.textColor = color;
494
        }
495

    
496

    
497
        public void setFontSize(double d) {
498
                Font newFont = new Font(
499
                                font.getName(),
500
                                font.getStyle(),
501
                                Math.round((float) d));
502
                this.font = newFont;                
503
        }
504

    
505

    
506
        public Geometry getTextWrappingShape(Point p) {
507
                
508
                Font font = getFont();
509
                GlyphVector gv = font.createGlyphVector(frc, text);
510

    
511
                Shape shape = gv.getOutline((float) p.getX(), (float) p.getY());
512
                Geometry myFShape;
513
                try {
514
                        myFShape = geoman.createSurface(new GeneralPathX(shape
515
                                        .getBounds2D().getPathIterator(null)), SUBTYPES.GEOM2D);
516
                        myFShape.transform(AffineTransform.getTranslateInstance(p.getX(), p.getY()));
517

    
518
                        if (rotation != 0) {
519
                                myFShape.transform(AffineTransform.getRotateInstance(rotation));
520
                        }
521
                        return myFShape;
522
                } catch (CreateGeometryException e) {
523
                        logger.error("Error creating a surface", e);
524
                }
525
                return null;
526
        }
527

    
528

    
529
        public Rectangle getBounds() {
530
                
531
                Rectangle bounds = null;
532
                try {
533
                        Geometry aux = getTextWrappingShape(geoman.createPoint(0,0, SUBTYPES.GEOM2D));
534
                        Envelope env = aux.getEnvelope();
535
                        bounds = new Rectangle(
536
                                        (int) env.getMinimum(0),
537
                                        (int) env.getMinimum(1),
538
                                        (int) env.getLength(0),
539
                                        (int) env.getLength(1));
540
                } catch (CreateGeometryException e) {
541
                        logger.error("Error creating a point", e);
542
                }
543
                return bounds;
544
        }
545

    
546
        public double getRotation() {
547
                return this.rotation;
548
        }
549

    
550

    
551
        public void setRotation(double rot) {
552
                this.rotation = rot;
553
        }
554

    
555
        public void setAutoresizeEnabled(boolean ar) {
556
                autoresize = ar;
557
        }
558

    
559

    
560
        public boolean isAutoresizeEnabled() {
561
                return autoresize;
562
        }
563

    
564

    
565
        public Color getHaloColor() {
566
                return this.haloColor;
567
        }
568

    
569

    
570
        public void setHaloColor(Color co) {
571
                this.haloColor = co;
572
        }
573

    
574

    
575
        public float getHaloWidth() {
576
                return this.haloWidth;
577
        }
578

    
579

    
580
        public void setHaloWidth(float w) {
581
                this.haloWidth = w;
582
                this.haloStroke = new BasicStroke(
583
                                2*haloWidth, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
584
        }
585

    
586

    
587
        public boolean isDrawWithHalo() {
588
                return this.hasHalo;
589
        }
590

    
591

    
592
        public void setDrawWithHalo(boolean h) {
593
                this.hasHalo = h;
594
        }
595

    
596
        // ==============================
597

    
598

    
599
        public void setUnit(int unitIndex) {
600
                unit = unitIndex;
601
        }
602

    
603

    
604
        public int getUnit() {
605
                return unit;
606
        }
607

    
608

    
609
        public int getReferenceSystem() {
610
                return this.referenceSystem;
611
        }
612

    
613

    
614
        public void setReferenceSystem(int rs) {
615
                this.referenceSystem = rs;
616
        }
617

    
618

    
619
        public void setCartographicSize(double cartographicSize, Geometry geom) {
620
                setFontSize(cartographicSize);
621
        }
622

    
623
        public double toCartographicSize(ViewPort viewPort, double dpi, Geometry geom) {
624
                double oldSize = getFont().getSize();
625
                setCartographicSize(getCartographicSize(viewPort, dpi, geom), geom);
626
                return oldSize;
627
        }
628

    
629
        public double getCartographicSize(ViewPort viewPort, double dpi, Geometry geom) {
630
                return SymbolUtils.        getCartographicLength(
631
                                this, getFont().getSize(), viewPort, dpi);
632
        }
633

    
634
        // ========================
635
        
636
        public Object clone() throws CloneNotSupportedException {
637
                return super.clone();
638
        }
639
        
640
        // ==========================
641
        
642
        public static void registerPersistent() {
643
                PersistenceManager manager = ToolsLocator.getPersistenceManager();
644
                if( manager.getDefinition(SMART_TEXT_SYMBOL_PERSISTENCE_DEFINITION_NAME)==null ) {
645
                        DynStruct definition = manager.addDefinition(
646
                                        SmartTextSymbol.class,
647
                                        SMART_TEXT_SYMBOL_PERSISTENCE_DEFINITION_NAME,
648
                                        SMART_TEXT_SYMBOL_PERSISTENCE_DEFINITION_NAME+" Persistence definition",
649
                                        null, 
650
                                        null
651
                        );
652
                        
653
                        definition.addDynFieldString(FIELD_DESCRIPTION).setMandatory(true);
654
                        definition.addDynFieldBoolean(FIELD_IS_SHAPE_VISIBLE).setMandatory(true);
655
                        definition.addDynFieldInt(FIELD_REFERENCE_SYSTEM).setMandatory(true);
656
                        definition.addDynFieldInt(FIELD_UNIT).setMandatory(true);
657
                        definition.addDynFieldBoolean(FIELD_AUTO_RESIZE).setMandatory(true);
658
                        definition.addDynFieldObject(FIELD_FONT).setClassOfValue(Font.class).setMandatory(true);
659
                        definition.addDynFieldDouble(FIELD_ROTATION).setMandatory(true);
660
                        definition.addDynFieldString(FIELD_TEXT).setMandatory(true);
661
                        definition.addDynFieldObject(FIELD_TEXT_COLOR).setClassOfValue(Color.class).setMandatory(true);
662
                        // halo
663
                        definition.addDynFieldBoolean(FIELD_HAS_HALO).setMandatory(true);
664
                        definition.addDynFieldObject(FIELD_HALO_COLOR).setClassOfValue(
665
                                        Color.class).setMandatory(true);
666
                        definition.addDynFieldFloat(FIELD_HALO_WIDTH).setMandatory(true);
667
                }
668
                
669
        }
670
        
671
        public void loadFromState(PersistentState state)
672
                        throws PersistenceException {
673
                setDescription(state.getString(FIELD_DESCRIPTION));
674
                setIsShapeVisible(state.getBoolean(FIELD_IS_SHAPE_VISIBLE));
675
                setReferenceSystem(state.getInt(FIELD_REFERENCE_SYSTEM));
676
                setUnit(state.getInt(FIELD_UNIT));
677
                
678
                setAutoresizeEnabled(state.getBoolean(FIELD_AUTO_RESIZE));
679
                setFont((Font) state.get(FIELD_FONT));
680
                setRotation(state.getDouble(FIELD_ROTATION));
681
                setText(state.getString(FIELD_TEXT));
682
                setTextColor((Color) state.get(FIELD_TEXT_COLOR));
683
                // halo
684
                this.setDrawWithHalo(state.getBoolean(FIELD_HAS_HALO));
685
                this.setHaloColor((Color) state.get(FIELD_HALO_COLOR));
686
                this.setHaloWidth(state.getFloat(FIELD_HALO_WIDTH));
687
        }
688

    
689
        public void saveToState(PersistentState state) throws PersistenceException {
690
                state.set(FIELD_DESCRIPTION, getDescription());
691
                state.set(FIELD_IS_SHAPE_VISIBLE, isShapeVisible());
692
                state.set(FIELD_REFERENCE_SYSTEM, getReferenceSystem());
693
                state.set(FIELD_UNIT, getUnit());
694
                
695
                state.set(FIELD_AUTO_RESIZE, isAutoresizeEnabled());
696
                state.set(FIELD_FONT, getFont());
697
                state.set(FIELD_ROTATION, getRotation());
698
                state.set(FIELD_TEXT, getText());
699
                state.set(FIELD_TEXT_COLOR, getTextColor());
700
                // halo
701
                state.set(FIELD_HAS_HALO, this.isDrawWithHalo());
702
                state.set(FIELD_HALO_COLOR, this.getHaloColor());
703
                state.set(FIELD_HALO_WIDTH, this.getHaloWidth());
704
        }
705

    
706

    
707

    
708

    
709

    
710
}