Source code: com/xerox/VTM/engine/View.java
1 /* FILE: View.java
2 * DATE OF CREATION: Jul 11 2000
3 * AUTHOR : Emmanuel Pietriga (emmanuel.pietriga@xrce.xerox.com)
4 * MODIF: Tue Aug 05 09:22:16 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 javax.swing.*;
24 import java.awt.event.*;
25 import java.awt.*;
26 import java.awt.event.*;
27 import java.awt.image.BufferedImage;
28 import java.awt.image.Raster;
29 import com.xerox.VTM.glyphs.*;
30
31 /**
32 * A view is a window and can be composed of one or several cameras superimposed - use EView or IView <BR>
33 * A view is repainted on a regular basis when active - for inactive views, the default is to repaint only if the mouse is inside the view (but the frame is not selected) - this can be changed to repaint the view automatically even if it is not selected and if the mouse is not inside, using setRepaintPolicy()
34 * @author Emmanuel Pietriga
35 **/
36
37 public abstract class View {
38
39 /**list of Camera objects used in this view*/
40 Vector cameras;
41
42 void initCameras(Vector c){
43 cameras=c;
44 for (int i=0;i<cameras.size();i++){
45 ((Camera)c.elementAt(i)).setOwningView(this);
46 }
47 }
48
49 /**mouse glyph*/
50 public VCursor mouse;
51
52 /**the actual panel*/
53 ViewPanel panel;
54
55 /**enables detection of multiple full fills in one view repaint - for this specific view - STILL VERY BUGGY - ONLY SUPPORTS VRectangle and VCircle for now*/
56 boolean detectMultipleFullFills;
57
58 JLabel statusBar;
59
60 /**View name*/
61 String name;
62
63 /**root VTM class*/
64 VirtualSpaceManager parent;
65
66 // /**font used in this view (use setFont() to modify)*/
67 // Font font=Glyph.defaultFont;
68
69 /**triggers the mouseMoved method in AppEventHandler when the mouse is moved - set to false by default because few applications will need this; it is therefore not necessary to overload other applications with these events*/
70 boolean notifyMouseMoved=false;
71
72 /**destroy this view*/
73 public abstract void destroyView();
74
75 /**get the java.awt.Container for this view*/
76 public abstract Container getFrame();
77
78 /**used only in Internal Views to get focus in view for key events (called automatically when the mouse enters the (Acc)IView)*/
79 public abstract void requestFocus();
80
81 /**sets the cursor icon
82 *@param c a value in java.awt.Cursor like DEFAULT_CURSOR or CROSSHAIR_CURSOR - to use the standard VTM cursor, use Cursor.CUSTOM_CURSOR (DEFAULT_CURSOR represents the default AWT/underlying_OS cursor)
83 */
84 public void setCursorIcon(int c){
85 panel.setAWTCursor(c);
86 }
87
88 /**set application class to which events are sent*/
89 public void setEventHandler(AppEventHandler eh){
90 panel.setEventHandler(eh);
91 }
92
93 /**sets whether the mouseMoved method in AppEventHandler is triggered when the mouse is moved - set to false by default because few applications will need this; it is therefore not necessary to overload other applications with these events*/
94 public void setNotifyMouseMoved(boolean b){
95 notifyMouseMoved=b;
96 }
97
98 /**get state of notifyMouseMoved for this view*/
99 public boolean getNotifyMouseMoved(){return notifyMouseMoved;}
100
101 /**set status bar text*/
102 public void setStatusBarText(String s){
103 if (statusBar!=null){if (s.equals("")){statusBar.setText(" ");}else{{statusBar.setText(s);}}}
104 }
105
106 /**set font used in status bar text*/
107 public void setStatusBarFont(Font f){
108 if (statusBar!=null){statusBar.setFont(f);}
109 }
110
111 /**set color used for status bar text*/
112 public void setStatusBarForeground(Color c){
113 if (statusBar!=null){statusBar.setForeground(c);}
114 }
115
116 /**enable/disable detection of multiple full fills in one view repaint - for this specific view */
117 public void setDetectMultiFills(boolean b){
118 detectMultipleFullFills=b;
119 }
120
121 /**get state of detection of multiple full fills in one view repaint - for this specific view*/
122 public boolean getDetectMultiFills(){
123 return detectMultipleFullFills;
124 }
125
126 /**returns bounds of rectangle representing virtual space's region seen through camera c [west,north,east,south]*/
127 public long[] getVisibleRegion(Camera c){ //
128 long[] res=new long[4];
129 if (cameras.contains(c)){
130 float uncoef=(float)((c.focal+c.altitude)/c.focal); //compute region seen from this view through camera
131 res[0]=(long)(c.posx-panel.getSize().width/2*uncoef);
132 res[1]=(long)(c.posy+panel.getSize().height/2*uncoef);
133 res[2]=(long)(c.posx+panel.getSize().width/2*uncoef);
134 res[3]=(long)(c.posy-panel.getSize().height/2*uncoef);
135 }
136 return res;
137 }
138
139 /**returns a BufferedImage representation of this view (this is actually a COPY of the original) that can be used for instance with ImageIO.ImageWriter*/
140 public BufferedImage getImage(){
141 BufferedImage res=null;
142 synchronized(this.getClass()){
143 BufferedImage i=panel.getImage();
144 if (i!=null){
145 //this is the old method for doing this, which eventually stopped working on POSIX systems (hangs at i.copyData())
146 // java.awt.image.WritableRaster wr=Raster.createWritableRaster(i.getSampleModel(),new java.awt.Point(0,0));
147 // res=new BufferedImage(i.getColorModel(),i.copyData(wr),false,null);
148 //new way of doing things
149 res=new BufferedImage(i.getWidth(),i.getHeight(),i.getType());
150 Graphics2D resg2d=res.createGraphics();
151 resg2d.drawImage(i,null,0,0);
152 }
153 }
154 return res;
155 }
156
157 /**set the layer (camera) active in this view
158 * @param i i-th layer 0 is the deepest layer
159 */
160 public void setActiveLayer(int i){
161 mouse.resetGlyphsUnderMouseList(((Camera)cameras.elementAt(i)).parentSpace,((Camera)cameras.elementAt(i)).getIndex());
162 panel.activeLayer=i;
163 }
164
165 /**get the active layer in this view (0 is deepest)*/
166 public int getActiveLayer(){
167 return panel.activeLayer;
168 }
169
170 /**update font used in this view (for all cameras) (should be automatically called when changing the VSM's main font)*/
171 public void updateFont(){panel.updateFont=true;}
172
173 // /**get font used in this view*/
174 // public Font getFont(){return font;}
175
176 /**set antialias rendering hint for this view*/
177 public void setAntialiasing(boolean b){
178 if (b!=panel.antialias){
179 panel.antialias=b;
180 panel.updateAntialias=true;
181 }
182 }
183
184 /**get the value of the antialias rendering hint for this view*/
185 public boolean getAntialiasing(){
186 return panel.antialias;
187 }
188
189 /**get camera number i (corresponds to layer)*/
190 public Camera getCameraNumber(int i){
191 if (cameras.size()>i){return (Camera)cameras.elementAt(i);}
192 else return null;
193 }
194
195 /**get active camera (associated with active layer)*/
196 public Camera getActiveCamera(){
197 return panel.cams[panel.activeLayer];
198 }
199
200 void destroyCamera(Camera c){
201 for (int i=0;i<panel.cams.length;i++){
202 if (panel.cams[i]==c){
203 panel.cams[i]=null;
204 if (i==panel.activeLayer){//if the camera we remove was associated to the active layer, make active another non-null layer
205 for (int j=0;j<panel.cams.length;j++){
206 if (panel.cams[j]!=null){
207 panel.activeLayer=j;
208 break;
209 }
210 }
211 }
212 break;
213 }
214 }
215 cameras.remove(c);
216 }
217
218 /**set background color for this view*/
219 public void setBackgroundColor(Color c){
220 panel.backColor=c;
221 }
222
223 /**get background color of this view*/
224 public Color getBackgroundColor(){
225 return panel.backColor;
226 }
227
228 /**tells whether this frame is selected or not*/
229 public abstract boolean isSelected();
230
231 /**set the window title*/
232 public abstract void setTitle(String t);
233
234 /**set the window location*/
235 public abstract void setLocation(int x,int y);
236
237 /**set the window size*/
238 public abstract void setSize(int x,int y);
239
240 /**can the window be resized or not*/
241 public abstract void setResizable(boolean b);
242
243 /**Shows or hides this view*/
244 public abstract void setVisible(boolean b);
245
246 /**Brings this window to the front. Places this window at the top of the stacking order and shows it in front of any other windows*/
247 public abstract void toFront();
248
249 /**Sends this window to the back. Places this window at the bottom of the stacking order and makes the corresponding adjustment to other visible windows*/
250 public abstract void toBack();
251
252 /**Set this view's refresh rate - default is 20
253 *@param r positive integer (refresh rate in milliseconds)
254 */
255 public void setRefreshRate(int r){
256 panel.setRefreshRate(r);
257 }
258
259 /**Set this view's refresh rate - default is 20*/
260 public int getRefreshRate(){
261 return panel.getRefreshRate();
262 }
263
264 /**should repaint this view on a regular basis or not (even if not activated, but does not apply to iconified views)*/
265 public void setRepaintPolicy(boolean b){
266 panel.alwaysRepaintMe=b;
267 if (b){panel.active=true;}
268 else {if ((!isSelected()) && (!panel.inside)){panel.active=false;}}
269 }
270
271 /**
272 * make a view blank (the view is erased and filled with a uniform color)
273 *@param c blank color (will fill the entire view) - put null to exit blank mode
274 */
275 public void setBlank(Color c){
276 if (c==null){
277 panel.blankColor=null;
278 panel.notBlank=true;
279 repaintNow();
280 }
281 else {
282 panel.blankColor=c;
283 panel.notBlank=false;
284 repaintNow();
285 }
286 }
287
288 /**
289 *tells if a view is in blank mode (returns the fill color) or not (returns null)
290 */
291 public Color isBlank(){
292 if (!panel.notBlank){
293 return panel.blankColor;
294 }
295 else return null;
296 }
297
298 /**
299 *Go in full screen mode and display this View's content - DOES NOT WORK FOR AccIView or IView or AppletView ; only for AccEView or EView (external views)
300 */
301 public abstract void goFullScreen(boolean b,DisplayMode dm);
302
303 public abstract boolean isFullScreen();
304
305 /**if true, compute the list of glyphs under mouse each time the view is repainted (default is false) - note that this list is computed each time the mouse is moved inside the view, no matter the policy*/
306 public void setComputeMouseOverListPolicy(boolean b){
307 panel.computeListAtEachRepaint=b;
308 }
309
310 /**activate the view means that it will be repainted*/
311 public void activate(){
312 parent.setActiveView(this);
313 panel.active=true;
314 if (panel.evH!=null){panel.evH.viewActivated(this);}
315 }
316
317 /**deactivate the view (will not be repainted unless setRepaintPolicy(true) or mouse inside the view)*/
318 public void deactivate(){
319 if ((!panel.alwaysRepaintMe) && (!panel.inside)){panel.active=false;}
320 if (panel.evH!=null){panel.evH.viewDeactivated(this);}
321 }
322
323 /**called from the window listener when the window is iconified - repaint is automatically disabled*/
324 void iconify(){
325 panel.active=false;
326 if (panel.evH!=null){panel.evH.viewIconified(this);}
327 }
328
329 /**called from the window listener when the window is deiconified - repaint is automatically re-enabled*/
330 void deiconify(){
331 panel.active=true;
332 if (panel.evH!=null){panel.evH.viewDeiconified(this);}
333 }
334
335 /**called from the window listener when the window is closed*/
336 protected void close(){
337 if (panel.evH!=null){panel.evH.viewClosing(this);}
338 }
339
340 /**call if the view should be repainted at once*/
341 void repaintNow(){
342 panel.repaintNow=true;
343 panel.newRequest=true;
344 }
345
346 /**gives access to the panel's Graphics object - can be useful in some cases, for instance to compute the bounds of a text string that has not yet been added to any virtual space. SHOULD NOT BE TAMPERED WITH. USE AT YOUR OWN RISKS!*/
347 public Graphics getGraphicsContext(){
348 return panel.g2;
349 }
350
351
352 //we have to specify the layer too (I think) write this later
353 // /**show/hide in this view the region seen through a camera (as a rectangle)
354 // *@param c the camera to be displayed (should not be one of the cameras composing this view)
355 // */
356 // public void showCamera(Camera c,boolean b,Color col){
357
358 // }
359
360 void buildConstraints(GridBagConstraints gbc, int gx,int gy,int gw,int gh,int wx,int wy){
361 gbc.gridx=gx;
362 gbc.gridy=gy;
363 gbc.gridwidth=gw;
364 gbc.gridheight=gh;
365 gbc.weightx=wx;
366 gbc.weighty=wy;
367 }
368
369 }