1 /* FILE: GlyphFactory.java
2 * DATE OF CREATION: Mon Oct 21 07:55:36 2002
3 * AUTHOR : Emmanuel Pietriga (emmanuel@w3.org)
4 * MODIF: Thu Feb 20 10:44:34 2003 by Emmanuel Pietriga
5 * Copyright (c) Emmanuel Pietriga, 2002. All Rights Reserved
6 * Licensed under the GNU LGPL. For full terms see the file COPYING.
7 */
8
9 package net.claribole.zvtm.glyphs;
10
11 import java.awt;
12 import java.awt.event;
13 import javax.swing;
14 import javax.swing.event;
15 import javax.swing.border;
16 import java.util.Vector;
17 import com.xerox.VTM.glyphs;
18
19
20 public class GlyphFactory extends JDialog implements ActionListener,MouseListener,ChangeListener {
21
22 /***/
23 public static String V_Shape="VShape";
24 public static String V_Rectangle="VRectangle";
25 public static String V_Ellipse="VEllipse";
26 public static String V_Circle="VCircle";
27 public static String V_Triangle="VTriangle";
28 public static String V_Diamond="VDiamond";
29 public static String V_Octagon="VOctagon";
30 private static Vector initShapeTypes(){
31 Vector res=new Vector();
32 res.add(V_Shape);res.add(V_Rectangle);res.add(V_Ellipse);res.add(V_Circle);
33 res.add(V_Triangle);res.add(V_Diamond);res.add(V_Octagon);
34 return res;
35 }
36 private static Vector allowedShapeTypes=initShapeTypes();
37 private static String defaultShapeType=V_Shape;
38 private static boolean changeableShapeType=true;
39
40 private static Color defaultFillColor=Color.white;
41 private static boolean editableFillColor=true;
42
43 private static Color defaultBorderColor=Color.white;
44 private static boolean editableBorderColor=true;
45
46 private static boolean defaultTransparencyOnOff=true;
47 private static boolean editableTransparencyOnOff=true;
48 private static double defaultAlphaValue=1.0;
49 private static boolean editableAlphaValue=true;
50
51 private static boolean defaultOrientationOnOff=true;
52 private static boolean editableOrientationOnOff=true;
53 private static double defaultAngleValue=0.0;
54 private static boolean editableAngleValue=true;
55 public static boolean hasEditableAngle(){return editableAngleValue;}
56
57 private static long defaultSizeValue=10;
58 private static boolean editableSizeValue=true;
59
60 private static int defaultVertexCount=8;
61 private static boolean editableVertexCount=true;
62
63 private static double[] defaultVertexValues={1.0,0.5,1.0,0.5,1.0,0.5,1.0,0.5};
64 private static boolean editableVertexValues=true;
65 public static boolean hasEditableVertexValues(){return editableVertexValues;}
66
67 private static int GLYPH_PANEL_WIDTH=301;
68
69 GlyphTracker gt;
70
71 GlyphPanel glyphPanel;
72 JComboBox glList;
73 ColorIndicator ci1,ci2;
74 JCheckBox transpChk,angleChk,aliasChk,gridChk,geomChk;
75 JSpinner transpSpin,angleSpin,sizeSpin,vxSpin;
76 JLabel vxVal,vxValLb,vxLb;
77 JButton okBt,cancelBt,resetBt;
78
79 double angle=defaultAngleValue;
80 long size=defaultSizeValue;
81 boolean orientable=defaultOrientationOnOff;
82 double aspectRatio=1.0; //(width/height ratio for RectangularShape)
83 double alpha=defaultAlphaValue;
84 Color fillColor=defaultFillColor;
85 Color borderColor=defaultBorderColor;
86 double[] vertices=defaultVertexValues;
87
88
89 /** Call a GlyphFactory window that will return the glyph created in the window (all parameters have default value and are editable)
90 *@param owner application frame that owns this Modal component
91 */
92 public static Glyph getGlyphFactoryDialog(Frame owner){
93 GlyphTracker res=new GlyphTracker();
94 GlyphFactory gf=new GlyphFactory(res,owner);
95 gf.addWindowListener(new GlyphFactory.Closer());
96 gf.addComponentListener(new GlyphFactory.DisposeOnClose());
97 gf.show(); //blocks until the dialog is closed
98 return res.getGlyph();
99 }
100
101 /** Call a GlyphFactory window that will return the glyph created in the window (all parameters have default value and are editable)
102 *@param owner application dialog that owns this Modal component
103 */
104 public static Glyph getGlyphFactoryDialog(Dialog owner){
105 GlyphTracker res=new GlyphTracker();
106 GlyphFactory gf=new GlyphFactory(res,owner);
107 gf.addWindowListener(new GlyphFactory.Closer());
108 gf.addComponentListener(new GlyphFactory.DisposeOnClose());
109 gf.show(); //blocks until the dialog is closed
110 return res.getGlyph();
111 }
112
113 /** Call a GlyphFactory window that will return the glyph created in the window (all parameters have default value and are editable)
114 *@param owner application frame that owns this Modal component
115 *@param dsv default size value (positive number) ; takes its default value if provided param is -1
116 */
117 public static Glyph getGlyphFactoryDialog(Frame owner,long dsv){
118 if (dsv!=-1){defaultSizeValue=dsv;}
119 GlyphTracker res=new GlyphTracker();
120 GlyphFactory gf=new GlyphFactory(res,owner);
121 gf.addWindowListener(new GlyphFactory.Closer());
122 gf.addComponentListener(new GlyphFactory.DisposeOnClose());
123 gf.show(); //blocks until the dialog is closed
124 return res.getGlyph();
125 }
126
127 /** Call a GlyphFactory window that will return the glyph created in the window (all parameters have default value and are editable)
128 *@param owner application dialog that owns this Modal component
129 *@param dsv default size value (positive number) ; takes its default value if provided param is -1
130 */
131 public static Glyph getGlyphFactoryDialog(Dialog owner,long dsv){
132 if (dsv!=-1){defaultSizeValue=dsv;}
133 GlyphTracker res=new GlyphTracker();
134 GlyphFactory gf=new GlyphFactory(res,owner);
135 gf.addWindowListener(new GlyphFactory.Closer());
136 gf.addComponentListener(new GlyphFactory.DisposeOnClose());
137 gf.show(); //blocks until the dialog is closed
138 return res.getGlyph();
139 }
140
141 /** Call a GlyphFactory window that will return the glyph created in the window (programer sets the default value(s) for every field and specifies if the field can be changed or not)
142 *@param owner application frame that owns this Modal component
143 *@param ast vector of allowed shape types (any sequence of static String V_xxx defined in this class) ; takes its default value if provided param is null
144 *@param dst default shape type (must be one of the elements of ast - default is V_Shape)
145 *@param cst tells whether the shape type can be changed or not
146 *@param dfc default fill color ; takes its default value if provided param is null
147 *@param efc tells whether the fill color can be changed or not
148 *@param dbc default border color ; takes its default value if provided param is null
149 *@param ebc tells whether the border color can be changed or not
150 *@param dto is transparency ON or OFF by default
151 *@param eto tells whether the transparency switch can be changed or not
152 *@param dav default alpha channel value (in range [0,1.0]) ; takes its default value if provided param is -1.0
153 *@param eav tells whether the alpha value can be changed or not
154 *@param doo is orientation ON or OFF by default
155 *@param eoo tells whether the orientation switch can be toggled
156 *@param dagv default angle value (in range [0,2*Pi]) ; takes its default value if provided param is -10.0
157 *@param eagv tells whether the angle value can be changed or not
158 *@param dsv default size value (positive number) ; takes its default value if provided param is -1
159 *@param esv tells whether the size value can be changed or not
160 *@param dvc default vertex count (positive number) ; takes its default value if provided param is -1 ; if dvc and dvv are not coherent, dvv's length determines the vertex count
161 *@param evc tells whether the vertex count can be changed or not
162 *@param dvv default vertex values (each value in range [0,1.0]) ; takes its default value if provided param is null ; if dvc and dvv are not coherent, dvv's length determines the vertex count
163 *@param evv tells whether vertex values can be changed or not
164 */
165 public static Glyph getGlyphFactoryDialog(Frame owner,Vector ast,String dst,boolean cst,Color dfc,boolean efc,Color dbc,boolean ebc,boolean dto,boolean eto,double dav,boolean eav,boolean doo,boolean eoo,double dagv,boolean eagv,long dsv,boolean esv,int dvc,boolean evc,double[] dvv,boolean evv){
166 if (ast!=null){allowedShapeTypes=ast;}
167 if (allowedShapeTypes.contains(dst)){defaultShapeType=dst;}
168 changeableShapeType=cst;
169 if (dfc!=null){defaultFillColor=dfc;}
170 editableFillColor=efc;
171 if (dbc!=null){defaultBorderColor=dbc;}
172 editableBorderColor=ebc;
173 defaultTransparencyOnOff=dto;
174 editableTransparencyOnOff=eto;
175 if (dav!=-1.0){defaultAlphaValue=dav;}
176 editableAlphaValue=eav;
177 defaultOrientationOnOff=doo;
178 editableOrientationOnOff=eoo;
179 if (dagv!=-10.0){defaultAngleValue=dagv;}
180 editableAngleValue=eagv;
181 if (dsv!=-1){defaultSizeValue=dsv;}
182 editableSizeValue=esv;
183 if (dvc>0){defaultVertexCount=dvc;}
184 editableVertexCount=evc;
185 if (dvv!=null){defaultVertexValues=dvv;}
186 editableVertexValues=evv;
187 if (defaultVertexValues.length!=defaultVertexCount){defaultVertexCount=defaultVertexValues.length;}
188 return getGlyphFactoryDialog(owner);
189 }
190
191 /** Call a GlyphFactory window that will return the glyph created in the window (programer sets the default value(s) for every field and specifies if the field can be changed or not)
192 *@param owner application dialog that owns this Modal component
193 *@param ast vector of allowed shape types (any sequence of static String V_xxx defined in this class) ; takes its default value if provided param is null
194 *@param dst default shape type (must be one of the elements of ast - default is V_Shape)
195 *@param cst tells whether the shape type can be changed or not
196 *@param dfc default fill color ; takes its default value if provided param is null
197 *@param efc tells whether the fill color can be changed or not
198 *@param dbc default border color ; takes its default value if provided param is null
199 *@param ebc tells whether the border color can be changed or not
200 *@param dto is transparency ON or OFF by default
201 *@param eto tells whether the transparency switch can be changed or not
202 *@param dav default alpha channel value (in range [0,1.0]) ; takes its default value if provided param is -1.0
203 *@param eav tells whether the alpha value can be changed or not
204 *@param doo is orientation ON or OFF by default
205 *@param eoo tells whether the orientation switch can be toggled
206 *@param dagv default angle value (in range [0,2*Pi]) ; takes its default value if provided param is -10.0
207 *@param eagv tells whether the angle value can be changed or not
208 *@param dsv default size value (positive number) ; takes its default value if provided param is -1
209 *@param esv tells whether the size value can be changed or not
210 *@param dvc default vertex count (positive number) ; takes its default value if provided param is -1 ; if dvc and dvv are not coherent, dvv's length determines the vertex count
211 *@param evc tells whether the vertex count can be changed or not
212 *@param dvv default vertex values (each value in range [0,1.0]) ; takes its default value if provided param is null ; if dvc and dvv are not coherent, dvv's length determines the vertex count
213 *@param evv tells whether vertex values can be changed or not
214 */
215 public static Glyph getGlyphFactoryDialog(Dialog owner,Vector ast,String dst,boolean cst,Color dfc,boolean efc,Color dbc,boolean ebc,boolean dto,boolean eto,double dav,boolean eav,boolean doo,boolean eoo,double dagv,boolean eagv,long dsv,boolean esv,int dvc,boolean evc,double[] dvv,boolean evv){
216 if (ast!=null){allowedShapeTypes=ast;}
217 if (allowedShapeTypes.contains(dst)){defaultShapeType=dst;}
218 changeableShapeType=cst;
219 if (dfc!=null){defaultFillColor=dfc;}
220 editableFillColor=efc;
221 if (dbc!=null){defaultBorderColor=dbc;}
222 editableBorderColor=ebc;
223 defaultTransparencyOnOff=dto;
224 editableTransparencyOnOff=eto;
225 if (dav!=-1.0){defaultAlphaValue=dav;}
226 editableAlphaValue=eav;
227 defaultOrientationOnOff=doo;
228 editableOrientationOnOff=eoo;
229 if (dagv!=-10.0){defaultAngleValue=dagv;}
230 editableAngleValue=eagv;
231 if (dsv!=-1){defaultSizeValue=dsv;}
232 editableSizeValue=esv;
233 if (dvc>0){defaultVertexCount=dvc;}
234 editableVertexCount=evc;
235 if (dvv!=null){defaultVertexValues=dvv;}
236 editableVertexValues=evv;
237 if (defaultVertexValues.length!=defaultVertexCount){defaultVertexCount=defaultVertexValues.length;}
238 return getGlyphFactoryDialog(owner);
239 }
240
241 static float[] doubleToFloatArray(double[] ar){
242 float[] res=new float[ar.length];
243 for (int i=0;i<ar.length;i++){
244 res[i]=(float)ar[i];
245 }
246 return res;
247 }
248
249 GlyphFactory(GlyphTracker glt,Frame owner){
250 super(owner,"ZVTM Glyph Factory",true);
251 gt=glt;
252 initUI(defaultShapeType,true,false,true);
253 }
254
255 GlyphFactory(GlyphTracker glt,Dialog owner){
256 super(owner,"ZVTM Glyph Factory",true);
257 gt=glt;
258 initUI(defaultShapeType,true,false,true);
259 }
260
261 void initUI(String si,boolean grid,boolean alias,boolean geom){//depending on selected item/default shape type
262 Container cp=this.getContentPane();
263 try {
264 glList.removeActionListener(this);
265 ci1.removeMouseListener(this);
266 ci2.removeMouseListener(this);
267 transpChk.removeActionListener(this);
268 transpSpin.removeChangeListener(this);
269 angleChk.removeActionListener(this);
270 angleSpin.removeChangeListener(this);
271 sizeSpin.removeChangeListener(this);
272 vxSpin.removeChangeListener(this);
273 gridChk.removeActionListener(this);
274 aliasChk.removeActionListener(this);
275 geomChk.removeActionListener(this);
276 glyphPanel.removeMouseListener((MouseListener)glyphPanel);
277 glyphPanel.removeMouseMotionListener((MouseMotionListener)glyphPanel);
278 okBt.removeActionListener(this);
279 cancelBt.removeActionListener(this);
280 resetBt.removeActionListener(this);
281 }
282 catch (NullPointerException ex){/*all these might be null (for instance when poping up a GlyphFactory for the first time)*/}
283 cp.removeAll();
284 //glyph definition panel
285 JPanel mainPanel=new JPanel();
286 mainPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.black),"Parameters"));
287 mainPanel.setLayout(new GridLayout(1,2));
288 //glyph repr panel
289 glyphPanel=setGlyphPanel(si);
290 glyphPanel.setPreferredSize(new Dimension(GLYPH_PANEL_WIDTH,GLYPH_PANEL_WIDTH));
291 glyphPanel.setMinimumSize(new Dimension(GLYPH_PANEL_WIDTH,GLYPH_PANEL_WIDTH));
292 glyphPanel.setMaximumSize(new Dimension(GLYPH_PANEL_WIDTH,GLYPH_PANEL_WIDTH));
293 //glyphPanel.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.RAISED));
294 mainPanel.add(glyphPanel);
295 glyphPanel.addMouseListener((MouseListener)glyphPanel);
296 glyphPanel.addMouseMotionListener((MouseMotionListener)glyphPanel);
297 //glyph param panel
298 JPanel paramPanel=new JPanel();
299 GridBagLayout gridBag1=new GridBagLayout();
300 GridBagConstraints constraints1=new GridBagConstraints();
301 paramPanel.setLayout(gridBag1);
302 constraints1.fill=GridBagConstraints.HORIZONTAL;
303 constraints1.anchor=GridBagConstraints.CENTER;
304 Vector glyphTypes=(Vector)GlyphFactory.allowedShapeTypes.clone();
305 glList=new JComboBox(glyphTypes);
306 glList.setMaximumRowCount(5);
307 buildConstraints(constraints1,0,0,2,1,100,14);
308 gridBag1.setConstraints(glList,constraints1);
309 paramPanel.add(glList);
310 glList.setSelectedItem(si);
311 glList.addActionListener(this);
312 glList.setEnabled(changeableShapeType);
313 ci1=new ColorIndicator("Fill Color",fillColor);
314 buildConstraints(constraints1,0,1,1,1,50,14);
315 gridBag1.setConstraints(ci1,constraints1);
316 paramPanel.add(ci1);
317 ci2=new ColorIndicator("Border Color",borderColor);
318 buildConstraints(constraints1,1,1,1,1,50,14);
319 gridBag1.setConstraints(ci2,constraints1);
320 paramPanel.add(ci2);
321 ci1.addMouseListener(this);ci2.addMouseListener(this);
322
323 transpChk=new JCheckBox("Translucent",defaultTransparencyOnOff);
324 buildConstraints(constraints1,0,2,1,1,50,14);
325 gridBag1.setConstraints(transpChk,constraints1);
326 paramPanel.add(transpChk);
327 transpChk.addActionListener(this);
328 transpChk.setEnabled(editableTransparencyOnOff);
329 transpSpin=new JSpinner(new SpinnerNumberModel(defaultAlphaValue,0.0,1.0,0.05));
330 buildConstraints(constraints1,1,2,1,1,50,14);
331 gridBag1.setConstraints(transpSpin,constraints1);
332 paramPanel.add(transpSpin);
333 transpSpin.setEnabled(transpChk.isSelected() ? editableAlphaValue : false);
334 transpSpin.addChangeListener(this);
335
336 angleChk=new JCheckBox("Orientation",defaultOrientationOnOff);
337 buildConstraints(constraints1,0,3,1,1,50,14);
338 gridBag1.setConstraints(angleChk,constraints1);
339 paramPanel.add(angleChk);
340 angleChk.addActionListener(this);
341 angleChk.setEnabled(editableOrientationOnOff);
342 angleSpin=new JSpinner(new SpinnerNumberModel(defaultAngleValue,0.0,2*Math.PI,0.02));
343 buildConstraints(constraints1,1,3,1,1,50,14);
344 gridBag1.setConstraints(angleSpin,constraints1);
345 paramPanel.add(angleSpin);
346 angleSpin.setEnabled(angleChk.isSelected() ? editableAngleValue : false);
347 angleSpin.addChangeListener(this);
348
349 JLabel szLb=new JLabel("Size");
350 buildConstraints(constraints1,0,4,1,1,50,14);
351 gridBag1.setConstraints(szLb,constraints1);
352 paramPanel.add(szLb);
353 sizeSpin=new JSpinner(new SpinnerNumberModel((int)defaultSizeValue,0,Integer.MAX_VALUE,10));
354 buildConstraints(constraints1,1,4,1,1,50,14);
355 gridBag1.setConstraints(sizeSpin,constraints1);
356 paramPanel.add(sizeSpin);
357 sizeSpin.setEnabled(editableSizeValue);
358 sizeSpin.addChangeListener(this);
359
360 vxLb=new JLabel("Vertex count");
361 buildConstraints(constraints1,0,5,1,1,50,14);
362 gridBag1.setConstraints(vxLb,constraints1);
363 paramPanel.add(vxLb);
364 vxSpin=new JSpinner(new SpinnerNumberModel(defaultVertexCount,3,Integer.MAX_VALUE,1));
365 buildConstraints(constraints1,1,5,1,1,50,14);
366 gridBag1.setConstraints(vxSpin,constraints1);
367 paramPanel.add(vxSpin);
368 vxSpin.setEnabled(editableVertexCount);
369 vxSpin.addChangeListener(this);
370
371 vxValLb=new JLabel("Selected vertex value");
372 buildConstraints(constraints1,0,6,1,1,50,14);
373 gridBag1.setConstraints(vxValLb,constraints1);
374 paramPanel.add(vxValLb);
375 vxVal=new JLabel(" ");
376 buildConstraints(constraints1,1,6,1,1,50,14);
377 gridBag1.setConstraints(vxVal,constraints1);
378 paramPanel.add(vxVal);
379
380 gridChk=new JCheckBox("Grid",grid);
381 buildConstraints(constraints1,0,7,1,1,50,14);
382 gridBag1.setConstraints(gridChk,constraints1);
383 paramPanel.add(gridChk);
384 gridChk.addActionListener(this);
385 aliasChk=new JCheckBox("Antialiasing",alias);
386 buildConstraints(constraints1,1,7,1,1,50,14);
387 gridBag1.setConstraints(aliasChk,constraints1);
388 paramPanel.add(aliasChk);
389 aliasChk.addActionListener(this);
390
391 geomChk=new JCheckBox("Indicators",geom);
392 buildConstraints(constraints1,0,8,2,1,100,14);
393 gridBag1.setConstraints(geomChk,constraints1);
394 paramPanel.add(geomChk);
395 geomChk.setSelected(true);
396 geomChk.addActionListener(this);
397
398 paramPanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
399 mainPanel.add(paramPanel);
400 //ok, cancel, reset buttons
401 JPanel btPanel=new JPanel();
402 btPanel.setLayout(new FlowLayout());
403 okBt=new JButton("OK");
404 okBt.addActionListener(this);
405 btPanel.add(okBt);
406 cancelBt=new JButton("Cancel");
407 cancelBt.addActionListener(this);
408 btPanel.add(cancelBt);
409 resetBt=new JButton("Reset");
410 resetBt.addActionListener(this);
411 btPanel.add(resetBt);
412 //main components
413 GridBagLayout gridBag=new GridBagLayout();
414 GridBagConstraints constraints=new GridBagConstraints();
415 cp.setLayout(gridBag);
416 constraints.fill=GridBagConstraints.BOTH;
417 constraints.anchor=GridBagConstraints.CENTER;
418 buildConstraints(constraints,0,0,1,1,100,99);
419 gridBag.setConstraints(mainPanel,constraints);
420 cp.add(mainPanel);
421 buildConstraints(constraints,0,1,1,1,100,1);
422 gridBag.setConstraints(btPanel,constraints);
423 cp.add(btPanel);
424 pack();
425 this.setResizable(false);
426 if (si.equals(GlyphFactory.V_Shape)){
427 vxSpin.setEnabled(true);
428 vxLb.setEnabled(true);
429 vxVal.setEnabled(true);
430 vxValLb.setEnabled(true);
431 }
432 else {
433 vxSpin.setEnabled(false);
434 vxLb.setEnabled(false);
435 vxVal.setEnabled(false);
436 vxValLb.setEnabled(false);
437 if (si.equals(GlyphFactory.V_Ellipse) || si.equals(GlyphFactory.V_Circle)){
438 angleSpin.setValue(new Double(0.0));
439 orientable=false;
440 angleSpin.setEnabled(false);
441 angleChk.setSelected(false);
442 angleChk.setEnabled(false);
443 if (glyphPanel.selectedVertex==-2){glyphPanel.selectedVertex=-1;}
444 }
445 }
446 if (aliasChk.isSelected()){glyphPanel.setAntialiasing(true);}
447 else {glyphPanel.setAntialiasing(false);}
448 if (gridChk.isSelected()){glyphPanel.setGrid(true);}
449 else {glyphPanel.setGrid(false);}
450 if (geomChk.isSelected()){glyphPanel.setGeom(true);}
451 else {glyphPanel.setGeom(false);}
452 }
453
454 GlyphPanel setGlyphPanel(String glClass){
455 if (glClass.equals(V_Shape)){return new VShapePanel(this);}
456 else if (glClass.equals(V_Rectangle)){return new VRectPanel(this);}
457 else if (glClass.equals(V_Circle)){return new VCirPanel(this);}
458 else if (glClass.equals(V_Ellipse)){return new VEllPanel(this);}
459 else if (glClass.equals(V_Triangle)){return new VTrgPanel(this);}
460 else if (glClass.equals(V_Diamond)){return new VDiamPanel(this);}
461 else if (glClass.equals(V_Octagon)){return new VOctPanel(this);}
462 else {return new VShapePanel(this);}
463 }
464
465 void changeFillColor(Color c){
466 fillColor=c;
467 ci1.setColor(fillColor);
468 glyphPanel.setColor(fillColor,borderColor);
469 }
470
471 void changeBorderColor(Color c){
472 borderColor=c;
473 ci2.setColor(borderColor);
474 glyphPanel.setColor(fillColor,borderColor);
475 }
476
477 void changeOrient(double d){
478 angle=d;
479 glyphPanel.setAngle(angle);
480 }
481
482 void changeSize(int s){
483 size=s;
484 }
485
486 void updateAngleSpin(double d){
487 angle=d;
488 angleSpin.setValue(new Double(d));
489 }
490
491 void changeTransp(double d){
492 alpha=d;
493 glyphPanel.setTransparency(alpha);
494 }
495
496 void changeVertices(int i){
497 if (i>vertices.length){
498 double[] tmpA=new double[vertices.length+1];
499 System.arraycopy(vertices,0,tmpA,0,vertices.length);
500 tmpA[tmpA.length-1]=1.0;
501 vertices=tmpA;
502 glyphPanel.setVertices(vertices);
503 }
504 else if (i<vertices.length){
505 double[] tmpA=new double[vertices.length-1];
506 System.arraycopy(vertices,0,tmpA,0,vertices.length-1);
507 vertices=tmpA;
508 glyphPanel.setVertices(vertices);
509 }
510 }
511
512 void setVertexVal(double d){
513 if (d>=0){
514 String s=Double.toString(d);
515 vxVal.setText((s.length()>6) ? s.substring(0,6) : s);
516 }
517 else {vxVal.setText("");}
518 }
519
520 Glyph instantiateGlyph(String si){
521 Glyph g=null;
522 if (si.equals(V_Shape)){
523 if (transpChk.isSelected()){
524 g=new VShapeST(0,0,0,size,doubleToFloatArray(vertices),fillColor,(float)angle);
525 ((Transparent)g).setTransparencyValue((float)alpha);
526 }
527 else {
528 g=new VShape(0,0,0,size,doubleToFloatArray(vertices),fillColor,(float)angle);
529 float[] hsv=new float[3];
530 Color.RGBtoHSB(borderColor.getRed(),borderColor.getGreen(),borderColor.getBlue(),hsv);
531 g.setHSVbColor(hsv[0],hsv[1],hsv[2]);
532 }
533 }
534 else if (si.equals(V_Rectangle)){
535 long w,h;
536 if (aspectRatio >= 1.0){
537 w=size;
538 h=Math.round(size/aspectRatio);
539 }
540 else {
541 h=size;
542 w=Math.round(size*aspectRatio);
543 }
544 if (angleChk.isSelected()){
545 if (transpChk.isSelected()){
546 g=new VRectangleOrST(0,0,0,w,h,fillColor,(float)angle);
547 ((Transparent)g).setTransparencyValue((float)alpha);
548 }
549 else {g=new VRectangleOr(0,0,0,w,h,fillColor,(float)angle);}
550 }
551 else {
552 if (transpChk.isSelected()){
553 g=new VRectangleST(0,0,0,w,h,fillColor);
554 ((Transparent)g).setTransparencyValue((float)alpha);
555 }
556 else {g=new VRectangle(0,0,0,w,h,fillColor);}
557 }
558 }
559 else if (si.equals(V_Ellipse)){
560 long w,h;
561 if (aspectRatio >= 1.0){
562 w=size;
563 h=Math.round(size/aspectRatio);
564 }
565 else {
566 h=size;
567 w=Math.round(size*aspectRatio);
568 }
569 if (transpChk.isSelected()){
570 g=new VEllipseST(0,0,0,w,h,fillColor);
571 ((Transparent)g).setTransparencyValue((float)alpha);
572 }
573 else {g=new VEllipse(0,0,0,w,h,fillColor);}
574 }
575 else if (si.equals(V_Circle)){
576 if (transpChk.isSelected()){
577 g=new VCircleST(0,0,0,size,fillColor);
578 ((Transparent)g).setTransparencyValue((float)alpha);
579 }
580 else {g=new VCircle(0,0,0,size,fillColor);}
581 }
582 else if (si.equals(V_Triangle)){
583 if (angleChk.isSelected()){
584 if (transpChk.isSelected()){
585 g=new VTriangleOrST(0,0,0,size,fillColor,(float)angle);
586 ((Transparent)g).setTransparencyValue((float)alpha);
587 }
588 else {g=new VTriangleOr(0,0,0,size,fillColor,(float)angle);}
589 }
590 else {
591 if (transpChk.isSelected()){
592 g=new VTriangleST(0,0,0,size,fillColor);
593 ((Transparent)g).setTransparencyValue((float)alpha);
594 }
595 else {g=new VTriangle(0,0,0,size,fillColor);}
596 }
597 }
598 else if (si.equals(V_Diamond)){
599 if (angleChk.isSelected()){
600 if (transpChk.isSelected()){
601 g=new VDiamondOrST(0,0,0,size,fillColor,(float)angle);
602 ((Transparent)g).setTransparencyValue((float)alpha);
603 }
604 else {g=new VDiamondOr(0,0,0,size,fillColor,(float)angle);}
605 }
606 else {
607 if (transpChk.isSelected()){
608 g=new VDiamondST(0,0,0,size,fillColor);
609 ((Transparent)g).setTransparencyValue((float)alpha);
610 }
611 else {g=new VDiamond(0,0,0,size,fillColor);}
612 }
613 }
614 else if (si.equals(V_Octagon)){
615 if (angleChk.isSelected()){
616 if (transpChk.isSelected()){
617 g=new VOctagonOrST(0,0,0,size,fillColor,(float)angle);
618 ((Transparent)g).setTransparencyValue((float)alpha);
619 }
620 else {g=new VOctagonOr(0,0,0,size,fillColor,(float)angle);}
621 }
622 else {
623 if (transpChk.isSelected()){
624 g=new VOctagonST(0,0,0,size,fillColor);
625 ((Transparent)g).setTransparencyValue((float)alpha);
626 }
627 else {g=new VOctagon(0,0,0,size,fillColor);}
628 }
629 }
630 //border color
631 float[] hsv=new float[3];
632 Color.RGBtoHSB(borderColor.getRed(),borderColor.getGreen(),borderColor.getBlue(),hsv);
633 g.setHSVbColor(hsv[0],hsv[1],hsv[2]);
634 return g;
635 }
636
637 public void actionPerformed(ActionEvent e){
638 Object source=e.getSource();
639 if (source==transpChk){
640 if (transpChk.isSelected()){transpSpin.setEnabled(editableAlphaValue);}
641 else {
642 transpSpin.setValue(new Double(1.0));
643 transpSpin.setEnabled(false);
644 }
645 }
646 else if (source==angleChk){
647 if (angleChk.isSelected()){
648 orientable=true;
649 angleSpin.setEnabled(editableAngleValue);
650 if (glyphPanel.selectedVertex==-2){glyphPanel.selectedVertex=-1;}
651 glyphPanel.repaint();
652 }
653 else {
654 angleSpin.setValue(new Double(0.0));
655 orientable=false;
656 angleSpin.setEnabled(false);
657 if (glyphPanel.selectedVertex==-2){glyphPanel.selectedVertex=-1;}
658 glyphPanel.repaint();
659 }
660 }
661 else if (source==aliasChk){
662 if (aliasChk.isSelected()){
663 glyphPanel.setAntialiasing(true);
664 }
665 else {
666 glyphPanel.setAntialiasing(false);
667 }
668 }
669 else if (source==gridChk){
670 if (gridChk.isSelected()){
671 glyphPanel.setGrid(true);
672 }
673 else {
674 glyphPanel.setGrid(false);
675 }
676 }
677 else if (source==geomChk){
678 if (geomChk.isSelected()){
679 glyphPanel.setGeom(true);
680 }
681 else {
682 glyphPanel.setGeom(false);
683 }
684 }
685 else if (source==okBt){
686 Glyph g=instantiateGlyph((String)glList.getSelectedItem());
687 gt.setGlyph(g);
688 this.dispose();
689 }
690 else if (source==cancelBt){
691 gt.setGlyph(null);
692 this.dispose();
693 }
694 else if (source==resetBt){
695 angle=defaultAngleValue;
696 angleSpin.setValue(new Double(angle));
697 size=defaultSizeValue;
698 sizeSpin.setValue(new Integer((int)size));
699 alpha=defaultAlphaValue;
700 transpSpin.setValue(new Double(alpha));
701 fillColor=defaultFillColor;
702 ci1.setColor(fillColor);
703 borderColor=defaultBorderColor;
704 ci2.setColor(borderColor);
705 vertices=defaultVertexValues;
706 vxSpin.setValue(new Integer(vertices.length));
707 glyphPanel.setColor(fillColor,borderColor);
708 glyphPanel.setAngle(angle);
709 glyphPanel.setTransparency(alpha);
710 glyphPanel.setVertices(vertices);
711 }
712 else if (source==glList){
713 initUI((String)glList.getSelectedItem(),gridChk.isSelected(),aliasChk.isSelected(),geomChk.isSelected());
714 }
715 }
716
717 public void stateChanged(ChangeEvent e){
718 Object source=e.getSource();
719 if (source==transpSpin){
720 changeTransp(((Double)transpSpin.getValue()).doubleValue());
721 }
722 else if (source==vxSpin){
723 changeVertices(((Integer)vxSpin.getValue()).intValue());
724 }
725 else if (source==angleSpin){
726 changeOrient(((Double)angleSpin.getValue()).doubleValue());
727 }
728 else if (source==sizeSpin){
729 changeSize(((Integer)sizeSpin.getValue()).intValue());
730 }
731 }
732
733 public void mousePressed(MouseEvent e){
734 Object source=e.getSource();
735 if (source==ci1 && editableFillColor){
736 changeFillColor(JColorChooser.showDialog(this,"Choose a New Fill Color",fillColor));
737 }
738 else if (source==ci2 && editableBorderColor){
739 changeBorderColor(JColorChooser.showDialog(this,"Choose a New Border Color",borderColor));
740 }
741 }
742 public void mouseClicked(MouseEvent e){}
743 public void mouseEntered(MouseEvent e){}
744 public void mouseExited(MouseEvent e){}
745 public void mouseReleased(MouseEvent e){}
746
747 static void buildConstraints(GridBagConstraints gbc, int gx,int gy,int gw,int gh,int wx,int wy){
748 gbc.gridx=gx;
749 gbc.gridy=gy;
750 gbc.gridwidth=gw;
751 gbc.gridheight=gh;
752 gbc.weightx=wx;
753 gbc.weighty=wy;
754 }
755
756 static class Closer extends WindowAdapter {
757 public void windowClosing(WindowEvent e) {
758 Window w = e.getWindow();
759 w.hide();
760 }
761 }
762
763 static class DisposeOnClose extends ComponentAdapter {
764 public void componentHidden(ComponentEvent e) {
765 Window w = (Window)e.getComponent();
766 w.dispose();
767 }
768 }
769 }
770
771 class GlyphTracker {
772
773 Glyph g;
774
775 public void setGlyph(Glyph gl){
776 g=gl;
777 }
778
779 public Glyph getGlyph() {
780 return g;
781 }
782 }
783
784 class ColorIndicator extends JPanel {
785
786 Color color;
787 String label;
788 JPanel p;
789
790 ColorIndicator(String l,Color c){
791 super();
792 color=c;
793 label=l;
794 setBorder(BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.black),label));
795 p=new JPanel();
796 p.setBackground(color);
797 add(p);
798 }
799
800 void setColor(Color c){
801 color=c;
802 p.setBackground(color);
803 repaint();
804 }
805
806 Color getColor(){
807 return color;
808 }
809
810 }
811
812 class GlyphPanel extends JPanel {
813
814 GlyphFactory gf;
815
816 int pw,ph; //panel width and height
817 int cx,cy,cs; //glyph X Y and size in panel
818 double vertexAngle;
819 double[] vertices;
820 int[] xcoords;
821 int[] ycoords;
822
823 Color fColor,bColor;
824 double alpha=1.0;
825
826 int selectedVertex=-1; //-1 if none, [0..n] if vertex, -2 if orientation handle (always -1 or -2 for all glyphs except VShape and subclasses)
827 int hdx,hdy; //temporary variable used for vertex selection
828
829 int xorientHandle,yorientHandle;
830
831 Object alias=RenderingHints.VALUE_ANTIALIAS_OFF;
832 boolean displayGrid=false;
833 boolean displayIndicators=true;
834
835 Stroke continuous;
836 static float dash1[]={5.0f};
837 static Stroke dashed=new BasicStroke(1.0f,BasicStroke.CAP_BUTT,BasicStroke.JOIN_MITER,10.0f,dash1,0.0f);
838 static AlphaComposite acO=AlphaComposite.getInstance(AlphaComposite.SRC_OVER); //opaque
839 AlphaComposite acST=AlphaComposite.getInstance(AlphaComposite.SRC_OVER,(float)alpha);
840 static Color gridGray=new Color(190,190,190);
841 Graphics2D g2d;
842
843 GlyphPanel(GlyphFactory gfact){
844 super(true);
845 gf=gfact;
846 fColor=gf.fillColor;
847 bColor=gf.borderColor;
848 alpha=gf.alpha;
849 acST=AlphaComposite.getInstance(AlphaComposite.SRC_OVER,(float)alpha);
850 }
851
852 void setColor(Color c1,Color c2){
853 fColor=c1;
854 bColor=c2;
855 repaint();
856 }
857
858 void setAngle(double a){
859 vertexAngle=a;
860 repaint();
861 }
862
863 void setTransparency(double t){
864 alpha=t;
865 acST=AlphaComposite.getInstance(AlphaComposite.SRC_OVER,(float)alpha);
866 repaint();
867 }
868
869 void setVertices(double[] array){
870 vertices=new double[array.length];
871 xcoords=new int[vertices.length];
872 ycoords=new int[vertices.length];
873 System.arraycopy(array,0,vertices,0,array.length);
874 repaint();
875 }
876
877 void setAntialiasing(boolean b){
878 if (b){
879 alias=RenderingHints.VALUE_ANTIALIAS_ON;
880 }
881 else {
882 alias=RenderingHints.VALUE_ANTIALIAS_OFF;
883 }
884 repaint();
885 }
886
887 void setGrid(boolean b){
888 displayGrid=b;
889 repaint();
890 }
891
892 void setGeom(boolean b){
893 displayIndicators=b;
894 repaint();
895 }
896
897 public void paint(Graphics g) {
898 pw=this.getSize().width;
899 ph=this.getSize().height;
900 g2d=(Graphics2D)g;
901 g2d.clearRect(0,0,pw,ph);
902 g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,alias);
903 continuous=g2d.getStroke();
904 vertexAngle=gf.angle;
905 cs=Math.round(Math.min(pw,ph)/2-20);
906 cx=pw/2;
907 cy=ph/2;
908 if (displayGrid){
909 g2d.setColor(gridGray);
910 for (int i=0;i<pw;i+=30){
911 g2d.drawLine(0,i,pw,i);
912 g2d.drawLine(i,0,i,ph);
913 }
914 }
915 if (gf.orientable && displayIndicators){
916 g2d.setColor(Color.black);
917 xorientHandle=(int)Math.round(-Math.sin(gf.angle)*cs*1.1)+cx;
918 yorientHandle=-(int)Math.round(Math.cos(gf.angle)*cs*1.1)+cy;
919 g2d.drawLine(cx,cy,xorientHandle,yorientHandle);
920 if (selectedVertex==-2){g2d.setColor(Color.red);}
921 g2d.fillOval(xorientHandle-4,yorientHandle-4,8,8);
922 }
923 }
924
925 void orientDrag(MouseEvent e){
926 if (selectedVertex==-2){
927 hdx=e.getX()-cx;
928 hdy=e.getY()-cy;
929 if (hdy!=0){
930 if (hdy<0){
931 if (hdx<0){gf.updateAngleSpin(Math.atan(((double)hdx)/((double)hdy)));}
932 else {gf.updateAngleSpin(2*Math.PI+Math.atan(((double)hdx)/((double)hdy)));}
933 }
934 else {
935 if (hdx<0){gf.updateAngleSpin(Math.PI+Math.atan(((double)hdx)/((double)hdy)));}
936 else {gf.updateAngleSpin(Math.PI+Math.atan(((double)hdx)/((double)hdy)));}
937 }
938 }
939 else {
940 if (hdx>0){gf.updateAngleSpin(3*Math.PI/((double)2.0));}
941 else {gf.updateAngleSpin(Math.PI/((double)2.0));}
942 }
943 //do not repaint as a repaint will be triggered as a consequence of updateAngleSpin
944 //when doing JSpinner.setValue() which fires a ChangeEvent
945 }
946 }
947
948 }
949
950
951 class VShapePanel extends GlyphPanel implements MouseMotionListener,MouseListener {
952
953 Polygon p;
954
955 int x2,y2; //temporary variables used for vertex computation
956 double tmpD; //temporary variable used for vertex selection
957
958 VShapePanel(GlyphFactory gfact){
959 super(gfact);
960 vertices=gf.vertices;
961 xcoords=new int[vertices.length];
962 ycoords=new int[vertices.length];
963 }
964
965 public void paint(Graphics g) {
966 super.paint(g);
967 for (int j=0;j<vertices.length-1;j++){
968 xcoords[j]=(int)Math.round(cx+cs*Math.cos(vertexAngle)*vertices[j]);
969 ycoords[j]=(int)Math.round(cy-cs*Math.sin(vertexAngle)*vertices[j]);
970 vertexAngle+=2*Math.PI/vertices.length;
971 }//last iteration outside to loop to avoid one vertxAngle computation too many
972 xcoords[vertices.length-1]=(int)Math.round(cx+cs*Math.cos(vertexAngle)*vertices[vertices.length-1]);
973 ycoords[vertices.length-1]=(int)Math.round(cy-cs*Math.sin(vertexAngle)*vertices[vertices.length-1]);
974 p=new Polygon(xcoords,ycoords,xcoords.length);
975 if (alpha>0.0){
976 if (alpha==1.0){
977 g2d.setColor(fColor);
978 g2d.fillPolygon(p);
979 }
980 else {
981 g2d.setColor(fColor);
982 g2d.setComposite(acST);
983 g2d.fillPolygon(p);
984 g2d.setComposite(acO);
985 }
986 }
987 g2d.setColor(bColor);
988 g2d.drawPolygon(p);
989 g2d.setColor(Color.black);
990 //bounding circle and vertex segments
991 if (displayIndicators){
992 g2d.setStroke(dashed);
993 g2d.drawOval(cx-cs,cy-cs,2*cs,2*cs);
994 vertexAngle=gf.angle;
995 for (int i=0;i<xcoords.length;i++){
996 x2=(int)Math.round(cx+cs*Math.cos(vertexAngle));
997 y2=(int)Math.round(cy-cs*Math.sin(vertexAngle));
998 g2d.drawLine(cx,cy,x2,y2);
999 if (i==selectedVertex){
1000 g2d.setColor(Color.red);
1001 g2d.fillRect(xcoords[i]-3,ycoords[i]-3,6,6);
1002 g2d.setColor(Color.black);
1003 }
1004 else {
1005 g2d.fillRect(xcoords[i]-3,ycoords[i]-3,6,6);
1006 }
1007 vertexAngle+=2*Math.PI/vertices.length;
1008 }
1009 }
1010 }
1011
1012 public void mouseMoved(MouseEvent e){}
1013 public void mouseDragged(MouseEvent e){
1014 if (selectedVertex>=0){
1015 tmpD=Math.sqrt(Math.pow(e.getX()-cx,2)+Math.pow(e.getY()-cy,2))/((double)cs);
1016 if (tmpD<0){tmpD=0.0;}
1017 else if (tmpD>1.0){tmpD=1.0;}
1018 vertices[selectedVertex]=tmpD;
1019 gf.setVertexVal(tmpD);
1020 repaint();
1021 }
1022 else {orientDrag(e);}
1023 }
1024 public void mousePressed(MouseEvent e){
1025 int mx=e.getX();
1026 int my=e.getY();
1027 boolean selectedSomething=false;
1028 if (GlyphFactory.hasEditableVertexValues()){
1029 for (int i=0;i<xcoords.length;i++){
1030 if ((xcoords[i]-3 <= mx ) && (mx <= xcoords[i]+3) && (ycoords[i]-3 <= my) && (my <= ycoords[i]+3)){
1031 selectedVertex=i;
1032 selectedSomething=true;
1033 break;
1034 }
1035 }
1036 }
1037 if (!selectedSomething){
1038 if ((gf.orientable) && (GlyphFactory.hasEditableAngle()) && (xorientHandle-3 <= mx ) && (mx <= xorientHandle+3) && (yorientHandle-3 <= my) && (my <= yorientHandle+3)){
1039 selectedVertex=-2;
1040 }
1041 else {
1042 selectedVertex=-1;
1043 }
1044 }
1045 repaint();
1046 }
1047
1048 public void mouseClicked(MouseEvent e){
1049 int mx=e.getX();
1050 int my=e.getY();
1051 boolean selectedSomething=false;
1052 if (GlyphFactory.hasEditableVertexValues()){
1053 for (int i=0;i<xcoords.length;i++){
1054 if ((xcoords[i]-3 <= mx ) && (mx <= xcoords[i]+3) && (ycoords[i]-3 <= my) && (my <= ycoords[i]+3)){
1055 selectedSomething=true;
1056 selectedVertex=i;
1057 gf.setVertexVal(vertices[i]);
1058 break;
1059 }
1060 }
1061 }
1062 if (!selectedSomething){
1063 selectedVertex=-1;
1064 gf.setVertexVal(-1.0);
1065 }
1066 repaint();
1067 }
1068 public void mouseEntered(MouseEvent e){
1069 setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR));
1070 }
1071 public void mouseExited(MouseEvent e){
1072 }
1073 public void mouseReleased(MouseEvent e){
1074 gf.vertices=this.vertices;
1075 //selectedVertex=-1;
1076 }
1077
1078 }
1079
1080 class VRectPanel extends GlyphPanel implements MouseMotionListener,MouseListener {
1081
1082 int cw,ch;
1083 int arhx=-1;
1084 int arhy=-1;
1085 int hdx2,hdy2;
1086 double ratioAngle;
1087
1088 VRectPanel(GlyphFactory gfact){
1089 super(gfact);
1090 }
1091
1092 public void paint(Graphics g) {
1093 super.paint(g);
1094 if (arhx==-1 && arhy==-1){
1095 hdx2=Math.round(cx*0.707f);
1096 hdy2=Math.round(cy*0.707f);
1097 hdx=Math.abs(hdx2);
1098 hdy=Math.abs(hdy2);
1099 updateRatioHandle();
1100 }
1101 if (hdx==0 && hdy==0){gf.aspectRatio=1.0;}
1102 else {gf.aspectRatio=Math.abs((double)hdx/(double)hdy);}
1103 if (gf.aspectRatio==1.0){
1104 cw=cs;
1105 ch=cs;
1106 }
1107 else if (gf.aspectRatio>1.0){
1108 cw=cs;
1109 ch=(int)Math.round(cs/gf.aspectRatio);
1110 }
1111 else {
1112 cw=(int)Math.round(cs*gf.aspectRatio);
1113 ch=cs;
1114 }
1115 if (alpha>0.0){
1116 if (alpha==1.0){
1117 g2d.setColor(fColor);
1118 g2d.fillRect(cx-cw,cy-ch,2*cw,2*ch);
1119 }
1120 else {
1121 g2d.setColor(fColor);
1122 g2d.setComposite(acST);
1123 g2d.fillRect(cx-cw,cy-ch,2*cw,2*ch);
1124 g2d.setComposite(acO);
1125 }
1126 }
1127 g2d.setColor(bColor);
1128 g2d.drawRect(cx-cw,cy-ch,2*cw,2*ch);
1129 if (displayIndicators){
1130 if (selectedVertex==0){
1131 g2d.setColor(Color.red);
1132 g2d.fillRect(arhx-3,arhy-3,6,6);
1133 g2d.setColor(Color.black);
1134 }
1135 else {
1136 g2d.setColor(Color.black);
1137 g2d.fillRect(arhx-3,arhy-3,6,6);
1138 }
1139 g2d.setStroke(dashed);
1140 g2d.drawOval(0,0,pw-1,ph-1);
1141 g2d.drawLine(cx,cy,arhx,arhy);
1142 }
1143 }
1144
1145 void updateRatioHandle(){
1146 if (hdy2!=0){
1147 if (hdy2<0){
1148 if (hdx2<0){ratioAngle=Math.atan(((double)hdx2)/((double)hdy2));}
1149 else {ratioAngle=2*Math.PI+Math.atan(((double)hdx2)/((double)hdy2));}
1150 }
1151 else {
1152 if (hdx2<0){ratioAngle=Math.PI+Math.atan(((double)hdx2)/((double)hdy2));}
1153 else {ratioAngle=Math.PI+Math.atan(((double)hdx2)/((double)hdy2));}
1154 }
1155 }
1156 else {
1157 if (hdx2>0){ratioAngle=3*Math.PI/((double)2.0);}
1158 else {ratioAngle=Math.PI/((double)2.0);}
1159 }
1160 arhx=cx-(int)Math.round(Math.sin(ratioAngle)*cx);
1161 arhy=cy-(int)Math.round(Math.cos(ratioAngle)*cy);
1162 }
1163
1164 public void mouseMoved(MouseEvent e){}
1165 public void mouseDragged(MouseEvent e){
1166 if (selectedVertex==0){
1167 int mx=e.getX();
1168 int my=e.getY();
1169 hdx2=mx-cx;
1170 hdy2=my-cy;
1171 hdx=Math.abs(hdx2);
1172 hdy=Math.abs(hdy2);
1173 updateRatioHandle();
1174 repaint();
1175 }
1176 else if (selectedVertex==-2){
1177 orientDrag(e);
1178 }
1179 }
1180
1181 public void mousePressed(MouseEvent e){
1182 int mx=e.getX();
1183 int my=e.getY();
1184 boolean selectedSomething=false;
1185 if (GlyphFactory.hasEditableVertexValues()){
1186 if ((arhx-3 <= mx ) && (mx <= arhx+3) && (arhy-3 <= my) && (my <= arhy+3)){
1187 selectedVertex=0; //east
1188 selectedSomething=true;
1189 }
1190 }
1191 if (!selectedSomething){
1192 if ((gf.orientable) && (GlyphFactory.hasEditableAngle()) && (xorientHandle-3 <= mx ) && (mx <= xorientHandle+3) && (yorientHandle-3 <= my) && (my <= yorientHandle+3)){
1193 selectedVertex=-2;
1194 }
1195 else {selectedVertex=-1;}
1196 }
1197 repaint();
1198 }
1199
1200 public void mouseClicked(MouseEvent e){}
1201 public void mouseEntered(MouseEvent e){
1202 setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR));
1203 }
1204 public void mouseExited(MouseEvent e){}
1205 public void mouseReleased(MouseEvent e){}
1206
1207 }
1208
1209 class VCirPanel extends GlyphPanel implements MouseMotionListener,MouseListener {
1210
1211 VCirPanel(GlyphFactory gfact){
1212 super(gfact);
1213 }
1214
1215 public void paint(Graphics g) {
1216 super.paint(g);
1217 if (alpha>0.0){
1218 if (alpha==1.0){
1219 g2d.setColor(fColor);
1220 g2d.fillOval(cx-cs,cy-cs,2*cs,2*cs);
1221 }
1222 else {
1223 g2d.setColor(fColor);
1224 g2d.setComposite(acST);
1225 g2d.fillOval(cx-cs,cy-cs,2*cs,2*cs);
1226 g2d.setComposite(acO);
1227 }
1228 }
1229 g2d.setColor(bColor);
1230 g2d.drawOval(cx-cs,cy-cs,2*cs,2*cs);
1231 }
1232
1233 public void mouseMoved(MouseEvent e){}
1234 public void mouseDragged(MouseEvent e){}
1235 public void mousePressed(MouseEvent e){}
1236
1237 public void mouseClicked(MouseEvent e){}
1238 public void mouseEntered(MouseEvent e){
1239 setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR));
1240 }
1241 public void mouseExited(MouseEvent e){}
1242 public void mouseReleased(MouseEvent e){}
1243
1244 }
1245
1246 class VEllPanel extends GlyphPanel implements MouseMotionListener,MouseListener {
1247
1248 int cw,ch;
1249 int arhx=-1;
1250 int arhy=-1;
1251 int hdx2,hdy2;
1252 double ratioAngle;
1253
1254 VEllPanel(GlyphFactory gfact){
1255 super(gfact);
1256 }
1257
1258 public void paint(Graphics g) {
1259 super.paint(g);
1260 if (arhx==-1 && arhy==-1){
1261 hdx2=Math.round(cx*0.707f);
1262 hdy2=Math.round(cy*0.707f);
1263 hdx=Math.abs(hdx2);
1264 hdy=Math.abs(hdy2);
1265 updateRatioHandle();
1266 }
1267 if (hdx==0 && hdy==0){gf.aspectRatio=1.0;}
1268 else {gf.aspectRatio=Math.abs((double)hdx/(double)hdy);}
1269 if (gf.aspectRatio==1.0){
1270 cw=cs;
1271 ch=cs;
1272 }
1273 else if (gf.aspectRatio>1.0){
1274 cw=cs;
1275 ch=(int)Math.round(cs/gf.aspectRatio);
1276 }
1277 else {
1278 cw=(int)Math.round(cs*gf.aspectRatio);
1279 ch=cs;
1280 }
1281 if (alpha>0.0){
1282 if (alpha==1.0){
1283 g2d.setColor(fColor);
1284 g2d.fillOval(cx-cw,cy-ch,2*cw,2*ch);
1285 }
1286 else {
1287 g2d.setColor(fColor);
1288 g2d.setComposite(acST);
1289 g2d.fillOval(cx-cw,cy-ch,2*cw,2*ch);
1290 g2d.setComposite(acO);
1291 }
1292 }
1293 g2d.setColor(bColor);
1294 g2d.drawOval(cx-cw,cy-ch,2*cw,2*ch);
1295 if (displayIndicators){
1296 if (selectedVertex==0){
1297 g2d.setColor(Color.red);
1298 g2d.fillRect(arhx-3,arhy-3,6,6);
1299 g2d.setColor(Color.black);
1300 }
1301 else {
1302 g2d.setColor(Color.black);
1303 g2d.fillRect(arhx-3,arhy-3,6,6);
1304 }
1305 g2d.setStroke(dashed);
1306 g2d.drawOval(0,0,pw-1,ph-1);
1307 g2d.drawLine(cx,cy,arhx,arhy);
1308 }
1309 }
1310
1311 void updateRatioHandle(){
1312 if (hdy2!=0){
1313 if (hdy2<0){
1314 if (hdx2<0){ratioAngle=Math.atan(((double)hdx2)/((double)hdy2));}
1315 else {ratioAngle=2*Math.PI+Math.atan(((double)hdx2)/((double)hdy2));}
1316 }
1317 else {
1318 if (hdx2<0){ratioAngle=Math.PI+Math.atan(((double)hdx2)/((double)hdy2));}
1319 else {ratioAngle=Math.PI+Math.atan(((double)hdx2)/((double)hdy2));}
1320 }
1321 }
1322 else {
1323 if (hdx2>0){ratioAngle=3*Math.PI/((double)2.0);}
1324 else {ratioAngle=Math.PI/((double)2.0);}
1325 }
1326 arhx=cx-(int)Math.round(Math.sin(ratioAngle)*cx);
1327 arhy=cy-(int)Math.round(Math.cos(ratioAngle)*cy);
1328 }
1329
1330 public void mouseMoved(MouseEvent e){}
1331 public void mouseDragged(MouseEvent e){
1332 if (selectedVertex==0){
1333 int mx=e.getX();
1334 int my=e.getY();
1335 hdx2=mx-cx;
1336 hdy2=my-cy;
1337 hdx=Math.abs(hdx2);
1338 hdy=Math.abs(hdy2);
1339 updateRatioHandle();
1340 repaint();
1341 }
1342 }
1343
1344 public void mousePressed(MouseEvent e){
1345 int mx=e.getX();
1346 int my=e.getY();
1347 boolean selectedSomething=false;
1348 if (GlyphFactory.hasEditableVertexValues()){
1349 if ((arhx-3 <= mx ) && (mx <= arhx+3) && (arhy-3 <= my) && (my <= arhy+3)){
1350 selectedVertex=0; //east
1351 selectedSomething=true;
1352 }
1353 }
1354 if (!selectedSomething){
1355 selectedVertex=-1;
1356 }
1357 repaint();
1358 }
1359
1360 public void mouseClicked(MouseEvent e){}
1361 public void mouseEntered(MouseEvent e){
1362 setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR));
1363 }
1364 public void mouseExited(MouseEvent e){}
1365 public void mouseReleased(MouseEvent e){}
1366
1367 }
1368
1369 class VTrgPanel extends GlyphPanel implements MouseMotionListener,MouseListener {
1370
1371 Polygon p;
1372 int halfEdge,thirdHeight; //temporary variables used for vertex computation
1373
1374 // double tmpD; //temporary variable used for vertex selection
1375
1376 VTrgPanel(GlyphFactory gfact){
1377 super(gfact);
1378 xcoords=new int[3];
1379 ycoords=new int[3];
1380 }
1381
1382 public void paint(Graphics g) {
1383 super.paint(g);
1384 halfEdge=Math.round(0.866f*cs);
1385 thirdHeight=Math.round(0.5f*cs);
1386 xcoords[0]=(int)Math.round(cx-cs*Math.sin(vertexAngle));
1387 xcoords[1]=(int)Math.round(cx-halfEdge*Math.cos(vertexAngle)+thirdHeight*Math.sin(vertexAngle));
1388 xcoords[2]=(int)Math.round(cx+halfEdge*Math.cos(vertexAngle)+thirdHeight*Math.sin(vertexAngle));
1389 ycoords[0]=(int)Math.round(cy-cs*Math.cos(vertexAngle));
1390 ycoords[1]=(int)Math.round(cy+thirdHeight*Math.cos(vertexAngle)+halfEdge*Math.sin(vertexAngle));
1391 ycoords[2]=(int)Math.round(cy+thirdHeight*Math.cos(vertexAngle)-halfEdge*Math.sin(vertexAngle));
1392 p=new Polygon(xcoords,ycoords,3);
1393 if (alpha>0.0){
1394 if (alpha==1.0){
1395 g2d.setColor(fColor);
1396 g2d.fillPolygon(p);
1397 }
1398 else {
1399 g2d.setColor(fColor);
1400 g2d.setComposite(acST);
1401 g2d.fillPolygon(p);
1402 g2d.setComposite(acO);
1403 }
1404 }
1405 g2d.setColor(bColor);
1406 g2d.drawPolygon(p);
1407 g2d.setColor(Color.black);
1408 //bounding circle and vertex segments
1409 if (displayIndicators){
1410 g2d.setStroke(dashed);
1411 g2d.drawOval(cx-cs,cy-cs,2*cs,2*cs);
1412 }
1413 }
1414
1415 public void mouseMoved(MouseEvent e){}
1416 public void mouseDragged(MouseEvent e){
1417 orientDrag(e);
1418 }
1419 public void mousePressed(MouseEvent e){
1420 int mx=e.getX();
1421 int my=e.getY();
1422 if ((gf.orientable) && (GlyphFactory.hasEditableAngle()) && (xorientHandle-3 <= mx ) && (mx <= xorientHandle+3) && (yorientHandle-3 <= my) && (my <= yorientHandle+3)){
1423 selectedVertex=-2;
1424 }
1425 else {
1426 selectedVertex=-1;
1427 }
1428 repaint();
1429 }
1430
1431 public void mouseClicked(MouseEvent e){
1432 selectedVertex=-1;
1433 gf.setVertexVal(-1.0);
1434 repaint();
1435 }
1436 public void mouseEntered(MouseEvent e){
1437 setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR));
1438 }
1439 public void mouseExited(MouseEvent e){
1440 }
1441 public void mouseReleased(MouseEvent e){
1442 }
1443
1444 }
1445
1446 class VDiamPanel extends GlyphPanel implements MouseMotionListener,MouseListener {
1447
1448 VDiamPanel(GlyphFactory gfact){
1449 super(gfact);
1450 xcoords=new int[4];
1451 ycoords=new int[4];
1452 }
1453
1454 Polygon p;
1455
1456 public void paint(Graphics g) {
1457 super.paint(g);
1458 xcoords[0]=(int)Math.round(cx+cs*Math.cos(vertexAngle));
1459 xcoords[1]=(int)Math.round(cx-cs*Math.sin(vertexAngle));
1460 xcoords[2]=(int)Math.round(cx-cs*Math.cos(vertexAngle));
1461 xcoords[3]=(int)Math.round(cx+cs*Math.sin(vertexAngle));
1462 ycoords[0]=(int)Math.round(cy-cs*Math.sin(vertexAngle));
1463 ycoords[1]=(int)Math.round(cy-cs*Math.cos(vertexAngle));
1464 ycoords[2]=(int)Math.round(cy+cs*Math.sin(vertexAngle));
1465 ycoords[3]=(int)Math.round(cy+cs*Math.cos(vertexAngle));
1466 p=new Polygon(xcoords,ycoords,4);
1467 if (alpha>0.0){
1468 if (alpha==1.0){
1469 g2d.setColor(fColor);
1470 g2d.fillPolygon(p);
1471 }
1472 else {
1473 g2d.setColor(fColor);
1474 g2d.setComposite(acST);
1475 g2d.fillPolygon(p);
1476 g2d.setComposite(acO);
1477 }
1478 }
1479 g2d.setColor(bColor);
1480 g2d.drawPolygon(p);
1481 g2d.setColor(Color.black);
1482 //bounding circle and vertex segments
1483 if (displayIndicators){
1484 g2d.setStroke(dashed);
1485 g2d.drawOval(cx-cs,cy-cs,2*cs,2*cs);
1486 }
1487 }
1488
1489 public void mouseMoved(MouseEvent e){}
1490 public void mouseDragged(MouseEvent e){
1491 orientDrag(e);
1492 }
1493 public void mousePressed(MouseEvent e){
1494 int mx=e.getX();
1495 int my=e.getY();
1496 if ((gf.orientable) && (GlyphFactory.hasEditableAngle()) && (xorientHandle-3 <= mx ) && (mx <= xorientHandle+3) && (yorientHandle-3 <= my) && (my <= yorientHandle+3)){
1497 selectedVertex=-2;
1498 }
1499 else {
1500 selectedVertex=-1;
1501 }
1502 repaint();
1503 }
1504
1505 public void mouseClicked(MouseEvent e){
1506 selectedVertex=-1;
1507 gf.setVertexVal(-1.0);
1508 repaint();
1509 }
1510 public void mouseEntered(MouseEvent e){
1511 setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR));
1512 }
1513 public void mouseExited(MouseEvent e){
1514 }
1515 public void mouseReleased(MouseEvent e){
1516 }
1517
1518 }
1519
1520 class VOctPanel extends GlyphPanel implements MouseMotionListener,MouseListener {
1521
1522 VOctPanel(GlyphFactory gfact){
1523 super(gfact);
1524 xcoords=new int[8];
1525 ycoords=new int[8];
1526 }
1527
1528 Polygon p;
1529 int hs;
1530
1531 public void paint(Graphics g) {
1532 super.paint(g);
1533 hs=cs/2;
1534 xcoords[0]=(int)Math.round((cs*Math.cos(vertexAngle)-hs*Math.sin(vertexAngle))+cx);
1535 xcoords[1]=(int)Math.round((hs*Math.cos(vertexAngle)-cs*Math.sin(vertexAngle))+cx);
1536 xcoords[2]=(int)Math.round((-hs*Math.cos(vertexAngle)-cs*Math.sin(vertexAngle))+cx);
1537 xcoords[3]=(int)Math.round((-cs*Math.cos(vertexAngle)-hs*Math.sin(vertexAngle))+cx);
1538 xcoords[4]=(int)Math.round((-cs*Math.cos(vertexAngle)+hs*Math.sin(vertexAngle))+cx);
1539 xcoords[5]=(int)Math.round((-hs*Math.cos(vertexAngle)+cs*Math.sin(vertexAngle))+cx);
1540 xcoords[6]=(int)Math.round((hs*Math.cos(vertexAngle)+cs*Math.sin(vertexAngle))+cx);
1541 xcoords[7]=(int)Math.round((cs*Math.cos(vertexAngle)+hs*Math.sin(vertexAngle))+cx);
1542 ycoords[0]=(int)Math.round((-hs*Math.cos(vertexAngle)-cs*Math.sin(vertexAngle))+cy);
1543 ycoords[1]=(int)Math.round((-cs*Math.cos(vertexAngle)-hs*Math.sin(vertexAngle))+cy);
1544 ycoords[2]=(int)Math.round((-cs*Math.cos(vertexAngle)+hs*Math.sin(vertexAngle))+cy);
1545 ycoords[3]=(int)Math.round((-hs*Math.cos(vertexAngle)+cs*Math.sin(vertexAngle))+cy);
1546 ycoords[4]=(int)Math.round((hs*Math.cos(vertexAngle)+cs*Math.sin(vertexAngle))+cy);
1547 ycoords[5]=(int)Math.round((cs*Math.cos(vertexAngle)+hs*Math.sin(vertexAngle))+cy);
1548 ycoords[6]=(int)Math.round((cs*Math.cos(vertexAngle)-hs*Math.sin(vertexAngle))+cy);
1549 ycoords[7]=(int)Math.round((hs*Math.cos(vertexAngle)-cs*Math.sin(vertexAngle))+cy);
1550 p=new Polygon(xcoords,ycoords,8);
1551 if (alpha>0.0){
1552 if (alpha==1.0){
1553 g2d.setColor(fColor);
1554 g2d.fillPolygon(p);
1555 }
1556 else {
1557 g2d.setColor(fColor);
1558 g2d.setComposite(acST);
1559 g2d.fillPolygon(p);
1560 g2d.setComposite(acO);
1561 }
1562 }
1563 g2d.setColor(bColor);
1564 g2d.drawPolygon(p);
1565 g2d.setColor(Color.black);
1566 //bounding circle and vertex segments
1567 if (displayIndicators){
1568 g2d.setStroke(dashed);
1569 g2d.drawOval(cx-cs,cy-cs,2*cs,2*cs);
1570 }
1571 }
1572
1573 public void mouseMoved(MouseEvent e){}
1574 public void mouseDragged(MouseEvent e){
1575 orientDrag(e);
1576 }
1577 public void mousePressed(MouseEvent e){
1578 int mx=e.getX();
1579 int my=e.getY();
1580 if ((gf.orientable) && (GlyphFactory.hasEditableAngle()) && (xorientHandle-3 <= mx ) && (mx <= xorientHandle+3) && (yorientHandle-3 <= my) && (my <= yorientHandle+3)){
1581 selectedVertex=-2;
1582 }
1583 else {
1584 selectedVertex=-1;
1585 }
1586 repaint();
1587 }
1588
1589 public void mouseClicked(MouseEvent e){
1590 selectedVertex=-1;
1591 gf.setVertexVal(-1.0);
1592 repaint();
1593 }
1594 public void mouseEntered(MouseEvent e){
1595 setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR));
1596 }
1597 public void mouseExited(MouseEvent e){
1598 }
1599 public void mouseReleased(MouseEvent e){
1600 }
1601
1602 }