Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/xerox/VTM/glyphs/Glyph.java


1   /*   FILE: Glyph.java
2    *   DATE OF CREATION:   Jul 11 2000
3    *   AUTHOR :            Emmanuel Pietriga (emmanuel.pietriga@xrce.xerox.com)
4    *   MODIF:              Wed Aug 06 14:22:52 2003 by Emmanuel Pietriga (emmanuel@w3.org, emmanuel@claribole.net)
5    *   Copyright (c) Xerox Corporation, XRCE/Contextual Computing, and Emmanuel Pietriga, 2002. All Rights Reserved
6    *
7    * This library is free software; you can redistribute it and/or
8    * modify it under the terms of the GNU Lesser General Public
9    * License as published by the Free Software Foundation; either
10   * version 2.1 of the License, or (at your option) any later version.
11   * 
12   * This library is distributed in the hope that it will be useful,
13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15   * Lesser General Public License for more details.
16   *
17   * For full terms see the file COPYING.
18   */
19  
20  package com.xerox.VTM.glyphs;
21  
22  import com.xerox.VTM.engine.*;
23  import java.awt.Graphics2D;
24  import java.awt.Color;
25  import java.awt.Polygon;
26  import java.util.Vector;
27  import java.awt.geom.AffineTransform;
28  import java.awt.Stroke;
29  import java.awt.BasicStroke;
30  import java.awt.Font;
31  import java.awt.geom.Rectangle2D;
32  import java.util.Enumeration;
33  import net.claribole.zvtm.glyphs.*;
34  
35  /**glyph - parent class of all graphical objects
36   * @author Emmanuel Pietriga
37   */
38  
39  public abstract class Glyph implements Cloneable {
40  
41      /**Glyph ID*/
42      Long ID;
43      /**coordinate in virtual space (geometric center of object)*/
44      public long vx,vy;
45      /**altitude (in virtual space)*/
46      public float vz;
47      /**radius of bounding circle*/
48      float size;
49      /**object orientation [0:2Pi[ */
50      float orient=0.0f;
51      /**tells whether this glyph is selected or not (default is false)*/
52      boolean selected=false;
53      /**tells whether this glyph is visible or not (default is true)*/
54      boolean visible=true;
55      /**tells whether we should detect entry/exit in this glyph*/
56      boolean sensit=true;
57      /**set sensitivity of this glyph*/
58      public void setSensitivity(boolean b){
59    sensit=b;
60      }
61      /**tells whether mouse sends events related to entry/exit in this glyph or not*/
62      public boolean isSensitive(){return sensit;}
63  
64      /**text that should be drawn with glyph*/
65      String text;
66      /**1=always draw text 0=draw text when approx fits inside object -1=never draw text 2=as VText*/
67      int fontSizePolicy=1;
68      /**tells if string should be painted inside glyph (=0), on top of glyph (=1),  or under glyph (=-1)*/
69      int textPos=0;
70      /**width of text in pixels (only available in textDraw())*/
71      int textWidth;
72      /**height of text in pixels (only available in textDraw())*/
73      int textHeight;
74      /**constant: default font used in the VTM (must be the same as the one in View)*/
75  //     public static Font defaultFont=new Font("Dialog",0,10);
76      /**font size in pixels*/
77      public static float fontSize=VirtualSpaceManager.getMainFont().getSize2D();
78      /**special font used in this object only (null if default font)*/
79      Font font;
80  
81      /**ref to the object this glyph represents*/
82      Object owner;
83      /**type of object (can be any string)*/
84      String type="";
85  
86      /**composite glyph associated with this glyph (meaning that this glyph is either a primary or secondary glyph inside a CGlyph)*/
87      CGlyph cGlyph=null;
88      /**set the composite glyph associated with this glyph (meaning that this glyph is either a primary or secondary glyph inside a CGlyph) - do not call this method manually ; called autolatically when adding the glyph in the cglyph*/
89      public void setCGlyph(CGlyph c){cGlyph=c;}
90      /**returns the composite glyph associated with this glyph (meaning that this glyph is either a primary or secondary glyph inside a CGlyph) - returns null if none*/
91      public CGlyph getCGlyph(){return cGlyph;}
92  
93  
94      Vector dependants;
95      /**add a glyph to the list of glyphs depending on this one - put glyphs that depend on this one here  (for instance segments to hide when hiding this object...). What should be done with dependants depends on the application (the programmer has to specify what to do with dependants when something happens to this glyph manually - we just store them here) - this list has to be maintained manually (if a glyph is destroyed, it is not removed from dependant lists in which it might appear)*/
96      public void addDependant(Glyph g){
97    if (dependants==null){dependants=new Vector();}
98    dependants.add(g);
99      }
100     /**remove a glyph frmo the list of glyphs depending on this one (nothing happens if g is not in the list)*/
101     public void removeDependant(Glyph g){
102   if (dependants!=null){dependants.remove(g);}
103   if (dependants.isEmpty()){dependants=null;}
104     }
105     /**get list of glyphs depending on this one*/
106     public Vector getDependants(){
107   return dependants;
108     }
109 
110     /**projection coef*/
111     public float coef=1.0f;
112 
113     /**ref to VSM*/
114     public VirtualSpaceManager vsm;
115 
116     /**color of interior*/
117     public Color color;
118     /**current color of border*/
119     public Color borderColor;
120     /**color of border when glyph is selected (can be different fom color when cursor is inside glyph)*/
121     public Color selectedColor;
122     /**color of border when cursor is inside glyph*/
123     public Color mouseInsideColor;
124     /**standard color of border*/
125     public Color bColor=Color.black;
126 
127     /**HSV coordinates of interior color  in range 0.0-1.0*/
128     protected float[] HSV=new float[3];
129     /**HSV coordinates of border color*/
130     protected float[] HSVb=new float[3];
131     
132     //Stroke originalStroke;  //used to store original graphics context's stroke
133     /**first is width of line, last is offset*/
134     public static float DEFAULT_STROKE_WIDTH=1.0f;
135     BasicStroke stroke=null;  
136     boolean dashedContour=false;
137     float strokeWidth=DEFAULT_STROKE_WIDTH;
138     boolean paintBorder=true;
139 
140     /**
141      *@param b true -> draw a discontinuous contour for this glyph
142      */
143     public void setDashed(boolean b){
144   dashedContour=b;
145   strokeWidth=(stroke!=null) ? stroke.getLineWidth() : DEFAULT_STROKE_WIDTH;
146   int cap=(stroke!=null) ? stroke.getEndCap() : BasicStroke.CAP_BUTT;
147   int join=(stroke!=null) ? stroke.getLineJoin() : BasicStroke.JOIN_MITER;
148   float miterlimit=(stroke!=null) ? stroke.getMiterLimit() : 4.0f;
149   if (dashedContour){
150       float[] dasharray={10.0f};
151       float dashphase=(stroke!=null) ? stroke.getDashPhase() : 0.0f;
152       stroke=new BasicStroke(strokeWidth,cap,join,miterlimit,dasharray,dashphase);
153   }
154   else {
155       stroke=new BasicStroke(strokeWidth,cap,join,miterlimit);
156   }
157   try{vsm.repaintNow();}catch(NullPointerException e){}
158     }
159 
160     /**
161      *@param w stroke width - does not change the dashed property
162      */
163     public void setStrokeWidth(float w){
164   strokeWidth=w;
165   int cap=(stroke!=null) ? stroke.getEndCap() : BasicStroke.CAP_BUTT;
166   int join=(stroke!=null) ? stroke.getLineJoin() : BasicStroke.JOIN_MITER;
167   float miterlimit=(stroke!=null) ? stroke.getMiterLimit() : 4.0f;
168   if (dashedContour){
169       float[] dasharray={10.0f};
170       float dashphase=(stroke!=null) ? stroke.getDashPhase() : 0.0f;
171       stroke=new BasicStroke(strokeWidth,cap,join,miterlimit,dasharray,dashphase);
172   }
173   else {
174       stroke=new BasicStroke(strokeWidth,cap,join,miterlimit);
175   }
176   try{vsm.repaintNow();}catch(NullPointerException e){}
177     }
178 
179     /**
180      *@param s basic stroke - has to be built by user - if null, get back to standard stroke
181      */
182     public void setStroke(BasicStroke b){
183   if (b!=null){stroke=b;strokeWidth=stroke.getLineWidth();}
184   else {stroke=null;strokeWidth=1.0f;}
185   try{vsm.repaintNow();}catch(NullPointerException e){/*System.err.println("VSM null in Glyph "+e);*/}
186     }
187 
188     /**
189      *returns the stroke used to paint the border of this glyph (null if none)
190      */
191     public BasicStroke getStroke(){
192   return stroke;
193     }
194 
195     /**
196      *returns the stroke width used to paint the border of this glyph (default is 1.0)
197      */
198     public float getStrokeWidth(){
199   if (stroke!=null){return stroke.getLineWidth();}
200   else return strokeWidth;
201     }
202 
203     /**
204      *@param b draw border with border color (default is true)
205      */
206     public void setPaintBorder(boolean b){
207   if (b!=paintBorder){
208       paintBorder=b;
209       try{vsm.repaintNow();}catch(NullPointerException e){/*System.err.println("VSM null in Glyph "+e);*/}
210   }
211     }
212 
213     /**tells whether a glyph's border is painted or not*/
214     public boolean getPaintBorderStatus(){return paintBorder;}
215 
216     /**set border color when glyph is selected
217      *@param c color used for selection
218      */
219     public void setSelectedColor(Color c){
220   this.selectedColor=c;
221     }
222 
223     /**set border color when cursor is inside glyph
224      *@param c color used for selction
225      */
226     public void setMouseInsideColor(Color c){
227   this.mouseInsideColor=c;
228     }
229 
230     /**select this glyph
231      *@param b true to select glyph, false to unselect it
232      */
233     public void select(boolean b){
234   selected=b;
235   if (b){if (selectedColor!=null){borderColor=selectedColor;}else{borderColor=color;}}
236   else{borderColor=bColor;}
237   try{vsm.repaintNow();}catch(NullPointerException e){/*System.err.println("VSM null in Glyph "+e);*/}
238     }
239 
240     /**get this glyph's selection state (returns true if selected)*/
241     public boolean isSelected(){
242   return selected;
243     }
244 
245     /**make this glyph (in)visible
246      *@param b true to make glyph visible, false to make it invisible
247      */
248     public void setVisible(boolean b){
249   if (b!=visible){
250       visible=b;
251       try{vsm.repaintNow();}catch(NullPointerException e){/*System.err.println("VSM null in Glyph "+e);*/}
252   }
253     }
254 
255     /**get this glyph's visibility state (returns true if visible)*/
256     public boolean isVisible(){
257   return visible;
258     }
259 
260     boolean filled=true;
261     /**
262      *@param b false -> do not paint interior of glyph (only paint contour)
263      */
264     public void setFill(boolean b){
265   if (b!=filled){
266       filled=b;
267       try{vsm.repaintNow();}catch(NullPointerException e){/*System.err.println("VSM null in Glyph "+e);*/}
268   }
269     }
270 
271     /**tells whether this glyph is filled or not*/
272     public boolean getFillStatus(){return filled;}
273 
274     /**glyphs sticked to this one*/
275     Vector stickedGlyphs;
276 
277     /**object to which this glyph is sticked to (could be a VCursor or a Glyph)*/
278     public Object stickedTo;
279 
280     /**draw his glyph
281      *@param g graphic context in which the glyph should be drawn 
282      *@param vW associated view width (used to determine if border should be drawn)
283      *@param vH associated view height (used to determine if border should be drawn)
284      * right now only VRectangle and VRectangleOr(/Or=0) use this
285      *@param i camera index in the virtual space
286      */
287     public abstract void draw(Graphics2D g,int vW,int vH,int i,Stroke stdS,AffineTransform stdT);
288 
289     /**project shape in camera coord sys prior to actual painting*/
290     public abstract void project(Camera c,ViewPanel v);
291 
292     /**relative translation (offset)*/
293     public void move(long x,long y){
294   vx+=x;
295   vy+=y;
296   propagateMove(x,y);  //take care of sticked glyphs
297   try{vsm.repaintNow();}catch(NullPointerException e){/*System.err.println("VSM null in Glyph "+e);*/}
298   //try{vsm.constMgr.suggestAPos(this.ID,vx,vy);}catch(NullPointerException e){/*System.err.println("VSM null in Glyph "+e);*/}
299     }
300 
301     /**absolute translation*/
302     public void moveTo(long x,long y){
303   propagateMove(x-vx,y-vy);  //take care of sticked glyphs
304   vx=x;
305   vy=y;
306   try{vsm.repaintNow();}catch(NullPointerException e){/*System.err.println("VSM null in Glyph "+e);*/}
307   //try{vsm.constMgr.suggestAPos(this.ID,vx,vy);}catch(NullPointerException e){/*System.err.println("VSM null in Glyph "+e);*/}
308     }
309 
310     /**absolute translation DO NOT SUGGEST NEW VALUE TO SOLVER*/
311 //     public void moveToNS(long x,long y){
312 //   propagateMove(x-vx,y-vy);  //take care of sticked glyphs
313 //   vx=x;
314 //   vy=y;
315 //     }
316 
317     /**propagate this glyph's movement to all glyphs constrained by this one (pos)*/
318     public void propagateMove(long x,long y){
319   if (stickedGlyphs!=null){
320       for (Enumeration e=stickedGlyphs.elements();e.hasMoreElements();){
321     ((Glyph)(e.nextElement())).move(x,y);
322       }
323   }
324     }
325 
326     /**get size of object (radius of bounding circle)*/
327     public abstract float getSize();    
328 
329     /**set size of object by setting its bounding circle's radius*/
330     public abstract void sizeTo(float radius);
331 
332     /**multiply bounding circle radius by factor*/
333     public abstract void reSize(float factor);
334 
335     /**set size of object by setting its bounding circle's radius*/
336 //     public abstract void sizeToNS(float radius);
337 
338     /**get orientation*/
339     public abstract float getOrient();
340 
341     /**set absolute orientation*/
342     public abstract void orientTo(float angle);
343 
344     /**set absolute orientation*/
345 //     public abstract void orientToNS(float angle);
346 
347     /**called when glyph is created in order to create the initial set of projected coordinates wrt the number of cameras in the space
348      *@param nbCam current number of cameras in the virtual space
349      */
350     public abstract void initCams(int nbCam);
351 
352     /**used internally to create new projected coordinates to use with the new camera
353      *@param verifIndex camera index, just to be sure that the number of projected coordinates is consistent with the number of cameras
354      */
355     public abstract void addCamera(int verifIndex);
356 
357     /**if a camera is removed from the virtual space, we should delete the corresponding projected coordinates, but do not modify the array it self because we do not want to change other cameras' index - just point to null*/
358     public abstract void removeCamera(int index);
359 
360     /**detects whether the given point is inside this glyph or not 
361      *@param x EXPECTS PROJECTED JPanel COORDINATE
362      *@param y EXPECTS PROJECTED JPanel COORDINATE
363      */
364     public abstract boolean coordInside(int x,int y,int camIndex);
365 
366     /**reset prevMouseIn for projected coordinates nb i*/
367     public abstract void resetMouseIn(int i);
368     
369     /**used to find out if it is necessary to project and draw the glyph in the current view*/
370     public boolean drawMe(long w1,long h1,long w2,long h2,int i){//i should be the camera's index (used only by some glyph classes redefining this method)
371   if ((vx>=w2) && (vx<=w1) && (vy>=h2) && (vy<=h1)){ //if glyph hotspot is in the region, it is obviously visible
372       return true;
373   }
374   else {
375       if (((vx-size)<=w1) && ((vx+size)>=w2) && ((vy-size)<=h1) && ((vy+size)>=h2)){
376     //if glyph is at least partially in region (we approximate using the glyph
377     // bounding circle, meaning that some glyphs not actually visible can 
378     return true;  //be projected and drawn  (but they won't be displayed))
379       } 
380       else return false;   //otherwise the glyph is not visible
381   }
382     }
383 
384     /**used to find out if glyph completely fills the view (in which case it is not necessary to repaint objects at a lower altitude)*/
385     public abstract boolean fillsView(long w,long h,int camIndex);
386 
387     /**returns 1 if mouse has entered the glyph, -1 if it has exited the glyph, 0 if nothing has changed (meaning it was already inside or outside it)*/
388     public abstract int mouseInOut(int x,int y,int camIndex);
389 
390     /**used by glyph constructor to initialize color*/
391     public void setColor(Color c){
392   color=c;
393   HSV=Color.RGBtoHSB(c.getRed(),c.getGreen(),c.getBlue(),(new float[3]));
394   try{vsm.repaintNow();}catch(NullPointerException e){/*System.err.println("VSM null in Glyph "+e);*/}
395     }
396 
397     /**used by glyph constructor to initialize color*/
398     public void setBorderColor(Color c){
399   borderColor=c;
400   HSVb=Color.RGBtoHSB(borderColor.getRed(),borderColor.getGreen(),borderColor.getBlue(),(new float[3]));
401   bColor=borderColor;
402   try{vsm.repaintNow();}catch(NullPointerException e){/*System.err.println("VSM null in Glyph "+e);*/}
403     }
404 
405     /**set absolute fill color in HSV coord sys*/
406     public void setHSVColor(float h,float s,float v){ //color  [0.0,1.0]
407   HSV[0]=h;
408   if (HSV[0]>1) {HSV[0]=1.0f;} else {if (HSV[0]<0) {HSV[0]=0;}}
409   HSV[1]=s;
410   if (HSV[1]>1) {HSV[1]=1.0f;} else {if (HSV[1]<0) {HSV[1]=0;}}
411   HSV[2]=v;
412   if (HSV[2]>1) {HSV[2]=1.0f;} else {if (HSV[2]<0) {HSV[2]=0;}}
413   this.color=Color.getHSBColor(HSV[0],HSV[1],HSV[2]);
414   try{/*vsm.constMgr.suggestAColor(this.ID,HSV[0],HSV[1],HSV[2]);*/vsm.repaintNow();}catch(NullPointerException e){}
415     }
416 
417 //     /**set absolute fill color in HSV coord sys*/
418 //     public void setHSVColorNS(float h,float s,float v){ //color  [0.0,1.0]
419 //   HSV[0]=h;
420 //   if (HSV[0]>1) {HSV[0]=1.0f;} else {if (HSV[0]<0) {HSV[0]=0;}}
421 //   HSV[1]=s;
422 //   if (HSV[1]>1) {HSV[1]=1.0f;} else {if (HSV[1]<0) {HSV[1]=0;}}
423 //   HSV[2]=v;
424 //   if (HSV[2]>1) {HSV[2]=1.0f;} else {if (HSV[2]<0) {HSV[2]=0;}}
425 //   this.color=Color.getHSBColor(HSV[0],HSV[1],HSV[2]);
426 //   try{vsm.repaintNow();}catch(NullPointerException e){}
427 //     }
428 
429     /**set relative fill color in HSV coord sys*/
430     public void addHSVColor(float h,float s,float v){ //color  [-1.0,1.0]
431   HSV[0]=HSV[0]+h;
432   if (HSV[0]>1) {HSV[0]=1.0f;} else {if (HSV[0]<0) {HSV[0]=0;}}
433   HSV[1]=HSV[1]+s;
434   if (HSV[1]>1) {HSV[1]=1.0f;} else {if (HSV[1]<0) {HSV[1]=0;}}
435   HSV[2]=HSV[2]+v;
436   if (HSV[2]>1) {HSV[2]=1.0f;} else {if (HSV[2]<0) {HSV[2]=0;}}
437   this.color=Color.getHSBColor(HSV[0],HSV[1],HSV[2]);
438   try{/*vsm.constMgr.suggestAColor(this.ID,HSV[0],HSV[1],HSV[2]);*/vsm.repaintNow();}catch(NullPointerException e){}
439     }
440 
441     /**set absolute border color in HSV coord sys*/
442     public void setHSVbColor(float h,float s,float v){//color  [0.0,1.0]
443   HSVb[0]=h;
444   if (HSVb[0]>1) {HSVb[0]=1.0f;} else {if (HSVb[0]<0) {HSVb[0]=0;}}
445   HSVb[1]=s;
446   if (HSVb[1]>1) {HSVb[1]=1.0f;} else {if (HSVb[1]<0) {HSVb[1]=0;}}
447   HSVb[2]=v;
448   if (HSVb[2]>1) {HSVb[2]=1.0f;} else {if (HSVb[2]<0) {HSVb[2]=0;}}
449   this.borderColor=Color.getHSBColor(HSVb[0],HSVb[1],HSVb[2]);
450   this.bColor=this.borderColor;
451   try{vsm.repaintNow();}catch(NullPointerException e){}
452     }
453     
454     /**set relative border color in HSV coord sys*/
455     public void addHSVbColor(float h,float s,float v){//color  [-1.0,1.0]
456   HSVb[0]=HSVb[0]+h;
457   if (HSVb[0]>1) {HSVb[0]=1.0f;} else {if (HSVb[0]<0) {HSVb[0]=0;}}
458   HSVb[1]=HSVb[1]+s;
459   if (HSVb[1]>1) {HSVb[1]=1.0f;} else {if (HSVb[1]<0) {HSVb[1]=0;}}
460   HSVb[2]=HSVb[2]+v;
461   if (HSVb[2]>1) {HSVb[2]=1.0f;} else {if (HSVb[2]<0) {HSVb[2]=0;}}
462   this.borderColor=Color.getHSBColor(HSVb[0],HSVb[1],HSVb[2]);
463   this.bColor=this.borderColor;
464   try{vsm.repaintNow();}catch(NullPointerException e){}
465     }
466 
467     /**get fill color*/
468     public float[] getHSVColor(){    //color  [0.0-1.0]
469   return this.HSV;
470     }
471 
472     /**get border color*/
473     public float[] getHSVbColor(){   //border color [0.0-1.0]
474   return this.HSVb;
475     }
476 
477     /**get fill color as an object*/
478     public Color getColor(){
479   return this.color;
480     }
481 
482     /**get border color as an object*/
483     public Color getColorb(){
484   return this.borderColor;
485     }
486 
487     /**get text associated with this glyph*/
488     public String getText(){return text;}
489 
490     /**set text that should be painted with this glyph*/
491     public void setText(String t){
492   text=t;
493   try{vsm.repaintNow();}catch(NullPointerException e){/*System.err.println("VSM null in Glyph "+e);*/}
494     }
495 
496     /**change font for this specific text object - f=null to get back to default font*/
497     public void setSpecialFont(Font f){
498   if (f!=null){font=f;fontSize=font.getSize2D();}else{font=null;fontSize=VirtualSpaceManager.getMainFont().getSize2D();}
499   try{vsm.repaintNow();}catch(NullPointerException e){/*System.err.println("VSM null in Glyph "+e);*/}
500     }
501 
502     /**returns the font used for this glyph's text*/
503     public Font getFont(){
504   if (font!=null){return font;}
505   else return VirtualSpaceManager.getMainFont();
506     }
507 
508     /**tells whether this glyph is using a special font or not (note: using a special font does not necessarily means that this font is different from the default font (although it should, but this is at programer's prerogative))*/
509     public boolean usesSpecialFont(){
510   if (font==null){return false;}
511   else {return true;}
512     }
513 
514     /**
515      *set the font size display policy
516      *@param policy 1=always draw text 0=draw text when approx fits inside object -1=never draw text 2=shrink text
517      */
518     public void setFontSizePolicy(int policy){
519   this.fontSizePolicy=policy; //1=always draw text ; 0=draw text when approx fits inside object ; -1=never draw text ; 2=shrink text
520   if ((this.fontSizePolicy<(-1)) || (this.fontSizePolicy>2)){this.fontSizePolicy=1;}
521   try {vsm.repaintNow();}catch(NullPointerException e){/*System.err.println("VSM null in Glyph "+e);*/}
522     }
523 
524     /**
525      *
526      *@param p -1=text is drawn under glyph ; 0=text is drawn inside glyph ; 1=text is drawn on top of glyph
527      */
528     public void setTextPos(int p){
529   this.textPos=p;
530   try{vsm.repaintNow();}catch(NullPointerException e){/*System.err.println("VSM null in Glyph "+e);*/}
531     }
532 
533     /**get glyph ID*/
534     public Long getID(){
535   return ID;
536     }
537 
538     /**set glyph ID (make sure there is no conflict)*/
539     public void setID(Long ident){
540   ID=ident;
541     }
542 
543     /**get object this glyph represents*/
544     public Object getOwner(){
545   return owner;
546     }
547    
548     /**associate an application object with this glyph*/
549     public void setOwner(Object o){
550   this.owner=o;
551     }
552 
553     /**get glyph type*/
554     public String getType(){
555   return type;
556     }
557    
558     /**
559      *set glyph type
560      *@param t any string
561      */
562     public void setType(String t){
563   this.type=t;
564     }
565 
566 
567     /**set a ref to the virtual space manager*/
568     public void setVSM(VirtualSpaceManager v){this.vsm=v;}
569 
570     /**
571      *attach glyph to this one
572      *@param g glyph to be attached to this one
573      */
574     public void stick(Glyph g){
575   if (stickedGlyphs==null){
576       stickedGlyphs=new Vector();
577       stickedGlyphs.add(g);
578       g.stickedTo=this;
579   }
580   else {
581       if (!stickedGlyphs.contains(g)){
582     stickedGlyphs.add(g);
583     g.stickedTo=this;
584       }
585       else {
586     if (this.vsm.debugModeON()){System.err.println("Warning: trying to stick Glyph "+g+" to Glyph "+this+" while they are already sticked.");}
587       }
588   }
589     }
590 
591     /**
592      *detach glyph from this one
593      *@param g glyph to be detached
594      */
595     public void unstick(Glyph g){
596   if (stickedGlyphs!=null){
597       stickedGlyphs.remove(g);
598       if (stickedGlyphs.isEmpty()){stickedGlyphs=null;}
599       g.stickedTo=null;
600   }
601     }
602 
603     /**
604      * return the list of glyphs sticked to this one (empty vector if none)
605      */
606     public Vector getStickedGlyphs(){
607   if (stickedGlyphs==null){return new Vector();}
608   else return stickedGlyphs;
609     }
610 
611     /***returns coordinates of the glyph's geom center as a LongPoint*/
612     public LongPoint getLocation(){return new LongPoint(vx,vy);}
613 
614     /**
615      * returns a String with ID, position, and altitude
616      */
617     public String toString(){
618   return new String(super.toString()+" Glyph ID "+ID+" pos ("+vx+","+vy+","+vz+") "+type);
619     }
620 
621     public abstract Object clone();
622 
623 }