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

Last change on this file since 518 was 518, checked in by jts21, 11 years ago

Add 'run' command which allows easier creation of widgets and running of actions (just type the short name of the widget or action and drop it onto the run item)

File size: 32.9 KB
Line 
1package org.expeditee.actions;
2
3import java.awt.Color;
4import java.awt.Desktop;
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.LinkedList;
15import java.util.List;
16
17import javax.imageio.ImageIO;
18
19import org.expeditee.gui.AttributeUtils;
20import org.expeditee.gui.Browser;
21import org.expeditee.gui.DisplayIO;
22import org.expeditee.gui.Frame;
23import org.expeditee.gui.FrameGraphics;
24import org.expeditee.gui.FrameIO;
25import org.expeditee.gui.FrameMouseActions;
26import org.expeditee.gui.FrameUtils;
27import org.expeditee.gui.FreeItems;
28import org.expeditee.gui.MessageBay;
29import org.expeditee.gui.Reminders;
30import org.expeditee.gui.TimeKeeper;
31import org.expeditee.importer.FrameDNDTransferHandler;
32import org.expeditee.items.Item;
33import org.expeditee.items.ItemUtils;
34import org.expeditee.items.Line;
35import org.expeditee.items.Text;
36import org.expeditee.items.widgets.InteractiveWidget;
37import org.expeditee.math.ExpediteeJEP;
38import org.expeditee.simple.SString;
39import org.expeditee.stats.CometStats;
40import org.expeditee.stats.DocumentStatsFast;
41import org.expeditee.stats.SessionStats;
42import org.expeditee.stats.StatsLogger;
43import org.expeditee.stats.TreeStats;
44import org.nfunk.jep.Node;
45import org.nfunk.jep.ParseException;
46
47
48
49/**
50 * A list of miscellaneous Actions and Actions specific to Expeditee
51 *
52 */
53public class Misc {
54
55 /**
56 * Causes the system to beep
57 */
58 public static void beep() {
59 java.awt.Toolkit.getDefaultToolkit().beep();
60 }
61
62 /**
63 * Returns an Item located at the specified position.
64 * kgas1 - 23/01/2012
65 * @param x
66 * @param y
67 * @return
68 */
69 public static Item getItemAtPosition(int x, int y, Frame f)
70 {
71 Frame current = f;
72 List<Item> allItems = current.getItems();
73
74 for(Item i : allItems)
75 {
76 if(i.getX() == x && i.getY() == y)
77 return i;
78 }
79
80 return null;
81 }
82
83 /**
84 * Returns an item containing a specified piece of data.
85 * kgas1 - 7/06/2012
86 * @param s
87 * @param f
88 * @return
89 */
90 public static Item getItemContainingData(String s, Frame f){
91
92 Frame current = f;
93
94 List<Item> allItems = current.getItems();
95
96
97 for(Item i : allItems){
98
99
100 if(i.getData() != null && i.getData().size() > 0){
101 if(i.getData().contains(s)){
102 return i;
103 }
104 }
105 }
106
107 return null;
108 }
109
110 /**
111 * Forces a repaint of the current Frame
112 */
113 public static void display() {
114 FrameGraphics.refresh(false);
115 }
116
117 public static String getWindowSize() {
118 return Browser.getWindows()[0].getSize().toString();
119 }
120
121 /**
122 * Restores the current frame to the last saved version currently on the
123 * hard disk
124 */
125 public static void restore() {
126 FrameIO.Reload();
127 // MessageBay.displayMessage("Restoration complete.");
128 }
129
130 /**
131 * Toggles AudienceMode on or off
132 */
133 public static void toggleAudienceMode() {
134 FrameGraphics.ToggleAudienceMode();
135 }
136
137 /**
138 * Toggles TwinFrames mode on or off
139 */
140 public static void toggleTwinFramesMode() {
141 DisplayIO.ToggleTwinFrames();
142 }
143
144 /**
145 * If the given Item is a Text Item, then the text of the Item is
146 * interpreted as actions, if not this method does nothing.
147 *
148 * @param current
149 * The Item to read the Actions from
150 */
151 public static void runItem(Item current) throws Exception {
152 if (current instanceof Text) {
153 List<String> actions = ((Text) current).getTextList();
154 for (String action : actions) {
155 if (!action.equalsIgnoreCase("runitem")) {
156 Actions.PerformAction(DisplayIO.getCurrentFrame(), current,
157 action);
158 }
159 }
160 } else {
161 MessageBay.errorMessage("Item must be a text item.");
162 }
163 }
164
165 /**
166 * Prompts the user to confirm deletion of the current Frame, and deletes if
167 * the user chooses. After deletion this action calls back(), to ensure the
168 * deleted frame is not still being shown
169 *
170 */
171 public static void DeleteFrame(Frame toDelete) {
172 String deletedFrame = toDelete.getName();
173 String deletedFrameNameLowercase = deletedFrame.toLowerCase();
174 String errorMessage = "Error deleting " + deletedFrame;
175 try {
176 String deletedFrameName = FrameIO.DeleteFrame(toDelete);
177 if (deletedFrameName != null) {
178 DisplayIO.Back();
179 // Remove any links on the previous frame to the one being
180 // deleted
181 Frame current = DisplayIO.getCurrentFrame();
182 for (Item i : current.getItems())
183 if (i.getLink() != null
184 && i.getAbsoluteLink().toLowerCase().equals(
185 deletedFrameNameLowercase)) {
186 i.setLink(null);
187 }
188 MessageBay.displayMessage(deletedFrame + " renamed "
189 + deletedFrameName);
190 // FrameGraphics.Repaint();
191 return;
192 }
193 } catch (IOException ioe) {
194 if (ioe.getMessage() != null)
195 errorMessage += ". " + ioe.getMessage();
196 } catch (SecurityException se) {
197 if (se.getMessage() != null)
198 errorMessage += ". " + se.getMessage();
199 } catch (Exception e) {
200 e.printStackTrace();
201 }
202 MessageBay.errorMessage(errorMessage);
203 }
204
205 /**
206 * Loads the Frame linked to by the given Item. The first Item on the Frame
207 * that is not the title or name is then placed on the cursor. If the given
208 * Item has no link, or no item is found then this is a no-op.
209 *
210 * @param current
211 * The Item that links to the Frame that the Item will be loaded
212 * from.
213 */
214 public static Item GetItemFromChildFrame(Item current) {
215 return getFromChildFrame(current, false);
216 }
217
218 public static void GetItemsFromChildFrame(Item current) {
219 getItemsFromChildFrame(current, false);
220 }
221
222 /**
223 * Loads the Frame linked to by the given Item. The first Text Item on the
224 * Frame that is not the title or name is then placed on the cursor. If the
225 * given Item has no link, or no item is found then this is a no-op.
226 *
227 * @param current
228 * The Item that links to the Frame that the Item will be loaded
229 * from.
230 */
231 public static Item GetTextFromChildFrame(Item current) {
232 return getFromChildFrame(current, true);
233 }
234
235 private static Item getFromChildFrame(Item current, boolean textOnly) {
236 Item item = getFirstBodyItemOnChildFrame(current, textOnly);
237 // if no item was found
238 if (item != null) {
239 // copy the item and switch
240 item = item.copy();
241 item.setPosition(DisplayIO.getMouseX(), FrameMouseActions.getY());
242 }
243 return item;
244 }
245
246 private static void getItemsFromChildFrame(Item current, boolean textOnly) {
247 Collection<Item> items = getItemsOnChildFrame(current, textOnly);
248 // if no item was found
249 if (items == null || items.size() == 0) {
250 return;
251 }
252
253 // copy the item and switch
254 Collection<Item> copies = ItemUtils.CopyItems(items);
255 Item first = items.iterator().next();
256 float deltaX = DisplayIO.getMouseX() - first.getX();
257 float deltaY = FrameMouseActions.getY() - first.getY();
258 for (Item i : copies) {
259 if (i.isVisible())
260 i.setXY(i.getX() + deltaX, i.getY() + deltaY);
261 i.setParent(null);
262 }
263 FrameMouseActions.pickup(copies);
264 FrameGraphics.Repaint();
265 }
266
267 /**
268 * Sets the given Item to have the Given Color. Color can be null (for
269 * default)
270 *
271 * @param toChange
272 * The Item to set the Color.
273 * @param toUse
274 * The Color to give the Item.
275 */
276 public static void SetItemBackgroundColor(Item toChange, Color toUse) {
277 if (toChange == null)
278 return;
279
280 toChange.setBackgroundColor(toUse);
281 FrameGraphics.Repaint();
282 }
283
284 /**
285 * Sets the given Item to have the Given Color. Color can be null (for
286 * default)
287 *
288 * @param toChange
289 * The Item to set the Color.
290 * @param toUse
291 * The Color to give the Item.
292 */
293 public static void SetItemColor(Item toChange, Color toUse) {
294 if (toChange == null)
295 return;
296
297 toChange.setColor(toUse);
298 FrameGraphics.Repaint();
299 }
300
301 /**
302 * Creates a new Text Object containing general statistics for the current
303 * session. The newly created Text Object is then attached to the cursor via
304 * FrameMouseActions.pickup(Item)
305 */
306 public static void GetSessionStats() {
307 attachStatsToCursor(SessionStats.getCurrentStats());
308 }
309
310 /**
311 * Creates a new Text Object containing statistics for the current tree.
312 */
313 public static String GetCometStats(Frame frame) {
314 TimeKeeper timer = new TimeKeeper();
315 MessageBay.displayMessage("Computing comet stats...");
316 CometStats cometStats = new CometStats(frame);
317 String result = cometStats.toString();
318 MessageBay.overwriteMessage("Comet stats time: "
319 + timer.getElapsedStringSeconds());
320 return result;
321 }
322
323 public static String GetTreeStats(Frame frame) {
324 TimeKeeper timer = new TimeKeeper();
325 MessageBay.displayMessage("Computing tree stats...");
326
327 TreeStats treeStats = new TreeStats(frame);
328 String result = treeStats.toString();
329 MessageBay.overwriteMessage("Tree stats time: "
330 + timer.getElapsedStringSeconds());
331 return result;
332
333 }
334
335 public static String GetDocumentStats(Frame frame) {
336 TimeKeeper timer = new TimeKeeper();
337 MessageBay.displayMessage("Computing document stats...");
338 FrameIO.ForceSaveFrame(frame);
339 DocumentStatsFast docStats = new DocumentStatsFast(frame.getName(),
340 frame.getTitle());
341 String result = docStats.toString();
342
343 MessageBay.overwriteMessage("Document stats time: "
344 + timer.getElapsedStringSeconds());
345 return result;
346
347 }
348
349 /**
350 * Creates a text item and attaches it to the cursor.
351 *
352 * @param itemText
353 * the text to attach to the cursor
354 */
355 public static void attachStatsToCursor(String itemText) {
356 SessionStats.CreatedText();
357 Frame current = DisplayIO.getCurrentFrame();
358 Item text = current.getStatsTextItem(itemText);
359 FrameMouseActions.pickup(text);
360 FrameGraphics.Repaint();
361 }
362
363 public static void attachTextToCursor(String itemText) {
364 SessionStats.CreatedText();
365 Frame current = DisplayIO.getCurrentFrame();
366 Item text = current.getTextItem(itemText);
367 FrameMouseActions.pickup(text);
368 FrameGraphics.Repaint();
369 }
370
371 /**
372 * Creates a new Text Object containing statistics for moving, deleting and
373 * creating items in the current session. The newly created Text Object is
374 * then attached to the cursor via FrameMouseActions.pickup(Item)
375 */
376 public static String getItemStats() {
377 return SessionStats.getItemStats();
378 }
379
380 /**
381 * Creates a new Text Object containing statistics for the time between
382 * events triggered by the user through mouse clicks and key presses. The
383 * newly created Text Object is then attached to the cursor via
384 * FrameMouseActions.pickup(Item)
385 */
386 public static String getEventStats() {
387 return SessionStats.getEventStats();
388 }
389
390 /**
391 * Creates a new Text Object containing the contents of the current frames
392 * file.
393 */
394 public static String getFrameFile(Frame frame) {
395 return FrameIO.ForceSaveFrame(frame);
396 }
397
398 /**
399 * Creates a new Text Object containing the available fonts.
400 */
401 public static String getFontNames() {
402 Collection<String> availableFonts = Actions.getFonts().values();
403 StringBuilder fontsList = new StringBuilder();
404 for (String s : availableFonts) {
405 fontsList.append(s).append(Text.LINE_SEPARATOR);
406 }
407 fontsList.deleteCharAt(fontsList.length() - 1);
408
409 return fontsList.toString();
410 }
411
412 public static String getUnicodeCharacters(int start, int finish) {
413 if (start < 0 && finish < 0) {
414 throw new RuntimeException("Parameters must be non negative");
415 }
416 // Swap the start and finish if they are inthe wrong order
417 if (start > finish) {
418 start += finish;
419 finish = start - finish;
420 start = start - finish;
421 }
422 StringBuilder charList = new StringBuilder();
423 int count = 0;
424 charList.append(String.format("Unicode block 0x%x - 0x%x", start,
425 finish));
426 System.out.println();
427 // charList.append("Unicode block: ").append(String.format(format,
428 // args))
429 for (char i = (char) start; i < (char) finish; i++) {
430 if (Character.isDefined(i)) {
431 if (count++ % 64 == 0)
432 charList.append(Text.LINE_SEPARATOR);
433 charList.append(Character.valueOf(i));
434 }
435 }
436 return charList.toString();
437 }
438
439 /**
440 * Gets a single block of Unicode characters.
441 *
442 * @param start
443 * the start of the block
444 */
445 public static String getUnicodeCharacters(int start) {
446 return getUnicodeCharacters(start, start + 256);
447 }
448
449 public static String getMathSymbols() {
450 return getUnicodeCharacters('\u2200', '\u2300');
451 }
452
453 /**
454 * Resets the statistics back to zero.
455 */
456 public static void repaint() {
457 StatsLogger.WriteStatsFile();
458 SessionStats.resetStats();
459 }
460
461 /**
462 * Loads a frame with the given name and saves it as a JPEG image.
463 *
464 * @param framename
465 * The name of the Frame to save
466 */
467 public static void jpegFrame(String framename) {
468 ImageFrame(framename, "JPEG");
469 }
470
471 /**
472 * Saves the current frame as a JPEG image. This is the same as calling
473 * JpegFrame(currentFrame.getName())
474 */
475 public static void jpegFrame() {
476 ImageFrame(DisplayIO.getCurrentFrame().getName(), "JPEG");
477 }
478
479 public static void jpgFrame() {
480 jpegFrame();
481 }
482
483 /**
484 * Loads a frame with the given name and saves it as a PNG image.
485 *
486 * @param framename
487 * The name of the Frame to save
488 */
489 public static void PNGFrame(String framename) {
490 ImageFrame(framename, "PNG");
491 }
492
493 /**
494 * Saves the current frame as a PNG image. This is the same as calling
495 * PNGFrame(currentFrame.getName())
496 */
497 public static void PNGFrame(Frame frame) {
498 ImageFrame(frame.getName(), "PNG");
499 }
500
501 public static String SaveImage(BufferedImage screen, String format,
502 String directory, String fileName) {
503 String suffix = "." + format.toLowerCase();
504 String shortFileName = fileName;
505 // Check if we need to append the suffix
506 if (fileName.indexOf('.') < 0)
507 fileName += suffix;
508 else
509 shortFileName = fileName.substring(0, fileName.length() - suffix.length());
510
511 try {
512 int count = 2;
513 // set up the file for output
514 File out = new File(directory + fileName);
515 while (out.exists()) {
516 fileName = shortFileName + "_" + count++ + suffix;
517 out = new File(directory + fileName);
518 }
519
520 if (!out.getParentFile().exists())
521 out.mkdirs();
522
523 // If the image is successfully written out return the fileName
524 if (ImageIO.write(screen, format, out))
525 return fileName;
526
527 } catch (Exception e) {
528 e.printStackTrace();
529 }
530 return null;
531 }
532
533 public static String ImageFrame(Frame frame, String format, String directory) {
534 assert (frame != null);
535
536 Image oldBuffer = frame.getBuffer();
537 frame.setBuffer(null);
538 // Jpeg only works properly with volitile frames
539 // Png transparency only works with bufferedImage form
540 Image frameBuffer = FrameGraphics.getBuffer(frame, false, format
541 .equalsIgnoreCase("jpeg"));
542 // Make sure overlay stuff doesnt disapear on the frame visible on the
543 // screen
544 frame.setBuffer(oldBuffer);
545 BufferedImage screen = null;
546
547 if (frameBuffer instanceof VolatileImage) {
548 // If its the current frame it will be a volitive image
549 screen = ((VolatileImage) frameBuffer).getSnapshot();
550 } else {
551 assert (frameBuffer instanceof BufferedImage);
552 screen = (BufferedImage) frameBuffer;
553 }
554 return SaveImage(screen, format, directory, frame.getExportFileName());
555 }
556
557 /**
558 * Saves the Frame with the given Framename as an image of the given format.
559 *
560 * @param framename
561 * The name of the Frame to save as an image
562 * @param format
563 * The Image format to use (i.e. "PNG", "BMP", etc)
564 */
565 public static void ImageFrame(String framename, String format) {
566 Frame loaded = FrameIO.LoadFrame(framename);
567
568 // if the frame was loaded successfully
569 if (loaded != null) {
570 String path = FrameIO.EXPORTS_DIR;
571 String frameName = ImageFrame(loaded, format, path);
572 if (frameName != null)
573 MessageBay.displayMessage("Frame successfully saved to " + path
574 + frameName);
575 else
576 MessageBay.errorMessage("Could not find image writer for "
577 + format + " format");
578 // if the frame was not loaded successfully, alert the user
579 } else {
580 MessageBay.displayMessage("Frame '" + framename
581 + "' could not be found.");
582 }
583 }
584
585 public static void MessageLn(Item message) {
586 if (message instanceof Text)
587 MessageBay.displayMessage((Text) message);
588 }
589
590 /**
591 * Displays a message in the message box area.
592 *
593 * @param message
594 * the message to display
595 */
596 public static void MessageLn(String message) {
597 MessageBay.displayMessage(message);
598 }
599
600 public static void MessageLn2(String message, String message2) {
601 MessageBay.displayMessage(message + " " + message2);
602 }
603
604 public static void CopyFile(String existingFile, String newFileName) {
605 try {
606 // TODO is there a built in method which will do this faster?
607
608 MessageBay.displayMessage("Copying file " + existingFile + " to "
609 + newFileName + "...");
610 FrameIO.copyFile(existingFile, newFileName);
611 MessageBay.displayMessage("File copied successfully");
612 } catch (FileNotFoundException e) {
613 MessageBay.displayMessage("Error opening file: " + existingFile);
614 } catch (Exception e) {
615 MessageBay.displayMessage("File could not be copied");
616 }
617 }
618
619 /**
620 * Runs two methods alternatively a specified number of times and reports on
621 * the time spent running each method.
622 *
623 * @param fullMethodNameA
624 * @param fullMethodNameB
625 * @param repsPerTest
626 * the number of time each method is run per test
627 * @param tests
628 * the number of tests to conduct
629 *
630 */
631 public static void CompareMethods(String fullMethodNameA,
632 String fullMethodNameB, int repsPerTest, int tests) {
633 try {
634 String classNameA = getClassName(fullMethodNameA);
635 String classNameB = getClassName(fullMethodNameB);
636 String methodNameA = getMethodName(fullMethodNameA);
637 String methodNameB = getMethodName(fullMethodNameB);
638
639 Class<?> classA = Class.forName(classNameA);
640 Class<?> classB = Class.forName(classNameB);
641 Method methodA = classA.getDeclaredMethod(methodNameA,
642 new Class[] {});
643 Method methodB = classB.getDeclaredMethod(methodNameB,
644 new Class[] {});
645 TimeKeeper timeKeeper = new TimeKeeper();
646 long timeA = 0;
647 long timeB = 0;
648 // Run the tests
649 for (int i = 0; i < tests; i++) {
650 // Test methodA
651 timeKeeper.restart();
652 for (int j = 0; j < repsPerTest; j++) {
653 methodA.invoke((Object) null, new Object[] {});
654 }
655 timeA += timeKeeper.getElapsedMillis();
656 timeKeeper.restart();
657 // Test methodB
658 for (int j = 0; j < repsPerTest; j++) {
659 methodB.invoke((Object) null, new Object[] {});
660 }
661 timeB += timeKeeper.getElapsedMillis();
662 }
663
664 float aveTimeA = timeA * 1000F / repsPerTest / tests;
665 float aveTimeB = timeB * 1000F / repsPerTest / tests;
666 // Display Results
667 MessageBay.displayMessage("Average Execution Time");
668 MessageBay.displayMessage(methodNameA + ": "
669 + TimeKeeper.Formatter.format(aveTimeA) + "us");
670 MessageBay.displayMessage(methodNameB + ": "
671 + TimeKeeper.Formatter.format(aveTimeB) + "us");
672 } catch (Exception e) {
673 MessageBay.errorMessage(e.getClass().getSimpleName() + ": "
674 + e.getMessage());
675 }
676 }
677
678 public static String getClassName(String fullMethodName) {
679 assert (fullMethodName != null);
680 assert (fullMethodName.length() > 0);
681 int lastPeriod = fullMethodName.lastIndexOf('.');
682 if (lastPeriod > 0 && lastPeriod < fullMethodName.length() - 1)
683 return fullMethodName.substring(0, lastPeriod);
684 throw new RuntimeException("Invalid method name: " + fullMethodName);
685 }
686
687 public static String getMethodName(String methodName) {
688 assert (methodName != null);
689 assert (methodName.length() > 0);
690 int lastPeriod = methodName.lastIndexOf('.');
691 if (lastPeriod > 0 && lastPeriod < methodName.length() - 1)
692 return methodName.substring(1 + lastPeriod);
693 throw new RuntimeException("Invalid method name: " + methodName);
694 }
695
696 /**
697 * Loads the Frame linked to by the given Item. The first Item on the Frame
698 * that is not the title or name is then placed on the current frame. The
699 * item that was clicked on is placed on the frame it was linked to and the
700 * link is switched to the item from the child frame. If the given Item has
701 * no link, or no item is found then this is a no-op.
702 *
703 * @param current
704 * The Item that links to the Frame that the Item will be loaded
705 * from.
706 */
707 public static void SwapItemWithItemOnChildFrame(Item current) {
708 Item item = getFirstBodyItemOnChildFrame(current, false);
709 // if no item was found
710 if (item == null) {
711 return;
712 }
713
714 // swap the items parents
715 Frame parentFrame = current.getParent();
716 Frame childFrame = item.getParent();
717 current.setParent(childFrame);
718 item.setParent(parentFrame);
719
720 // swap the items on the frames
721 parentFrame.removeItem(current);
722 childFrame.removeItem(item);
723 parentFrame.addItem(item);
724 childFrame.addItem(current);
725
726 // swap the items links
727 item.setActions(current.getAction());
728 item.setLink(childFrame.getName());
729 current.setLink(parentFrame.getName());
730 // current.setLink(null);
731 current.setActions(null);
732
733 FrameGraphics.Repaint();
734 }
735
736 private static Item getFirstBodyItemOnChildFrame(Item current,
737 boolean textOnly) {
738 // the item must link to a frame
739 if (current.getLink() == null) {
740 MessageBay
741 .displayMessage("Cannot get item from child - this item has no link");
742 return null;
743 }
744
745 Frame child = FrameIO.LoadFrame(current.getAbsoluteLink());
746
747 // if the frame could not be loaded
748 if (child == null) {
749 MessageBay.errorMessage("Could not load child frame.");
750 return null;
751 }
752
753 // find the first non-title and non-name item
754 List<Item> body = new ArrayList<Item>();
755 if (textOnly)
756 body.addAll(child.getBodyTextItems(false));
757 else
758 body.addAll(child.getItems());
759 Item item = null;
760
761 for (Item i : body)
762 if (i != child.getTitleItem() && !i.isAnnotation()) {
763 item = i;
764 break;
765 }
766
767 // if no item was found
768 if (item == null) {
769 MessageBay.displayMessage("No item found to copy");
770 return null;
771 }
772
773 return item;
774 }
775
776 private static Collection<Item> getItemsOnChildFrame(Item current,
777 boolean textOnly) {
778 // the item must link to a frame
779 if (current.getLink() == null) {
780 MessageBay
781 .displayMessage("Cannot get item from child - this item has no link");
782 return null;
783 }
784 Frame child = FrameIO.LoadFrame(current.getAbsoluteLink());
785
786 // if the frame could not be loaded
787 if (child == null) {
788 MessageBay.errorMessage("Could not load child frame.");
789 return null;
790 }
791
792 // find the first non-title and non-name item
793 Collection<Item> body = new ArrayList<Item>();
794 if (textOnly)
795 body.addAll(child.getBodyTextItems(false));
796 else
797 body.addAll(child.getItems());
798
799 return body;
800 }
801
802 public static void calculate(Frame frame, Item toCalculate) {
803 if (toCalculate instanceof Text) {
804 Text text = (Text) toCalculate;
805 ExpediteeJEP myParser = new ExpediteeJEP();
806 myParser.addVariables(frame);
807 String linkedFrame = toCalculate.getAbsoluteLink();
808 if (linkedFrame != null) {
809 myParser.addVariables(FrameIO.LoadFrame(linkedFrame));
810 }
811 myParser.resetObserver();
812
813 // Do the calculation
814 String formulaFullCase = text.getText().replace('\n', ' ');
815 String formula = formulaFullCase.toLowerCase();
816
817 try {
818 Node node = myParser.parse(formula);
819 Object result = myParser.evaluate(node);
820 text.setText(result.toString(), true);
821 text.setFormula(formulaFullCase);
822 if (text.isFloating()) {
823 text.setPosition(FrameMouseActions.MouseX,
824 FrameMouseActions.MouseY);
825 FrameMouseActions.resetOffset();
826 } else {
827 text.getParentOrCurrentFrame().change();
828 }
829 } catch (ParseException e) {
830 MessageBay.errorMessage("Parse error "
831 + e.getMessage().replace("\n", ""));
832 } catch (Exception e) {
833 MessageBay.errorMessage("evaluation error "
834 + e.getMessage().replace("\n", ""));
835 e.printStackTrace();
836 }
837 }
838 }
839
840 /**
841 * Attach an item to the cursor.
842 *
843 * @param item
844 */
845 public static void attachToCursor(Item item) {
846 item.setParent(null);
847 FrameMouseActions.pickup(item);
848 FrameGraphics.Repaint();
849 }
850
851 public static void attachToCursor(Collection<Item> items) {
852 for (Item i : items) {
853 i.setParent(null);
854 i.invalidateAll();
855 }
856 FrameMouseActions.pickup(items);
857 // TODO figure out why this isnt repainting stuff immediately
858 // All of text item doesnt repaint until the cursor is moved
859 FrameGraphics.requestRefresh(true);
860 }
861
862 public static void importFiles(Item item) {
863 List<File> files = new LinkedList<File>();
864 for (String s : item.getText().split("\\s+")) {
865 File file = new File(s.trim());
866 if (file.exists()) {
867 files.add(file);
868 }
869 }
870 try {
871 FrameDNDTransferHandler.getInstance().importFileList(files,
872 FrameMouseActions.getPosition());
873 } catch (Exception e) {
874 }
875 }
876
877 public static void importFile(Item item) {
878 File file = new File(item.getText().trim());
879 if (file.exists()) {
880 try {
881 FrameDNDTransferHandler.getInstance().importFile(file,
882 FrameMouseActions.getPosition());
883 } catch (Exception e) {
884 e.printStackTrace();
885 }
886 }
887 }
888
889 public static Item createPolygon(Item item, int sides) {
890 if (item instanceof Text) {
891 try {
892 SString s = new SString(item.getText());
893 sides = s.integerValue().intValue();
894 } catch (NumberFormatException e) {
895 }
896 }
897
898 if (sides < 3) {
899 MessageBay.errorMessage("Shapes must have at least 3 sides");
900 }
901 double angle = -(180 - ((sides - 2) * 180.0F) / sides);
902 double curAngle = 0;
903 double size = 50F;
904 if (item.isLineEnd() && item.getLines().size() > 0) {
905 item = item.getLines().get(0);
906 }
907 // Use line length to determine the size of the shape
908 if (item instanceof Line) {
909 size = ((Line) item).getLength();
910 }
911
912 float curX = FrameMouseActions.MouseX;
913 float curY = FrameMouseActions.MouseY;
914
915 Collection<Item> newItems = new LinkedList<Item>();
916 Item[] d = new Item[sides];
917 // create dots
918 Frame current = DisplayIO.getCurrentFrame();
919 for (int i = 0; i < d.length; i++) {
920 d[i] = current.createDot();
921 newItems.add(d[i]);
922 d[i].setPosition(curX, curY);
923 curX += (float) (Math.cos((curAngle) * Math.PI / 180.0) * size);
924 curY += (float) (Math.sin((curAngle) * Math.PI / 180.0) * size);
925
926 curAngle += angle;
927 }
928 // create lines
929 for (int i = 1; i < d.length; i++) {
930 newItems.add(new Line(d[i - 1], d[i], current.getNextItemID()));
931 }
932 newItems.add(new Line(d[d.length - 1], d[0], current.getNextItemID()));
933
934 current.addAllItems(newItems);
935 if (item instanceof Text) {
936 for (Item i : item.getAllConnected()) {
937 if (i instanceof Line) {
938 item = i;
939 break;
940 }
941 }
942 }
943
944 Color newColor = item.getColor();
945 if (newColor != null) {
946 d[0].setColor(item.getColor());
947 if (item instanceof Text && item.getBackgroundColor() != null) {
948 d[0].setFillColor(item.getBackgroundColor());
949 } else {
950 d[0].setFillColor(item.getFillColor());
951 }
952 }
953 float newThickness = item.getThickness();
954 if (newThickness > 0) {
955 d[0].setThickness(newThickness);
956 }
957
958 ItemUtils.EnclosedCheck(newItems);
959 FrameGraphics.refresh(false);
960
961 return d[0];
962 }
963
964 public static void StopReminder() {
965 Reminders.stop();
966 }
967
968 public static void print(String file) {
969 try {
970 if (Browser._theBrowser.isMinimumVersion6()) {
971 if (Desktop.isDesktopSupported()) {
972 Desktop.getDesktop().print(new File(file));
973 }
974 }
975 } catch (Exception e) {
976 MessageBay.errorMessage("Printing error: " + e.getMessage());
977 }
978 }
979
980 public static int wordCount(String paragraph) {
981 return paragraph.trim().split("\\s+").length + 1;
982 }
983
984 public static int wordCount(Frame frame) {
985 int count = 0;
986
987 for (Text t : frame.getBodyTextItems(false)) {
988 count += wordCount(t.getText());
989 }
990
991 return count;
992 }
993
994 public static void moveToPublic(Frame frame) {
995 FrameIO.moveFrameset(frame.getFramesetName(), FrameIO.PUBLIC_PATH);
996 }
997
998 public static void moveToPrivate(Frame frame) {
999 FrameIO.moveFrameset(frame.getFramesetName(), FrameIO.FRAME_PATH);
1000 }
1001
1002 /**
1003 * Returns the value of a specified item attribute.
1004 *
1005 * @param item
1006 * from which to extract the value
1007 * @param attribute
1008 * name of an items attribute
1009 * @return the value of the attribute
1010 */
1011 public static String extract(Item item, String attribute) {
1012 return AttributeUtils.getAttribute(item, attribute);
1013 }
1014
1015 /**
1016 * Launches items.widgets.Browser and uses Text item as URL.
1017 * @param text Text item which passes contents as URL for browser.
1018 * @throws Exception
1019 */
1020 public static void startBrowser(Item text) throws Exception {
1021 if (text instanceof Text) {
1022 FreeItems.getInstance().clear(); // remove url text from cursor
1023
1024 Text wt = new Text("@iw:org.expeditee.items.widgets.Browser"); // create new text item for browser widget
1025 wt.setParent(DisplayIO.getCurrentFrame()); // set parent of text source for InteractiveWidget.createWidget()
1026 wt.setXY(FrameMouseActions.getX(), FrameMouseActions.getY());
1027 // create widget from text item
1028 org.expeditee.items.widgets.Browser browser = (org.expeditee.items.widgets.Browser) InteractiveWidget.createWidget(wt);
1029
1030 if(FreeItems.textOnlyAttachedToCursor()) { // navigates to url specified by the text item
1031 browser.navigate(text.getText());
1032 } else {
1033 browser.navigate("http://www.waikato.ac.nz");
1034 }
1035
1036 FrameMouseActions.pickup(browser.getItems()); // attach browser widget to mouse
1037 } else {
1038 MessageBay.errorMessage("Must be a text item.");
1039 }
1040 }
1041
1042 /**
1043 * Text item becomes link to new frame containing items.widgets.Browser and uses Text item as URL for browser.
1044 * @param text Text item which passes contents as URL for browser and becomes link to the browser's new frame.
1045 * @throws Exception
1046 */
1047 public static void startBrowserNewFrame(Item text) throws Exception {
1048 System.out.println("test");
1049 if (!(text instanceof Text)) {
1050 MessageBay.errorMessage("Must be a text item.");
1051 return;
1052 }
1053 if(text.getLink() != null) { // text item can't already have a link
1054 MessageBay.errorMessage("Text item already has link.");
1055 return;
1056 }
1057
1058 Frame frame = FrameIO.CreateNewFrame(text); // create new frame for browser
1059 frame.addText(0, 50, "@iw:org.expeditee.items.widgets.Browser", null); // create new text item for browser widget
1060 FrameUtils.Parse(frame); // parse created frame; loads browser widget
1061
1062 for(InteractiveWidget iw : frame.getInteractiveWidgets()) { // may be other widgets on frame
1063 if(iw instanceof org.expeditee.items.widgets.Browser) {
1064 // Set browser to 'full screen'
1065 iw.setSize(-1, -1, -1, -1, Browser._theBrowser.getWidth(), Browser._theBrowser.getHeight() - MessageBay.MESSAGE_BUFFER_HEIGHT - 80);
1066
1067 // If there is a text item attached to cursor use it as url for browser
1068 if(FreeItems.textOnlyAttachedToCursor()) {
1069 text.setLink("" + frame.getNumber());
1070 ((org.expeditee.items.widgets.Browser)iw).navigate(text.getText());
1071 } else {
1072 // Navigate to www.waikato.ac.nz by default if no url supplied and create new text item to be the link
1073 ((org.expeditee.items.widgets.Browser)iw).navigate("http://www.waikato.ac.nz");
1074 Text t = new Text("http://www.waikato.ac.nz");
1075 t.setParent(DisplayIO.getCurrentFrame()); // set parent of text source for InteractiveWidget.createWidget()
1076 t.setXY(FrameMouseActions.getX(), FrameMouseActions.getY());
1077 t.setLink("" + frame.getNumber()); // link url text to new browser frame
1078 FrameMouseActions.pickup(t); // Attach new text link to cursor
1079 }
1080 }
1081 }
1082
1083 FrameIO.SaveFrame(frame); // save frame to disk
1084 }
1085
1086 private static boolean startWidget(String name) throws Exception {
1087 String fullName = Actions.getClassName(name);
1088 if(fullName == null) {
1089 return false;
1090 }
1091 MessageBay.displayMessage("Creating new \"" + fullName + "\"");
1092
1093 FreeItems.getInstance().clear();
1094 Text wt = new Text("@iw:" + fullName); // create new text item for browser widget
1095 wt.setParent(DisplayIO.getCurrentFrame()); // set parent of text source for InteractiveWidget.createWidget()
1096 wt.setXY(FrameMouseActions.getX(), FrameMouseActions.getY()); // move to the mouse cursor
1097 InteractiveWidget widget = InteractiveWidget.createWidget(wt);
1098 FrameMouseActions.pickup(widget.getItems());
1099
1100 return true;
1101 }
1102
1103 private static void runUnknown(String command) throws Exception {
1104 if(startWidget(command)) {
1105 return;
1106 }
1107
1108 Actions.PerformAction(DisplayIO.getCurrentFrame(), null, command);
1109 }
1110
1111 public static void run(String command) throws Exception {
1112 int firstSpace = command.indexOf(" ");
1113 if(firstSpace == -1) {
1114 runUnknown(command);
1115 return;
1116 }
1117 String argLower = command.toLowerCase();
1118 String name = argLower.substring(0, firstSpace).trim(); // first word
1119 String args = argLower.substring(firstSpace).trim(); // remainder after first word
1120 if(name == "action" || name == "agent") {
1121 if(args.length() > 0) {
1122 Actions.PerformAction(DisplayIO.getCurrentFrame(), null, args);
1123 } else {
1124 MessageBay.displayMessage("Please specify an action/agent name");
1125 }
1126 } else if(name == "widget") {
1127 if(args.length() > 0) {
1128 if(!startWidget(args)) {
1129 MessageBay.displayMessage("Widget \"" + name + "\" does not exist");
1130 }
1131 } else {
1132 MessageBay.displayMessage("Please specify a widget name");
1133 }
1134 } else {
1135 runUnknown(command);
1136 }
1137 }
1138
1139 public static void run(Item item) throws Exception {
1140 run(((Text)item).getText());
1141 }
1142}
Note: See TracBrowser for help on using the repository browser.