Changeset 975 for trunk/src/org/expeditee/actions/Actions.java
- Timestamp:
- 11/24/15 11:17:31 (9 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/expeditee/actions/Actions.java
r919 r975 20 20 21 21 import java.awt.GraphicsEnvironment; 22 import java.io.File;23 import java.io.IOException;24 22 import java.lang.reflect.Constructor; 25 23 import java.lang.reflect.Method; 26 24 import java.lang.reflect.Modifier; 27 import java.net.URL;28 import java.net.URI;29 import java.net.URLDecoder;30 import java.net.JarURLConnection;31 25 import java.rmi.UnexpectedException; 32 import java.util.ArrayList;33 26 import java.util.Collection; 34 import java.util. Enumeration;27 import java.util.Comparator; 35 28 import java.util.HashMap; 36 29 import java.util.LinkedList; 37 30 import java.util.List; 38 31 import java.util.Set; 39 import java.util.jar.JarEntry;40 import java.util.jar.JarFile;41 import java.util.zip.ZipEntry;42 32 43 33 import org.expeditee.agents.Agent; … … 54 44 import org.expeditee.items.Text; 55 45 import org.expeditee.reflection.PackageLoader; 56 import org.expeditee.settings.UserSettings;57 46 import org.expeditee.simple.SString; 58 47 import org.expeditee.stats.Logger; … … 61 50 * The Action class is used to launch Actions and Agents. 62 51 * 63 * This class checks all class files in the same directory, and reads in and adds all the methods from them. The methods 64 * are stored in a Hashtable so that the lowercase method names can be mapped to the correctly capatilized method names 65 * (to provide case-insensitivity) 52 * This class checks all class files in the same directory, and reads in and 53 * adds all the methods from them. The methods are stored in a Hashtable so that 54 * the lowercase method names can be mapped to the correctly capatilized method 55 * names (to provide case-insensitivity) 66 56 * 67 * When adding an action to a class in the actions folder the following must be considered: <li>If the first parameter 68 * is of type Frame, the current frame will be passed as a parameter. <li>If the next param is of type Item the item on 69 * the end of the cursor will be passed or the item that was clicked to execute the action if nothing is on the end of 70 * the cursor. current frame or item.</li> <li>If there are multiple overloads for the same method they should be 71 * declared in order of the methods with the most parameteres to least parameters.</li> 57 * When adding an action to a class in the actions folder the following must be 58 * considered: <li>If the first parameter is of type Frame, the current frame 59 * will be passed as a parameter. <li>If the next param is of type Item the item 60 * on the end of the cursor will be passed or the item that was clicked to 61 * execute the action if nothing is on the end of the cursor. current frame or 62 * item.</li> <li>If there are multiple overloads for the same method they 63 * should be declared in order of the methods with the most parameteres to least 64 * parameters.</li> 72 65 */ 73 66 public class Actions { … … 99 92 public static final String WIDGET_PACKAGE = ROOT_PACKAGE + "items.widgets."; 100 93 101 public static final String CHARTS_PACKAGE = ROOT_PACKAGE + "items.widgets.charts."; 102 103 public static final String NAVIGATIONS_CLASS = ROOT_PACKAGE + "actions.NavigationActions"; 94 public static final String CHARTS_PACKAGE = ROOT_PACKAGE 95 + "items.widgets.charts."; 96 97 public static final String NAVIGATIONS_CLASS = ROOT_PACKAGE 98 + "actions.NavigationActions"; 104 99 105 100 // public static Class[] getClasses(String pckgname) … … 213 208 214 209 /** 215 * Clears out the Action and JAG Hashtables and refills them. Normally this is only called once when the system 216 * starts. 217 * 218 * @return a warning message if there were any problems loading agents or actions. 210 * Clears out the Action and JAG Hashtables and refills them. Normally this 211 * is only called once when the system starts. 212 * 213 * @return a warning message if there were any problems loading agents or 214 * actions. 219 215 */ 220 216 public static Collection<String> Init() { … … 232 228 } 233 229 234 235 230 classes = PackageLoader.getClassesNew(WIDGET_PACKAGE); 236 231 … … 241 236 } 242 237 243 244 238 classes = PackageLoader.getClassesNew(CHARTS_PACKAGE); 245 239 … … 282 276 283 277 /** 284 * Temporary, if a plugin system is devised then this would porbably become redundant. For now this allows external285 * agents to be included.278 * Temporary, if a plugin system is devised then this would porbably become 279 * redundant. For now this allows external agents to be included. 286 280 * 287 281 * @param fullClassNames 288 * A set of full class names, that is, the class package and name. For 289 * example" "org.myplugin.agents.SerializedSearch" 290 * 291 * @return A collection of classes their were omitted because either there was a name clash with existing agents or 292 * did not exist. i.e. is completely successful this will be empty. Never null. 282 * A set of full class names, that is, the class package and 283 * name. For example" "org.myplugin.agents.SerializedSearch" 284 * 285 * @return A collection of classes their were omitted because either there 286 * was a name clash with existing agents or did not exist. i.e. is 287 * completely successful this will be empty. Never null. 293 288 * 294 289 * @throws NullPointerException … … 335 330 336 331 /** 337 * Loads all the Methods that meet the requirements checked by MethodCheck into the hashtable. 332 * Loads all the Methods that meet the requirements checked by MethodCheck 333 * into the hashtable. 338 334 * 339 335 * @param c … … 365 361 366 362 /** 367 * Checks if the given Method corresponds to the restrictions of Action commands, namely: Declared (not inherited), 368 * Public, and Static, with a void return type. 363 * Checks if the given Method corresponds to the restrictions of Action 364 * commands, namely: Declared (not inherited), Public, and Static, with a 365 * void return type. 369 366 * 370 367 * @param m … … 392 389 393 390 /** 394 * Performs the given action command. The source Frame and Item are given because they are required by some actions. 395 * Note that the source frame does not have to be the Item's parent Frame. 391 * Performs the given action command. The source frame and item are given 392 * because they are required by some actions. Note that the source frame 393 * does not ahve to be the items parent frame. 394 * 395 * If multiple actions exist with the name command.takeWhile(_ != ' ') then 396 * it attempts to find candidate that best matches the arguments passed in. 397 * (arguments are command.dropWhile(_ != ' ') or is floating) 396 398 * 397 399 * @param source 398 * The Frame that the action should apply to400 * The frame that the action should apply to 399 401 * @param launcher 400 * The Item that has the action assigned to it402 * The item that has the action assigned to it 401 403 * @param command 402 404 * The action to perform 403 */ 404 public static Object PerformAction(Frame source, Item launcher, String command) throws Exception { 405 // if (!command.equalsIgnoreCase("Restore")) 406 // FrameIO.SaveFrame(source, false); 407 // TODO make restore UNDO the changes made by the last action 408 409 // separate method name and parameter names 410 String mname = getName(command); 411 command = command.substring(mname.length()).trim(); 412 // If no params are provided get them from a text item on the cursor 413 if (command.length() == 0 && launcher instanceof Text && launcher.isFloating()) { 414 command = launcher.getText(); 415 } 416 417 // Strip off the @ from annotation items 418 if (mname.startsWith("@")) 419 mname = mname.substring(1); 420 421 mname = mname.trim(); 422 String lowercaseName = mname.toLowerCase(); 423 // check for protection on frame 424 if (ItemUtils.ContainsTag(source.getItems(), "@No" + mname)) { 425 throw new RuntimeException("Frame is protected by @No" + mname + " tag."); 426 } 427 428 // retrieve methods that match the name 429 Method toRun = _Actions.get(lowercaseName); 430 431 // if this is not the name of a method, it may be the name of an agent 432 if (toRun == null) { 433 LaunchAgent(mname, command, source, launcher); 405 * @return 406 * @throws Exception 407 */ 408 public static Object PerformAction(final Frame source, final Item launcher, 409 final String command) throws Exception { 410 System.err.println("Running action: " + command + " with floating: " + launcher); 411 final String actionName = getName(command); 412 final String parameters = command.substring(actionName.length()).trim(); 413 414 // Check for protection on frame. 415 if (ItemUtils.ContainsTag(source.getItems(), "@No" + actionName)) { 416 final String errorMsg = "Frame is protected by @No" + actionName 417 + " tag."; 418 MessageBay.errorMessage(errorMsg); 419 throw new RuntimeException(errorMsg); 420 } 421 422 // Find all canditates. Sort by quantity of arguments. 423 final String lowercaseName = actionName.toLowerCase(); 424 final Method firstCanditate = _Actions.get(lowercaseName); 425 // if this is not the name of a method, it may be the name of an agent 426 if (firstCanditate == null) { 427 LaunchAgent(actionName, command, source, launcher); 434 428 return null; 435 429 } 436 437 // Need to save the frame if we are navigating away from it so we dont 438 // loose changes 439 if (toRun.getDeclaringClass().getName().equals(NAVIGATIONS_CLASS)) { 430 // need to save the frame if we are navigating away from it so we dont 431 // loose changes 432 if (firstCanditate.getDeclaringClass().getName().equals(NAVIGATIONS_CLASS)) { 440 433 FrameIO.SaveFrame(DisplayIO.getCurrentFrame()); 441 434 } 442 443 // if there are duplicate methods with the same name 444 List<Method> possibles = new LinkedList<Method>(); 445 possibles.add(toRun); 435 final List<Method> canditates = new LinkedList<Method>(); 436 canditates.add(firstCanditate); 446 437 int i = 0; 447 while (_Actions.containsKey(lowercaseName + i)) { 448 possibles.add(_Actions.get(lowercaseName + i)); 449 i++; 450 } 451 452 for (Method possible : possibles) { 453 // try first with the launching item as a parameter 454 455 // run method 438 while (_Actions.containsKey(lowercaseName + i)) 439 canditates.add(_Actions.get(lowercaseName + i++)); 440 canditates.sort(new Comparator<Method>() { 441 @Override 442 public int compare(final Method m1, final Method m2) { 443 return m2.getParameterCount() - m1.getParameterCount(); 444 } 445 }); 446 447 // Find best candidate. Start searching with the candidate with most 448 // arguments. 449 for (final Method canditate : canditates) { 450 final Object[] paramObjects = CreateObjects(canditate, source, 451 launcher, parameters); 456 452 try { 457 // convert parameters to objects and get the method to invoke 458 Object[] parameters = CreateObjects(possible, source, launcher, command); 459 // Check that there are the same amount of params 460 if (parameters == null) { 461 continue; 462 } 463 464 return possible.invoke(null, parameters); 465 } catch (Exception e) { 453 if (paramObjects != null) 454 return canditate.invoke(null, paramObjects); 455 } catch (final Exception e) { 466 456 Logger.Log(e); 467 457 e.printStackTrace(); 468 458 } 469 459 } 470 // If the actions was not found... then it is run as an agent 471 assert (possibles.size() > 0); 472 throw new RuntimeException("Incorrect parameters for " + mname); 473 } 460 assert (canditates.size() > 0); 461 final String nl = System.getProperty("line.separator"); 462 final StringBuilder errorBuilder = new StringBuilder( 463 "Incorrect parameters for " + actionName + nl + "Canditates: "); 464 for (final Method canditate : canditates) 465 errorBuilder.append(canditate + nl); 466 throw new RuntimeException(errorBuilder.toString()); 467 } 468 469 // /** 470 // * Performs the given action command. The source Frame and Item are given 471 // because they are required by some actions. 472 // * Note that the source frame does not have to be the Item's parent Frame. 473 // * 474 // * @param source 475 // * The Frame that the action should apply to 476 // * @param launcher 477 // * The Item that has the action assigned to it 478 // * @param command 479 // * The action to perform 480 // */ 481 // public static Object PerformAction(Frame source, Item launcher, String 482 // command) throws Exception { 483 // // if (!command.equalsIgnoreCase("Restore")) 484 // // FrameIO.SaveFrame(source, false); 485 // // TODO make restore UNDO the changes made by the last action 486 // 487 // // separate method name and parameter names 488 // String mname = getName(command); 489 // command = command.substring(mname.length()).trim(); 490 // // If no params are provided get them from a text item on the cursor 491 // if (command.length() == 0 && launcher instanceof Text && 492 // launcher.isFloating()) { 493 // command = launcher.getText(); 494 // } 495 // 496 // // Strip off the @ from annotation items 497 // if (mname.startsWith("@")) 498 // mname = mname.substring(1); 499 // 500 // mname = mname.trim(); 501 // String lowercaseName = mname.toLowerCase(); 502 // // check for protection on frame 503 // if (ItemUtils.ContainsTag(source.getItems(), "@No" + mname)) { 504 // throw new RuntimeException("Frame is protected by @No" + mname + 505 // " tag."); 506 // } 507 // 508 // // retrieve methods that match the name 509 // Method toRun = _Actions.get(lowercaseName); 510 // 511 // // if this is not the name of a method, it may be the name of an agent 512 // if (toRun == null) { 513 // LaunchAgent(mname, command, source, launcher); 514 // return null; 515 // } 516 // 517 // // Need to save the frame if we are navigating away from it so we dont 518 // // loose changes 519 // if (toRun.getDeclaringClass().getName().equals(NAVIGATIONS_CLASS)) { 520 // FrameIO.SaveFrame(DisplayIO.getCurrentFrame()); 521 // } 522 // 523 // // if there are duplicate methods with the same name 524 // List<Method> possibles = new LinkedList<Method>(); 525 // possibles.add(toRun); 526 // int i = 0; 527 // while (_Actions.containsKey(lowercaseName + i)) { 528 // possibles.add(_Actions.get(lowercaseName + i)); 529 // i++; 530 // } 531 // 532 // for (Method possible : possibles) { 533 // // try first with the launching item as a parameter 534 // 535 // // run method 536 // try { 537 // // convert parameters to objects and get the method to invoke 538 // Object[] parameters = CreateObjects(possible, source, launcher, command); 539 // // Check that there are the same amount of params 540 // if (parameters == null) { 541 // continue; 542 // } 543 // 544 // return possible.invoke(null, parameters); 545 // } catch (Exception e) { 546 // Logger.Log(e); 547 // e.printStackTrace(); 548 // } 549 // } 550 // // If the actions was not found... then it is run as an agent 551 // assert (possibles.size() > 0); 552 // throw new RuntimeException("Incorrect parameters for " + mname); 553 // } 474 554 475 555 /** … … 483 563 * The starting Frame that the JAG is being launched on 484 564 */ 485 private static void LaunchAgent(String name, String parameters, Frame source, Item clicked) throws Exception { 565 private static void LaunchAgent(String name, String parameters, 566 Frame source, Item clicked) throws Exception { 486 567 // Use the correct case version for printing error messages 487 568 String nameWithCorrectCase = name; … … 495 576 fullClassName = _JAGs.get(name); 496 577 } else if (name.endsWith("tree")) { 497 parameters = name.substring(0, name.length() - "tree".length()) + " " + parameters; 578 parameters = name.substring(0, name.length() - "tree".length()) 579 + " " + parameters; 498 580 fullClassName = AGENTS_PACKAGE + "writetree"; 499 581 500 582 } else if (name.endsWith("frame")) { 501 parameters = name.substring(0, name.length() - "frame".length()) + " " + parameters; 583 parameters = name 584 .substring(0, name.length() - "frame".length()) 585 + " " 586 + parameters; 502 587 fullClassName = AGENTS_PACKAGE + "writeframe"; 503 588 } … … 520 605 String[] paramStrings = parameters.split("\\s+"); 521 606 /** 522 * Any extra parameters will be treated as the rest of the string if the last param is a string 607 * Any extra parameters will be treated as the rest of the 608 * string if the last param is a string 523 609 */ 524 610 if (paramCount > paramStrings.length) { … … 527 613 528 614 /** 529 * If there are extra parameters the last param must be a String 615 * If there are extra parameters the last param must be a 616 * String 530 617 */ 531 618 int lastParam = paramTypes.length - 1; 532 619 533 if (paramCount < paramStrings.length && !paramTypes[lastParam].equals(String.class)) { 620 if (paramCount < paramStrings.length 621 && !paramTypes[lastParam].equals(String.class)) { 534 622 continue; 535 623 } … … 539 627 SString nextParam = new SString(paramStrings[i]); 540 628 params[i] = null; 541 if (paramTypes[i].equals(int.class) || paramTypes[i].equals(Integer.class)) { 629 if (paramTypes[i].equals(int.class) 630 || paramTypes[i].equals(Integer.class)) { 542 631 params[i] = nextParam.integerValue().intValue(); 543 } else if (paramTypes[i].equals(long.class) || paramTypes[i].equals(Long.class)) { 632 } else if (paramTypes[i].equals(long.class) 633 || paramTypes[i].equals(Long.class)) { 544 634 params[i] = nextParam.integerValue(); 545 } else if (paramTypes[i].equals(double.class) || paramTypes[i].equals(Double.class)) { 635 } else if (paramTypes[i].equals(double.class) 636 || paramTypes[i].equals(Double.class)) { 546 637 params[i] = nextParam.doubleValue(); 547 } else if (paramTypes[i].equals(float.class) || paramTypes[i].equals(Float.class)) { 548 params[i] = nextParam.doubleValue().floatValue(); 549 } else if (paramTypes[i].equals(boolean.class) || paramTypes[i].equals(Boolean.class)) { 638 } else if (paramTypes[i].equals(float.class) 639 || paramTypes[i].equals(Float.class)) { 640 params[i] = nextParam.doubleValue() 641 .floatValue(); 642 } else if (paramTypes[i].equals(boolean.class) 643 || paramTypes[i].equals(Boolean.class)) { 550 644 params[i] = nextParam.booleanValue(); 551 645 } else if (paramTypes[i].equals(String.class)) { 552 646 params[i] = nextParam.stringValue(); 553 647 } else { 554 throw new UnexpectedException("Unexpected type " + paramTypes[i].getClass().toString()); 648 throw new UnexpectedException( 649 "Unexpected type " 650 + paramTypes[i].getClass() 651 .toString()); 555 652 } 556 653 } … … 562 659 563 660 /** 564 * Append extra params on the end of the last string param 661 * Append extra params on the end of the last string 662 * param 565 663 */ 566 664 String s = params[lastParam].toString(); … … 581 679 // if there is no constructor, return 582 680 if (con == null) { 583 throw new RuntimeException(INVALID_PARAMETERS_ERROR + nameWithCorrectCase); 681 throw new RuntimeException(INVALID_PARAMETERS_ERROR 682 + nameWithCorrectCase); 584 683 } 585 684 … … 591 690 } catch (ClassNotFoundException cnf) { 592 691 _Agent = null; 593 throw new RuntimeException("'" + nameWithCorrectCase + "' is not an action or agent."); 594 } 595 } 596 597 public static void LaunchAgent(String name, String parameters, Frame source) throws Exception { 692 throw new RuntimeException("'" + nameWithCorrectCase 693 + "' is not an action or agent."); 694 } 695 } 696 697 public static void LaunchAgent(String name, String parameters, Frame source) 698 throws Exception { 598 699 LaunchAgent(name, parameters, source, null); 599 700 } … … 630 731 631 732 Thread.UncaughtExceptionHandler h = new Thread.UncaughtExceptionHandler() { 632 public void uncaughtException(Thread th, Throwable ex) { 633 634 MessageBay.errorMessage("Error occurred in Action: " + th.getName()); 635 ex.printStackTrace(); 636 637 stopAgent(); 638 _Agent = null; 639 } 733 public void uncaughtException(Thread th, Throwable ex) { 734 735 MessageBay.errorMessage("Error occurred in Action: " 736 + th.getName()); 737 ex.printStackTrace(); 738 739 stopAgent(); 740 _Agent = null; 741 } 640 742 }; 641 642 Thread t = new Thread(_Agent, nameWithCorrectCase);643 743 744 Thread t = new Thread(_Agent, nameWithCorrectCase); 745 644 746 t.setPriority(Thread.MIN_PRIORITY); 645 747 t.setUncaughtExceptionHandler(h); 646 748 647 749 if (FreeItems.textOnlyAttachedToCursor()) { 648 750 itemParam = FreeItems.getItemAttachedToCursor(); … … 652 754 if (!_Agent.initialise(source, itemParam)) { 653 755 _Agent = null; 654 throw new RuntimeException("Error initialising agent: " + nameWithCorrectCase); 756 throw new RuntimeException("Error initialising agent: " 757 + nameWithCorrectCase); 655 758 } 656 759 … … 658 761 // TODO make this nicer... ie. make Format an action rather than an 659 762 // agent and save frames only before running agents 660 if (!nameWithCorrectCase.equalsIgnoreCase("format") && !nameWithCorrectCase.equalsIgnoreCase("sort")) { 763 if (!nameWithCorrectCase.equalsIgnoreCase("format") 764 && !nameWithCorrectCase.equalsIgnoreCase("sort")) { 661 765 FrameUtils.LeavingFrame(source); 662 766 } … … 667 771 t.run(); 668 772 if (_Agent != null) { 669 String result = _Agent.toString(); 670 // Attach the result to the cursor 671 if (FreeItems.textOnlyAttachedToCursor()) { 672 Item resultItem = FreeItems.getItemAttachedToCursor(); 673 resultItem.setText(result); 674 } 675 // if there is a completion frame, then display it to the user 773 String result = _Agent.toString(); 774 // Attach the result to the cursor 775 if (FreeItems.textOnlyAttachedToCursor()) { 776 Item resultItem = FreeItems.getItemAttachedToCursor(); 777 resultItem.setText(result); 778 } 779 // if there is a completion frame, then display it to the 780 // user 676 781 } 677 782 } else { … … 687 792 _Agent = null; 688 793 e.printStackTrace(); 689 throw new RuntimeException("Error creating Agent: '" + nameWithCorrectCase + "'"); 794 throw new RuntimeException("Error creating Agent: '" 795 + nameWithCorrectCase + "'"); 690 796 } 691 797 FrameGraphics.refresh(false); … … 705 811 706 812 /** 707 * Stops the currently running Agent (If there is one) by calling Agent.stop(). Note: This may not stop the Agent 708 * immediately, but the Agent should terminate as soon as it is safe to do so. 813 * Stops the currently running Agent (If there is one) by calling 814 * Agent.stop(). Note: This may not stop the Agent immediately, but the 815 * Agent should terminate as soon as it is safe to do so. 709 816 */ 710 817 public static void stopAgent() { … … 725 832 * 726 833 * @param launcher 727 * The Item used to launch the action, it may be required as a parameter 834 * The Item used to launch the action, it may be required as a 835 * parameter 728 836 * @param values 729 837 * A list of space separated String values to convert to objects 730 838 * @return The created array of Objects 731 839 */ 732 public static Object[] CreateObjects(Method method, Frame source, Item launcher, String values) { 840 public static Object[] CreateObjects(Method method, Frame source, 841 Item launcher, String values) { 733 842 // The parameter types that should be created from the given String 734 843 Class<?>[] paramTypes = method.getParameterTypes(); … … 743 852 744 853 /* 745 * if the first class in the list is a frame or item, it is the source or launcher length must be at least one746 * if we are still running854 * if the first class in the list is a frame or item, it is the source 855 * or launcher length must be at least one if we are still running 747 856 */ 748 857 if (paramTypes[ind] == Frame.class) { … … 792 901 793 902 /** 794 * Returns a string containing the remaining params after ignoring the first one. 903 * Returns a string containing the remaining params after ignoring the first 904 * one. 795 905 * 796 906 * @param params … … 824 934 825 935 /** 826 * Returns the first value in the space separated String of parameters passed in. Strings are enclosed in double827 * quotes.936 * Returns the first value in the space separated String of parameters 937 * passed in. Strings are enclosed in double quotes. 828 938 * 829 939 * @param params … … 854 964 855 965 /** 856 * Separates the name of the given command from any parameters and returns them 966 * Separates the name of the given command from any parameters and returns 967 * them Also deals with leading '@'s and leading and tailing whitespace. 857 968 * 858 969 * @param command … … 861 972 */ 862 973 private static String getName(String command) { 974 command = command.trim(); 975 if (command.startsWith("@")) 976 command = command.substring(1); 863 977 if (command.indexOf(" ") < 0) 864 978 return command; … … 868 982 869 983 /** 870 * Gets an uncapitalized font name and returns the capitalized font name. The capitalized form can be used with the 871 * Font.decoded method to get a corresponding Font object. 984 * Gets an uncapitalized font name and returns the capitalized font name. 985 * The capitalized form can be used with the Font.decoded method to get a 986 * corresponding Font object. 872 987 * 873 988 * @param fontName … … 886 1001 private static void initFonts() { 887 1002 if (_Fonts.size() == 0) { 888 String[] availableFonts = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames(); 1003 String[] availableFonts = GraphicsEnvironment 1004 .getLocalGraphicsEnvironment() 1005 .getAvailableFontFamilyNames(); 889 1006 for (String s : availableFonts) { 890 1007 _Fonts.put(s.toLowerCase(), s); … … 898 1015 } 899 1016 900 public static Object PerformActionCatchErrors(Frame current, Item launcher, String command) { 1017 public static Object PerformActionCatchErrors(Frame current, Item launcher, 1018 String command) { 901 1019 try { 902 1020 return PerformAction(current, launcher, command); … … 906 1024 } catch (Exception e) { 907 1025 e.printStackTrace(); 908 MessageBay.errorMessage("Action failed: " + e.getClass().getSimpleName()); 1026 MessageBay.errorMessage("Action failed: " 1027 + e.getClass().getSimpleName()); 909 1028 } 910 1029 return null;
Note:
See TracChangeset
for help on using the changeset viewer.