source: trunk/src/org/expeditee/gui/Browser.java@ 290

Last change on this file since 290 was 290, checked in by ra33, 16 years ago
File size: 12.0 KB
Line 
1package org.expeditee.gui;
2
3import java.awt.Color;
4import java.awt.Dimension;
5import java.awt.Graphics;
6import java.awt.Graphics2D;
7import java.awt.MouseInfo;
8import java.awt.Point;
9import java.awt.RenderingHints;
10import java.awt.Toolkit;
11import java.awt.event.ComponentEvent;
12import java.awt.event.ComponentListener;
13import java.awt.event.WindowEvent;
14import java.awt.event.WindowListener;
15import java.awt.event.WindowStateListener;
16import java.util.Collection;
17
18import javax.swing.JFrame;
19import javax.swing.RepaintManager;
20import javax.swing.SwingUtilities;
21
22import org.expeditee.AbsoluteLayout;
23import org.expeditee.actions.Actions;
24import org.expeditee.actions.Simple;
25import org.expeditee.agents.mail.MailSession;
26import org.expeditee.importer.FrameDNDTransferHandler;
27import org.expeditee.io.Logger;
28import org.expeditee.items.widgets.WidgetCacheManager;
29import org.expeditee.stats.StatsLogger;
30import org.expeditee.taskmanagement.EntitySaveManager;
31import org.expeditee.taskmanagement.SaveStateChangedEvent;
32import org.expeditee.taskmanagement.SaveStateChangedEventListener;
33
34/**
35 * The Main GUI class, comprises what people will see on the screen.<br>
36 * Note: Each Object (Item) is responsible for drawing itself on the screen.<br>
37 * Note2: The Frame is registered as a MouseListener and KeyListener, and
38 * processes any Events.
39 *
40 * @author jdm18
41 *
42 */
43public class Browser extends JFrame implements ComponentListener,
44 WindowListener, WindowStateListener, SaveStateChangedEventListener {
45
46 /**
47 * Default version - just to stop eclipse from complaining about it.
48 */
49 private static final long serialVersionUID = 1L;
50
51 // private static final JScrollPane scrollPane = new JScrollPane();
52
53 public static Browser _theBrowser = null;
54
55 // A flag which is set once the application is exiting.
56 private boolean _isExiting = false;
57
58 private static boolean _initComplete = false;
59
60 /**
61 * Constructs a new Browser object, then launches it
62 *
63 * @param args
64 */
65 public static void main(String[] args) {
66
67 // Prepare all expeditee and swing data on the AWT event thread.
68 SwingUtilities.invokeLater(new Runnable() {
69 public void run() {
70 // MessageBay.supressMessages(true);
71
72 // MessageBay.supressMessages(false);
73
74 _theBrowser = new Browser();
75 _theBrowser.requestFocus();
76 FrameMouseActions.MouseX = MouseInfo.getPointerInfo()
77 .getLocation().x
78 - _theBrowser.getOrigin().x;
79 FrameMouseActions.MouseY = MouseInfo.getPointerInfo()
80 .getLocation().y
81 - _theBrowser.getOrigin().y;
82 _initComplete = true;
83 }
84 });
85
86 }
87
88 public Point getOrigin() {
89 return getContentPane().getLocationOnScreen();
90 }
91
92 /**
93 * @return
94 *
95 * True if the application is about to exit. False if not. Not that this is
96 * only set once the window is in its closed state (not closing) or if the
97 * application has explicity being requested to exit.
98 *
99 * @see Browser#exit()
100 *
101 */
102 public boolean isExisting() {
103 return _isExiting;
104 }
105
106 private static boolean isInitComplete() {
107 return _initComplete;
108 }
109
110 public void setSizes(Dimension size) {
111 setSize(size);
112 setPreferredSize(size);
113 Dimension paneSize = getContentPane().getSize();
114 FrameGraphics.setMaxSize(paneSize);
115 }
116
117 private Browser() {
118 // Use the default values initially so we can load the profile frame
119 setSizes(new Dimension(UserSettings.InitialWidth,
120 UserSettings.InitialHeight));
121 // center the frame on the screen
122 Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
123 double xpos = screen.getWidth() / 2;
124 double ypos = screen.getHeight() / 2;
125 setLocation((int) (xpos - (UserSettings.InitialWidth / 2)),
126 (int) (ypos - (UserSettings.InitialHeight / 2)));
127
128 addWindowListener(this);
129 addWindowStateListener(this);
130
131 DisplayIO.addDisplayIOObserver(WidgetCacheManager.getInstance());
132 DisplayIO.addDisplayIOObserver(PopupManager.getInstance());
133
134 UserSettings.Init();
135 UserSettings.Username = FrameIO.ConvertToValidFramesetName(System
136 .getProperty("user.name"));
137 String userName = UserSettings.Username;
138 Frame profile = FrameIO.LoadProfile(userName);
139 if (profile == null) {
140 try {
141 profile = FrameIO.CreateNewProfile(userName);
142 } catch (Exception e) {
143 // TODO tell the user that there was a problem creating the
144 // profile frame and close nicely
145 e.printStackTrace();
146 assert (false);
147 }
148 }
149
150 // Need to display errors once things have been init otherwise
151 // exceptions occur if there are more than four messages neededing to be
152 // displayed.
153 Collection<String> warningMessages = FrameUtils.ParseProfile(profile);
154
155 // set the layout to absolute layout for widgets
156 this.getContentPane().setLayout(new AbsoluteLayout());
157 // enable the glasspane-for capturing all mouse events
158 this
159 .setGlassPane(new MouseEventRouter(getJMenuBar(),
160 getContentPane()));
161 this.getGlassPane().setVisible(true);
162 this.getContentPane().setBackground(Color.white);
163 this.getContentPane().setFocusTraversalKeysEnabled(false);
164
165 addComponentListener(this);
166 pack();
167
168 // Reset windows to user specified size
169 // Must be done after initialising the content pane above!
170 setSizes(new Dimension(UserSettings.InitialWidth,
171 UserSettings.InitialHeight));
172
173 // See java bug ID 4016934. They say that window closed events are
174 // called once the
175 // jframe is disposed.
176 setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
177
178 // Expeditee handles its own repainting of AWT/Swing components
179 RepaintManager.setCurrentManager(ExpediteeRepaintManager.getInstance());
180
181 // Listen for save status to display during and after runtime
182 EntitySaveManager.getInstance().addSaveStateChangedEventListener(this);
183
184 String version = System.getProperty("java.version");
185
186 if (version.startsWith("1.6")) {
187 // Set the drag and drop handler
188 setTransferHandler(FrameDNDTransferHandler.getInstance());
189 } else {
190 System.out.println("Upgrade to Java 1.6 to enable drag and drop");
191 }
192
193 try {
194 warningMessages.addAll(Actions.Init());
195
196 DisplayIO.Init(this);
197 // Set visible must be just after DisplayIO.Init for the message box
198 // to
199 // be the right size
200 setVisible(true);
201
202 setupGraphics();
203
204 // required to accept TAB key
205 setFocusTraversalKeysEnabled(false);
206
207 // Must be loaded after setupGraphics if images are on the frame
208 // Turn off XRay mode and load the first frame
209 FrameGraphics.setMode(FrameGraphics.MODE_NORMAL, false);
210 FrameUtils.loadFirstFrame(profile);
211 DisplayIO.UpdateTitle();
212
213 // I think this can be moved back up to the top of the Go method
214 // now...
215 // It used to crash the program trying to print error messages up
216 // the top
217 for (String message : warningMessages)
218 MessageBay.warningMessage(message);
219
220 FrameKeyboardActions keyboardListner = new FrameKeyboardActions();
221 this.getContentPane().addKeyListener(keyboardListner);
222 this.addKeyListener(keyboardListner);
223
224 FrameKeyboardActions.Refresh();
225 // setVisible(true);
226 } catch (Exception e) {
227 e.printStackTrace();
228 Logger.Log(e);
229 }
230 }
231
232 public Graphics2D g;
233
234 private void setupGraphics() {
235 if (g != null)
236 g.dispose();
237 g = (Graphics2D) this.getContentPane().getGraphics();
238 assert (g != null);
239 g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
240 RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
241 g.setFont(g.getFont().deriveFont(40f));
242 FrameGraphics.setDisplayGraphics(g);
243 }
244
245 // private int count = 0;
246 @Override
247 public void paint(Graphics g) {
248 // All this does is make sure the screen is repainted when the browser
249 // is moved so that some of the window is off the edge of the display
250 // then moved back into view
251 super.paint(g);
252 FrameGraphics.ForceRepaint();
253 // System.out.println("Paint " + count++);
254 }
255
256 /**
257 * @inheritDoc
258 */
259 public void componentResized(ComponentEvent e) {
260 setSizes(this.getSize());
261 setupGraphics();
262 FrameIO.RefreshCasheImages();
263 FrameGraphics.ForceRepaint();
264 }
265
266 /**
267 * @inheritDoc
268 */
269 public void componentMoved(ComponentEvent e) {
270 // FrameGraphics.setMaxSize(this.getSize());
271 }
272
273 /**
274 * @inheritDoc
275 */
276 public void componentShown(ComponentEvent e) {
277 }
278
279 /**
280 * @inheritDoc
281 */
282 public void componentHidden(ComponentEvent e) {
283 }
284
285 public void windowClosing(WindowEvent e) {
286 }
287
288 public void windowClosed(WindowEvent e) {
289 exit();
290 }
291
292 public void windowOpened(WindowEvent e) {
293 }
294
295 public void windowIconified(WindowEvent e) {
296 }
297
298 public void windowDeiconified(WindowEvent e) {
299 }
300
301 public void windowActivated(WindowEvent e) {
302 // System.out.println("Activated");
303 }
304
305 public void windowDeactivated(WindowEvent e) {
306 }
307
308 public void windowStateChanged(WindowEvent e) {
309 }
310
311 public int getDrawingAreaX() {
312 // return scrollPane.getLocationOnScreen().x;
313 return this.getLocationOnScreen().x;
314 }
315
316 public int getDrawingAreaY() {
317 // return scrollPane.getLocationOnScreen().y;
318 return this.getLocationOnScreen().y;
319 }
320
321 public void saveCompleted(SaveStateChangedEvent event) {
322 // if (isExisting()) {
323
324 // } else {
325 MessageBay.displayMessage("Save finished!", Color.BLUE);
326 // }
327 }
328
329 public void saveStarted(SaveStateChangedEvent event) {
330 // if (isExisting()) {
331
332 // } else {
333 String name = event.getEntity().getSaveName();
334 if (name == null)
335 name = "data";
336 MessageBay.displayMessage("Saving " + name + "...", Color.BLUE);
337 // }
338 }
339
340 /**
341 * Closes the browser and ends the application. Performs saving operations -
342 * halting until saves have completed. Feedback is given to the user while
343 * the application is exiting. Must call on the swing thread.
344 */
345 public void exit() {
346
347 // Set exiting flag
348 _isExiting = true;
349
350 MessageBay.displayMessage("System exiting...");
351
352 /**
353 * TODO: Prompt the user etc.
354 */
355
356 // TODO: Should we should a popup with a progress bar for user feedback?
357 // this would be nice and easy to do.
358 // Exit on a dedicated thread so that feedback can be obtained
359 new Exiter().start(); // this will exit the application
360 }
361
362 /**
363 * The system must exit on a different thread other than the swing thread so
364 * that the save threads can fire save-feedback to the swing thread and thus
365 * provide user feedback on asynchronous save operations.
366 *
367 * @author Brook Novak
368 *
369 */
370 private class Exiter extends Thread {
371
372 @Override
373 public void run() {
374
375 // The final save point for saveable entities
376 EntitySaveManager.getInstance().saveAll();
377 try {
378 EntitySaveManager.getInstance().waitUntilAllSavingFinished();
379 } catch (InterruptedException e) {
380 e.printStackTrace();
381 }
382
383 // The final phase must save on the swing thread since dealing with
384 // the expeditee data model
385 SwingUtilities.invokeLater(new Runnable() {
386 public void run() {
387
388 // Stop any agents or simple programs
389 Simple.stop();
390 Actions.stopAgent();
391 // Wait for them to stop
392 try {
393 MessageBay
394 .displayMessage("Stopping Simple programs..."); // TODO:
395 // Only
396 // stop
397 // if
398 // need
399 // to...
400 while (Simple.isProgramRunning()) {
401 Thread.sleep(100); // Brook: What purpose does this
402 // serve?
403 }
404 MessageBay.displayMessage("Stopping Agents..."); // TODO:
405 // Only
406 // stop
407 // if
408 // need
409 // to...
410 while (Actions.isAgentRunning()) {
411 Thread.sleep(100); // Brook: What purpose does this
412 // serve?
413 }
414 } catch (Exception e) {
415
416 }
417
418 MessageBay.displayMessage("Saving current frame...");
419 FrameIO.SaveFrame(DisplayIO.getCurrentFrame());
420
421 while (FrameIO.DeleteFrameset("messages"))
422 ;
423
424 MessageBay.displayMessage("Saving stats...");
425 StatsLogger.WriteStatsFile();
426
427 if (MailSession.getInstance() != null) {
428 if (MailSession.getInstance().finalise()) {
429 MessageBay.displayMessage("Closing ExpMail...");
430 }
431 }
432
433 MessageBay.displayMessage("System exited");
434 System.exit(0);
435 }
436 });
437 }
438 }
439
440 /**
441 * Used to set up the the browser for use in testing.
442 *
443 * @return
444 */
445 public static Browser initializeForTesting() {
446 if (Browser._theBrowser == null) {
447 MailSession._autoConnect = false;
448 Browser.main(null);
449 try {
450 while (!isInitComplete()) {
451 Thread.sleep(10);
452 }
453 } catch (Exception e) {
454 }
455 }
456 return _theBrowser;
457 }
458
459}
Note: See TracBrowser for help on using the repository browser.