1 | /* |
---|
2 | * $Id: VectorKey.java,v 1.14 2003/08/22 23:02:32 dwd Exp $ |
---|
3 | * |
---|
4 | * This software is provided by NOAA for full, free and open release. It is |
---|
5 | * understood by the recipient/user that NOAA assumes no liability for any |
---|
6 | * errors contained in the code. Although this software is released without |
---|
7 | * conditions or restrictions in its use, it is expected that appropriate |
---|
8 | * credit be given to its author and to the National Oceanic and Atmospheric |
---|
9 | * Administration should the software be included by the recipient as an |
---|
10 | * element in other product development. |
---|
11 | */ |
---|
12 | |
---|
13 | package gov.noaa.pmel.sgt; |
---|
14 | |
---|
15 | import gov.noaa.pmel.util.Point2D; |
---|
16 | import gov.noaa.pmel.util.Rectangle2D; |
---|
17 | import gov.noaa.pmel.util.Debug; |
---|
18 | |
---|
19 | import java.util.Vector; |
---|
20 | import java.util.Enumeration; |
---|
21 | import java.awt.Graphics; |
---|
22 | import java.awt.Graphics2D; |
---|
23 | import java.awt.Stroke; |
---|
24 | import java.awt.BasicStroke; |
---|
25 | import java.awt.geom.GeneralPath; |
---|
26 | import java.awt.Rectangle; |
---|
27 | import java.awt.Point; |
---|
28 | import java.text.DecimalFormat; |
---|
29 | |
---|
30 | import java.beans.PropertyChangeListener; |
---|
31 | import java.beans.PropertyChangeEvent; |
---|
32 | import java.beans.PropertyChangeSupport; |
---|
33 | |
---|
34 | /** |
---|
35 | * <code>VectorKey</code> is used to create a key for the |
---|
36 | * <code>VectorCartesianRenderer</code>. Multiple |
---|
37 | * lines can be included in the key. |
---|
38 | * |
---|
39 | * @author Donald Denbo |
---|
40 | * @version $Revision: 1.14 $, $Date: 2003/08/22 23:02:32 $ |
---|
41 | * @since 2.1 |
---|
42 | **/ |
---|
43 | public class VectorKey implements Cloneable, |
---|
44 | DataKey, Moveable, PropertyChangeListener { |
---|
45 | private String ident_; |
---|
46 | /** @directed */ |
---|
47 | private Layer layer_; |
---|
48 | /** @link aggregation |
---|
49 | * @supplierCardinality * |
---|
50 | * @label vectors*/ |
---|
51 | /*#VectorCartesianRenderer lnkVectorCartesianRenderer; */ |
---|
52 | private Vector vectors_; |
---|
53 | /** |
---|
54 | *@link aggregation |
---|
55 | * @associates <{SGLabel}> |
---|
56 | * @label label |
---|
57 | * @supplierCardinality * |
---|
58 | * @undirected |
---|
59 | */ |
---|
60 | /* private Vector lnkSGLabel; */ |
---|
61 | private Vector label_; |
---|
62 | private Vector scaleLabel_; |
---|
63 | private int columns_; |
---|
64 | private int style_; |
---|
65 | private int valign_; |
---|
66 | private int halign_; |
---|
67 | private Point2D.Double porigin_; |
---|
68 | private double vectorLengthP_; |
---|
69 | private int maxLabelLength_; |
---|
70 | private int maxLabelHeight_; |
---|
71 | private int maxScaleLength_; |
---|
72 | private String floatScaleFormat_ = "###.##"; |
---|
73 | private String expScaleFormat_ = "0.####E0"; |
---|
74 | private DecimalFormat floatFormat_; |
---|
75 | private DecimalFormat expFormat_; |
---|
76 | private float xoff_; |
---|
77 | private float yoff_; |
---|
78 | private float slope_; |
---|
79 | private boolean selected_; |
---|
80 | private boolean selectable_; |
---|
81 | private boolean visible_; |
---|
82 | private boolean moveable_; |
---|
83 | private PropertyChangeSupport changes_ = new PropertyChangeSupport(this); |
---|
84 | private static final int VERTICAL_BORDER_ = 3; |
---|
85 | private static final int HORIZONTAL_BORDER_ = 15; |
---|
86 | private static final int COLUMN_SPACE_ = 10; |
---|
87 | private static final int ROW_SPACE_ = 3; |
---|
88 | private static final int LABEL_SPACE_ = 10; |
---|
89 | private static final int SCALE_SPACE_ = 7; |
---|
90 | /** |
---|
91 | * Use plain line border. |
---|
92 | */ |
---|
93 | public static final int PLAIN_LINE = 0; |
---|
94 | /** |
---|
95 | * Use raised border. |
---|
96 | */ |
---|
97 | public static final int RAISED = 1; |
---|
98 | /** |
---|
99 | * Do not draw a border. |
---|
100 | */ |
---|
101 | public static final int NO_BORDER = 2; |
---|
102 | /** |
---|
103 | * Align to top of key. |
---|
104 | */ |
---|
105 | public static final int TOP = 0; |
---|
106 | /** |
---|
107 | * Align to middle of key. |
---|
108 | */ |
---|
109 | public static final int MIDDLE = 1; |
---|
110 | /** |
---|
111 | * Align to bottom of key. |
---|
112 | */ |
---|
113 | public static final int BOTTOM = 2; |
---|
114 | /** |
---|
115 | * Align to left of key. |
---|
116 | */ |
---|
117 | public static final int LEFT = 0; |
---|
118 | /** |
---|
119 | * Align to center of key. |
---|
120 | */ |
---|
121 | public static final int CENTER = 1; |
---|
122 | /** |
---|
123 | * Align to right of key. |
---|
124 | */ |
---|
125 | public static final int RIGHT = 2; |
---|
126 | |
---|
127 | |
---|
128 | /** |
---|
129 | * Default constructor. |
---|
130 | */ |
---|
131 | public VectorKey() { |
---|
132 | this(new Point2D.Double(0.0, 0.0), BOTTOM, LEFT); |
---|
133 | } |
---|
134 | /** |
---|
135 | * Create <code>VectorKey</code>. |
---|
136 | */ |
---|
137 | public VectorKey(Point2D.Double loc,int valign,int halign) { |
---|
138 | porigin_ = loc; |
---|
139 | valign_ = valign; |
---|
140 | halign_ = halign; |
---|
141 | vectors_ = new Vector(2,2); |
---|
142 | label_ = new Vector(2,2); |
---|
143 | scaleLabel_ = new Vector(2,2); |
---|
144 | // |
---|
145 | // set defaults |
---|
146 | // |
---|
147 | style_ = PLAIN_LINE; |
---|
148 | columns_ = 1; |
---|
149 | ident_ = ""; |
---|
150 | vectorLengthP_ = 0.3f; |
---|
151 | selected_ = false; |
---|
152 | selectable_ = true; |
---|
153 | visible_ = true; |
---|
154 | moveable_ = true; |
---|
155 | |
---|
156 | floatFormat_ = new DecimalFormat(floatScaleFormat_); |
---|
157 | expFormat_ = new DecimalFormat(expScaleFormat_); |
---|
158 | } |
---|
159 | /** |
---|
160 | * Create of copy of VectorKey. |
---|
161 | */ |
---|
162 | public LayerChild copy() { |
---|
163 | VectorKey newKey; |
---|
164 | try { |
---|
165 | newKey = (VectorKey)clone(); |
---|
166 | } catch (CloneNotSupportedException e) { |
---|
167 | newKey = new VectorKey(); |
---|
168 | } |
---|
169 | newKey.vectors_ = new Vector(2,2); |
---|
170 | newKey.label_ = new Vector(2,2); |
---|
171 | return newKey; |
---|
172 | } |
---|
173 | public void setSelected(boolean sel) { |
---|
174 | selected_ = sel; |
---|
175 | } |
---|
176 | public boolean isSelected() { |
---|
177 | return selected_; |
---|
178 | } |
---|
179 | public void setSelectable(boolean select) { |
---|
180 | selectable_ = select; |
---|
181 | } |
---|
182 | public boolean isSelectable() { |
---|
183 | return selectable_; |
---|
184 | } |
---|
185 | public boolean isMoveable() { |
---|
186 | return moveable_; |
---|
187 | } |
---|
188 | public void setMoveable(boolean moveable) { |
---|
189 | moveable_ = moveable; |
---|
190 | } |
---|
191 | /** |
---|
192 | * Set parent layer. |
---|
193 | * |
---|
194 | * @param l parent layer |
---|
195 | */ |
---|
196 | public void setLayer(Layer l) { |
---|
197 | layer_ = l; |
---|
198 | } |
---|
199 | /** |
---|
200 | * Get layer. |
---|
201 | * |
---|
202 | * @return layer |
---|
203 | */ |
---|
204 | public Layer getLayer() { |
---|
205 | return layer_; |
---|
206 | } |
---|
207 | |
---|
208 | public AbstractPane getPane() { |
---|
209 | return layer_.getPane(); |
---|
210 | } |
---|
211 | |
---|
212 | public void modified(String mess) { |
---|
213 | if(layer_ != null) |
---|
214 | layer_.modified(mess); |
---|
215 | } |
---|
216 | /** |
---|
217 | * Set VectorKey identifier. |
---|
218 | * |
---|
219 | * @param id key identifier |
---|
220 | */ |
---|
221 | public void setId(String id) { |
---|
222 | ident_ = id; |
---|
223 | } |
---|
224 | /** |
---|
225 | * Get VectorKey identifier |
---|
226 | * |
---|
227 | * @return identifier |
---|
228 | */ |
---|
229 | public String getId() { |
---|
230 | return ident_; |
---|
231 | } |
---|
232 | /** |
---|
233 | * Set line length. |
---|
234 | * |
---|
235 | * @param len line length |
---|
236 | */ |
---|
237 | public void setVectorLengthP(double len) { |
---|
238 | if(vectorLengthP_ != len) { |
---|
239 | vectorLengthP_ = len; |
---|
240 | modified("VectorKey: setVectorLengthP()"); |
---|
241 | } |
---|
242 | } |
---|
243 | /** |
---|
244 | * @since 3.0 |
---|
245 | */ |
---|
246 | public void setLineLengthP(double len) { |
---|
247 | setVectorLengthP(len); |
---|
248 | } |
---|
249 | /** |
---|
250 | * Get line length |
---|
251 | * |
---|
252 | * @return line length |
---|
253 | */ |
---|
254 | public double getVectorLengthP() { |
---|
255 | return vectorLengthP_; |
---|
256 | } |
---|
257 | /** |
---|
258 | * Set the number of columns. |
---|
259 | * |
---|
260 | * @param col number of columns |
---|
261 | */ |
---|
262 | public void setColumns(int col) { |
---|
263 | if(columns_ != col) { |
---|
264 | columns_ = col; |
---|
265 | modified("VectorKey: setColumms()"); |
---|
266 | } |
---|
267 | } |
---|
268 | /** |
---|
269 | * Get the number of columns. |
---|
270 | * |
---|
271 | * @return number of columns |
---|
272 | */ |
---|
273 | public int getColumns() { |
---|
274 | return columns_; |
---|
275 | } |
---|
276 | /** |
---|
277 | * Set border style. |
---|
278 | * |
---|
279 | * @param style border style |
---|
280 | * @see #PLAIN_LINE |
---|
281 | * @see #RAISED |
---|
282 | * @see #NO_BORDER |
---|
283 | */ |
---|
284 | public void setBorderStyle(int style) { |
---|
285 | if(style_ != style) { |
---|
286 | style_ = style; |
---|
287 | modified("VectorKey: setBorderStyle()"); |
---|
288 | } |
---|
289 | } |
---|
290 | /** |
---|
291 | * Get border style. |
---|
292 | * |
---|
293 | * @return border style |
---|
294 | */ |
---|
295 | public int getBorderStyle() { |
---|
296 | return style_; |
---|
297 | } |
---|
298 | /** |
---|
299 | * Set alignment. |
---|
300 | * |
---|
301 | * @param vert vertical alignment |
---|
302 | * @param horz horizontal alignment |
---|
303 | */ |
---|
304 | public void setAlign(int vert,int horz) { |
---|
305 | if(valign_ != vert || halign_ != horz) { |
---|
306 | valign_ = vert; |
---|
307 | halign_ = horz; |
---|
308 | modified("VectorKey: setAlign()"); |
---|
309 | } |
---|
310 | } |
---|
311 | /** |
---|
312 | * Set vertical alignment |
---|
313 | * |
---|
314 | * @param vert vertical alignment |
---|
315 | */ |
---|
316 | public void setVAlign(int vert) { |
---|
317 | if(valign_ != vert) { |
---|
318 | valign_ = vert; |
---|
319 | modified("VectorKey: setVAlign()"); |
---|
320 | } |
---|
321 | } |
---|
322 | /** |
---|
323 | * Set horizontal alignment |
---|
324 | * |
---|
325 | * @param horz horizontal alignment |
---|
326 | */ |
---|
327 | public void setHAlign(int horz) { |
---|
328 | if(halign_ != horz) { |
---|
329 | halign_ = horz; |
---|
330 | modified("VectorKey: setHAlign()"); |
---|
331 | } |
---|
332 | } |
---|
333 | /** |
---|
334 | * Get vertical alignment |
---|
335 | * |
---|
336 | * @return vertical alignment |
---|
337 | */ |
---|
338 | public int getVAlign() { |
---|
339 | return valign_; |
---|
340 | } |
---|
341 | /** |
---|
342 | * Get horizontal alignment |
---|
343 | * |
---|
344 | * @return horizontal alignment |
---|
345 | */ |
---|
346 | public int getHAlign() { |
---|
347 | return halign_; |
---|
348 | } |
---|
349 | /** |
---|
350 | * Set location of key |
---|
351 | * <BR><B>Property Change:</B> <code>location</code>. |
---|
352 | * |
---|
353 | * @param loc key location |
---|
354 | */ |
---|
355 | public void setLocationP(Point2D.Double loc) { |
---|
356 | if(porigin_ == null || !porigin_.equals(loc)) { |
---|
357 | Point2D.Double temp = porigin_; |
---|
358 | porigin_ = loc; |
---|
359 | changes_.firePropertyChange("location", |
---|
360 | temp, |
---|
361 | porigin_); |
---|
362 | modified("VectorKey: setLocationP()"); |
---|
363 | } |
---|
364 | } |
---|
365 | /** |
---|
366 | * Set the bounds, in physical units, of the <code>VectorKey</code> |
---|
367 | */ |
---|
368 | public void setBoundsP(Rectangle2D.Double r) { |
---|
369 | setLocationP(new Point2D.Double(r.x, r.y)); |
---|
370 | } |
---|
371 | public Rectangle2D.Double getBoundsP() { |
---|
372 | throw new MethodNotImplementedError(); |
---|
373 | } |
---|
374 | /** |
---|
375 | * Get location of key. |
---|
376 | * |
---|
377 | * @return Key location |
---|
378 | */ |
---|
379 | public Point2D.Double getLocationP() { |
---|
380 | return porigin_; |
---|
381 | } |
---|
382 | /** |
---|
383 | * Add a VectorCartesianRenderer and label to the VectorKey. |
---|
384 | * |
---|
385 | * @param line VectorCartesianRenderer object |
---|
386 | * @param label descriptive label |
---|
387 | */ |
---|
388 | public void addVectorGraph(VectorCartesianRenderer vector, SGLabel label) { |
---|
389 | vectors_.addElement(vector); |
---|
390 | label.setLayer(layer_); |
---|
391 | label.setMoveable(false); |
---|
392 | label.setSelectable(false); |
---|
393 | label_.addElement(label); |
---|
394 | SGLabel scale = new SGLabel("scale label", |
---|
395 | " ", |
---|
396 | label.getHeightP(), |
---|
397 | label.getLocationP(), |
---|
398 | label.getVAlign(), |
---|
399 | label.getHAlign()); |
---|
400 | scale.setFont(label.getFont()); |
---|
401 | scale.setLayer(label.getLayer()); |
---|
402 | scale.setMoveable(false); |
---|
403 | scale.setSelectable(false); |
---|
404 | scaleLabel_.addElement(scale); |
---|
405 | ((VectorAttribute)vector.getAttribute()).addPropertyChangeListener(this); |
---|
406 | modified("VectorKey: addVectorGraph()"); |
---|
407 | } |
---|
408 | /** |
---|
409 | * Add a VectorCartesianRenderer and label to the VectorKey. |
---|
410 | * |
---|
411 | * @param rend CartesianRenderer object |
---|
412 | * @param label descriptive label |
---|
413 | * @since 3.0 |
---|
414 | */ |
---|
415 | public void addGraph(CartesianRenderer rend, SGLabel label) |
---|
416 | throws IllegalArgumentException { |
---|
417 | if(!(rend instanceof VectorCartesianRenderer)) |
---|
418 | throw new IllegalArgumentException("Renderer is not a VectorCartesianRenderer"); |
---|
419 | addVectorGraph((VectorCartesianRenderer)rend, label); |
---|
420 | } |
---|
421 | /** |
---|
422 | * Remove a line from the VectorKey. |
---|
423 | * |
---|
424 | */ |
---|
425 | public void removeVectorGraph(SGLabel label) { |
---|
426 | } |
---|
427 | /** |
---|
428 | * Remove a line from the VectorKey. |
---|
429 | * |
---|
430 | */ |
---|
431 | public void removeVectorRenderer(VectorCartesianRenderer line) { |
---|
432 | } |
---|
433 | /** |
---|
434 | * Remove a line from the VectorKey. |
---|
435 | * |
---|
436 | */ |
---|
437 | public void removeVectorGraph(String ident) { |
---|
438 | } |
---|
439 | /** |
---|
440 | * Remove all lines from the VectorKey. |
---|
441 | */ |
---|
442 | public void clearAll() { |
---|
443 | VectorAttribute attr; |
---|
444 | for(Enumeration e = vectors_.elements(); e.hasMoreElements(); ) { |
---|
445 | attr = (VectorAttribute)((VectorCartesianRenderer)e.nextElement()).getAttribute(); |
---|
446 | attr.removePropertyChangeListener(this); |
---|
447 | } |
---|
448 | vectors_.removeAllElements(); |
---|
449 | label_.removeAllElements(); |
---|
450 | modified("VectorKey: clearAll()"); |
---|
451 | } |
---|
452 | /** |
---|
453 | * Remove data from key by id. |
---|
454 | */ |
---|
455 | public void clear(String data_id) { |
---|
456 | VectorCartesianRenderer vcr; |
---|
457 | int indx = -1; |
---|
458 | for(Enumeration it = vectors_.elements(); it.hasMoreElements();) { |
---|
459 | indx++; |
---|
460 | vcr = (VectorCartesianRenderer)it.nextElement(); |
---|
461 | // if(pcr.getLine().getId().equals(data_id)) { |
---|
462 | // pcr.getAttribute().removePropertyChangeListener(this); |
---|
463 | // points_.removeElement(lcr); |
---|
464 | // label_.removeElementAt(indx); |
---|
465 | // modified("VectorKey: clear()"); |
---|
466 | // break; |
---|
467 | // } |
---|
468 | } |
---|
469 | } |
---|
470 | /** |
---|
471 | * Return height of key row in pixels. |
---|
472 | */ |
---|
473 | public int getRowHeight() { |
---|
474 | Rectangle bounds; |
---|
475 | bounds = getBounds(); |
---|
476 | return ROW_SPACE_ + maxLabelHeight_; |
---|
477 | } |
---|
478 | /** |
---|
479 | * Draw the Key. |
---|
480 | */ |
---|
481 | public void draw(Graphics g) { |
---|
482 | double maxLabelLength, maxLabelHeight; |
---|
483 | int numLines, numRows, i; |
---|
484 | float vectorLength; |
---|
485 | float vectorLengthU; |
---|
486 | int col, row, ytemp; |
---|
487 | double xloc, labelSpace, scaleSpace, scaleLength; |
---|
488 | double[] xp, yp; |
---|
489 | int[] xd, yd; |
---|
490 | int[] xout, yout; |
---|
491 | float hx1, hx2; |
---|
492 | float hy1, hy2; |
---|
493 | float headX, headY; |
---|
494 | float orgX, orgY; |
---|
495 | float xphead, yphead; |
---|
496 | float tScale, fixedScale; |
---|
497 | float scale; |
---|
498 | float headScale; |
---|
499 | float minSize; |
---|
500 | float maxSize; |
---|
501 | Rectangle bounds; |
---|
502 | VectorCartesianRenderer render = null; |
---|
503 | SGLabel label; |
---|
504 | SGLabel scaleLabel; |
---|
505 | String scaleStr; |
---|
506 | VectorAttribute attr = null; |
---|
507 | Graphics2D g2 = (Graphics2D)g; |
---|
508 | GeneralPath gp; |
---|
509 | Stroke savedStroke = g2.getStroke(); |
---|
510 | BasicStroke stroke; |
---|
511 | slope_ = (float)layer_.getXSlope(); |
---|
512 | xoff_ = (float)layer_.getXOffset(); |
---|
513 | yoff_ = (float)layer_.getYOffset(); |
---|
514 | // |
---|
515 | numLines = vectors_.size(); |
---|
516 | if((numLines <= 0) || !visible_) return; |
---|
517 | |
---|
518 | numRows = numLines/columns_; |
---|
519 | if(numLines%columns_ != 0) numRows++; |
---|
520 | |
---|
521 | xp = new double[columns_]; |
---|
522 | xd = new int[columns_]; |
---|
523 | yp = new double[numRows]; |
---|
524 | yd = new int[numRows]; |
---|
525 | xout = new int[2]; |
---|
526 | yout = new int[2]; |
---|
527 | |
---|
528 | g.setColor(layer_.getPane().getComponent().getForeground()); |
---|
529 | bounds = getBounds(); |
---|
530 | // |
---|
531 | // compute location of rows and columns in device and physical coordinates |
---|
532 | // |
---|
533 | vectorLength = xPtoD((float)vectorLengthP_) - xPtoD(0.0f); |
---|
534 | labelSpace = layer_.getXDtoP(LABEL_SPACE_) - layer_.getXDtoP(0); |
---|
535 | scaleLength = layer_.getXDtoP(maxScaleLength_) - layer_.getXDtoP(0); |
---|
536 | scaleSpace = layer_.getXDtoP(SCALE_SPACE_) - layer_.getXDtoP(0); |
---|
537 | // |
---|
538 | yd[0] = bounds.y + VERTICAL_BORDER_ + maxLabelHeight_; |
---|
539 | yp[0] = layer_.getYDtoP(yd[0]); |
---|
540 | for(i=1; i < numRows; i++) { |
---|
541 | yd[i] = yd[i-1] + ROW_SPACE_ + maxLabelHeight_; |
---|
542 | yp[i] = layer_.getYDtoP(yd[i]); |
---|
543 | } |
---|
544 | xd[0] = bounds.x + HORIZONTAL_BORDER_; |
---|
545 | xp[0] = layer_.getXDtoP(xd[0]); |
---|
546 | for(i=1; i < columns_; i++) { |
---|
547 | xd[i] = xd[i-1] + COLUMN_SPACE_ + (int)vectorLength + |
---|
548 | SCALE_SPACE_ + maxScaleLength_ + |
---|
549 | LABEL_SPACE_ + maxLabelLength_; |
---|
550 | xp[i] = layer_.getXDtoP(xd[i]); |
---|
551 | } |
---|
552 | // |
---|
553 | row = 0; |
---|
554 | col = 0; |
---|
555 | Object obj; |
---|
556 | Enumeration labelIt = label_.elements(); |
---|
557 | Enumeration scaleIt = scaleLabel_.elements(); |
---|
558 | for(Enumeration lineIt = vectors_.elements(); lineIt.hasMoreElements();) { |
---|
559 | obj = lineIt.nextElement(); |
---|
560 | render = (VectorCartesianRenderer)obj; |
---|
561 | attr = (VectorAttribute)render.getAttribute(); |
---|
562 | label = (SGLabel)labelIt.nextElement(); |
---|
563 | scaleLabel = (SGLabel)scaleIt.nextElement(); |
---|
564 | // |
---|
565 | // draw line |
---|
566 | // |
---|
567 | g2.setColor(attr.getVectorColor()); |
---|
568 | stroke = new BasicStroke(attr.getWidth(), |
---|
569 | attr.getCapStyle(), |
---|
570 | attr.getMiterStyle(), |
---|
571 | attr.getMiterLimit()); |
---|
572 | scale = (float)attr.getVectorScale(); |
---|
573 | headScale = (float)attr.getHeadScale()*0.94386f; |
---|
574 | fixedScale = (float)(headScale*attr.getHeadFixedSize()); |
---|
575 | minSize = (float)attr.getHeadMinSize(); |
---|
576 | maxSize = (float)attr.getHeadMaxSize(); |
---|
577 | vectorLengthU = (float)(vectorLengthP_/scale); |
---|
578 | g2.setStroke(stroke); |
---|
579 | gp = new GeneralPath(); |
---|
580 | orgX = (float)xd[col]; |
---|
581 | orgY = (float)(yd[row] - maxLabelHeight_/2); |
---|
582 | headX = orgX + vectorLength; |
---|
583 | headY = orgY; |
---|
584 | xphead = xDtoP(headX); |
---|
585 | yphead = yDtoP(headY); |
---|
586 | gp.moveTo(orgX, orgY); |
---|
587 | gp.lineTo(headX, headY); |
---|
588 | // |
---|
589 | // add head |
---|
590 | // |
---|
591 | if(vectorLength == 0.0) { |
---|
592 | g.drawLine((int)headX, (int)headY, (int)headX, (int)headY); |
---|
593 | } else { |
---|
594 | if(attr.getVectorStyle() != VectorAttribute.NO_HEAD) { |
---|
595 | if(attr.getVectorStyle() == VectorAttribute.HEAD) { |
---|
596 | // unscaled head |
---|
597 | tScale = fixedScale; |
---|
598 | hx1 = xPtoD(xphead - tScale); |
---|
599 | hy1 = yPtoD(yphead + 0.35f*tScale); |
---|
600 | hx2 = xPtoD(xphead - tScale); |
---|
601 | hy2 = yPtoD(yphead - 0.35f*tScale); |
---|
602 | gp.moveTo(hx1, hy1); |
---|
603 | gp.lineTo(headX, headY); |
---|
604 | gp.lineTo(hx2, hy2); |
---|
605 | } else { |
---|
606 | // scaled head |
---|
607 | if(vectorLengthP_ >= maxSize) { |
---|
608 | tScale = maxSize*headScale; |
---|
609 | } else if(vectorLengthP_ <= minSize) { |
---|
610 | tScale = minSize*headScale; |
---|
611 | } else { |
---|
612 | tScale = (float)(vectorLengthP_*headScale); |
---|
613 | } |
---|
614 | hx1 = xPtoD(xphead - tScale); |
---|
615 | hy1 = yPtoD(yphead + 0.35f*tScale); |
---|
616 | hx2 = xPtoD(xphead - tScale); |
---|
617 | hy2 = yPtoD(yphead - 0.35f*tScale); |
---|
618 | gp.moveTo(hx1, hy1); |
---|
619 | gp.lineTo(headX, headY); |
---|
620 | gp.lineTo(hx2, hy2); |
---|
621 | } |
---|
622 | } |
---|
623 | } |
---|
624 | |
---|
625 | g2.draw(gp); |
---|
626 | g2.setStroke(savedStroke); |
---|
627 | // |
---|
628 | // draw mark |
---|
629 | // |
---|
630 | xout[0] = (int)orgX; |
---|
631 | yout[0] = (int)orgY; |
---|
632 | if(attr.getOriginStyle() == VectorAttribute.MARK) { |
---|
633 | g.setColor(attr.getMarkColor()); |
---|
634 | render.drawMark(g, xout, yout, 1, attr); |
---|
635 | } |
---|
636 | // |
---|
637 | // scale label |
---|
638 | // |
---|
639 | xloc = xp[col] + vectorLengthP_ + scaleSpace; |
---|
640 | if(vectorLengthU > 1000.0 || vectorLengthU < 0.01) { |
---|
641 | scaleStr = expFormat_.format(vectorLengthU); |
---|
642 | } else { |
---|
643 | scaleStr = floatFormat_.format(vectorLengthU); |
---|
644 | } |
---|
645 | scaleLabel.setText(scaleStr); |
---|
646 | scaleLabel.setLocationP(new Point2D.Double(xloc, yp[row])); |
---|
647 | |
---|
648 | // |
---|
649 | // user label |
---|
650 | // |
---|
651 | xloc = xloc + scaleLength + labelSpace; |
---|
652 | label.setLocationP(new Point2D.Double(xloc, yp[row])); |
---|
653 | try { |
---|
654 | scaleLabel.draw(g); |
---|
655 | label.draw(g); |
---|
656 | } catch (SGException e) { System.out.println(e);} |
---|
657 | // |
---|
658 | col++; |
---|
659 | if(col >= columns_) { |
---|
660 | col = 0; |
---|
661 | row++; |
---|
662 | } |
---|
663 | } |
---|
664 | switch(style_) { |
---|
665 | case PLAIN_LINE: |
---|
666 | g.drawRect(bounds.x, bounds.y, bounds.width-1, bounds.height-1); |
---|
667 | break; |
---|
668 | case RAISED: |
---|
669 | break; |
---|
670 | default: |
---|
671 | case NO_BORDER: |
---|
672 | } |
---|
673 | } |
---|
674 | |
---|
675 | private float xPtoD(float xp) { |
---|
676 | return slope_*xp + xoff_; |
---|
677 | } |
---|
678 | |
---|
679 | private float yPtoD(float yp) { |
---|
680 | return yoff_ - slope_*yp; |
---|
681 | } |
---|
682 | |
---|
683 | private float xDtoP(float xd) { |
---|
684 | return (xd - xoff_)/slope_; |
---|
685 | } |
---|
686 | |
---|
687 | private float yDtoP(float yd) { |
---|
688 | return (yoff_ - yd)/slope_; |
---|
689 | } |
---|
690 | |
---|
691 | /** |
---|
692 | * Get the bounding rectangle. |
---|
693 | * |
---|
694 | * @return bounding rectangle |
---|
695 | */ |
---|
696 | public Rectangle getBounds() { |
---|
697 | int vectorLength; |
---|
698 | int numLines, rows; |
---|
699 | int x, y, height, width; |
---|
700 | |
---|
701 | numLines = vectors_.size(); |
---|
702 | if(numLines <= 0) return new Rectangle(0, 0, 0, 0); |
---|
703 | // |
---|
704 | // find longest label and scale |
---|
705 | // |
---|
706 | maxLabelLength_ = 0; |
---|
707 | maxLabelHeight_ = 0; |
---|
708 | maxScaleLength_ = 0; |
---|
709 | Object obj; |
---|
710 | VectorCartesianRenderer render; |
---|
711 | VectorAttribute attr; |
---|
712 | double vectorLengthU; |
---|
713 | Enumeration lineIt = vectors_.elements(); |
---|
714 | Enumeration scaleIt = scaleLabel_.elements(); |
---|
715 | SGLabel label; |
---|
716 | String scaleStr; |
---|
717 | SGLabel scaleLabel; |
---|
718 | for(Enumeration it = label_.elements(); it.hasMoreElements();) { |
---|
719 | label = (SGLabel)it.nextElement(); |
---|
720 | Rectangle sz = label.getBounds(); |
---|
721 | maxLabelLength_ = Math.max(maxLabelLength_, sz.width); |
---|
722 | maxLabelHeight_ = Math.max(maxLabelHeight_, sz.height); |
---|
723 | // |
---|
724 | obj = lineIt.nextElement(); |
---|
725 | render = (VectorCartesianRenderer)obj; |
---|
726 | attr = (VectorAttribute)render.getAttribute(); |
---|
727 | vectorLengthU = vectorLengthP_/attr.getVectorScale(); |
---|
728 | if(vectorLengthU > 1000.0 || vectorLengthU < 0.01) { |
---|
729 | scaleStr = expFormat_.format(vectorLengthU); |
---|
730 | } else { |
---|
731 | scaleStr = floatFormat_.format(vectorLengthU); |
---|
732 | } |
---|
733 | scaleLabel = (SGLabel)scaleIt.nextElement(); |
---|
734 | scaleLabel.setText(scaleStr); |
---|
735 | sz = scaleLabel.getBounds(); |
---|
736 | maxScaleLength_ = Math.max(maxScaleLength_, sz.width); |
---|
737 | } |
---|
738 | // |
---|
739 | rows = numLines/columns_; |
---|
740 | if(numLines%columns_ != 0) rows++; |
---|
741 | vectorLength = layer_.getXPtoD(vectorLengthP_) - layer_.getXPtoD(0.0f); |
---|
742 | width = 2*HORIZONTAL_BORDER_ + |
---|
743 | columns_*(vectorLength + SCALE_SPACE_ + maxScaleLength_ + |
---|
744 | LABEL_SPACE_ + maxLabelLength_) + |
---|
745 | (columns_ - 1)*COLUMN_SPACE_; |
---|
746 | height = 2*VERTICAL_BORDER_ + rows*maxLabelHeight_ + |
---|
747 | (rows-1)*ROW_SPACE_; |
---|
748 | // temp fudge |
---|
749 | height = height + 5; |
---|
750 | // |
---|
751 | x = layer_.getXPtoD(porigin_.x); |
---|
752 | y = layer_.getYPtoD(porigin_.y); |
---|
753 | switch(halign_) { |
---|
754 | case RIGHT: |
---|
755 | x = x - width; |
---|
756 | break; |
---|
757 | case CENTER: |
---|
758 | x = x - width/2; |
---|
759 | } |
---|
760 | switch(valign_) { |
---|
761 | case BOTTOM: |
---|
762 | y = y - height; |
---|
763 | break; |
---|
764 | case MIDDLE: |
---|
765 | y = y - height/2; |
---|
766 | } |
---|
767 | return new Rectangle(x, y, width, height); |
---|
768 | } |
---|
769 | public Point getLocation() { |
---|
770 | Rectangle bnds = getBounds(); |
---|
771 | return new Point(bnds.x, bnds.y); |
---|
772 | } |
---|
773 | public void setLocation(Point loc) { |
---|
774 | Rectangle bnds = getBounds(); |
---|
775 | setBounds(loc.x, loc.y, bnds.width, bnds.height); |
---|
776 | } |
---|
777 | /** |
---|
778 | * Set the bounds, in pixels, of the <code>VectorKey</code> |
---|
779 | */ |
---|
780 | public void setBounds(Rectangle r) { |
---|
781 | setBounds(r.x, r.y, r.width, r.height); |
---|
782 | } |
---|
783 | /** |
---|
784 | * Set the bounds, in pixels, of the <code>VectorKey</code> |
---|
785 | * <BR><B>Property Change:</B> <code>location</code>. |
---|
786 | */ |
---|
787 | public void setBounds(int x, int y, int width, int height) { |
---|
788 | switch(halign_) { |
---|
789 | case RIGHT: |
---|
790 | x = x + width; |
---|
791 | break; |
---|
792 | case CENTER: |
---|
793 | x = x + width/2; |
---|
794 | } |
---|
795 | switch(valign_) { |
---|
796 | case BOTTOM: |
---|
797 | y = y + height; |
---|
798 | break; |
---|
799 | case MIDDLE: |
---|
800 | y = y + height/2; |
---|
801 | } |
---|
802 | double xp = layer_.getXDtoP(x); |
---|
803 | double yp = layer_.getYDtoP(y); |
---|
804 | if(porigin_.x != xp || porigin_.y != yp) { |
---|
805 | Point2D.Double temp = porigin_; |
---|
806 | porigin_.x = xp; |
---|
807 | porigin_.y = yp; |
---|
808 | changes_.firePropertyChange("location", |
---|
809 | temp, |
---|
810 | new Point2D.Double(xp, yp)); |
---|
811 | modified("VectorKey: setBounds()"); |
---|
812 | } |
---|
813 | } |
---|
814 | Object getObjectAt(Point pt) { |
---|
815 | Rectangle lbnds; |
---|
816 | Rectangle bounds; |
---|
817 | VectorCartesianRenderer vector; |
---|
818 | int[] xout, yout; |
---|
819 | int[] xd, yd; |
---|
820 | int numLines, numRows; |
---|
821 | int vectorLength; |
---|
822 | double labelSpace, scaleSpace; |
---|
823 | int i; |
---|
824 | |
---|
825 | numLines = vectors_.size(); |
---|
826 | if(numLines <= 0) return null; |
---|
827 | |
---|
828 | numRows = numLines/columns_; |
---|
829 | if(numLines%columns_ != 0) numRows++; |
---|
830 | |
---|
831 | xd = new int[columns_]; |
---|
832 | yd = new int[numRows]; |
---|
833 | xout = new int[2]; |
---|
834 | yout = new int[2]; |
---|
835 | bounds = getBounds(); |
---|
836 | // |
---|
837 | // compute location of rows and columns in device and physical coordinates |
---|
838 | // |
---|
839 | vectorLength = layer_.getXPtoD(vectorLengthP_) - layer_.getXPtoD(0.0); |
---|
840 | labelSpace = layer_.getXDtoP(LABEL_SPACE_) - layer_.getXDtoP(0); |
---|
841 | scaleSpace = layer_.getXDtoP(SCALE_SPACE_) - layer_.getXDtoP(0); |
---|
842 | // |
---|
843 | yd[0] = bounds.y + VERTICAL_BORDER_ + maxLabelHeight_; |
---|
844 | for(i=1; i < numRows; i++) { |
---|
845 | yd[i] = yd[i-1] + ROW_SPACE_ + maxLabelHeight_; |
---|
846 | } |
---|
847 | xd[0] = bounds.x + HORIZONTAL_BORDER_; |
---|
848 | for(i=1; i < columns_; i++) { |
---|
849 | xd[i] = xd[i-1] + COLUMN_SPACE_ + vectorLength + SCALE_SPACE_ + |
---|
850 | maxScaleLength_ + LABEL_SPACE_ + maxLabelLength_; |
---|
851 | } |
---|
852 | // loop over all the lines |
---|
853 | int row = 0; |
---|
854 | int col = 0; |
---|
855 | for(Enumeration lineIt = vectors_.elements(); lineIt.hasMoreElements();) { |
---|
856 | vector = (VectorCartesianRenderer)lineIt.nextElement(); |
---|
857 | xout[0] = xd[col]; |
---|
858 | // xout[1] = xout[0] + vectorLength + 2*LABEL_SPACE_ + |
---|
859 | // maxScaleLenght_ + maxLabelLength_; |
---|
860 | xout[1] = xout[0] + vectorLength + SCALE_SPACE_; |
---|
861 | yout[0] = yd[row] - maxLabelHeight_; |
---|
862 | yout[1] = yd[row]; |
---|
863 | lbnds = new Rectangle(xout[0], yout[0], |
---|
864 | xout[1] - xout[0], |
---|
865 | yout[1] - yout[0]); |
---|
866 | |
---|
867 | if(lbnds.contains(pt)) { |
---|
868 | return vector; |
---|
869 | } |
---|
870 | // |
---|
871 | col++; |
---|
872 | if(col >= columns_) { |
---|
873 | col = 0; |
---|
874 | row++; |
---|
875 | } |
---|
876 | } |
---|
877 | if(bounds.contains(pt)) { |
---|
878 | return this; |
---|
879 | } |
---|
880 | return null; |
---|
881 | } |
---|
882 | public String toString() { |
---|
883 | String name = getClass().getName(); |
---|
884 | return name.substring(name.lastIndexOf(".")+1) + ": " + ident_; |
---|
885 | } |
---|
886 | public boolean isVisible() { |
---|
887 | return visible_; |
---|
888 | } |
---|
889 | public void setVisible(boolean visible) { |
---|
890 | if(visible_ != visible) { |
---|
891 | visible_ = visible; |
---|
892 | modified("VectorKey: setVisible()"); |
---|
893 | } |
---|
894 | } |
---|
895 | public void propertyChange(PropertyChangeEvent evt) { |
---|
896 | // if(Debug.EVENT) { |
---|
897 | // System.out.println("VectorKey: " + evt); |
---|
898 | // System.out.println(" " + evt.getPropertyName()); |
---|
899 | // } |
---|
900 | modified("VectorKey: propertyChange(" + |
---|
901 | evt.getSource().toString() + "[" + |
---|
902 | evt.getPropertyName() + "]" + ")"); |
---|
903 | } |
---|
904 | public void addPropertyChangeListener(PropertyChangeListener l) { |
---|
905 | changes_.addPropertyChangeListener(l); |
---|
906 | } |
---|
907 | public void removePropertyChangeListener(PropertyChangeListener l) { |
---|
908 | changes_.removePropertyChangeListener(l); |
---|
909 | } |
---|
910 | } |
---|