~ubuntu-branches/debian/sid/geogebra/sid

« back to all changes in this revision

Viewing changes to geogebra/euclidian/Drawable.java

  • Committer: Package Import Robot
  • Author(s): Giovanni Mascellani
  • Date: 2012-01-10 11:37:41 UTC
  • mfrom: (1.1.6)
  • Revision ID: package-import@ubuntu.com-20120110113741-satwohsd4de4ite1
Tags: 4.0.19.0+dfsg1-1
* New upstream version (closes: #649893).
* Update dependency: icedtea-plugin -> icedtea-netx-common (LP: #893007).
* New thumbnailer configuration compatible with Gnome 3.
* Package building is now managed by javahelper instead of upstream
  build.xml.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* 
2
 
GeoGebra - Dynamic Mathematics for Everyone
3
 
http://www.geogebra.org
4
 
 
5
 
This file is part of GeoGebra.
6
 
 
7
 
This program is free software; you can redistribute it and/or modify it 
8
 
under the terms of the GNU General Public License as published by 
9
 
the Free Software Foundation.
10
 
 
11
 
*/
12
 
 
13
 
/*
14
 
 * Drawable.java
15
 
 *
16
 
 * Created on 13. Oktober 2001, 17:40
17
 
 */
18
 
 
19
 
package geogebra.euclidian;
20
 
 
21
 
import geogebra.kernel.Construction;
22
 
import geogebra.kernel.GeoElement;
23
 
import geogebra.kernel.GeoPoint;
24
 
import geogebra.kernel.GeoVector;
25
 
import geogebra.kernel.Kernel;
26
 
 
27
 
import java.awt.BasicStroke;
28
 
import java.awt.Color;
29
 
import java.awt.Dimension;
30
 
import java.awt.Font;
31
 
import java.awt.Graphics2D;
32
 
import java.awt.Point;
33
 
import java.awt.Rectangle;
34
 
import java.awt.RenderingHints;
35
 
import java.awt.Shape;
36
 
import java.awt.font.FontRenderContext;
37
 
import java.awt.font.TextLayout;
38
 
import java.util.ArrayList;
39
 
 
40
 
/**
41
 
 *
42
 
 * @author  Markus
43
 
 * @version 
44
 
 */
45
 
public abstract class Drawable {
46
 
        BasicStroke objStroke = EuclidianView.getDefaultStroke();
47
 
        BasicStroke selStroke = EuclidianView.getDefaultSelectionStroke();
48
 
        BasicStroke decoStroke = EuclidianView.getDefaultStroke();
49
 
 
50
 
        private int lineThickness = -1;
51
 
        public int lineType = -1;
52
 
 
53
 
        protected EuclidianView view;
54
 
        protected GeoElement geo;
55
 
        public int xLabel, yLabel;
56
 
        int mouseX, mouseY; // for Previewables
57
 
        protected String labelDesc; // label Description
58
 
        private String oldLabelDesc;    
59
 
        private boolean labelHasIndex = false;
60
 
        Rectangle labelRectangle = new Rectangle(); // for label hit testing
61
 
        Shape strokedShape, strokedShape2;
62
 
 
63
 
        
64
 
        private int lastFontSize = -1;
65
 
        
66
 
        // tracing      
67
 
        protected boolean isTracing = false;
68
 
        
69
 
        boolean createdByDrawList = false;      
70
 
 
71
 
        public abstract void update();
72
 
        public abstract void draw(Graphics2D g2);
73
 
        public abstract boolean hit(int x, int y);
74
 
        public abstract boolean isInside(Rectangle rect);
75
 
        public abstract GeoElement getGeoElement();
76
 
        public abstract void setGeoElement(GeoElement geo);
77
 
        
78
 
        public double getxLabel() {
79
 
                return xLabel;
80
 
        }
81
 
        
82
 
        public double getyLabel() {
83
 
                return yLabel;
84
 
        }
85
 
        
86
 
        void updateFontSize() {
87
 
        }
88
 
        
89
 
        /**
90
 
         * Returns the bounding box of this Drawable in screen coordinates. 
91
 
         * @return null when this Drawable is infinite or undefined      
92
 
         */
93
 
        public Rectangle getBounds() {          
94
 
                return null;    
95
 
        }
96
 
        
97
 
        final protected void drawLabel(Graphics2D g2) {
98
 
                if (labelDesc == null) return;          
99
 
                String label = labelDesc;
100
 
                Font oldFont  = null;
101
 
                
102
 
                // label changed: check for bold or italic tags in caption
103
 
                if (oldLabelDesc != labelDesc || labelDesc.startsWith("<")) {                                   
104
 
                        boolean italic = false;
105
 
                        
106
 
                        // support for bold and italic tags in captions
107
 
                        // must be whole caption
108
 
                        if (label.startsWith("<i>") && label.endsWith("</i>")) {
109
 
                                if (oldFont == null)
110
 
                                        oldFont = g2.getFont();
111
 
                                
112
 
                                // use Serif font so that we can get a nice curly italic x
113
 
                                g2.setFont(view.getApplication().getFont(true, oldFont.getStyle() | Font.ITALIC, oldFont.getSize()));                   
114
 
                                label = label.substring(3, label.length() - 4);
115
 
                                italic = true;
116
 
                        } 
117
 
        
118
 
                        if (label.startsWith("<b>") && label.endsWith("</b>")) {                        
119
 
                                if (oldFont == null)
120
 
                                        oldFont = g2.getFont();
121
 
        
122
 
                                g2.setFont(g2.getFont().deriveFont(Font.BOLD + (italic ? Font.ITALIC : 0)));    
123
 
                                label = label.substring(3, label.length() - 4);                 
124
 
                        }
125
 
                }
126
 
                                
127
 
                // no index in label: draw it fast
128
 
                int fontSize = g2.getFont().getSize();
129
 
                if (oldLabelDesc == labelDesc && !labelHasIndex && lastFontSize == fontSize) {
130
 
                        g2.drawString(label, xLabel, yLabel);
131
 
                        labelRectangle.setLocation(xLabel, yLabel - fontSize);
132
 
                } 
133
 
                else { // label with index or label has changed:
134
 
                        // do the slower index drawing routine and check for indices
135
 
                        oldLabelDesc = labelDesc;
136
 
                        lastFontSize = fontSize;
137
 
                                        
138
 
                        Point p = drawIndexedString(g2, label, xLabel, yLabel);
139
 
                        labelHasIndex = p.y > 0;
140
 
                        labelRectangle.setBounds(xLabel, yLabel - fontSize, p.x, fontSize + p.y);                       
141
 
                }               
142
 
                
143
 
                if (oldFont != null)
144
 
                        g2.setFont(oldFont);
145
 
        }                       
146
 
        
147
 
        /**
148
 
         * Adapts xLabel and yLabel to make sure that the label rectangle fits fully on screen.
149
 
         */
150
 
        final public void ensureLabelDrawsOnScreen() {
151
 
                // draw label and 
152
 
                drawLabel(view.g2Dtemp);
153
 
                
154
 
                // make sure labelRectangle fits on screen horizontally         
155
 
                if (xLabel < 3) 
156
 
                        xLabel = 3;
157
 
                else
158
 
                        xLabel = Math.min(xLabel, view.width - labelRectangle.width - 3);                                       
159
 
                if (yLabel < view.fontSize) 
160
 
                        yLabel = view.fontSize;
161
 
                else
162
 
                        yLabel = Math.min(yLabel, view.height - 3);     
163
 
                
164
 
                // update label rectangle position
165
 
                labelRectangle.setLocation(xLabel, yLabel - view.fontSize);             
166
 
        }
167
 
        
168
 
        // Michael Borcherds 2008-06-10
169
 
        final float textWidth(String str, Font font, FontRenderContext frc)
170
 
        {
171
 
                if (str.equals("")) return 0f;
172
 
                TextLayout layout = new TextLayout(str , font, frc);
173
 
                return layout.getAdvance();     
174
 
                
175
 
        }
176
 
        
177
 
        
178
 
        /* old version
179
 
        final void drawMultilineLaTeX(Graphics2D g2, Font font, Color fgColor, Color bgColor) {
180
 
                
181
 
                int fontSize = g2.getFont().getSize();
182
 
                float lineSpread = fontSize * 1.0f;
183
 
                float lineSpace = fontSize * 0.5f;
184
 
 
185
 
                int maxhOffset=0;
186
 
                float height=0;
187
 
                
188
 
                Dimension dim;
189
 
                
190
 
                labelDesc=labelDesc.replaceAll("\\$\\$", "\\$"); // replace $$ with $
191
 
                labelDesc=labelDesc.replaceAll("\\\\\\[", "\\$");// replace \[ with $
192
 
                labelDesc=labelDesc.replaceAll("\\\\\\]", "\\$");// replace \] with $
193
 
                labelDesc=labelDesc.replaceAll("\\\\\\(", "\\$");// replace \( with $
194
 
                labelDesc=labelDesc.replaceAll("\\\\\\)", "\\$");// replace \) with $
195
 
                
196
 
                
197
 
                String[] lines=labelDesc.split("\n");
198
 
                
199
 
                
200
 
                for (int k=0 ; k<lines.length ; k++)
201
 
                {
202
 
 
203
 
                        String[] strings=lines[k].split("\\$");
204
 
                        int heights[] = new int[strings.length];
205
 
 
206
 
                        boolean latex=false;
207
 
                        if (lines[k].indexOf('$') == -1 && lines.length == 1) 
208
 
                        {
209
 
                                latex=true; // just latex
210
 
                        }
211
 
 
212
 
                        int maxHeight=0;
213
 
                        // calculate heights of each element
214
 
                        for (int j=0 ; j<strings.length ; j++)
215
 
                        {
216
 
 
217
 
                                if (!strings[j].equals(str(" ",strings[j].length()))) // check not empty or just spaces
218
 
                                {
219
 
                                        if (latex)
220
 
                                        {                                               
221
 
                                                dim = drawEquation(view.getTempGraphics2D(),0,0, strings[j], font, fgColor, bgColor);
222
 
                                                //dim = sHotEqn.getSizeof(strings[j]);
223
 
                                                //widths[j] = dim.width;                                
224
 
                                                heights[j] = dim.height;
225
 
                                        }
226
 
                                        else
227
 
                                        {
228
 
                                                heights[j] = (int)lineSpread; //p.y;            
229
 
                                        }
230
 
                                }
231
 
                                else
232
 
                                {
233
 
                                        heights[j]=0;
234
 
                                }
235
 
                                latex=!latex;
236
 
                                if (heights[j] > maxHeight) maxHeight=heights[j];
237
 
 
238
 
                        }
239
 
                        
240
 
                        if (k!=0) maxHeight += lineSpace;
241
 
                        
242
 
                        int hOffset=0;
243
 
                        
244
 
                        latex=false;
245
 
                        if (lines[k].indexOf('$') == -1 && lines.length == 1) 
246
 
                        {
247
 
                                latex=true; // just latex
248
 
                                //Application.debug("just latex");
249
 
                        }
250
 
 
251
 
                        // draw elements
252
 
                        for (int j=0 ; j<strings.length ; j++)
253
 
                        {
254
 
 
255
 
                                if (!strings[j].equals(str(" ",strings[j].length()))) // check not empty or just spaces
256
 
                                {
257
 
                                        
258
 
                                        int vOffset = (maxHeight - heights[j] )/2; // vertical centering
259
 
                                        
260
 
                                        if (latex)
261
 
                                        {
262
 
                                                
263
 
                                                dim = drawEquation(g2,xLabel + hOffset,(int)(yLabel + height) + vOffset, strings[j], font, fgColor, bgColor);
264
 
                                                hOffset+=dim.width;
265
 
                                        }
266
 
                                        else
267
 
                                        {                               
268
 
                                                Point p = drawIndexedString(g2, strings[j], xLabel + hOffset, yLabel + height + vOffset + lineSpread);
269
 
                                                hOffset+=p.x;
270
 
                                        }
271
 
                                }
272
 
                                latex=!latex;
273
 
                        }
274
 
                        if (hOffset > maxhOffset) maxhOffset = hOffset;
275
 
                        height += maxHeight;
276
 
                }
277
 
                labelRectangle.setBounds(xLabel, yLabel, maxhOffset, (int)height);
278
 
        }       
279
 
 
280
 
        // returns a string consisting of n consecutive "str"s
281
 
        final private String str(String str, int n)
282
 
        {
283
 
                if (n == 0) return "";
284
 
                else if (n == 1) return str;
285
 
                else {
286
 
                        StringBuffer ret = new StringBuffer();
287
 
                        
288
 
                        for (int i=0 ; i<n ; i++) ret.append(str);
289
 
                        return ret.toString();
290
 
                }
291
 
        } */
292
 
        
293
 
        
294
 
        /**
295
 
         * Draw a multiline LaTeX label. 
296
 
         * 
297
 
         * TODO: Improve performance (caching, etc.)
298
 
         * Florian Sonner
299
 
         * @param g2
300
 
         * @param font
301
 
         * @param fgColor
302
 
         * @param bgColor
303
 
         */
304
 
        final void drawMultilineLaTeX(Graphics2D g2, Font font, Color fgColor, Color bgColor) {
305
 
                int fontSize = g2.getFont().getSize();
306
 
                int lineSpread = (int)(fontSize * 1.0f);
307
 
                int lineSpace = (int)(fontSize * 0.5f);
308
 
                
309
 
                // latex delimiters \[ \] \( \) $$ -> $
310
 
                labelDesc = labelDesc.replaceAll("(\\$\\$|\\\\\\[|\\\\\\]|\\\\\\(|\\\\\\))", "\\$");
311
 
                
312
 
                // split on $ but not \$
313
 
                String[] elements = labelDesc.split("(?<![\\\\])(\\$)", -1);
314
 
                
315
 
                ArrayList lineHeights = new ArrayList();
316
 
                lineHeights.add(new Integer(lineSpread + lineSpace));
317
 
                ArrayList elementHeights = new ArrayList();
318
 
                
319
 
                // use latex by default just if there is just a single element
320
 
                boolean isLaTeX = (elements.length == 1);
321
 
                
322
 
                // calculate the required space of every element
323
 
                for(int i = 0, currentLine = 0, currentElement = 0; i < elements.length; ++i) {                 
324
 
                        if(isLaTeX) {
325
 
                                // save the height of this element by drawing it to a temporary buffer
326
 
                                int height = drawEquation(view.getTempGraphics2D(font), 0, 0, elements[i], font, fgColor, bgColor).height;
327
 
                                elementHeights.add(new Integer(height));
328
 
                                
329
 
                                // check if this element is taller than every else in the line
330
 
                                if(height > ((Integer)lineHeights.get(currentLine)).intValue())
331
 
                                        lineHeights.set(currentLine, new Integer(height));
332
 
                                
333
 
                                ++currentElement;
334
 
                        } else {
335
 
                                elements[i] = elements[i].replaceAll("\\\\\\$", "\\$");
336
 
                                String[] lines = elements[i].split("\\n", -1);
337
 
                                
338
 
                                for(int j = 0; j < lines.length; ++j) {
339
 
                                        elementHeights.add(new Integer(lineSpread));
340
 
                                        
341
 
                                        // create a new line
342
 
                                        if(j + 1 < lines.length) {
343
 
                                                ++currentLine;
344
 
                                                
345
 
                                                lineHeights.add(new Integer(lineSpread + lineSpace));
346
 
                                        }
347
 
                                        
348
 
                                        ++currentElement;
349
 
                                }
350
 
                        }
351
 
                        
352
 
                        isLaTeX = !isLaTeX;
353
 
                }
354
 
                
355
 
                int width = 0;
356
 
                int height = 0;
357
 
                
358
 
                // use latex by default just if there is just a single element
359
 
                isLaTeX = (elements.length == 1);
360
 
                
361
 
                int xOffset = 0;
362
 
                int yOffset = 0;
363
 
                
364
 
                // now draw all elements
365
 
                for(int i = 0, currentLine = 0, currentElement = 0; i < elements.length; ++i) {                 
366
 
                        if(isLaTeX) {
367
 
                                // calculate the y offset of this element by: (lineHeight - elementHeight) / 2
368
 
                                yOffset = (((Integer)(lineHeights.get(currentLine))).intValue() - ((Integer)(elementHeights.get(currentElement))).intValue()) / 2;
369
 
                                
370
 
                                // draw the equation and save the x offset
371
 
                                xOffset += drawEquation(g2, xLabel + xOffset, (int)(yLabel + height) + yOffset, elements[i], font, fgColor, bgColor).width;
372
 
                                
373
 
                                ++currentElement;
374
 
                        } else {
375
 
                                String[] lines = elements[i].split("\\n", -1);
376
 
                                
377
 
                                for(int j = 0; j < lines.length; ++j) {
378
 
                                        // calculate the y offset like done with the element
379
 
                                        yOffset = (((Integer)(lineHeights.get(currentLine))).intValue() - ((Integer)(elementHeights.get(currentElement))).intValue()) / 2;
380
 
                                        
381
 
                                        // draw the string
382
 
                                        xOffset += drawIndexedString(g2, lines[j], xLabel + xOffset, yLabel + height + yOffset + lineSpread).x;
383
 
                                        
384
 
                                        // add the height of this line if more lines follow
385
 
                                        if(j + 1 < lines.length) {
386
 
                                                height += ((Integer)(lineHeights.get(currentLine))).intValue();
387
 
                                                
388
 
                                                if(xOffset > width)
389
 
                                                        width = xOffset;
390
 
                                        }
391
 
                                        
392
 
                                        // create a new line if more will follow
393
 
                                        if(j + 1 < lines.length) {
394
 
                                                ++currentLine;
395
 
                                                xOffset = 0;
396
 
                                        } 
397
 
                                        
398
 
                                        ++currentElement;
399
 
                                }
400
 
                        }
401
 
                        
402
 
                        // last element, increase total height and check if this is the most wide element
403
 
                        if(i + 1 == elements.length) {
404
 
                                height += ((Integer)(lineHeights.get(currentLine))).intValue();
405
 
                                
406
 
                                if(xOffset > width)
407
 
                                        width = xOffset;
408
 
                        }
409
 
                        
410
 
                        isLaTeX = !isLaTeX;
411
 
                }
412
 
                labelRectangle.setBounds(xLabel - 3, yLabel - 3, width + 6, height + 6);
413
 
        }
414
 
 
415
 
        
416
 
        private geogebra.gui.hoteqn.sHotEqn eqn;
417
 
        
418
 
        final public Dimension drawEquation(Graphics2D g2, int x, int y, String text, Font font, Color fgColor, Color bgColor)
419
 
        {
420
 
                Dimension dim;
421
 
                if (eqn == null) {                      
422
 
                        eqn = new geogebra.gui.hoteqn.sHotEqn(text);
423
 
                        //Application.debug(eqn.getSize());
424
 
                        eqn.setDoubleBuffered(false);
425
 
                        eqn.setEditable(false); 
426
 
                        eqn.removeMouseListener(eqn);
427
 
                        eqn.removeMouseMotionListener(eqn);                             
428
 
                        eqn.setDebug(false);
429
 
                        eqn.setOpaque(false);
430
 
                }
431
 
                else
432
 
                {
433
 
                        eqn.setEquation(text);
434
 
                }
435
 
 
436
 
                        //setEqnFontSize();                                                                                                                                                                                                                             
437
 
                        int size = (font.getSize() / 2) * 2; 
438
 
                        if (size < 10) 
439
 
                                size = 10;
440
 
                        else if (size > 28) 
441
 
                                size = 28;
442
 
                        
443
 
                        eqn.setFontname(font.getName());
444
 
                        eqn.setFontsizes(size, size - 2, size - 4, size - 6);
445
 
                        eqn.setFontStyle(font.getStyle());
446
 
 
447
 
                        
448
 
                        eqn.setForeground(fgColor);             
449
 
                        eqn.setBackground(bgColor);
450
 
                
451
 
                        
452
 
                        //eqn.paintComponent(g2Dtemp,0,0);              
453
 
                        //dim=eqn.getSizeof(text);
454
 
                        eqn.paintComponent(g2,x,y);             
455
 
                        dim=eqn.getSize();
456
 
                        
457
 
                        //Application.debug(size);
458
 
                        return dim;
459
 
        }
460
 
        
461
 
        final void drawMultilineText(Graphics2D g2) {
462
 
                
463
 
                if (labelDesc == null) return;
464
 
                
465
 
                int lines = 0;                          
466
 
                int fontSize = g2.getFont().getSize();
467
 
                float lineSpread = fontSize * 1.5f;
468
 
 
469
 
                Font font = g2.getFont();
470
 
                FontRenderContext frc = g2.getFontRenderContext();
471
 
                int xoffset = 0, yoffset = 0;
472
 
 
473
 
                // no index in text
474
 
                if (oldLabelDesc == labelDesc && !labelHasIndex) {              
475
 
                        // draw text line by line
476
 
                        int lineBegin = 0;
477
 
                        int length = labelDesc.length();
478
 
                        for (int i=0; i < length-1; i++) {
479
 
                                if (labelDesc.charAt(i) == '\n') {
480
 
                                        //end of line reached: draw this line
481
 
                                        g2.drawString(labelDesc.substring(lineBegin, i), xLabel, yLabel + lines * lineSpread);
482
 
 
483
 
                                        int width=(int)textWidth(labelDesc.substring(lineBegin, i), font, frc);
484
 
                                        if (width > xoffset) xoffset = width;                   
485
 
                                        
486
 
                                        lines++;
487
 
                                        lineBegin = i + 1;                                      
488
 
                                }
489
 
                        }
490
 
                        
491
 
                        float ypos = yLabel + lines * lineSpread;
492
 
                        g2.drawString(labelDesc.substring(lineBegin), xLabel, ypos);
493
 
 
494
 
                        int width=(int)textWidth(labelDesc.substring(lineBegin), font, frc);
495
 
                        if (width > xoffset) xoffset = width;                   
496
 
                        
497
 
                        // Michael Borcherds 2008-06-10
498
 
                        // changed setLocation to setBounds (bugfix)
499
 
                        // and added final float textWidth()
500
 
                        //labelRectangle.setLocation(xLabel, yLabel - fontSize);
501
 
                        int height = (int) ( (lines +1)*lineSpread);
502
 
                        labelRectangle.setBounds(xLabel, yLabel - fontSize, xoffset, height );
503
 
                } 
504
 
                else {                  
505
 
                        // text with indices
506
 
                        // label description has changed, search for possible indices
507
 
                        oldLabelDesc = labelDesc;
508
 
                        
509
 
                        // draw text line by line
510
 
                        int lineBegin = 0;
511
 
                        int length = labelDesc.length();
512
 
                        xoffset = 0;
513
 
                        yoffset = 0;
514
 
                        for (int i=0; i < length-1; i++) {
515
 
                                if (labelDesc.charAt(i) == '\n') {
516
 
                                        //end of line reached: draw this line
517
 
                                        Point p = drawIndexedString(g2, labelDesc.substring(lineBegin, i), xLabel, yLabel + lines * lineSpread);
518
 
                                        if (p.x > xoffset) xoffset = p.x;
519
 
                                        if (p.y > yoffset) yoffset = p.y;
520
 
                                        lines++;
521
 
                                        lineBegin = i + 1;                                      
522
 
                                }
523
 
                        }
524
 
                                        
525
 
                        float ypos = yLabel + lines * lineSpread;
526
 
                        Point p = drawIndexedString(g2, labelDesc.substring(lineBegin), xLabel, ypos);
527
 
                        if (p.x > xoffset) xoffset = p.x;
528
 
                        if (p.y > yoffset) yoffset = p.y;
529
 
                        labelHasIndex = yoffset > 0;                    
530
 
                        int height = (int) ( (lines +1)*lineSpread);
531
 
                        labelRectangle.setBounds(xLabel, yLabel - fontSize, xoffset, height );
532
 
                }
533
 
        }               
534
 
        
535
 
        /**
536
 
         * Draws a string str with possible indices to g2 at position x, y. 
537
 
         * The indices are drawn using the given indexFont. 
538
 
         * Examples for strings with indices: "a_1" or "s_{ab}"
539
 
         * @param g2
540
 
         * @param str
541
 
         * @return additional pixel needed to draw str (x-offset, y-offset) 
542
 
         */
543
 
        public static Point drawIndexedString(Graphics2D g2, String str, float xPos, float yPos) {
544
 
                Font g2font = g2.getFont();
545
 
                Font indexFont = getIndexFont(g2font);
546
 
                Font font = g2font;
547
 
                TextLayout layout;
548
 
                FontRenderContext frc = g2.getFontRenderContext();
549
 
 
550
 
                int indexOffset = indexFont.getSize() / 2;
551
 
                float maxY = 0;
552
 
                int depth = 0;
553
 
                float x = xPos;
554
 
                float y = yPos;
555
 
                int startPos = 0;
556
 
                if (str == null) return null;
557
 
                int length = str.length();
558
 
 
559
 
                for (int i=0; i < length; i++) {
560
 
                        switch (str.charAt(i)) {
561
 
                                case '_':                       
562
 
                                        //      draw everything before _                                                                                                                        
563
 
                                        if (i > startPos) {
564
 
                                                font = (depth == 0) ? g2font : indexFont;
565
 
                                                y = yPos + depth * indexOffset;
566
 
                                                if (y > maxY) maxY = y;                 
567
 
                                                String tempStr = str.substring(startPos, i);
568
 
                                                layout = new TextLayout(tempStr, font, frc);
569
 
                                                g2.setFont(font);                                               
570
 
                                                g2.drawString(tempStr, x, y);                           
571
 
                                                x += layout.getAdvance();               
572
 
                                        }                                       
573
 
                                        startPos = i + 1;
574
 
                                        depth++;
575
 
                        
576
 
                                        // check if next character is a '{' (beginning of index with several chars)
577
 
                                        if (startPos < length && str.charAt(startPos) != '{') {
578
 
                                                font = (depth == 0) ? g2font : indexFont;                                                                               
579
 
                                                y = yPos + depth * indexOffset;
580
 
                                                if (y > maxY) maxY = y;
581
 
                                                String tempStr = str.substring(startPos, startPos+1);
582
 
                                                layout = new TextLayout(tempStr, font, frc);
583
 
                                                g2.setFont(font);
584
 
                                                g2.drawString(tempStr, x, y);
585
 
                                                x += layout.getAdvance();       
586
 
                                                depth--;                                                                                                                                                                                                        
587
 
                                        }
588
 
                                        i++;
589
 
                                        startPos++; 
590
 
                                        break;                          
591
 
                        
592
 
                                case '}': // end of index with several characters
593
 
                                        if (depth > 0) {                                                
594
 
                                                if (i > startPos) {
595
 
                                                        font = (depth == 0) ? g2font : indexFont;               
596
 
                                                        y = yPos + depth * indexOffset;
597
 
                                                        if (y > maxY) maxY = y;
598
 
                                                        String tempStr = str.substring(startPos, i);
599
 
                                                        layout = new TextLayout(tempStr, font, frc);
600
 
                                                        g2.setFont(font);
601
 
                                                        g2.drawString(tempStr, x, y);
602
 
                                                        x += layout.getAdvance();
603
 
                                                }                                                                                               
604
 
                                                startPos = i+1;
605
 
                                                depth--;                
606
 
                                        }
607
 
                                        break;          
608
 
                        }               
609
 
                }
610
 
        
611
 
                if (startPos < length) {
612
 
                        font = (depth == 0) ? g2font : indexFont;
613
 
                        y = yPos + depth * indexOffset;
614
 
                        if (y > maxY) maxY = y;
615
 
                        String tempStr = str.substring(startPos);
616
 
                        layout = new TextLayout(tempStr, font, frc);
617
 
                        g2.setFont(font);
618
 
                        g2.drawString(tempStr, x, y);
619
 
                        x += layout.getAdvance();
620
 
                }       
621
 
                g2.setFont(g2font);
622
 
                return new Point(Math.round(x - xPos), Math.round(maxY - yPos));
623
 
        }
624
 
        
625
 
        private static Font getIndexFont(Font f) {
626
 
                //      index font size should be at least 8pt
627
 
                int newSize = Math.max( (int) (f.getSize() * 0.9) , 8); 
628
 
                return f.deriveFont(f.getStyle(), newSize);              
629
 
        }
630
 
 
631
 
        /**
632
 
         * Adds geo's label offset to xLabel and yLabel.
633
 
         * 
634
 
         * @return whether something was changed
635
 
         */
636
 
        final protected boolean addLabelOffset() {
637
 
                return addLabelOffset(false);
638
 
        }
639
 
                
640
 
        /**
641
 
         * Adds geo's label offset to xLabel and yLabel.
642
 
         * @param ensureLabelOnScreen: if true we make sure that the label is drawn on screen
643
 
         * 
644
 
         * @return whether something was changed
645
 
         */
646
 
        final protected boolean addLabelOffset(boolean ensureLabelOnScreen) {
647
 
                if (ensureLabelOnScreen) {
648
 
                        // MAKE SURE LABEL STAYS ON SCREEN
649
 
                        int xLabelOld = xLabel;
650
 
                        int yLabelOld = yLabel;                 
651
 
                        xLabel += geo.labelOffsetX;
652
 
                        yLabel += geo.labelOffsetY;
653
 
                        
654
 
                        // change xLabel and yLabel so that label stays on screen
655
 
                        ensureLabelDrawsOnScreen();
656
 
                        
657
 
                        // something changed?
658
 
                        return xLabelOld != xLabel || yLabelOld != yLabel;
659
 
                }
660
 
                else {
661
 
                        // STANDARD BEHAVIOUR
662
 
                        if (geo.labelOffsetX == 0 && geo.labelOffsetY == 0) return false;
663
 
                                
664
 
                        int x = xLabel + geo.labelOffsetX;
665
 
                        int y = yLabel + geo.labelOffsetY;
666
 
                        
667
 
                        // don't let offset move label out of screen
668
 
                        int xmax = view.width - 15;
669
 
                        int ymax = view.height - 5;
670
 
                        if (x < 5 || x > xmax ) return false;
671
 
                        if (y < 15 || y > ymax) return false;
672
 
                        
673
 
                        xLabel = x;
674
 
                        yLabel = y;
675
 
                        return true;
676
 
                }
677
 
        }
678
 
        
679
 
        /**
680
 
         * Was the label clicked at? (mouse pointer
681
 
         * location (x,y) in screen coords)
682
 
         */             
683
 
        public boolean hitLabel(int x, int y) {
684
 
                return labelRectangle.contains(x, y);
685
 
        }
686
 
 
687
 
        final void updateStrokes(GeoElement geo) {
688
 
                strokedShape = null;
689
 
                strokedShape2 = null;           
690
 
                
691
 
                if (lineThickness != geo.lineThickness) {
692
 
                        lineThickness = geo.lineThickness;
693
 
                        lineType = geo.lineType;
694
 
 
695
 
                        float width = lineThickness / 2.0f;
696
 
                        objStroke = EuclidianView.getStroke(width, lineType);
697
 
                        decoStroke = EuclidianView.getStroke(width, EuclidianView.LINE_TYPE_FULL);
698
 
                        selStroke =
699
 
                                EuclidianView.getStroke(
700
 
                                        width + EuclidianView.SELECTION_ADD,
701
 
                                        EuclidianView.LINE_TYPE_FULL);
702
 
                } else if (lineType != geo.lineType) {
703
 
                        lineType = geo.lineType;
704
 
 
705
 
                        float width = lineThickness / 2.0f;
706
 
                        objStroke = EuclidianView.getStroke(width, lineType);
707
 
                }
708
 
        }
709
 
        
710
 
        final public static void drawWithValueStrokePure(Shape shape, Graphics2D g2) {
711
 
                Object oldHint = g2.getRenderingHint(RenderingHints.KEY_STROKE_CONTROL);                        
712
 
                g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);                       
713
 
                g2.draw(shape);
714
 
                g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, oldHint);                        
715
 
        }               
716
 
        
717
 
        final public static void fillWithValueStrokePure(Shape shape, Graphics2D g2) {
718
 
                Object oldHint = g2.getRenderingHint(RenderingHints.KEY_STROKE_CONTROL);                        
719
 
                g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);       
720
 
                g2.fill(shape);
721
 
                g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, oldHint);                        
722
 
        }
723
 
        
724
 
        //private StringBuffer command = new StringBuffer();
725
 
        private double[] coords = new double[2];
726
 
        
727
 
        public void recordToSpreadsheet(GeoElement geo) {
728
 
                
729
 
                
730
 
                // stop spurious numbers after undo
731
 
                if (view.getKernel().isViewReiniting()) return;
732
 
                
733
 
        // record to spreadsheet tool & trace to spreadsheet
734
 
        Construction cons = view.getKernel().getConstruction();
735
 
        {
736
 
                int row;
737
 
                String col;
738
 
                
739
 
                switch (geo.getGeoClassType()) {
740
 
                
741
 
                /* TODO: use this, rather than the code in GeoNumeric.update()
742
 
                case GeoElement.GEO_CLASS_NUMERIC:
743
 
                        
744
 
                        cons.getApplication().getGuiManager().traceToSpreadsheet(geo);
745
 
                        
746
 
                        break;*/
747
 
                        
748
 
                case GeoElement.GEO_CLASS_POINT:
749
 
                //Application.debug("GEO_CLASS_POINT");                 
750
 
                        GeoPoint P = (GeoPoint)geo;
751
 
                        
752
 
                        boolean polar = P.getMode() == Kernel.COORD_POLAR;
753
 
                        
754
 
                        if (polar)
755
 
                                P.getPolarCoords(coords);
756
 
                        else
757
 
                                P.getInhomCoords(coords);
758
 
                        
759
 
                        
760
 
                        if (P.getLastTrace1() != coords[0] || P.getLastTrace2() != coords[1]) {
761
 
                                
762
 
                                cons.getApplication().getGuiManager().traceToSpreadsheet(geo);
763
 
                                /*
764
 
                                col = P.getTraceColumn1(); // call before getTraceRow()
765
 
                                row = P.getTraceRow();
766
 
                                if (row > 0) {
767
 
                                //Application.debug(col+row);                   
768
 
                                        cons.getApplication().getGuiManager().setScrollToShow(true);
769
 
                                        
770
 
                                        GeoNumeric traceCell = new GeoNumeric(cons,col+row,coords[0]);
771
 
                                        traceCell.setAuxiliaryObject(true);
772
 
                                        
773
 
                                        col = P.getTraceColumn2(); // call before getTraceRow()
774
 
                                //Application.debug(col+row);                   
775
 
                                        
776
 
                                        GeoNumeric traceCell2;
777
 
                                        
778
 
                                        if (polar) traceCell2 = new GeoAngle(cons,col+row,coords[1]);
779
 
                                        else traceCell2 = new GeoNumeric(cons,col+row,coords[1]);
780
 
                                        
781
 
                                        traceCell2.setAuxiliaryObject(true);
782
 
                                        
783
 
                                        cons.getApplication().getGuiManager().setScrollToShow(false);   
784
 
                                        
785
 
                                        P.setLastTrace1(coords[0]);
786
 
                                        P.setLastTrace2(coords[1]);
787
 
                                }*/
788
 
                                
789
 
                        }
790
 
                break;
791
 
                
792
 
                case GeoElement.GEO_CLASS_VECTOR:
793
 
                // record to spreadsheet tool
794
 
                        GeoVector vector = (GeoVector)geo;
795
 
 
796
 
 
797
 
                        vector.getInhomCoords(coords);
798
 
                        
799
 
                        if (vector.getLastTrace1() != coords[0] || vector.getLastTrace2() != coords[1]) {
800
 
                                
801
 
                                cons.getApplication().getGuiManager().traceToSpreadsheet(geo);
802
 
                                
803
 
                                /*
804
 
                                col = vector.getTraceColumn1();
805
 
                                row = vector.getTraceRow();
806
 
                                if (row > 0) {
807
 
                                        cons.getApplication().getGuiManager().setScrollToShow(true);
808
 
                                        
809
 
                                        GeoNumeric traceCell = new GeoNumeric(cons,col+row,coords[0]);
810
 
                                        traceCell.setAuxiliaryObject(true);
811
 
                                        GeoNumeric traceCell2 = new GeoNumeric(cons,vector.getTraceColumn2()+row,coords[1]);
812
 
                                        traceCell2.setAuxiliaryObject(true);
813
 
                                        
814
 
                                        cons.getApplication().getGuiManager().setScrollToShow(false);
815
 
                                        
816
 
                                        vector.setLastTrace1(coords[0]);
817
 
                                        vector.setLastTrace2(coords[1]);
818
 
                                }*/
819
 
                                
820
 
                        }
821
 
                                                
822
 
                        break;
823
 
                }
824
 
        }       
825
 
        }
826
 
 
827
 
}
 
 
b'\\ No newline at end of file'
 
1
/*
 
2
GeoGebra - Dynamic Mathematics for Everyone
 
3
http://www.geogebra.org
 
4
 
 
5
This file is part of GeoGebra.
 
6
 
 
7
This program is free software; you can redistribute it and/or modify it
 
8
under the terms of the GNU General Public License as published by
 
9
the Free Software Foundation.
 
10
 
 
11
*/
 
12
 
 
13
/*
 
14
 * Drawable.java
 
15
 *
 
16
 * Created on 13. Oktober 2001, 17:40
 
17
 */
 
18
 
 
19
package geogebra.euclidian;
 
20
 
 
21
import geogebra.kernel.Construction;
 
22
import geogebra.kernel.GeoElement;
 
23
import geogebra.kernel.GeoText;
 
24
import geogebra.main.Application;
 
25
import geogebra.main.MyError;
 
26
import geogebra.util.Unicode;
 
27
 
 
28
import java.awt.BasicStroke;
 
29
import java.awt.Color;
 
30
import java.awt.Font;
 
31
import java.awt.Graphics2D;
 
32
import java.awt.Image;
 
33
import java.awt.Insets;
 
34
import java.awt.Point;
 
35
import java.awt.Rectangle;
 
36
import java.awt.RenderingHints;
 
37
import java.awt.Shape;
 
38
import java.awt.font.FontRenderContext;
 
39
import java.awt.font.TextLayout;
 
40
import java.awt.geom.Area;
 
41
import java.util.ArrayList;
 
42
import java.util.Iterator;
 
43
 
 
44
import javax.swing.JLabel;
 
45
 
 
46
 
 
47
 
 
48
/**
 
49
 *
 
50
 * @author  Markus
 
51
 * @version
 
52
 */
 
53
public abstract class Drawable extends DrawableND {
 
54
 
 
55
        private boolean forceNoFill;
 
56
 
 
57
 
 
58
        BasicStroke objStroke = EuclidianView.getDefaultStroke();
 
59
        BasicStroke selStroke = EuclidianView.getDefaultSelectionStroke();
 
60
        BasicStroke decoStroke = EuclidianView.getDefaultStroke();
 
61
 
 
62
        private int lineThickness = -1;
 
63
        public int lineType = -1;
 
64
 
 
65
        protected EuclidianView view;
 
66
        protected int hitThreshold = 3;
 
67
        protected GeoElement geo;
 
68
        public int xLabel, yLabel;
 
69
        /** for Previewables */
 
70
        int mouseX, mouseY;
 
71
        /** label Description */
 
72
        protected String labelDesc;
 
73
        private String oldLabelDesc;
 
74
        private boolean labelHasIndex = false;
 
75
        /** for label hit testing */
 
76
        Rectangle labelRectangle = new Rectangle();
 
77
        Shape strokedShape, strokedShape2;
 
78
 
 
79
        private Area shape;
 
80
 
 
81
 
 
82
 
 
83
        private int lastFontSize = -1;
 
84
 
 
85
        /** tracing */
 
86
        protected boolean isTracing = false;
 
87
 
 
88
        //boolean createdByDrawList = false;
 
89
 
 
90
        public abstract void update();
 
91
        public abstract void draw(Graphics2D g2);
 
92
        public abstract boolean hit(int x, int y);
 
93
        public abstract boolean isInside(Rectangle rect);
 
94
        public abstract GeoElement getGeoElement();
 
95
        public abstract void setGeoElement(GeoElement geo);
 
96
 
 
97
        public double getxLabel() {
 
98
                return xLabel;
 
99
        }
 
100
 
 
101
        public double getyLabel() {
 
102
                return yLabel;
 
103
        }
 
104
 
 
105
        void updateFontSize() {
 
106
        }
 
107
 
 
108
        /**
 
109
         * Returns the bounding box of this Drawable in screen coordinates.
 
110
         * @return null when this Drawable is infinite or undefined
 
111
         */
 
112
        public Rectangle getBounds() {
 
113
                return null;
 
114
        }
 
115
 
 
116
        final protected void drawLabel(Graphics2D g2) {
 
117
                if (labelDesc == null) return;
 
118
                String label = labelDesc;
 
119
                Font oldFont  = null;
 
120
 
 
121
                // allow LaTeX caption surrounded by $ $
 
122
                if (label.startsWith("$") && label.endsWith("$")) {
 
123
                        boolean serif = true; // nice "x"s
 
124
                        if (geo.isGeoText()) serif = ((GeoText)geo).isSerifFont();
 
125
                        int offsetY = 10 + view.fontSize; // make sure LaTeX labels don't go off bottom of screen
 
126
                        FormulaDimension dim = view.getApplication().getDrawEquation().drawEquation(geo.getKernel().getApplication(), geo, g2, xLabel, yLabel - offsetY, label.substring(1, label.length() - 1), g2.getFont(), serif, g2.getColor(), g2.getBackground(), true);
 
127
                        labelRectangle.setBounds(xLabel, yLabel - dim.depth - offsetY, (int)dim.width, (int)dim.height);
 
128
                        return;
 
129
                }
 
130
 
 
131
                // label changed: check for bold or italic tags in caption
 
132
                if (oldLabelDesc != labelDesc || labelDesc.startsWith("<")) {
 
133
                        boolean italic = false;
 
134
 
 
135
                        // support for bold and italic tags in captions
 
136
                        // must be whole caption
 
137
                        if (label.startsWith("<i>") && label.endsWith("</i>")) {
 
138
                                if (oldFont == null)
 
139
                                        oldFont = g2.getFont();
 
140
 
 
141
                                // use Serif font so that we can get a nice curly italic x
 
142
                                g2.setFont(view.getApplication().getFont(true, oldFont.getStyle() | Font.ITALIC, oldFont.getSize()));
 
143
                                label = label.substring(3, label.length() - 4);
 
144
                                italic = true;
 
145
                        }
 
146
 
 
147
                        if (label.startsWith("<b>") && label.endsWith("</b>")) {
 
148
                                if (oldFont == null)
 
149
                                        oldFont = g2.getFont();
 
150
 
 
151
                                g2.setFont(g2.getFont().deriveFont(Font.BOLD + (italic ? Font.ITALIC : 0)));
 
152
                                label = label.substring(3, label.length() - 4);
 
153
                        }
 
154
                }
 
155
 
 
156
                // no index in label: draw it fast
 
157
                int fontSize = g2.getFont().getSize();
 
158
                if (oldLabelDesc == labelDesc && !labelHasIndex && lastFontSize == fontSize) {
 
159
                        lastFontSize = fontSize;
 
160
                        g2.drawString(label, xLabel, yLabel);
 
161
                        labelRectangle.setLocation(xLabel, yLabel - fontSize);
 
162
                }
 
163
                else { // label with index or label has changed:
 
164
                        // do the slower index drawing routine and check for indices
 
165
                        oldLabelDesc = labelDesc;
 
166
 
 
167
                        Point p = drawIndexedString(view.getApplication(), g2, label, xLabel, yLabel, isSerif());
 
168
                        labelHasIndex = p.y > 0;
 
169
                        labelRectangle.setBounds(xLabel, yLabel - fontSize, p.x, fontSize + p.y);
 
170
                }
 
171
 
 
172
                if (oldFont != null)
 
173
                        g2.setFont(oldFont);
 
174
        }
 
175
 
 
176
        /**
 
177
         * Adapts xLabel and yLabel to make sure that the label rectangle fits fully on screen.
 
178
         */
 
179
        final public void ensureLabelDrawsOnScreen() {
 
180
                // draw label and
 
181
                drawLabel(view.getTempGraphics2D(view.getApplication().getPlainFont()));
 
182
 
 
183
                // make sure labelRectangle fits on screen horizontally
 
184
                if (xLabel < 3)
 
185
                        xLabel = 3;
 
186
                else
 
187
                        xLabel = Math.min(xLabel, view.width - labelRectangle.width - 3);
 
188
                if (yLabel < labelRectangle.height)
 
189
                        yLabel = labelRectangle.height;
 
190
                else
 
191
                        yLabel = Math.min(yLabel, view.height - 3);
 
192
 
 
193
                // update label rectangle position
 
194
                labelRectangle.setLocation(xLabel, yLabel - view.fontSize);
 
195
        }
 
196
 
 
197
        // Michael Borcherds 2008-06-10
 
198
        final static float textWidth(String str, Font font, FontRenderContext frc)
 
199
        {
 
200
                if (str.equals("")) return 0f;
 
201
                TextLayout layout = new TextLayout(str , font, frc);
 
202
                return layout.getAdvance();
 
203
 
 
204
        }
 
205
 
 
206
 
 
207
        /* old version
 
208
        final void drawMultilineLaTeX(Graphics2D g2, Font font, Color fgColor, Color bgColor) {
 
209
 
 
210
                int fontSize = g2.getFont().getSize();
 
211
                float lineSpread = fontSize * 1.0f;
 
212
                float lineSpace = fontSize * 0.5f;
 
213
 
 
214
                int maxhOffset=0;
 
215
                float height=0;
 
216
 
 
217
                Dimension dim;
 
218
 
 
219
                labelDesc=labelDesc.replaceAll("\\$\\$", "\\$"); // replace $$ with $
 
220
                labelDesc=labelDesc.replaceAll("\\\\\\[", "\\$");// replace \[ with $
 
221
                labelDesc=labelDesc.replaceAll("\\\\\\]", "\\$");// replace \] with $
 
222
                labelDesc=labelDesc.replaceAll("\\\\\\(", "\\$");// replace \( with $
 
223
                labelDesc=labelDesc.replaceAll("\\\\\\)", "\\$");// replace \) with $
 
224
 
 
225
 
 
226
                String[] lines=labelDesc.split("\n");
 
227
 
 
228
 
 
229
                for (int k=0 ; k<lines.length ; k++)
 
230
                {
 
231
 
 
232
                        String[] strings=lines[k].split("\\$");
 
233
                        int heights[] = new int[strings.length];
 
234
 
 
235
                        boolean latex=false;
 
236
                        if (lines[k].indexOf('$') == -1 && lines.length == 1)
 
237
                        {
 
238
                                latex=true; // just latex
 
239
                        }
 
240
 
 
241
                        int maxHeight=0;
 
242
                        // calculate heights of each element
 
243
                        for (int j=0 ; j<strings.length ; j++)
 
244
                        {
 
245
 
 
246
                                if (!strings[j].equals(str(" ",strings[j].length()))) // check not empty or just spaces
 
247
                                {
 
248
                                        if (latex)
 
249
                                        {
 
250
                                                dim = drawEquation(view.getTempGraphics2D(),0,0, strings[j], font, fgColor, bgColor);
 
251
                                                //dim = sHotEqn.getSizeof(strings[j]);
 
252
                                                //widths[j] = dim.width;
 
253
                                                heights[j] = dim.height;
 
254
                                        }
 
255
                                        else
 
256
                                        {
 
257
                                                heights[j] = (int)lineSpread; //p.y;
 
258
                                        }
 
259
                                }
 
260
                                else
 
261
                                {
 
262
                                        heights[j]=0;
 
263
                                }
 
264
                                latex=!latex;
 
265
                                if (heights[j] > maxHeight) maxHeight=heights[j];
 
266
 
 
267
                        }
 
268
 
 
269
                        if (k!=0) maxHeight += lineSpace;
 
270
 
 
271
                        int hOffset=0;
 
272
 
 
273
                        latex=false;
 
274
                        if (lines[k].indexOf('$') == -1 && lines.length == 1)
 
275
                        {
 
276
                                latex=true; // just latex
 
277
                                //Application.debug("just latex");
 
278
                        }
 
279
 
 
280
                        // draw elements
 
281
                        for (int j=0 ; j<strings.length ; j++)
 
282
                        {
 
283
 
 
284
                                if (!strings[j].equals(str(" ",strings[j].length()))) // check not empty or just spaces
 
285
                                {
 
286
 
 
287
                                        int vOffset = (maxHeight - heights[j] )/2; // vertical centering
 
288
 
 
289
                                        if (latex)
 
290
                                        {
 
291
 
 
292
                                                dim = drawEquation(g2,xLabel + hOffset,(int)(yLabel + height) + vOffset, strings[j], font, fgColor, bgColor);
 
293
                                                hOffset+=dim.width;
 
294
                                        }
 
295
                                        else
 
296
                                        {
 
297
                                                Point p = drawIndexedString(g2, strings[j], xLabel + hOffset, yLabel + height + vOffset + lineSpread);
 
298
                                                hOffset+=p.x;
 
299
                                        }
 
300
                                }
 
301
                                latex=!latex;
 
302
                        }
 
303
                        if (hOffset > maxhOffset) maxhOffset = hOffset;
 
304
                        height += maxHeight;
 
305
                }
 
306
                labelRectangle.setBounds(xLabel, yLabel, maxhOffset, (int)height);
 
307
        }
 
308
 
 
309
        // returns a string consisting of n consecutive "str"s
 
310
        final private String str(String str, int n)
 
311
        {
 
312
                if (n == 0) return "";
 
313
                else if (n == 1) return str;
 
314
                else {
 
315
                        StringBuilder ret = new StringBuilder();
 
316
 
 
317
                        for (int i=0 ; i<n ; i++) ret.append(str);
 
318
                        return ret.toString();
 
319
                }
 
320
        } */
 
321
 
 
322
 
 
323
        /**
 
324
         * Draw a multiline LaTeX label.
 
325
         *
 
326
         * TODO: Improve performance (caching, etc.)
 
327
         * Florian Sonner
 
328
         * @param g2
 
329
         * @param font
 
330
         * @param fgColor
 
331
         * @param bgColor
 
332
         */
 
333
        public final void drawMultilineLaTeX(Graphics2D g2, Font font, Color fgColor, Color bgColor) {
 
334
                int fontSize = g2.getFont().getSize();
 
335
                int lineSpread = (int)(fontSize * 1.0f);
 
336
                int lineSpace = (int)(fontSize * 0.5f);
 
337
 
 
338
                // latex delimiters \[ \] \( \) $$ -> $
 
339
                labelDesc = labelDesc.replaceAll("(\\$\\$|\\\\\\[|\\\\\\]|\\\\\\(|\\\\\\))", "\\$");
 
340
 
 
341
                // split on $ but not \$
 
342
                String[] elements = labelDesc.split("(?<![\\\\])(\\$)", -1);
 
343
 
 
344
                ArrayList<Integer> lineHeights = new ArrayList<Integer>();
 
345
                lineHeights.add(new Integer(lineSpread + lineSpace));
 
346
                ArrayList<Integer> elementHeights = new ArrayList<Integer>();
 
347
                ArrayList<Integer> elementDepths = new ArrayList<Integer>();
 
348
 
 
349
                int depth = 0;
 
350
 
 
351
                // use latex by default just if there is just a single element
 
352
                boolean isLaTeX = (elements.length == 1);
 
353
 
 
354
                // calculate the required space of every element
 
355
                for(int i = 0, currentLine = 0, currentElement = 0; i < elements.length; ++i) {
 
356
                        if(isLaTeX) {
 
357
                                // save the height of this element by drawing it to a temporary buffer
 
358
                                FormulaDimension dim = new FormulaDimension();
 
359
                                dim = view.getApplication().getDrawEquation().drawEquation(view.app, geo, view.getTempGraphics2D(font), 0, 0, elements[i], font, ((GeoText)geo).isSerifFont(), fgColor, bgColor, false);
 
360
                                
 
361
                                int height = dim.height;
 
362
                                
 
363
                                depth += dim.depth;
 
364
                                
 
365
                                elementHeights.add(new Integer(height));
 
366
                                elementDepths.add(new Integer(dim.depth));
 
367
 
 
368
                                // check if this element is taller than every else in the line
 
369
                                if(height > (lineHeights.get(currentLine)).intValue())
 
370
                                        lineHeights.set(currentLine, new Integer(height));
 
371
 
 
372
                                ++currentElement;
 
373
                        } else {
 
374
                                elements[i] = elements[i].replaceAll("\\\\\\$", "\\$");
 
375
                                String[] lines = elements[i].split("\\n", -1);
 
376
 
 
377
                                for(int j = 0; j < lines.length; ++j) {
 
378
                                        elementHeights.add(new Integer(lineSpread));
 
379
                                        elementDepths.add(new Integer(0));
 
380
 
 
381
                                        // create a new line
 
382
                                        if(j + 1 < lines.length) {
 
383
                                                ++currentLine;
 
384
 
 
385
                                                lineHeights.add(new Integer(lineSpread + lineSpace));
 
386
                                        }
 
387
 
 
388
                                        ++currentElement;
 
389
                                }
 
390
                        }
 
391
 
 
392
                        isLaTeX = !isLaTeX;
 
393
                }
 
394
 
 
395
                int width = 0;
 
396
                int height = 0;
 
397
 
 
398
                // use latex by default just if there is just a single element
 
399
                isLaTeX = (elements.length == 1);
 
400
 
 
401
                int xOffset = 0;
 
402
                int yOffset = 0;
 
403
 
 
404
                // now draw all elements
 
405
                for(int i = 0, currentLine = 0, currentElement = 0; i < elements.length; ++i) {
 
406
                        if(isLaTeX) {
 
407
                                // calculate the y offset of this element by: (lineHeight - elementHeight) / 2
 
408
                                yOffset = (((lineHeights.get(currentLine))).intValue() - ((elementHeights.get(currentElement))).intValue()) / 2;
 
409
                                
 
410
                                // draw the equation and save the x offset
 
411
                                xOffset += view.getApplication().getDrawEquation().drawEquation(view.app, geo, g2, xLabel + xOffset, (yLabel + height) + yOffset + elementDepths.get(currentElement), elements[i], font, ((GeoText)geo).isSerifFont(), fgColor, bgColor, true).width;
 
412
 
 
413
                                ++currentElement;
 
414
                        } else {
 
415
                                String[] lines = elements[i].split("\\n", -1);
 
416
 
 
417
                                for(int j = 0; j < lines.length; ++j) {
 
418
                                        // calculate the y offset like done with the element
 
419
                                        yOffset = (((lineHeights.get(currentLine))).intValue() - ((elementHeights.get(currentElement))).intValue()) / 2;
 
420
 
 
421
                                        // draw the string
 
422
                                        g2.setFont(font); // JLaTeXMath changes g2's fontsize
 
423
                                        xOffset += drawIndexedString(view.getApplication(), g2, lines[j], xLabel + xOffset, yLabel + height + yOffset + lineSpread, isSerif()).x;
 
424
 
 
425
                                        // add the height of this line if more lines follow
 
426
                                        if(j + 1 < lines.length) {
 
427
                                                height += ((lineHeights.get(currentLine))).intValue();
 
428
 
 
429
                                                if(xOffset > width)
 
430
                                                        width = xOffset;
 
431
                                        }
 
432
 
 
433
                                        // create a new line if more will follow
 
434
                                        if(j + 1 < lines.length) {
 
435
                                                ++currentLine;
 
436
                                                xOffset = 0;
 
437
                                        }
 
438
 
 
439
                                        ++currentElement;
 
440
                                }
 
441
                        }
 
442
 
 
443
                        // last element, increase total height and check if this is the most wide element
 
444
                        if(i + 1 == elements.length) {
 
445
                                height += ((lineHeights.get(currentLine))).intValue();
 
446
 
 
447
                                if(xOffset > width)
 
448
                                        width = xOffset;
 
449
                        }
 
450
 
 
451
                        isLaTeX = !isLaTeX;
 
452
                }
 
453
                labelRectangle.setBounds(xLabel - 3, yLabel - 3 + depth, width + 6, height + 6 );
 
454
        }
 
455
        /*
 
456
        private static geogebra.gui.hoteqn.sHotEqn eqn;
 
457
 
 
458
        final  public static Dimension drawEquationHotEqn(Application app, Graphics2D g2, int x, int y, String text, Font font, Color fgColor, Color bgColor)
 
459
        {
 
460
                Dimension dim;
 
461
                if (eqn == null) {
 
462
                        eqn = new geogebra.gui.hoteqn.sHotEqn(text);
 
463
                        //Application.debug(eqn.getSize());
 
464
                        eqn.setDoubleBuffered(false);
 
465
                        eqn.setEditable(false);
 
466
                        eqn.removeMouseListener(eqn);
 
467
                        eqn.removeMouseMotionListener(eqn);
 
468
                        eqn.setDebug(false);
 
469
                        eqn.setOpaque(false);
 
470
                }
 
471
                else
 
472
                {
 
473
                        eqn.setEquation(text);
 
474
                }
 
475
 
 
476
                        //setEqnFontSize();
 
477
                        int size = (font.getSize() / 2) * 2;
 
478
                        if (size < 10)
 
479
                                size = 10;
 
480
                        else if (size > 28)
 
481
                                size = 28;
 
482
 
 
483
                        eqn.setFontname(font.getName());
 
484
                        eqn.setFontsizes(size, size - 2, size - 4, size - 6);
 
485
                        eqn.setFontStyle(font.getStyle());
 
486
 
 
487
 
 
488
                        eqn.setForeground(fgColor);
 
489
                        eqn.setBackground(bgColor);
 
490
 
 
491
 
 
492
                        //eqn.paintComponent(g2Dtemp,0,0);
 
493
                        //dim=eqn.getSizeof(text);
 
494
                        eqn.paintComponent(g2,x,y);
 
495
                        dim=eqn.getSize();
 
496
 
 
497
                        //Application.debug(size);
 
498
                        return dim;
 
499
        }//*/
 
500
 
 
501
 
 
502
        /**
 
503
         * Adds \\- to positions where the line can
 
504
         * be broken. Now it only breaks at +, -, *
 
505
         * and spaces.
 
506
         *
 
507
         * @param latex String
 
508
         * @return The LaTeX string with breaks
 
509
         */
 
510
        private static String addPossibleBreaks(String latex){
 
511
                StringBuilder latexTmp=new StringBuilder(latex);
 
512
                int depth=0;
 
513
                boolean no_addition=true;
 
514
                for (int i=0; i<latexTmp.length()-2;i++){
 
515
                        char character=latexTmp.charAt(i);
 
516
                        switch (character){
 
517
                        case '(':
 
518
                        case '[':
 
519
                        case '{':
 
520
                                depth++;
 
521
                                break;
 
522
                        case ')':
 
523
                        case ']':
 
524
                        case '}':
 
525
                                depth--;
 
526
                                break;
 
527
                        case '\\':
 
528
                                if (latexTmp.charAt(i+1) != ';')
 
529
                                        break;
 
530
                                i++;
 
531
                                latexTmp.insert(i+1, "\\?");
 
532
                                i=i+2;
 
533
                                break;
 
534
                        case ' ':
 
535
                                if (latexTmp.charAt(i+1)!=' ')
 
536
                                        break;
 
537
                                i++;
 
538
                        case '*':
 
539
                                if (depth != 0)
 
540
                                        break;
 
541
                                latexTmp.insert(i+1, "\\?");
 
542
                                i=i+2;
 
543
                                break;
 
544
                        case '+':
 
545
                        case '-':
 
546
                                if (depth != 0)
 
547
                                        break;
 
548
                                latexTmp.insert(i+1, "\\-");
 
549
                                i=i+2;
 
550
                                no_addition=false;
 
551
                        }
 
552
                }
 
553
                //no addition happened at depth zero so it can be broken
 
554
                //on * and space too.
 
555
                if (no_addition){
 
556
                        return latexTmp.toString().replaceAll("\\?", "\\-");
 
557
                } else {
 
558
                        return latexTmp.toString().replaceAll("\\?", "");
 
559
                }
 
560
        }
 
561
 
 
562
 
 
563
        final static Rectangle drawMultiLineText(Application app, String labelDesc, int xLabel, int yLabel, Graphics2D g2, boolean serif) {
 
564
                int lines = 0;
 
565
                int fontSize = g2.getFont().getSize();
 
566
                float lineSpread = fontSize * 1.5f;
 
567
 
 
568
                Font font = g2.getFont();
 
569
                font = app.getFontCanDisplay(labelDesc, serif, font.getStyle(), font.getSize());
 
570
 
 
571
                FontRenderContext frc = g2.getFontRenderContext();
 
572
                int xoffset = 0;
 
573
 
 
574
                // draw text line by line
 
575
                int lineBegin = 0;
 
576
                int length = labelDesc.length();
 
577
                for (int i=0; i < length-1; i++) {
 
578
                        if (labelDesc.charAt(i) == '\n') {
 
579
                                //end of line reached: draw this line
 
580
                                g2.drawString(labelDesc.substring(lineBegin, i), xLabel, yLabel + lines * lineSpread);
 
581
 
 
582
                                int width=(int)textWidth(labelDesc.substring(lineBegin, i), font, frc);
 
583
                                if (width > xoffset) xoffset = width;
 
584
 
 
585
                                lines++;
 
586
                                lineBegin = i + 1;
 
587
                        }
 
588
                }
 
589
 
 
590
                float ypos = yLabel + lines * lineSpread;
 
591
                g2.drawString(labelDesc.substring(lineBegin), xLabel, ypos);
 
592
 
 
593
                int width=(int)textWidth(labelDesc.substring(lineBegin), font, frc);
 
594
                if (width > xoffset) xoffset = width;
 
595
 
 
596
                // Michael Borcherds 2008-06-10
 
597
                // changed setLocation to setBounds (bugfix)
 
598
                // and added final float textWidth()
 
599
                //labelRectangle.setLocation(xLabel, yLabel - fontSize);
 
600
                int height = (int) ( (lines +1)*lineSpread);
 
601
 
 
602
                return new Rectangle(xLabel-3, yLabel - fontSize -3, xoffset+6, height+6);
 
603
                //labelRectangle.setBounds(xLabel, yLabel - fontSize, xoffset, height );
 
604
 
 
605
        }
 
606
        
 
607
        final boolean isSerif() {
 
608
                return geo.isGeoText() ? ((GeoText)geo).isSerifFont() : false;
 
609
        }
 
610
 
 
611
        final void drawMultilineText(Graphics2D g2) {
 
612
 
 
613
                if (labelDesc == null) return;
 
614
 
 
615
 
 
616
                // no index in text
 
617
                if (oldLabelDesc == labelDesc && !labelHasIndex) {
 
618
 
 
619
                        labelRectangle.setBounds(drawMultiLineText(view.getApplication(), labelDesc, xLabel, yLabel, g2, isSerif()) );
 
620
                }
 
621
                else {
 
622
                        int lines = 0;
 
623
                        int fontSize = g2.getFont().getSize();
 
624
                        float lineSpread = fontSize * 1.5f;
 
625
 
 
626
                        int xoffset = 0, yoffset = 0;
 
627
                        // text with indices
 
628
                        // label description has changed, search for possible indices
 
629
                        oldLabelDesc = labelDesc;
 
630
 
 
631
                        // draw text line by line
 
632
                        int lineBegin = 0;
 
633
                        int length = labelDesc.length();
 
634
                        xoffset = 0;
 
635
                        yoffset = 0;
 
636
                        for (int i=0; i < length-1; i++) {
 
637
                                if (labelDesc.charAt(i) == '\n') {
 
638
                                        //end of line reached: draw this line
 
639
                                        Point p = drawIndexedString(view.getApplication(), g2, labelDesc.substring(lineBegin, i), xLabel, yLabel + lines * lineSpread, geo.isGeoText() ? ((GeoText)geo).isSerifFont() : false);
 
640
                                        if (p.x > xoffset) xoffset = p.x;
 
641
                                        if (p.y > yoffset) yoffset = p.y;
 
642
                                        lines++;
 
643
                                        lineBegin = i + 1;
 
644
                                }
 
645
                        }
 
646
 
 
647
                        float ypos = yLabel + lines * lineSpread;
 
648
                        Point p = drawIndexedString(view.getApplication(), g2, labelDesc.substring(lineBegin), xLabel, ypos, isSerif());
 
649
                        if (p.x > xoffset) xoffset = p.x;
 
650
                        if (p.y > yoffset) yoffset = p.y;
 
651
                        labelHasIndex = yoffset > 0;
 
652
                        int height = (int) ( (lines +1)*lineSpread);
 
653
                        labelRectangle.setBounds(xLabel-3, yLabel - fontSize - 3, xoffset + 6, height + 6 );
 
654
                }
 
655
        }
 
656
 
 
657
        /**
 
658
         * Draws a string str with possible indices to g2 at position x, y.
 
659
         * The indices are drawn using the given indexFont.
 
660
         * Examples for strings with indices: "a_1" or "s_{ab}"
 
661
         * @param g2
 
662
         * @param str
 
663
         * @return additional pixel needed to draw str (x-offset, y-offset)
 
664
         */
 
665
        public static Point drawIndexedString(Application app, Graphics2D g2, String str, float xPos, float yPos, boolean serif) {
 
666
                Font g2font = g2.getFont();
 
667
                g2font = app.getFontCanDisplay(str, serif, g2font.getStyle(), g2font.getSize());
 
668
                Font indexFont = getIndexFont(g2font);
 
669
                Font font = g2font;
 
670
                TextLayout layout;
 
671
                FontRenderContext frc = g2.getFontRenderContext();
 
672
 
 
673
                int indexOffset = indexFont.getSize() / 2;
 
674
                float maxY = 0;
 
675
                int depth = 0;
 
676
                float x = xPos;
 
677
                float y = yPos;
 
678
                int startPos = 0;
 
679
                if (str == null) return null;
 
680
                int length = str.length();
 
681
 
 
682
                for (int i=0; i < length; i++) {
 
683
                        switch (str.charAt(i)) {
 
684
                                case '_':
 
685
                                        //      draw everything before _
 
686
                                        if (i > startPos) {
 
687
                                                font = (depth == 0) ? g2font : indexFont;
 
688
                                                y = yPos + depth * indexOffset;
 
689
                                                if (y > maxY) maxY = y;
 
690
                                                String tempStr = str.substring(startPos, i);
 
691
                                                layout = new TextLayout(tempStr, font, frc);
 
692
                                                g2.setFont(font);
 
693
                                                g2.drawString(tempStr, x, y);
 
694
                                                x += layout.getAdvance();
 
695
                                        }
 
696
                                        startPos = i + 1;
 
697
                                        depth++;
 
698
 
 
699
                                        // check if next character is a '{' (beginning of index with several chars)
 
700
                                        if (startPos < length && str.charAt(startPos) != '{') {
 
701
                                                font = (depth == 0) ? g2font : indexFont;
 
702
                                                y = yPos + depth * indexOffset;
 
703
                                                if (y > maxY) maxY = y;
 
704
                                                String tempStr = str.substring(startPos, startPos+1);
 
705
                                                layout = new TextLayout(tempStr, font, frc);
 
706
                                                g2.setFont(font);
 
707
                                                g2.drawString(tempStr, x, y);
 
708
                                                x += layout.getAdvance();
 
709
                                                depth--;
 
710
                                        }
 
711
                                        i++;
 
712
                                        startPos++;
 
713
                                        break;
 
714
 
 
715
                                case '}': // end of index with several characters
 
716
                                        if (depth > 0) {
 
717
                                                if (i > startPos) {
 
718
                                                        font = (depth == 0) ? g2font : indexFont;
 
719
                                                        y = yPos + depth * indexOffset;
 
720
                                                        if (y > maxY) maxY = y;
 
721
                                                        String tempStr = str.substring(startPos, i);
 
722
                                                        layout = new TextLayout(tempStr, font, frc);
 
723
                                                        g2.setFont(font);
 
724
                                                        g2.drawString(tempStr, x, y);
 
725
                                                        x += layout.getAdvance();
 
726
                                                }
 
727
                                                startPos = i+1;
 
728
                                                depth--;
 
729
                                        }
 
730
                                        break;
 
731
                        }
 
732
                }
 
733
 
 
734
                if (startPos < length) {
 
735
                        font = (depth == 0) ? g2font : indexFont;
 
736
                        y = yPos + depth * indexOffset;
 
737
                        if (y > maxY) maxY = y;
 
738
                        String tempStr = str.substring(startPos);
 
739
                        layout = new TextLayout(tempStr, font, frc);
 
740
                        g2.setFont(font);
 
741
                        g2.drawString(tempStr, x, y);
 
742
                        x += layout.getAdvance();
 
743
                }
 
744
                g2.setFont(g2font);
 
745
                return new Point(Math.round(x - xPos), Math.round(maxY - yPos));
 
746
        }
 
747
 
 
748
        private static Font getIndexFont(Font f) {
 
749
                //      index font size should be at least 8pt
 
750
                int newSize = Math.max( (int) (f.getSize() * 0.9) , 8);
 
751
                return f.deriveFont(f.getStyle(), newSize);
 
752
        }
 
753
 
 
754
        /**
 
755
         * Adds geo's label offset to xLabel and yLabel.
 
756
         *
 
757
         * @return whether something was changed
 
758
         */
 
759
        final protected boolean addLabelOffset() {
 
760
                return addLabelOffset(false);
 
761
        }
 
762
 
 
763
        /**
 
764
         * Adds geo's label offset to xLabel and yLabel.
 
765
         * @param ensureLabelOnScreen if true we make sure that the label is drawn on screen
 
766
         *
 
767
         * @return whether something was changed
 
768
         */
 
769
        final protected boolean addLabelOffset(boolean ensureLabelOnScreen) {
 
770
                if (ensureLabelOnScreen) {
 
771
                        // MAKE SURE LABEL STAYS ON SCREEN
 
772
                        int xLabelOld = xLabel;
 
773
                        int yLabelOld = yLabel;
 
774
                        xLabel += geo.labelOffsetX;
 
775
                        yLabel += geo.labelOffsetY;
 
776
 
 
777
                        // change xLabel and yLabel so that label stays on screen
 
778
                        ensureLabelDrawsOnScreen();
 
779
 
 
780
                        // something changed?
 
781
                        return xLabelOld != xLabel || yLabelOld != yLabel;
 
782
                }
 
783
                else {
 
784
                        // STANDARD BEHAVIOUR
 
785
                        if (geo.labelOffsetX == 0 && geo.labelOffsetY == 0) return false;
 
786
 
 
787
                        int x = xLabel + geo.labelOffsetX;
 
788
                        int y = yLabel + geo.labelOffsetY;
 
789
 
 
790
                        // don't let offset move label out of screen
 
791
                        int xmax = view.width - 15;
 
792
                        int ymax = view.height - 5;
 
793
                        if (x < 5 || x > xmax ) return false;
 
794
                        if (y < 15 || y > ymax) return false;
 
795
 
 
796
                        xLabel = x;
 
797
                        yLabel = y;
 
798
                        return true;
 
799
                }
 
800
        }
 
801
 
 
802
        /**
 
803
         * Was the label clicked at? (mouse pointer
 
804
         * location (x,y) in screen coords)
 
805
         */
 
806
        public boolean hitLabel(int x, int y) {
 
807
                return labelRectangle.contains(x, y);
 
808
        }
 
809
        private boolean forcedLineType;
 
810
 
 
811
        /**
 
812
         * Set fixed line type and ignore line type of the geo.
 
813
         * Needed for inequalities.
 
814
         * @param type
 
815
         */
 
816
        final void forceLineType(int type){
 
817
                forcedLineType = true;
 
818
                lineType = type;
 
819
        }
 
820
 
 
821
        /**
 
822
         * Update strokes (default,selection,deco) accordingly to geo
 
823
         * @param geo
 
824
         */
 
825
        final void updateStrokes(GeoElement geo) {
 
826
                strokedShape = null;
 
827
                strokedShape2 = null;
 
828
 
 
829
                if (lineThickness != geo.lineThickness) {
 
830
                        lineThickness = geo.lineThickness;
 
831
                        if(!forcedLineType)
 
832
                                lineType = geo.lineType;
 
833
 
 
834
                        float width = lineThickness / 2.0f;
 
835
                        objStroke = EuclidianView.getStroke(width, lineType);
 
836
                        decoStroke = EuclidianView.getStroke(width, EuclidianView.LINE_TYPE_FULL);
 
837
                        selStroke =
 
838
                                EuclidianView.getStroke(
 
839
                                        width + EuclidianView.SELECTION_ADD,
 
840
                                        EuclidianView.LINE_TYPE_FULL);
 
841
                } else if (lineType != geo.lineType) {
 
842
                        if(!forcedLineType)
 
843
                                lineType = geo.lineType;
 
844
 
 
845
                        float width = lineThickness / 2.0f;
 
846
                        objStroke = EuclidianView.getStroke(width, lineType);
 
847
                }
 
848
        }
 
849
 
 
850
        final public static void drawWithValueStrokePure(Shape shape, Graphics2D g2) {
 
851
                Object oldHint = g2.getRenderingHint(RenderingHints.KEY_STROKE_CONTROL);
 
852
                g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
 
853
                g2.draw(shape);
 
854
                g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, oldHint);
 
855
        }
 
856
 
 
857
        final public static void fillWithValueStrokePure(Shape shape, Graphics2D g2) {
 
858
                Object oldHint = g2.getRenderingHint(RenderingHints.KEY_STROKE_CONTROL);
 
859
                g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
 
860
                g2.fill(shape);
 
861
                g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, oldHint);
 
862
        }
 
863
 
 
864
        //private StringBuilder command = new StringBuilder();
 
865
        private double[] coords = new double[2];
 
866
 
 
867
 
 
868
 
 
869
        //=================================================================
 
870
        //G.Sturr 2010-5-14: new recordToSpreadsheet method
 
871
 
 
872
 
 
873
        public void recordToSpreadsheet(GeoElement geo) {
 
874
 
 
875
                // stop spurious numbers after undo
 
876
                if (view.getKernel().isViewReiniting())
 
877
                        return;
 
878
                Construction cons = view.getKernel().getConstruction();
 
879
                if (cons.getApplication().useFullGui())
 
880
                        cons.getApplication().getGuiManager().traceToSpreadsheet(geo);
 
881
        }
 
882
 
 
883
        protected void fill(Graphics2D g2, Shape shape, boolean usePureStroke) {
 
884
                if(isForceNoFill())
 
885
                        return;
 
886
                if (geo.getFillType()==GeoElement.FILL_HATCH) {
 
887
 
 
888
                        // use decoStroke as it is always full (not dashed/dotted etc)
 
889
                        HatchingHandler.setHatching(g2, decoStroke, geo.getObjectColor(), geo.getBackgroundColor(), geo.getAlphaValue(), geo.getHatchingDistance(), geo.getHatchingAngle());
 
890
                        if (usePureStroke)
 
891
                                Drawable.fillWithValueStrokePure(shape, g2);
 
892
                        else
 
893
                                g2.fill(shape);
 
894
 
 
895
                }
 
896
                else if (geo.getFillType()==GeoElement.FILL_IMAGE)
 
897
                {
 
898
                        HatchingHandler.setTexture(g2, geo, geo.getAlphaValue());
 
899
                        g2.fill(shape);
 
900
                }
 
901
                else if (geo.getAlphaValue() > 0.0f)
 
902
                {
 
903
                        g2.setPaint(geo.getFillColor());
 
904
                        g2.fill(shape);
 
905
 
 
906
                }
 
907
 
 
908
        }
 
909
        /**
 
910
         * @param forceNoFill the forceNoFill to set
 
911
         */
 
912
        public void setForceNoFill(boolean forceNoFill) {
 
913
                this.forceNoFill = forceNoFill;
 
914
        }
 
915
        /**
 
916
         * @return the forceNoFill
 
917
         */
 
918
        public boolean isForceNoFill() {
 
919
                return forceNoFill;
 
920
        }
 
921
        /**
 
922
         * @param shape the shape to set
 
923
         */
 
924
        public void setShape(Area shape) {
 
925
                this.shape = shape;
 
926
        }
 
927
        /**
 
928
         * @return the shape
 
929
         */
 
930
        public Area getShape() {
 
931
                return shape;
 
932
        }
 
933
        
 
934
        
 
935
}