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

Last change on this file since 464 was 464, checked in by davidb, 11 years ago

Refactoring

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