source: trunk/org/expeditee/gui/DisplayIO.java@ 4

Last change on this file since 4 was 4, checked in by davidb, 16 years ago

Starting source code to Expeditee

File size: 15.0 KB
Line 
1package org.expeditee.gui;
2
3import java.awt.AWTException;
4import java.awt.Color;
5import java.awt.Cursor;
6import java.awt.Image;
7import java.awt.Point;
8import java.awt.Robot;
9import java.awt.Toolkit;
10import java.awt.image.MemoryImageSource;
11import java.util.List;
12import java.util.Stack;
13
14import javax.swing.JOptionPane;
15
16import org.expeditee.items.Item;
17import org.expeditee.items.ItemPermission;
18import org.expeditee.stats.SessionStats;
19
20/**
21 * This Interface is used by the Frame to control all display input and output.
22 *
23 * @author jdm18
24 *
25 */
26public class DisplayIO {
27
28 private static final int SMALL_CURSOR_SIZE = 16;
29
30 private static final int MEDIUM_CURSOR_SIZE = 32;
31
32 private static final int LARGE_CURSOR_SIZE = 64;
33
34 public static final Color DEFAULT_BACKGROUND = Color.WHITE;
35
36 /**
37 * The color to be used to highlight the linked parent item, when the user
38 * navigates backwards.
39 */
40 public static final Color BACK_HIGHLIGHT_COLOR = Color.MAGENTA;
41
42 private static Browser _Browser;
43
44 // The current Frame being displayed on the screen.
45 private static Frame _CurrentFrames[] = new Frame[2];
46
47 // Maintains the list of frames visited thus-far for back-tracking
48 @SuppressWarnings("unchecked")
49 private static Stack<String>[] _VisitedFrames = new Stack[2];
50
51 // used to change the mouse cursor position on the screen
52 private static Robot _Robot;
53
54 // public static JMenuBar _MenuBar = new JMenuBar();
55
56 private static boolean _TwinFrames = false;
57
58 /**
59 * The title to display in the Title bar.
60 */
61 public static final String TITLE = "Exp13Mar2008A";
62
63 private DisplayIO() {
64 }
65
66 public static void Init(Browser browser) {
67 _Browser = browser;
68 try {
69 _Robot = new Robot();
70 } catch (AWTException e) {
71 e.printStackTrace();
72 }
73
74 Point mouse = _Browser.getMousePosition();
75 if (mouse != null) {
76 FrameMouseActions.MouseX = mouse.x;
77 FrameMouseActions.MouseY = mouse.y;
78 }
79
80 _VisitedFrames[0] = new Stack<String>();
81 _VisitedFrames[1] = new Stack<String>();
82 UpdateTitle();
83 }
84
85 public static void setTextCursor(int size) {
86 if (cursorType == Item.TEXT_CURSOR)
87 return;
88
89 cursorType = Item.TEXT_CURSOR;
90
91 //Do some stuff to adjust the cursor size based on the font size
92 final int MEDIUM_CURSOR_CUTOFF = 31;
93 final int LARGE_CURSOR_CUTOFF = 62;
94
95 int cursorSize = LARGE_CURSOR_SIZE;
96 int hotspotPos = 0;
97 int start = 0;
98
99 if (size < MEDIUM_CURSOR_CUTOFF) {
100 cursorSize = MEDIUM_CURSOR_SIZE;
101 start = cursorSize - size - 2;
102 hotspotPos = cursorSize - (size + 2) / 4;
103 } else if (size < LARGE_CURSOR_CUTOFF) {
104 hotspotPos = cursorSize - (size - 5) / 4;
105 start = cursorSize - size - 2;
106 } else {
107 int FIXED_CURSOR_MIN = 77;
108 if (size >= FIXED_CURSOR_MIN) {
109 hotspotPos = cursorSize - 2;
110 } else {
111 hotspotPos = size - (FIXED_CURSOR_MIN - cursorSize);
112 }
113 }
114
115 /*System.out.println("hs: " + hotspotPos + " start: " + start + " font: "
116 + size + " cursor: " + (cursorSize - start));*/
117
118 int[] pixels = new int[cursorSize * cursorSize];
119
120 for (int i = start; i < cursorSize; i++)
121 pixels[i * cursorSize] = pixels[(i * cursorSize) + 1] = 0xFF000000;
122
123 Image image = Toolkit.getDefaultToolkit().createImage(
124 new MemoryImageSource(cursorSize, cursorSize, pixels, 0,
125 cursorSize));
126 Cursor textCursor = Toolkit.getDefaultToolkit().createCustomCursor(
127 image, new Point(0, hotspotPos), "textcursor");
128 _Browser.setCursor(textCursor);
129 }
130
131 /**
132 * Sets the type of cursor the display should be using
133 *
134 * @param type
135 * The type of cursor to display, using constants defined in the
136 * Cursor class.
137 */
138 public static void setCursor(int type) {
139 // avoid flicker when not changing
140 if (type == cursorType || type == Item.UNCHANGED_CURSOR)
141 return;
142
143 cursorType = type;
144
145 if (type == Item.HIDDEN_CURSOR) {
146 int[] pixels = new int[SMALL_CURSOR_SIZE * SMALL_CURSOR_SIZE];
147 Image image = Toolkit.getDefaultToolkit().createImage(
148 new MemoryImageSource(SMALL_CURSOR_SIZE, SMALL_CURSOR_SIZE,
149 pixels, 0, SMALL_CURSOR_SIZE));
150 Cursor transparentCursor = Toolkit.getDefaultToolkit()
151 .createCustomCursor(image, new Point(0, 0),
152 "invisiblecursor");
153 _Browser.setCursor(transparentCursor);
154 } else
155 _Browser.setCursor(new Cursor(type));
156 }
157
158 private static int cursorType = Item.DEFAULT_CURSOR;
159
160 public static int getCursor() {
161 return cursorType;
162 }
163
164 /**
165 * Moves the mouse cursor to the given x,y coordinates on the screen
166 *
167 * @param x
168 * The x coordinate
169 * @param y
170 * The y coordinate
171 */
172 public static void setCursorPosition(int x, int y) {
173 setCursorPosition(x, y, true);
174 }
175
176 public static void setCursorPosition(int x, int y, boolean forceArrow) {
177 y += getOffset();
178
179 if (Frame.itemAttachedToCursor()) {
180 List<Item> toMove = Frame.FreeItems;
181
182 int deltax = x - FrameMouseActions.MouseX;
183 int deltay = y - FrameMouseActions.MouseY;
184
185 for (Item move : toMove) {
186 move.setPosition(move.getX() + deltax, move.getY() + deltay);
187 }
188
189 // FrameGraphics.Repaint();
190
191 // if (!item.getArea().contains(x, y))
192 // item.setPosition(x, y);
193 }
194
195 if (_TwinFrames) {
196 if (getCurrentSide() == 1)
197 x += getMiddle();
198 }
199
200 // cheat
201 FrameMouseActions.setForceArrow(forceArrow);
202
203 // ensures the cursor doesn't fall behind while waiting for robot
204 FrameMouseActions.MouseX = x;
205 FrameMouseActions.MouseY = y;
206
207 _Robot.mouseMove(_Browser.getDrawingAreaX() + x, _Browser
208 .getDrawingAreaY()
209 + y);
210
211 }
212
213 public static void resetCursorOffset() {
214 FrameMouseActions.resetOffset();
215 }
216
217 public static void setCursorPosition(Point pos) {
218 setCursorPosition(pos.x, pos.y);
219 }
220
221 public static void setCursorPosition(Point pos, boolean forceArrow) {
222 setCursorPosition(pos.x, pos.y, forceArrow);
223 }
224
225 private static boolean _typed = false;
226
227 public static void setKeyTyped(boolean val) {
228 _typed = val;
229 }
230
231 public static boolean getKeyTyped() {
232 return _typed;
233 }
234
235 /**
236 * Forces a complete repaint of the GUI and Frame
237 */
238 public static void repaint() {
239 _Browser.repaint();
240 }
241
242 /**
243 * Returns the top item (last added) of the Back-Stack (which is popped off)
244 *
245 * @return The name of the last Frame added to the back-stack
246 */
247 public static String getLastFrame() {
248 int side = getCurrentSide();
249
250 if (_VisitedFrames[side].size() > 0)
251 return _VisitedFrames[side].pop();
252 else
253 return null;
254 }
255
256 /**
257 * Adds the given Frame to the back-stack
258 *
259 * @param frame
260 * The Frame to add
261 */
262 public static void addToBack(Frame toAdd) {
263 int side = getCurrentSide();
264
265 // do not allow duplicate frames
266 if (_VisitedFrames[side].size() > 0)
267 if (_VisitedFrames[side].peek().equals(toAdd.getFrameName())) {
268 return;
269 }
270
271 ItemPermission ip = FrameUtils.getCurrentItem();
272 if (ip == null || ip.Item == null)
273 _VisitedFrames[side].push(toAdd.getFrameName());
274 else
275 _VisitedFrames[side].push(toAdd.getFrameName());
276 }
277
278 /**
279 * Returns a 'peek' at the end element on the back-stack of the current
280 * side. If the back-stack is empty, null is returned.
281 *
282 * @return The name of the most recent Frame added to the back-stack, or
283 * null if the back-stack is empty.
284 */
285 public static String peekFromBack() {
286 int side = getCurrentSide();
287
288 // check that the stack is not empty
289 if (_VisitedFrames[side].size() > 0)
290 return _VisitedFrames[side].peek();
291
292 // if the stack is empty, return null
293 return null;
294 }
295
296 /**
297 * Sets the currently displayed Frame to the given Frame
298 *
299 * @param frame
300 * The Frame to display on the screen
301 */
302 public static void setCurrentFrame(Frame frame) {
303 if (frame == null)
304 return;
305
306 if (_TwinFrames) {
307 if (_CurrentFrames[0] == null) {
308 _CurrentFrames[0] = frame;
309 return;
310 }
311 if (_CurrentFrames[1] == null) {
312 _CurrentFrames[1] = frame;
313 return;
314 }
315 }
316
317 // if this is already the current frame
318 if (frame == getCurrentFrame()) {
319 FrameGraphics.Repaint();
320 FrameGraphics.DisplayMessage(frame.getFrameName()
321 + " is already the current frame.");
322 return;
323 } else {
324 SessionStats.AccessedFrame();
325 }
326
327 if (_TwinFrames) {
328 // if the same frame is being shown in both sides, load a fresh
329 // copy
330 // from disk
331 if (_CurrentFrames[getOppositeSide()] == frame
332 || _CurrentFrames[getOppositeSide()].getOverlays()
333 .contains(new Overlay(frame, 1))) {
334 FrameIO.SuspendCache();
335 frame = FrameIO.LoadFrame(frame.getFrameName());
336 FrameIO.ResumeCache();
337 }
338
339 _CurrentFrames[getCurrentSide()] = frame;
340 } else {
341 _CurrentFrames[getCurrentSide()] = frame;
342 frame.setMaxSize(FrameGraphics.getMaxFrameSize());
343 }
344
345 FrameGraphics.Repaint();
346 }
347
348 public static void UpdateTitle() {
349 StringBuffer title = new StringBuffer(TITLE);
350
351 if (FrameGraphics.isAudienceMode())
352 title.append(" - Audience Mode");
353 // title.append(SessionStats.getShortStats());*/
354
355 _Browser.setTitle(title.toString());
356 }
357
358 public static int getCurrentSide() {
359 if (_Browser == null)
360 return 0;
361
362 if (_TwinFrames
363 && FrameMouseActions.MouseX >= (_Browser.getWidth() / 2)
364 && _CurrentFrames[1] != null)
365 return 1;
366
367 if (_CurrentFrames[0] == null && _CurrentFrames[1] != null)
368 return 1;
369
370 return 0;
371 }
372
373 private static int getOppositeSide() {
374 if (getCurrentSide() == 0)
375 return 1;
376
377 return 0;
378 }
379
380 public static int FrameOnSide(Frame toFind) {
381 if (_CurrentFrames[0] == toFind)
382 return 0;
383
384 if (_CurrentFrames[1] == toFind)
385 return 1;
386
387 return -1;
388 }
389
390 /**
391 * Returns the Frame currently being displayed on the screen.
392 *
393 * @return The Frame currently displayed.
394 */
395 public static Frame getCurrentFrame() {
396 return _CurrentFrames[getCurrentSide()];
397 }
398
399 public static Frame getOppositeFrame() {
400 return _CurrentFrames[getOppositeSide()];
401 }
402
403 public static Frame[] getFrames() {
404 return _CurrentFrames;
405 }
406
407 public static int getMiddle() {
408 return _Browser.getWidth() / 2;
409 }
410
411 public static int getHeight() {
412 return _Browser.getHeight();
413 }
414
415 /**
416 * Adds the given JMenu to the JMenuBar of the GUI
417 *
418 * @param menu
419 * The menu to add
420 */
421 /*
422 * public static void addMenu(JMenu menu) { if (menu.getItemCount() == 0)
423 * return;
424 *
425 * _MenuBar.add(menu); // show progress _Browser.loadedMenu(menu.getText()); }
426 */
427
428 /**
429 * Performs the same action as if the user had clicked on the MenuItem at
430 * the given index in the Menu at the given index.
431 *
432 * @param menu
433 * The index of the menu (starts from 0)
434 * @param index
435 * The index of the Item to simulate a click on (starts from 0)
436 */
437 /*
438 * public static void activateMenuItem(int menu, int index) { if
439 * (_MenuBar.getComponentCount() < menu) return;
440 *
441 * JMenu act = _MenuBar.getMenu(menu);
442 *
443 * if (act.getComponentCount() < index) return;
444 *
445 * act.getItem(index).doClick(); }
446 *
447 * public static int getMenuHeight() { if (_MenuBar.getHeight() < 5) return
448 * 21;
449 *
450 * return _MenuBar.getHeight() - 5; }
451 */
452
453 /**
454 *
455 */
456 public static int getOffset() {
457 if (_Browser != null)
458 return /* getMenuHeight() + */_Browser.getTitleBarHeight();
459
460 // default offset (if the menu has not been created yet, etc)
461 return 0;
462 }
463
464 /**
465 * Returns the current mouse X coordinate. This coordinate is relative to
466 * the left edge of the frame the mouse is in. It takes into account the
467 * user being in twin frames mode.
468 *
469 * @return The X coordinate of the mouse.
470 */
471 public static int getMouseX() {
472 if (_TwinFrames && getMouseY() < FrameGraphics.getMaxSize().height)
473 return FrameMouseActions.MouseX % (_Browser.getWidth() / 2);
474
475 return FrameMouseActions.MouseX;
476 }
477
478 /**
479 * Returns the current mouse Y coordinate. This is relative to the top of
480 * the frame.
481 *
482 * @return The Y coordinate of the mouse.
483 */
484 public static int getMouseY() {
485 return FrameMouseActions.MouseY - getOffset();
486 }
487
488 public static int getRealMouseX() {
489 return FrameMouseActions.MouseX;
490 }
491
492 public static int getRealMouseY() {
493 return FrameMouseActions.MouseY;
494 }
495
496 public static void Back() {
497 int side = getCurrentSide();
498
499 // there must be a frame to go back to
500 if (_VisitedFrames[side].size() < 1) {
501 FrameGraphics.DisplayMessage("You are already on the home frame");
502 return;
503 }
504
505 if (!FrameUtils.LeavingFrame(getCurrentFrame())) {
506 FrameGraphics.DisplayMessage("Back operation cancelled");
507 return;
508 }
509
510 String oldFrame = getCurrentFrame().getFrameName().toLowerCase();
511
512 // do not get a cached version (in case it is in the other window)
513 if (isTwinFramesOn())
514 FrameIO.SuspendCache();
515 Frame frame = FrameIO.LoadFrame(_VisitedFrames[side].pop());
516 if (isTwinFramesOn())
517 FrameIO.ResumeCache();
518
519 FrameUtils.DisplayFrame(frame, false);
520 FrameMouseActions.setHighlightHold(true);
521
522 for (Item i : frame.getItems())
523 if (i.getLink() != null
524 && i.getLink().toLowerCase().equals(oldFrame)) {
525 i.showHighlight(true, BACK_HIGHLIGHT_COLOR);
526 }
527
528 FrameGraphics.Repaint();
529 }
530
531 /**
532 * Toggles the display of frames between TwinFrames mode and Single frame
533 * mode.
534 */
535 public static void ToggleTwinFrames() {
536 // determine which side is the active side
537 int opposite = getOppositeSide();
538 int current = getCurrentSide();
539 _TwinFrames = !_TwinFrames;
540
541 // if TwinFrames is being turned on
542 if (_TwinFrames) {
543 // if this is the first time TwinFrames has been toggled on,
544 // load
545 // the user's first frame
546 if (_VisitedFrames[opposite].size() == 0) {
547 FrameIO.SuspendCache();
548 setCurrentFrame(FrameIO.LoadFrame(UserSettings.FirstFrame));
549 FrameIO.ResumeCache();
550 } else {
551 // otherwise, restore the frame from the side's back-stack
552 setCurrentFrame(FrameIO.LoadFrame(_VisitedFrames[opposite]
553 .pop()));
554 }
555
556 // else, TwinFrames is being turned off
557 } else {
558 // add the frame to the back-stack
559 Frame hiding = _CurrentFrames[opposite];
560 FrameUtils.LeavingFrame(hiding);
561 _VisitedFrames[opposite].add(hiding.getFrameName());
562 _CurrentFrames[opposite] = null;
563 _CurrentFrames[current].setMaxSize(FrameGraphics.getMaxFrameSize());
564 }
565 if (_CurrentFrames[current] != null)
566 _CurrentFrames[current].setMaxSize(FrameGraphics.getMaxFrameSize());
567 if (_CurrentFrames[opposite] != null)
568 _CurrentFrames[opposite]
569 .setMaxSize(FrameGraphics.getMaxFrameSize());
570
571 FrameGraphics.Clear();
572 FrameGraphics.Repaint();
573 }
574
575 public static boolean isTwinFramesOn() {
576 return _TwinFrames;
577 }
578
579 public static void Reload(int side) {
580 if (side < 0)
581 return;
582
583 FrameIO.SuspendCache();
584 _CurrentFrames[side] = FrameIO.LoadFrame(_CurrentFrames[side]
585 .getFrameName());
586 FrameIO.ResumeCache();
587 }
588
589 public static boolean DisplayConfirmDialog(String message, String title,
590 int type, int options, int res) {
591 return JOptionPane.showConfirmDialog(_Browser, message, title, options,
592 type) == res;
593 }
594
595 public static final int RESULT_OK = JOptionPane.OK_OPTION;
596
597 public static final int OPTIONS_OK_CANCEL = JOptionPane.OK_CANCEL_OPTION;
598
599 public static final int TYPE_WARNING = JOptionPane.WARNING_MESSAGE;
600
601 public static void pressMouse(int buttons) {
602 _Robot.mousePress(buttons);
603 }
604
605 public static void releaseMouse(int buttons) {
606 _Robot.mouseRelease(buttons);
607 }
608
609 public static void clickMouse(int buttons) {
610 _Robot.mousePress(buttons);
611 _Robot.mouseRelease(buttons);
612 }
613}
Note: See TracBrowser for help on using the repository browser.