~ubuntu-branches/debian/squeeze/latexdraw/squeeze

« back to all changes in this revision

Viewing changes to latexDraw/figures/Figure.java

  • Committer: Bazaar Package Importer
  • Author(s): Stuart Prescott
  • Date: 2009-05-03 23:49:35 UTC
  • Revision ID: james.westby@ubuntu.com-20090503234935-cls7n48x018g0vk2
Tags: upstream-2.0.2+1
ImportĀ upstreamĀ versionĀ 2.0.2+1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
package latexDraw.figures;
 
2
 
 
3
import static java.lang.Math.PI;
 
4
import static java.lang.Math.atan;
 
5
import static java.lang.Math.toDegrees;
 
6
 
 
7
import java.awt.*;
 
8
import java.awt.geom.GeneralPath;
 
9
import java.awt.geom.Line2D;
 
10
import java.awt.geom.Point2D;
 
11
import java.awt.geom.Rectangle2D;
 
12
import java.io.Serializable;
 
13
 
 
14
import javax.swing.JLabel;
 
15
 
 
16
import latexDraw.figures.properties.Arrowable;
 
17
import latexDraw.figures.properties.Drawable;
 
18
import latexDraw.lang.LaTeXDrawLang;
 
19
import latexDraw.psTricks.DviPsColors;
 
20
import latexDraw.psTricks.PSTricksConstants;
 
21
import latexDraw.ui.components.Delimitor;
 
22
import latexDraw.ui.components.LaTeXDrawComboBox;
 
23
import latexDraw.ui.components.LabelListCellRenderer;
 
24
import latexDraw.ui.components.MagneticGrid;
 
25
import latexDraw.util.LaTeXDrawException;
 
26
import latexDraw.util.LaTeXDrawPoint2D;
 
27
import latexDraw.util.LaTeXDrawResources;
 
28
 
 
29
/**
 
30
 * This class defines what it is, in general, a figure.<br>
 
31
 * <br>
 
32
 * This file is part of LaTeXDraw<br>
 
33
 * Copyright (c) 2005-2008 Arnaud BLOUIN<br>
 
34
 * <br>
 
35
 * LaTeXDraw is free software; you can redistribute it and/or modify it under
 
36
 * the terms of the GNU General Public License as published by the Free Software
 
37
 * Foundation; either version 2 of the License, or (at your option) any later
 
38
 * version.<br>
 
39
 * <br>
 
40
 * LaTeXDraw is distributed without any warranty; without even the implied
 
41
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 
42
 * General Public License for more details.<br>
 
43
 * <br>
 
44
 * 03/17/2007<br>
 
45
 * @author Arnaud BLOUIN<br>
 
46
 * @version 2.0.0<br>
 
47
 */
 
48
public abstract class Figure implements Serializable, Cloneable, Drawable
 
49
{
 
50
        private static final long serialVersionUID = 1L;
 
51
        
 
52
        /** The number by default of pixels per cm. */
 
53
        public static final int PPC = 50;
 
54
        
 
55
        /** Corresponds to the thickness of the borders of the figure (in pixels). */
 
56
        protected float thickness;
 
57
 
 
58
        /** Corresponds to the selected delimiter (if there is a one selected) */
 
59
        protected Delimitor dSelected;
 
60
 
 
61
        /** Allows to know if the figure is selected */
 
62
        protected boolean isSelected;
 
63
 
 
64
        /** Allows to know if the figure can be filled by a colour */
 
65
        protected boolean canBeFilled;
 
66
 
 
67
        /** Allows to know if the figure is filled by a colour */
 
68
        protected boolean isFilled;
 
69
 
 
70
        /** Allows to know if the thickness of the figure can be changed */
 
71
        protected boolean isThicknessable;
 
72
 
 
73
        /** Allows to know if the borders of the figure are movable */
 
74
        protected boolean isBordersMovable;
 
75
 
 
76
        /** The colour of the borders */
 
77
        protected Color linesColor;
 
78
 
 
79
        /** The colour of the interior of the figure */
 
80
        protected Color interiorColor;
 
81
 
 
82
        /** The number of the figure. */
 
83
        protected int number;
 
84
 
 
85
        /** The meter of figures */
 
86
        private static int meter = 0;
 
87
 
 
88
        /** Allows to know if the figure is customisable or not */
 
89
        protected boolean isCustomizable;
 
90
 
 
91
        /** Allows to know if the bounds are double */
 
92
        protected boolean hasDoubleBoundary;
 
93
 
 
94
        /** Allows to know if the figure can have double boundary */
 
95
        protected boolean isDoubleBoundaryable;
 
96
 
 
97
        /** The colour of the double boundary */
 
98
        protected Color doubleColor;
 
99
 
 
100
        /** The position of the double boundary */
 
101
        protected String bordersPosition;
 
102
 
 
103
        /** Allows to know if the figure can be dotted or dashed */
 
104
        protected boolean isDashableOrDotable;
 
105
 
 
106
        /** The colour of the hatch */
 
107
        protected Color hatchingColor;
 
108
 
 
109
        /** The angle of the hatch (in rad). */
 
110
        protected double hatchingAngle;
 
111
 
 
112
        /** The width of the lines of the hatch (in pixels). */
 
113
        protected float hatchingWidth;
 
114
 
 
115
        /** Allows to know if the figure is resizable or not */
 
116
        protected boolean isResizable;
 
117
 
 
118
        /** The kind of hatch used by the figure */
 
119
        protected String hatchingStyle;
 
120
 
 
121
        /** True if the figure has a shadow. */
 
122
        protected boolean hasShadow;
 
123
        
 
124
        /** The size of the shadow (in pixels). */
 
125
        protected double shadowSize;
 
126
        
 
127
        /** The angle of the shadow (in rad). */
 
128
        protected double shadowAngle;
 
129
        
 
130
        /** The colour of the shadow. */
 
131
        protected Color shadowColor;
 
132
        
 
133
        /** Define if the figure can have a shadow. */
 
134
        protected boolean canHaveShadow;
 
135
        
 
136
        /** The angle of the gradient (in rad). */
 
137
        protected double gradientAngle;
 
138
        
 
139
        /** The position of the midpoint, as a fraction of the distance from
 
140
                top to bottom. Should be between 0 and 1. */
 
141
        protected double gradientMidPoint;
 
142
        
 
143
        /** The first colour of the gradient. */
 
144
        protected Color gradientStartColor;
 
145
        
 
146
        /** The second colour of the gradient. */
 
147
        protected Color gradientEndColor;
 
148
        
 
149
        /** The position of the midpoint, as a fraction of the distance from
 
150
        top to bottom. Should be between 0 and 1. */
 
151
        public static final double DEFAULT_GRADIENT_MID_POINT = 1;
 
152
        
 
153
        /** The angle of the gradient in radian. */
 
154
        public static final double DEFAULT_GRADIENT_ANGLE = Math.toRadians(PSTricksConstants.DEFAULT_GRADIENT_ANGLE);
 
155
        
 
156
        /** The value by default of hasShadow. */
 
157
        public static final boolean DEFAULT_SHADOW_HAS =  PSTricksConstants.DEFAULT_SHADOW;
 
158
        
 
159
        /** The value by default of shadowSize (in pixels). */
 
160
        public static final double DEFAULT_SHADOW_SIZE =  PSTricksConstants.DEFAULT_SHADOW_SIZE*PPC;
 
161
        
 
162
        /** The value by default of shadowAngle (in rad). */
 
163
        public static final double DEFAULT_SHADOW_ANGLE =  Math.toRadians(PSTricksConstants.DEFAULT_SHADOW_ANGLE);
 
164
        
 
165
        /** The value by default of shadowAngle. */
 
166
        public static final Color DEFAULT_SHADOW_COLOR =  PSTricksConstants.DEFAULT_SHADOW_COLOR;
 
167
        
 
168
        /** The position by default of the double boundary */
 
169
        public static final String DEFAULT_BORDERS_POSITION = PSTricksConstants.BORDERS_INSIDE;
 
170
 
 
171
        /** The colour of the double boundary of the figure by default */
 
172
        public static final Color DEFAULT_DOUBLE_COLOR = PSTricksConstants.DEFAULT_DOUBLE_COLOR;
 
173
 
 
174
        /** The value by default of the attribute hasDoubleBoudary */
 
175
        public static final boolean DEFAULT_HAS_DOUBLE_BOUNDARY = false;
 
176
 
 
177
        /** The angle of the lines of the hatch by default */
 
178
        public static final double DEFAULT_HATCH_ANGLE = 0.;
 
179
        
 
180
        /** The size of the separation between the hatching by default. */
 
181
        public static final double DEFAULT_HATCH_SEP = PSTricksConstants.DEFAULT_HATCH_SEP*PPC;
 
182
 
 
183
        /** A figure is customisable by default ? */
 
184
        public static final boolean DEFAULT_IS_CUSTOMISABLE = true;
 
185
 
 
186
        /** The borders of the figure are movable by default */
 
187
        public static final boolean DEFAULT_IS_BORDERS_MOVABLE = true;
 
188
 
 
189
        /** The colour by default of the borders of the figure */
 
190
        public static final Color DEFAULT_BORDERS_COL = Color.BLACK;
 
191
 
 
192
        /** The colour by default of the interior of the figure */
 
193
        public static final Color DEFAULT_INTERIOR_COL = Color.WHITE;
 
194
 
 
195
        /** The colour by default of the hatch of the figure */
 
196
        public static final Color DEFAULT_HATCH_COL = Color.BLACK;
 
197
 
 
198
        /** The value by default of the attribute isThicknessable */
 
199
        public static final boolean DEFAULT_IS_THICKNESSABLE = true;
 
200
 
 
201
        /** value of the thickness by default (in pixels). */
 
202
        public static final float DEFAULT_THICKNESS = 2; 
 
203
 
 
204
        /** The style of the lines of the figure */
 
205
        protected String lineStyle;
 
206
 
 
207
        /** The style of lines by default */
 
208
        public static final String DEFAULT_LINE_STYLE = PSTricksConstants.LINE_NONE_STYLE;
 
209
 
 
210
        /** If a figure is filled by default */
 
211
        public static final boolean DEFAULT_IS_FILLED = false;
 
212
 
 
213
        /** The label of the ComboBox containing all kinds of hatches */
 
214
        public static final String LABEL_HATCH_CHOICE = "Hatch choice"; //$NON-NLS-1$
 
215
 
 
216
        /** The label of the field which allows to change the width of the hatch */
 
217
        public static final String LABEL_HATCH_WIDTH = "Hatch width"; //$NON-NLS-1$
 
218
 
 
219
        /** The label of the hatch used by default */
 
220
        public static final String DEFAULT_HATCH_STYLE = PSTricksConstants.TOKEN_FILL_NONE;
 
221
 
 
222
        /** The value by default of the width of the hatch (in pixels). */
 
223
        public static final float DEFAULT_HATCH_WIDTH = DEFAULT_THICKNESS;
 
224
 
 
225
        /** The value by default of the attribute isResizable */
 
226
        public static final boolean DEFAULT_ISRESIZABLE = true;
 
227
 
 
228
        /** The value by default of the attribute isHatched */
 
229
        public static final boolean DEFAULT_IS_HATCHED = false;
 
230
 
 
231
        /** The label of double boundary choice */
 
232
        public static final String LABEL_BORDERS_POSITION_CHOICE = LaTeXDrawLang.getOthersString("Figure.boundPos"); //$NON-NLS-1$
 
233
 
 
234
        /** The centre of the rotation */
 
235
        protected LaTeXDrawPoint2D gravityCenter;
 
236
 
 
237
        /** The angle of rotation (in rad) */
 
238
        public double rotationAngle;
 
239
 
 
240
        /** Allows to know if the figure is on rotation */
 
241
        protected boolean isOnRotation;
 
242
 
 
243
        /** The size of the separation between the double line in pixels */
 
244
        protected double doubleSep;
 
245
 
 
246
        /** The value by default of the attribute doubleLine */
 
247
        public static final boolean DEFAULT_DOUBLELINE = false;
 
248
 
 
249
        /** The value by default of the attribute doubleSep (in pixels). */
 
250
        public static final double DEFAULT_DOUBLESEP = 6;
 
251
 
 
252
        /** The angle of rotation by default */
 
253
        public static final double DEFAULT_ROTATION_ANGLE = 0.;
 
254
 
 
255
        public static final float DEFAULT_BLACK_DASH_LGTH = 8;
 
256
 
 
257
        public static final float DEFAULT_WHITE_DASH_LGTH = 8;
 
258
 
 
259
        /** The separator between dots by default (in pixels). */
 
260
        public static final float DEFAULT_DOT_SEP = 8;
 
261
 
 
262
        /** The length of the black dash of a line (in pixels). */
 
263
        protected float blackDashLength;
 
264
 
 
265
        /** The length of the white dash of a line (in pixels). */
 
266
        protected float whiteDashLength;
 
267
 
 
268
        /** The separation between two dots in a dotted line (in pixels). */
 
269
        protected float dotSep;
 
270
 
 
271
        /** The borders of the figure */
 
272
        protected LaTeXDrawRectangle borders;
 
273
 
 
274
        /** The shape of the figure */
 
275
        protected transient Shape shape; 
 
276
 
 
277
        /** The size of the separation between the hatching (in pixels). */
 
278
        protected double hatchingSep;
 
279
        
 
280
        /** Define if the shape can have arrows. */
 
281
        protected boolean canHaveArrow;
 
282
        
 
283
        /** The token used for Horizontal hatch in LaTeXDraw 1.5.1.1, 1.5.1 and 1.5.<br>
 
284
         * Useful to read file ldp of these versions of LaTeXDraw.*/
 
285
        public static final String DECREPETED_FILL_HORIZ = "Horizontal hatch";//$NON-NLS-1$
 
286
        
 
287
        /** The token used for Vertical hatch in LaTeXDraw 1.5.1.1, 1.5.1 and 1.5.<br>
 
288
         * Useful to read file ldp of these versions of LaTeXDraw.*/
 
289
        public static final String DECREPETED_FILL_VERT  = "Vertical hatch";//$NON-NLS-1$
 
290
        
 
291
        /** The token used for Cross hatch in LaTeXDraw 1.5.1.1, 1.5.1 and 1.5.<br>
 
292
         * Useful to read file ldp of these versions of LaTeXDraw.*/
 
293
        public static final String DECREPETED_FILL_CROSS = "Cross hatch";//$NON-NLS-1$
 
294
        
 
295
        /** The token used for No hatch in LaTeXDraw 1.5.1.1, 1.5.1 and 1.5.<br>
 
296
         * Useful to read file ldp of these versions of LaTeXDraw.*/
 
297
        public static final String DECREPETED_FILL_NO    = "No hatch";//$NON-NLS-1$
 
298
 
 
299
        public static final short DELIMITOR_ORIENTATION_NONE    = -1;
 
300
        
 
301
        public static final short DELIMITOR_ORIENTATION_WEST    = 0;
 
302
        
 
303
        public static final short DELIMITOR_ORIENTATION_EAST    = 2;
 
304
        
 
305
        public static final short DELIMITOR_ORIENTATION_NORTH = 3;
 
306
        
 
307
        public static final short DELIMITOR_ORIENTATION_SOUTH = 8;
 
308
        
 
309
        public static final short DELIMITOR_ORIENTATION_NW      = 4;
 
310
        
 
311
        public static final short DELIMITOR_ORIENTATION_SW      = 5;
 
312
        
 
313
        public static final short DELIMITOR_ORIENTATION_NE      = 6;
 
314
        
 
315
        public static final short DELIMITOR_ORIENTATION_SE      = 7;
 
316
        
 
317
        public static final short DELIMITOR_ROTATION            = 9;
 
318
        
 
319
        
 
320
 
 
321
        /**
 
322
         * The constructor.
 
323
         * @param increaseMeter If the figure must increase the meter of figure {@literal number}.
 
324
         */
 
325
        protected Figure(boolean increaseMeter)
 
326
        {
 
327
                canHaveArrow = false;
 
328
                hatchingSep = DEFAULT_HATCH_SEP;
 
329
                isBordersMovable = DEFAULT_IS_BORDERS_MOVABLE;
 
330
                bordersPosition = DEFAULT_BORDERS_POSITION;
 
331
                doubleColor = DEFAULT_DOUBLE_COLOR;
 
332
                isResizable = DEFAULT_ISRESIZABLE;
 
333
                doubleSep = DEFAULT_DOUBLESEP;
 
334
                isDashableOrDotable = true;
 
335
                isDoubleBoundaryable = true;
 
336
                isCustomizable = DEFAULT_IS_CUSTOMISABLE;
 
337
                isOnRotation = false;
 
338
                isThicknessable = DEFAULT_IS_THICKNESSABLE;
 
339
                rotationAngle = DEFAULT_ROTATION_ANGLE;
 
340
                isSelected = false;
 
341
                interiorColor = DEFAULT_INTERIOR_COL;
 
342
                linesColor = DEFAULT_BORDERS_COL;
 
343
                hatchingColor = DEFAULT_BORDERS_COL;
 
344
                hatchingStyle = DEFAULT_HATCH_STYLE;
 
345
                isFilled = DEFAULT_IS_FILLED;
 
346
                canBeFilled = true;
 
347
                dSelected = null;
 
348
                number = increaseMeter ? meter++ : -1;
 
349
                blackDashLength = DEFAULT_BLACK_DASH_LGTH;
 
350
                whiteDashLength = DEFAULT_WHITE_DASH_LGTH;
 
351
                lineStyle = PSTricksConstants.LINE_NONE_STYLE;
 
352
                dotSep = DEFAULT_DOT_SEP;
 
353
                thickness = DEFAULT_THICKNESS;
 
354
                hatchingWidth = DEFAULT_HATCH_WIDTH;
 
355
                gravityCenter = new LaTeXDrawPoint2D();
 
356
                isResizable = true;
 
357
                shadowAngle = DEFAULT_SHADOW_ANGLE;
 
358
                shadowColor = DEFAULT_SHADOW_COLOR;
 
359
                shadowSize  = DEFAULT_SHADOW_SIZE;
 
360
                hasShadow   = DEFAULT_SHADOW_HAS;
 
361
                canHaveShadow = true;
 
362
                gradientAngle           = DEFAULT_GRADIENT_ANGLE;
 
363
                gradientEndColor        = PSTricksConstants.DEFAULT_GRADIENT_END_COLOR;
 
364
                gradientStartColor      = PSTricksConstants.DEFAULT_GRADIENT_START_COLOR;
 
365
                gradientMidPoint        = DEFAULT_GRADIENT_MID_POINT;
 
366
        }
 
367
 
 
368
 
 
369
 
 
370
        
 
371
        /**
 
372
         * Creates a figure from one another (but do not create the gravity centre, the border and the shape).
 
373
         * @param f The figure to copy.
 
374
         * @param sameNumber True is the new figure must have the same number as the other.
 
375
         * @throws IllegalArgumentException If f is null.
 
376
         */
 
377
        protected Figure(Figure f, boolean sameNumber)
 
378
        {
 
379
                if(f==null)
 
380
                        throw new IllegalArgumentException();
 
381
                
 
382
                canBeFilled             = f.canBeFilled;
 
383
                canHaveShadow   = f.canHaveShadow;
 
384
                isBordersMovable= f.isBordersMovable;
 
385
                isCustomizable  = f.isCustomizable;
 
386
                isDashableOrDotable = f.isDashableOrDotable;
 
387
                isDoubleBoundaryable= f.isDoubleBoundaryable;
 
388
                isFilled                = f.isFilled;
 
389
                isOnRotation    = f.isOnRotation;
 
390
                isResizable             = f.isResizable;
 
391
                isSelected              = f.isSelected;
 
392
                interiorColor   = f.interiorColor;
 
393
                isThicknessable = f.isThicknessable;
 
394
                blackDashLength = f.blackDashLength;
 
395
                bordersPosition = f.bordersPosition;
 
396
                dotSep                  = f.dotSep;
 
397
                doubleColor     = f.doubleColor;
 
398
                doubleSep               = f.doubleSep;
 
399
                gradientAngle   = f.gradientAngle;
 
400
                gradientEndColor= f.gradientEndColor;
 
401
                gradientMidPoint= f.gradientMidPoint;
 
402
                gradientStartColor=f.gradientStartColor;
 
403
                hasDoubleBoundary=f.hasDoubleBoundary;
 
404
                hasShadow               = f.hasShadow;
 
405
                hatchingAngle   = f.hatchingAngle;
 
406
                hatchingColor   = f.hatchingColor;
 
407
                hatchingStyle   = f.hatchingStyle;
 
408
                hatchingWidth   = f.hatchingWidth;
 
409
                hatchingSep             = f.hatchingSep;
 
410
                linesColor              = f.linesColor;
 
411
                lineStyle               = f.lineStyle;
 
412
                number                  = sameNumber ? f.number : meter++;
 
413
                rotationAngle   = f.rotationAngle;
 
414
                shadowAngle             = f.shadowAngle;
 
415
                shadowColor             = f.shadowColor;
 
416
                shadowSize              = f.shadowSize;
 
417
                thickness               = f.thickness;
 
418
                whiteDashLength = f.whiteDashLength;
 
419
        }
 
420
        
 
421
        
 
422
 
 
423
        /**
 
424
         * Allows to know if the new position is a valid borders position.
 
425
         * @param pos The position to check.
 
426
         * @return True is the position is valid.
 
427
         */
 
428
        public static boolean isValidBordersPosition(String pos)
 
429
        {
 
430
                return pos.equals(PSTricksConstants.BORDERS_INSIDE)
 
431
                                || pos.equals(PSTricksConstants.BORDERS_MIDDLE)
 
432
                                || pos.equals(PSTricksConstants.BORDERS_OUTSIDE);
 
433
        }
 
434
 
 
435
 
 
436
 
 
437
 
 
438
        /**
 
439
         * @return True if the figure is in rotation.
 
440
         */
 
441
        public boolean isOnRotation()
 
442
        {
 
443
                return isOnRotation;
 
444
        }
 
445
 
 
446
 
 
447
 
 
448
 
 
449
        /**
 
450
         * @return True if the figure is hatched.
 
451
         */
 
452
        public synchronized boolean isHatched()
 
453
        {
 
454
                return !hatchingStyle.equals(PSTricksConstants.TOKEN_FILL_NONE) &&
 
455
                                !hatchingStyle.equals(PSTricksConstants.TOKEN_FILL_SOLID) &&
 
456
                                !hatchingStyle.equals(PSTricksConstants.TOKEN_FILL_GRADIENT) ;
 
457
        }
 
458
 
 
459
 
 
460
 
 
461
 
 
462
        /**
 
463
         * Allows to set if the figure must be in rotation or not.
 
464
         * @param on True : the figure must be on rotation.
 
465
         */
 
466
        public synchronized void setOnRotation(boolean on)
 
467
        {
 
468
                if(borders != null)
 
469
                        borders.setOnRotation(on);
 
470
                
 
471
                isOnRotation = on;
 
472
                updateStyleOfDelimitors();
 
473
        }
 
474
 
 
475
 
 
476
 
 
477
 
 
478
        /**
 
479
         * Allows to change the style of the delimiters following the actions to do (rotation, ...).
 
480
         */
 
481
        public void updateStyleOfDelimitors()
 
482
        {
 
483
                if(borders != null)
 
484
                        borders.updateStyleOfDelimitors();
 
485
        }
 
486
 
 
487
 
 
488
 
 
489
 
 
490
        /**
 
491
         * Allows to create a Java Swing shape from the figure.
 
492
         * @return The Java Swing shape.
 
493
         */
 
494
        public abstract Shape createShape2D();
 
495
 
 
496
 
 
497
        
 
498
        /**
 
499
         * Allows to create a java swing shape from the figure (without any rotation).
 
500
         * @return The java swing shape.
 
501
         */
 
502
        public abstract Shape createNonRotatedShape2D();
 
503
 
 
504
 
 
505
 
 
506
        @Override
 
507
        public Object clone() throws CloneNotSupportedException
 
508
        {
 
509
                Figure f = (Figure)super.clone();
 
510
                f.dSelected = null;
 
511
                f.isOnRotation = isOnRotation;
 
512
                f.rotationAngle = rotationAngle;
 
513
                f.isSelected = isSelected;
 
514
                f.interiorColor = interiorColor;
 
515
                f.linesColor = linesColor;
 
516
                f.isFilled = isFilled;
 
517
                f.canBeFilled = canBeFilled;
 
518
                f.number = meter++;
 
519
                f.blackDashLength = blackDashLength;
 
520
                f.whiteDashLength = whiteDashLength;
 
521
                f.lineStyle = lineStyle;
 
522
                f.dotSep = dotSep;
 
523
                f.thickness = thickness;
 
524
                f.gravityCenter = (LaTeXDrawPoint2D)gravityCenter.clone();
 
525
                
 
526
                f.doubleColor = doubleColor;
 
527
                f.doubleSep = doubleSep;
 
528
                f.hasDoubleBoundary = hasDoubleBoundary;
 
529
                f.hatchingAngle = hatchingAngle;
 
530
                f.hatchingColor = hatchingColor;
 
531
                f.hatchingStyle = hatchingStyle;
 
532
                f.hatchingWidth = hatchingWidth;
 
533
                f.isBordersMovable = isBordersMovable;
 
534
                f.isCustomizable = isCustomizable;
 
535
                f.isDashableOrDotable = isDashableOrDotable;
 
536
                f.isDoubleBoundaryable = isDoubleBoundaryable;
 
537
                f.isResizable = isResizable;
 
538
                f.isThicknessable = isThicknessable;
 
539
                f.bordersPosition = bordersPosition;
 
540
                
 
541
                f.hasShadow     = hasShadow;
 
542
                f.shadowAngle   = shadowAngle;
 
543
                f.shadowColor   = shadowColor;
 
544
                f.shadowSize    = shadowSize;
 
545
                f.canHaveShadow = canHaveShadow;
 
546
                f.gradientAngle = gradientAngle;
 
547
                f.gradientEndColor              = gradientEndColor;
 
548
                f.gradientStartColor    = gradientStartColor;
 
549
                f.gradientMidPoint              = gradientMidPoint;
 
550
 
 
551
                f.hatchingSep = hatchingSep;
 
552
                
 
553
                return f;
 
554
        }
 
555
 
 
556
 
 
557
 
 
558
 
 
559
        /**
 
560
         * Allows to know if the figure can be filled or not.
 
561
         * @return True if the figure can be filled.
 
562
         */
 
563
        public boolean canBeFilled()
 
564
        {
 
565
                return canBeFilled;
 
566
        }
 
567
 
 
568
 
 
569
 
 
570
 
 
571
        /**
 
572
         * Allows to know if the figure can be hatched or not
 
573
         * @return True if the figure can be hatched (for most of figures, if it can be filled, it can be hatched)
 
574
         */
 
575
        public boolean canBeHatched()
 
576
        {
 
577
                return canBeFilled;
 
578
        }
 
579
 
 
580
 
 
581
 
 
582
 
 
583
        /**
 
584
         * Allows to get the number of the figure
 
585
         * @return The number of the figure
 
586
         */
 
587
        public synchronized int getNumber()
 
588
        {
 
589
                return number;
 
590
        }
 
591
 
 
592
 
 
593
 
 
594
 
 
595
        /**
 
596
         * Allows to get a point of the borders
 
597
         * @param id The position of the point (-1 : return the last point, in fact  the south-east point)
 
598
         * @return The point
 
599
         */
 
600
        public synchronized LaTeXDrawPoint2D getBordersPoint(int id)
 
601
        {
 
602
                if(borders == null)
 
603
                        return null;
 
604
 
 
605
                if(id == -1)
 
606
                        return borders.getPoint(borders.getNbPoints()-1);
 
607
 
 
608
                if(id<0 || id>LaTeXDrawRectangle.NB_POINTS_FRAME-1)
 
609
                        throw new IllegalArgumentException();
 
610
 
 
611
                return borders.getPoint(id);
 
612
        }
 
613
 
 
614
 
 
615
 
 
616
 
 
617
        /**
 
618
         * Allows to get the angle of rotation (in rad).
 
619
         * @return The angle of rotation.
 
620
         */
 
621
        public synchronized double getRotationAngle()
 
622
        {
 
623
                return rotationAngle;
 
624
        }
 
625
 
 
626
 
 
627
 
 
628
 
 
629
        /**
 
630
         * Allows to set the angle of rotation
 
631
         * @param theta The new angle of rotation in radian.
 
632
         */
 
633
        public synchronized void setRotationAngle(double theta)
 
634
        {
 
635
                if(!Double.isInfinite(theta) && !Double.isNaN(theta))
 
636
                {
 
637
                        rotationAngle = theta%(PI*2.);
 
638
                        
 
639
                        if(borders != null)
 
640
                                borders.setRotationAngle(rotationAngle);
 
641
                }
 
642
        }
 
643
 
 
644
 
 
645
 
 
646
 
 
647
        /**
 
648
         * Allows to set the variable isSelected
 
649
         * @param state The new value of isSelected
 
650
         */
 
651
        public synchronized void setSelected(boolean state)
 
652
        {
 
653
                if(!state)
 
654
                {
 
655
                        onRelease();
 
656
                        onDelimitorRelease();
 
657
                }
 
658
                else
 
659
                {
 
660
                        isSelected = state;
 
661
                        if(borders != null)
 
662
                                borders.setSelected(state);
 
663
                }
 
664
        }
 
665
 
 
666
 
 
667
 
 
668
 
 
669
 
 
670
        /**
 
671
         * Allows to set the colour of the borders of the figure
 
672
         * @param c The new colour of the borders
 
673
         */
 
674
        public synchronized void setLinesColor(Color c)
 
675
        {
 
676
                if(c!=null)
 
677
                        linesColor = c;
 
678
        }
 
679
 
 
680
 
 
681
 
 
682
 
 
683
        /**
 
684
         * Allows to set the colour of the interior of the figure
 
685
         * @param c The new colour of the interior
 
686
         */
 
687
        public synchronized void setInteriorColor(Color c)
 
688
        {
 
689
                if(c!=null)
 
690
                        interiorColor = c;
 
691
        }
 
692
 
 
693
 
 
694
 
 
695
 
 
696
 
 
697
        /**
 
698
         * Allows to set the style of the lines of the figure
 
699
         * @param style The new style of the lines of the figure
 
700
         * @throws IllegalArgumentException If the style is invalid.
 
701
         */
 
702
        public synchronized void setLineStyle(String style)
 
703
        {
 
704
                if(isValidStyle(style))
 
705
                        lineStyle = style;
 
706
                else
 
707
                        throw new IllegalArgumentException();
 
708
        }
 
709
 
 
710
 
 
711
 
 
712
 
 
713
        /**
 
714
         * Allows to change the kid of hatch of the figure.
 
715
         * @param style The new style.
 
716
         * @throws IllegalArgumentException If the style is invalid.
 
717
         */
 
718
        public synchronized void setHatchingStyle(String style)
 
719
        {
 
720
                if(PSTricksConstants.isValidFillStyle(style))
 
721
                        hatchingStyle = style;
 
722
                else
 
723
                        throw new IllegalArgumentException();
 
724
        }
 
725
 
 
726
 
 
727
 
 
728
 
 
729
        /**
 
730
         * Allows to set the attribute isFilled
 
731
         * @param state The new value of
 
732
         */
 
733
        public synchronized void setIsFilled(boolean state)
 
734
        {
 
735
                isFilled = state;
 
736
        }
 
737
 
 
738
 
 
739
 
 
740
 
 
741
        /**
 
742
         * Allows to set the colour of the hatch of the figure
 
743
         * @param color The new colour of the hatch
 
744
         */
 
745
        public synchronized void setHatchingColor(Color color)
 
746
        {
 
747
                if(canBeFilled() && color!=null)
 
748
                        hatchingColor = color;
 
749
        }
 
750
 
 
751
 
 
752
 
 
753
 
 
754
        /**
 
755
         * Allows to set the width of the hatch.
 
756
         * @param width The new width of the hatch.
 
757
         */
 
758
        public synchronized void setHatchingWidth(float width)
 
759
        {
 
760
                if(width>0 && !Double.isInfinite(width) && !Double.isNaN(width))
 
761
                        hatchingWidth = width;
 
762
        }
 
763
 
 
764
 
 
765
 
 
766
 
 
767
        /**
 
768
         * Allows to set the thickness of the figure
 
769
         * @param value The new
 
770
         */
 
771
        public synchronized void setThickness(float value) 
 
772
        {
 
773
                if(value<=0 || Float.isInfinite(value) || Float.isNaN(value))
 
774
                        return ;
 
775
 
 
776
                if(borders != null)
 
777
                        borders.setThickness(value);
 
778
                
 
779
                thickness = value;
 
780
        }
 
781
 
 
782
 
 
783
 
 
784
 
 
785
        /**
 
786
         * Defines the actions to do when the figure is dragged.
 
787
         * @param formerPt The former position of the cursor.
 
788
         * @param newPt The new position of the cursor.
 
789
         * @throws Exception
 
790
         */
 
791
        public abstract void onDragged(Point formerPt, Point newPt) throws Exception;
 
792
 
 
793
 
 
794
 
 
795
 
 
796
        /**
 
797
         * Allows to draw the figure.
 
798
         * @param g The graphic
 
799
         * @param antiAlias The antialiasing value
 
800
         * @param rendering The rendering value
 
801
         * @param alphaInter The alpha interpolation value
 
802
         * @param colorRendering The colour rendering value
 
803
         */
 
804
        public abstract void draw(Graphics2D g, Object antiAlias, Object rendering, Object alphaInter, Object colorRendering);
 
805
 
 
806
 
 
807
 
 
808
 
 
809
        /**
 
810
         * Allows to set the last point of the figure
 
811
         * @param pt The new point
 
812
         */
 
813
        public synchronized void setLastPoint(LaTeXDrawPoint2D pt)
 
814
        {
 
815
                setLastPoint(pt.x, pt.y);
 
816
        }
 
817
 
 
818
 
 
819
 
 
820
 
 
821
        /**
 
822
         * Allows to set the last point of the figure
 
823
         * @param x The X-coordinates of the new point
 
824
         * @param y The Y-coordinates of the new point
 
825
         */
 
826
        public abstract void setLastPoint(double x, double y);
 
827
 
 
828
 
 
829
        
 
830
        /**
 
831
         * @return The last point, null if there is no last point.
 
832
         */
 
833
        public abstract LaTeXDrawPoint2D getLastPoint();
 
834
        
 
835
        
 
836
        
 
837
        /**
 
838
         * Allows to set the first point of the figure
 
839
         * @param pt The new point
 
840
         */
 
841
        public synchronized void setFirstPoint(LaTeXDrawPoint2D pt)
 
842
        {
 
843
                setFirstPoint(pt.x, pt.y);
 
844
        }
 
845
 
 
846
 
 
847
 
 
848
 
 
849
        /**
 
850
         * Allows to set the first point of the figure
 
851
         * @param x The X-coordinates of the new point
 
852
         * @param y The Y-coordinates of the new point
 
853
         */
 
854
        public abstract void setFirstPoint(double x, double y);
 
855
 
 
856
 
 
857
 
 
858
 
 
859
        /**
 
860
         * Allows to gap the figure
 
861
         * @param shiftX The X-coordinates gap
 
862
         * @param shiftY The Y-coordinates gap
 
863
         */
 
864
        public abstract void shift(double shiftX, double shiftY);
 
865
 
 
866
 
 
867
 
 
868
 
 
869
        /**
 
870
         * Allows to gap the figure.
 
871
         * @param formerPt The former position of the figure.
 
872
         * @param newPt The new position of the figure.
 
873
         * @throws IllegalArgumentException If one of the point is null.
 
874
         */
 
875
        public void shift(LaTeXDrawPoint2D formerPt, LaTeXDrawPoint2D newPt)
 
876
        {
 
877
                if(formerPt==null || newPt==null)
 
878
                        throw new IllegalArgumentException();
 
879
                
 
880
                shift(newPt.x - formerPt.x, newPt.y - formerPt.y);
 
881
        }
 
882
 
 
883
 
 
884
 
 
885
 
 
886
        /**
 
887
         * Allows to gap the figure
 
888
         * 
 
889
         * @param formerPt The former position of the figure
 
890
         * @param newPt The new position of the figure
 
891
         */
 
892
        public void shift(Point formerPt, Point newPt)
 
893
        {
 
894
                shift(newPt.x - formerPt.x, newPt.y - formerPt.y);
 
895
        }
 
896
 
 
897
 
 
898
 
 
899
 
 
900
        /**
 
901
         * Allows to rescale the polygon in width
 
902
         * @param formerX The old value of the X-coordinate to change
 
903
         * @param newX The X-coordinate of the point which rescale the figure. It's
 
904
         * Useful for determinate of which side (east or west) we must enlarge thecfigure
 
905
         * @param percent The new width of the figure in percent
 
906
         * @param bound The reference for moving points (the borders of the figure
 
907
         * or, for example, the borders of the drawing containing the figure)
 
908
         */
 
909
        public abstract void rescaleX(double formerX, double newX, double percent, LaTeXDrawRectangle bound);
 
910
 
 
911
 
 
912
 
 
913
 
 
914
        /**
 
915
         * Allows to rescale the polygon in width
 
916
         * @param formerY The former value of the y
 
917
         * @param newY The Y-coordinate of the point which rescale the polygon. It's
 
918
         * Useful for determinate of which side (east or west) we must enlarge the polygon
 
919
         * @param percent The new width of the polygon in percent
 
920
         * @param bound The reference for moving points (the borders of the figure
 
921
         * or, for example, the borders of the drawing containing the figure)
 
922
         */
 
923
        public abstract void rescaleY(double formerY, double newY, double percent, LaTeXDrawRectangle bound);
 
924
 
 
925
 
 
926
 
 
927
 
 
928
        /**
 
929
         * Allows to rotate, following the angle of rotation, the given point.
 
930
         * @param p The point to rotate.
 
931
         * @return The new point rotated.
 
932
         */
 
933
        public LaTeXDrawPoint2D rotatePoint(LaTeXDrawPoint2D p)
 
934
        {
 
935
                return rotatePoint(p, gravityCenter, rotationAngle);
 
936
        }
 
937
 
 
938
 
 
939
 
 
940
 
 
941
        /**
 
942
         * Allows to rotate a point with the gravity centre of the figure.
 
943
         * @param p The point to rotate.
 
944
         * @param theta The angle of rotation.
 
945
         * @return The rotated point.
 
946
         */
 
947
        public synchronized LaTeXDrawPoint2D rotatePoint(LaTeXDrawPoint2D p, double theta)
 
948
        {
 
949
                return rotatePoint(p, getGravityCenter(), theta);
 
950
        }
 
951
 
 
952
 
 
953
        
 
954
        
 
955
        /**
 
956
         * Allows to rotate a point with as reference an other point.
 
957
         * @param p The point to rotate.
 
958
         * @param gravityC The point of reference.
 
959
         * @param theta The angle of rotation (in rad).
 
960
         * @return The rotated point.
 
961
         */
 
962
        public static LaTeXDrawPoint2D rotatePoint(LaTeXDrawPoint2D p, LaTeXDrawPoint2D gravityC, double theta)
 
963
        {
 
964
                LaTeXDrawPoint2D pt = new LaTeXDrawPoint2D();
 
965
                double cosTheta;
 
966
                double sinTheta;
 
967
                
 
968
                if(theta<0.)
 
969
                        theta = 2.*PI + theta;
 
970
                
 
971
                if((theta%(2.*PI))==0.)
 
972
                        return (LaTeXDrawPoint2D)p.clone();
 
973
                
 
974
                if(Math.abs(theta%(2.*PI)-PI/2.)<0.000001)
 
975
                {       
 
976
                        cosTheta = 0.;
 
977
                        sinTheta = 1.;
 
978
                }
 
979
                else
 
980
                {
 
981
                        if(Math.abs(theta%(2.*PI)-PI)<0.000001)
 
982
                        {
 
983
                                cosTheta = -1.;
 
984
                                sinTheta = 0.;
 
985
                        }
 
986
                        else
 
987
                        {
 
988
                                if(Math.abs(theta%(2.*PI)-(3.*PI/2.))<0.000001)
 
989
                                {
 
990
                                        cosTheta = 0.;
 
991
                                        sinTheta = -1.;
 
992
                                }
 
993
                                else
 
994
                                {
 
995
                                        cosTheta = Math.cos(theta);
 
996
                                        sinTheta = Math.sin(theta);
 
997
                                }
 
998
                        }
 
999
                }
 
1000
 
 
1001
                pt.x = cosTheta * (p.x - gravityC.x) - sinTheta * (p.y - gravityC.y) + gravityC.x;
 
1002
                pt.y = sinTheta * (p.x - gravityC.x) + cosTheta * (p.y - gravityC.y) + gravityC.y;
 
1003
 
 
1004
                return pt;
 
1005
        }
 
1006
        
 
1007
        
 
1008
 
 
1009
 
 
1010
        /**
 
1011
         * Allows to rotate, following the negation of angle of rotation, the given point.
 
1012
         * @param p The point to rotate.
 
1013
         * @return The new point rotated.
 
1014
         */
 
1015
        public LaTeXDrawPoint2D rotateInvertPoint(LaTeXDrawPoint2D p)
 
1016
        {
 
1017
                LaTeXDrawPoint2D pt = new LaTeXDrawPoint2D();
 
1018
                double angle = -rotationAngle;
 
1019
                double cosTheta;
 
1020
                double sinTheta;
 
1021
 
 
1022
                if(angle<0)
 
1023
                        angle = 2.*PI + angle;
 
1024
                
 
1025
                angle = angle%(2.*PI);
 
1026
                
 
1027
                if(angle==0.)
 
1028
                        return (LaTeXDrawPoint2D)p.clone();
 
1029
                
 
1030
                if(Math.abs(angle-(PI/2.))<0.000001)
 
1031
                {       
 
1032
                        cosTheta = 0.;
 
1033
                        sinTheta = 1.;
 
1034
                }
 
1035
                else
 
1036
                {
 
1037
                        if(Math.abs(angle-PI)<0.000001)
 
1038
                        {
 
1039
                                cosTheta = -1.;
 
1040
                                sinTheta = 0.;
 
1041
                        }
 
1042
                        else
 
1043
                        {
 
1044
                                if(Math.abs(angle-(3.*PI/2.))<0.000001)
 
1045
                                {
 
1046
                                        cosTheta = 0.;
 
1047
                                        sinTheta = -1.;
 
1048
                                }
 
1049
                                else
 
1050
                                {
 
1051
                                        cosTheta = Math.cos(angle);
 
1052
                                        sinTheta = Math.sin(angle);
 
1053
                                }
 
1054
                        }
 
1055
                }
 
1056
                
 
1057
                pt.x = cosTheta * (p.x - gravityCenter.x) - sinTheta * (p.y - gravityCenter.y) + gravityCenter.x;
 
1058
                pt.y = sinTheta * (p.x - gravityCenter.x) + cosTheta * (p.y - gravityCenter.y) + gravityCenter.y;
 
1059
 
 
1060
                return pt;
 
1061
        }
 
1062
 
 
1063
 
 
1064
 
 
1065
 
 
1066
        /**
 
1067
         * Allows to rotate, following the angle of rotation, the given point.
 
1068
         * @param p The point to rotate.
 
1069
         * @return The new point rotated.
 
1070
         */
 
1071
        public LaTeXDrawPoint2D rotatePoint(Point p)
 
1072
        {
 
1073
                return rotatePoint(new LaTeXDrawPoint2D(p.x, p.y));
 
1074
        }
 
1075
 
 
1076
 
 
1077
 
 
1078
 
 
1079
        /**
 
1080
         * Allows to rotate, following the negation of the angle of rotation, the given point.
 
1081
         * @param p The point to rotate.
 
1082
         * @return The new point rotated.
 
1083
         */
 
1084
        public LaTeXDrawPoint2D rotateInvertPoint(Point p)
 
1085
        {
 
1086
                return rotateInvertPoint(new LaTeXDrawPoint2D(p.x, p.y));
 
1087
        }
 
1088
 
 
1089
 
 
1090
 
 
1091
 
 
1092
        /**
 
1093
         * Actions to do when the figure is released.
 
1094
         */
 
1095
        public synchronized void onDelimitorRelease()
 
1096
        {
 
1097
                updateStyleOfDelimitors();
 
1098
                dSelected = null;
 
1099
                if(borders != null)
 
1100
                        borders.onDelimitorRelease();
 
1101
        }
 
1102
 
 
1103
 
 
1104
 
 
1105
 
 
1106
        /**
 
1107
         * Fills a figure.
 
1108
         * @param g The graphics.
 
1109
         * @param antiAlias The antialiasing value.
 
1110
         * @param rendering The rendering value.
 
1111
         * @param alphaInter The alpha interpolation value.
 
1112
         * @param colorRendering The colour rendering value.
 
1113
         * @param s The pattern of the figure to fill.
 
1114
         */
 
1115
        protected void fillFigure(Graphics2D g, Object antiAlias, Object rendering, Object alphaInter, Object colorRendering, Shape s)
 
1116
        {
 
1117
                Color formerColor = g.getColor();
 
1118
                GeneralPath p = new GeneralPath(s);
 
1119
                p.setWindingRule(GeneralPath.WIND_NON_ZERO);
 
1120
                
 
1121
                try
 
1122
                {
 
1123
                        if(!hatchingStyle.equals(PSTricksConstants.TOKEN_FILL_NONE))
 
1124
                        {
 
1125
                                if(hatchingStyle.equals(PSTricksConstants.TOKEN_FILL_SOLID))
 
1126
                                {
 
1127
                                        g.setColor(interiorColor);
 
1128
                                        g.fill(shape);
 
1129
                                        g.setColor(formerColor);
 
1130
                                        return;
 
1131
                                }
 
1132
                                
 
1133
                                if(hatchingStyle.equals(PSTricksConstants.TOKEN_FILL_GRADIENT))
 
1134
                                {
 
1135
                                        LaTeXDrawPoint2D NW = getTheNWPoint();
 
1136
                                        LaTeXDrawPoint2D SE = getTheSEPoint();
 
1137
                                        LaTeXDrawPoint2D pt1 = new LaTeXDrawPoint2D((NW.x+SE.x)/2., NW.y);
 
1138
                                        LaTeXDrawPoint2D pt2 = new LaTeXDrawPoint2D((NW.x+SE.x)/2., SE.y);
 
1139
                                        double angle = gradientAngle%(2*PI);
 
1140
                                        double gradMidPt = gradientMidPoint;
 
1141
                                        if(angle<0)
 
1142
                                                angle = 2*PI + angle;
 
1143
                                        
 
1144
                                        if(angle>=PI)
 
1145
                                        {
 
1146
                                                gradMidPt = 1 - gradientMidPoint;
 
1147
                                                angle = angle-PI;
 
1148
                                        }
 
1149
                                        
 
1150
                                        if(angle!=0)
 
1151
                                        {
 
1152
                                                if((angle%(PI/2.))==0)
 
1153
                                                {
 
1154
                                                        pt1 = new LaTeXDrawPoint2D(NW.x, (NW.y+SE.y)/2.);
 
1155
                                                        pt2 = new LaTeXDrawPoint2D(SE.x, (NW.y+SE.y)/2.);
 
1156
                                                        if(gradMidPt<0.5)
 
1157
                                                                pt1.x = pt2.x - Point2D.distance(pt2.x, pt2.y, SE.x,(NW.y+SE.y)/2.);
 
1158
                                                        pt2.x = (NW.x+(SE.x-NW.x)*gradMidPt);
 
1159
                                                }
 
1160
                                                else
 
1161
                                                {
 
1162
                                                        LaTeXDrawPoint2D cg = getGravityCenter();
 
1163
                                                        Line l2, l;
 
1164
                                                        
 
1165
                                                        pt1 = Figure.rotatePoint(pt1, cg, -angle);
 
1166
                                                        pt2 = Figure.rotatePoint(pt2, cg, -angle);
 
1167
                                                        l = new Line(pt1, pt2, false);
 
1168
                                                        
 
1169
                                                        if(angle>=0 && angle<(PI/2.))
 
1170
                                                                 l2 = l.getPerpendicularLine(NW, false);
 
1171
                                                        else l2 = l.getPerpendicularLine(new LaTeXDrawPoint2D(NW.x,SE.y), false);
 
1172
                                                        
 
1173
                                                        pt1 = l.getIntersection(l2);
 
1174
                                                        double distance = Point2D.distance(cg.x, cg.y, pt1.x, pt1.y);
 
1175
                                                        l.setPointAt(pt1, 0);
 
1176
                                                        LaTeXDrawPoint2D[] pts = l.findPoints(pt1, 2*distance*gradMidPt);
 
1177
                                                        pt2 = pts[0];
 
1178
                                                        
 
1179
                                                        if(gradMidPt<0.5)
 
1180
                                                                pt1 = Figure.rotatePoint(pt1, gravityCenter, PI);
 
1181
                                                }
 
1182
                                        }//if(angle!=0)
 
1183
                                        else 
 
1184
                                        {
 
1185
                                                if(gradMidPt<0.5)
 
1186
                                                        pt1.y = pt2.y - Point2D.distance(pt2.x, pt2.y, (NW.x+SE.x)/2.,SE.y);
 
1187
                                                pt2.y = (NW.y+(SE.y-NW.y)*gradMidPt);
 
1188
                                        }
 
1189
                                        
 
1190
                                        g.setPaint(new GradientPaint(
 
1191
                                                        (float)pt1.x, (float)pt1.y, gradientStartColor, 
 
1192
                                                        (float)pt2.x, (float)pt2.y, gradientEndColor,true));
 
1193
                                        g.fill(p);
 
1194
                                        g.setColor(formerColor);
 
1195
                                        return;
 
1196
                                }
 
1197
                                
 
1198
                                Shape oldClip           = g.getClip();
 
1199
                                Rectangle2D bounds  = s.getBounds2D();
 
1200
                                g.setClip(s);
 
1201
                                
 
1202
                                if(isFilled() || hasShadow())
 
1203
                                {
 
1204
                                        g.setColor(interiorColor);
 
1205
                                        g.fill(bounds);
 
1206
                                }
 
1207
                                
 
1208
                                if(isHatched())
 
1209
                                {
 
1210
                                        Stroke oldStroke = g.getStroke();
 
1211
                                        
 
1212
                                        if(hatchingStyle.equals(PSTricksConstants.TOKEN_FILL_VLINES) || 
 
1213
                                                hatchingStyle.equals(PSTricksConstants.TOKEN_FILL_VLINES_F)) 
 
1214
                                                paintHatchings2(g, hatchingAngle, bounds);
 
1215
                                        else 
 
1216
                                                if(hatchingStyle.equals(PSTricksConstants.TOKEN_FILL_HLINES) || 
 
1217
                                                   hatchingStyle.equals(PSTricksConstants.TOKEN_FILL_HLINES_F)) 
 
1218
                                                paintHatchings2(g, hatchingAngle>0?hatchingAngle-Math.PI/2.:hatchingAngle+Math.PI/2., bounds);
 
1219
                                        else 
 
1220
                                                if(hatchingStyle.equals(PSTricksConstants.TOKEN_FILL_CROSSHATCH) ||
 
1221
                                                   hatchingStyle.equals(PSTricksConstants.TOKEN_FILL_CROSSHATCH_F)) 
 
1222
                                                {
 
1223
                                                        paintHatchings2(g, hatchingAngle, bounds);
 
1224
                                                        paintHatchings2(g, hatchingAngle>0?hatchingAngle-Math.PI/2.:hatchingAngle+Math.PI/2., bounds);
 
1225
                                                }
 
1226
                                        
 
1227
                                        g.setStroke(oldStroke);
 
1228
                                }
 
1229
                                
 
1230
                                g.setClip(oldClip);
 
1231
                        }
 
1232
                        else
 
1233
                                if(isFilled)
 
1234
                                {
 
1235
                                        g.setColor(interiorColor);
 
1236
                                        g.fill(p);
 
1237
                                }
 
1238
                }catch(LaTeXDrawException e)
 
1239
                {
 
1240
                        e.printStackTrace();
 
1241
                }
 
1242
                g.setColor(formerColor);
 
1243
        }
 
1244
 
 
1245
        
 
1246
        
 
1247
        /**
 
1248
         * Paints the hatchings.
 
1249
         * @param g The graphics to paint.
 
1250
         * @param angle The angle of the hatchings (in radian).
 
1251
         * @param clip The clip box.
 
1252
         */
 
1253
        private void paintHatchings2(Graphics2D g, double angle, Rectangle2D clip)
 
1254
        {
 
1255
                if(g==null || clip==null)
 
1256
                        return ;
 
1257
        
 
1258
                double angle2 = angle%(Math.PI*2.);
 
1259
                float halphPI = (float)(Math.PI/2.);
 
1260
                
 
1261
                if(angle2>0)
 
1262
                {
 
1263
                        if((float)angle2>3f*halphPI)
 
1264
                                angle2 = angle2-Math.PI*2.;
 
1265
                        else
 
1266
                                if((float)angle2>halphPI)
 
1267
                                        angle2 = angle2-Math.PI;
 
1268
                }
 
1269
                else
 
1270
                        if((float)angle2<-3f*halphPI)
 
1271
                                angle2 = angle2+Math.PI*2.;
 
1272
                        else
 
1273
                                if((float)angle2<-halphPI)
 
1274
                                        angle2 = angle2+Math.PI;
 
1275
                
 
1276
                Line2D.Double line  = new Line2D.Double();
 
1277
                double val                      = hatchingWidth+hatchingSep;
 
1278
                float fAngle            = (float)angle2;
 
1279
                
 
1280
                g.setStroke(new BasicStroke(hatchingWidth, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER));
 
1281
                g.setPaint(getHatchingColor());
 
1282
                
 
1283
                if(fAngle==0f)
 
1284
                {
 
1285
                        line.y1         = clip.getMinY();
 
1286
                        line.y2         = clip.getMaxY();
 
1287
                        double maxX = clip.getMaxX();
 
1288
                        
 
1289
                        for(double x = clip.getMinX(); x<maxX; x+=val)
 
1290
                        {
 
1291
                                line.x1 = line.x2 = x;
 
1292
                                g.draw(line);
 
1293
                        }
 
1294
                }
 
1295
                else 
 
1296
                        if(fAngle==halphPI || fAngle==-halphPI)
 
1297
                        {
 
1298
                                line.x1         = clip.getMinX();
 
1299
                                line.x2         = clip.getMaxX();
 
1300
                                double maxY = clip.getMaxY();
 
1301
                                
 
1302
                                for(double y = clip.getMinY(); y<maxY; y+=val)
 
1303
                                {
 
1304
                                        line.y1 = line.y2 = y;
 
1305
                                        g.draw(line);
 
1306
                                }
 
1307
                        }
 
1308
                        else 
 
1309
                        {
 
1310
                                double incX = val/Math.cos(angle2);
 
1311
                                double incY = val/Math.sin(angle2);
 
1312
                                double maxX;
 
1313
                                
 
1314
                                if(fAngle>0f) 
 
1315
                                {
 
1316
                                        line.y1 = clip.getMinY();
 
1317
                                        maxX    = clip.getMaxX() + (clip.getMaxY()-(clip.getMinY()<0?clip.getMinY():0)) * Math.tan(angle2);
 
1318
                                }
 
1319
                                else 
 
1320
                                {
 
1321
                                        line.y1 = clip.getMaxY();
 
1322
                                        maxX    = clip.getMaxX() - clip.getMaxY() * Math.tan(angle2);
 
1323
                                }
 
1324
                                
 
1325
                                line.x1 = clip.getMinX();
 
1326
                                line.x2 = line.x1;
 
1327
                                line.y2 = line.y1;
 
1328
                                
 
1329
                                if(((float)incX)<=0f)
 
1330
                                        return ;
 
1331
                                
 
1332
                                while(line.x2 < maxX)
 
1333
                                {
 
1334
                                        line.x2 += incX;
 
1335
                                        line.y1 += incY;
 
1336
                                        g.draw(line);
 
1337
                                }
 
1338
                        }
 
1339
        }
 
1340
        
 
1341
 
 
1342
 
 
1343
        /**
 
1344
         * Allows to know if the point pt is in (or on) the figure.
 
1345
         * @param pt The point
 
1346
         * @return true: if the point is in or on the figure.
 
1347
         */
 
1348
        public boolean isIn(Point pt)
 
1349
        {
 
1350
                return isIn(new LaTeXDrawPoint2D(pt.x, pt.y));
 
1351
        }
 
1352
 
 
1353
 
 
1354
 
 
1355
 
 
1356
        /**
 
1357
         * Allows to know if the point pt is in(or on) the figure.
 
1358
         * @param pt The point
 
1359
         * @return true : if the point is in or on the figure.
 
1360
         */
 
1361
        public abstract boolean isIn(LaTeXDrawPoint2D pt);
 
1362
 
 
1363
 
 
1364
 
 
1365
 
 
1366
        /**
 
1367
         * @return True if the figure is filled by a colour.
 
1368
         */
 
1369
        public synchronized boolean isFilled()
 
1370
        {
 
1371
                return isFilled;
 
1372
        }
 
1373
 
 
1374
 
 
1375
 
 
1376
 
 
1377
        /**
 
1378
         * @return True if a delimiter is selected.
 
1379
         */
 
1380
        public synchronized boolean isADelimitorSelected()
 
1381
        {
 
1382
                return dSelected != null;
 
1383
        }
 
1384
 
 
1385
 
 
1386
 
 
1387
 
 
1388
        /**
 
1389
         * Allows to know if the figure intersects the given shape.
 
1390
         * @param r The shape.
 
1391
         * @return True if the figure intersects the shape.
 
1392
         */
 
1393
        public boolean intersected(Rectangle2D.Double r)
 
1394
        {
 
1395
                if(r==null)
 
1396
                        return false;
 
1397
                
 
1398
                Shape s = createShape2D();
 
1399
                        
 
1400
                Shape sTooSmall = getTooSmallShape(s);
 
1401
                
 
1402
                if(sTooSmall!=null)
 
1403
                        s = sTooSmall;
 
1404
                
 
1405
                BasicStroke wideline = new BasicStroke(thickness);
 
1406
        Shape outline = wideline.createStrokedShape(s);
 
1407
                
 
1408
                return outline.intersects(r) && !outline.contains(r);
 
1409
        }
 
1410
 
 
1411
 
 
1412
 
 
1413
 
 
1414
        /**
 
1415
         * Allows to check if the style is possible.
 
1416
         * @param style The style to check.
 
1417
         * @return True if the style is valid.
 
1418
         */
 
1419
        public static boolean isValidStyle(String style)
 
1420
        {
 
1421
                if(style.equals(PSTricksConstants.LINE_NONE_STYLE)|| 
 
1422
                        style.equals(PSTricksConstants.LINE_DASHED_STYLE) || 
 
1423
                        style.equals(PSTricksConstants.LINE_DOTTED_STYLE))
 
1424
                        return true;
 
1425
 
 
1426
                return false;
 
1427
        }
 
1428
 
 
1429
 
 
1430
 
 
1431
 
 
1432
        /**
 
1433
         * Allows to create a list of the different position of the borders.
 
1434
         * @return The list.
 
1435
         */
 
1436
        public static LaTeXDrawComboBox createBordersPositionChoice()
 
1437
        {
 
1438
                LaTeXDrawComboBox dbPositionChoice = new LaTeXDrawComboBox();
 
1439
                dbPositionChoice.setRenderer(new LabelListCellRenderer());
 
1440
 
 
1441
                JLabel label = new JLabel(PSTricksConstants.BORDERS_OUTSIDE);
 
1442
                label.setName(PSTricksConstants.BORDERS_OUTSIDE);
 
1443
                label.setIcon(LaTeXDrawResources.innerIcon);
 
1444
                dbPositionChoice.addItem(label);
 
1445
 
 
1446
                label = new JLabel(PSTricksConstants.BORDERS_INSIDE);
 
1447
                label.setName(PSTricksConstants.BORDERS_INSIDE);
 
1448
                label.setIcon(LaTeXDrawResources.outerIcon);
 
1449
                dbPositionChoice.addItem(label);
 
1450
 
 
1451
                label = new JLabel(PSTricksConstants.BORDERS_MIDDLE);
 
1452
                label.setName(PSTricksConstants.BORDERS_MIDDLE);
 
1453
                label.setIcon(LaTeXDrawResources.middleIcon);
 
1454
                dbPositionChoice.addItem(label);
 
1455
 
 
1456
                dbPositionChoice.setName(Figure.LABEL_BORDERS_POSITION_CHOICE);
 
1457
                dbPositionChoice.setActionCommand(Figure.LABEL_BORDERS_POSITION_CHOICE);
 
1458
                dbPositionChoice.setSelectedItem(Figure.DEFAULT_BORDERS_POSITION);
 
1459
 
 
1460
                return dbPositionChoice;
 
1461
        }
 
1462
 
 
1463
 
 
1464
        
 
1465
        
 
1466
        /**
 
1467
         * Allows to create a list of the different style of line.
 
1468
         * @return The list.
 
1469
         */
 
1470
        public static LaTeXDrawComboBox createStyleLineChoice()
 
1471
        {
 
1472
                LaTeXDrawComboBox lineChoice  = new LaTeXDrawComboBox();
 
1473
                lineChoice.setRenderer(new LabelListCellRenderer());
 
1474
                JLabel label = new JLabel(PSTricksConstants.LINE_NONE_STYLE);
 
1475
                label.setName(PSTricksConstants.LINE_NONE_STYLE);
 
1476
                label.setIcon(LaTeXDrawResources.lineStyleNoneIcon);
 
1477
        lineChoice.addItem(label);
 
1478
                label = new JLabel(PSTricksConstants.LINE_DASHED_STYLE);
 
1479
                label.setName(PSTricksConstants.LINE_DASHED_STYLE);
 
1480
                label.setIcon(LaTeXDrawResources.lineStyleDashedIcon);
 
1481
        lineChoice.addItem(label);
 
1482
        label = new JLabel(PSTricksConstants.LINE_DOTTED_STYLE);
 
1483
        label.setName(PSTricksConstants.LINE_DOTTED_STYLE);
 
1484
                label.setIcon(LaTeXDrawResources.lineStyleDottedIcon);
 
1485
        lineChoice.addItem(label);      
 
1486
        
 
1487
        lineChoice.setSelectedItem(PSTricksConstants.LINE_NONE_STYLE);
 
1488
        
 
1489
        return lineChoice;
 
1490
        }
 
1491
        
 
1492
        
 
1493
 
 
1494
 
 
1495
        /**
 
1496
         * Allows to create a list containing all kinds of hatch.
 
1497
         * @return A JComboBox.
 
1498
         */
 
1499
        public static LaTeXDrawComboBox createFillChoice()
 
1500
        {
 
1501
                LaTeXDrawComboBox list = new LaTeXDrawComboBox();
 
1502
                list.setRenderer(new LabelListCellRenderer());
 
1503
                list.setName(LABEL_HATCH_CHOICE);
 
1504
                list.setActionCommand(LABEL_HATCH_CHOICE);
 
1505
 
 
1506
                JLabel l = new JLabel(PSTricksConstants.TOKEN_FILL_NONE);
 
1507
                l.setName(PSTricksConstants.TOKEN_FILL_NONE);
 
1508
                l.setIcon(LaTeXDrawResources.hatchNoneIcon);
 
1509
                list.addItem(l);
 
1510
                l = new JLabel(PSTricksConstants.TOKEN_FILL_CROSSHATCH);
 
1511
                l.setName(PSTricksConstants.TOKEN_FILL_CROSSHATCH);
 
1512
                l.setIcon(LaTeXDrawResources.hatchCrossIcon);
 
1513
                list.addItem(l);
 
1514
                l = new JLabel(PSTricksConstants.TOKEN_FILL_HLINES);
 
1515
                l.setName(PSTricksConstants.TOKEN_FILL_HLINES);
 
1516
                l.setIcon(LaTeXDrawResources.hatchHorizIcon);
 
1517
                list.addItem(l);
 
1518
                l = new JLabel(PSTricksConstants.TOKEN_FILL_VLINES);
 
1519
                l.setName(PSTricksConstants.TOKEN_FILL_VLINES);
 
1520
                l.setIcon(LaTeXDrawResources.hatchVertIcon);
 
1521
                list.addItem(l);
 
1522
                l = new JLabel(PSTricksConstants.TOKEN_FILL_GRADIENT);
 
1523
                l.setName(PSTricksConstants.TOKEN_FILL_GRADIENT);
 
1524
                l.setIcon(LaTeXDrawResources.gradientIcon);
 
1525
                list.addItem(l);
 
1526
 
 
1527
                return list;
 
1528
        }
 
1529
 
 
1530
 
 
1531
 
 
1532
 
 
1533
        /**
 
1534
         * Allows to obtain the point most to the North and on the West of the figure.
 
1535
         * @return the point most to the North and on the West of the figure.
 
1536
         */
 
1537
        public LaTeXDrawPoint2D getTheNWPoint()
 
1538
        {
 
1539
                if(borders != null)
 
1540
                        return borders.getTheNWPoint();
 
1541
                return null;
 
1542
        }
 
1543
 
 
1544
 
 
1545
 
 
1546
 
 
1547
        /**
 
1548
         * Allows to get the south-east point by taking into account the angle of rotation.
 
1549
         * @return The south-east point of the rotated rectangle.
 
1550
         */
 
1551
        public synchronized LaTeXDrawPoint2D getTheSERotatedPoint()
 
1552
        {
 
1553
                if(borders != null)
 
1554
                        return borders.getTheSERotatedPoint();
 
1555
                return null;
 
1556
        }
 
1557
 
 
1558
 
 
1559
 
 
1560
 
 
1561
        /**
 
1562
         * Allows to get the north-west point by taking into account the angle of rotation.
 
1563
         * @return The north-west point of the rotated rectangle.
 
1564
         */
 
1565
        public LaTeXDrawPoint2D getTheNWRotatedPoint()
 
1566
        {
 
1567
                if(borders != null)
 
1568
                        return borders.getTheNWRotatedPoint();
 
1569
                return null;
 
1570
        }
 
1571
 
 
1572
 
 
1573
 
 
1574
 
 
1575
        /**
 
1576
         * Allows to get a clone of the centre of gravity of the figure.
 
1577
         * @return The centre of gravity of the figure.
 
1578
         */
 
1579
        public synchronized LaTeXDrawPoint2D getGravityCenter()
 
1580
        {
 
1581
                updateGravityCenter();
 
1582
                return (LaTeXDrawPoint2D)gravityCenter.clone();
 
1583
        }
 
1584
 
 
1585
 
 
1586
 
 
1587
 
 
1588
        /**
 
1589
         * Allows to get the LaTeX code of the figure.
 
1590
         * @return the LaTeX code of the figure.
 
1591
         */
 
1592
        public abstract String getCodePSTricks(DrawBorders drawBorders, float ppc);
 
1593
 
 
1594
 
 
1595
 
 
1596
 
 
1597
        /**
 
1598
         * Allows to get the colour of the borders of the figure.
 
1599
         * @return The colour of the borders of the figure.
 
1600
         */
 
1601
        public synchronized Color getLinesColor()
 
1602
        {
 
1603
                return linesColor;
 
1604
        }
 
1605
 
 
1606
 
 
1607
 
 
1608
 
 
1609
        /**
 
1610
         * @return The borders of the figure.
 
1611
         */
 
1612
        public synchronized LaTeXDrawRectangle getBorders()
 
1613
        {
 
1614
                return borders;
 
1615
        }
 
1616
 
 
1617
 
 
1618
 
 
1619
        /**
 
1620
         * @return The colour of the interior of the figure.
 
1621
         */
 
1622
        public synchronized Color getInteriorColor()
 
1623
        {
 
1624
                return interiorColor;
 
1625
        }
 
1626
 
 
1627
 
 
1628
 
 
1629
        /**
 
1630
         * @return The style of the lines of the figure.
 
1631
         */
 
1632
        public synchronized String getLineStyle()
 
1633
        {
 
1634
                return lineStyle;
 
1635
        }
 
1636
 
 
1637
 
 
1638
 
 
1639
        /**
 
1640
         * @return The kind of hatch.
 
1641
         */
 
1642
        public synchronized String getHatchingStyle()
 
1643
        {
 
1644
                return hatchingStyle;
 
1645
        }
 
1646
 
 
1647
 
 
1648
 
 
1649
        /**
 
1650
         * @return The colour of the hatch.
 
1651
         */
 
1652
        public synchronized Color getHatchingColor()
 
1653
        {
 
1654
                return hatchingColor;
 
1655
        }
 
1656
 
 
1657
 
 
1658
 
 
1659
        /**
 
1660
         * @return The width of the lines of the hatch.
 
1661
         */
 
1662
        public synchronized float getHatchingWidth()
 
1663
        {
 
1664
                return hatchingWidth;
 
1665
        }
 
1666
 
 
1667
 
 
1668
 
 
1669
        /**
 
1670
         * @return The thickness of the figure.
 
1671
         */
 
1672
        public synchronized float getThickness()
 
1673
        {
 
1674
                return thickness;
 
1675
        }
 
1676
 
 
1677
 
 
1678
 
 
1679
        /**
 
1680
         * Corresponds to what to do when the user click on the figure.
 
1681
         * @param pt The clicked point.
 
1682
         */
 
1683
        public synchronized void onClick(Point pt)
 
1684
        {
 
1685
                isSelected = true;
 
1686
 
 
1687
                if (borders != null)
 
1688
                        borders.onClick(pt);
 
1689
        }
 
1690
 
 
1691
 
 
1692
 
 
1693
 
 
1694
        /**
 
1695
         * Corresponds to what to do when the user release the mouse.
 
1696
         */
 
1697
        public synchronized void onRelease()
 
1698
        {
 
1699
                setOnRotation(false);
 
1700
                isSelected = false;
 
1701
                dSelected = null;
 
1702
                if(borders != null)
 
1703
                        borders.onRelease();
 
1704
        }
 
1705
 
 
1706
 
 
1707
 
 
1708
 
 
1709
        /**
 
1710
         * Allows to obtain the point most to the South and on the East of the figure.
 
1711
         * @return the point most to the South and on the East of the figure.
 
1712
         */
 
1713
        public synchronized LaTeXDrawPoint2D getTheSEPoint()
 
1714
        {
 
1715
                if(borders != null)
 
1716
                        return borders.getTheSEPoint();
 
1717
                return null;
 
1718
        }
 
1719
 
 
1720
 
 
1721
 
 
1722
 
 
1723
        /**
 
1724
         * @return True if the figure is selected.
 
1725
         */
 
1726
        public synchronized boolean isSelected()
 
1727
        {
 
1728
                return isSelected;
 
1729
        }
 
1730
 
 
1731
 
 
1732
 
 
1733
 
 
1734
        /**
 
1735
         * Allows to update the centre of gravity of the figure (Useful for rotation).
 
1736
         */
 
1737
        public synchronized void updateGravityCenter()
 
1738
        {
 
1739
                if(borders==null)
 
1740
                        return ;
 
1741
                
 
1742
                borders.updateGravityCenter();
 
1743
                
 
1744
                LaTeXDrawPoint2D gc = borders.getGravityCenter();
 
1745
                
 
1746
                if(gravityCenter!=null)
 
1747
                {
 
1748
                        if(gc!=null)
 
1749
                                gravityCenter.setLocation(gc);
 
1750
                }
 
1751
                else gravityCenter = gc;
 
1752
        }
 
1753
 
 
1754
 
 
1755
 
 
1756
        /**
 
1757
         * @return Returns the isCustomizable.
 
1758
         */
 
1759
        public synchronized boolean isCustomizable()
 
1760
        {
 
1761
                return isCustomizable;
 
1762
        }
 
1763
 
 
1764
 
 
1765
 
 
1766
        /**
 
1767
         * @return Returns the isThicknessable.
 
1768
         */
 
1769
        public synchronized boolean isThicknessable()
 
1770
        {
 
1771
                return isThicknessable;
 
1772
        }
 
1773
 
 
1774
 
 
1775
 
 
1776
        /**
 
1777
         * @return Returns the doubleSep.
 
1778
         */
 
1779
        public synchronized double getDoubleSep()
 
1780
        {
 
1781
                return doubleSep;
 
1782
        }
 
1783
 
 
1784
 
 
1785
 
 
1786
        /**
 
1787
         * @param doubleSep The doubleSep to set.
 
1788
         */
 
1789
        public synchronized void setDoubleSep(double doubleSep)
 
1790
        {
 
1791
                if(!Double.isInfinite(doubleSep) && !Double.isNaN(doubleSep))
 
1792
                        this.doubleSep = doubleSep;
 
1793
        }
 
1794
 
 
1795
 
 
1796
 
 
1797
        /**
 
1798
         * @return Returns the hasDoubleBoundary.
 
1799
         */
 
1800
        public synchronized boolean hasDoubleBoundary()
 
1801
        {
 
1802
                return hasDoubleBoundary;
 
1803
        }
 
1804
 
 
1805
 
 
1806
 
 
1807
        /**
 
1808
         * @param hasDoubleBoundary The hasDoubleBoundary to set.
 
1809
         */
 
1810
        public synchronized void setHasDoubleBoundary(boolean hasDoubleBoundary)
 
1811
        {
 
1812
                this.hasDoubleBoundary = hasDoubleBoundary;
 
1813
                updateShape();
 
1814
        }
 
1815
 
 
1816
 
 
1817
 
 
1818
        /**
 
1819
         * @return Returns the isDashableOrDotable.
 
1820
         */
 
1821
        public synchronized boolean isDashableOrDotable()
 
1822
        {
 
1823
                return isDashableOrDotable;
 
1824
        }
 
1825
 
 
1826
 
 
1827
 
 
1828
        /**
 
1829
         * @return Returns the isDoubleBoundaryable.
 
1830
         */
 
1831
        public synchronized boolean isDoubleBoundaryable()
 
1832
        {
 
1833
                return isDoubleBoundaryable;
 
1834
        }
 
1835
 
 
1836
 
 
1837
 
 
1838
        /**
 
1839
         * @param isCustomizable The isCustomizable to set.
 
1840
         */
 
1841
        public synchronized void setCustomizable(boolean isCustomizable)
 
1842
        {
 
1843
                this.isCustomizable = isCustomizable;
 
1844
        }
 
1845
 
 
1846
 
 
1847
 
 
1848
        /**
 
1849
         * @return Returns the isResizable.
 
1850
         */
 
1851
        public synchronized boolean isResizable()
 
1852
        {
 
1853
                return isResizable;
 
1854
        }
 
1855
 
 
1856
 
 
1857
 
 
1858
        /**
 
1859
         * @param isResizable The isResizable to set.
 
1860
         */
 
1861
        public synchronized void setResizable(boolean isResizable)
 
1862
        {
 
1863
                this.isResizable = isResizable;
 
1864
        }
 
1865
 
 
1866
 
 
1867
 
 
1868
        /**
 
1869
         * @return Returns the doubleColor.
 
1870
         */
 
1871
        public synchronized Color getDoubleColor()
 
1872
        {
 
1873
                return doubleColor;
 
1874
        }
 
1875
 
 
1876
 
 
1877
 
 
1878
        /**
 
1879
         * @param doublecolor The doubleColor to set.
 
1880
         */
 
1881
        public synchronized void setDoubleColor(Color doublecolor)
 
1882
        {
 
1883
                if(doublecolor!=null)
 
1884
                        this.doubleColor = doublecolor;
 
1885
        }
 
1886
 
 
1887
 
 
1888
 
 
1889
        /**
 
1890
         * @return Returns the doubleLinePosition.
 
1891
         */
 
1892
        public synchronized String getBordersPosition()
 
1893
        {
 
1894
                return bordersPosition;
 
1895
        }
 
1896
 
 
1897
 
 
1898
 
 
1899
        /**
 
1900
         * @param doubleLinePosition The doubleLinePosition to set.
 
1901
         */
 
1902
        public synchronized void setBordersPosition(String doubleLinePosition)
 
1903
        {
 
1904
                if(isValidBordersPosition(doubleLinePosition) && isBordersMovable)
 
1905
                {
 
1906
                        this.bordersPosition = doubleLinePosition;
 
1907
                        updateShape();
 
1908
                }
 
1909
        }
 
1910
 
 
1911
 
 
1912
 
 
1913
        /**
 
1914
         * Allows to get the north-westiest point of the bounds of the figure (the
 
1915
         * bounds consider the thickness of the figure and the position of the  borders).
 
1916
         * @return The north-westiest point of the bounds of the figure
 
1917
         */
 
1918
        public LaTeXDrawPoint2D getTheNWBoundPoint()
 
1919
        {
 
1920
                Rectangle2D bounds = createShape2D().getBounds2D();
 
1921
 
 
1922
                if(bounds == null)
 
1923
                        return null;
 
1924
 
 
1925
                if(hasShadow)
 
1926
                {
 
1927
                        double dx=0, dy=0;
 
1928
                        LaTeXDrawPoint2D cg = getGravityCenter();
 
1929
                        LaTeXDrawPoint2D shadowCg = (LaTeXDrawPoint2D)cg.clone();
 
1930
                        shadowCg.setLocation(cg.x+shadowSize, cg.y);
 
1931
                        shadowCg = Figure.rotatePoint(shadowCg, cg, shadowAngle);
 
1932
                        dx = shadowCg.x-cg.x;
 
1933
                        dy = cg.y-shadowCg.y;
 
1934
                        Rectangle2D.Double bounds2 = new Rectangle2D.Double(bounds.getX()+dx,bounds.getY()+dy,
 
1935
                                                                                        bounds.getWidth(), bounds.getHeight());
 
1936
                        bounds2.add(bounds);
 
1937
                        bounds = bounds2;
 
1938
                }
 
1939
                
 
1940
                return new LaTeXDrawPoint2D(bounds.getX()-thickness/2., bounds.getY()-thickness/2.);
 
1941
        }
 
1942
 
 
1943
 
 
1944
        
 
1945
        
 
1946
        /**
 
1947
         * Allows to get the north-westiest point of the bounds of the figure (the
 
1948
         * bounds consider the thickness of the figure and the position of the
 
1949
         * borders), without any rotation of the figure. It doesn't take account  of the shadow.
 
1950
         */
 
1951
        public LaTeXDrawPoint2D getTheNWNonRotatedBoundPoint()
 
1952
        {
 
1953
                Rectangle2D bounds = createNonRotatedShape2D().getBounds2D();
 
1954
 
 
1955
                if(bounds == null)
 
1956
                        return null;
 
1957
 
 
1958
                return new LaTeXDrawPoint2D(bounds.getMinX() - thickness / 2., 
 
1959
                                                                        bounds.getMinY() - thickness / 2.);
 
1960
        }
 
1961
 
 
1962
        
 
1963
        
 
1964
        
 
1965
 
 
1966
        /**
 
1967
         * Allows to get the south-eastiest point of the bounds of the figure (the
 
1968
         * bounds consider the thickness of the figure and the position of the
 
1969
         * borders), without any rotation of the figure. It doesn't take account of the shadow.
 
1970
         * @return The south-eastiest point of the bounds of the figure.
 
1971
         */
 
1972
        public LaTeXDrawPoint2D getTheSENonRotatedBoundPoint()
 
1973
        {
 
1974
                Rectangle2D bounds = createNonRotatedShape2D().getBounds2D();
 
1975
 
 
1976
                if (bounds == null)
 
1977
                        return null;
 
1978
 
 
1979
                return new LaTeXDrawPoint2D(bounds.getMaxX() + thickness / 2., bounds.getMaxY() + thickness / 2.);
 
1980
        }
 
1981
        
 
1982
        
 
1983
        
 
1984
 
 
1985
        /**
 
1986
         * Allows to get the south-eastiest point of the bounds of the figure (the
 
1987
         * bounds consider the thickness of the figure and the position of the borders).
 
1988
         * @return The south-eastiest point of the bounds of the figure.
 
1989
         */
 
1990
        public LaTeXDrawPoint2D getTheSEBoundPoint()
 
1991
        {
 
1992
                Rectangle2D bounds = createShape2D().getBounds2D();
 
1993
 
 
1994
                if(bounds == null)
 
1995
                        return null;
 
1996
                
 
1997
                if(hasShadow)
 
1998
                {
 
1999
                        double dx=0, dy=0;
 
2000
                        LaTeXDrawPoint2D cg = getGravityCenter();
 
2001
                        LaTeXDrawPoint2D shadowCg = (LaTeXDrawPoint2D)cg.clone();
 
2002
                        shadowCg.setLocation(cg.x+shadowSize, cg.y);
 
2003
                        shadowCg = Figure.rotatePoint(shadowCg, cg, shadowAngle);
 
2004
                        dx = shadowCg.x-cg.x;
 
2005
                        dy = cg.y-shadowCg.y;
 
2006
                        Rectangle2D.Double bounds2 = new Rectangle2D.Double(bounds.getX()+dx,bounds.getY()+dy,
 
2007
                                                                                        bounds.getWidth(), bounds.getHeight());
 
2008
                        bounds2.add(bounds);
 
2009
                        bounds = bounds2;
 
2010
                }
 
2011
 
 
2012
                return new LaTeXDrawPoint2D(bounds.getX() + thickness / 2.
 
2013
                                + bounds.getWidth(), bounds.getY() + thickness / 2. + bounds.getHeight());
 
2014
        }
 
2015
 
 
2016
 
 
2017
 
 
2018
        /**
 
2019
         * @return True if the borders of the figure can move.
 
2020
         */
 
2021
        public synchronized boolean isBordersMovable()
 
2022
        {
 
2023
                return isBordersMovable;
 
2024
        }
 
2025
        
 
2026
        
 
2027
        
 
2028
        /**
 
2029
         * Allows to change the number of the figure.
 
2030
         */
 
2031
        public synchronized void changeMeter()
 
2032
        {
 
2033
                number = meter++;
 
2034
        }
 
2035
        
 
2036
 
 
2037
        
 
2038
        /**
 
2039
         * Allows to compute the angle of the point pt.
 
2040
         * @param pt The point of reference.
 
2041
         * @param gravityC The centre of gravity of the trigonometric circle.
 
2042
         * @return The angle.
 
2043
         */
 
2044
        public static double computeAngle(Point pt, LaTeXDrawPoint2D gravityC)
 
2045
        {
 
2046
                double c = gravityC.y-pt.y;
 
2047
                double b = gravityC.x-pt.x;
 
2048
                
 
2049
                return atan(c/b);
 
2050
        }
 
2051
        
 
2052
        
 
2053
        
 
2054
        
 
2055
        /**
 
2056
         * Allows to compute the angle of rotation between two points.
 
2057
         * using the gravity centre of the figure.
 
2058
         * @param formerPt The first point.
 
2059
         * @param newPt The second point.
 
2060
         * @return The rotation point.
 
2061
         * @throws IllegalArgumentException If formerPt or newPt are null.
 
2062
         */
 
2063
        public double computeRotationAngle(Point formerPt, Point newPt) throws IllegalArgumentException
 
2064
        {
 
2065
                double thetaOld = Figure.computeAngle(formerPt, gravityCenter);
 
2066
                double thetaNew = Figure.computeAngle(newPt, gravityCenter);
 
2067
 
 
2068
                if((thetaNew-thetaOld)>(PI/2.) || (thetaNew-thetaOld)<-(PI/2.))
 
2069
                        return thetaNew+thetaOld;
 
2070
 
 
2071
                return thetaNew-thetaOld;
 
2072
        }
 
2073
        
 
2074
        
 
2075
        
 
2076
        
 
2077
        /**
 
2078
         * Allows to rotate the figure around its gravity centre.
 
2079
         * @param formerPt The former point.
 
2080
         * @param newPt The new point.
 
2081
         * @throws IllegalArgumentException If formerPt or newPt is null.
 
2082
         */
 
2083
        public void rotate(Point formerPt, Point newPt) throws IllegalArgumentException
 
2084
        {
 
2085
                setRotationAngle(rotationAngle+computeRotationAngle(formerPt, newPt));
 
2086
        }
 
2087
        
 
2088
        
 
2089
        
 
2090
        
 
2091
        /**
 
2092
         * Allows rotate the figure around the point gravityC.
 
2093
         * @param gravityC The point of reference of the rotation.
 
2094
         * @param angle The angle of the rotation.
 
2095
         */
 
2096
        public void rotate(LaTeXDrawPoint2D gravityC, double angle)
 
2097
        {
 
2098
                if(!gravityC.equals(gravityCenter))
 
2099
                {// We must rotate the position of the figure
 
2100
                        LaTeXDrawPoint2D rotGC = rotatePoint(gravityCenter, gravityC, angle);
 
2101
                        shift(gravityCenter, rotGC);
 
2102
                        updateGravityCenter();
 
2103
                }
 
2104
                
 
2105
                setRotationAngle(rotationAngle+angle);
 
2106
        }
 
2107
 
 
2108
 
 
2109
 
 
2110
        /**
 
2111
         * @return the blackDashLength.
 
2112
         */
 
2113
        public synchronized float getBlackDashLength()
 
2114
        {
 
2115
                return blackDashLength;
 
2116
        }
 
2117
 
 
2118
 
 
2119
 
 
2120
        /**
 
2121
         * @param blackDashLength the blackDashLength to set.
 
2122
         */
 
2123
        public synchronized void setBlackDashLength(float blackDashLength)
 
2124
        {
 
2125
                if(blackDashLength>0 && !Float.isInfinite(blackDashLength) && !Float.isNaN(blackDashLength))
 
2126
                        this.blackDashLength = blackDashLength;
 
2127
        }
 
2128
 
 
2129
 
 
2130
 
 
2131
        /**
 
2132
         * @return the hatchingAngle.
 
2133
         */
 
2134
        public synchronized double getHatchingAngle()
 
2135
        {
 
2136
                return hatchingAngle;
 
2137
        }
 
2138
 
 
2139
 
 
2140
 
 
2141
        /**
 
2142
         * @param hatchingAngle the hatchingAngle to set.
 
2143
         */
 
2144
        public synchronized void setHatchingAngle(double hatchingAngle)
 
2145
        {
 
2146
                if(!Double.isInfinite(hatchingAngle) && !Double.isNaN(hatchingAngle))
 
2147
                        this.hatchingAngle = hatchingAngle%(Math.PI*2.);
 
2148
        }
 
2149
 
 
2150
 
 
2151
 
 
2152
        /**
 
2153
         * @return the whiteDashLength.
 
2154
         */
 
2155
        public synchronized float getWhiteDashLength()
 
2156
        {
 
2157
                return whiteDashLength;
 
2158
        }
 
2159
 
 
2160
 
 
2161
 
 
2162
        /**
 
2163
         * @param whiteDashLength the whiteDashLength to set.
 
2164
         */
 
2165
        public synchronized void setWhiteDashLength(float whiteDashLength)
 
2166
        {
 
2167
                if(whiteDashLength>0 && !Float.isInfinite(whiteDashLength) && !Float.isNaN(whiteDashLength))
 
2168
                        this.whiteDashLength = whiteDashLength;
 
2169
        }
 
2170
 
 
2171
 
 
2172
 
 
2173
        /**
 
2174
         * @return the dotSep.
 
2175
         */
 
2176
        public synchronized float getDotSep()
 
2177
        {
 
2178
                return dotSep;
 
2179
        }
 
2180
 
 
2181
 
 
2182
 
 
2183
        /**
 
2184
         * @param dotSep the dotSep to set.
 
2185
         */
 
2186
        public synchronized void setDotSep(float dotSep)
 
2187
        {
 
2188
                if(dotSep>0 && !Float.isInfinite(dotSep) && !Float.isNaN(dotSep))
 
2189
                        this.dotSep = dotSep;
 
2190
        }
 
2191
        
 
2192
        
 
2193
        
 
2194
        /**
 
2195
         * Allows to update the shape of the figure.
 
2196
         */
 
2197
        public abstract void updateShape();
 
2198
        
 
2199
        
 
2200
        /**
 
2201
         * Allows to know if the figure is too small to be rescaled.
 
2202
         * @return True if the figure is too small to be rescaled.
 
2203
         */
 
2204
        public abstract boolean isTooSmallToBeRescaled();
 
2205
 
 
2206
 
 
2207
 
 
2208
        /**
 
2209
         * @return the hasShadow.
 
2210
         * @since 1.7
 
2211
         */
 
2212
        public synchronized boolean hasShadow()
 
2213
        {
 
2214
                return hasShadow;
 
2215
        }
 
2216
 
 
2217
 
 
2218
 
 
2219
        /**
 
2220
         * @param hasShadow the hasShadow to set.
 
2221
         * @since 1.7
 
2222
         */
 
2223
        public synchronized void setHasShadow(boolean hasShadow)
 
2224
        {
 
2225
                this.hasShadow = hasShadow;
 
2226
        }
 
2227
 
 
2228
 
 
2229
 
 
2230
        /**
 
2231
         * @return The shadowAngle (in rad).
 
2232
         * @since 1.7
 
2233
         */
 
2234
        public synchronized double getShadowAngle()
 
2235
        {
 
2236
                return shadowAngle;
 
2237
        }
 
2238
 
 
2239
 
 
2240
 
 
2241
        /**
 
2242
         * @param shadowAngle the shadowAngle to set in radian.
 
2243
         * @since 1.7
 
2244
         */
 
2245
        public synchronized void setShadowAngle(double shadowAngle)
 
2246
        {
 
2247
                if(!Double.isInfinite(shadowAngle) && !Double.isNaN(shadowAngle))
 
2248
                        this.shadowAngle = shadowAngle%(2*Math.PI);
 
2249
        }
 
2250
 
 
2251
 
 
2252
 
 
2253
        /**
 
2254
         * @return the shadowColor.
 
2255
         * @since 1.7
 
2256
         */
 
2257
        public synchronized Color getShadowColor()
 
2258
        {
 
2259
                return shadowColor;
 
2260
        }
 
2261
 
 
2262
 
 
2263
 
 
2264
        /**
 
2265
         * @param shadowColor the shadowColor to set.
 
2266
         * @since 1.7
 
2267
         */
 
2268
        public synchronized void setShadowColor(Color shadowColor)
 
2269
        {
 
2270
                if(shadowColor!=null)
 
2271
                        this.shadowColor = shadowColor;
 
2272
        }
 
2273
 
 
2274
 
 
2275
 
 
2276
        /**
 
2277
         * @return the shadowSize.
 
2278
         * @since 1.7
 
2279
         */
 
2280
        public synchronized double getShadowSize()
 
2281
        {
 
2282
                return shadowSize;
 
2283
        }
 
2284
 
 
2285
 
 
2286
 
 
2287
        /**
 
2288
         * @param shadowSize the shadowSize to set.
 
2289
         * @since 1.7
 
2290
         */
 
2291
        public synchronized void setShadowSize(double shadowSize)
 
2292
        {
 
2293
                if(!Double.isInfinite(shadowSize) && !Double.isNaN(shadowSize))
 
2294
                        this.shadowSize = shadowSize;
 
2295
        }
 
2296
 
 
2297
 
 
2298
 
 
2299
        /**
 
2300
         * @return the canHaveShadow.
 
2301
         * @since 1.7
 
2302
         */
 
2303
        public boolean canHaveShadow()
 
2304
        {
 
2305
                return canHaveShadow;
 
2306
        }
 
2307
        
 
2308
        
 
2309
        
 
2310
        /**
 
2311
         * Allows to create a shape corresponding to the shadow of the figure.
 
2312
         * @return The shadow.
 
2313
         * @since 1.7
 
2314
         */
 
2315
        public Shape createShadowShape()
 
2316
        {
 
2317
                if(!canHaveShadow || !hasShadow) return shape;
 
2318
                
 
2319
                Rectangle2D shadowS = createShape2D().getBounds2D();
 
2320
                double dx=0, dy=0;
 
2321
                LaTeXDrawPoint2D cg = getGravityCenter();
 
2322
                LaTeXDrawPoint2D shadowCg = (LaTeXDrawPoint2D)cg.clone();
 
2323
                shadowCg.setLocation(cg.x+shadowSize, cg.y);
 
2324
                shadowCg = Figure.rotatePoint(shadowCg, cg, shadowAngle);
 
2325
                dx = shadowCg.x-cg.x;
 
2326
                dy = cg.y-shadowCg.y;
 
2327
                Rectangle2D.Double bounds2 = new Rectangle2D.Double(shadowS.getX()+dx-thickness/2.,
 
2328
                                                                                shadowS.getY()+dy-thickness/2.,
 
2329
                                                                                shadowS.getWidth()+thickness, shadowS.getHeight()+thickness);
 
2330
                return bounds2;
 
2331
        }
 
2332
 
 
2333
 
 
2334
 
 
2335
        /**
 
2336
         * @return the gradientAngle.
 
2337
         * @since 1.7
 
2338
         */
 
2339
        public synchronized double getGradientAngle()
 
2340
        {
 
2341
                return gradientAngle;
 
2342
        }
 
2343
 
 
2344
 
 
2345
 
 
2346
        /**
 
2347
         * @param gradientAngle the gradientAngle to set (in radian).
 
2348
         * @since 1.7
 
2349
         */
 
2350
        public synchronized void setGradientAngle(double gradientAngle)
 
2351
        {
 
2352
                if(!Double.isInfinite(gradientAngle) && !Double.isNaN(gradientAngle))
 
2353
                        this.gradientAngle = gradientAngle;
 
2354
        }
 
2355
 
 
2356
 
 
2357
 
 
2358
        /**
 
2359
         * @return the gradientEndColor.
 
2360
         * @since 1.7
 
2361
         */
 
2362
        public synchronized Color getGradientEndColor()
 
2363
        {
 
2364
                return gradientEndColor;
 
2365
        }
 
2366
 
 
2367
 
 
2368
 
 
2369
        /**
 
2370
         * @param gradientEndColor the gradientEndColor to set.
 
2371
         * @since 1.7
 
2372
         */
 
2373
        public synchronized void setGradientEndColor(Color gradientEndColor)
 
2374
        {
 
2375
                if(gradientEndColor!=null)
 
2376
                        this.gradientEndColor = gradientEndColor;
 
2377
        }
 
2378
 
 
2379
 
 
2380
 
 
2381
        /**
 
2382
         * @return the gradientMidPoint.
 
2383
         * @since 1.7
 
2384
         */
 
2385
        public synchronized double getGradientMidPoint()
 
2386
        {
 
2387
                return gradientMidPoint;
 
2388
        }
 
2389
 
 
2390
 
 
2391
 
 
2392
        /**
 
2393
         * @param gradientMidPoint the gradientMidPoint to set.
 
2394
         * @since 1.7
 
2395
         */
 
2396
        public synchronized void setGradientMidPoint(double gradientMidPoint)
 
2397
        {
 
2398
                if(gradientMidPoint>=0 && gradientMidPoint<=1)
 
2399
                        this.gradientMidPoint = gradientMidPoint;
 
2400
        }
 
2401
 
 
2402
 
 
2403
 
 
2404
        /**
 
2405
         * @return the gradientStartColor.
 
2406
         * @since 1.7
 
2407
         */
 
2408
        public synchronized Color getGradientStartColor()
 
2409
        {
 
2410
                return gradientStartColor;
 
2411
        }
 
2412
 
 
2413
 
 
2414
 
 
2415
        /**
 
2416
         * @param gradientStartColor the gradientStartColor to set.
 
2417
         * @since 1.7
 
2418
         */
 
2419
        public synchronized void setGradientStartColor(Color gradientStartColor)
 
2420
        {
 
2421
                if(gradientStartColor!=null)
 
2422
                        this.gradientStartColor = gradientStartColor;
 
2423
        }
 
2424
        
 
2425
        
 
2426
        
 
2427
        /**
 
2428
         * @return The PSTricks code for the filling of the figure.
 
2429
         * @since 1.7
 
2430
         */
 
2431
        public String getPSTricksCodeFilling(float ppc)
 
2432
        {
 
2433
                String str="fillstyle=";//$NON-NLS-1$
 
2434
 
 
2435
                if(hatchingStyle.equals(PSTricksConstants.TOKEN_FILL_NONE))
 
2436
                {
 
2437
                        if(isFilled)
 
2438
                                str += "solid"; //$NON-NLS-1$
 
2439
                        else str = "";//$NON-NLS-1$
 
2440
                }
 
2441
                else
 
2442
                        if(hatchingStyle.equals(PSTricksConstants.TOKEN_FILL_GRADIENT))
 
2443
                        {
 
2444
                                str+= "gradient,gradlines=2000";//$NON-NLS-1$
 
2445
                                
 
2446
                                if(!gradientStartColor.equals(PSTricksConstants.DEFAULT_GRADIENT_START_COLOR))
 
2447
                                {
 
2448
                                        String name = DviPsColors.getColourName(gradientStartColor);
 
2449
                                        if(name==null)
 
2450
                                        {
 
2451
                                                name = "color"+number+'g';//$NON-NLS-1$
 
2452
                                                DviPsColors.addUserColour(gradientStartColor, name); 
 
2453
                                        }
 
2454
                                        str += ",gradbegin=" + name; //$NON-NLS-1$
 
2455
                                }
 
2456
                                
 
2457
                                if(!gradientEndColor.equals(PSTricksConstants.DEFAULT_GRADIENT_END_COLOR))
 
2458
                                {
 
2459
                                        String name = DviPsColors.getColourName(gradientEndColor);
 
2460
                                        if(name==null)
 
2461
                                        {
 
2462
                                                name = "color"+number+'f';//$NON-NLS-1$
 
2463
                                                DviPsColors.addUserColour(gradientEndColor, name); 
 
2464
                                        }
 
2465
                                        str += ",gradend=" + name; //$NON-NLS-1$
 
2466
                                }
 
2467
                                
 
2468
                                if(gradientMidPoint!=PSTricksConstants.DEFAULT_GRADIENT_MID_POINT)
 
2469
                                        str+=",gradmidpoint="+(float)gradientMidPoint;//$NON-NLS-1$
 
2470
                                
 
2471
                                if(gradientAngle!=PSTricksConstants.DEFAULT_GRADIENT_ANGLE)
 
2472
                                        str+=",gradangle="+(float)toDegrees(gradientAngle);//$NON-NLS-1$
 
2473
                        }
 
2474
                        else
 
2475
                        {
 
2476
                                if(hatchingStyle.equals(PSTricksConstants.TOKEN_FILL_CROSSHATCH))
 
2477
                                        str += "crosshatch"; //$NON-NLS-1$
 
2478
                                else
 
2479
                                        if (hatchingStyle.equals(PSTricksConstants.TOKEN_FILL_HLINES))
 
2480
                                                str += "hlines"; //$NON-NLS-1$
 
2481
                                        else
 
2482
                                                str += "vlines"; //$NON-NLS-1$
 
2483
        
 
2484
                                if(isFilled)
 
2485
                                        str += "*"; //$NON-NLS-1$
 
2486
        
 
2487
                                str += ",hatchwidth=" + (getHatchingWidth()/ppc) + ",hatchangle=" + //$NON-NLS-1$ //$NON-NLS-2$
 
2488
                                                (float)Math.toDegrees(hatchingAngle);
 
2489
                                
 
2490
                                if(((float)hatchingSep)!=((float)DEFAULT_HATCH_SEP))
 
2491
                                        str+=",hatchsep="+(float)(hatchingSep/PPC); //$NON-NLS-1$
 
2492
                                
 
2493
                                if(!hatchingColor.equals(PSTricksConstants.DEFAULT_HATCHING_COLOR))
 
2494
                                {
 
2495
                                        String name = DviPsColors.getColourName(hatchingColor);
 
2496
                                        if(name==null)
 
2497
                                        {
 
2498
                                                name = "color"+number+'c';//$NON-NLS-1$
 
2499
                                                DviPsColors.addUserColour(hatchingColor, name); 
 
2500
                                        }
 
2501
                                        str += ",hatchcolor=" + name; //$NON-NLS-1$
 
2502
                                }
 
2503
                        }
 
2504
                
 
2505
                if(isFilled)
 
2506
                {
 
2507
                        if(!interiorColor.equals(PSTricksConstants.DEFAULT_INTERIOR_COLOR))
 
2508
                        {
 
2509
                                String name = DviPsColors.getColourName(interiorColor);
 
2510
                                if(name==null)
 
2511
                                {
 
2512
                                        name = "color"+number+'b';//$NON-NLS-1$
 
2513
                                        DviPsColors.addUserColour(interiorColor, name); 
 
2514
                                }
 
2515
                                str += ",fillcolor=" + name; //$NON-NLS-1$
 
2516
                        }
 
2517
                }
 
2518
                
 
2519
                return str;
 
2520
        }
 
2521
        
 
2522
        
 
2523
        
 
2524
        
 
2525
        /**
 
2526
         * @return The PSTricks code for the shape of the lines of the figure.
 
2527
         * @since 1.7
 
2528
         */
 
2529
        public String getPSTricksCodeLine(float ppc)
 
2530
        {
 
2531
                String str = "";//$NON-NLS-1$
 
2532
                boolean coma = false;
 
2533
                
 
2534
                if(!linesColor.equals(PSTricksConstants.DEFAULT_LINE_COLOR))
 
2535
                {
 
2536
                        String name = DviPsColors.getColourName(linesColor);
 
2537
                        if(name==null)
 
2538
                        {
 
2539
                                name = "color"+number;//$NON-NLS-1$
 
2540
                                DviPsColors.addUserColour(linesColor, name); 
 
2541
                        }
 
2542
                        str += "linecolor=" + name; //$NON-NLS-1$
 
2543
                        coma = true;
 
2544
                }
 
2545
                
 
2546
                if(lineStyle.equals(PSTricksConstants.LINE_DOTTED_STYLE))
 
2547
                        str += (coma ? "," : "")+ "linestyle=" + lineStyle + ",dotsep=" + //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 
2548
                                        (getDotSep() / ppc) + "cm"; //$NON-NLS-1$
 
2549
                else
 
2550
                        if (lineStyle.equals(PSTricksConstants.LINE_DASHED_STYLE))
 
2551
                                str += (coma ? "," : "") +"linestyle=" + lineStyle + ",dash=" + //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 
2552
                                                (getBlackDashLength() / ppc) + "cm " + //$NON-NLS-1$
 
2553
                                                (getWhiteDashLength() / ppc) + "cm"; //$NON-NLS-1$
 
2554
 
 
2555
                return str;
 
2556
        }
 
2557
        
 
2558
        
 
2559
        
 
2560
        
 
2561
        /**
 
2562
         * @return True if the current style of the interior of the figure is a gradient.
 
2563
         * @since 1.7
 
2564
         */
 
2565
        public synchronized boolean hasGradient()
 
2566
        {
 
2567
                return hatchingStyle.equals(PSTricksConstants.TOKEN_FILL_GRADIENT);
 
2568
        }
 
2569
        
 
2570
        
 
2571
 
 
2572
        
 
2573
        /**
 
2574
         * @return The borders of the figure (taking account of the thickness, the double borders, ...).
 
2575
         * @since 1.7
 
2576
         */
 
2577
        public LaTeXDrawRectangle getBoundBorders()
 
2578
        {
 
2579
                LaTeXDrawPoint2D NW = getTheNWBoundPoint(), SE = getTheSEBoundPoint();
 
2580
                return new LaTeXDrawRectangle(NW, SE, false);
 
2581
        }
 
2582
 
 
2583
 
 
2584
 
 
2585
 
 
2586
 
 
2587
        /**
 
2588
         * @return the hatchingSep.
 
2589
         * @since 1.8
 
2590
         */
 
2591
        public synchronized double getHatchingSep()
 
2592
        {
 
2593
                return hatchingSep;
 
2594
        }
 
2595
 
 
2596
 
 
2597
 
 
2598
        /**
 
2599
         * @param hatchSep the hatchingSep to set.
 
2600
         * @since 1.8
 
2601
         */
 
2602
        public synchronized void setHatchingSep(double hatchSep)
 
2603
        {
 
2604
                if(hatchSep>0 && !Double.isInfinite(hatchSep) && !Double.isNaN(hatchSep))
 
2605
                        this.hatchingSep = hatchSep;
 
2606
        }
 
2607
 
 
2608
 
 
2609
 
 
2610
        /**
 
2611
         * @return the canHaveArrow.
 
2612
         */
 
2613
        public synchronized boolean canHaveArrow()
 
2614
        {
 
2615
                return canHaveArrow;
 
2616
        }
 
2617
 
 
2618
 
 
2619
 
 
2620
        /**
 
2621
         * Returns horizontally the figure.
 
2622
         * @since 1.8
 
2623
         * @param origin The location of the horizontal axe.
 
2624
         */
 
2625
        public abstract void mirrorHorizontal(LaTeXDrawPoint2D origin);
 
2626
 
 
2627
 
 
2628
        
 
2629
        /**
 
2630
         * Returns vertically the figure.
 
2631
         * @since 1.8
 
2632
         * @param origin The location of the vertical axe.
 
2633
         */
 
2634
        public abstract void mirrorVertical(LaTeXDrawPoint2D origin);
 
2635
 
 
2636
 
 
2637
 
 
2638
        /**
 
2639
         * Updates the coordinates of the figure to the grid given in parameter.<br>
 
2640
         * Nothing will be done if the magnetic grid is not activated.
 
2641
         * @since 1.9
 
2642
         * @param grid The magnetic grid.
 
2643
         */
 
2644
        public abstract void updateToGrid(MagneticGrid grid);
 
2645
 
 
2646
        
 
2647
        
 
2648
        
 
2649
        /**
 
2650
         * Checks if the parameters of the figures are equals.
 
2651
         * @param f The figure to compare.
 
2652
         * @param considerShadow True if the parameters of the shadows must be considered.
 
2653
         * @param considerArrow True if the parameters of the arrows must be considered.
 
2654
         * @return True if the parameters are equals.
 
2655
         * @since 1.9
 
2656
         */
 
2657
        public boolean isParametersEquals(Figure f, boolean considerShadow, boolean considerArrow)
 
2658
        {
 
2659
                boolean lineOk = !f.isDashableOrDotable || !isDashableOrDotable || 
 
2660
                                                (lineStyle.equals(f.lineStyle) && thickness==f.thickness && 
 
2661
                                                (lineStyle.equals(PSTricksConstants.LINE_NONE_STYLE) ||
 
2662
                                                (lineStyle.equals(PSTricksConstants.LINE_DOTTED_STYLE) && dotSep==f.dotSep) ||
 
2663
                                                (lineStyle.equals(PSTricksConstants.LINE_DASHED_STYLE) && 
 
2664
                                                blackDashLength==f.blackDashLength && whiteDashLength==f.whiteDashLength)));
 
2665
                
 
2666
                boolean filledOk = !f.canBeFilled || !canBeFilled || 
 
2667
                                                        (isFilled==f.isFilled && interiorColor.equals(f.interiorColor));
 
2668
                                                        
 
2669
                boolean dblbndOk = !f.isDoubleBoundaryable || f.isDoubleBoundaryable || 
 
2670
                                                        (f.hasDoubleBoundary==hasDoubleBoundary &&
 
2671
                                                        doubleColor.equals(f.doubleColor) && doubleSep==f.doubleSep);
 
2672
                
 
2673
                boolean arrowOk = !considerArrow || !f.canHaveArrow || !canHaveArrow || 
 
2674
                                                  (((Arrowable)f).getArrowHead1().equals(((Arrowable)this).getArrowHead1()) &&
 
2675
                                                  ((Arrowable)f).getArrowHead2().equals(((Arrowable)this).getArrowHead2()));
 
2676
                
 
2677
                boolean hatchOk = (!f.canBeFilled || !canBeFilled || 
 
2678
                                                        ((f.hatchingStyle.equals(hatchingStyle) && (!isHatched() ||
 
2679
                                                        (f.hatchingAngle==hatchingAngle && f.hatchingColor.equals(hatchingColor) &&
 
2680
                                                        ((float)f.hatchingSep)==((float)hatchingSep) && f.hatchingWidth==hatchingWidth))) && 
 
2681
                                                  (hasGradient()==f.hasGradient() &&(!hasGradient() ||
 
2682
                                                  (gradientAngle==f.gradientAngle && gradientEndColor.equals(f.gradientEndColor) &&
 
2683
                                                  gradientMidPoint==f.gradientMidPoint && gradientStartColor.equals(f.gradientStartColor))))));
 
2684
                
 
2685
                boolean shadowOk = !considerShadow || !f.canHaveShadow || !canHaveArrow || 
 
2686
                                                        (hasShadow==f.hasShadow && shadowAngle==f.shadowAngle &&
 
2687
                                                        shadowColor.equals(f.shadowColor) && ((float)shadowSize)==((float)f.shadowSize));
 
2688
                
 
2689
                return linesColor.equals(f.linesColor) && lineOk && filledOk && dblbndOk && shadowOk &&
 
2690
                                hatchOk && arrowOk ;
 
2691
        }
 
2692
        
 
2693
        
 
2694
        
 
2695
        /**
 
2696
         * @return True is a delimiter is selected.
 
2697
         * @since 1.9
 
2698
         */
 
2699
        public boolean isDelimitorSelected()
 
2700
        {
 
2701
                return dSelected!=null || (borders==null ? false : borders.isDelimitorSelected());
 
2702
        }
 
2703
 
 
2704
 
 
2705
        
 
2706
        /**
 
2707
         * @return The position of the selected delimiter.
 
2708
         * @since 1.9
 
2709
         */
 
2710
        public int getSelectedDelimitorOrientation()
 
2711
        {
 
2712
                if(isOnRotation())
 
2713
                        return DELIMITOR_ROTATION;
 
2714
                
 
2715
                return DELIMITOR_ORIENTATION_NONE;
 
2716
        }
 
2717
        
 
2718
        
 
2719
        
 
2720
        /**
 
2721
         * Sometimes a rectangle is too small to be drawn; this method check if the given shape is too small
 
2722
         * and if it is the case, it return a visible shape based on the given shape.
 
2723
         * @param s The shape to check.
 
2724
         * @return A visible check if the given shape is too small or null if it is not the case.
 
2725
         * @since 1.9
 
2726
         */
 
2727
        protected Shape getTooSmallShape(Shape s)
 
2728
        {
 
2729
                Rectangle2D bds = s.getBounds2D();
 
2730
                
 
2731
                if(bds.getHeight()<=0)
 
2732
                {
 
2733
                        if(bds.getWidth()<=0)
 
2734
                                return new Line2D.Double(bds.getMinX(), bds.getMinY(), bds.getMinX()+1, bds.getMinY()+1);
 
2735
                        return new Line2D.Double(bds.getMinX(), bds.getMaxY(), bds.getMaxX(), bds.getMaxY());
 
2736
                }
 
2737
                
 
2738
                if(bds.getWidth()<=0)
 
2739
                        return new Line2D.Double(bds.getMaxX(), bds.getMinY(), bds.getMaxX(), bds.getMaxY());
 
2740
                return null;
 
2741
        }
 
2742
        
 
2743
        
 
2744
        
 
2745
        
 
2746
        /**
 
2747
         * Gives a gradient to the shape.
 
2748
         * @since 1.9
 
2749
         */
 
2750
        protected void setHasGradient()
 
2751
        {
 
2752
                hatchingStyle = PSTricksConstants.TOKEN_FILL_GRADIENT;
 
2753
        }
 
2754
        
 
2755
        
 
2756
        
 
2757
        @Override
 
2758
        public int hashCode()
 
2759
        {
 
2760
                return (int)thickness+(int)doubleSep+(linesColor.hashCode()^interiorColor.hashCode()^
 
2761
                                hatchingStyle.hashCode()^lineStyle.hashCode());
 
2762
        }
 
2763
        
 
2764
        
 
2765
        
 
2766
        
 
2767
        /**
 
2768
         * Given a right-rectangle ABC right in A, it computes the gap created by the corner of the triangle in B
 
2769
         * based on an initial gap.
 
2770
         * @param a The point A.
 
2771
         * @param b The point B.
 
2772
         * @param c The point C.
 
2773
         * @param gap The initial gap (for example, the thickness, the double border gap,...).
 
2774
         * @return The gap created by the corner of the point B.
 
2775
         * @since 2.0.0
 
2776
         */
 
2777
        public static double getCornerGap(Point2D a, Point2D b, Point2D c, double gap)
 
2778
        {
 
2779
                if(a==null || b==null || c==null)
 
2780
                        return 0.;
 
2781
                
 
2782
                return gap / Triangle.getAltitude(a, b, c) * a.distance(b);
 
2783
        }
 
2784
        
 
2785
        
 
2786
        
 
2787
        
 
2788
        /**
 
2789
         * @return True if when the shape has a shadow, then it is filled.
 
2790
         * @since 2.0.0
 
2791
         */
 
2792
        public boolean shadowFillsShape()
 
2793
        {
 
2794
                return true;
 
2795
        }
 
2796
 
 
2797
 
 
2798
        /**
 
2799
         * @return the shape.
 
2800
         * @since 2.0.0
 
2801
         */
 
2802
        public synchronized Shape getShape()
 
2803
        {
 
2804
                return shape;
 
2805
        }
 
2806
 
 
2807
 
 
2808
        /**
 
2809
         * @param number the number to set.
 
2810
         * @since 2.0.0
 
2811
         */
 
2812
        public synchronized void setNumber(int number)
 
2813
        {
 
2814
                this.number = number;
 
2815
        }
 
2816
 
 
2817
 
 
2818
        public void setNewNumber()
 
2819
        {
 
2820
                setNumber(meter++);
 
2821
        }
 
2822
        
 
2823
        
 
2824
        
 
2825
        @Override
 
2826
        public String toString() 
 
2827
        {
 
2828
                return getClass().getName() + "#" + getNumber() + "[thick=" + getThickness() + ", bordCol=" + getLinesColor() +  //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
 
2829
                                ", intCol=" + getInteriorColor() + ", dbleCol=" + getDoubleColor() + ", shadCol=" + getShadowColor() + //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
 
2830
                                ", isFilled=" + isFilled() + ", hasShad=" + hasShadow() + ", hasDble=" + hasDoubleBoundary() + //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
 
2831
                                ", shadSize=" + getShadowSize() + ", shadAngle=" + getShadowAngle() + ", gradAngle=" + getGradientAngle() + //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
 
2832
                                ", gradMP=" + getGradientMidPoint() + ", gradCol1=" + getGradientStartColor() + ", gradCol2=" + getGradientEndColor() + //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
 
2833
                                ", bordPos=" + getBordersPosition() + ", blackDash=" + getBlackDashLength() + ", dotSep=" + getDotSep() +  //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
 
2834
                                ", dbleSep=" + getDoubleSep() + ", hatchAngle=" + getHatchingAngle() + ", hatchSep=" + getHatchingSep() +  //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
 
2835
                                ", hatchStyle=" + getHatchingStyle() + ", hatchWidth=" + getHatchingWidth() + ", lineStyle=" + getLineStyle() + //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
 
2836
                                ", rotAngle=" + getRotationAngle() + ", whiteDash=" + getWhiteDashLength() + ", gc=" + getGravityCenter() +  //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
 
2837
                                ", isHatched=" + isHatched() + "]"; //$NON-NLS-1$ //$NON-NLS-2$
 
2838
        }
 
2839
}