Source code: com/xerox/VTM/engine/VirtualSpace.java
1 /* FILE: VirtualSpace.java
2 * DATE OF CREATION: Jul 11 2000
3 * AUTHOR : Emmanuel Pietriga (emmanuel.pietriga@xrce.xerox.com)
4 * MODIF: Tue Aug 05 15:38:41 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 com.xerox.VTM.glyphs.*;
23 import java.util.Vector;
24 import java.util.Hashtable;
25 import java.util.Enumeration;
26
27 /**
28 * A virtual space contains glyphs and can be observed through one or several cameras
29 * @author Emmanuel Pietriga
30 **/
31
32 public class VirtualSpace {
33
34 /**
35 *computes the geometrical center of a set of glyphs (takes glyph sizes into account) (0,0 if list is empty)
36 *@param v a list of Glyph instances
37 */
38 public static LongPoint getGlyphSetGeometricalCenter(Glyph[] gl){
39 if (gl!=null && gl.length>0){
40 long[] tmpC=new long[4];
41 long size=(long)gl[0].getSize();
42 tmpC[0]=gl[0].vx-size;
43 tmpC[1]=gl[0].vy+size;
44 tmpC[2]=gl[0].vx+size;
45 tmpC[3]=gl[0].vy-size;
46 long tmp;
47 for (int i=1;i<gl.length;i++){
48 size=(long)gl[i].getSize();
49 tmp=gl[i].vx-size; if (tmp<tmpC[0]){tmpC[0]=tmp;}
50 tmp=gl[i].vy+size; if (tmp>tmpC[1]){tmpC[1]=tmp;}
51 tmp=gl[i].vx+size; if (tmp>tmpC[2]){tmpC[2]=tmp;}
52 tmp=gl[i].vy-size; if (tmp<tmpC[3]){tmpC[3]=tmp;}
53 }
54 return new LongPoint((tmpC[2]+tmpC[0])/2,(tmpC[1]+tmpC[3])/2);
55 }
56 else {return new LongPoint(0,0);}
57 }
58
59 /**name of virtual space*/
60 public String spaceName;
61
62 VirtualSpaceManager vsm;
63
64 /**camera manager for this virtual space*/
65 CameraManager cm;
66
67 /**all glyphs in this virtual space, visible or not*/
68 Vector visualEnts;
69
70 /**visible glyphs - order is important (biggest index gets drawn on top)*/
71 Vector drawingList; //this one can be shared by all cameras in the virtual space as it is the same for all of them
72
73 // /**glyphs actually drawn (a glyph can be visible but not inside a view)*/
74 // Vector drawnList; //in theory, I suppose we should have such a list for every camera/view in a given space, as the lists can be different
75 // //in practice, it does not seem to be a problem, and this way we reduce the amount of memory needed
76 // //however, if in the future this causes trouble (e.g. in VCursor.computeMouseOverList), I'll consider
77 // //having a list for each camera/view actually observing a virtual space
78
79 Vector[] camera2drawnList; //sharing drawnList WAS causing a problem ; this is an experiment to try and solve the problem (have a drawnList for each camera in the vs) - it seems to work fine (at least the problem has disappeared in IsaViz's radar view)
80
81 /**
82 *@param n virtual space name
83 */
84 VirtualSpace(String n){
85 cm=new CameraManager(this);
86 visualEnts=new Vector();
87 camera2drawnList=new Vector[0];
88 drawingList=new Vector();
89 spaceName=n;
90 }
91
92 /**get virtual space name*/
93 public String getName(){return spaceName;}
94
95 /**get virtual space's i-th camera*/
96 public Camera getCamera(int i){return cm.getCamera(i);}
97
98 /**
99 *@deprecated As of zvtm 0.9.0, replaced by getCameraListAsArray
100 *@see #getCameraListAsArray()
101 */
102 public Vector getCameraList(){
103 Vector res=new Vector();
104 for (int i=0;i<cm.cameraList.length;i++){
105 res.add(cm.cameraList[i]);
106 }
107 return res;
108 }
109
110 /**returns the list of all cameras in this virtual space*/
111 public Camera[] getCameraListAsArray(){return cm.cameraList;}
112
113 /**create a new camera*/
114 Camera createCamera(){
115 Camera c=cm.addCamera();
116 Vector[] newDrawnListList=new Vector[camera2drawnList.length+1]; //create a new drawnList for it
117 System.arraycopy(camera2drawnList,0,newDrawnListList,0,camera2drawnList.length);
118 newDrawnListList[camera2drawnList.length]=new Vector();
119 camera2drawnList=newDrawnListList;
120 c.setOwningSpace(this);
121 for (Enumeration e=visualEnts.elements();e.hasMoreElements();){
122 Glyph g=(Glyph)e.nextElement();
123 g.addCamera(c.getIndex());
124 }
125 return c;
126 }
127
128 /**remove camera at index i
129 * when a camera is destroyed, its index is not reused for another one - so if camera number #3 is removed and then a new camera is added it will be assigned number #4 even though there is no camera at index #3 any longer
130 *@param i index of camera in virtual space
131 */
132 public void removeCamera(int i){
133 if (cm.cameraList.length>i){
134 for (Enumeration e=vsm.allViews.elements();e.hasMoreElements();){
135 View v=(View)e.nextElement();
136 if (v.cameras.contains(cm.getCamera(i))){
137 v.destroyCamera(cm.getCamera(i));
138 }
139 }
140 for (Enumeration e=visualEnts.elements();e.hasMoreElements();){
141 Glyph g=(Glyph)e.nextElement();
142 g.removeCamera(i);
143 }
144 cm.removeCamera(i);
145 camera2drawnList[i]=null;
146 }
147 }
148
149 /**destroy this virtual space - call method in virtual space manager*/
150 protected void destroy(){
151 for (int i=0;i<cm.cameraList.length;i++){
152 this.removeCamera(i);
153 }
154 for (Enumeration e=visualEnts.elements();e.hasMoreElements();){
155 this.destroyGlyph((Glyph)e.nextElement());
156 }
157 }
158
159 /**add glyph g to this space*/
160 void addGlyph(Glyph g){
161 g.initCams(cm.cameraList.length);
162 visualEnts.add(g);
163 drawingList.add(g);
164 }
165
166 /**get all glyphs in this space, visible or not, sensitive or not*/
167 public Vector getAllGlyphs(){
168 return visualEnts;
169 }
170
171 /**get all visible glyphs*/
172 public Vector getVisibleGlyphs(){
173 return drawingList;
174 }
175
176 /**
177 *@deprecated as of zvtm 0.9.0
178 *@see #getDrawnGlyphs(int cameraIndex)
179 */
180 public Vector getDrawnGlyphs(){
181 if (camera2drawnList.length>0){
182 return camera2drawnList[0];
183 }
184 else return null;
185 }
186
187 /**
188 *get all glyphs actually drawn for a given camera in this virtual space
189 */
190 public Vector getDrawnGlyphs(int cameraIndex){
191 if (cameraIndex<camera2drawnList.length){
192 return camera2drawnList[cameraIndex];
193 }
194 else return null;
195 }
196
197 /*put glyph gl in the list of glyphs actually drawn (this list is used to compute the list of glyphs under mouse)*/
198 protected void drewGlyph(Glyph gl,int cameraIndex){
199 if (cameraIndex<camera2drawnList.length && camera2drawnList[cameraIndex]!=null){
200 camera2drawnList[cameraIndex].add(gl);
201 }
202 }
203
204 /**get selected glyphs*/
205 public Vector getSelectedGlyphs(){
206 Vector v=new Vector();
207 Glyph g;
208 for (Enumeration e=visualEnts.elements();e.hasMoreElements();){
209 g=(Glyph)e.nextElement();
210 if (g.isSelected()){
211 v.add(g);
212 }
213 }
214 return v;
215 }
216
217 /**select all glyphs*/
218 public void selectAllGlyphs(){
219 for (Enumeration e=visualEnts.elements();e.hasMoreElements();){
220 ((Glyph)e.nextElement()).select(true);
221 }
222 }
223
224 /**unselect all glyphs*/
225 public void unselectAllGlyphs(){
226 for (Enumeration e=visualEnts.elements();e.hasMoreElements();){
227 ((Glyph)e.nextElement()).select(false);
228 }
229 }
230
231 /**get all glyphs of type t - if t=="" then select all glyphs (means ANY type)*/
232 public Vector getGlyphsOfType(String t){//
233 Vector v=new Vector();
234 Glyph g;
235 for (Enumeration e=visualEnts.elements();e.hasMoreElements();){
236 g=(Glyph)e.nextElement();
237 if ((t.equals("")) || (g.getType().equals(t))){v.add(g);}
238 }
239 return v;
240 }
241
242 /**remove this glyph from this virtual space (should then be garbage-collected)*/
243 public void destroyGlyph(Glyph g){
244 try {
245 if (g.stickedTo!=null){
246 if (g.stickedTo instanceof Glyph){((Glyph)g.stickedTo).unstick(g);}
247 else {((VCursor)g.stickedTo).unstickSpecificGlyph(g);}
248 }
249 if (g.getCGlyph()!=null){//remove from composite glyph if was part of one
250 g.getCGlyph().removeSecondaryGlyph(g);
251 }
252 for (int i=0;i<camera2drawnList.length;i++){
253 if (camera2drawnList[i]!=null){//camera2drawnlist[i] can be null if camera i has been removed from
254 camera2drawnList[i].remove(g);//the virtual space
255 }
256 }
257 View v;
258 for (Enumeration e=vsm.allViews.elements();e.hasMoreElements();){
259 v=(View)e.nextElement();
260 v.mouse.removeGlyphFromList(g);
261 }
262 visualEnts.remove(g);
263 drawingList.remove(g);
264 vsm.allGlyphs.remove(g);
265 vsm.repaintNow();
266 }
267 catch (NullPointerException ex){System.err.println("ZVTM Error: VirtualSpace.destroyGlyph(): the glyph you are trying to delete might not be a member of this virtual space ("+spaceName+") or might be null");ex.printStackTrace();}
268 }
269
270 /**make this glyph visible*/
271 public void show(Glyph g){
272 if (visualEnts.contains(g) && (!drawingList.contains(g))) {drawingList.add(g);}
273 vsm.repaintNow();
274 }
275
276 /**hide this glyph*/
277 public void hide(Glyph g){
278 boolean b=drawingList.removeElement(g);
279 vsm.repaintNow();
280 }
281
282 /**put this glyph on top of the drawing list (will be drawn last)*/
283 public void onTop(Glyph g){
284 if (drawingList.contains(g)){drawingList.removeElement(g);drawingList.add(g);}
285 }
286
287 /**put this glyph at bottom of the drawing list (will be drawn first)*/
288 public void atBottom(Glyph g){
289 if (drawingList.contains(g)){drawingList.removeElement(g);drawingList.insertElementAt(g,0);}
290 }
291
292 /**put glyph g1 just above glyph g2 in the drawing list (g1 painted after g2)*/
293 public void above(Glyph g1,Glyph g2){
294 if ((drawingList.contains(g1)) && (drawingList.contains(g2))){
295 drawingList.remove(g1);
296 int i=drawingList.indexOf(g2);
297 drawingList.insertElementAt(g1,i+1);
298 }
299 }
300
301 /**put glyph g1 just below glyph g2 in the drawing list (g1 painted before g2)*/
302 public void below(Glyph g1,Glyph g2){
303 if ((drawingList.contains(g1)) && (drawingList.contains(g2))){
304 drawingList.remove(g1);
305 int i=drawingList.indexOf(g2);
306 drawingList.insertElementAt(g1,i);
307 }
308 }
309
310 void setManager(VirtualSpaceManager v){this.vsm=v;}
311
312 }
313
314
315