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

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

Lots of changes!!

File size: 17.8 KB
Line 
1package org.expeditee.actions;
2
3import java.awt.Color;
4import java.awt.Dimension;
5import java.awt.GraphicsEnvironment;
6import java.awt.Image;
7import java.awt.image.BufferedImage;
8import java.awt.image.VolatileImage;
9import java.io.File;
10import java.io.FileNotFoundException;
11import java.io.IOException;
12import java.lang.reflect.Method;
13import java.util.ArrayList;
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 KMS 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(), DisplayIO.getMouseY());
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, true);
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, true);
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 text.setSelectedMode(Item.SelectedMode.Normal);
261 text.setSelectedMode(Item.SelectedMode.None);
262 FrameMouseActions.pickup(text);
263 FrameGraphics.Repaint();
264 }
265
266 /**
267 * Creates a new Text Object containing statistics for moving, deleting and
268 * creating items in the current session. The newly created Text Object is
269 * then attached to the cursor via FrameMouseActions.pickup(Item)
270 */
271 public static void GetItemStats() {
272 CreateTextItem(SessionStats.getItemStats());
273 }
274
275 /**
276 * Creates a new Text Object containing statistics for the time between
277 * events triggered by the user through mouse clicks and key presses. The
278 * newly created Text Object is then attached to the cursor via
279 * FrameMouseActions.pickup(Item)
280 */
281 public static void GetEventStats() {
282 CreateTextItem(SessionStats.getEventStats());
283 }
284
285 /**
286 * Creates a new Text Object containing the contents of the current frames
287 * file.
288 */
289 public static void GetCurrentFrameFile() {
290
291 Frame current = DisplayIO.getCurrentFrame();
292 current.change();
293 String fileContents = FrameIO.SaveFrame(current);
294
295 Text text = current.createNewText();
296 // We dont want the stats to wrap at all
297 text.setMaxSize(new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE));
298
299 text.setText(fileContents);
300
301 text.setPosition(DisplayIO.getMouseX(), DisplayIO.getMouseY());
302 text.setSize(FRAME_FILE_FONT_SIZE);
303
304 FrameMouseActions.pickup(text);
305
306 FrameGraphics.Repaint();
307 }
308
309 /**
310 * Creates a new Text Object containing the available fonts.
311 */
312 public static void GetAvailableFontFamilyNames() {
313
314 String[] availableFonts = GraphicsEnvironment
315 .getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
316 StringBuilder fontsList = new StringBuilder();
317 for (String s : availableFonts) {
318 fontsList.append(s).append('\n');
319 }
320
321 Text text = DisplayIO.getCurrentFrame().createNewText();
322 // We dont want the stats to wrap at all
323 text.setMaxSize(new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE));
324 text.setText(fontsList.toString());
325
326 text.setPosition(DisplayIO.getMouseX(), DisplayIO.getMouseY());
327 text.setSize(FRAME_FILE_FONT_SIZE);
328
329 FrameMouseActions.pickup(text);
330
331 FrameGraphics.Repaint();
332 }
333
334 /**
335 * Resets the statistics back to zero.
336 */
337 public static void ResetStats() {
338 StatsLogger.WriteStatsFile();
339 SessionStats.resetStats();
340 }
341
342 /**
343 * Loads a frame with the given name and saves it as a JPEG image.
344 *
345 * @param framename
346 * The name of the Frame to save
347 */
348 public static void JpegFrame(String framename) {
349 ImageFrame(framename, "JPEG");
350 }
351
352 /**
353 * Saves the current frame as a JPEG image. This is the same as calling
354 * JpegFrame(currentFrame.getName())
355 */
356 public static void JpegFrame() {
357 ImageFrame(DisplayIO.getCurrentFrame().getName(), "JPEG");
358 }
359
360 public static void JPGFrame() {
361 JpegFrame();
362 }
363
364 /**
365 * Loads a frame with the given name and saves it as a PNG image.
366 *
367 * @param framename
368 * The name of the Frame to save
369 */
370 public static void PNGFrame(String framename) {
371 ImageFrame(framename, "PNG");
372 }
373
374 /**
375 * Saves the current frame as a PNG image. This is the same as calling
376 * PNGFrame(currentFrame.getName())
377 */
378 public static void PNGFrame() {
379 ImageFrame(DisplayIO.getCurrentFrame().getName(), "PNG");
380 }
381
382 public static String SaveImage(BufferedImage screen, String format,
383 String directory, String fileName) {
384 // Check if we need to append the suffix
385 if (fileName.indexOf('.') < 0)
386 fileName += "." + format.toLowerCase();
387
388 try {
389 // set up the file for output
390 String fullFileName = directory + fileName;
391 File out = new File(fullFileName);
392 if (!out.getParentFile().exists())
393 out.mkdirs();
394
395 // If the image is successfully written out return the fileName
396 if (ImageIO.write(screen, format, out))
397 return fileName;
398
399 } catch (Exception e) {
400 e.printStackTrace();
401 }
402 return null;
403 }
404
405 public static String ImageFrame(Frame frame, String format, String directory) {
406 assert (frame != null);
407
408 FrameGraphics.UpdateBuffer(frame, false);
409
410 BufferedImage screen = null;
411 Image frameBuffer = frame.getBuffer();
412 if (frame.getBuffer() instanceof BufferedImage) {
413 screen = (BufferedImage) frameBuffer;
414 } else if (frameBuffer instanceof VolatileImage) {
415 screen = ((VolatileImage) frameBuffer).getSnapshot();
416 } else {
417 assert (false);
418 }
419 return SaveImage(screen, format, directory, frame.getExportFileName());
420 }
421
422 /**
423 * Saves the Frame with the given Framename as an image of the given format.
424 *
425 * @param framename
426 * The name of the Frame to save as an image
427 * @param format
428 * The Image format to use (i.e. "PNG", "BMP", etc)
429 */
430 public static void ImageFrame(String framename, String format) {
431 Frame loaded = FrameIO.LoadFrame(framename);
432
433 // if the frame was loaded successfully
434 if (loaded != null) {
435 String path = FrameIO.IMAGES_PATH;
436 String frameName = ImageFrame(loaded, format, path);
437 if (frameName != null)
438 FrameGraphics.DisplayMessage("Frame successfully saved to "
439 + path + frameName);
440 else
441 FrameGraphics.ErrorMessage("Could not find image writer for "
442 + format + " format");
443 // if the frame was not loaded successfully, alert the user
444 } else
445 FrameGraphics.DisplayMessage("Frame '" + framename
446 + "' could not be found.");
447 }
448
449 /**
450 * Displays a message in the message box area.
451 *
452 * @param message
453 * the message to display
454 */
455 public static void MessageLn(String message) {
456 FrameGraphics.DisplayMessage(message);
457 }
458
459 public static void MessageLn2(String message, String message2) {
460 FrameGraphics.DisplayMessage(message + " " + message2);
461 }
462
463 public static void CopyFile(String existingFile, String newFileName) {
464 try {
465 // TODO is there a built in method which will do this faster?
466
467 FrameGraphics.DisplayMessage("Copying file " + existingFile
468 + " to " + newFileName + "...");
469 FrameIO.copyFile(existingFile, newFileName);
470 FrameGraphics.DisplayMessage("File copied successfully");
471 } catch (FileNotFoundException e) {
472 FrameGraphics.DisplayMessage("Error opening file: " + existingFile);
473 } catch (Exception e) {
474 FrameGraphics.DisplayMessage("File could not be copied");
475 }
476 }
477
478 /**
479 * Runs two methods alternatively a specified number of times and reports on
480 * the time spent running each method.
481 *
482 * @param fullMethodNameA
483 * @param fullMethodNameB
484 * @param repsPerTest
485 * the number of time each method is run per test
486 * @param tests
487 * the number of tests to conduct
488 *
489 */
490 public static void CompareMethods(String fullMethodNameA,
491 String fullMethodNameB, int repsPerTest, int tests) {
492 try {
493 String classNameA = getClassName(fullMethodNameA);
494 String classNameB = getClassName(fullMethodNameB);
495 String methodNameA = getMethodName(fullMethodNameA);
496 String methodNameB = getMethodName(fullMethodNameB);
497
498 Class classA = Class.forName(classNameA);
499 Class classB = Class.forName(classNameB);
500 Method methodA = classA.getDeclaredMethod(methodNameA,
501 new Class[] {});
502 Method methodB = classB.getDeclaredMethod(methodNameB,
503 new Class[] {});
504 TimeKeeper timeKeeper = new TimeKeeper();
505 long timeA = 0;
506 long timeB = 0;
507 // Run the tests
508 for (int i = 0; i < tests; i++) {
509 // Test methodA
510 timeKeeper.restart();
511 for (int j = 0; j < repsPerTest; j++) {
512 methodA.invoke((Object) null, new Object[] {});
513 }
514 timeA += timeKeeper.getElapsedMillis();
515 timeKeeper.restart();
516 // Test methodB
517 for (int j = 0; j < repsPerTest; j++) {
518 methodB.invoke((Object) null, new Object[] {});
519 }
520 timeB += timeKeeper.getElapsedMillis();
521 }
522
523 float aveTimeA = timeA * 1000F / repsPerTest / tests;
524 float aveTimeB = timeB * 1000F / repsPerTest / tests;
525 // Display Results
526 FrameGraphics.DisplayMessage("Average Execution Time");
527 FrameGraphics.DisplayMessage(methodNameA + ": "
528 + TimeKeeper.Formatter.format(aveTimeA) + "us");
529 FrameGraphics.DisplayMessage(methodNameB + ": "
530 + TimeKeeper.Formatter.format(aveTimeB) + "us");
531 } catch (Exception e) {
532 FrameGraphics.ErrorMessage(e.getClass().getSimpleName() + ": "
533 + e.getMessage());
534 }
535 }
536
537 public static String getClassName(String fullMethodName) {
538 assert (fullMethodName != null);
539 assert (fullMethodName.length() > 0);
540 int lastPeriod = fullMethodName.lastIndexOf('.');
541 if (lastPeriod > 0 && lastPeriod < fullMethodName.length() - 1)
542 return fullMethodName.substring(0, lastPeriod);
543 throw new RuntimeException("Invalid method name: " + fullMethodName);
544 }
545
546 public static String getMethodName(String methodName) {
547 assert (methodName != null);
548 assert (methodName.length() > 0);
549 int lastPeriod = methodName.lastIndexOf('.');
550 if (lastPeriod > 0 && lastPeriod < methodName.length() - 1)
551 return methodName.substring(1 + lastPeriod);
552 throw new RuntimeException("Invalid method name: " + methodName);
553 }
554
555 /**
556 * Loads the Frame linked to by the given Item. The first Item on the Frame
557 * that is not the title or name is then placed on the current frame. The
558 * item that was clicked on is placed on the frame it was linked to and the
559 * link is switched to the item from the child frame. If the given Item has
560 * no link, or no item is found then this is a no-op.
561 *
562 * @param current
563 * The Item that links to the Frame that the Item will be loaded
564 * from.
565 */
566 public static void SwapItemWithItemOnChildFrame(Item current) {
567 Item item = getFirstBodyItemOnChildFrame(current, false);
568 // if no item was found
569 if (item == null) {
570 return;
571 }
572
573 // swap the items parents
574 Frame parentFrame = current.getParent();
575 Frame childFrame = item.getParent();
576 current.setParent(childFrame);
577 item.setParent(parentFrame);
578
579 // swap the items on the frames
580 parentFrame.removeItem(current);
581 childFrame.removeItem(item);
582 parentFrame.addItem(item);
583 childFrame.addItem(current);
584
585 // swap the items links
586 item.setActions(current.getAction());
587 item.setLink(childFrame.getName());
588 current.setLink(parentFrame.getName());
589 // current.setLink(null);
590 current.setActions(null);
591
592 FrameGraphics.Repaint();
593 }
594
595 private static Item getFirstBodyItemOnChildFrame(Item current,
596 boolean textOnly) {
597 // the item must link to a frame
598 if (current.getLink() == null) {
599 FrameGraphics
600 .DisplayMessage("Cannot get item from child - this item has no link");
601 return null;
602 }
603
604 Frame child = FrameIO.LoadFrame(current.getAbsoluteLink());
605
606 // if the frame could not be loaded
607 if (child == null) {
608 FrameGraphics.ErrorMessage("Could not load child frame.");
609 return null;
610 }
611
612 // find the first non-title and non-name item
613 List<Item> body = new ArrayList<Item>();
614 if (textOnly)
615 body.addAll(child.getBodyTextItems(false));
616 else
617 body.addAll(child.getItems());
618 Item item = null;
619
620 for (Item i : body)
621 if (i != child.getTitleItem() && !i.isAnnotation()) {
622 item = i;
623 break;
624 }
625
626 // if no item was found
627 if (item == null) {
628 FrameGraphics.DisplayMessage("No item found to copy");
629 return null;
630 }
631
632 return item;
633 }
634}
Note: See TracBrowser for help on using the repository browser.