Source code: com/xerox/VTM/engine/VirtualSpaceManager.java
1 /* FILE: VirtualSpaceManager.java
2 * DATE OF CREATION: Jul 11 2000
3 * AUTHOR : Emmanuel Pietriga (emmanuel.pietriga@xrce.xerox.com)
4 * MODIF: Wed Jul 23 15:25:29 2003 by Emmanuel Pietriga (emmanuel@w3.org, emmanuel@claribole.net)
5 * Copyright (c) Xerox Corporation, XRCE/Contextual Computing, 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.engine;
21
22 import java.util.Vector;
23 import java.util.Hashtable;
24 import java.util.Enumeration;
25 import java.awt.Color;
26 import java.awt.Font;
27 import java.awt.Point;
28 import javax.swing.*;
29 import com.xerox.VTM.engine.*;
30 import com.xerox.VTM.glyphs.*;
31 import net.claribole.zvtm.glyphs.CGlyph;
32 import net.claribole.zvtm.engine.Location;
33 // import EDU.Washington.grad.gjb.cassowary.*;
34
35 /**
36 * Virtual space manager - VTM root class - virtual space management (camera, glyphs,...) is done here - primary interface to application. This is the main class to instantiate.
37 * @author Emmanuel Pietriga
38 **/
39
40 public class VirtualSpaceManager implements java.awt.event.AWTEventListener {
41
42 static Font mainFont=new Font("Dialog",0,10);
43
44 public static Font getMainFont(){return mainFont;}
45
46 public void setMainFont(Font f){
47 mainFont=f;
48 for (Enumeration e=allViews.elements();e.hasMoreElements();){((View)e.nextElement()).updateFont();}
49 Object g;
50 for (Enumeration e=allGlyphs.elements();e.hasMoreElements();){
51 g=e.nextElement();
52 if (g instanceof VText){((VText)g).invalidate();}
53 }
54 repaintNow();
55 }
56
57 /**select only mouse sensitive and visible glyphs*/
58 public static short VIS_AND_SENS_GLYPHS=0;
59 /**select only visible glyphs*/
60 public static short VISIBLE_GLYPHS=1;
61 /**select only mouse sensitive glyphs*/
62 public static short SENSITIVE_GLYPHS=2;
63 /**select all glyphs in the region*/
64 public static short ALL_GLYPHS=3;
65
66 /**print exceptions*/
67 boolean debug=false;
68
69 /**next glyph will have ID...*/
70 private long nextID;
71 /**next camera will have ID...*/
72 private int nextcID;
73 /**next cursor will have ID...*/
74 private int nextmID;
75
76 /**key is glyph ID (Long)*/
77 protected Hashtable allGlyphs;
78 /**key is camera ID (Integer)*/
79 protected Hashtable allCameras;
80 /**key is space name (String)*/
81 protected Hashtable allVirtualSpaces;
82 /**key is view name (String)*/
83 protected Hashtable allViews;
84
85 /**current view*/
86 public View activeView;
87
88 /**default policy for view repainting - true means all views are repainted even if ((not active) or (mouse not inside the view)) - false means only the active view and the view in which the mouse is currently located (if different) are repainted - default is true*/
89 boolean generalRepaintPolicy=true;
90
91 /**enables detection of multiple full fills in one view repaint - default value assigned to new views - STILL VERY BUGGY - ONLY SUPPORTS VRectangle and VCircle for now*/
92 boolean defaultMultiFill=false;
93
94 /**value under which a VText is drawn as a point instead of a text (considered too small to be read). Default is 0.5 - if you raise this value, text that was still displayed as a string will be displayed as a segment and inversely - of course, displaying a line instead of applying affine transformations to strings is faster*/
95 float textAsLineCoef=0.5f;
96
97 /**sync mouse cursor and mouse glyph*/
98 public boolean mouseSync;
99
100 /**Animation Manager*/
101 public AnimManager animator;
102
103 /**allow negative camera altitudes (zoom beyond the standard size=magnification)*/
104 protected int zoomFloor=0;
105
106 /**Constraint Manager*/
107 // public ConstraintManager constMgr;
108
109 Color selectColor=Color.yellow;
110 Color mouseInsideColor=Color.white;
111
112 /**
113 * Only for use with stand-alone Java applications (use other constructor with applet=true if running inside a JApplet)
114 */
115 public VirtualSpaceManager(){
116 if (debug){System.out.println("Debug mode ON");}
117 nextID=1;
118 nextcID=1;
119 nextmID=1;
120 allGlyphs=new Hashtable();
121 allCameras=new Hashtable();
122 allVirtualSpaces=new Hashtable();
123 allViews=new Hashtable();
124 animator=new AnimManager(this); //started only when a view is created
125 // constMgr=new ConstraintManager(this);
126 mouseSync=true;
127 java.awt.Toolkit.getDefaultToolkit().addAWTEventListener(this,java.awt.AWTEvent.WINDOW_EVENT_MASK);
128 }
129
130 /**
131 * Set applet to true if you are calling ZVTM from inside an Applet
132 */
133 public VirtualSpaceManager(boolean applet){
134 if (debug){System.out.println("Debug mode ON");}
135 nextID=1;
136 nextcID=1;
137 nextmID=1;
138 allGlyphs=new Hashtable();
139 allCameras=new Hashtable();
140 allVirtualSpaces=new Hashtable();
141 allViews=new Hashtable();
142 animator=new AnimManager(this); //started only when a view is created
143 // constMgr=new ConstraintManager(this);
144 mouseSync=true;
145 if (!applet){java.awt.Toolkit.getDefaultToolkit().addAWTEventListener(this,java.awt.AWTEvent.WINDOW_EVENT_MASK);}
146 }
147
148 /**set debug mode ON or OFF*/
149 public void setDebug(boolean b){
150 debug=b;
151 }
152
153 /**get debug mode state (ON or OFF)*/
154 public boolean debugModeON(){return debug;}
155
156 /**set policy for view repainting - true means all views are repainted even if ((not active) or (mouse not inside the view)) - policy is forwarded to all existing views (no matter its current policy) and will be applied to future ones (but it can be changed for each single view)*/
157 public void setRepaintPolicy(boolean b){
158 if (b!=generalRepaintPolicy){
159 generalRepaintPolicy=b;
160 for (Enumeration e=allViews.elements();e.hasMoreElements();){
161 ((View)e.nextElement()).setRepaintPolicy(generalRepaintPolicy);
162 }
163 }
164 }
165
166 /**get general policy for view repainting (this is the current default policy, but this does not guarantee that all views comply with it since the policy may be changed for each single view)*/
167 public boolean getRepaintPolicy(){return generalRepaintPolicy;}
168
169 /**enable/disable detection of multiple full fills in one view repaint - default value assigned to new views - default is false */
170 public void setDefaultMultiFills(boolean b){
171 defaultMultiFill=b;
172 }
173
174 /**get state of detection of multiple full fills in one view repaint - default value assigned to new views */
175 public boolean getDefaultMultiFills(){
176 return defaultMultiFill;
177 }
178
179 /**
180 * set a zoom-in limit/maximum magnification (like a floor the camera cannot go through)<br>
181 * value 0 means that, at maximum magnification, the size of observed glyphs corresponds to their <i>real</i> size (e.g. if a circle has a declared radius of 50 in the virtual space, then its radius at max magnification is 50)<br>
182 * if the floor is set to a negative value, you will be able to zoom in further (meaning that you will be able to magnify objects beyond their declared size)<br>
183 * Note: there is no limit for zoom out (no so-called ceiling)
184 *@param a the altitude of the floor - the default value is 0 (put a negative value if you want to be able to magnify objects beyond their normal size)
185 */
186 public void setZoomLimit(int a){
187 zoomFloor=a;
188 }
189
190 /**
191 * get the zoom-in limit/maximum magnification (like a floor the camera cannot go through)<br>
192 * default value 0 means that, at maximum magnification, the size of observed glyphs corresponds to their <i>real</i> size (e.g. if a circle has a declared radius of 50 in the virtual space, then its radius at max magnification is 50)<br>
193 * if the floor is set to a negative value, you will be able to zoom in further (meaning that you will be able to magnify objects beyond their declared size)<br>
194 * Note: there is no limit for zoom out (no so-called ceiling)
195 */
196 public int getZoomLimit(){
197 return zoomFloor;
198 }
199
200 /**true -> sync mouse cursor and mouse glyph*/
201 public void setMouseSync(boolean b){
202 mouseSync=b;
203 activeView.mouse.setSync(mouseSync);
204 }
205
206 /**set border color of selected glyphs (not propagated to existing glyphs)*/
207 public void setSelectedGlyphColor(Color c){
208 selectColor=c;
209 }
210
211 /**set border color of glyphs overlapped by mouse (not propagated to existing glyphs)*/
212 public void setMouseInsideGlyphColor(Color c){
213 mouseInsideColor=c;
214 }
215
216 /**add glyph g to virtual space whose name is vs*/
217 public Glyph addGlyph(Glyph g,String vs){
218 if (g!=null){
219 if (allVirtualSpaces.containsKey(vs)){
220 VirtualSpace tvs=(VirtualSpace)allVirtualSpaces.get(vs);
221 tvs.addGlyph(g);
222 g.setID(new Long(nextID++));
223 g.setVSM(this);
224 g.setSelectedColor(this.selectColor);
225 g.setMouseInsideColor(this.mouseInsideColor);
226 allGlyphs.put(g.getID(),g);
227 repaintNow();
228 return g;
229 }
230 else {System.err.println("ZVTM Error:VirtualSpaceManager:addGlyph:unknown virtual space: "+vs);return null;}
231 }
232 else {System.err.println("ZVTM Error:VirtualSpaceManager:addGlyph:attempting to add a null Glyph in space: "+vs);return null;}
233 }
234
235 /**add composite glyph c to virtual space whose name is vs*/
236 public CGlyph addCGlyph(CGlyph c,String vs){
237 if (c!=null){
238 if (allVirtualSpaces.containsKey(vs)){
239 c.setID(new Long(nextID++));
240 c.setVSM(this);
241 allGlyphs.put(c.getID(),c);
242 return c;
243 }
244 else {System.err.println("Error:VirtualSpaceManager:addCGlyph:unknown virtual space: "+vs);return null;}
245 }
246 else {System.err.println("Error:VirtualSpaceManager:addCGlyph:attempting to add a null composite glyph in space: "+vs);return null;}
247 }
248
249 /**get glyph with ID id*/
250 public Glyph getGlyph(Long id){
251 return (Glyph)(allGlyphs.get(id));
252 }
253
254 /** returns a vector of glyphs whose hotspot is in region delimited by rectangle (x1,y1,x2,y2) in virtual space vs (returns null if empty). Coordinates of the mouse cursor in virtual space are available in instance variables vx and vy of class VCursor. The selection rectangle can be drawn on screen by using ViewPanel.setDrawRect(true) (e.g. call when mouse button is pressed)/ViewPanel.setDrawRect(false) (e.g. call when mouse button is released)
255 *@param x1 x coord of first point
256 *@param y1 y coord of first point
257 *@param x2 x coord of opposite point
258 *@param y2 y coord of opposite point
259 *@param vsn name of virtual space
260 *@param wg which glyphs in the region should be returned (among VIS_AND_SENS_GLYPHS (default), VISIBLE_GLYPHS, SENSIBLE_GLYPHS, ALL_GLYPHS)
261 */
262 public Vector getGlyphsInRegion(long x1,long y1,long x2,long y2,String vsn,int wg){
263 Vector res=new Vector();
264 VirtualSpace vs=getVirtualSpace(vsn);
265 long minX=Math.min(x1,x2);
266 long minY=Math.min(y1,y2);
267 long maxX=Math.max(x1,x2);
268 long maxY=Math.max(y1,y2);
269 if (vs!=null){
270 Vector allG=vs.getAllGlyphs();
271 Glyph g;
272 for (int i=0;i<allG.size();i++){
273 g=(Glyph)allG.elementAt(i);
274 if ((g.vx>=minX) && (g.vy>=minY) && (g.vx<=maxX) && (g.vy<=maxY)){
275 if ((wg==VIS_AND_SENS_GLYPHS) && g.isSensitive() && g.isVisible()){res.add(g);}
276 else if ((wg==VISIBLE_GLYPHS) && g.isVisible()){res.add(g);}
277 else if ((wg==SENSITIVE_GLYPHS) && g.isSensitive()){res.add(g);}
278 else if (wg==ALL_GLYPHS){res.add(g);}
279 }
280 }
281 }
282 if (res.isEmpty()){res=null;}
283 return res;
284 }
285
286 /**destroy all glyphs in space whose name is spaceName*/
287 public void destroyGlyphsInSpace(String spaceName){
288 VirtualSpace vs=getVirtualSpace(spaceName);
289 Glyph g;
290 Vector entClone=(Vector)vs.getAllGlyphs().clone();
291 for (Enumeration e=entClone.elements();e.hasMoreElements();){
292 g=(Glyph)(e.nextElement());
293 vs.destroyGlyph(g);
294 allGlyphs.remove(g);
295 }
296 repaintNow();
297 }
298
299 /**add camera to space whose name is vs
300 *@param vs owning virtual space
301 */
302 public Camera addCamera(String vs){
303 VirtualSpace tvs=(VirtualSpace)allVirtualSpaces.get(vs);
304 Camera c=tvs.createCamera();
305 c.setID(new Integer(nextcID++));
306 allCameras.put(c.getID(),c);
307 return c;
308 }
309
310 /**
311 *add camera to space whose name is vs
312 *@param vs owning virtual space
313 *@param lazy true if this is to be a lazy camera (false otherwise)
314 */
315 public Camera addCamera(String vs,boolean lazy){
316 VirtualSpace tvs=(VirtualSpace)allVirtualSpaces.get(vs);
317 Camera c=tvs.createCamera();
318 c.setLaziness(lazy);
319 c.setID(new Integer(nextcID++));
320 allCameras.put(c.getID(),c);
321 return c;
322 }
323
324 /**get camera whose ID is id*/
325 public Camera getCamera(Integer id){
326 return (Camera)(allCameras.get(id));
327 }
328
329 /**get active camera*/
330 public Camera getActiveCamera(){
331 return activeView.getActiveCamera();
332 }
333
334 /**create a new view - old method
335 *@param c vector of cameras superimposed in this view
336 *@param name view name
337 *@param w width of window in pixels
338 *@param h height of window in pixels
339 *@param bar true -> add a status bar to this view (below main panel)
340 *@param visible should the view be made visible automatically or not
341 */
342 public View addView(Vector c,String name,int w,int h,boolean bar,boolean visible){
343 EView tvi=new EView(c,name,w,h,bar,visible,this);
344 tvi.mouse.setID(new Long(nextmID++));
345 allViews.put(name,tvi);
346 tvi.setRepaintPolicy(generalRepaintPolicy);
347 if (!animator.started){animator.start();} //start animator only when a view is created
348 return tvi;
349 }
350
351 /**create a new accelerated view - old method
352 *@param c vector of cameras superimposed in this view
353 *@param name view name
354 *@param w width of window in pixels
355 *@param h height of window in pixels
356 *@param bar true -> add a status bar to this view (below main panel)
357 *@param visible should the view be made visible automatically or not
358 */
359 public View addAccView(Vector c,String name,int w,int h,boolean bar,boolean visible){
360 AccEView tvi=new AccEView(c,name,w,h,bar,visible,this);
361 tvi.mouse.setID(new Long(nextmID++));
362 allViews.put(name,tvi);
363 tvi.setRepaintPolicy(generalRepaintPolicy);
364 if (!animator.started){animator.start();} //start animator only when a view is created
365 return tvi;
366 }
367
368 /**create a new view - old method
369 *@param c vector of cameras superimposed in this view
370 *@param name view name
371 *@param w width of window in pixels
372 *@param h height of window in pixels
373 *@param bar true -> add a status bar to this view (below main panel)
374 *@param mnb a menu bar, already configured with actionListeners already attached to items (it is just added to the view)
375 *@param visible should the view be made visible automatically or not
376 */
377 public View addView(Vector c,String name,int w,int h,boolean bar,boolean visible,JMenuBar mnb){
378 EView tvi=new EView(c,name,w,h,bar,visible,this,mnb);
379 tvi.mouse.setID(new Long(nextmID++));
380 allViews.put(name,tvi);
381 tvi.setRepaintPolicy(generalRepaintPolicy);
382 if (!animator.started){animator.start();} //start animator only when a view is created
383 return tvi;
384 }
385
386 /**create a new accelerated view - old method
387 *@param c vector of cameras superimposed in this view
388 *@param name view name
389 *@param w width of window in pixels
390 *@param h height of window in pixels
391 *@param bar true -> add a status bar to this view (below main panel)
392 *@param mnb a menu bar, already configured with actionListeners already attached to items (it is just added to the view)
393 *@param visible should the view be made visible automatically or not
394 */
395 public View addAccView(Vector c,String name,int w,int h,boolean bar,boolean visible,JMenuBar mnb){
396 AccEView tvi=new AccEView(c,name,w,h,bar,visible,this,mnb);
397 tvi.mouse.setID(new Long(nextmID++));
398 allViews.put(name,tvi);
399 tvi.setRepaintPolicy(generalRepaintPolicy);
400 if (!animator.started){animator.start();} //start animator only when a view is created
401 return tvi;
402 }
403
404 /**create a new external view
405 *@param c vector of cameras superimposed in this view
406 *@param name view name
407 *@param w width of window in pixels
408 *@param h height of window in pixels
409 *@param bar true -> add a status bar to this view (below main panel)
410 *@param visible should the view be made visible automatically or not
411 */
412 public EView addExternalView(Vector c,String name,int w,int h,boolean bar,boolean visible){
413 EView tvi=new EView(c,name,w,h,bar,visible,this);
414 tvi.mouse.setID(new Long(nextmID++));
415 allViews.put(name,tvi);
416 tvi.setRepaintPolicy(generalRepaintPolicy);
417 if (!animator.started){animator.start();} //start animator only when a view is created
418 return tvi;
419 }
420
421 /**create a new external accelerated view
422 *@param c vector of cameras superimposed in this view
423 *@param name view name
424 *@param w width of window in pixels
425 *@param h height of window in pixels
426 *@param bar true -> add a status bar to this view (below main panel)
427 *@param visible should the view be made visible automatically or not
428 */
429 public AccEView addExternalAccView(Vector c,String name,int w,int h,boolean bar,boolean visible){
430 AccEView tvi=new AccEView(c,name,w,h,bar,visible,this);
431 tvi.mouse.setID(new Long(nextmID++));
432 allViews.put(name,tvi);
433 tvi.setRepaintPolicy(generalRepaintPolicy);
434 if (!animator.started){animator.start();} //start animator only when a view is created
435 return tvi;
436 }
437
438 /**create a new external view
439 *@param c vector of cameras superimposed in this view
440 *@param name view name
441 *@param w width of window in pixels
442 *@param h height of window in pixels
443 *@param bar true -> add a status bar to this view (below main panel)
444 *@param mnb a menu bar, already configured with actionListeners already attached to items (it is just added to the view)
445 *@param visible should the view be made visible automatically or not
446 */
447 public EView addExternalView(Vector c,String name,int w,int h,boolean bar,boolean visible,JMenuBar mnb){
448 EView tvi=new EView(c,name,w,h,bar,visible,this,mnb);
449 tvi.mouse.setID(new Long(nextmID++));
450 allViews.put(name,tvi);
451 tvi.setRepaintPolicy(generalRepaintPolicy);
452 if (!animator.started){animator.start();} //start animator only when a view is created
453 return tvi;
454 }
455
456 /**create a new external accelerated view
457 *@param c vector of cameras superimposed in this view
458 *@param name view name
459 *@param w width of window in pixels
460 *@param h height of window in pixels
461 *@param bar true -> add a status bar to this view (below main panel)
462 *@param mnb a menu bar, already configured with actionListeners already attached to items (it is just added to the view)
463 *@param visible should the view be made visible automatically or not
464 */
465 public AccEView addExternalAccView(Vector c,String name,int w,int h,boolean bar,boolean visible,JMenuBar mnb){
466 AccEView tvi=new AccEView(c,name,w,h,bar,visible,this,mnb);
467 tvi.mouse.setID(new Long(nextmID++));
468 allViews.put(name,tvi);
469 tvi.setRepaintPolicy(generalRepaintPolicy);
470 if (!animator.started){animator.start();} //start animator only when a view is created
471 return tvi;
472 }
473
474 /**create a new internal view
475 *@param c vector of cameras superimposed in this view
476 *@param name view name
477 *@param w width of window in pixels
478 *@param h height of window in pixels
479 *@param bar true -> add a status bar to this view (below main panel)
480 *@param visible should the view be made visible automatically or not
481 *@param desktop parent desktop pane
482 *@param layer layer number in the JDesktopPane (ivc) - put 1 if you don't care
483 */
484 public IView addInternalView(Vector c,String name,int w,int h,boolean bar,boolean visible,IViewContainer ivc,Integer layer){
485 IView tvi=new IView(c,name,w,h,bar,visible,this,ivc,layer);
486 tvi.mouse.setID(new Long(nextmID++));
487 allViews.put(name,tvi);
488 tvi.setRepaintPolicy(generalRepaintPolicy);
489 if (!animator.started){animator.start();} //start animator only when a view is created
490 return tvi;
491 }
492
493 /**create a new internal accelerated view
494 *@param c vector of cameras superimposed in this view
495 *@param name view name
496 *@param w width of window in pixels
497 *@param h height of window in pixels
498 *@param bar true -> add a status bar to this view (below main panel)
499 *@param visible should the view be made visible automatically or not
500 *@param desktop parent desktop pane
501 *@param layer layer number in the JDesktopPane (ivc) - put 1 if you don't care
502 */
503 public AccIView addInternalAccView(Vector c,String name,int w,int h,boolean bar,boolean visible,IViewContainer ivc,Integer layer){
504 AccIView tvi=new AccIView(c,name,w,h,bar,visible,this,ivc,layer);
505 tvi.mouse.setID(new Long(nextmID++));
506 allViews.put(name,tvi);
507 tvi.setRepaintPolicy(generalRepaintPolicy);
508 if (!animator.started){animator.start();} //start animator only when a view is created
509 return tvi;
510 }
511
512 /**create a new internal view
513 *@param c vector of cameras superimposed in this view
514 *@param name view name
515 *@param w width of window in pixels
516 *@param h height of window in pixels
517 *@param bar true -> add a status bar to this view (below main panel)
518 *@param desktop parent desktop pane
519 *@param mnb a menu bar, already configured with actionListeners already attached to items (it is just added to the view)
520 *@param visible should the view be made visible automatically or not
521 *@param layer layer number in the JDesktopPane (ivc) - put 1 if you don't care
522 */
523 public IView addInternalView(Vector c,String name,int w,int h,boolean bar,boolean visible,JMenuBar mnb,IViewContainer ivc,Integer layer){
524 IView tvi=new IView(c,name,w,h,bar,visible,this,ivc,mnb,layer);
525 tvi.mouse.setID(new Long(nextmID++));
526 allViews.put(name,tvi);
527 tvi.setRepaintPolicy(generalRepaintPolicy);
528 if (!animator.started){animator.start();} //start animator only when a view is created
529 return tvi;
530 }
531
532 /**create a new internal accelerated view
533 *@param c vector of cameras superimposed in this view
534 *@param name view name
535 *@param w width of window in pixels
536 *@param h height of window in pixels
537 *@param bar true -> add a status bar to this view (below main panel)
538 *@param desktop parent desktop pane
539 *@param mnb a menu bar, already configured with actionListeners already attached to items (it is just added to the view)
540 *@param visible should the view be made visible automatically or not
541 *@param layer layer number in the JDesktopPane (ivc) - put 1 if you don't care
542 */
543 public AccIView addInternalAccView(Vector c,String name,int w,int h,boolean bar,boolean visible,JMenuBar mnb,IViewContainer ivc,Integer layer){
544 AccIView tvi=new AccIView(c,name,w,h,bar,visible,this,ivc,mnb,layer);
545 tvi.mouse.setID(new Long(nextmID++));
546 allViews.put(name,tvi);
547 tvi.setRepaintPolicy(generalRepaintPolicy);
548 if (!animator.started){animator.start();} //start animator only when a view is created
549 return tvi;
550 }
551
552 /**create a JFrame container for IViews - required parameter in IView constructor
553 *@param name title of the JFrame
554 *@param w width of the main JFrame (0 for max width and height)
555 *@param h height of the main JFrame (0 for max width and height)
556 */
557 public IViewContainer createIViewContainer(String name,int w,int h){
558 IViewContainer ivc;
559 if ((w==0) && (h==0)){ivc=new IViewContainer(name);}
560 else{ivc=new IViewContainer(name,w,h);}
561 return ivc;
562 }
563
564 /**create a new applet view
565 *@param c vector of cameras superimposed in this view
566 *@param name view name
567 *@param w width of window in pixels
568 *@param h height of window in pixels
569 */
570 public JPanel addAppletView(Vector c,String name,int w,int h){
571 AppletView tvi=new AppletView(c,name,w,h,this);
572 tvi.mouse.setID(new Long(nextmID++));
573 allViews.put(name,tvi);
574 tvi.setRepaintPolicy(generalRepaintPolicy);
575 if (!animator.started){animator.start();} //start animator only when a view is created
576 return tvi.panel;
577 }
578
579 /**get view whose name is n*/
580 public View getView(String n){
581 return (View)(allViews.get(n));
582 }
583
584 /**destroy a view - used internally - not available to programmer, who should call the method directly on the view itself*/
585 protected void destroyView(String viewName){
586 allViews.remove(viewName);
587 if (allViews.isEmpty()){animator.stop();} //if there are no more views, stop AnimatorManager
588 }
589
590 /**call this if you want to repaint all views at once
591 * in some cases it is not possible to detect graphical changes, like when a glyph is selected so repaint has to be done manually (unless you are willing to wait for another event to trigger repaint, like mouse moving)
592 */
593 public void repaintNow(){
594 for (Enumeration e=allViews.elements();e.hasMoreElements();){
595 ((View)(e.nextElement())).repaintNow();
596 }
597 }
598
599 /**create a new virtual space with name n*/
600 public VirtualSpace addVirtualSpace(String n){
601 VirtualSpace tvs=new VirtualSpace(n);
602 tvs.setManager(this);
603 allVirtualSpaces.put(n,tvs);
604 return tvs;
605 }
606
607 /**destroy a virtual space*/
608 public void destroyVirtualSpace(String n){
609 if (allVirtualSpaces.containsKey(n)){
610 VirtualSpace vs=(VirtualSpace)(allVirtualSpaces.get(n));
611 vs.destroy();
612 allVirtualSpaces.remove(n);
613 }
614 }
615
616 /**get virtual space whose name is n*/
617 public VirtualSpace getVirtualSpace(String n){
618 return (VirtualSpace)(allVirtualSpaces.get(n));
619 }
620
621 /**get active virtual space*/
622 public VirtualSpace getActiveSpace(){
623 return activeView.getActiveCamera().getOwningSpace();
624 }
625
626 /**set active view*/
627 public void setActiveView(View v){
628 activeView=v;
629 }
630
631 /**get active view*/
632 public View getActiveView(){
633 return activeView;
634 }
635
636 /**stick glyph whose ID is id to mouse (to drag it) - glyph is automatically made unsensitive to mouse events*/
637 public void stickToMouse(Long id){
638 stickToMouse(getGlyph(id));
639 }
640
641 /**stick glyph g to mouse (to drag it) - glyph is automatically made unsensitive to mouse events*/
642 public void stickToMouse(Glyph g){
643 activeView.mouse.stick(g);
644 }
645
646 /**unstick ONLY LAST glyph sticked to mouse - glyph is automatically made sensitive to mouse events - you can get the number of glyphs sticked to the mouse by calling VCursor.getStickedGlyphsNumber()*/
647 public void unstickFromMouse(){
648 activeView.mouse.unstick();
649 }
650
651 /**stick glyph whose ID is id1 to glyph whose ID is id2 (behaves like a one-way constraint)*/
652 public void stickToGlyph(Long id1,Long id2){
653 stickToGlyph(getGlyph(id1),getGlyph(id2));
654 }
655
656 /**stick glyph g1 to glyph g2 (behaves like a one-way constraint)*/
657 public void stickToGlyph(Glyph g1,Glyph g2){
658 g2.stick(g1);
659 }
660
661 /**unstick glyph whose ID is id1 from glyph whose ID is id2*/
662 public void unstickFromGlyph(Long id1,Long id2){
663 getGlyph(id2).unstick(getGlyph(id1));
664 }
665
666 /**unstick glyph g1 from glyph g2*/
667 public void unstickFromGlyph(Glyph g1,Glyph g2){
668 g2.unstick(g1);
669 }
670
671 /**unstick all glyphs sticked to g*/
672 public void unstickAllGlyphs(Glyph g){
673 Vector v=g.getStickedGlyphs();
674 for (int i=v.size()-1;i>=0;i--){
675 g.unstick((Glyph)v.elementAt(i));
676 }
677 }
678
679 /**translates and (un)zooms a camera in order to see everything visible in the associated virtual space
680 *@param c Camera to be moved
681 *@param d duration of the animation in ms
682 *@return the final camera location
683 */
684 public Location getGlobalView(Camera c,int d){
685 View v=null;
686 try {
687 v=c.getOwningView();
688 if (v!=null){
689 long[] wnes=findFarmostGlyphCoords(c.parentSpace); //wnes=west north east south
690 long dx=(wnes[2]+wnes[0])/2; //new coords where camera should go
691 long dy=(wnes[1]+wnes[3])/2;
692 long[] regBounds=v.getVisibleRegion(c);
693 long[] trRegBounds={regBounds[0]+dx-c.posx,regBounds[3]+dy-c.posy}; //region that will be visible after translation, but before zoom/unzoom (need to compute zoom) ; we only take left and down because we only need horizontal and vertical ratios, which are equals for left and right, up and down
694 float currentAlt=c.getAltitude()+c.getFocal();
695 float ratio=0;
696 //compute the mult factor for altitude to see all stuff on X
697 if (trRegBounds[0]!=0){ratio=(dx-wnes[0])/((float)(dx-trRegBounds[0]));}
698 //same for Y ; take the max of both
699 if (trRegBounds[1]!=0){
700 float tmpRatio=(dy-wnes[3])/((float)(dy-trRegBounds[1]));
701 if (tmpRatio>ratio){ratio=tmpRatio;}
702 }
703 float newAlt=currentAlt*Math.abs(ratio);
704 float dAlt=newAlt-currentAlt;
705 Vector prms=new Vector();
706 prms.add(new Float(dAlt));prms.add(new LongPoint(dx-c.posx,dy-c.posy));
707 animator.createCameraAnimation(d,AnimManager.CA_ALT_TRANS_SIG,prms,c.getID());
708 return new Location(dx,dy,newAlt);
709 }
710 else return null;
711 }
712 catch (NullPointerException e){
713 System.err.println("Error:VirtualSpaceManager:getGlobalView: ");
714 System.err.println("Camera c="+c);
715 System.err.println("View v="+v);
716 if (debug){e.printStackTrace();}
717 else {System.err.println(e);}
718 return null;
719 }
720 }
721
722 /**returns the leftmost xpos, upmost ypos, rightmost xpos, downmost ypos visible in virtual space s*/
723 public static long[] findFarmostGlyphCoords(VirtualSpace s){
724 if (s!=null){
725 long[] res=new long[4];
726 Vector v=s.getVisibleGlyphs();
727 if (!v.isEmpty()){
728 Glyph g=(Glyph)v.firstElement();//init result with first glyph found
729 long size=(long)g.getSize();
730 res[0]=g.vx-size;
731 res[1]=g.vy+size;
732 res[2]=g.vx+size;
733 res[3]=g.vy-size;
734 long tmp;
735 for (int i=1;i<v.size();i++){
736 g=(Glyph)v.elementAt(i);
737 size=(long)g.getSize();
738 tmp=g.vx-size; if (tmp<res[0]){res[0]=tmp;}
739 tmp=g.vy+size; if (tmp>res[1]){res[1]=tmp;}
740 tmp=g.vx+size; if (tmp>res[2]){res[2]=tmp;}
741 tmp=g.vy-size; if (tmp<res[3]){res[3]=tmp;}
742 }
743 return res;
744 }
745 else {res[0]=0;res[1]=0;res[2]=0;res[3]=0;return res;}
746 }
747 else return null;
748 }
749
750 /**translates and (un)zooms a camera in order to focus on glyph g
751 *@param g Glyph of interest
752 *@param c Camera to be moved
753 *@param d duration of the animation in ms
754 *@return the final camera location
755 */
756 public Location centerOnGlyph(Glyph g,Camera c,int d){
757 View v=null;
758 try {
759 v=c.getOwningView();
760 if (v!=null){
761 long dx;
762 long dy;
763 if (g instanceof VText){
764 VText t=(VText)g;
765 LongPoint p=t.getBounds(c.getIndex());
766 if (t.getTextAnchor()==VText.TEXT_ANCHOR_START){
767 dx=g.vx+p.x/2-c.posx;
768 dy=g.vy+p.y/2-c.posy;
769 }
770 else if (t.getTextAnchor()==VText.TEXT_ANCHOR_MIDDLE){
771 dx=g.vx-c.posx;
772 dy=g.vy-c.posy;
773 }
774 else {
775 dx=g.vx-p.x/2-c.posx;
776 dy=g.vy-p.y/2-c.posy;
777 }
778 }
779 else if (g instanceof VPath){
780 VPath p=(VPath)g;
781 dx=p.realHotSpot.x-c.posx;
782 dy=p.realHotSpot.y-c.posy;
783 }
784 else {
785 dx=g.vx-c.posx;
786 dy=g.vy-c.posy;
787 }
788 long[] regBounds=v.getVisibleRegion(c);
789 long[] trRegBounds={regBounds[0]+dx,regBounds[3]+dy}; //region that will be visible after translation, but before zoom/unzoom (need to compute zoom) ; we only take left and down because ratios are equals for left and right, up and down
790 float currentAlt=c.getAltitude()+c.getFocal();
791 float ratio=0;
792 //compute the mult factor for altitude to see glyph g entirely
793 if (trRegBounds[0]!=0){ratio=(g.getSize())/((float)(g.vx-trRegBounds[0]));}
794 //same for Y ; take the max of both
795 if (trRegBounds[1]!=0){
796 float tmpRatio=(g.getSize())/((float)(g.vy-trRegBounds[1]));
797 if (tmpRatio>ratio){ratio=tmpRatio;}
798 }
799 float newAlt=currentAlt*Math.abs(ratio);
800 float dAlt=newAlt-currentAlt;
801 // animator.createCameraAnimation(d,2,new LongPoint(dx,dy),c.getID());
802 // animator.createCameraAnimation(d,5,new Float(dAlt),c.getID());
803 Vector prms=new Vector();
804 prms.add(new Float(dAlt));prms.add(new LongPoint(dx,dy));
805 animator.createCameraAnimation(d,AnimManager.CA_ALT_TRANS_SIG,prms,c.getID());
806 return new Location(g.vx,g.vy,newAlt);
807 }
808 else return null;
809 }
810 catch (NullPointerException e){
811 System.err.println("Error:VirtualSpaceManager:centerOnGlyph: ");
812 System.err.println("Glyph g="+g);
813 System.err.println("Camera c="+c);
814 System.err.println("View v="+v);
815 if (debug){e.printStackTrace();}
816 else {System.err.println(e);}
817 return null;
818 }
819 }
820
821 /**translates and (un)zooms a camera in order to focus on a specific rectangular region
822 *@param c Camera to be moved
823 *@param d duration of the animation in ms
824 *@param x1 coordinate of the region's west bound (in virtual space)
825 *@param y1 coordinate of the region's north bound (in virtual space)
826 *@param x2 coordinate of the region's east bound (in virtual space)
827 *@param y2 coordinate of the region's south bound (in virtual space)
828 *@return the final camera location
829 */
830 public Location centerOnRegion(Camera c,int d,long x1,long y1,long x2,long y2){
831 View v=null;
832 try {
833 v=c.getOwningView();
834 if (v!=null){
835 long[] wnes={x1,y1,x2,y2}; //wnes=west north east south
836 long dx=(wnes[2]+wnes[0])/2; //new coords where camera should go
837 long dy=(wnes[1]+wnes[3])/2;
838 long[] regBounds=v.getVisibleRegion(c);
839 long[] trRegBounds={regBounds[0]+dx-c.posx,regBounds[3]+dy-c.posy}; //region that will be visible after translation, but before zoom/unzoom (need to compute zoom) ; we only take left and down because we only need horizontal and vertical ratios, which are equals for left and right, up and down
840 float currentAlt=c.getAltitude()+c.getFocal();
841 float ratio=0;
842 //compute the mult factor for altitude to see all stuff on X
843 if (trRegBounds[0]!=0){ratio=(dx-wnes[0])/((float)(dx-trRegBounds[0]));}
844 //same for Y ; take the max of both
845 if (trRegBounds[1]!=0){
846 float tmpRatio=(dy-wnes[3])/((float)(dy-trRegBounds[1]));
847 if (tmpRatio>ratio){ratio=tmpRatio;}
848 }
849 float newAlt=currentAlt*Math.abs(ratio);
850 float dAlt=newAlt-currentAlt;
851 Vector prms=new Vector();
852 prms.add(new Float(dAlt));prms.add(new LongPoint(dx-c.posx,dy-c.posy));
853 animator.createCameraAnimation(d,AnimManager.CA_ALT_TRANS_SIG,prms,c.getID());
854 return new Location(dx,dy,newAlt);
855 }
856 else return null;
857 }
858 catch (NullPointerException e){
859 System.err.println("Error:VirtualSpaceManager:centerOnRegion: ");
860 System.err.println("Camera c="+c);
861 System.err.println("View v="+v);
862 if (debug){e.printStackTrace();}
863 else {System.err.println(e);}
864 return null;
865 }
866 }
867
868 /**set the value under which a VText is drawn as a point instead of a text (considered too small to be read). Default is 0.5 (it is compared to the product of the font size by the projection value) - if you raise this value, more text that was still displayed as a string will be displayed as a segment and inversely - of course, displaying a line instead of applying affine transformations to strings is faster*/
869 public void setTextDisplayedAsSegCoef(float f){
870 textAsLineCoef=f;
871 }
872
873 /**set the value under which a VText is drawn as a point instead of a text (considered too small to be read). Default is 0.5 (it is compared to the product of the font size by the projection value)*/
874 public float getTextDisplayedAsSegCoef(){
875 return textAsLineCoef;
876 }
877
878 // /**create a vector linking two glyphs - a vector is a helper that can be used in constraints (constrainable dimensions are size, position and orientation) - use with caution: vectors introduce non-linear relations in contraints that are processed outside of the solver, thus limiting the support for cycles in the constraint graph
879 // *@param ID1 ID of glyph1 (tail)
880 // *@param ID2 ID of glyph 2 (head)
881 // */
882 // public Long createHVector(Long ID1,Long ID2){return constMgr.createVect(ID1,ID2);}
883
884 // /**remove a helper (like vector)
885 // *@param hID ID of helper
886 // */
887 // public void removeHelper(Long hID){constMgr.removeHelper(hID);}
888
889
890 // /**get all constraints involving a glyph
891 // *@param gID ID of glyph
892 // *returns a vector of Long (IDs of constraints)
893 // */
894 // public Vector getConstraints(Long gID){return constMgr.getConstraints(gID);}
895
896 // /**destroy a constraint
897 // *@param cID ID of constraint
898 // */
899 // public void removeConstraint(Long cID){constMgr.removeConstraint(cID);}
900
901 // /**activate an existing constraint
902 // *@param cID ID of constraint
903 // */
904 // public void activateConstraint(Long cID){constMgr.activateConstraint(cID);}
905
906 // /**deactivate an existing constraint
907 // *@param cID ID of constraint
908 // */
909 // public void deactivateConstraint(Long cID){constMgr.deactivateConstraint(cID);}
910
911 // /**create a constraint that links a size to a size
912 // *@param id1 first glyph or helper ID
913 // *@param id2 second glyph or helper ID
914 // *@param exp math expression of the constraint (for syntax refer to top of this page)
915 // */
916 // public Long createCnstrntSizeSize(Long id1,Long id2,String exp){
917 // Vector glyphs=new Vector();glyphs.add(id1);glyphs.add(id2);
918 // Vector attrs=new Vector();attrs.add("sz");attrs.add("sz");
919 // return constMgr.createConstraint(glyphs,attrs,exp);
920 // }
921
922 // /**create a constraint that links an orientation to an orientation
923 // *@param id1 first glyph or helper ID
924 // *@param id2 second glyph or helper ID
925 // *@param exp math expression of the constraint (for syntax refer to top of this page)
926 // */
927 // public Long createCnstrntOrientOrient(Long id1,Long id2,String exp){
928 // Vector glyphs=new Vector();glyphs.add(id1);glyphs.add(id2);
929 // Vector attrs=new Vector();attrs.add("or");attrs.add("or");
930 // return constMgr.createConstraint(glyphs,attrs,exp);
931 // }
932
933 // /**create a constraint that links a size to an orientation
934 // *@param id1 first glyph or helper ID
935 // *@param id2 second glyph or helper ID
936 // *@param exp math expression of the constraint (for syntax refer to top of this page)
937 // */
938 // public Long createCnstrntSizeOrient(Long id1,Long id2,String exp){
939 // Vector glyphs=new Vector();glyphs.add(id1);glyphs.add(id2);
940 // Vector attrs=new Vector();attrs.add("sz");attrs.add("or");
941 // return constMgr.createConstraint(glyphs,attrs,exp);
942 // }
943
944 // /**create a constraint that links a position to a position
945 // *@param id1 first glyph or helper ID
946 // *@param id2 second glyph or helper ID
947 // *@param exp math expression of the constraint (for syntax refer to top of this page)
948 // *@param pos1 integer describing which one of x,y is involved (1=x, 2=y, 3=both)
949 // *@param pos2 integer describing which one of x,y is involved (1=x, 2=y, 3=both)
950 // */
951 // public Long createCnstrntPosPos(Long id1,Long id2,String exp,int pos1,int pos2){
952 // Vector glyphs=new Vector();
953 // Vector attrs=new Vector();
954 // if ((pos1>0) && (pos1<4) && (pos2>0) && (pos2<4)){
955 // switch (pos1){
956 // case 1:{glyphs.add(id1);attrs.add("x");break;}
957 // case 2:{glyphs.add(id1);attrs.add("y");break;}
958 // case 3:{glyphs.add(id1);attrs.add("x");glyphs.add(id1);attrs.add("y");break;}
959 // }
960 // switch (pos2){
961 // case 1:{glyphs.add(id2);attrs.add("x");break;}
962 // case 2:{glyphs.add(id2);attrs.add("y");break;}
963 // case 3:{glyphs.add(id2);attrs.add("x");glyphs.add(id2);attrs.add("y");break;}
964 // }
965 // return constMgr.createConstraint(glyphs,attrs,exp);
966 // }
967 // else return null;
968 // }
969
970 // /**create a constraint that links a position to a size
971 // *@param id1 first glyph or helper ID
972 // *@param id2 second glyph or helper ID
973 // *@param exp math expression of the constraint (for syntax refer to top of this page)
974 // *@param pos1 integer describing which one of x,y is involved (1=x, 2=y, 3=both)
975 // */
976 // public Long createCnstrntPosSize(Long id1,Long id2,String exp,int pos1){
977 // Vector glyphs=new Vector();
978 // Vector attrs=new Vector();
979 // if ((pos1>0) && (pos1<4)){
980 // switch (pos1){
981 // case 1:{glyphs.add(id1);attrs.add("x");break;}
982 // case 2:{glyphs.add(id1);attrs.add("y");break;}
983 // case 3:{glyphs.add(id1);attrs.add("x");glyphs.add(id1);attrs.add("y");break;}
984 // }
985 // glyphs.add(id2);attrs.add("sz");
986 // return constMgr.createConstraint(glyphs,attrs,exp);
987 // }
988 // else return null;
989 // }
990
991 // /**create a constraint that links a position to an orientation
992 // *@param id1 first glyph or helper ID
993 // *@param id2 second glyph or helper ID
994 // *@param exp math expression of the constraint (for syntax refer to top of this page)
995 // *@param pos1 integer describing which one of x,y is involved (1=x, 2=y, 3=both)
996 // */
997 // public Long createCnstrntPosOrient(Long id1,Long id2,String exp,int pos1){
998 // Vector glyphs=new Vector();
999 // Vector attrs=new Vector();
1000// if ((pos1>0) && (pos1<4)){
1001// switch (pos1){
1002// case 1:{glyphs.add(id1);attrs.add("x");break;}
1003// case 2:{glyphs.add(id1);attrs.add("y");break;}
1004// case 3:{glyphs.add(id1);attrs.add("x");glyphs.add(id1);attrs.add("y");break;}
1005// }
1006// glyphs.add(id2);attrs.add("or");
1007// return constMgr.createConstraint(glyphs,attrs,exp);
1008// }
1009// else return null;
1010// }
1011
1012// /**create a constraint that links a position to a color
1013// *@param id1 first glyph or helper ID
1014// *@param id2 second glyph or helper ID
1015// *@param exp math expression of the constraint (for syntax refer to top of this page)
1016// *@param pos1 integer describing which one of x,y is involved (1=x, 2=y, 3=both)
1017// *@param pos2 integer describing which one of h,s,v is involved ()
1018// */
1019// public Long createCnstrntPosCol(Long id1,Long id2,String exp,int pos1,int col2){
1020// Vector glyphs=new Vector();
1021// Vector attrs=new Vector();
1022// if ((pos1>0) && (pos1<4) && (col2>0) && (col2<8)){
1023// switch (pos1){
1024// case 1:{glyphs.add(id1);attrs.add("x");break;}
1025// case 2:{glyphs.add(id1);attrs.add("y");break;}
1026// case 3:{glyphs.add(id1);attrs.add("x");glyphs.add(id1);attrs.add("y");break;}
1027// }
1028// switch (col2){
1029// case 1:{glyphs.add(id2);attrs.add("v");break;}
1030// case 2:{glyphs.add(id2);attrs.add("s");break;}
1031// case 3:{glyphs.add(id2);glyphs.add(id2);attrs.add("s");attrs.add("v");break;}
1032// case 4:{glyphs.add(id2);attrs.add("h");break;}
1033// case 5:{glyphs.add(id2);glyphs.add(id2);attrs.add("h");attrs.add("v");break;}
1034// case 6:{glyphs.add(id2);glyphs.add(id2);attrs.add("h");attrs.add("s");break;}
1035// case 7:{glyphs.add(id2);glyphs.add(id2);glyphs.add(id2);attrs.add("h");attrs.add("s");attrs.add("v");break;}
1036// }
1037// return constMgr.createConstraint(glyphs,attrs,exp);
1038// }
1039// else return null;
1040// }
1041
1042// /**create a constraint that links a size to a color
1043// *@param id1 first glyph or helper ID
1044// *@param id2 second glyph or helper ID
1045// *@param exp math expression of the constraint (for syntax refer to top of this page)
1046// *@param col2 integer describing which one of h,s,v is involved ()
1047// */
1048// public Long createCnstrntSizeCol(Long id1,Long id2,String exp,int col2){
1049// Vector glyphs=new Vector();
1050// Vector attrs=new Vector();
1051// if ((col2>0) && (col2<8)){
1052// glyphs.add(id1);attrs.add("sz");
1053// switch (col2){
1054// case 1:{glyphs.add(id2);attrs.add("v");break;}
1055// case 2:{glyphs.add(id2);attrs.add("s");break;}
1056// case 3:{glyphs.add(id2);glyphs.add(id2);attrs.add("s");attrs.add("v");break;}
1057// case 4:{glyphs.add(id2);attrs.add("h");break;}
1058// case 5:{glyphs.add(id2);glyphs.add(id2);attrs.add("h");attrs.add("v");break;}
1059// case 6:{glyphs.add(id2);glyphs.add(id2);attrs.add("h");attrs.add("s");break;}
1060// case 7:{glyphs.add(id2);glyphs.add(id2);glyphs.add(id2);attrs.add("h");attrs.add("s");attrs.add("v");break;}
1061// }
1062// return constMgr.createConstraint(glyphs,attrs,exp);
1063// }
1064// else return null;
1065// }
1066
1067// /**create a constraint that links an orientation to a color
1068// *@param id1 first glyph or helper ID
1069// *@param id2 second glyph or helper ID
1070// *@param exp math expression of the constraint (for syntax refer to top of this page)
1071// *@param col2 integer describing which one of h,s,v is involved ()
1072// */
1073// public Long createCnstrntOrientCol(Long id1,Long id2,String exp,int col2){
1074// Vector glyphs=new Vector();
1075// Vector attrs=new Vector();
1076// if ((col2>0) && (col2<8)){
1077// glyphs.add(id1);attrs.add("or");
1078// switch (col2){
1079// case 1:{glyphs.add(id2);attrs.add("v");break;}
1080// case 2:{glyphs.add(id2);attrs.add("s");break;}
1081// case 3:{glyphs.add(id2);glyphs.add(id2);attrs.add("s");attrs.add("v");break;}
1082// case 4:{glyphs.add(id2);attrs.add("h");break;}
1083// case 5:{glyphs.add(id2);glyphs.add(id2);attrs.add("h");attrs.add("v");break;}
1084// case 6:{glyphs.add(id2);glyphs.add(id2);attrs.add("h");attrs.add("s");break;}
1085// case 7:{glyphs.add(id2);glyphs.add(id2);glyphs.add(id2);attrs.add("h");attrs.add("s");attrs.add("v");break;}
1086// }
1087// return constMgr.createConstraint(glyphs,attrs,exp);
1088// }
1089// else return null;
1090// }
1091
1092// /**create a constraint that links an orientation to a color
1093// *@param id1 first glyph or helper ID
1094// *@param id2 second glyph or helper ID
1095// *@param exp math expression of the constraint (for syntax refer to top of this page)
1096// *@param col2 integer describing which one of h,s,v is involved ()
1097// */
1098// public Long createCnstrntColCol(Long id1,Long id2,String exp,int col1,int col2){
1099// Vector glyphs=new Vector();
1100// Vector attrs=new Vector();
1101// if ((col1>0) && (col1<8) && (col2>0) && (col2<8)){
1102// switch (col1){
1103// case 1:{glyphs.add(id1);attrs.add("v");break;}
1104// case 2:{glyphs.add(id1);attrs.add("s");break;}
1105// case 3:{glyphs.add(id1);glyphs.add(id1);attrs.add("s");attrs.add("v");break;}
1106// case 4:{glyphs.add(id1);attrs.add("h");break;}
1107// case 5:{glyphs.add(id1);glyphs.add(id1);attrs.add("h");attrs.add("v");break;}
1108// case 6:{glyphs.add(id1);glyphs.add(id1);attrs.add("h");attrs.add("s");break;}
1109// case 7:{glyphs.add(id1);glyphs.add(id1);glyphs.add(id1);attrs.add("h");attrs.add("s");attrs.add("v");break;}
1110// }
1111// switch (col2){
1112// case 1:{glyphs.add(id2);attrs.add("v");break;}
1113// case 2:{glyphs.add(id2);attrs.add("s");break;}
1114// case 3:{glyphs.add(id2);glyphs.add(id2);attrs.add("s");attrs.add("v");break;}
1115// case 4:{glyphs.add(id2);attrs.add("h");break;}
1116// case 5:{glyphs.add(id2);glyphs.add(id2);attrs.add("h");attrs.add("v");break;}
1117// case 6:{glyphs.add(id2);glyphs.add(id2);attrs.add("h");attrs.add("s");break;}
1118// case 7:{glyphs.add(id2);glyphs.add(id2);glyphs.add(id2);attrs.add("h");attrs.add("s");attrs.add("v");break;}
1119// }
1120// return constMgr.createConstraint(glyphs,attrs,exp);
1121// }
1122// else return null;
1123// }
1124
1125// /**create a complex constraint
1126// *@param v1 vector of Long IDs of glyphs to be linked
1127// *@param v2 vector of attributes to be linked
1128// *@param exp math expression of the constraint (for syntax refer to top of this page)
1129// */
1130// public Long createComplexCnstrnt(Vector v1,Vector v2,String exp){
1131// Vector glyphs=v1;
1132// Vector attrs=v2;
1133// return constMgr.createConstraint(glyphs,attrs,exp);
1134// }
1135
1136// /**create a compound constraint
1137// *@param v1 vector of Long IDs of constraints to be compound
1138// */
1139// public Long createCompoundCnstrnt(Vector v1){
1140// return constMgr.createCompoundConstraint(v1);
1141// }
1142
1143// /**create stay constraint(s)
1144// *@param v1 vector of IDs of glyph
1145// *@param v2 vector of Strings in x,y,or,sz,h,s,v
1146// */
1147// public void createStayCnstrnt(Vector v1,Vector v2){
1148// constMgr.addStay(v1,v2);
1149// }
1150
1151// /**remove stay constraint(s)
1152// *@param v1 vector of IDs of glyph
1153// *@param v2 vector of Strings in x,y,or,sz,h,s,v
1154// */
1155// public void removeStayCnstrnt(Vector v1,Vector v2){
1156// constMgr.removeStay(v1,v2);
1157// }
1158
1159 //should not be used by applications - public because accessed by Glyphs themselves when made unsensitive
1160 public void removeGlyphFromUnderMouseLists(Glyph g){
1161 VirtualSpace vs=null;
1162 try {
1163 for (Enumeration e=allVirtualSpaces.elements();e.hasMoreElements();){
1164 vs=(VirtualSpace)e.nextElement();
1165 if (vs.getAllGlyphs().contains(g)){break;}
1166 }
1167 for (Enumeration e=vs.getCameraList().elements();e.hasMoreElements();){
1168 ((View)((Camera)e.nextElement()).getOwningView()).mouse.removeGlyphFromList(g);
1169 }
1170 }
1171 catch (NullPointerException ex){}
1172 }
1173
1174 Object activeJFrame=null;
1175
1176 public void eventDispatched(java.awt.AWTEvent e){
1177 if (e.getID()==java.awt.event.WindowEvent.WINDOW_ACTIVATED){activeJFrame=e.getSource();}
1178 }
1179
1180}
1181
1182
1183