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

Last change on this file since 1079 was 1079, checked in by davidb, 8 years ago

Comments added to track some useful StackOverflow articles on custom git-merging

File size: 44.1 KB
RevLine 
[919]1/**
2 * Misc.java
3 * Copyright (C) 2010 New Zealand Digital Library, http://expeditee.org
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
[4]19package org.expeditee.actions;
20
21import java.awt.Color;
[309]22import java.awt.Desktop;
[78]23import java.awt.Image;
[4]24import java.awt.image.BufferedImage;
[78]25import java.awt.image.VolatileImage;
[660]26import java.io.BufferedReader;
[4]27import java.io.File;
28import java.io.FileNotFoundException;
29import java.io.IOException;
[1076]30import java.io.InputStream;
[660]31import java.io.InputStreamReader;
[72]32import java.lang.reflect.Method;
[996]33import java.net.URI;
34import java.net.URISyntaxException;
[624]35import java.net.URL;
36import java.net.URLClassLoader;
[70]37import java.util.ArrayList;
[108]38import java.util.Collection;
[242]39import java.util.LinkedList;
[4]40import java.util.List;
[996]41import java.util.Map;
42import java.util.Map.Entry;
43import java.util.Set;
[624]44import java.util.jar.Attributes;
45import java.util.jar.JarFile;
[4]46
47import javax.imageio.ImageIO;
48
[376]49import org.expeditee.gui.AttributeUtils;
[309]50import org.expeditee.gui.Browser;
[1076]51import org.expeditee.io.Conversion;
[4]52import org.expeditee.gui.DisplayIO;
[1076]53import org.expeditee.io.ExpReader;
[4]54import org.expeditee.gui.Frame;
55import org.expeditee.gui.FrameGraphics;
56import org.expeditee.gui.FrameIO;
[632]57import org.expeditee.gui.FrameKeyboardActions;
[4]58import org.expeditee.gui.FrameMouseActions;
[514]59import org.expeditee.gui.FrameUtils;
60import org.expeditee.gui.FreeItems;
[121]61import org.expeditee.gui.MessageBay;
[689]62import org.expeditee.gui.MessageBay.Progress;
[284]63import org.expeditee.gui.Reminders;
[72]64import org.expeditee.gui.TimeKeeper;
[278]65import org.expeditee.importer.FrameDNDTransferHandler;
[4]66import org.expeditee.items.Item;
[162]67import org.expeditee.items.ItemUtils;
[247]68import org.expeditee.items.Line;
[4]69import org.expeditee.items.Text;
[634]70import org.expeditee.items.XRayable;
[514]71import org.expeditee.items.widgets.InteractiveWidget;
[634]72import org.expeditee.items.widgets.WidgetCorner;
73import org.expeditee.items.widgets.WidgetEdge;
[190]74import org.expeditee.math.ExpediteeJEP;
[614]75import org.expeditee.settings.UserSettings;
[278]76import org.expeditee.simple.SString;
[90]77import org.expeditee.stats.CometStats;
[376]78import org.expeditee.stats.DocumentStatsFast;
[4]79import org.expeditee.stats.SessionStats;
80import org.expeditee.stats.StatsLogger;
[90]81import org.expeditee.stats.TreeStats;
[156]82import org.nfunk.jep.Node;
[190]83import org.nfunk.jep.ParseException;
[4]84
[996]85import com.lowagie.text.Font;
[438]86
87
[996]88
[4]89/**
[105]90 * A list of miscellaneous Actions and Actions specific to Expeditee
[4]91 *
92 */
93public class Misc {
[438]94
[4]95 /**
96 * Causes the system to beep
97 */
[181]98 public static void beep() {
[4]99 java.awt.Toolkit.getDefaultToolkit().beep();
100 }
[438]101
[4]102 /**
[438]103 * Returns an Item located at the specified position.
104 * kgas1 - 23/01/2012
105 * @param x
106 * @param y
107 * @return
108 */
109 public static Item getItemAtPosition(int x, int y, Frame f)
110 {
111 Frame current = f;
112 List<Item> allItems = current.getItems();
113
[441]114 for(Item i : allItems)
115 {
[438]116 if(i.getX() == x && i.getY() == y)
117 return i;
118 }
119
120 return null;
121 }
122
[441]123 /**
124 * Returns an item containing a specified piece of data.
125 * kgas1 - 7/06/2012
126 * @param s
127 * @param f
128 * @return
129 */
[438]130 public static Item getItemContainingData(String s, Frame f){
[441]131
132 Frame current = f;
133
134 List<Item> allItems = current.getItems();
135
136
137 for(Item i : allItems){
138
139
140 if(i.getData() != null && i.getData().size() > 0){
141 if(i.getData().contains(s)){
142 return i;
143 }
144 }
145 }
146
147 return null;
148 }
[438]149
[996]150 public static void openURL(Item item){
151
152 if(item.getData() != null && item.getData().size() > 0){
153
154 String url = item.getData().get(0);
155 openURL(url);
156 }
157
158 //openURL("http://www.google.com");
159 }
[438]160 /**
[996]161 * Treats a string as a URL and attempts to open it
162 */
163 public static void openURL(String siteURL){
164
165 try {
166 URL check = new URL(siteURL);
167 Desktop.getDesktop().browse(new URI(siteURL));
168
169 } catch (IOException| URISyntaxException e) {
170
171 MessageBay.displayMessage("'" + siteURL + "' is not a valid URL");
172 }
173 }
174 /**
175 * Backs up the current frame as a default and saves it to the file
176 */
177 public static void setRestorePoint()
178 {
179 Frame current = DisplayIO.getCurrentFrame();
180 current.change();
181 FrameIO.SaveFrameAsRestore(current, true, true);
182 }
183 /**
[4]184 * Forces a repaint of the current Frame
185 */
[181]186 public static void display() {
187 FrameGraphics.refresh(false);
[4]188 }
[412]189
190 public static String getWindowSize() {
191 return Browser.getWindows()[0].getSize().toString();
192 }
[4]193
194 /**
195 * Restores the current frame to the last saved version currently on the
196 * hard disk
197 */
[181]198 public static void restore() {
[4]199 FrameIO.Reload();
[121]200 // MessageBay.displayMessage("Restoration complete.");
[4]201 }
202
203 /**
204 * Toggles AudienceMode on or off
205 */
[181]206 public static void toggleAudienceMode() {
[4]207 FrameGraphics.ToggleAudienceMode();
208 }
209
210 /**
211 * Toggles TwinFrames mode on or off
212 */
[181]213 public static void toggleTwinFramesMode() {
[4]214 DisplayIO.ToggleTwinFrames();
215 }
216
217 /**
218 * If the given Item is a Text Item, then the text of the Item is
219 * interpreted as actions, if not this method does nothing.
220 *
221 * @param current
222 * The Item to read the Actions from
223 */
[181]224 public static void runItem(Item current) throws Exception {
[4]225 if (current instanceof Text) {
[80]226 List<String> actions = ((Text) current).getTextList();
[4]227 for (String action : actions) {
[181]228 if (!action.equalsIgnoreCase("runitem")) {
[160]229 Actions.PerformAction(DisplayIO.getCurrentFrame(), current,
230 action);
231 }
[4]232 }
[156]233 } else {
234 MessageBay.errorMessage("Item must be a text item.");
[4]235 }
236 }
237
238 /**
239 * Prompts the user to confirm deletion of the current Frame, and deletes if
240 * the user chooses. After deletion this action calls back(), to ensure the
241 * deleted frame is not still being shown
242 *
243 */
[282]244 public static void DeleteFrame(Frame toDelete) {
[80]245 String deletedFrame = toDelete.getName();
[7]246 String deletedFrameNameLowercase = deletedFrame.toLowerCase();
[97]247 String errorMessage = "Error deleting " + deletedFrame;
[4]248 try {
[154]249 String deletedFrameName = FrameIO.DeleteFrame(toDelete);
250 if (deletedFrameName != null) {
251 DisplayIO.Back();
[156]252 // Remove any links on the previous frame to the one being
253 // deleted
[4]254 Frame current = DisplayIO.getCurrentFrame();
255 for (Item i : current.getItems())
256 if (i.getLink() != null
[7]257 && i.getAbsoluteLink().toLowerCase().equals(
258 deletedFrameNameLowercase)) {
[4]259 i.setLink(null);
260 }
[154]261 MessageBay.displayMessage(deletedFrame + " renamed "
262 + deletedFrameName);
[156]263 // FrameGraphics.Repaint();
[97]264 return;
[4]265 }
[115]266 } catch (IOException ioe) {
267 if (ioe.getMessage() != null)
268 errorMessage += ". " + ioe.getMessage();
[97]269 } catch (SecurityException se) {
[115]270 if (se.getMessage() != null)
271 errorMessage += ". " + se.getMessage();
[97]272 } catch (Exception e) {
273 e.printStackTrace();
[4]274 }
[121]275 MessageBay.errorMessage(errorMessage);
[4]276 }
277
278 /**
279 * Loads the Frame linked to by the given Item. The first Item on the Frame
280 * that is not the title or name is then placed on the cursor. If the given
281 * Item has no link, or no item is found then this is a no-op.
282 *
283 * @param current
284 * The Item that links to the Frame that the Item will be loaded
285 * from.
286 */
[181]287 public static Item GetItemFromChildFrame(Item current) {
288 return getFromChildFrame(current, false);
[70]289 }
[163]290
[162]291 public static void GetItemsFromChildFrame(Item current) {
292 getItemsFromChildFrame(current, false);
293 }
[72]294
[70]295 /**
[72]296 * Loads the Frame linked to by the given Item. The first Text Item on the
297 * Frame that is not the title or name is then placed on the cursor. If the
298 * given Item has no link, or no item is found then this is a no-op.
[70]299 *
300 * @param current
301 * The Item that links to the Frame that the Item will be loaded
302 * from.
303 */
[181]304 public static Item GetTextFromChildFrame(Item current) {
305 return getFromChildFrame(current, true);
[70]306 }
[72]307
[181]308 private static Item getFromChildFrame(Item current, boolean textOnly) {
[70]309 Item item = getFirstBodyItemOnChildFrame(current, textOnly);
[4]310 // if no item was found
[181]311 if (item != null) {
312 // copy the item and switch
313 item = item.copy();
314 item.setPosition(DisplayIO.getMouseX(), FrameMouseActions.getY());
[4]315 }
[181]316 return item;
[4]317 }
[163]318
[162]319 private static void getItemsFromChildFrame(Item current, boolean textOnly) {
320 Collection<Item> items = getItemsOnChildFrame(current, textOnly);
321 // if no item was found
322 if (items == null || items.size() == 0) {
323 return;
324 }
[4]325
[162]326 // copy the item and switch
327 Collection<Item> copies = ItemUtils.CopyItems(items);
[163]328 Item first = items.iterator().next();
329 float deltaX = DisplayIO.getMouseX() - first.getX();
330 float deltaY = FrameMouseActions.getY() - first.getY();
331 for (Item i : copies) {
332 if (i.isVisible())
333 i.setXY(i.getX() + deltaX, i.getY() + deltaY);
[162]334 i.setParent(null);
335 }
336 FrameMouseActions.pickup(copies);
337 FrameGraphics.Repaint();
338 }
[950]339
[4]340 /**
341 * Sets the given Item to have the Given Color. Color can be null (for
342 * default)
343 *
344 * @param toChange
345 * The Item to set the Color.
346 * @param toUse
347 * The Color to give the Item.
348 */
[181]349 public static void SetItemBackgroundColor(Item toChange, Color toUse) {
[4]350 if (toChange == null)
351 return;
352
353 toChange.setBackgroundColor(toUse);
354 FrameGraphics.Repaint();
355 }
356
357 /**
358 * Sets the given Item to have the Given Color. Color can be null (for
359 * default)
360 *
361 * @param toChange
362 * The Item to set the Color.
363 * @param toUse
364 * The Color to give the Item.
365 */
[181]366 public static void SetItemColor(Item toChange, Color toUse) {
[4]367 if (toChange == null)
368 return;
369
370 toChange.setColor(toUse);
371 FrameGraphics.Repaint();
372 }
373
374 /**
[70]375 * Creates a new Text Object containing general statistics for the current
376 * session. The newly created Text Object is then attached to the cursor via
377 * FrameMouseActions.pickup(Item)
[4]378 */
[21]379 public static void GetSessionStats() {
[115]380 attachStatsToCursor(SessionStats.getCurrentStats());
[70]381 }
[4]382
[86]383 /**
384 * Creates a new Text Object containing statistics for the current tree.
385 */
[181]386 public static String GetCometStats(Frame frame) {
[90]387 TimeKeeper timer = new TimeKeeper();
[121]388 MessageBay.displayMessage("Computing comet stats...");
[105]389 CometStats cometStats = new CometStats(frame);
[181]390 String result = cometStats.toString();
[121]391 MessageBay.overwriteMessage("Comet stats time: "
[90]392 + timer.getElapsedStringSeconds());
[181]393 return result;
[90]394 }
[86]395
[181]396 public static String GetTreeStats(Frame frame) {
[90]397 TimeKeeper timer = new TimeKeeper();
[121]398 MessageBay.displayMessage("Computing tree stats...");
[90]399
[105]400 TreeStats treeStats = new TreeStats(frame);
[181]401 String result = treeStats.toString();
[121]402 MessageBay.overwriteMessage("Tree stats time: "
[90]403 + timer.getElapsedStringSeconds());
[181]404 return result;
405
[86]406 }
[376]407
[362]408 public static String GetDocumentStats(Frame frame) {
409 TimeKeeper timer = new TimeKeeper();
410 MessageBay.displayMessage("Computing document stats...");
[376]411 FrameIO.ForceSaveFrame(frame);
412 DocumentStatsFast docStats = new DocumentStatsFast(frame.getName(),
413 frame.getTitle());
414 String result = docStats.toString();
[86]415
[362]416 MessageBay.overwriteMessage("Document stats time: "
417 + timer.getElapsedStringSeconds());
418 return result;
419
420 }
421
[115]422 /**
423 * Creates a text item and attaches it to the cursor.
424 *
425 * @param itemText
426 * the text to attach to the cursor
427 */
428 public static void attachStatsToCursor(String itemText) {
[72]429 SessionStats.CreatedText();
430 Frame current = DisplayIO.getCurrentFrame();
[78]431 Item text = current.getStatsTextItem(itemText);
[4]432 FrameMouseActions.pickup(text);
433 FrameGraphics.Repaint();
434 }
435
[115]436 public static void attachTextToCursor(String itemText) {
437 SessionStats.CreatedText();
438 Frame current = DisplayIO.getCurrentFrame();
439 Item text = current.getTextItem(itemText);
440 FrameMouseActions.pickup(text);
441 FrameGraphics.Repaint();
442 }
[438]443
[4]444 /**
[70]445 * Creates a new Text Object containing statistics for moving, deleting and
446 * creating items in the current session. The newly created Text Object is
447 * then attached to the cursor via FrameMouseActions.pickup(Item)
448 */
[181]449 public static String getItemStats() {
450 return SessionStats.getItemStats();
[70]451 }
452
453 /**
454 * Creates a new Text Object containing statistics for the time between
455 * events triggered by the user through mouse clicks and key presses. The
456 * newly created Text Object is then attached to the cursor via
457 * FrameMouseActions.pickup(Item)
458 */
[181]459 public static String getEventStats() {
460 return SessionStats.getEventStats();
[70]461 }
462
463 /**
[4]464 * Creates a new Text Object containing the contents of the current frames
465 * file.
466 */
[181]467 public static String getFrameFile(Frame frame) {
468 return FrameIO.ForceSaveFrame(frame);
[4]469 }
[7]470
[4]471 /**
472 * Creates a new Text Object containing the available fonts.
473 */
[181]474 public static String getFontNames() {
[115]475 Collection<String> availableFonts = Actions.getFonts().values();
[4]476 StringBuilder fontsList = new StringBuilder();
[7]477 for (String s : availableFonts) {
[115]478 fontsList.append(s).append(Text.LINE_SEPARATOR);
[4]479 }
[115]480 fontsList.deleteCharAt(fontsList.length() - 1);
[7]481
[181]482 return fontsList.toString();
[115]483 }
[996]484 /**
485 * Creates a new Text Object containing the available fonts already loaded into Expeditee.
486 */
487 public static String getExpediteeFontNames(){
488
489 StringBuilder fontsList = new StringBuilder();
490
491 for (String s: Text.FONT_WHEEL){
492
493 fontsList.append(s).append(Text.LINE_SEPARATOR);
494 }
[4]495
[996]496 for (Entry<String, java.awt.Font> entry: Text.FONT_WHEEL_ADDITIONAL_LOOKUP.entrySet()){
497
498 String fontName = entry.getKey();
499 fontsList.append(fontName).append(Text.LINE_SEPARATOR);
500 }
501 //add the default soon too
502 fontsList.deleteCharAt(fontsList.length() - 1);
503 return fontsList.toString();
504 }
505
[181]506 public static String getUnicodeCharacters(int start, int finish) {
[154]507 if (start < 0 && finish < 0) {
[115]508 throw new RuntimeException("Parameters must be non negative");
509 }
[154]510 // Swap the start and finish if they are inthe wrong order
511 if (start > finish) {
[115]512 start += finish;
[154]513 finish = start - finish;
[115]514 start = start - finish;
515 }
516 StringBuilder charList = new StringBuilder();
517 int count = 0;
[154]518 charList.append(String.format("Unicode block 0x%x - 0x%x", start,
519 finish));
[115]520 System.out.println();
[154]521 // charList.append("Unicode block: ").append(String.format(format,
522 // args))
523 for (char i = (char) start; i < (char) finish; i++) {
[115]524 if (Character.isDefined(i)) {
[154]525 if (count++ % 64 == 0)
[115]526 charList.append(Text.LINE_SEPARATOR);
527 charList.append(Character.valueOf(i));
528 }
529 }
[181]530 return charList.toString();
[4]531 }
[154]532
[115]533 /**
534 * Gets a single block of Unicode characters.
[154]535 *
536 * @param start
537 * the start of the block
[115]538 */
[181]539 public static String getUnicodeCharacters(int start) {
540 return getUnicodeCharacters(start, start + 256);
[115]541 }
[154]542
[978]543 /**
544 * Get a single Unicode character
545 *
546 * @param codePoint
547 * the Unicode codePoint
548 */
549 public static String getUnicodeCharacter(int codePoint) {
550 char codePointChar = (char) codePoint;
551 if (Character.isDefined(codePointChar)) {
552 return Character.valueOf(codePointChar).toString();
553 }
554 else {
555 MessageBay.errorMessage("Character value '" + codePoint +"' not defined");
556 return "";
557 }
558 }
559
[181]560 public static String getMathSymbols() {
561 return getUnicodeCharacters('\u2200', '\u2300');
[115]562 }
[4]563
564 /**
565 * Resets the statistics back to zero.
566 */
[181]567 public static void repaint() {
[4]568 StatsLogger.WriteStatsFile();
569 SessionStats.resetStats();
570 }
571
572 /**
573 * Loads a frame with the given name and saves it as a JPEG image.
574 *
575 * @param framename
576 * The name of the Frame to save
577 */
[181]578 public static void jpegFrame(String framename) {
[80]579 ImageFrame(framename, "JPEG");
[4]580 }
581
582 /**
583 * Saves the current frame as a JPEG image. This is the same as calling
[80]584 * JpegFrame(currentFrame.getName())
[4]585 */
[181]586 public static void jpegFrame() {
[80]587 ImageFrame(DisplayIO.getCurrentFrame().getName(), "JPEG");
[4]588 }
589
[181]590 public static void jpgFrame() {
591 jpegFrame();
[80]592 }
593
[4]594 /**
595 * Loads a frame with the given name and saves it as a PNG image.
596 *
597 * @param framename
598 * The name of the Frame to save
599 */
600 public static void PNGFrame(String framename) {
601 ImageFrame(framename, "PNG");
602 }
603
604 /**
605 * Saves the current frame as a PNG image. This is the same as calling
[80]606 * PNGFrame(currentFrame.getName())
[4]607 */
[376]608 public static void PNGFrame(Frame frame) {
609 ImageFrame(frame.getName(), "PNG");
[4]610 }
611
[86]612 public static String SaveImage(BufferedImage screen, String format,
613 String directory, String fileName) {
[376]614 String suffix = "." + format.toLowerCase();
615 String shortFileName = fileName;
[80]616 // Check if we need to append the suffix
617 if (fileName.indexOf('.') < 0)
[376]618 fileName += suffix;
619 else
620 shortFileName = fileName.substring(0, fileName.length() - suffix.length());
[80]621
622 try {
[376]623 int count = 2;
[80]624 // set up the file for output
[376]625 File out = new File(directory + fileName);
626 while (out.exists()) {
627 fileName = shortFileName + "_" + count++ + suffix;
628 out = new File(directory + fileName);
629 }
630
[80]631 if (!out.getParentFile().exists())
632 out.mkdirs();
633
634 // If the image is successfully written out return the fileName
635 if (ImageIO.write(screen, format, out))
636 return fileName;
637
638 } catch (Exception e) {
639 e.printStackTrace();
640 }
641 return null;
642 }
[86]643
[80]644 public static String ImageFrame(Frame frame, String format, String directory) {
645 assert (frame != null);
[86]646
[181]647 Image oldBuffer = frame.getBuffer();
648 frame.setBuffer(null);
649 // Jpeg only works properly with volitile frames
650 // Png transparency only works with bufferedImage form
651 Image frameBuffer = FrameGraphics.getBuffer(frame, false, format
652 .equalsIgnoreCase("jpeg"));
653 // Make sure overlay stuff doesnt disapear on the frame visible on the
654 // screen
655 frame.setBuffer(oldBuffer);
656 BufferedImage screen = null;
[80]657
[181]658 if (frameBuffer instanceof VolatileImage) {
659 // If its the current frame it will be a volitive image
[80]660 screen = ((VolatileImage) frameBuffer).getSnapshot();
661 } else {
[181]662 assert (frameBuffer instanceof BufferedImage);
663 screen = (BufferedImage) frameBuffer;
[80]664 }
665 return SaveImage(screen, format, directory, frame.getExportFileName());
666 }
667
[4]668 /**
669 * Saves the Frame with the given Framename as an image of the given format.
670 *
671 * @param framename
672 * The name of the Frame to save as an image
673 * @param format
674 * The Image format to use (i.e. "PNG", "BMP", etc)
675 */
676 public static void ImageFrame(String framename, String format) {
677 Frame loaded = FrameIO.LoadFrame(framename);
678
679 // if the frame was loaded successfully
680 if (loaded != null) {
[406]681 String path = FrameIO.EXPORTS_DIR;
[80]682 String frameName = ImageFrame(loaded, format, path);
683 if (frameName != null)
[154]684 MessageBay.displayMessage("Frame successfully saved to " + path
685 + frameName);
[80]686 else
[121]687 MessageBay.errorMessage("Could not find image writer for "
[80]688 + format + " format");
[4]689 // if the frame was not loaded successfully, alert the user
[181]690 } else {
[121]691 MessageBay.displayMessage("Frame '" + framename
[4]692 + "' could not be found.");
[181]693 }
[4]694 }
695
[336]696 public static void MessageLn(Item message) {
697 if (message instanceof Text)
698 MessageBay.displayMessage((Text) message);
699 }
700
[4]701 /**
702 * Displays a message in the message box area.
703 *
704 * @param message
705 * the message to display
706 */
707 public static void MessageLn(String message) {
[121]708 MessageBay.displayMessage(message);
[4]709 }
710
711 public static void MessageLn2(String message, String message2) {
[121]712 MessageBay.displayMessage(message + " " + message2);
[4]713 }
714
715 public static void CopyFile(String existingFile, String newFileName) {
716 try {
[7]717 // TODO is there a built in method which will do this faster?
718
[154]719 MessageBay.displayMessage("Copying file " + existingFile + " to "
720 + newFileName + "...");
[7]721 FrameIO.copyFile(existingFile, newFileName);
[121]722 MessageBay.displayMessage("File copied successfully");
[4]723 } catch (FileNotFoundException e) {
[121]724 MessageBay.displayMessage("Error opening file: " + existingFile);
[7]725 } catch (Exception e) {
[121]726 MessageBay.displayMessage("File could not be copied");
[4]727 }
728 }
729
730 /**
[72]731 * Runs two methods alternatively a specified number of times and reports on
732 * the time spent running each method.
733 *
734 * @param fullMethodNameA
735 * @param fullMethodNameB
736 * @param repsPerTest
737 * the number of time each method is run per test
738 * @param tests
739 * the number of tests to conduct
740 *
741 */
742 public static void CompareMethods(String fullMethodNameA,
743 String fullMethodNameB, int repsPerTest, int tests) {
744 try {
745 String classNameA = getClassName(fullMethodNameA);
746 String classNameB = getClassName(fullMethodNameB);
747 String methodNameA = getMethodName(fullMethodNameA);
748 String methodNameB = getMethodName(fullMethodNameB);
749
[176]750 Class<?> classA = Class.forName(classNameA);
751 Class<?> classB = Class.forName(classNameB);
[72]752 Method methodA = classA.getDeclaredMethod(methodNameA,
753 new Class[] {});
754 Method methodB = classB.getDeclaredMethod(methodNameB,
755 new Class[] {});
756 TimeKeeper timeKeeper = new TimeKeeper();
757 long timeA = 0;
758 long timeB = 0;
759 // Run the tests
760 for (int i = 0; i < tests; i++) {
761 // Test methodA
762 timeKeeper.restart();
763 for (int j = 0; j < repsPerTest; j++) {
[80]764 methodA.invoke((Object) null, new Object[] {});
[72]765 }
766 timeA += timeKeeper.getElapsedMillis();
767 timeKeeper.restart();
768 // Test methodB
769 for (int j = 0; j < repsPerTest; j++) {
[80]770 methodB.invoke((Object) null, new Object[] {});
[72]771 }
772 timeB += timeKeeper.getElapsedMillis();
773 }
774
775 float aveTimeA = timeA * 1000F / repsPerTest / tests;
776 float aveTimeB = timeB * 1000F / repsPerTest / tests;
777 // Display Results
[121]778 MessageBay.displayMessage("Average Execution Time");
779 MessageBay.displayMessage(methodNameA + ": "
[72]780 + TimeKeeper.Formatter.format(aveTimeA) + "us");
[121]781 MessageBay.displayMessage(methodNameB + ": "
[72]782 + TimeKeeper.Formatter.format(aveTimeB) + "us");
783 } catch (Exception e) {
[121]784 MessageBay.errorMessage(e.getClass().getSimpleName() + ": "
[72]785 + e.getMessage());
786 }
787 }
788
789 public static String getClassName(String fullMethodName) {
790 assert (fullMethodName != null);
791 assert (fullMethodName.length() > 0);
792 int lastPeriod = fullMethodName.lastIndexOf('.');
793 if (lastPeriod > 0 && lastPeriod < fullMethodName.length() - 1)
794 return fullMethodName.substring(0, lastPeriod);
795 throw new RuntimeException("Invalid method name: " + fullMethodName);
796 }
797
798 public static String getMethodName(String methodName) {
799 assert (methodName != null);
800 assert (methodName.length() > 0);
801 int lastPeriod = methodName.lastIndexOf('.');
802 if (lastPeriod > 0 && lastPeriod < methodName.length() - 1)
803 return methodName.substring(1 + lastPeriod);
804 throw new RuntimeException("Invalid method name: " + methodName);
805 }
806
807 /**
[4]808 * Loads the Frame linked to by the given Item. The first Item on the Frame
809 * that is not the title or name is then placed on the current frame. The
810 * item that was clicked on is placed on the frame it was linked to and the
811 * link is switched to the item from the child frame. If the given Item has
812 * no link, or no item is found then this is a no-op.
813 *
814 * @param current
815 * The Item that links to the Frame that the Item will be loaded
816 * from.
817 */
818 public static void SwapItemWithItemOnChildFrame(Item current) {
[70]819 Item item = getFirstBodyItemOnChildFrame(current, false);
[4]820 // if no item was found
821 if (item == null) {
822 return;
823 }
824
825 // swap the items parents
826 Frame parentFrame = current.getParent();
827 Frame childFrame = item.getParent();
828 current.setParent(childFrame);
829 item.setParent(parentFrame);
830
831 // swap the items on the frames
832 parentFrame.removeItem(current);
833 childFrame.removeItem(item);
834 parentFrame.addItem(item);
835 childFrame.addItem(current);
836
837 // swap the items links
[74]838 item.setActions(current.getAction());
[80]839 item.setLink(childFrame.getName());
840 current.setLink(parentFrame.getName());
[4]841 // current.setLink(null);
[74]842 current.setActions(null);
[4]843
844 FrameGraphics.Repaint();
845 }
846
[72]847 private static Item getFirstBodyItemOnChildFrame(Item current,
848 boolean textOnly) {
[4]849 // the item must link to a frame
850 if (current.getLink() == null) {
[121]851 MessageBay
852 .displayMessage("Cannot get item from child - this item has no link");
[4]853 return null;
854 }
855
856 Frame child = FrameIO.LoadFrame(current.getAbsoluteLink());
857
858 // if the frame could not be loaded
859 if (child == null) {
[121]860 MessageBay.errorMessage("Could not load child frame.");
[4]861 return null;
862 }
863
864 // find the first non-title and non-name item
[70]865 List<Item> body = new ArrayList<Item>();
[72]866 if (textOnly)
[70]867 body.addAll(child.getBodyTextItems(false));
868 else
869 body.addAll(child.getItems());
[4]870 Item item = null;
871
872 for (Item i : body)
[80]873 if (i != child.getTitleItem() && !i.isAnnotation()) {
[4]874 item = i;
875 break;
876 }
877
878 // if no item was found
879 if (item == null) {
[121]880 MessageBay.displayMessage("No item found to copy");
[4]881 return null;
882 }
883
884 return item;
885 }
[163]886
[162]887 private static Collection<Item> getItemsOnChildFrame(Item current,
888 boolean textOnly) {
889 // the item must link to a frame
890 if (current.getLink() == null) {
891 MessageBay
892 .displayMessage("Cannot get item from child - this item has no link");
893 return null;
894 }
895 Frame child = FrameIO.LoadFrame(current.getAbsoluteLink());
[156]896
[162]897 // if the frame could not be loaded
898 if (child == null) {
899 MessageBay.errorMessage("Could not load child frame.");
900 return null;
901 }
902
903 // find the first non-title and non-name item
904 Collection<Item> body = new ArrayList<Item>();
905 if (textOnly)
906 body.addAll(child.getBodyTextItems(false));
907 else
908 body.addAll(child.getItems());
[163]909
[162]910 return body;
911 }
912
[156]913 public static void calculate(Frame frame, Item toCalculate) {
914 if (toCalculate instanceof Text) {
915 Text text = (Text) toCalculate;
[161]916 ExpediteeJEP myParser = new ExpediteeJEP();
917 myParser.addVariables(frame);
918 String linkedFrame = toCalculate.getAbsoluteLink();
919 if (linkedFrame != null) {
920 myParser.addVariables(FrameIO.LoadFrame(linkedFrame));
[156]921 }
[162]922 myParser.resetObserver();
[160]923
[156]924 // Do the calculation
[190]925 String formulaFullCase = text.getText().replace('\n', ' ');
926 String formula = formulaFullCase.toLowerCase();
927
928 try {
929 Node node = myParser.parse(formula);
930 Object result = myParser.evaluate(node);
[390]931 text.setText(result.toString(), true);
[190]932 text.setFormula(formulaFullCase);
933 if (text.isFloating()) {
934 text.setPosition(FrameMouseActions.MouseX,
935 FrameMouseActions.MouseY);
936 FrameMouseActions.resetOffset();
[161]937 } else {
[190]938 text.getParentOrCurrentFrame().change();
[156]939 }
[190]940 } catch (ParseException e) {
941 MessageBay.errorMessage("Parse error "
942 + e.getMessage().replace("\n", ""));
943 } catch (Exception e) {
944 MessageBay.errorMessage("evaluation error "
945 + e.getMessage().replace("\n", ""));
946 e.printStackTrace();
[156]947 }
948 }
949 }
[181]950
951 /**
952 * Attach an item to the cursor.
953 *
954 * @param item
955 */
956 public static void attachToCursor(Item item) {
957 item.setParent(null);
958 FrameMouseActions.pickup(item);
959 FrameGraphics.Repaint();
960 }
[242]961
[278]962 public static void attachToCursor(Collection<Item> items) {
963 for (Item i : items) {
964 i.setParent(null);
[311]965 i.invalidateAll();
[278]966 }
967 FrameMouseActions.pickup(items);
[311]968 // TODO figure out why this isnt repainting stuff immediately
969 // All of text item doesnt repaint until the cursor is moved
970 FrameGraphics.requestRefresh(true);
[278]971 }
972
[247]973 public static void importFiles(Item item) {
[242]974 List<File> files = new LinkedList<File>();
[282]975 for (String s : item.getText().split("\\s+")) {
976 File file = new File(s.trim());
[247]977 if (file.exists()) {
[242]978 files.add(file);
979 }
980 }
981 try {
982 FrameDNDTransferHandler.getInstance().importFileList(files,
983 FrameMouseActions.getPosition());
984 } catch (Exception e) {
985 }
986 }
[247]987
988 public static void importFile(Item item) {
[282]989 File file = new File(item.getText().trim());
[247]990 if (file.exists()) {
991 try {
992 FrameDNDTransferHandler.getInstance().importFile(file,
993 FrameMouseActions.getPosition());
994 } catch (Exception e) {
995 e.printStackTrace();
996 }
997 }
[242]998 }
[247]999
[278]1000 public static Item createPolygon(Item item, int sides) {
1001 if (item instanceof Text) {
1002 try {
1003 SString s = new SString(item.getText());
1004 sides = s.integerValue().intValue();
1005 } catch (NumberFormatException e) {
1006 }
1007 }
1008
[247]1009 if (sides < 3) {
1010 MessageBay.errorMessage("Shapes must have at least 3 sides");
1011 }
[278]1012 double angle = -(180 - ((sides - 2) * 180.0F) / sides);
[247]1013 double curAngle = 0;
1014 double size = 50F;
[282]1015 if (item.isLineEnd() && item.getLines().size() > 0) {
[247]1016 item = item.getLines().get(0);
1017 }
1018 // Use line length to determine the size of the shape
1019 if (item instanceof Line) {
1020 size = ((Line) item).getLength();
1021 }
1022
1023 float curX = FrameMouseActions.MouseX;
1024 float curY = FrameMouseActions.MouseY;
1025
1026 Collection<Item> newItems = new LinkedList<Item>();
1027 Item[] d = new Item[sides];
1028 // create dots
1029 Frame current = DisplayIO.getCurrentFrame();
1030 for (int i = 0; i < d.length; i++) {
1031 d[i] = current.createDot();
1032 newItems.add(d[i]);
1033 d[i].setPosition(curX, curY);
1034 curX += (float) (Math.cos((curAngle) * Math.PI / 180.0) * size);
1035 curY += (float) (Math.sin((curAngle) * Math.PI / 180.0) * size);
1036
1037 curAngle += angle;
1038 }
1039 // create lines
1040 for (int i = 1; i < d.length; i++) {
1041 newItems.add(new Line(d[i - 1], d[i], current.getNextItemID()));
1042 }
1043 newItems.add(new Line(d[d.length - 1], d[0], current.getNextItemID()));
1044
1045 current.addAllItems(newItems);
[294]1046 if (item instanceof Text) {
1047 for (Item i : item.getAllConnected()) {
1048 if (i instanceof Line) {
[278]1049 item = i;
1050 break;
1051 }
1052 }
1053 }
[294]1054
1055 Color newColor = item.getColor();
1056 if (newColor != null) {
[278]1057 d[0].setColor(item.getColor());
[294]1058 if (item instanceof Text && item.getBackgroundColor() != null) {
1059 d[0].setFillColor(item.getBackgroundColor());
[311]1060 } else {
[294]1061 d[0].setFillColor(item.getFillColor());
1062 }
[278]1063 }
[294]1064 float newThickness = item.getThickness();
1065 if (newThickness > 0) {
1066 d[0].setThickness(newThickness);
1067 }
[247]1068
1069 ItemUtils.EnclosedCheck(newItems);
1070 FrameGraphics.refresh(false);
[278]1071
1072 return d[0];
[247]1073 }
[294]1074
[284]1075 public static void StopReminder() {
1076 Reminders.stop();
1077 }
[311]1078
1079 public static void print(String file) {
[309]1080 try {
[464]1081 if (Browser._theBrowser.isMinimumVersion6()) {
[309]1082 if (Desktop.isDesktopSupported()) {
1083 Desktop.getDesktop().print(new File(file));
1084 }
1085 }
1086 } catch (Exception e) {
1087 MessageBay.errorMessage("Printing error: " + e.getMessage());
1088 }
1089 }
[362]1090
1091 public static int wordCount(String paragraph) {
1092 return paragraph.trim().split("\\s+").length + 1;
1093 }
[376]1094
[362]1095 public static int wordCount(Frame frame) {
1096 int count = 0;
[376]1097
1098 for (Text t : frame.getBodyTextItems(false)) {
[362]1099 count += wordCount(t.getText());
1100 }
[376]1101
[362]1102 return count;
1103 }
[376]1104
1105 public static void moveToPublic(Frame frame) {
[362]1106 FrameIO.moveFrameset(frame.getFramesetName(), FrameIO.PUBLIC_PATH);
1107 }
[376]1108
1109 public static void moveToPrivate(Frame frame) {
[362]1110 FrameIO.moveFrameset(frame.getFramesetName(), FrameIO.FRAME_PATH);
1111 }
[376]1112
1113 /**
1114 * Returns the value of a specified item attribute.
1115 *
1116 * @param item
1117 * from which to extract the value
1118 * @param attribute
1119 * name of an items attribute
1120 * @return the value of the attribute
1121 */
1122 public static String extract(Item item, String attribute) {
1123 return AttributeUtils.getAttribute(item, attribute);
1124 }
[514]1125
1126 /**
1127 * Launches items.widgets.Browser and uses Text item as URL.
1128 * @param text Text item which passes contents as URL for browser.
1129 * @throws Exception
1130 */
[534]1131 public static void startLoboBrowser(Item text) throws Exception {
1132 if (!(text instanceof Text)) {
1133 MessageBay.errorMessage("Must be a text item.");
1134 return;
1135 }
1136 if(text.getLink() != null) {
1137 MessageBay.errorMessage("Text item cannot have link.");
1138 return;
1139 }
1140
1141 FreeItems.getInstance().clear(); // remove url text from cursor
[514]1142
[534]1143 Text wt = new Text("@iw:org.expeditee.items.widgets.Browser"); // create new text item for browser widget
1144 wt.setParent(DisplayIO.getCurrentFrame()); // set parent of text source for InteractiveWidget.createWidget()
1145 wt.setXY(FrameMouseActions.getX(), FrameMouseActions.getY());
1146 // create widget from text item
1147 org.expeditee.items.widgets.Browser browser = (org.expeditee.items.widgets.Browser) InteractiveWidget.createWidget(wt);
[514]1148
[534]1149 if(FreeItems.textOnlyAttachedToCursor()) { // navigates to url specified by the text item
1150 browser.navigate(text.getText());
[514]1151 } else {
[534]1152 browser.navigate("http://www.waikato.ac.nz");
[514]1153 }
[534]1154
1155 FrameMouseActions.pickup(browser.getItems()); // attach browser widget to mouse
[514]1156 }
1157
1158 /**
1159 * Text item becomes link to new frame containing items.widgets.Browser and uses Text item as URL for browser.
1160 * @param text Text item which passes contents as URL for browser and becomes link to the browser's new frame.
1161 * @throws Exception
1162 */
[534]1163 public static void startLoboBrowserNewFrame(Item text) throws Exception {
[514]1164 if (!(text instanceof Text)) {
1165 MessageBay.errorMessage("Must be a text item.");
1166 return;
1167 }
1168 if(text.getLink() != null) { // text item can't already have a link
1169 MessageBay.errorMessage("Text item already has link.");
1170 return;
1171 }
1172
[548]1173 // Create new frame and text item for browser widget and parse created frame; loads browser widget
1174 Frame frame = FrameIO.CreateNewFrame(text);
1175 frame.addText(0, 50, "@iw:org.expeditee.items.widgets.Browser", null);
1176 FrameUtils.Parse(frame);
[514]1177
[548]1178 for(InteractiveWidget iw : frame.getInteractiveWidgets()) { // may be other widgets on frame
[514]1179 if(iw instanceof org.expeditee.items.widgets.Browser) {
[516]1180 // Set browser to 'full screen'
[548]1181 iw.setSize(-1, -1, -1, -1, Browser._theBrowser.getWidth(), Browser._theBrowser.getHeight()
1182 - MessageBay.MESSAGE_BUFFER_HEIGHT - 80);
[516]1183
[514]1184 // If there is a text item attached to cursor use it as url for browser
1185 if(FreeItems.textOnlyAttachedToCursor()) {
1186 text.setLink("" + frame.getNumber());
1187 ((org.expeditee.items.widgets.Browser)iw).navigate(text.getText());
1188 } else {
1189 // Navigate to www.waikato.ac.nz by default if no url supplied and create new text item to be the link
1190 ((org.expeditee.items.widgets.Browser)iw).navigate("http://www.waikato.ac.nz");
1191 Text t = new Text("http://www.waikato.ac.nz");
[548]1192 t.setParent(DisplayIO.getCurrentFrame()); // set parent of text source for InteractiveWidget.createWidget()
[514]1193 t.setXY(FrameMouseActions.getX(), FrameMouseActions.getY());
[548]1194 t.setLink("" + frame.getNumber()); // link url text to new browser frame
1195 FrameMouseActions.pickup(t); // Attach new text link to cursor
[514]1196 }
1197 }
1198 }
1199
[548]1200 FrameIO.SaveFrame(frame); // save frame to disk
[514]1201 }
[518]1202
1203 private static boolean startWidget(String name) throws Exception {
1204 String fullName = Actions.getClassName(name);
1205 if(fullName == null) {
1206 return false;
1207 }
1208 MessageBay.displayMessage("Creating new \"" + fullName + "\"");
1209
1210 FreeItems.getInstance().clear();
1211 Text wt = new Text("@iw:" + fullName); // create new text item for browser widget
1212 wt.setParent(DisplayIO.getCurrentFrame()); // set parent of text source for InteractiveWidget.createWidget()
1213 wt.setXY(FrameMouseActions.getX(), FrameMouseActions.getY()); // move to the mouse cursor
1214 InteractiveWidget widget = InteractiveWidget.createWidget(wt);
1215 FrameMouseActions.pickup(widget.getItems());
1216
1217 return true;
1218 }
1219
1220 private static void runUnknown(String command) throws Exception {
1221 if(startWidget(command)) {
1222 return;
1223 }
1224
1225 Actions.PerformAction(DisplayIO.getCurrentFrame(), null, command);
1226 }
1227
1228 public static void run(String command) throws Exception {
[574]1229 if(command == null) {
1230 MessageBay.warningMessage("Please provide a command to run");
1231 return;
1232 }
[518]1233 int firstSpace = command.indexOf(" ");
1234 if(firstSpace == -1) {
1235 runUnknown(command);
1236 return;
1237 }
1238 String argLower = command.toLowerCase();
1239 String name = argLower.substring(0, firstSpace).trim(); // first word
1240 String args = argLower.substring(firstSpace).trim(); // remainder after first word
1241 if(name == "action" || name == "agent") {
1242 if(args.length() > 0) {
1243 Actions.PerformAction(DisplayIO.getCurrentFrame(), null, args);
1244 } else {
1245 MessageBay.displayMessage("Please specify an action/agent name");
1246 }
1247 } else if(name == "widget") {
1248 if(args.length() > 0) {
1249 if(!startWidget(args)) {
1250 MessageBay.displayMessage("Widget \"" + name + "\" does not exist");
1251 }
1252 } else {
1253 MessageBay.displayMessage("Please specify a widget name");
1254 }
1255 } else {
1256 runUnknown(command);
1257 }
1258 }
1259
1260 public static void run(Item item) throws Exception {
[574]1261 if(item == null) {
1262 MessageBay.warningMessage("Please provide a command to run");
1263 return;
1264 }
[518]1265 run(((Text)item).getText());
1266 }
[574]1267
[614]1268 /**
[622]1269 * Rebuilds the home frame restoring its original presentation.
1270 * Basically removes all items on the frame and reruns FrameUtils.CreateDefaultProfile().
[614]1271 */
[622]1272 public static void resetHomeFrame() {
[655]1273 Frame homeFrame = FrameIO.LoadFrame(UserSettings.HomeFrame.get());
[622]1274 homeFrame.removeAllItems(homeFrame.getItems());
1275 homeFrame.addText(0, 0, "title", null);
[655]1276 FrameUtils.CreateDefaultProfile(UserSettings.UserName.get(), homeFrame);
[614]1277 }
[645]1278
1279 /**
[624]1280 * Loads and runs an executable jar file in a new Thread
1281 * @param jar path to the jar file to run
1282 */
1283 public static void runJar(String jar) throws Exception {
1284 File jf = new File(jar);
1285 if(!jf.exists()) {
1286 System.err.println("jar '" + jar + "' could not be found");
1287 return;
1288 }
1289 JarFile jarFile = new JarFile(jf);
1290
1291 String mainClassName = (String) jarFile.getManifest().getMainAttributes().get(new Attributes.Name("Main-Class"));
1292 if(mainClassName == null) {
1293 System.err.println("jar '" + jar + "' does not have a Main-Class entry");
1294 jarFile.close();
1295 return;
1296 }
1297 jarFile.close();
1298 System.out.println("Main-Class = " + mainClassName);
1299
1300 ClassLoader classLoader = ClassLoader.getSystemClassLoader();
1301
1302 Method addURL = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
1303 addURL.setAccessible(true);
1304 addURL.invoke(classLoader, jf.toURI().toURL());
1305
1306 final Class<?> jarClass = classLoader.loadClass(mainClassName);
1307
1308 final Method main = jarClass.getDeclaredMethod("main", String[].class);
1309
1310 new Thread(new Runnable() {
1311 public void run() {
1312 try {
1313 main.invoke(jarClass, new Object[] {new String[0]});
1314 } catch (Exception e) {
1315 System.out.println("Failed to start jar");
1316 e.printStackTrace();
1317 }
1318 }
1319 }).start();
1320 }
[632]1321
1322 public static void pan(Frame frame, int x, int y) {
[805]1323 for (Item i : frame.getAllItems()) {
1324 if (i instanceof WidgetEdge || i instanceof WidgetCorner) {
[634]1325 continue;
[805]1326 }
1327 else {
[812]1328 int new_x = i.getX();
1329 int new_y = i.getY();
[805]1330
[812]1331 if (!i.isAnchoredX()) {
1332 new_x += x;
1333 }
[805]1334
[812]1335 if (!i.isAnchoredY()) {
1336 new_y += y;
1337 }
[805]1338
1339 if(i instanceof XRayable) {
[812]1340 i.setPosition(new_x,new_y);
[805]1341 }
1342 else {
[812]1343 i.setXY(new_x,new_y);
[805]1344 }
[634]1345 }
[632]1346 // update the polygon, otherwise stuff moves but leaves it's outline behind
1347 i.updatePolygon();
1348 }
[805]1349
1350 for (InteractiveWidget iw : frame.getInteractiveWidgets()) {
1351
[812]1352 int new_x = iw.getX();
1353 int new_y = iw.getY();
1354
1355 if (!iw.isAnchoredX()) {
1356 new_x += x;
1357 }
1358
1359 if (!iw.isAnchoredY()) {
1360 new_y += y;
1361 }
1362
[805]1363 iw.setPosition(new_x,new_y);
[812]1364
[634]1365 }
[805]1366
[632]1367 // make sure we save the panning of the frame
1368 frame.change();
1369 // redraw everything
1370 FrameKeyboardActions.Refresh();
1371 }
1372
1373 public static void pan(Frame frame, String pan) {
1374 String[] split = pan.split("\\s+");
1375 int x = 0;
1376 int y = 0;
1377 try {
1378 if(split.length != 2) throw new Exception();
1379 x = Integer.parseInt(split[0]);
1380 y = Integer.parseInt(split[1]);
1381 } catch(Exception e) {
1382 MessageBay.errorMessage("Panning takes 2 integer arguments");
1383 return;
1384 }
1385 pan(frame, x, y);
1386 }
1387
1388 public static void pan(Frame frame, Text pan) {
1389 pan(frame, pan.getText());
1390 }
[639]1391
[660]1392 public static String exec(String cmd) throws Exception {
1393
1394 String[] command;
1395
1396 // run command through sh if possible
1397 if(System.getProperty("os.name").toLowerCase().indexOf("win") == -1) {
1398 command = new String[] { "sh", "-c", cmd };
1399 } else {
1400 command = cmd.split("\\s+");
1401 }
1402
1403 ProcessBuilder pb = new ProcessBuilder(command);
1404 pb.redirectErrorStream(true);
1405 Process ps = pb.start();
1406
1407 BufferedReader in = new BufferedReader(new InputStreamReader(ps.getInputStream()));
1408 StringBuffer sb = new StringBuffer();
1409 String line;
1410 while ((line = in.readLine()) != null) {
1411 sb.append(line).append('\n');
1412 }
1413 ps.waitFor();
1414 in.close();
1415
1416 if(sb.length() > 0) {
1417 sb.deleteCharAt(sb.length() - 1);
1418 }
1419 return sb.toString();
[639]1420 }
[668]1421
[689]1422 public static void testProgress() {
1423 new Thread(new Runnable() {
1424
1425 @Override
1426 public void run() {
1427 Progress p = MessageBay.displayProgress("Loading something");
1428 for(int i = 1; i <= 100; i++) {
1429 try {
1430 Thread.sleep(100);
1431 p.set(i);
1432 } catch (Exception e) {
1433 e.printStackTrace();
1434 }
1435 }
1436 }
1437
1438 }).start();
1439 }
[722]1440
1441 public static void getIDs(Frame f) {
1442 for(Item i : f.getAllItems()) {
1443 System.out.println(i + " (" + i.getID() + ")");
1444 }
1445 }
[800]1446
1447 public static void flushResources() {
1448 FrameUtils.extractResources(true);
1449 MessageBay.displayMessage("Re-extracted resources, Expeditee may need to be restarted for certain resources to be reloaded");
1450 }
[1076]1451
1452 // Some experimental actions to do with keeping framesets stored within a Git repository
[1079]1453
1454
1455 // For custom merge, some potentially useful information at:
1456 // http://stackoverflow.com/questions/23140240/git-how-do-i-add-a-custom-merge-strategy
1457 // http://stackoverflow.com/questions/7607125/git-merge-conflict-to-always-take-the-newest-file
1458
[1076]1459 protected static String gitexe = "git";
1460
1461 protected static void runGitCommand(Frame frame, List<String> cmd_array) {
1462
1463 String framePath = frame.getPath();
1464 String frameName = frame.getName();
1465
1466 String frameDir = framePath + Conversion.getFramesetName(frameName)
1467 + File.separator;
1468 String localFname = Conversion.getFrameNumber(frameName)
1469 + ExpReader.EXTENTION;
1470
1471 ProcessBuilder process_builder = new ProcessBuilder(cmd_array);
1472
1473 process_builder.directory(new File(frameDir));
1474
1475 /*
1476 System.err.println("\nPATH:");
1477
1478 Map<String, String> env_map = process_builder.environment();
1479
1480 for (Entry<String, String> entry: env_map.entrySet()) {
1481 String key = entry.getKey();
1482 String value = entry.getValue();
1483 System.err.println(key + " = " + value);
1484 }
1485 */
1486
1487
1488 try {
1489 final Process process = process_builder.start();
1490 InputStream is = process.getInputStream();
1491 InputStreamReader isr = new InputStreamReader(is);
1492 BufferedReader br = new BufferedReader(isr);
1493 String line;
1494 while ((line = br.readLine()) != null) {
1495 System.out.println(line);
1496 }
1497 System.out.println("Program terminated!");
1498 }
1499 catch (Exception e) {
1500 e.printStackTrace();
1501 }
1502
1503 }
1504
1505 public static void GitPushFrame() {
1506
1507 FrameKeyboardActions.Save();
1508
1509 Frame current = DisplayIO.getCurrentFrame();
1510 String userName = UserSettings.ProfileName.get();
1511
1512 String frameName = current.getName();
1513 String localFname = Conversion.getFrameNumber(frameName)+ ExpReader.EXTENTION;
1514
1515 List<String> status_cmd_array = new ArrayList<String>();
1516 status_cmd_array.add(gitexe);
1517 status_cmd_array.add("status");
1518 status_cmd_array.add(".");
1519
1520 List<String> add_cmd_array = new ArrayList<String>();
1521 add_cmd_array.add(gitexe);
1522 add_cmd_array.add("add");
1523 add_cmd_array.add(localFname);
1524 add_cmd_array.add("frame.inf");
1525
1526 runGitCommand(current,add_cmd_array);
1527
1528 List<String> commit_cmd_array = new ArrayList<String>();
1529 commit_cmd_array.add(gitexe);
1530 commit_cmd_array.add("commit");
1531 commit_cmd_array.add("-m");
1532 commit_cmd_array.add("expeditee-edit-"+userName);
1533
1534 runGitCommand(current,commit_cmd_array);
1535
1536 List<String> push_cmd_array = new ArrayList<String>();
1537 push_cmd_array.add(gitexe);
1538 push_cmd_array.add("push");
1539 push_cmd_array.add("origin");
1540 push_cmd_array.add("master");
1541
1542 runGitCommand(current,push_cmd_array);
1543 }
1544
1545 public static void GitPullFrame() {
1546 Frame current = DisplayIO.getCurrentFrame();
1547
1548 List<String> cmd_array = new ArrayList<String>();
1549 cmd_array.add(gitexe);
1550 cmd_array.add("pull");
1551 cmd_array.add("origin");
1552 cmd_array.add("master");
1553 runGitCommand(current,cmd_array);
1554
1555 FrameIO.Reload();
1556 FrameKeyboardActions.Refresh();
1557 }
1558
[4]1559}
Note: See TracBrowser for help on using the repository browser.