Statistics
| Revision:

root / trunk / extensions / extSymbology / src / org / gvsig / symbology / fmap / symbols / SmartTextSymbol.java @ 20768

History | View | Annotate | Download (14.1 KB)

1
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
2
 *
3
 * Copyright (C) 2005 IVER T.I. and Generalitat Valenciana.
4
 *
5
 * This program is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU General Public License
7
 * as published by the Free Software Foundation; either version 2
8
 * of the License, or (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
18
 *
19
 * For more information, contact:
20
 *
21
 *  Generalitat Valenciana
22
 *   Conselleria d'Infraestructures i Transport
23
 *   Av. Blasco Ib??ez, 50
24
 *   46010 VALENCIA
25
 *   SPAIN
26
 *
27
 *      +34 963862235
28
 *   gvsig@gva.es
29
 *      www.gvsig.gva.es
30
 *
31
 *    or
32
 *
33
 *   IVER T.I. S.A
34
 *   Salamanca 50
35
 *   46005 Valencia
36
 *   Spain
37
 *
38
 *   +34 963163400
39
 *   dac@iver.es
40
 */
41

    
42
/* CVS MESSAGES:
43
*
44
* $Id: SmartTextSymbol.java 13953 2007-09-21 12:26:04Z jaume $
45
* $Log$
46
* Revision 1.6  2007-09-21 12:25:32  jaume
47
* cancellation support extended down to the IGeometry and ISymbol level
48
*
49
* Revision 1.5  2007/08/16 06:55:19  jvidal
50
* javadoc updated
51
*
52
* Revision 1.4  2007/08/13 11:36:50  jvidal
53
* javadoc
54
*
55
* Revision 1.3  2007/03/28 16:48:14  jaume
56
* *** empty log message ***
57
*
58
* Revision 1.2  2007/03/21 17:36:22  jaume
59
* *** empty log message ***
60
*
61
* Revision 1.1  2007/03/09 11:20:56  jaume
62
* Advanced symbology (start committing)
63
*
64
* Revision 1.1.2.8  2007/02/21 07:34:09  jaume
65
* labeling starts working
66
*
67
* Revision 1.1.2.7  2007/02/16 10:54:12  jaume
68
* multilayer splitted to multilayerline, multilayermarker,and  multilayerfill
69
*
70
* Revision 1.1.2.6  2007/02/15 16:23:44  jaume
71
* *** empty log message ***
72
*
73
* Revision 1.1.2.5  2007/02/09 07:47:05  jaume
74
* Isymbol moved
75
*
76
* Revision 1.1.2.4  2007/02/08 07:36:38  jaume
77
* *** empty log message ***
78
*
79
* Revision 1.1.2.3  2007/02/06 16:54:36  jaume
80
* *** empty log message ***
81
*
82
* Revision 1.1.2.2  2007/02/06 16:47:35  jaume
83
* first steps, follows a line
84
*
85
* Revision 1.1.2.1  2007/02/02 16:21:24  jaume
86
* start commiting labeling stuff
87
*
88
* Revision 1.1  2007/01/24 17:58:22  jaume
89
* new features and architecture error fixes
90
*
91
*
92
*/
93
package org.gvsig.symbology.fmap.symbols;
94

    
95
import java.awt.BorderLayout;
96
import java.awt.Color;
97
import java.awt.Dimension;
98
import java.awt.Font;
99
import java.awt.Graphics;
100
import java.awt.Graphics2D;
101
import java.awt.Rectangle;
102
import java.awt.event.ActionEvent;
103
import java.awt.event.ActionListener;
104
import java.awt.geom.AffineTransform;
105
import java.util.ArrayList;
106

    
107
import javax.swing.JCheckBox;
108
import javax.swing.JFrame;
109
import javax.swing.JPanel;
110
import javax.swing.JTextField;
111

    
112
import org.gvsig.gui.beans.swing.GridBagLayoutPanel;
113
import org.gvsig.gui.beans.swing.JComboBoxFonts;
114
import org.gvsig.gui.beans.swing.JIncrementalNumberField;
115

    
116
import com.iver.cit.gvsig.fmap.ViewPort;
117
import com.iver.cit.gvsig.fmap.core.FPolygon2D;
118
import com.iver.cit.gvsig.fmap.core.FPolyline2D;
119
import com.iver.cit.gvsig.fmap.core.FShape;
120
import com.iver.cit.gvsig.fmap.core.GeneralPathX;
121
import com.iver.cit.gvsig.fmap.core.IGeometry;
122
import com.iver.cit.gvsig.fmap.core.SymbologyFactory;
123
import com.iver.cit.gvsig.fmap.core.TextPath;
124
import com.iver.cit.gvsig.fmap.core.symbols.IFillSymbol;
125
import com.iver.cit.gvsig.fmap.core.symbols.ITextSymbol;
126
import com.iver.cit.gvsig.fmap.core.symbols.SimpleTextSymbol;
127
import com.iver.cit.gvsig.fmap.core.symbols.SymbolDrawingException;
128
import com.iver.cit.gvsig.fmap.core.v02.FConstant;
129
import com.iver.utiles.XMLEntity;
130
import com.iver.utiles.swing.JComboBox;
131
import com.iver.utiles.swing.threads.Cancellable;
132
 
133
/**
134
 * Class used to create symbols composed using a text defined by
135
 * the user.This text can be edited (changing the color, the font of the characters, and
136
 * the rotation of the text)and has the property that can follow a path.If this path
137
 * does not exist, the text is treated as a simpletextsymbol (when is drawn).
138
 * @author   jaume dominguez faus - jaume.dominguez@iver.es
139
 */
140
public class SmartTextSymbol extends SimpleTextSymbol implements ITextSymbol {
141
        
142
        private char[] text;
143
//        Background: ITextBackground
144
//        Case
145
        private double characterSpacing;
146
        private double characterWidth;
147
//        Direction
148
        private IFillSymbol fillSymbol;
149
        private double flipAngle;
150
//        boolean kerning;
151
        private double leading;
152
//        Position: textPosition
153
        private Color ShadowColor;
154
        private double ShadowXOffset;
155
        private double ShadowYOffset;
156
//        TypeSetting: Boolean
157
        private double wordSpacing;
158
//        ISimpleTextSymbol : ITextSymbol
159
//        BreakCharacter: Long
160
//        Clip: Boolean
161
        private TextPath textPath;
162
        private double xOffset;
163
        private double yOffset;
164
        private double angle;
165
//        Color: IColor
166

    
167
//        HorizontalAlignment:
168
//        esriTextHorizontalAlignment
169
        private boolean rightToLeft;
170
        //        VerticalAlignment
171
        private double maskSize;
172
//        MaskStyle
173
        private  IFillSymbol maskSymbol;
174
        private double margin;
175
        private int alignment;
176
        private boolean kerning = false;
177
        
178
        /**
179
         * Draws the text according. If this symbol has the text path set, then
180
         * it is used as the text line, otherwise shp <b>must be an FPoint2D</b>
181
         * indicating the starting point of the text and then the text will
182
         * be rendered from there and following the rotation previously set.
183
         */
184
        @Override
185
        public void draw(Graphics2D g, AffineTransform affineTransform, FShape shp, Cancellable cancel) {
186
                if (!isShapeVisible()) return;
187
                TextPath tp = new TextPath(g, shp, text, getFont(), 
188
                                (float) characterSpacing, (float) characterWidth, kerning,
189
                                (float) leading, alignment, (float) wordSpacing, (float) margin, rightToLeft);
190
                g.setFont(getFont());
191
                 
192
                for (int i = 0; i < tp.getGlyphCount(); i++) {
193
                        double[] coords = tp.nextPosForGlyph(i);
194
                        if (coords[0] == TextPath.NO_POS || coords[1] == TextPath.NO_POS) 
195
                                continue;
196
                        g.translate(coords[0], coords[1]);
197
                        g.rotate(coords[2]);
198

    
199
                        g.drawString(new String(new char[] {text[i]}), 0, 0);
200
                        
201
                        g.rotate(-coords[2]);
202
                        g.translate(-coords[0], -coords[1]);
203
                }
204
        }
205

    
206
        @Override
207
        public void getPixExtentPlus(FShape shp, float[] distances, ViewPort viewPort, int dpi) {
208
                // TODO Implement it
209
                throw new Error("Not yet implemented!");
210

    
211
        }
212

    
213
        @Override
214
        public int getOnePointRgb() {
215
                return getTextColor().getRGB();
216
        }
217

    
218
        @Override
219
        public XMLEntity getXMLEntity() {
220
                XMLEntity xml = new XMLEntity();
221
                xml.putProperty("className", getClassName());
222
                xml.putProperty("desc", getDescription());
223
                xml.putProperty("isShapeVisible", isShapeVisible());
224
                return xml;
225
        }
226

    
227
        @Override
228
        public int getSymbolType() {
229
                return FShape.TEXT;
230
        }
231

    
232
        @Override
233
        public boolean isSuitableFor(IGeometry geom) {
234
                return geom.getGeometryType() == FShape.LINE;
235
        }
236

    
237
        @Override
238
        public void drawInsideRectangle(Graphics2D g, AffineTransform scaleInstance, Rectangle r) throws SymbolDrawingException {
239
                // let's take the bottom segment of the rectangle as the line
240
                
241
                GeneralPathX gpx = new GeneralPathX();
242
                gpx.moveTo(r.getX(), r.getY());
243
                gpx.lineTo(r.getX()+r.getWidth(), r.getY());
244
                draw(g, scaleInstance, new FPolygon2D(gpx), null);
245
        }
246

    
247
        @Override
248
        public String getClassName() {
249
                return getClass().getName();
250
        }
251

    
252
        @Override
253
        public void setXMLEntity(XMLEntity xml) {
254
                setFont(new Font("Arial", Font.PLAIN, 18));
255
                setText("this is my TEST text that follows a line");
256
                setDescription(xml.getStringProperty("desc"));
257
                setIsShapeVisible(xml.getBooleanProperty("isShapeVisible"));
258

    
259
        }
260

    
261
        @Override
262
        public void setText(String text) {
263
                this.text = text.toCharArray();
264
        }
265

    
266
        @Override
267
        public String getText() {
268
                return new String(text);
269
        }
270
        
271
        public void setCharacterSpacing(double charSpacing) {
272
                this.characterSpacing = charSpacing;
273
        }                
274
        
275
        public void setWordSpacing(double wordSpacing) {
276
                this.wordSpacing = wordSpacing;
277
        }
278

    
279
        public void setAlignment(int alignment) {
280
                this.alignment = alignment;
281
        }
282
        
283
        public void setKerning(boolean kerning) {
284
                this.kerning = kerning;
285
        }
286

    
287
        public void setMargin(double margin) {
288
                this.margin = margin;
289
        }
290
        
291
        public void setRightToLeft(boolean rightToLeft) {
292
                this.rightToLeft = rightToLeft;
293
        }
294

    
295
        public static void main(String[] args) {
296
                class Item {
297
                        int value;
298
                        String text;
299
                        public Item(int value, String text) {
300
                                this.value = value;
301
                                this.text = text;
302
                        }
303
                        @Override
304
                        public String toString() {
305
                                return text;
306
                        }
307
                        
308
                        public int getValue() {
309
                                return value;
310
                        }
311
                }
312
                
313
                final int initialWidth = 300;
314
                final int initialHeight = 300;
315
                
316
                final JTextField textField = new JTextField("write your text here");
317
                final JIncrementalNumberField textFontSize = new JIncrementalNumberField();
318
                textFontSize.setDouble(15);
319
                final JIncrementalNumberField textCharSpacing = new JIncrementalNumberField();
320
                textCharSpacing.setDouble(1);
321
                final JIncrementalNumberField textWordSpacing = new JIncrementalNumberField();
322
                textCharSpacing.setDouble(10);
323
                final JCheckBox chkKerning = new JCheckBox("Kerning:");
324
                final JCheckBox chkRightToLeft = new JCheckBox("Rigth to left:");
325
                final JComboBoxFonts cmbFonts = new JComboBoxFonts();
326
                
327
                ArrayList<Integer> alignments = new ArrayList<Integer>();
328
                final JComboBox cmbAlign = new JComboBox(new Item[] {
329
                                new Item(FConstant.SYMBOL_STYLE_TEXTALIGNMENT_LEFT, "LEFT"),
330
                                new Item(FConstant.SYMBOL_STYLE_TEXTALIGNMENT_RIGHT, "RIGHT"),
331
                                new Item(FConstant.SYMBOL_STYLE_TEXTALIGNMENT_CENTERED, "CENTER"),
332
                                new Item(FConstant.SYMBOL_STYLE_TEXTALIGNMENT_JUSTIFY, "JUSTIFY"),
333
                });
334
                
335
                final JIncrementalNumberField txtMargin = new JIncrementalNumberField();
336
                txtMargin.setDouble(10);
337
                
338
                
339
                
340
                final JFrame f = new JFrame("test Smart Text Symbol"); 
341
                JPanel content = new JPanel(new BorderLayout(20,20));
342
                GridBagLayoutPanel controlPanel = new GridBagLayoutPanel();
343
                controlPanel.addComponent("Text: ", textField);
344
                controlPanel.addComponent("Font: ", cmbFonts);
345
                controlPanel.addComponent("Font size: ", textFontSize);
346
                controlPanel.addComponent("Char spacing: ", textCharSpacing);
347
                controlPanel.addComponent("Word spacing: ", textWordSpacing);
348
                controlPanel.addComponent("Alignment: ", cmbAlign);
349
                controlPanel.addComponent("Margin: ", txtMargin);
350
                controlPanel.addComponent(chkKerning);
351
                controlPanel.addComponent(chkRightToLeft);
352
                
353
                final SmartTextSymbol sms = new SmartTextSymbol();
354
                
355
                content.add(controlPanel, BorderLayout.NORTH);
356
                
357
                final JPanel canvas = new JPanel() {
358
                        private static final long serialVersionUID = 623038680274774722L;
359

    
360
                        @Override
361
                        protected void paintComponent(Graphics g) {
362
                                Graphics2D g2 = (Graphics2D) g;
363
                                double width = getBounds().getWidth();
364
                                double height= getBounds().getHeight();
365
                                GeneralPathX gpx = new GeneralPathX();
366
                                gpx.moveTo(0.033*width, 0.033*height);
367
                                gpx.lineTo(0.066*width, 0.5*height);
368
                                gpx.lineTo(0.5*width, 0.266*height);
369
                                gpx.lineTo(0.66*width, 0.4*height);
370
                                gpx.lineTo(0.933*width, 0.733*height);
371
                                gpx.lineTo(0.933*width, 0.866*height);
372
                                gpx.lineTo(0.833*width, 0.933*height);
373
                                gpx.lineTo(0.666*width, 0.933*height);
374
                                
375
                                
376
                                FPolyline2D theLineShape = new FPolyline2D(gpx);
377
                                SymbologyFactory.createDefaultLineSymbol().draw(g2, null, theLineShape, null);
378
                                sms.setFont(new Font((String) cmbFonts.getSelectedItem(), Font.PLAIN, 10));
379
                                sms.setFontSize(textFontSize.getDouble());
380
                                sms.setText(textField.getText());
381
                                sms.setCharacterSpacing(textCharSpacing.getDouble());
382
                                sms.setWordSpacing(textWordSpacing.getDouble());
383
                                sms.setAlignment(((Item) cmbAlign.getSelectedItem()).getValue());
384
                                sms.setKerning(chkKerning.isSelected());
385
                                sms.setRightToLeft(chkRightToLeft.isSelected());
386
                                sms.setMargin(txtMargin.getDouble());
387
                                sms.draw(g2, null, theLineShape, null);
388
                        }
389
                };
390
                
391
                ActionListener action = new ActionListener() {
392
                        public void actionPerformed(ActionEvent e) {
393
                                f.repaint();
394
                        }
395
                };
396
                textFontSize.addActionListener(action);
397
                textCharSpacing.addActionListener(action);
398
                textWordSpacing.addActionListener(action);
399
                cmbAlign.addActionListener(action);
400
                txtMargin.addActionListener(action);
401
                chkKerning.addActionListener(action);
402
                chkRightToLeft.addActionListener(action);
403
                cmbFonts.addActionListener(action);
404
                
405
                
406
                canvas.setPreferredSize(new Dimension(initialWidth, initialHeight));
407
                canvas.setSize(new Dimension(initialWidth, initialHeight));
408
                content.add(canvas, BorderLayout.CENTER);
409
                f.setContentPane(content);
410
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
411
                
412
                
413
                f.pack();
414
                f.setVisible(true);
415
        }
416

    
417
}
418

    
419
/*
420
private double factor = 0.4;
421
private int starPointCount = 5;
422

423
public void draw(Graphics2D g, AffineTransform affineTransform, FShape shp,
424
                Cancellable cancel) {
425
        FPoint2D p = (FPoint2D) shp;
426
        g.rotate(getRotation(), p.getX(), p.getY());
427
        double bigRadius = getSize()*0.5 ;
428
        Shape star = createStar((float) p.getX(), (float) p.getY(), (float) bigRadius, (float) (bigRadius*factor), starPointCount);
429
        g.setColor(getColor());
430
        g.fill(star);
431
        g.rotate(-getRotation(), p.getX(), p.getY());
432
        
433
}
434

435
private Shape createStar(float centerX, float centerY, float bigRadius, float smallRadius, int starPointCount) {
436
        GeneralPath gp = new GeneralPath();
437
        gp.moveTo(centerX, centerY-bigRadius);
438
        double TWO_PI = Math.PI*2;
439
        double subdivisionTheta =  TWO_PI / (2*starPointCount);
440
        for (int i = 1; i <= starPointCount*2; i++) {
441
                double theta = i * subdivisionTheta;
442
                double radius = i % 2 == 0 ? bigRadius : smallRadius;
443
                gp.lineTo(centerX - (float) ( radius*Math.sin(theta)),
444
                                  centerY - (float) ( radius*Math.cos(theta)));
445

446
        }
447
        return gp;
448
}
449

450
public ISymbol getSymbolForSelection() {
451
        return this;
452
}
453

454

455

456

457

458
public void setXMLEntity(XMLEntity xml) {
459
        factor = xml.getDoubleProperty("factor");
460
        starPointCount = xml.getIntProperty("starPointCount");
461
        setColor(StringUtilities.string2Color(xml.getStringProperty("color")));
462
        setRotation(xml.getDoubleProperty("rotation"));
463
        setDescription(xml.getStringProperty("desc"));
464
        setSize(xml.getDoubleProperty("size"));
465
        setIsShapeVisible(xml.getBooleanProperty("isShapeVisible"));
466
        setUnit(xml.getIntProperty("unit"));
467
        setReferenceSystem(xml.getIntProperty("referenceSystem"));
468
}
469

470

471
*/