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

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

added functionality for dockable @v's

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