source: trunk/src/org/expeditee/actions/Misc.java@ 108

Last change on this file since 108 was 108, checked in by ra33, 16 years ago

Heaps of changes!!!!
Added circles...
Better drawing of lines etc etc

File size: 17.7 KB
Line 
1package org.expeditee.actions;
2
3import java.awt.Color;
4import java.awt.Dimension;
5import java.awt.Image;
6import java.awt.image.BufferedImage;
7import java.awt.image.VolatileImage;
8import java.io.File;
9import java.io.FileNotFoundException;
10import java.io.IOException;
11import java.lang.reflect.Method;
12import java.util.ArrayList;
13import java.util.Collection;
14import java.util.List;
15
16import javax.imageio.ImageIO;
17
18import org.expeditee.gui.DisplayIO;
19import org.expeditee.gui.Frame;
20import org.expeditee.gui.FrameGraphics;
21import org.expeditee.gui.FrameIO;
22import org.expeditee.gui.FrameMouseActions;
23import org.expeditee.gui.TimeKeeper;
24import org.expeditee.items.Item;
25import org.expeditee.items.Text;
26import org.expeditee.stats.CometStats;
27import org.expeditee.stats.SessionStats;
28import org.expeditee.stats.StatsLogger;
29import org.expeditee.stats.TreeStats;
30
31/**
32 * A list of miscellaneous Actions and Actions specific to Expeditee
33 *
34 */
35public class Misc {
36 private static final int FRAME_FILE_FONT_SIZE = 10;
37
38 /**
39 * Causes the system to beep
40 */
41 public static void Beep() {
42 java.awt.Toolkit.getDefaultToolkit().beep();
43 }
44
45 /**
46 * Forces a repaint of the current Frame
47 */
48 public static void Display() {
49 FrameGraphics.ForceRepaint();
50 }
51
52 /**
53 * Restores the current frame to the last saved version currently on the
54 * hard disk
55 */
56 public static void Restore() {
57 FrameIO.Reload();
58 // FrameGraphics.DisplayMessage("Restoration complete.");
59 }
60
61 /**
62 * Toggles AudienceMode on or off
63 */
64 public static void ToggleAudienceMode() {
65 FrameGraphics.ToggleAudienceMode();
66 }
67
68 /**
69 * Toggles TwinFrames mode on or off
70 */
71 public static void ToggleTwinFramesMode() {
72 DisplayIO.ToggleTwinFrames();
73 }
74
75 /**
76 * Exits the System
77 */
78 public static void Exit() {
79 /**
80 * TODO: Prompt the user etc.
81 */
82 FrameIO.SaveFrame(DisplayIO.getCurrentFrame());
83
84 while (FrameIO.DeleteFrameset("messages"))
85 ;
86
87 StatsLogger.WriteStatsFile();
88
89 System.exit(0);
90 }
91
92 /**
93 * If the given Item is a Text Item, then the text of the Item is
94 * interpreted as actions, if not this method does nothing.
95 *
96 * @param current
97 * The Item to read the Actions from
98 */
99 public static void RunCurrentItem(Item current) {
100 if (current instanceof Text) {
101 List<String> actions = ((Text) current).getTextList();
102
103 for (String action : actions) {
104 Actions.PerformAction(DisplayIO.getCurrentFrame(), current,
105 action);
106 }
107 }
108
109 }
110
111 /**
112 * Prompts the user to confirm deletion of the current Frame, and deletes if
113 * the user chooses. After deletion this action calls back(), to ensure the
114 * deleted frame is not still being shown
115 *
116 */
117 public static void DeleteFrame() {
118 Frame toDelete = DisplayIO.getCurrentFrame();
119 String deletedFrame = toDelete.getName();
120 String deletedFrameNameLowercase = deletedFrame.toLowerCase();
121 String errorMessage = "Error deleting " + deletedFrame;
122 try {
123 if (FrameIO.DeleteFrame(toDelete)) {
124 Frame current = DisplayIO.getCurrentFrame();
125 for (Item i : current.getItems())
126 if (i.getLink() != null
127 && i.getAbsoluteLink().toLowerCase().equals(
128 deletedFrameNameLowercase)) {
129 i.setLink(null);
130 }
131 DisplayIO.Back();
132 FrameGraphics.Repaint();
133 FrameGraphics.DisplayMessage(deletedFrame + " deleted");
134 return;
135 }
136 } catch (IOException ioe){
137 if(ioe.getMessage() != null )
138 errorMessage += ". " + ioe.getMessage();
139 } catch (SecurityException se) {
140 if(se.getMessage() != null )
141 errorMessage += ". " + se.getMessage();
142 } catch (Exception e) {
143 e.printStackTrace();
144 }
145 FrameGraphics.ErrorMessage(errorMessage);
146 }
147
148 /**
149 * Loads the Frame linked to by the given Item. The first Item on the Frame
150 * that is not the title or name is then placed on the cursor. If the given
151 * Item has no link, or no item is found then this is a no-op.
152 *
153 * @param current
154 * The Item that links to the Frame that the Item will be loaded
155 * from.
156 */
157 public static void GetItemFromChildFrame(Item current) {
158 getFromChildFrame(current, false);
159 }
160
161 /**
162 * Loads the Frame linked to by the given Item. The first Text Item on the
163 * Frame that is not the title or name is then placed on the cursor. If the
164 * given Item has no link, or no item is found then this is a no-op.
165 *
166 * @param current
167 * The Item that links to the Frame that the Item will be loaded
168 * from.
169 */
170 public static void GetTextFromChildFrame(Item current) {
171 getFromChildFrame(current, true);
172 }
173
174 private static void getFromChildFrame(Item current, boolean textOnly) {
175 Item item = getFirstBodyItemOnChildFrame(current, textOnly);
176 // if no item was found
177 if (item == null) {
178 return;
179 }
180
181 // copy the item and switch
182 item = item.copy();
183 item.setPosition(DisplayIO.getMouseX(), FrameMouseActions.getY());
184 item.setParent(null);
185
186 FrameMouseActions.pickup(item);
187 FrameGraphics.Repaint();
188 }
189
190 /**
191 * Sets the given Item to have the Given Color. Color can be null (for
192 * default)
193 *
194 * @param toChange
195 * The Item to set the Color.
196 * @param toUse
197 * The Color to give the Item.
198 */
199 public static void SetCurrentItemBackgroundColor(Item toChange, Color toUse) {
200 if (toChange == null)
201 return;
202
203 toChange.setBackgroundColor(toUse);
204 FrameGraphics.Repaint();
205 }
206
207 /**
208 * Sets the given Item to have the Given Color. Color can be null (for
209 * default)
210 *
211 * @param toChange
212 * The Item to set the Color.
213 * @param toUse
214 * The Color to give the Item.
215 */
216 public static void SetCurrentItemColor(Item toChange, Color toUse) {
217 if (toChange == null)
218 return;
219
220 toChange.setColor(toUse);
221 FrameGraphics.Repaint();
222 }
223
224 /**
225 * Creates a new Text Object containing general statistics for the current
226 * session. The newly created Text Object is then attached to the cursor via
227 * FrameMouseActions.pickup(Item)
228 */
229 public static void GetSessionStats() {
230 CreateTextItem(SessionStats.getCurrentStats());
231 }
232
233 /**
234 * Creates a new Text Object containing statistics for the current tree.
235 */
236 public static void GetCometStats(Frame frame) {
237 TimeKeeper timer = new TimeKeeper();
238 FrameGraphics.DisplayMessage("Computing comet stats...");
239
240 CometStats cometStats = new CometStats(frame);
241 CreateTextItem(cometStats.toString());
242 FrameGraphics.OverwriteMessage("Comet stats time: "
243 + timer.getElapsedStringSeconds());
244 }
245
246 public static void GetTreeStats(Frame frame) {
247 TimeKeeper timer = new TimeKeeper();
248 FrameGraphics.DisplayMessage("Computing tree stats...");
249
250 TreeStats treeStats = new TreeStats(frame);
251 CreateTextItem(treeStats.toString());
252 FrameGraphics.OverwriteMessage("Tree stats time: "
253 + timer.getElapsedStringSeconds());
254 }
255
256 public static void CreateTextItem(String itemText) {
257 SessionStats.CreatedText();
258 Frame current = DisplayIO.getCurrentFrame();
259 Item text = current.getStatsTextItem(itemText);
260 FrameMouseActions.pickup(text);
261 FrameGraphics.Repaint();
262 }
263
264 /**
265 * Creates a new Text Object containing statistics for moving, deleting and
266 * creating items in the current session. The newly created Text Object is
267 * then attached to the cursor via FrameMouseActions.pickup(Item)
268 */
269 public static void GetItemStats() {
270 CreateTextItem(SessionStats.getItemStats());
271 }
272
273 /**
274 * Creates a new Text Object containing statistics for the time between
275 * events triggered by the user through mouse clicks and key presses. The
276 * newly created Text Object is then attached to the cursor via
277 * FrameMouseActions.pickup(Item)
278 */
279 public static void GetEventStats() {
280 CreateTextItem(SessionStats.getEventStats());
281 }
282
283 /**
284 * Creates a new Text Object containing the contents of the current frames
285 * file.
286 */
287 public static void GetCurrentFrameFile() {
288
289 Frame current = DisplayIO.getCurrentFrame();
290 current.change();
291 String fileContents = FrameIO.SaveFrame(current);
292
293 Text text = current.createNewText();
294 // We dont want the stats to wrap at all
295 text.setMaxSize(new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE));
296
297 text.setText(fileContents);
298
299 text.setPosition(DisplayIO.getMouseX(), FrameMouseActions.getY());
300 text.setSize(FRAME_FILE_FONT_SIZE);
301
302 FrameMouseActions.pickup(text);
303
304 FrameGraphics.Repaint();
305 }
306
307 /**
308 * Creates a new Text Object containing the available fonts.
309 */
310 public static void GetAvailableFontFamilyNames() {
311
312 Collection<String> availableFonts = Actions._Fonts.values();
313 StringBuilder fontsList = new StringBuilder();
314 for (String s : availableFonts) {
315 fontsList.append(s).append('\n');
316 }
317 fontsList.deleteCharAt(fontsList.length()-1);
318
319 Text text = DisplayIO.getCurrentFrame().createNewText();
320 // We dont want the stats to wrap at all
321 text.setMaxSize(new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE));
322 text.setText(fontsList.toString());
323
324 text.setPosition(DisplayIO.getMouseX(), FrameMouseActions.getY());
325 text.setSize(FRAME_FILE_FONT_SIZE);
326
327 FrameMouseActions.pickup(text);
328
329 FrameGraphics.Repaint();
330 }
331
332 /**
333 * Resets the statistics back to zero.
334 */
335 public static void ResetStats() {
336 StatsLogger.WriteStatsFile();
337 SessionStats.resetStats();
338 }
339
340 /**
341 * Loads a frame with the given name and saves it as a JPEG image.
342 *
343 * @param framename
344 * The name of the Frame to save
345 */
346 public static void JpegFrame(String framename) {
347 ImageFrame(framename, "JPEG");
348 }
349
350 /**
351 * Saves the current frame as a JPEG image. This is the same as calling
352 * JpegFrame(currentFrame.getName())
353 */
354 public static void JpegFrame() {
355 ImageFrame(DisplayIO.getCurrentFrame().getName(), "JPEG");
356 }
357
358 public static void JPGFrame() {
359 JpegFrame();
360 }
361
362 /**
363 * Loads a frame with the given name and saves it as a PNG image.
364 *
365 * @param framename
366 * The name of the Frame to save
367 */
368 public static void PNGFrame(String framename) {
369 ImageFrame(framename, "PNG");
370 }
371
372 /**
373 * Saves the current frame as a PNG image. This is the same as calling
374 * PNGFrame(currentFrame.getName())
375 */
376 public static void PNGFrame() {
377 ImageFrame(DisplayIO.getCurrentFrame().getName(), "PNG");
378 }
379
380 public static String SaveImage(BufferedImage screen, String format,
381 String directory, String fileName) {
382 // Check if we need to append the suffix
383 if (fileName.indexOf('.') < 0)
384 fileName += "." + format.toLowerCase();
385
386 try {
387 // set up the file for output
388 String fullFileName = directory + fileName;
389 File out = new File(fullFileName);
390 if (!out.getParentFile().exists())
391 out.mkdirs();
392
393 // If the image is successfully written out return the fileName
394 if (ImageIO.write(screen, format, out))
395 return fileName;
396
397 } catch (Exception e) {
398 e.printStackTrace();
399 }
400 return null;
401 }
402
403 public static String ImageFrame(Frame frame, String format, String directory) {
404 assert (frame != null);
405
406 FrameGraphics.UpdateBuffer(frame, false);
407
408 BufferedImage screen = null;
409 Image frameBuffer = frame.getBuffer();
410 if (frame.getBuffer() instanceof BufferedImage) {
411 screen = (BufferedImage) frameBuffer;
412 } else if (frameBuffer instanceof VolatileImage) {
413 screen = ((VolatileImage) frameBuffer).getSnapshot();
414 } else {
415 assert (false);
416 }
417 return SaveImage(screen, format, directory, frame.getExportFileName());
418 }
419
420 /**
421 * Saves the Frame with the given Framename as an image of the given format.
422 *
423 * @param framename
424 * The name of the Frame to save as an image
425 * @param format
426 * The Image format to use (i.e. "PNG", "BMP", etc)
427 */
428 public static void ImageFrame(String framename, String format) {
429 Frame loaded = FrameIO.LoadFrame(framename);
430
431 // if the frame was loaded successfully
432 if (loaded != null) {
433 String path = FrameIO.IMAGES_PATH;
434 String frameName = ImageFrame(loaded, format, path);
435 if (frameName != null)
436 FrameGraphics.DisplayMessage("Frame successfully saved to "
437 + path + frameName);
438 else
439 FrameGraphics.ErrorMessage("Could not find image writer for "
440 + format + " format");
441 // if the frame was not loaded successfully, alert the user
442 } else
443 FrameGraphics.DisplayMessage("Frame '" + framename
444 + "' could not be found.");
445 }
446
447 /**
448 * Displays a message in the message box area.
449 *
450 * @param message
451 * the message to display
452 */
453 public static void MessageLn(String message) {
454 FrameGraphics.DisplayMessage(message);
455 }
456
457 public static void MessageLn2(String message, String message2) {
458 FrameGraphics.DisplayMessage(message + " " + message2);
459 }
460
461 public static void CopyFile(String existingFile, String newFileName) {
462 try {
463 // TODO is there a built in method which will do this faster?
464
465 FrameGraphics.DisplayMessage("Copying file " + existingFile
466 + " to " + newFileName + "...");
467 FrameIO.copyFile(existingFile, newFileName);
468 FrameGraphics.DisplayMessage("File copied successfully");
469 } catch (FileNotFoundException e) {
470 FrameGraphics.DisplayMessage("Error opening file: " + existingFile);
471 } catch (Exception e) {
472 FrameGraphics.DisplayMessage("File could not be copied");
473 }
474 }
475
476 /**
477 * Runs two methods alternatively a specified number of times and reports on
478 * the time spent running each method.
479 *
480 * @param fullMethodNameA
481 * @param fullMethodNameB
482 * @param repsPerTest
483 * the number of time each method is run per test
484 * @param tests
485 * the number of tests to conduct
486 *
487 */
488 public static void CompareMethods(String fullMethodNameA,
489 String fullMethodNameB, int repsPerTest, int tests) {
490 try {
491 String classNameA = getClassName(fullMethodNameA);
492 String classNameB = getClassName(fullMethodNameB);
493 String methodNameA = getMethodName(fullMethodNameA);
494 String methodNameB = getMethodName(fullMethodNameB);
495
496 Class classA = Class.forName(classNameA);
497 Class classB = Class.forName(classNameB);
498 Method methodA = classA.getDeclaredMethod(methodNameA,
499 new Class[] {});
500 Method methodB = classB.getDeclaredMethod(methodNameB,
501 new Class[] {});
502 TimeKeeper timeKeeper = new TimeKeeper();
503 long timeA = 0;
504 long timeB = 0;
505 // Run the tests
506 for (int i = 0; i < tests; i++) {
507 // Test methodA
508 timeKeeper.restart();
509 for (int j = 0; j < repsPerTest; j++) {
510 methodA.invoke((Object) null, new Object[] {});
511 }
512 timeA += timeKeeper.getElapsedMillis();
513 timeKeeper.restart();
514 // Test methodB
515 for (int j = 0; j < repsPerTest; j++) {
516 methodB.invoke((Object) null, new Object[] {});
517 }
518 timeB += timeKeeper.getElapsedMillis();
519 }
520
521 float aveTimeA = timeA * 1000F / repsPerTest / tests;
522 float aveTimeB = timeB * 1000F / repsPerTest / tests;
523 // Display Results
524 FrameGraphics.DisplayMessage("Average Execution Time");
525 FrameGraphics.DisplayMessage(methodNameA + ": "
526 + TimeKeeper.Formatter.format(aveTimeA) + "us");
527 FrameGraphics.DisplayMessage(methodNameB + ": "
528 + TimeKeeper.Formatter.format(aveTimeB) + "us");
529 } catch (Exception e) {
530 FrameGraphics.ErrorMessage(e.getClass().getSimpleName() + ": "
531 + e.getMessage());
532 }
533 }
534
535 public static String getClassName(String fullMethodName) {
536 assert (fullMethodName != null);
537 assert (fullMethodName.length() > 0);
538 int lastPeriod = fullMethodName.lastIndexOf('.');
539 if (lastPeriod > 0 && lastPeriod < fullMethodName.length() - 1)
540 return fullMethodName.substring(0, lastPeriod);
541 throw new RuntimeException("Invalid method name: " + fullMethodName);
542 }
543
544 public static String getMethodName(String methodName) {
545 assert (methodName != null);
546 assert (methodName.length() > 0);
547 int lastPeriod = methodName.lastIndexOf('.');
548 if (lastPeriod > 0 && lastPeriod < methodName.length() - 1)
549 return methodName.substring(1 + lastPeriod);
550 throw new RuntimeException("Invalid method name: " + methodName);
551 }
552
553 /**
554 * Loads the Frame linked to by the given Item. The first Item on the Frame
555 * that is not the title or name is then placed on the current frame. The
556 * item that was clicked on is placed on the frame it was linked to and the
557 * link is switched to the item from the child frame. If the given Item has
558 * no link, or no item is found then this is a no-op.
559 *
560 * @param current
561 * The Item that links to the Frame that the Item will be loaded
562 * from.
563 */
564 public static void SwapItemWithItemOnChildFrame(Item current) {
565 Item item = getFirstBodyItemOnChildFrame(current, false);
566 // if no item was found
567 if (item == null) {
568 return;
569 }
570
571 // swap the items parents
572 Frame parentFrame = current.getParent();
573 Frame childFrame = item.getParent();
574 current.setParent(childFrame);
575 item.setParent(parentFrame);
576
577 // swap the items on the frames
578 parentFrame.removeItem(current);
579 childFrame.removeItem(item);
580 parentFrame.addItem(item);
581 childFrame.addItem(current);
582
583 // swap the items links
584 item.setActions(current.getAction());
585 item.setLink(childFrame.getName());
586 current.setLink(parentFrame.getName());
587 // current.setLink(null);
588 current.setActions(null);
589
590 FrameGraphics.Repaint();
591 }
592
593 private static Item getFirstBodyItemOnChildFrame(Item current,
594 boolean textOnly) {
595 // the item must link to a frame
596 if (current.getLink() == null) {
597 FrameGraphics
598 .DisplayMessage("Cannot get item from child - this item has no link");
599 return null;
600 }
601
602 Frame child = FrameIO.LoadFrame(current.getAbsoluteLink());
603
604 // if the frame could not be loaded
605 if (child == null) {
606 FrameGraphics.ErrorMessage("Could not load child frame.");
607 return null;
608 }
609
610 // find the first non-title and non-name item
611 List<Item> body = new ArrayList<Item>();
612 if (textOnly)
613 body.addAll(child.getBodyTextItems(false));
614 else
615 body.addAll(child.getItems());
616 Item item = null;
617
618 for (Item i : body)
619 if (i != child.getTitleItem() && !i.isAnnotation()) {
620 item = i;
621 break;
622 }
623
624 // if no item was found
625 if (item == null) {
626 FrameGraphics.DisplayMessage("No item found to copy");
627 return null;
628 }
629
630 return item;
631 }
632}
Note: See TracBrowser for help on using the repository browser.