Changeset 769
- Timestamp:
- 01/28/14 17:52:45 (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/expeditee/gui/FrameUtils.java
r755 r769 9 9 import java.io.FileInputStream; 10 10 import java.io.FileOutputStream; 11 import java.io.IOException; 11 12 import java.io.InputStream; 12 13 import java.net.JarURLConnection; 13 14 import java.net.URL; 15 import java.net.URLConnection; 14 16 import java.util.ArrayList; 15 17 import java.util.Arrays; … … 51 53 public class FrameUtils { 52 54 53 private static final int COLUMN_WIDTH = 50; 54 55 /** 56 * Provides a way to monitor the time elapsed between button-down and the 57 * finished painting. 55 private static final int COLUMN_WIDTH = 50; 56 57 /** 58 * Provides a way to monitor the time elapsed between button-down and the 59 * finished painting. 60 */ 61 public static TimeKeeper ResponseTimer = new TimeKeeper(); 62 63 private static float _ResponseTimeSum = 0; 64 65 private static float _LastResponse = 0; 66 67 private static Text LastEdited = null; 68 69 public static int MINIMUM_INTERITEM_SPACING = -6; 70 71 public static float getResponseTimeTotal() { 72 return _ResponseTimeSum; 73 } 74 75 public static float getLastResponseTime() { 76 return _LastResponse; 77 } 78 79 /** 80 * The list of known start pages framesets which will have prepopulated 81 * links in the home frame. 82 */ 83 public static final String[] startPages = { "exploratorysearch", 84 "webbrowser" }; 85 86 /** 87 * Checks if the given top Item is above the given bottom Item, allowing for 88 * the X coordinates to be off by a certain width... 89 * 90 * @param item1 91 * The Item to check is above the other Item 92 * @param item2 93 * The Item to check is below the top Item 94 * @return True if top is above bottom, False otherwise. 95 */ 96 public static boolean inSameColumn(Item item1, Item item2) { 97 if (!(item1 instanceof Text) || !(item2 instanceof Text)) 98 return false; 99 100 if (item1.getID() < 0 || item2.getID() < 0) 101 return false; 102 103 int minX = item2.getX(); 104 int maxX = item2.getX() + item2.getBoundsWidth(); 105 106 int startX = item1.getX(); 107 int endX = item1.getX() + item1.getBoundsWidth(); 108 109 // Check that the two items left values are close 110 if (Math.abs(item1.getX() - item2.getX()) > COLUMN_WIDTH) 111 return false; 112 113 // Ensure the two items 114 if ((minX >= startX && minX <= endX) 115 || (maxX >= startX && maxX <= endX) 116 || (startX >= minX && startX <= maxX) 117 || (endX >= minX && endX <= maxX)) 118 return true; 119 120 return false; 121 } 122 123 public static boolean sameBulletType(String bullet1, String bullet2) { 124 if (bullet1 == null || bullet2 == null) 125 return false; 126 127 if (bullet1.equals("") || bullet2.equals("")) 128 return false; 129 130 if (Character.isLetter(bullet1.charAt(0)) 131 && Character.isLetter(bullet2.charAt(0))) 132 return true; 133 134 if (Character.isDigit(bullet1.charAt(0)) 135 && Character.isDigit(bullet2.charAt(0))) 136 return true; 137 138 // TODO make this more sofisticated 139 140 return false; 141 } 142 143 private static boolean needsRenumbering(String s) { 144 if (s == null || s.equals("")) 145 return false; 146 if (!Character.isLetterOrDigit(s.charAt(0))) 147 return false; 148 149 s = s.trim(); 150 // if its all letters then we dont want to auto adjust 151 if (s.length() > 2) { 152 for (int i = 0; i < s.length() - 1; i++) { 153 if (!Character.isLetter(s.charAt(i))) 154 return true; 155 } 156 } else 157 return true; 158 159 return false; 160 } 161 162 /** 163 * 164 * @param toAlign 165 * @param moveAll 166 * @param adjust 167 * @return 168 */ 169 public static int Align(List<Text> toAlign, boolean moveAll, int adjust, 170 List<Item> changedItems) { 171 Collections.sort(toAlign); 172 173 /* 174 * Single items dont need alignment But if there are two items we may 175 * still want to format them... ie if they are too close together. 58 176 */ 59 public static TimeKeeper ResponseTimer = new TimeKeeper(); 60 61 private static float _ResponseTimeSum = 0; 62 63 private static float _LastResponse = 0; 64 65 private static Text LastEdited = null; 66 67 public static int MINIMUM_INTERITEM_SPACING = -6; 68 69 public static float getResponseTimeTotal() { 70 return _ResponseTimeSum; 71 } 72 73 public static float getLastResponseTime() { 74 return _LastResponse; 75 } 76 77 /** 78 * The list of known start pages framesets which will have prepopulated links in the home frame. 177 if (toAlign.size() < 1) 178 return 0; 179 180 // get the first item 181 Text from = toAlign.get(0); 182 if (from.getParent() == null) 183 from = toAlign.get(1); 184 int x = from.getX(); 185 186 Frame curr = from.getParent(); 187 Text above = curr.getTextAbove(from); 188 189 String lastBullet = ""; 190 191 if (above != null && curr.isNormalTextItem(above)) 192 lastBullet = FrameKeyboardActions.getAutoBullet(above.getText()); 193 else { 194 lastBullet = FrameKeyboardActions.getBullet(toAlign.get(0) 195 .getText()); 196 } 197 if (needsRenumbering(lastBullet)) { 198 // renumber... 199 for (int i = 0; i < toAlign.size(); i++) { 200 201 Text currentText = toAlign.get(i); 202 String currentBullet = FrameKeyboardActions 203 .getAutoBullet(currentText.getText()); 204 205 if (sameBulletType(lastBullet, currentBullet)) { 206 String oldText = currentText.getText(); 207 208 currentText.stripFirstWord(); 209 210 currentText.setText(lastBullet + currentText.getText()); 211 lastBullet = FrameKeyboardActions.getAutoBullet(currentText 212 .getText()); 213 214 // if we changed the item, add to changedItems list 215 if (changedItems != null 216 && oldText != currentText.getText() 217 && !changedItems.contains(currentText)) { 218 Item copy = currentText.copy(); 219 copy.setID(currentText.getID()); 220 copy.setText(oldText); 221 changedItems.add(copy); 222 } 223 } 224 } 225 } 226 227 // work out the spacing between the first item and the one above it 228 229 int space = 10 + adjust; 230 231 // if we are dropping from the title make the space a little bigger 232 // than normal 233 234 // If there are only two items get the gap from the start item on the 235 // zero frame if there is one 236 if (above == curr.getTitleItem()) { 237 Frame zero = FrameIO.LoadFrame(curr.getFramesetName() + '0'); 238 String strGap = zero.getAnnotationValue("start"); 239 if (strGap != null) { 240 try { 241 int gap = Integer.parseInt(strGap); 242 space = gap; 243 } catch (NumberFormatException nfe) { 244 245 } 246 } 247 } else if (above != null) { 248 // Make the gap between all items the same as the gap between 249 // the first two 250 space = (int) (from.getPolygon().getBounds().getMinY() - above 251 .getPolygon().getBounds().getMaxY()); 252 253 if (space < MINIMUM_INTERITEM_SPACING) 254 space = MINIMUM_INTERITEM_SPACING; 255 256 if (UserSettings.FormatSpacingMax.get() != null) { 257 double maxSpace = UserSettings.FormatSpacingMax.get() 258 * above.getSize(); 259 if (maxSpace < space) { 260 space = (int) Math.round(maxSpace); 261 } 262 } 263 264 if (UserSettings.FormatSpacingMin.get() != null) { 265 double minSpace = UserSettings.FormatSpacingMin.get() 266 * above.getSize(); 267 if (minSpace > space) { 268 space = (int) Math.round(minSpace); 269 } 270 } 271 272 // Need to do things differently for FORMAT than for DROPPING 273 if (moveAll && above != curr.getNameItem() 274 && above != curr.getTitleItem()) { 275 x = above.getX(); 276 int y = (int) above.getPolygon().getBounds().getMaxY() 277 + space 278 + ((int) (from.getY() - from.getPolygon().getBounds() 279 .getMinY())); 280 281 if (changedItems != null 282 && (from.getX() != x || from.getY() != y) 283 && !changedItems.contains(from)) { 284 Item copy = from.copy(); 285 copy.setID(from.getID()); 286 changedItems.add(copy); 287 } 288 from.setPosition(x, y); 289 } else { 290 x = from.getX(); 291 } 292 293 space += adjust; 294 } 295 for (int i = 1; i < toAlign.size(); i++) { 296 Item current = toAlign.get(i); 297 Item top = toAlign.get(i - 1); 298 299 // The bottom of the previous item 300 int bottom = (int) top.getPolygon().getBounds().getMaxY(); 301 302 // the difference between the current item's Y coordinate and 303 // the top of the highlight box 304 int diff = (int) (current.getY() - current.getPolygon().getBounds() 305 .getMinY()); 306 307 int newPos = bottom + space + diff; 308 309 if (changedItems != null 310 && ((moveAll && current.getX() != x) || current.getY() != newPos) 311 && !changedItems.contains(current)) { 312 Item copy = current.copy(); 313 copy.setID(current.getID()); 314 changedItems.add(copy); 315 } 316 317 if (moveAll) { 318 current.setPosition(x, newPos); 319 } else if (newPos > current.getY()) { 320 current.setY(newPos); 321 } 322 323 } 324 325 // if (insert != null) 326 // return insert.getY(); 327 328 // Michael thinks we return the y value for the next new item?? 329 int y = from.getY() + from.getBoundsHeight() + space; 330 return y; 331 } 332 333 public static int Align(List<Text> toAlign, boolean moveAll, int adjust) { 334 return Align(toAlign, moveAll, adjust, null); 335 } 336 337 public static boolean LeavingFrame(Frame current) { 338 checkTDFCItemWaiting(current); 339 // active overlay frames may also require saving if they have been 340 // changed 341 for (Overlay o : current.getOverlays()) 342 if (!SaveCheck(o.Frame)) 343 return false; 344 345 // if the check fails there is no point continuing 346 if (!SaveCheck(current)) 347 return false; 348 349 for (Item i : current.getItems()) 350 i.setHighlightMode(Item.HighlightMode.None); 351 return true; 352 } 353 354 private static boolean SaveCheck(Frame toSave) { 355 // don't bother saving frames that haven't changed 356 if (!toSave.hasChanged()) 357 return true; 358 359 // if the frame has been changed, then save it 360 if (DisplayIO.isTwinFramesOn()) { 361 Frame opposite = DisplayIO.getOppositeFrame(); 362 363 String side = "left"; 364 if (DisplayIO.getCurrentSide() == 0) 365 side = "right"; 366 367 // if the two frames both have changes, prompt the user for the 368 // next move 369 if (opposite.hasChanged() && opposite.equals(toSave)) { 370 if (DisplayIO.DisplayConfirmDialog( 371 "Leaving this frame will discard changes made in the " 372 + side + " Frame. Continue?", "Changes", 373 DisplayIO.TYPE_WARNING, DisplayIO.OPTIONS_OK_CANCEL, 374 DisplayIO.RESULT_OK)) { 375 FrameIO.SaveFrame(toSave); 376 DisplayIO.Reload(DisplayIO.FrameOnSide(opposite)); 377 return true; 378 } else 379 return false; 380 } else if (opposite.hasOverlay(toSave)) { 381 if (toSave.hasChanged()) 382 if (DisplayIO.DisplayConfirmDialog( 383 "Leaving this frame will discard changes made in the " 384 + side + " Frame. Continue?", "Changes", 385 DisplayIO.TYPE_WARNING, 386 DisplayIO.OPTIONS_OK_CANCEL, DisplayIO.RESULT_OK)) { 387 FrameIO.SaveFrame(toSave); 388 DisplayIO.Reload(DisplayIO.FrameOnSide(opposite)); 389 return true; 390 } else 391 return false; 392 } 393 394 // save the current frame and restore the other side 395 FrameIO.SaveFrame(toSave); 396 return true; 397 } 398 399 // single-frame mode can just save and return 400 FrameIO.SaveFrame(toSave); 401 return true; 402 } 403 404 /** 405 * Displays the given Frame on the display. If the current frame has changed 406 * since the last save then it will be saved before the switch is made. The 407 * caller can also dictate whether the current frame is added to the 408 * back-stack or not. 409 * 410 * @param toDisplay 411 * The Frame to display on the screen 412 * @param addToBack 413 * True if the current Frame should be added to the back-stack, 414 * False otherwise 415 */ 416 public static void DisplayFrame(Frame toDisplay, boolean addToBack, 417 boolean incrementStats) { 418 if (toDisplay == null) 419 return; 420 421 Frame current = DisplayIO.getCurrentFrame(); 422 423 // Dont need to do anything if the frame to display is already being 424 // displayed 425 if (current.equals(toDisplay)) 426 return; 427 428 // move any anchored connected items 429 if (FreeItems.itemsAttachedToCursor()) { 430 List<Item> toAdd = new ArrayList<Item>(); 431 List<Item> toCheck = new ArrayList<Item>(FreeItems.getInstance()); 432 433 while (toCheck.size() > 0) { 434 Item i = toCheck.get(0); 435 Collection<Item> connected = i.getAllConnected(); 436 437 // // Only move completely enclosed items 438 // if (!toCheck.containsAll(connected)) { 439 // connected.retainAll(FreeItems.getInstance()); 440 // FreeItems.getInstance().removeAll(connected); 441 // toCheck.removeAll(connected); 442 // FrameMouseActions.anchor(connected); 443 // } else { 444 // toCheck.removeAll(connected); 445 // } 446 447 // Anchor overlay items where they belong 448 if (i.getParent() != null && i.getParent() != current) { 449 FreeItems.getInstance().removeAll(connected); 450 toCheck.removeAll(connected); 451 FrameMouseActions.anchor(connected); 452 } else { 453 // Add stuff that is partially enclosed 454 // remove all the connected items from our list to check 455 toCheck.removeAll(connected); 456 // Dont add the items that are free 457 connected.removeAll(FreeItems.getInstance()); 458 toAdd.addAll(connected); 459 } 460 } 461 462 current.removeAllItems(toAdd); 463 464 boolean oldChange = toDisplay.hasChanged(); 465 toDisplay.updateIDs(toAdd); 466 toDisplay.addAllItems(toAdd); 467 toDisplay.setChanged(oldChange); 468 } 469 470 if (addToBack && current != toDisplay) { 471 FrameIO.checkTDFC(current); 472 } 473 474 // if the saving happened properly, we can continue 475 if (!LeavingFrame(current)) { 476 MessageBay.displayMessage("Navigation cancelled"); 477 return; 478 } 479 480 if (addToBack && current != toDisplay) { 481 DisplayIO.addToBack(current); 482 } 483 484 Parse(toDisplay); 485 DisplayIO.setCurrentFrame(toDisplay, incrementStats); 486 FrameMouseActions.updateCursor(); 487 // FrameMouseActions.getInstance().refreshHighlights(); 488 // update response timer 489 _LastResponse = ResponseTimer.getElapsedSeconds(); 490 _ResponseTimeSum += _LastResponse; 491 DisplayIO.UpdateTitle(); 492 } 493 494 /** 495 * Loads and displays the Frame with the given framename, and adds the 496 * current frame to the back-stack if required. 497 * 498 * @param framename 499 * The name of the Frame to load and display 500 * @param addToBack 501 * True if the current Frame should be added to the back-stack, 502 * false otherwise 503 */ 504 public static void DisplayFrame(String frameName, boolean addToBack, 505 boolean incrementStats) { 506 Frame newFrame = getFrame(frameName); 507 508 if (newFrame != null) 509 // display the frame 510 DisplayFrame(newFrame, addToBack, incrementStats); 511 } 512 513 /** 514 * Loads and displays the Frame with the given framename and adds the 515 * current frame to the back-stack. This is the same as calling 516 * DisplayFrame(framename, true) 517 * 518 * @param framename 519 * The name of the Frame to load and display 520 */ 521 public static void DisplayFrame(String framename) { 522 DisplayFrame(framename, true, true); 523 } 524 525 public static Frame getFrame(String frameName) { 526 // if the new frame does not exist then tell the user 527 Frame f = FrameIO.LoadFrame(frameName); 528 529 if (f == null) { 530 MessageBay.errorMessage("Frame '" + frameName 531 + "' could not be found."); 532 } 533 534 return f; 535 } 536 537 /** 538 * Creates a new Picture Item from the given Text source Item and adds it to 539 * the given Frame. 540 * 541 * @return True if the image was created successfully, false otherwise 542 */ 543 private static boolean createPicture(Frame frame, Text txt) { 544 // attempt to create the picture 545 Picture pic = ItemUtils.CreatePicture(txt, frame); 546 547 // if the picture could not be created successfully 548 if (pic == null) { 549 String imagePath = txt.getText(); 550 assert (imagePath != null); 551 imagePath = new AttributeValuePair(imagePath).getValue().trim(); 552 if (imagePath.length() == 0) { 553 return false; 554 // MessageBay.errorMessage("Expected image path after @i:"); 555 } else { 556 MessageBay.errorMessage("Image " + imagePath 557 + " could not be loaded"); 558 } 559 return false; 560 } 561 frame.addItem(pic); 562 563 return true; 564 } 565 566 /** 567 * Creates an interactive widget and adds it to a frame. If txt has no 568 * parent the parent will be set to frame. 569 * 570 * @param frame 571 * Frame to add widget to. Must not be null. 572 * 573 * @param txt 574 * Text to create the widget from. Must not be null. 575 * 576 * @return True if created/added. False if coul not create. 577 * 578 * @author Brook Novak 579 */ 580 private static boolean createWidget(Frame frame, Text txt) { 581 582 if (frame == null) 583 throw new NullPointerException("frame"); 584 if (txt == null) 585 throw new NullPointerException("txt"); 586 587 // Safety 588 if (txt.getParent() == null) 589 txt.setParent(frame); 590 591 InteractiveWidget iw = null; 592 593 try { 594 595 iw = InteractiveWidget.createWidget(txt); 596 597 } catch (InteractiveWidgetNotAvailableException e) { 598 e.printStackTrace(); 599 MessageBay.errorMessage("Cannot create iWidget: " + e.getMessage()); 600 } catch (InteractiveWidgetInitialisationFailedException e) { 601 e.printStackTrace(); 602 MessageBay.errorMessage("Cannot create iWidget: " + e.getMessage()); 603 } catch (IllegalArgumentException e) { 604 e.printStackTrace(); 605 MessageBay.errorMessage("Cannot create iWidget: " + e.getMessage()); 606 } 607 608 if (iw == null) 609 return false; 610 611 frame.removeItem(txt); 612 613 frame.addAllItems(iw.getItems()); 614 615 return true; 616 } 617 618 public static Collection<String> ParseProfile(Frame profile) { 619 Collection<String> errors = new LinkedList<String>(); 620 if (profile == null) 621 return errors; 622 623 /* 624 * Make sure the correct cursor shows when turning off the custom cursor 625 * and reparsing the profile frame 79 626 */ 80 public static final String[] startPages = { "exploratorysearch", "webbrowser" }; 81 82 /** 83 * Checks if the given top Item is above the given bottom Item, allowing for 84 * the X coordinates to be off by a certain width... 85 * 86 * @param item1 87 * The Item to check is above the other Item 88 * @param item2 89 * The Item to check is below the top Item 90 * @return True if top is above bottom, False otherwise. 627 FreeItems.getCursor().clear(); 628 DisplayIO.setCursor(Item.HIDDEN_CURSOR); 629 DisplayIO.setCursor(Item.DEFAULT_CURSOR); 630 631 // check for settings tags 632 for (Text item : profile.getBodyTextItems(true)) { 633 try { 634 635 AttributeValuePair avp = new AttributeValuePair(item.getText()); 636 String attributeFullCase = avp.getAttributeOrValue(); 637 638 if (attributeFullCase == null) { 639 continue; 640 } 641 String attribute = attributeFullCase.trim().toLowerCase() 642 .replaceAll("^@", ""); 643 644 if (attribute.equals("settings")) { 645 Settings.parseSettings(item); 646 } 647 648 } catch (Exception e) { 649 if (e.getMessage() != null) { 650 errors.add(e.getMessage()); 651 } else { 652 e.printStackTrace(); 653 errors.add("Error parsing [" + item.getText() + "] on " 654 + profile.getName()); 655 } 656 } 657 } 658 659 return errors; 660 } 661 662 /** 663 * Sets the first frame to be displayed. 664 * 665 * @param profile 666 */ 667 public static void loadFirstFrame(Frame profile) { 668 if (UserSettings.HomeFrame.get() == null) 669 UserSettings.HomeFrame.set(profile.getName()); 670 671 Frame firstFrame = FrameIO.LoadFrame(UserSettings.HomeFrame.get()); 672 if (firstFrame == null) { 673 MessageBay.warningMessage("Home frame not found: " 674 + UserSettings.HomeFrame); 675 UserSettings.HomeFrame.set(profile.getName()); 676 DisplayIO.setCurrentFrame(profile, true); 677 } else { 678 DisplayIO.setCurrentFrame(firstFrame, true); 679 } 680 681 } 682 683 public static Color[] getColorWheel(Frame frame) { 684 if (frame != null) { 685 List<Text> textItems = frame.getBodyTextItems(false); 686 Color[] colorList = new Color[textItems.size() + 1]; 687 for (int i = 0; i < textItems.size(); i++) { 688 colorList[i] = textItems.get(i).getColor(); 689 } 690 // Make the last item transparency or default for forecolor 691 colorList[colorList.length - 1] = null; 692 693 return colorList; 694 } 695 return new Color[] { Color.black, Color.white, null }; 696 } 697 698 public static String getLink(Item item, String alt) { 699 if (item == null || !(item instanceof Text)) 700 return alt; 701 702 AttributeValuePair avp = new AttributeValuePair(item.getText()); 703 assert (avp != null); 704 705 if (avp.hasPair() && avp.getValue().trim().length() != 0) { 706 item.setLink(avp.getValue()); 707 return avp.getValue(); 708 } else if (item.getLink() != null) { 709 return item.getAbsoluteLink(); 710 } 711 712 return alt; 713 } 714 715 public static String getDir(String name) { 716 if (name != null) { 717 File tester = new File(name); 718 if (tester.exists() && tester.isDirectory()) { 719 if (name.endsWith(File.separator)) 720 return name; 721 else 722 return name + File.separator; 723 } else { 724 throw new RuntimeException("Directory not found: " + name); 725 } 726 } 727 throw new RuntimeException("Missing value for profile attribute" + name); 728 } 729 730 public static ArrayList<String> getDirs(Item item) { 731 ArrayList<String> dirsToAdd = new ArrayList<String>(); 732 String dirListFrameName = item.getAbsoluteLink(); 733 if (dirListFrameName != null) { 734 Frame dirListFrame = FrameIO.LoadFrame(dirListFrameName); 735 if (dirListFrame != null) { 736 for (Text t : dirListFrame.getBodyTextItems(false)) { 737 String dirName = t.getText().trim(); 738 File tester = new File(dirName); 739 if (tester.exists() && tester.isDirectory()) { 740 if (dirName.endsWith(File.separator)) 741 dirsToAdd.add(dirName); 742 else 743 dirsToAdd.add(dirName + File.separator); 744 } 745 } 746 } 747 } 748 749 return dirsToAdd; 750 } 751 752 public static void Parse(Frame toParse) { 753 Parse(toParse, false); 754 } 755 756 /** 757 * Checks for any special Annotation items and updates the display as 758 * necessary. Special Items: Images, overlays, sort. 759 * 760 */ 761 public static void Parse(Frame toParse, boolean firstParse) { 762 Parse(toParse, firstParse, false); 763 } 764 765 /** 766 * 767 * @param toParse 768 * @param firstParse 769 * @param ignoreAnnotations 770 * used to prevent infinate loops such as when performing TDFC 771 * with an ao tag linked to a frame with an frameImage of a frame 772 * which also has an ao tag on it. 773 */ 774 public static void Parse(Frame toParse, boolean firstParse, 775 boolean ignoreAnnotations) { 776 // TODO check why we are getting toParse == null... when profile frame 777 // is being created and change the lines below 778 if (toParse == null) 779 return; 780 // System.out.println(firstParse); 781 if (firstParse) 782 ItemUtils.EnclosedCheck(toParse.getItems()); 783 List<Item> items = toParse.getItems(); 784 785 // if XRayMode is on, replace pictures with their underlying text 786 if (FrameGraphics.isXRayMode()) { 787 788 // BROOK: Must handle these a little different 789 List<InteractiveWidget> widgets = toParse.getInteractiveWidgets(); 790 791 for (Item i : items) { 792 if (i instanceof XRayable) { 793 toParse.removeItem(i); 794 // Show the items 795 for (Item item : ((XRayable) i).getConnected()) { 796 item.setVisible(true); 797 item.removeEnclosure(i); 798 } 799 } else if (i instanceof WidgetCorner) { 800 toParse.removeItem(i); 801 } else if (i instanceof WidgetEdge) { 802 toParse.removeItem(i); 803 } else if (i.hasFormula()) { 804 i.setText(i.getFormula()); 805 } else if (i.hasOverlay()) { 806 i.setVisible(true); 807 // int x = i.getBoundsHeight(); 808 } 809 } 810 811 for (InteractiveWidget iw : widgets) { 812 toParse.addItem(iw.getSource()); 813 } 814 } 815 816 // Text title = null; 817 // Text template = UserSettingsTemplate.copy(); 818 819 List<Overlay> overlays = new ArrayList<Overlay>(); 820 List<Vector> vectors = new ArrayList<Vector>(); 821 822 // disable reading of cached overlays if in twinframes mode 823 if (DisplayIO.isTwinFramesOn()) 824 FrameIO.SuspendCache(); 825 826 DotType pointtype = DotType.square; 827 boolean filledPoints = true; 828 829 UserAppliedPermission permission = toParse.getUserAppliedPermission(); 830 toParse.clearAnnotations(); 831 832 // check for any new overlay items 833 for (Item i : toParse.getItems()) { 834 try { 835 // reset overlay permission 836 i.setOverlayPermission(null); 837 // i.setPermission(permission); 838 if (i instanceof WidgetCorner) { 839 // TODO improve efficiency so it only updates once... using 840 // observer design pattern 841 i.update(); 842 } else if (i instanceof Text) { 843 if (i.isAnnotation()) { 844 if (ItemUtils.startsWithTag(i, ItemUtils.TAG_POINTTYPE)) { 845 Text txt = (Text) i; 846 String line = txt.getFirstLine(); 847 line = ItemUtils.StripTag(line, 848 ItemUtils.GetTag(ItemUtils.TAG_POINTTYPE)); 849 850 if (line != null) { 851 line = line.toLowerCase(); 852 if (line.indexOf(" ") > 0) { 853 String fill = line.substring(line 854 .indexOf(" ") + 1); 855 if (fill.startsWith("nofill")) 856 filledPoints = false; 857 else 858 filledPoints = true; 859 } 860 861 if (line.startsWith("circle")) 862 pointtype = DotType.circle; 863 else 864 pointtype = DotType.square; 865 } 866 }// check for new VECTOR items 867 else if (!FrameGraphics.isXRayMode() 868 && ItemUtils.startsWithTag(i, 869 ItemUtils.TAG_VECTOR) 870 && i.getLink() != null) { 871 if (!i.getAbsoluteLink().equals(toParse.getName())) 872 addVector(vectors, UserAppliedPermission.none, 873 permission, i); 874 } else if (!FrameGraphics.isXRayMode() 875 && ItemUtils.startsWithTag(i, 876 ItemUtils.TAG_ACTIVE_VECTOR) 877 && i.getLink() != null) { 878 if (!i.getAbsoluteLink().equals(toParse.getName())) 879 addVector(vectors, 880 UserAppliedPermission.followLinks, 881 permission, i); 882 } 883 // check for new OVERLAY items 884 else if (!ignoreAnnotations 885 && ItemUtils.startsWithTag(i, 886 ItemUtils.TAG_OVERLAY) 887 && i.getLink() != null) { 888 if (i.getAbsoluteLink().equalsIgnoreCase( 889 toParse.getName())) { 890 // This frame contains an active overlay which 891 // points to itself 892 MessageBay 893 .errorMessage(toParse.getName() 894 + " contains an @o which links to itself"); 895 continue; 896 } 897 898 Frame overlayFrame = FrameIO.LoadFrame(i 899 .getAbsoluteLink()); 900 // Parse(overlay); 901 if (overlayFrame != null 902 && Overlay.getOverlay(overlays, 903 overlayFrame) == null) 904 overlays.add(new Overlay(overlayFrame, 905 UserAppliedPermission.none)); 906 } 907 // check for ACTIVE_OVERLAY items 908 else if (!ignoreAnnotations 909 && ItemUtils.startsWithTag(i, 910 ItemUtils.TAG_ACTIVE_OVERLAY) 911 && i.getLink() != null) { 912 String link = i.getAbsoluteLink(); 913 if (link.equalsIgnoreCase(toParse.getName())) { 914 // This frame contains an active overlay which 915 // points to itself 916 MessageBay 917 .errorMessage(toParse.getName() 918 + " contains an @ao which links to itself"); 919 continue; 920 } 921 Frame overlayFrame = null; 922 923 Frame current = DisplayIO.getCurrentFrame(); 924 if (current != null) { 925 for (Overlay o : current.getOverlays()) { 926 if (o.Frame.getName() 927 .equalsIgnoreCase(link)) 928 overlayFrame = o.Frame; 929 } 930 } 931 if (overlayFrame == null) 932 overlayFrame = FrameIO.LoadFrame(link); 933 934 // get level if specified 935 String level = new AttributeValuePair(i.getText()) 936 .getValue(); 937 // default permission (if none is specified) 938 PermissionPair permissionLevel = new PermissionPair( 939 level, UserAppliedPermission.followLinks); 940 941 if (overlayFrame != null) { 942 Overlay existingOverlay = Overlay.getOverlay( 943 overlays, overlayFrame); 944 // If it wasn't in the list create it and add 945 // it. 946 if (existingOverlay == null) { 947 Overlay newOverlay = new Overlay( 948 overlayFrame, 949 permissionLevel 950 .getPermission(overlayFrame 951 .getOwner())); 952 i.setOverlay(newOverlay); 953 overlays.add(newOverlay); 954 } else { 955 existingOverlay.Frame 956 .setPermission(permissionLevel); 957 } 958 } 959 } 960 // check for Images and widgets 961 else { 962 if (!FrameGraphics.isXRayMode()) { 963 if (ItemUtils.startsWithTag(i, 964 ItemUtils.TAG_IMAGE, true)) { 965 if (!i.hasEnclosures()) { 966 createPicture(toParse, (Text) i); 967 } 968 // check for frame images 969 } else if (ItemUtils.startsWithTag(i, 970 ItemUtils.TAG_FRAME_IMAGE) 971 && i.getLink() != null 972 && !i.getAbsoluteLink() 973 .equalsIgnoreCase( 974 toParse.getName())) { 975 XRayable image = null; 976 if (i.hasEnclosures()) { 977 // i.setHidden(true); 978 // image = 979 // i.getEnclosures().iterator().next(); 980 // image.refresh(); 981 } else { 982 image = new FrameImage((Text) i, 983 toParse, null); 984 } 985 // TODO Add the image when creating new 986 // FrameImage 987 toParse.addItem(image); 988 } else if (ItemUtils.startsWithTag(i, 989 ItemUtils.TAG_BITMAP_IMAGE) 990 && i.getLink() != null 991 && !i.getAbsoluteLink() 992 .equalsIgnoreCase( 993 toParse.getName())) { 994 XRayable image = null; 995 if (i.hasEnclosures()) { 996 // image = 997 // i.getEnclosures().iterator().next(); 998 // image.refresh(); 999 // i.setHidden(true); 1000 } else { 1001 // If a new bitmap is created for a 1002 // frame which already has a bitmap dont 1003 // recreate the bitmap 1004 image = new FrameBitmap((Text) i, 1005 toParse, null); 1006 } 1007 toParse.addItem(image); 1008 } else if (ItemUtils.startsWithTag(i, "@c")) { 1009 // Can only have a @c 1010 if (!i.hasEnclosures() 1011 && i.getLines().size() == 1) { 1012 toParse.addItem(new Circle((Text) i)); 1013 } 1014 // Check for interactive widgets 1015 } else if (ItemUtils.startsWithTag(i, 1016 ItemUtils.TAG_IWIDGET)) { 1017 createWidget(toParse, (Text) i); 1018 } 1019 } 1020 // TODO decide exactly what to do here!! 1021 toParse.addAnnotation((Text) i); 1022 } 1023 } else if (!FrameGraphics.isXRayMode() && i.hasFormula()) { 1024 i.calculate(i.getFormula()); 1025 } 1026 } 1027 } catch (Exception e) { 1028 Logger.Log(e); 1029 e.printStackTrace(); 1030 MessageBay.warningMessage("Exception occured when loading " 1031 + i.getClass().getSimpleName() + "(ID: " + i.getID() 1032 + ") " + e.getMessage() != null ? e.getMessage() : ""); 1033 } 1034 } 1035 1036 /* 1037 * for (Item i : items) { if (i instanceof Dot) { ((Dot) 1038 * i).setPointType(pointtype); ((Dot) i).useFilledPoints(filledPoints); 1039 * } } 91 1040 */ 92 public static boolean inSameColumn(Item item1, Item item2) { 93 if (!(item1 instanceof Text) || !(item2 instanceof Text)) 94 return false; 95 96 if (item1.getID() < 0 || item2.getID() < 0) 97 return false; 98 99 int minX = item2.getX(); 100 int maxX = item2.getX() + item2.getBoundsWidth(); 101 102 int startX = item1.getX(); 103 int endX = item1.getX() + item1.getBoundsWidth(); 104 105 // Check that the two items left values are close 106 if (Math.abs(item1.getX() - item2.getX()) > COLUMN_WIDTH) 107 return false; 108 109 // Ensure the two items 110 if ((minX >= startX && minX <= endX) 111 || (maxX >= startX && maxX <= endX) 112 || (startX >= minX && startX <= maxX) 113 || (endX >= minX && endX <= maxX)) 114 return true; 115 116 return false; 117 } 118 119 public static boolean sameBulletType(String bullet1, String bullet2) { 120 if (bullet1 == null || bullet2 == null) 121 return false; 122 123 if (bullet1.equals("") || bullet2.equals("")) 124 return false; 125 126 if (Character.isLetter(bullet1.charAt(0)) 127 && Character.isLetter(bullet2.charAt(0))) 128 return true; 129 130 if (Character.isDigit(bullet1.charAt(0)) 131 && Character.isDigit(bullet2.charAt(0))) 132 return true; 133 134 // TODO make this more sofisticated 135 136 return false; 137 } 138 139 private static boolean needsRenumbering(String s) { 140 if (s == null || s.equals("")) 141 return false; 142 if (!Character.isLetterOrDigit(s.charAt(0))) 143 return false; 144 145 s = s.trim(); 146 // if its all letters then we dont want to auto adjust 147 if (s.length() > 2) { 148 for (int i = 0; i < s.length() - 1; i++) { 149 if (!Character.isLetter(s.charAt(i))) 150 return true; 1041 1042 FrameIO.ResumeCache(); 1043 1044 toParse.clearOverlays(); 1045 toParse.clearVectors(); 1046 toParse.addAllOverlays(overlays); 1047 toParse.addAllVectors(vectors); 1048 1049 } 1050 1051 /** 1052 * @param vectors 1053 * @param permission 1054 * @param i 1055 */ 1056 private static void addVector(List<Vector> vectors, 1057 UserAppliedPermission defaultPermission, 1058 UserAppliedPermission framePermission, Item i) { 1059 // TODO It is possible to get into an infinate loop if a 1060 // frame contains an @ao which leads to a frame with an 1061 // @v which points back to the frame with the @ao 1062 Frame vector = FrameIO.LoadFrame(i.getAbsoluteLink()); 1063 1064 // Get the permission from off the vector frame 1065 UserAppliedPermission vectorPermission = UserAppliedPermission 1066 .getPermission(vector.getAnnotationValue("permission"), 1067 defaultPermission); 1068 // If the frame permission is lower, use that 1069 vectorPermission = UserAppliedPermission.min(vectorPermission, 1070 framePermission); 1071 // Highest permissable permission for vectors is copy 1072 vectorPermission = UserAppliedPermission.min(vectorPermission, 1073 UserAppliedPermission.copy); 1074 if (vector != null) { 1075 String scaleString = new AttributeValuePair(i.getText()).getValue(); 1076 Float scale = 1F; 1077 try { 1078 scale = Float.parseFloat(scaleString); 1079 } catch (Exception e) { 1080 } 1081 Vector newVector = new Vector(vector, vectorPermission, scale, i); 1082 i.setOverlay(newVector); 1083 i.setVisible(false); 1084 vectors.add(newVector); 1085 } 1086 } 1087 1088 public static Item onItem(float floatX, float floatY, 1089 boolean changeLastEdited) { 1090 return onItem(DisplayIO.getCurrentFrame(), floatX, floatY, 1091 changeLastEdited); 1092 } 1093 1094 /** 1095 * Searches through the list of items on this frame to find one at the given 1096 * x,y coordinates. 1097 * 1098 * @param x 1099 * The x coordinate 1100 * @param y 1101 * The y coordinate 1102 * @return The Item at the given coordinates, or NULL if none is found. 1103 */ 1104 public static Item onItem(Frame toCheck, float floatX, float floatY, 1105 boolean bResetLastEdited) { 1106 // System.out.println("MouseX: " + floatX + " MouseY: " + floatY); 1107 int x = Math.round(floatX); 1108 int y = Math.round(floatY); 1109 if (toCheck == null) 1110 return null; 1111 1112 List<Item> possibles = new ArrayList<Item>(0); 1113 1114 // if the mouse is in the message area 1115 if (y > FrameGraphics.getMaxFrameSize().getHeight()) { 1116 // check the individual message items 1117 for (Item message : MessageBay.getMessages()) { 1118 if (message != null) { 1119 if (message.contains(x, y)) { 1120 message.setOverlayPermission(UserAppliedPermission.copy); 1121 possibles.add(message); 1122 } else { 1123 // Not sure why but if the line below is removed then 1124 // several items can be highlighted at once 1125 message.setHighlightMode(Item.HighlightMode.None); 1126 } 1127 } 1128 } 1129 1130 // check the link to the message frame 1131 if (MessageBay.getMessageLink() != null) { 1132 if (MessageBay.getMessageLink().contains(x, y)) { 1133 MessageBay.getMessageLink().setOverlayPermission( 1134 UserAppliedPermission.copy); 1135 possibles.add(MessageBay.getMessageLink()); 1136 } 1137 } 1138 1139 // this is taken into account in contains 1140 // y -= FrameGraphics.getMaxFrameSize().height; 1141 // otherwise, the mouse is on the frame 1142 } else { 1143 if (LastEdited != null) { 1144 if (LastEdited.contains(x, y) 1145 && !FreeItems.getInstance().contains(LastEdited) 1146 && LastEdited.getParent() == DisplayIO 1147 .getCurrentFrame() 1148 && LastEdited.getParent().getItems() 1149 .contains(LastEdited)) { 1150 LastEdited.setOverlayPermission(UserAppliedPermission.full); 1151 return LastEdited; 1152 } else if (bResetLastEdited) { 1153 setLastEdited(null); 1154 } 1155 } 1156 ArrayList<Item> checkList = new ArrayList<Item>(); 1157 checkList.addAll(toCheck.getInteractableItems()); 1158 checkList.add(toCheck.getNameItem()); 1159 for (Item i : checkList) { 1160 // do not check annotation items in audience mode 1161 if (i.isVisible() 1162 && !(FrameGraphics.isAudienceMode() && i.isAnnotation())) { 1163 if (i.contains(x, y) 1164 && !FreeItems.getInstance().contains(i)) { 1165 possibles.add(i); 1166 } 1167 } 1168 } 1169 } 1170 1171 // if there are no possible items, return null 1172 if (possibles.size() == 0) 1173 return null; 1174 1175 // if there is only one possibility, return it 1176 if (possibles.size() == 1) 1177 return possibles.get(0); 1178 1179 // return closest x,y pair to mouse 1180 Item closest = possibles.get(0); 1181 int distance = (int) Math.round(Math.sqrt(Math.pow( 1182 Math.abs(closest.getX() - x), 2) 1183 + Math.pow(Math.abs(closest.getY() - y), 2))); 1184 1185 for (Item i : possibles) { 1186 int d = (int) Math.round(Math.sqrt(Math.pow(Math.abs(i.getX() - x), 1187 2) + Math.pow(Math.abs(i.getY() - y), 2))); 1188 1189 // System.out.println(d); 1190 if (d <= distance) { 1191 distance = d; 1192 1193 // dots take precedence over lines 1194 if ((!(closest instanceof Dot && i instanceof Line)) 1195 && (!(closest instanceof Text && i instanceof Line))) 1196 closest = i; 1197 1198 } 1199 1200 } 1201 1202 return closest; 1203 } 1204 1205 public synchronized static Item getCurrentItem() { 1206 return onItem(DisplayIO.getCurrentFrame(), DisplayIO.getMouseX(), 1207 FrameMouseActions.getY(), true); 1208 } 1209 1210 public static Polygon getEnlosingPolygon() { 1211 Collection<Item> enclosure = getEnclosingLineEnds(); 1212 if (enclosure == null || enclosure.size() == 0) 1213 return null; 1214 1215 return enclosure.iterator().next().getEnclosedShape(); 1216 } 1217 1218 /** 1219 * 1220 * @param currentItem 1221 * @return 1222 */ 1223 public static Collection<Item> getCurrentItems() { 1224 return getCurrentItems(getCurrentItem()); 1225 } 1226 1227 public static Collection<Item> getCurrentItems(Item currentItem) { 1228 1229 Collection<Item> enclosure = getEnclosingLineEnds(); 1230 if (enclosure == null || enclosure.size() == 0) 1231 return null; 1232 1233 Item firstItem = enclosure.iterator().next(); 1234 1235 Collection<Item> enclosed = getItemsEnclosedBy( 1236 DisplayIO.getCurrentFrame(), firstItem.getEnclosedShape()); 1237 1238 // Brook: enclosed widgets are to be fully enclosed, never partially 1239 /* 1240 * MIKE says: but doesnt this mean that widgets are treated differently 1241 * from ALL other object which only need to be partially enclosed to be 1242 * picked up 1243 */ 1244 List<InteractiveWidget> enclosedWidgets = new LinkedList<InteractiveWidget>(); 1245 for (Item i : enclosed) { 1246 // Don't want to lose the highlighting from the current item 1247 if (i == currentItem || enclosure.contains(i)) { 1248 continue; 1249 } 1250 // Don't want to lose the highlighting of connected Dots 1251 if (i instanceof Dot 1252 && i.getHighlightMode() == HighlightMode.Connected) { 1253 for (Line l : i.getLines()) { 1254 if (l.getOppositeEnd(i).getHighlightMode() == HighlightMode.Normal) { 1255 continue; 1256 } 1257 } 1258 } 1259 if (i instanceof WidgetCorner) { 1260 if (!enclosedWidgets.contains(((WidgetCorner) i) 1261 .getWidgetSource())) 1262 enclosedWidgets.add(((WidgetCorner) i).getWidgetSource()); 1263 } 1264 i.setHighlightMode(Item.HighlightMode.None); 1265 } 1266 1267 for (InteractiveWidget iw : enclosedWidgets) { 1268 for (Item i : iw.getItems()) { 1269 if (!enclosed.contains(i)) { 1270 enclosed.add(i); 1271 } 1272 } 1273 } 1274 1275 return enclosed; 1276 } 1277 1278 public static Collection<Item> getEnclosingLineEnds() { 1279 return getEnclosingLineEnds(new Point(DisplayIO.getMouseX(), 1280 FrameMouseActions.getY())); 1281 } 1282 1283 public static Collection<Item> getEnclosingLineEnds(Point position) { 1284 // update enclosed shapes 1285 Frame current = DisplayIO.getCurrentFrame(); 1286 List<Item> items = current.getItems(); 1287 1288 // Remove all items that are connected to freeItems 1289 List<Item> freeItems = new ArrayList<Item>(FreeItems.getInstance()); 1290 while (freeItems.size() > 0) { 1291 Item item = freeItems.get(0); 1292 Collection<Item> connected = item.getAllConnected(); 1293 items.removeAll(connected); 1294 freeItems.removeAll(connected); 1295 } 1296 1297 List<Item> used = new ArrayList<Item>(0); 1298 1299 while (items.size() > 0) { 1300 Item i = items.get(0); 1301 items.remove(i); 1302 if (i.isEnclosed()) { 1303 Polygon p = i.getEnclosedShape(); 1304 if (p.contains(position.x, position.y)) { 1305 used.add(i); 1306 items.removeAll(i.getEnclosingDots()); 1307 } 1308 } 1309 } 1310 1311 if (used.size() == 0) 1312 return null; 1313 1314 // if there is only one possibility, return it 1315 if (used.size() == 1) { 1316 return used.get(0).getEnclosingDots(); 1317 // otherwise, determine which polygon is closest to the cursor 1318 } else { 1319 Collections.sort(used, new Comparator<Item>() { 1320 public int compare(Item d1, Item d2) { 1321 Polygon p1 = d1.getEnclosedShape(); 1322 Polygon p2 = d2.getEnclosedShape(); 1323 1324 int closest = Integer.MAX_VALUE; 1325 int close2 = Integer.MAX_VALUE; 1326 1327 int mouseX = DisplayIO.getMouseX(); 1328 int mouseY = FrameMouseActions.getY(); 1329 1330 for (int i = 0; i < p1.npoints; i++) { 1331 int diff = Math.abs(p1.xpoints[i] - mouseX) 1332 + Math.abs(p1.ypoints[i] - mouseY); 1333 int diff2 = Integer.MAX_VALUE; 1334 1335 if (i < p2.npoints) 1336 diff2 = Math.abs(p2.xpoints[i] - mouseX) 1337 + Math.abs(p2.ypoints[i] - mouseY); 1338 1339 if (diff < Math.abs(closest)) { 1340 close2 = closest; 1341 closest = diff; 1342 } else if (diff < Math.abs(close2)) 1343 close2 = diff; 1344 1345 if (diff2 < Math.abs(closest)) { 1346 close2 = closest; 1347 closest = -diff2; 1348 } else if (diff2 < Math.abs(close2)) 1349 close2 = diff2; 1350 } 1351 1352 if (closest > 0 && close2 > 0) 1353 return -10; 1354 1355 if (closest < 0 && close2 < 0) 1356 return 10; 1357 1358 if (closest > 0) 1359 return -10; 1360 1361 return 10; 1362 } 1363 1364 }); 1365 1366 return used.get(0).getEnclosingDots(); 1367 } 1368 } 1369 1370 // TODO Remove this method!! 1371 // Can just getItemsWithin be used? 1372 public static Collection<Item> getItemsEnclosedBy(Frame frame, Polygon poly) { 1373 Collection<Item> contained = frame.getItemsWithin(poly); 1374 1375 Collection<Item> results = new LinkedHashSet<Item>(contained.size()); 1376 1377 // check for correct permissions 1378 for (Item item : contained) { 1379 // if the item is on the frame 1380 if (item.getParent() == frame || item.getParent() == null) { 1381 // item.Permission = Permission.full; 1382 results.add(item); 1383 // otherwise, it must be on an overlay frame 1384 } else { 1385 for (Overlay overlay : frame.getOverlays()) { 1386 if (overlay.Frame == item.getParent()) { 1387 item.setOverlayPermission(overlay.permission); 1388 results.add(item); 1389 break; 1390 } 1391 } 1392 } 1393 } 1394 1395 return results; 1396 } 1397 1398 /** 1399 * Fills the given Frame with default profile tags 1400 */ 1401 public static void CreateDefaultProfile(String username, Frame profile) { 1402 Text title = profile.getTitleItem(); 1403 if (username.equals(UserSettings.DEFAULT_PROFILE_NAME)) { 1404 title.setText("Default Profile Frame"); 1405 } else { 1406 title.setText(username + "'s Profile Frame"); 1407 } 1408 1409 // int spacing = 50; 1410 final int intialYPos = 75; 1411 int xPos = 75; 1412 int yPos = intialYPos; 1413 1414 // yPos += spacing; 1415 // profile.addText(xPos, yPos, "@HomeFrame", null, profile.getName()); 1416 // yPos += spacing; 1417 // String defaultFrameName = profile.getFramesetName() + "0"; 1418 // profile.addText(xPos, yPos, "@DefaultFrame", null, defaultFrameName); 1419 // yPos += spacing; 1420 // 1421 // profile.addText(xPos, yPos, "@InitialWidth: " 1422 // + UserSettings.InitialWidth, null); 1423 // yPos += spacing; 1424 // 1425 // profile.addText(xPos, yPos, "@InitialHeight: " 1426 // + UserSettings.InitialHeight, null); 1427 // yPos += spacing; 1428 // 1429 // Text t = profile.addText(xPos, yPos, "@ItemTemplate", null); 1430 // t.setColor(null); 1431 // 1432 // yPos += spacing; 1433 // t = profile.addText(xPos, yPos, "@AnnotationTemplate", null); 1434 // t.setColor(Color.gray); 1435 // 1436 // yPos += spacing; 1437 // t = profile.addText(xPos, yPos, "@CommentTemplate", null); 1438 // t.setColor(Color.green.darker()); 1439 // 1440 // yPos += spacing; 1441 // t = profile.addText(xPos, yPos, "@StatsTemplate", null); 1442 // t.setColor(Color.BLACK); 1443 // t.setBackgroundColor(new Color(0.9F, 0.9F, 0.9F)); 1444 // t.setFamily(Text.MONOSPACED_FONT); 1445 // t.setSize(14); 1446 1447 Text t; 1448 1449 xPos = 300; 1450 // yPos = intialYPos + spacing; 1451 yPos = 100; 1452 1453 // Load documentation and start pages 1454 extractResources(); 1455 1456 // Add documentation links 1457 File helpDirectory = new File(FrameIO.HELP_PATH); 1458 if (helpDirectory != null) { 1459 File[] helpFramesets = helpDirectory.listFiles(); 1460 if (helpFramesets != null) { 1461 1462 // Add the title for the help index 1463 Text help = profile 1464 .addText(xPos, yPos, "@Expeditee Help", null); 1465 help.setSize(25); 1466 help.setFontStyle("Bold"); 1467 help.setFamily("SansSerif"); 1468 help.setColor(UserSettings.ColorWheel.get()[3]); 1469 1470 xPos += 25; 1471 System.out.println("Installing frameset: "); 1472 1473 for (File helpFrameset : helpFramesets) { 1474 String framesetName = helpFrameset.getName(); 1475 if (!FrameIO.isValidFramesetName(framesetName)) 1476 continue; 1477 System.out.println(" " + framesetName); 1478 Frame indexFrame = FrameIO.LoadFrame(framesetName + '1'); 1479 // Look through the folder for help index pages 1480 if (indexFrame != null 1481 && ItemUtils.FindTag(indexFrame.getItems(), 1482 "@HelpIndex") != null) { 1483 // yPos += spacing; 1484 yPos += 30; 1485 t = profile.addText(xPos, yPos, 1486 '@' + indexFrame.getFramesetName(), null); 1487 t.setLink(indexFrame.getName()); 1488 t.setColor(Color.gray); 1489 } 1490 } 1491 } 1492 } 1493 1494 xPos = 50; 1495 yPos = 100; 1496 1497 // Populate Start Pages and Settings 1498 File framesetDirectory = new File(FrameIO.FRAME_PATH); 1499 1500 if (framesetDirectory.exists()) { 1501 File[] startpagesFramesets = framesetDirectory.listFiles(); 1502 1503 if (startpagesFramesets != null) { 1504 // Add Start Page title 1505 Text templates = profile.addText(xPos, yPos, "@Start Pages", 1506 null); 1507 templates.setSize(25); 1508 templates.setFontStyle("Bold"); 1509 templates.setFamily("SansSerif"); 1510 templates.setColor(UserSettings.ColorWheel.get()[3]); 1511 1512 xPos += 25; 1513 1514 // Start Pages should be the first frame in its own frameset + 1515 // frameset name should be present in FrameUtils.startPages[]. 1516 for (File startpagesFrameset : startpagesFramesets) { 1517 String framesetName = startpagesFrameset.getName(); 1518 1519 // Only add link if frameset is a startpage 1520 for (int i = 0; i < startPages.length; i++) { 1521 if (framesetName.equals(startPages[i])) { 1522 Frame indexFrame = FrameIO 1523 .LoadFrame(framesetName + '1'); 1524 1525 // Add start page link 1526 if (indexFrame != null) { 1527 yPos += 30; 1528 t = profile.addText(xPos, yPos, 1529 '@' + indexFrame.getFramesetName(), 1530 null); 1531 t.setLink(indexFrame.getName()); 1532 t.setColor(Color.gray); 1533 } 151 1534 } 152 } else 153 return true; 154 155 return false; 156 } 157 158 /** 159 * 160 * @param toAlign 161 * @param moveAll 162 * @param adjust 163 * @return 164 */ 165 public static int Align(List<Text> toAlign, boolean moveAll, int adjust, List<Item> changedItems) { 166 Collections.sort(toAlign); 167 168 /* 169 * Single items dont need alignment But if there are two items we may 170 * still want to format them... ie if they are too close together. 171 */ 172 if (toAlign.size() < 1) 173 return 0; 174 175 // get the first item 176 Text from = toAlign.get(0); 177 if (from.getParent() == null) 178 from = toAlign.get(1); 179 int x = from.getX(); 180 181 Frame curr = from.getParent(); 182 Text above = curr.getTextAbove(from); 183 184 String lastBullet = ""; 185 186 if (above != null && curr.isNormalTextItem(above)) 187 lastBullet = FrameKeyboardActions.getAutoBullet(above.getText()); 188 else { 189 lastBullet = FrameKeyboardActions.getBullet(toAlign.get(0) 190 .getText()); 191 } 192 if (needsRenumbering(lastBullet)) { 193 // renumber... 194 for (int i = 0; i < toAlign.size(); i++) { 195 196 Text currentText = toAlign.get(i); 197 String currentBullet = FrameKeyboardActions 198 .getAutoBullet(currentText.getText()); 199 200 if (sameBulletType(lastBullet, currentBullet)) { 201 String oldText = currentText.getText(); 202 203 currentText.stripFirstWord(); 204 205 currentText.setText(lastBullet + currentText.getText()); 206 lastBullet = FrameKeyboardActions.getAutoBullet(currentText 207 .getText()); 208 209 // if we changed the item, add to changedItems list 210 if(changedItems != null && oldText != currentText.getText() && !changedItems.contains(currentText)) { 211 Item copy = currentText.copy(); 212 copy.setID(currentText.getID()); 213 copy.setText(oldText); 214 changedItems.add(copy); 215 } 1535 } 1536 } 1537 } 1538 } 1539 1540 FrameIO.SaveFrame(profile); 1541 1542 // Populate settings frameset 1543 Settings.Init(); 1544 t = profile.addText(550, 100, "@Settings", null); 1545 t.setSize((float) 25.0); 1546 t.setFamily("SansSerif"); 1547 t.setFontStyle("Bold"); 1548 t.setColor(Color.gray); 1549 Settings.generateSettingsTree(t); 1550 1551 FrameIO.SaveFrame(profile); 1552 } 1553 1554 private static void checkTDFCItemWaiting(Frame currentFrame) { 1555 Item tdfcItem = FrameUtils.getTdfcItem(); 1556 // if there is a TDFC Item waiting 1557 if (tdfcItem != null) { 1558 boolean change = currentFrame.hasChanged(); 1559 boolean saved = currentFrame.isSaved(); 1560 // Save the parent of the item if it has not been saved 1561 if (!change && !saved) { 1562 tdfcItem.setLink(null); 1563 tdfcItem.getParent().setChanged(true); 1564 FrameIO.SaveFrame(tdfcItem.getParent()); 1565 FrameGraphics.Repaint(); 1566 } else { 1567 SessionStats.CreatedFrame(); 1568 } 1569 1570 setTdfcItem(null); 1571 } 1572 } 1573 1574 public static void setTdfcItem(Item _tdfcItem) { 1575 FrameUtils._tdfcItem = _tdfcItem; 1576 } 1577 1578 public static Item getTdfcItem() { 1579 return FrameUtils._tdfcItem; 1580 } 1581 1582 private static Item _tdfcItem = null; 1583 1584 public static void setLastEdited(Text lastEdited) { 1585 1586 // If the lastEdited is being changed then check if its @i 1587 Frame toReparse = null; 1588 Frame toRecalculate = null; 1589 Frame toUpdateObservers = null; 1590 1591 if (LastEdited == null) { 1592 // System.out.print("N"); 1593 } else if (LastEdited != null) { 1594 // System.out.print("T"); 1595 Frame parent = LastEdited.getParentOrCurrentFrame(); 1596 1597 if (lastEdited != LastEdited) { 1598 if (LastEdited.startsWith("@i")) { 1599 // Check if its an image that can be resized to fit a box 1600 // around it 1601 String text = LastEdited.getText(); 1602 if (text.startsWith("@i:") 1603 && !Character 1604 .isDigit(text.charAt(text.length() - 1))) { 1605 Collection<Item> enclosure = FrameUtils 1606 .getEnclosingLineEnds(LastEdited.getPosition()); 1607 if (enclosure != null) { 1608 for (Item i : enclosure) { 1609 if (i.isLineEnd() && i.isEnclosed()) { 1610 DisplayIO.getCurrentFrame().removeAllItems( 1611 enclosure); 1612 Rectangle rect = i.getEnclosedRectangle(); 1613 LastEdited 1614 .setText(LastEdited.getText() 1615 + " " 1616 + Math.round(rect 1617 .getWidth())); 1618 LastEdited.setPosition(new Point(rect.x, 1619 rect.y)); 1620 LastEdited.setThickness(i.getThickness()); 1621 LastEdited.setBorderColor(i.getColor()); 1622 break; 216 1623 } 1624 } 1625 FrameMouseActions.deleteItems(enclosure, false); 217 1626 } 218 } 219 220 // work out the spacing between the first item and the one above it 221 222 int space = 10 + adjust; 223 224 // if we are dropping from the title make the space a little bigger 225 // than normal 226 227 // If there are only two items get the gap from the start item on the 228 // zero frame if there is one 229 if (above == curr.getTitleItem()) { 230 Frame zero = FrameIO.LoadFrame(curr.getFramesetName() + '0'); 231 String strGap = zero.getAnnotationValue("start"); 232 if (strGap != null) { 233 try { 234 int gap = Integer.parseInt(strGap); 235 space = gap; 236 } catch (NumberFormatException nfe) { 237 238 } 239 } 240 } else if (above != null) { 241 // Make the gap between all items the same as the gap between 242 // the first two 243 space = (int) (from.getPolygon().getBounds().getMinY() - above 244 .getPolygon().getBounds().getMaxY()); 245 246 if (space < MINIMUM_INTERITEM_SPACING) 247 space = MINIMUM_INTERITEM_SPACING; 248 249 if (UserSettings.FormatSpacingMax.get() != null) { 250 double maxSpace = UserSettings.FormatSpacingMax.get() * above.getSize(); 251 if (maxSpace < space) { 252 space = (int) Math.round(maxSpace); 253 } 254 } 255 256 if (UserSettings.FormatSpacingMin.get() != null) { 257 double minSpace = UserSettings.FormatSpacingMin.get() * above.getSize(); 258 if (minSpace > space) { 259 space = (int) Math.round(minSpace); 260 } 261 } 262 263 // Need to do things differently for FORMAT than for DROPPING 264 if (moveAll && above != curr.getNameItem() 265 && above != curr.getTitleItem()) { 266 x = above.getX(); 267 int y = (int) above.getPolygon().getBounds().getMaxY() 268 + space 269 + ((int) (from.getY() - from.getPolygon().getBounds() 270 .getMinY())); 271 272 if(changedItems != null && (from.getX() != x || from.getY() != y) && !changedItems.contains(from)) { 273 Item copy = from.copy(); 274 copy.setID(from.getID()); 275 changedItems.add(copy); 276 } 277 from.setPosition(x, y); 278 } else { 279 x = from.getX(); 280 } 281 282 space += adjust; 283 } 284 for (int i = 1; i < toAlign.size(); i++) { 285 Item current = toAlign.get(i); 286 Item top = toAlign.get(i - 1); 287 288 // The bottom of the previous item 289 int bottom = (int) top.getPolygon().getBounds().getMaxY(); 290 291 // the difference between the current item's Y coordinate and 292 // the top of the highlight box 293 int diff = (int) (current.getY() - current.getPolygon().getBounds() 294 .getMinY()); 295 296 int newPos = bottom + space + diff; 297 298 if(changedItems != null && ((moveAll && current.getX() != x) || current.getY() != newPos) && !changedItems.contains(current)) { 299 Item copy = current.copy(); 300 copy.setID(current.getID()); 301 changedItems.add(copy); 302 } 303 304 if (moveAll) { 305 current.setPosition(x, newPos); 306 } else if (newPos > current.getY()) { 307 current.setY(newPos); 308 } 309 310 } 311 312 // if (insert != null) 313 // return insert.getY(); 314 315 // Michael thinks we return the y value for the next new item?? 316 int y = from.getY() + from.getBoundsHeight() + space; 317 return y; 318 } 319 320 public static int Align(List<Text> toAlign, boolean moveAll, int adjust) { 321 return Align(toAlign, moveAll, adjust, null); 322 } 323 324 public static boolean LeavingFrame(Frame current) { 325 checkTDFCItemWaiting(current); 326 // active overlay frames may also require saving if they have been 327 // changed 328 for (Overlay o : current.getOverlays()) 329 if (!SaveCheck(o.Frame)) 330 return false; 331 332 // if the check fails there is no point continuing 333 if (!SaveCheck(current)) 334 return false; 335 336 for (Item i : current.getItems()) 337 i.setHighlightMode(Item.HighlightMode.None); 338 return true; 339 } 340 341 private static boolean SaveCheck(Frame toSave) { 342 // don't bother saving frames that haven't changed 343 if (!toSave.hasChanged()) 344 return true; 345 346 // if the frame has been changed, then save it 347 if (DisplayIO.isTwinFramesOn()) { 348 Frame opposite = DisplayIO.getOppositeFrame(); 349 350 String side = "left"; 351 if (DisplayIO.getCurrentSide() == 0) 352 side = "right"; 353 354 // if the two frames both have changes, prompt the user for the 355 // next move 356 if (opposite.hasChanged() && opposite.equals(toSave)) { 357 if (DisplayIO.DisplayConfirmDialog( 358 "Leaving this frame will discard changes made in the " 359 + side + " Frame. Continue?", "Changes", 360 DisplayIO.TYPE_WARNING, DisplayIO.OPTIONS_OK_CANCEL, 361 DisplayIO.RESULT_OK)) { 362 FrameIO.SaveFrame(toSave); 363 DisplayIO.Reload(DisplayIO.FrameOnSide(opposite)); 364 return true; 365 } else 366 return false; 367 } else if (opposite.hasOverlay(toSave)) { 368 if (toSave.hasChanged()) 369 if (DisplayIO.DisplayConfirmDialog( 370 "Leaving this frame will discard changes made in the " 371 + side + " Frame. Continue?", "Changes", 372 DisplayIO.TYPE_WARNING, 373 DisplayIO.OPTIONS_OK_CANCEL, DisplayIO.RESULT_OK)) { 374 FrameIO.SaveFrame(toSave); 375 DisplayIO.Reload(DisplayIO.FrameOnSide(opposite)); 376 return true; 377 } else 378 return false; 379 } 380 381 // save the current frame and restore the other side 382 FrameIO.SaveFrame(toSave); 383 return true; 384 } 385 386 // single-frame mode can just save and return 387 FrameIO.SaveFrame(toSave); 388 return true; 389 } 390 391 /** 392 * Displays the given Frame on the display. If the current frame has changed 393 * since the last save then it will be saved before the switch is made. The 394 * caller can also dictate whether the current frame is added to the 395 * back-stack or not. 396 * 397 * @param toDisplay 398 * The Frame to display on the screen 399 * @param addToBack 400 * True if the current Frame should be added to the back-stack, 401 * False otherwise 402 */ 403 public static void DisplayFrame(Frame toDisplay, boolean addToBack, 404 boolean incrementStats) { 405 if (toDisplay == null) 406 return; 407 408 Frame current = DisplayIO.getCurrentFrame(); 409 410 // Dont need to do anything if the frame to display is already being 411 // displayed 412 if (current.equals(toDisplay)) 413 return; 414 415 // move any anchored connected items 416 if (FreeItems.itemsAttachedToCursor()) { 417 List<Item> toAdd = new ArrayList<Item>(); 418 List<Item> toCheck = new ArrayList<Item>(FreeItems.getInstance()); 419 420 while (toCheck.size() > 0) { 421 Item i = toCheck.get(0); 422 Collection<Item> connected = i.getAllConnected(); 423 424 // // Only move completely enclosed items 425 // if (!toCheck.containsAll(connected)) { 426 // connected.retainAll(FreeItems.getInstance()); 427 // FreeItems.getInstance().removeAll(connected); 428 // toCheck.removeAll(connected); 429 // FrameMouseActions.anchor(connected); 430 // } else { 431 // toCheck.removeAll(connected); 432 // } 433 434 // Anchor overlay items where they belong 435 if (i.getParent() != null && i.getParent() != current) { 436 FreeItems.getInstance().removeAll(connected); 437 toCheck.removeAll(connected); 438 FrameMouseActions.anchor(connected); 439 } else { 440 // Add stuff that is partially enclosed 441 // remove all the connected items from our list to check 442 toCheck.removeAll(connected); 443 // Dont add the items that are free 444 connected.removeAll(FreeItems.getInstance()); 445 toAdd.addAll(connected); 446 } 447 } 448 449 current.removeAllItems(toAdd); 450 451 boolean oldChange = toDisplay.hasChanged(); 452 toDisplay.updateIDs(toAdd); 453 toDisplay.addAllItems(toAdd); 454 toDisplay.setChanged(oldChange); 455 } 456 457 if (addToBack && current != toDisplay) { 458 FrameIO.checkTDFC(current); 459 } 460 461 // if the saving happened properly, we can continue 462 if (!LeavingFrame(current)) { 463 MessageBay.displayMessage("Navigation cancelled"); 464 return; 465 } 466 467 if (addToBack && current != toDisplay) { 468 DisplayIO.addToBack(current); 469 } 470 471 Parse(toDisplay); 472 DisplayIO.setCurrentFrame(toDisplay, incrementStats); 473 FrameMouseActions.updateCursor(); 474 // FrameMouseActions.getInstance().refreshHighlights(); 475 // update response timer 476 _LastResponse = ResponseTimer.getElapsedSeconds(); 477 _ResponseTimeSum += _LastResponse; 478 DisplayIO.UpdateTitle(); 479 } 480 481 /** 482 * Loads and displays the Frame with the given framename, and adds the 483 * current frame to the back-stack if required. 484 * 485 * @param framename 486 * The name of the Frame to load and display 487 * @param addToBack 488 * True if the current Frame should be added to the back-stack, 489 * false otherwise 490 */ 491 public static void DisplayFrame(String frameName, boolean addToBack, 492 boolean incrementStats) { 493 Frame newFrame = getFrame(frameName); 494 495 if (newFrame != null) 496 // display the frame 497 DisplayFrame(newFrame, addToBack, incrementStats); 498 } 499 500 /** 501 * Loads and displays the Frame with the given framename and adds the 502 * current frame to the back-stack. This is the same as calling 503 * DisplayFrame(framename, true) 504 * 505 * @param framename 506 * The name of the Frame to load and display 507 */ 508 public static void DisplayFrame(String framename) { 509 DisplayFrame(framename, true, true); 510 } 511 512 public static Frame getFrame(String frameName) { 513 // if the new frame does not exist then tell the user 514 Frame f = FrameIO.LoadFrame(frameName); 515 516 if (f == null) { 517 MessageBay.errorMessage("Frame '" + frameName 518 + "' could not be found."); 519 } 520 521 return f; 522 } 523 524 /** 525 * Creates a new Picture Item from the given Text source Item and adds it to 526 * the given Frame. 527 * 528 * @return True if the image was created successfully, false otherwise 529 */ 530 private static boolean createPicture(Frame frame, Text txt) { 531 // attempt to create the picture 532 Picture pic = ItemUtils.CreatePicture(txt, frame); 533 534 // if the picture could not be created successfully 535 if (pic == null) { 536 String imagePath = txt.getText(); 537 assert (imagePath != null); 538 imagePath = new AttributeValuePair(imagePath).getValue().trim(); 539 if (imagePath.length() == 0) { 540 return false; 541 // MessageBay.errorMessage("Expected image path after @i:"); 542 } else { 543 MessageBay.errorMessage("Image " + imagePath 544 + " could not be loaded"); 545 } 546 return false; 547 } 548 frame.addItem(pic); 549 550 return true; 551 } 552 553 /** 554 * Creates an interactive widget and adds it to a frame. If txt has no 555 * parent the parent will be set to frame. 556 * 557 * @param frame 558 * Frame to add widget to. Must not be null. 559 * 560 * @param txt 561 * Text to create the widget from. Must not be null. 562 * 563 * @return True if created/added. False if coul not create. 564 * 565 * @author Brook Novak 566 */ 567 private static boolean createWidget(Frame frame, Text txt) { 568 569 if (frame == null) 570 throw new NullPointerException("frame"); 571 if (txt == null) 572 throw new NullPointerException("txt"); 573 574 // Safety 575 if (txt.getParent() == null) 576 txt.setParent(frame); 577 578 InteractiveWidget iw = null; 579 580 try { 581 582 iw = InteractiveWidget.createWidget(txt); 583 584 } catch (InteractiveWidgetNotAvailableException e) { 585 e.printStackTrace(); 586 MessageBay.errorMessage("Cannot create iWidget: " + e.getMessage()); 587 } catch (InteractiveWidgetInitialisationFailedException e) { 588 e.printStackTrace(); 589 MessageBay.errorMessage("Cannot create iWidget: " + e.getMessage()); 590 } catch (IllegalArgumentException e) { 591 e.printStackTrace(); 592 MessageBay.errorMessage("Cannot create iWidget: " + e.getMessage()); 593 } 594 595 if (iw == null) 596 return false; 597 598 frame.removeItem(txt); 599 600 frame.addAllItems(iw.getItems()); 601 602 return true; 603 } 604 605 public static Collection<String> ParseProfile(Frame profile) { 606 Collection<String> errors = new LinkedList<String>(); 607 if (profile == null) 608 return errors; 609 610 /* 611 * Make sure the correct cursor shows when turning off the custom cursor 612 * and reparsing the profile frame 613 */ 614 FreeItems.getCursor().clear(); 615 DisplayIO.setCursor(Item.HIDDEN_CURSOR); 616 DisplayIO.setCursor(Item.DEFAULT_CURSOR); 617 618 // check for settings tags 619 for (Text item : profile.getBodyTextItems(true)) { 620 try { 621 622 AttributeValuePair avp = new AttributeValuePair(item.getText()); 623 String attributeFullCase = avp.getAttributeOrValue(); 624 625 if (attributeFullCase == null) { 626 continue; 627 } 628 String attribute = attributeFullCase.trim().toLowerCase().replaceAll("^@", ""); 629 630 if(attribute.equals("settings")) { 631 Settings.parseSettings(item); 632 } 633 634 } catch (Exception e) { 635 if (e.getMessage() != null) { 636 errors.add(e.getMessage()); 637 } else { 638 e.printStackTrace(); 639 errors.add("Error parsing [" + item.getText() + "] on " 640 + profile.getName()); 641 } 642 } 643 } 644 645 return errors; 646 } 647 648 /** 649 * Sets the first frame to be displayed. 650 * 651 * @param profile 652 */ 653 public static void loadFirstFrame(Frame profile) { 654 if (UserSettings.HomeFrame.get() == null) 655 UserSettings.HomeFrame.set(profile.getName()); 656 657 Frame firstFrame = FrameIO.LoadFrame(UserSettings.HomeFrame.get()); 658 if (firstFrame == null) { 659 MessageBay.warningMessage("Home frame not found: " 660 + UserSettings.HomeFrame); 661 UserSettings.HomeFrame.set(profile.getName()); 662 DisplayIO.setCurrentFrame(profile, true); 663 } else { 664 DisplayIO.setCurrentFrame(firstFrame, true); 665 } 666 667 } 668 669 public static Color[] getColorWheel(Frame frame) { 670 if (frame != null) { 671 List<Text> textItems = frame.getBodyTextItems(false); 672 Color[] colorList = new Color[textItems.size() + 1]; 673 for (int i = 0; i < textItems.size(); i++) { 674 colorList[i] = textItems.get(i).getColor(); 675 } 676 // Make the last item transparency or default for forecolor 677 colorList[colorList.length - 1] = null; 678 679 return colorList; 680 } 681 return new Color[] { Color.black, Color.white, null }; 682 } 683 684 public static String getLink(Item item, String alt) { 685 if (item == null || !(item instanceof Text)) 686 return alt; 687 688 AttributeValuePair avp = new AttributeValuePair(item.getText()); 689 assert (avp != null); 690 691 if (avp.hasPair() && avp.getValue().trim().length() != 0) { 692 item.setLink(avp.getValue()); 693 return avp.getValue(); 694 } else if (item.getLink() != null) { 695 return item.getAbsoluteLink(); 696 } 697 698 return alt; 699 } 700 701 public static String getDir(String name) { 702 if (name != null) { 703 File tester = new File(name); 704 if (tester.exists() && tester.isDirectory()) { 705 if (name.endsWith(File.separator)) 706 return name; 707 else 708 return name + File.separator; 709 } else { 710 throw new RuntimeException("Directory not found: " + name); 711 } 712 } 713 throw new RuntimeException("Missing value for profile attribute" + name); 714 } 715 716 public static ArrayList<String> getDirs(Item item) { 717 ArrayList<String> dirsToAdd = new ArrayList<String>(); 718 String dirListFrameName = item.getAbsoluteLink(); 719 if (dirListFrameName != null) { 720 Frame dirListFrame = FrameIO.LoadFrame(dirListFrameName); 721 if (dirListFrame != null) { 722 for (Text t : dirListFrame.getBodyTextItems(false)) { 723 String dirName = t.getText().trim(); 724 File tester = new File(dirName); 725 if (tester.exists() && tester.isDirectory()) { 726 if (dirName.endsWith(File.separator)) 727 dirsToAdd.add(dirName); 728 else 729 dirsToAdd.add(dirName + File.separator); 730 } 731 } 732 } 733 } 734 735 return dirsToAdd; 736 } 737 738 public static void Parse(Frame toParse) { 739 Parse(toParse, false); 740 } 741 742 /** 743 * Checks for any special Annotation items and updates the display as 744 * necessary. Special Items: Images, overlays, sort. 745 * 746 */ 747 public static void Parse(Frame toParse, boolean firstParse) { 748 Parse(toParse, firstParse, false); 749 } 750 751 /** 752 * 753 * @param toParse 754 * @param firstParse 755 * @param ignoreAnnotations 756 * used to prevent infinate loops such as when performing TDFC 757 * with an ao tag linked to a frame with an frameImage of a frame 758 * which also has an ao tag on it. 759 */ 760 public static void Parse(Frame toParse, boolean firstParse, 761 boolean ignoreAnnotations) { 762 // TODO check why we are getting toParse == null... when profile frame 763 // is being created and change the lines below 764 if (toParse == null) 765 return; 766 // System.out.println(firstParse); 767 if (firstParse) 768 ItemUtils.EnclosedCheck(toParse.getItems()); 769 List<Item> items = toParse.getItems(); 770 771 // if XRayMode is on, replace pictures with their underlying text 772 if (FrameGraphics.isXRayMode()) { 773 774 // BROOK: Must handle these a little different 775 List<InteractiveWidget> widgets = toParse.getInteractiveWidgets(); 776 777 for (Item i : items) { 778 if (i instanceof XRayable) { 779 toParse.removeItem(i); 780 // Show the items 781 for (Item item : ((XRayable) i).getConnected()) { 782 item.setVisible(true); 783 item.removeEnclosure(i); 784 } 785 } else if (i instanceof WidgetCorner) { 786 toParse.removeItem(i); 787 } else if (i instanceof WidgetEdge) { 788 toParse.removeItem(i); 789 } else if (i.hasFormula()) { 790 i.setText(i.getFormula()); 791 } else if (i.hasOverlay()) { 792 i.setVisible(true); 793 // int x = i.getBoundsHeight(); 794 } 795 } 796 797 for (InteractiveWidget iw : widgets) { 798 toParse.addItem(iw.getSource()); 799 } 800 } 801 802 // Text title = null; 803 // Text template = UserSettingsTemplate.copy(); 804 805 List<Overlay> overlays = new ArrayList<Overlay>(); 806 List<Vector> vectors = new ArrayList<Vector>(); 807 808 // disable reading of cached overlays if in twinframes mode 809 if (DisplayIO.isTwinFramesOn()) 810 FrameIO.SuspendCache(); 811 812 DotType pointtype = DotType.square; 813 boolean filledPoints = true; 814 815 UserAppliedPermission permission = toParse.getUserAppliedPermission(); 816 toParse.clearAnnotations(); 817 818 // check for any new overlay items 819 for (Item i : toParse.getItems()) { 820 try { 821 // reset overlay permission 822 i.setOverlayPermission(null); 823 // i.setPermission(permission); 824 if (i instanceof WidgetCorner) { 825 // TODO improve efficiency so it only updates once... using 826 // observer design pattern 827 i.update(); 828 } else if (i instanceof Text) { 829 if (i.isAnnotation()) { 830 if (ItemUtils.startsWithTag(i, ItemUtils.TAG_POINTTYPE)) { 831 Text txt = (Text) i; 832 String line = txt.getFirstLine(); 833 line = ItemUtils.StripTag(line, ItemUtils 834 .GetTag(ItemUtils.TAG_POINTTYPE)); 835 836 if (line != null) { 837 line = line.toLowerCase(); 838 if (line.indexOf(" ") > 0) { 839 String fill = line.substring(line 840 .indexOf(" ") + 1); 841 if (fill.startsWith("nofill")) 842 filledPoints = false; 843 else 844 filledPoints = true; 845 } 846 847 if (line.startsWith("circle")) 848 pointtype = DotType.circle; 849 else 850 pointtype = DotType.square; 851 } 852 }// check for new VECTOR items 853 else if (!FrameGraphics.isXRayMode() 854 && ItemUtils.startsWithTag(i, 855 ItemUtils.TAG_VECTOR) 856 && i.getLink() != null) { 857 if (!i.getAbsoluteLink().equals(toParse.getName())) 858 addVector(vectors, UserAppliedPermission.none, permission, 859 i); 860 } else if (!FrameGraphics.isXRayMode() 861 && ItemUtils.startsWithTag(i, 862 ItemUtils.TAG_ACTIVE_VECTOR) 863 && i.getLink() != null) { 864 if (!i.getAbsoluteLink().equals(toParse.getName())) 865 addVector(vectors, UserAppliedPermission.followLinks, 866 permission, i); 867 } 868 // check for new OVERLAY items 869 else if (!ignoreAnnotations 870 && ItemUtils.startsWithTag(i, 871 ItemUtils.TAG_OVERLAY) 872 && i.getLink() != null) { 873 if (i.getAbsoluteLink().equalsIgnoreCase( 874 toParse.getName())) { 875 // This frame contains an active overlay which 876 // points to itself 877 MessageBay 878 .errorMessage(toParse.getName() 879 + " contains an @o which links to itself"); 880 continue; 881 } 882 883 Frame overlayFrame = FrameIO.LoadFrame(i 884 .getAbsoluteLink()); 885 // Parse(overlay); 886 if (overlayFrame != null 887 && Overlay.getOverlay(overlays, 888 overlayFrame) == null) 889 overlays.add(new Overlay(overlayFrame, 890 UserAppliedPermission.none)); 891 } 892 // check for ACTIVE_OVERLAY items 893 else if (!ignoreAnnotations 894 && ItemUtils.startsWithTag(i, 895 ItemUtils.TAG_ACTIVE_OVERLAY) 896 && i.getLink() != null) { 897 String link = i.getAbsoluteLink(); 898 if (link.equalsIgnoreCase(toParse.getName())) { 899 // This frame contains an active overlay which 900 // points to itself 901 MessageBay 902 .errorMessage(toParse.getName() 903 + " contains an @ao which links to itself"); 904 continue; 905 } 906 Frame overlayFrame = null; 907 908 Frame current = DisplayIO.getCurrentFrame(); 909 if (current != null) { 910 for (Overlay o : current.getOverlays()) { 911 if (o.Frame.getName() 912 .equalsIgnoreCase(link)) 913 overlayFrame = o.Frame; 914 } 915 } 916 if (overlayFrame == null) 917 overlayFrame = FrameIO.LoadFrame(link); 918 919 // get level if specified 920 String level = new AttributeValuePair(i.getText()).getValue(); 921 // default permission (if none is specified) 922 PermissionPair permissionLevel 923 = new PermissionPair(level,UserAppliedPermission.followLinks); 924 925 if (overlayFrame != null) { 926 Overlay existingOverlay = Overlay.getOverlay( 927 overlays, overlayFrame); 928 // If it wasn't in the list create it and add it. 929 if (existingOverlay == null) { 930 Overlay newOverlay = new Overlay( 931 overlayFrame, permissionLevel.getPermission(overlayFrame.getOwner())); 932 i.setOverlay(newOverlay); 933 overlays.add(newOverlay); 934 } else { 935 existingOverlay.Frame 936 .setPermission(permissionLevel); 937 } 938 } 939 } 940 // check for Images and widgets 941 else { 942 if (!FrameGraphics.isXRayMode()) { 943 if (ItemUtils.startsWithTag(i, 944 ItemUtils.TAG_IMAGE, true)) { 945 if (!i.hasEnclosures()) { 946 createPicture(toParse, (Text) i); 947 } 948 // check for frame images 949 } else if (ItemUtils.startsWithTag(i, 950 ItemUtils.TAG_FRAME_IMAGE) 951 && i.getLink() != null 952 && !i.getAbsoluteLink() 953 .equalsIgnoreCase( 954 toParse.getName())) { 955 XRayable image = null; 956 if (i.hasEnclosures()) { 957 // i.setHidden(true); 958 // image = 959 // i.getEnclosures().iterator().next(); 960 // image.refresh(); 961 } else { 962 image = new FrameImage((Text) i, 963 toParse, null); 964 } 965 // TODO Add the image when creating new 966 // FrameImage 967 toParse.addItem(image); 968 } else if (ItemUtils.startsWithTag(i, 969 ItemUtils.TAG_BITMAP_IMAGE) 970 && i.getLink() != null 971 && !i.getAbsoluteLink() 972 .equalsIgnoreCase( 973 toParse.getName())) { 974 XRayable image = null; 975 if (i.hasEnclosures()) { 976 // image = 977 // i.getEnclosures().iterator().next(); 978 // image.refresh(); 979 // i.setHidden(true); 980 } else { 981 // If a new bitmap is created for a 982 // frame which already has a bitmap dont 983 // recreate the bitmap 984 image = new FrameBitmap((Text) i, 985 toParse, null); 986 } 987 toParse.addItem(image); 988 } else if (ItemUtils.startsWithTag(i, "@c")) { 989 // Can only have a @c 990 if (!i.hasEnclosures() 991 && i.getLines().size() == 1) { 992 toParse.addItem(new Circle((Text) i)); 993 } 994 // Check for interactive widgets 995 } else if (ItemUtils.startsWithTag(i, 996 ItemUtils.TAG_IWIDGET)) { 997 createWidget(toParse, (Text) i); 998 } 999 } 1000 // TODO decide exactly what to do here!! 1001 toParse.addAnnotation((Text) i); 1002 } 1003 } else if (!FrameGraphics.isXRayMode() && i.hasFormula()) { 1004 i.calculate(i.getFormula()); 1005 } 1006 } 1007 } catch (Exception e) { 1008 Logger.Log(e); 1009 e.printStackTrace(); 1010 MessageBay.warningMessage("Exception occured when loading " 1011 + i.getClass().getSimpleName() + "(ID: " + i.getID() 1012 + ") " + e.getMessage() != null ? e.getMessage() : ""); 1013 } 1014 } 1015 1016 /* 1017 * for (Item i : items) { if (i instanceof Dot) { ((Dot) 1018 * i).setPointType(pointtype); ((Dot) i).useFilledPoints(filledPoints); } } 1019 */ 1020 1021 FrameIO.ResumeCache(); 1022 1023 toParse.clearOverlays(); 1024 toParse.clearVectors(); 1025 toParse.addAllOverlays(overlays); 1026 toParse.addAllVectors(vectors); 1027 1028 } 1029 1030 /** 1031 * @param vectors 1032 * @param permission 1033 * @param i 1034 */ 1035 private static void addVector(List<Vector> vectors, 1036 UserAppliedPermission defaultPermission, UserAppliedPermission framePermission, Item i) { 1037 // TODO It is possible to get into an infinate loop if a 1038 // frame contains an @ao which leads to a frame with an 1039 // @v which points back to the frame with the @ao 1040 Frame vector = FrameIO.LoadFrame(i.getAbsoluteLink()); 1041 1042 // Get the permission from off the vector frame 1043 UserAppliedPermission vectorPermission = UserAppliedPermission.getPermission(vector 1044 .getAnnotationValue("permission"), defaultPermission); 1045 // If the frame permission is lower, use that 1046 vectorPermission = UserAppliedPermission.min(vectorPermission, framePermission); 1047 // Highest permissable permission for vectors is copy 1048 vectorPermission = UserAppliedPermission.min(vectorPermission, UserAppliedPermission.copy); 1049 if (vector != null) { 1050 String scaleString = new AttributeValuePair(i.getText()).getValue(); 1051 Float scale = 1F; 1052 try { 1053 scale = Float.parseFloat(scaleString); 1054 } catch (Exception e) { 1055 } 1056 Vector newVector = new Vector(vector, vectorPermission, scale, i); 1057 i.setOverlay(newVector); 1058 i.setVisible(false); 1059 vectors.add(newVector); 1060 } 1061 } 1062 1063 public static Item onItem(float floatX, float floatY, 1064 boolean changeLastEdited) { 1065 return onItem(DisplayIO.getCurrentFrame(), floatX, floatY, 1066 changeLastEdited); 1067 } 1068 1069 /** 1070 * Searches through the list of items on this frame to find one at the given 1071 * x,y coordinates. 1072 * 1073 * @param x 1074 * The x coordinate 1075 * @param y 1076 * The y coordinate 1077 * @return The Item at the given coordinates, or NULL if none is found. 1078 */ 1079 public static Item onItem(Frame toCheck, float floatX, float floatY, 1080 boolean bResetLastEdited) { 1081 // System.out.println("MouseX: " + floatX + " MouseY: " + floatY); 1082 int x = Math.round(floatX); 1083 int y = Math.round(floatY); 1084 if (toCheck == null) 1085 return null; 1086 1087 List<Item> possibles = new ArrayList<Item>(0); 1088 1089 // if the mouse is in the message area 1090 if (y > FrameGraphics.getMaxFrameSize().getHeight()) { 1091 // check the individual message items 1092 for (Item message : MessageBay.getMessages()) { 1093 if (message != null) { 1094 if (message.contains(x, y)) { 1095 message.setOverlayPermission(UserAppliedPermission.copy); 1096 possibles.add(message); 1097 } else { 1098 // Not sure why but if the line below is removed then 1099 // several items can be highlighted at once 1100 message.setHighlightMode(Item.HighlightMode.None); 1101 } 1102 } 1103 } 1104 1105 // check the link to the message frame 1106 if (MessageBay.getMessageLink() != null) { 1107 if (MessageBay.getMessageLink().contains(x, y)) { 1108 MessageBay.getMessageLink().setOverlayPermission(UserAppliedPermission.copy); 1109 possibles.add(MessageBay.getMessageLink()); 1110 } 1111 } 1112 1113 // this is taken into account in contains 1114 // y -= FrameGraphics.getMaxFrameSize().height; 1115 // otherwise, the mouse is on the frame 1116 } else { 1117 if (LastEdited != null) { 1118 if (LastEdited.contains(x, y) 1119 && !FreeItems.getInstance().contains(LastEdited) 1120 && LastEdited.getParent() == DisplayIO 1121 .getCurrentFrame() 1122 && LastEdited.getParent().getItems().contains( 1123 LastEdited)) { 1124 LastEdited.setOverlayPermission(UserAppliedPermission.full); 1125 return LastEdited; 1126 } else if (bResetLastEdited) { 1127 setLastEdited(null); 1128 } 1129 } 1130 ArrayList<Item> checkList = new ArrayList<Item>(); 1131 checkList.addAll(toCheck.getInteractableItems()); 1132 checkList.add(toCheck.getNameItem()); 1133 for (Item i : checkList) { 1134 // do not check annotation items in audience mode 1135 if (i.isVisible() 1136 && !(FrameGraphics.isAudienceMode() && i.isAnnotation())) { 1137 if (i.contains(x, y) 1138 && !FreeItems.getInstance().contains(i)) { 1139 possibles.add(i); 1140 } 1141 } 1142 } 1143 } 1144 1145 // if there are no possible items, return null 1146 if (possibles.size() == 0) 1147 return null; 1148 1149 // if there is only one possibility, return it 1150 if (possibles.size() == 1) 1151 return possibles.get(0); 1152 1153 // return closest x,y pair to mouse 1154 Item closest = possibles.get(0); 1155 int distance = (int) Math.round(Math.sqrt(Math.pow(Math.abs(closest 1156 .getX() 1157 - x), 2) 1158 + Math.pow(Math.abs(closest.getY() - y), 2))); 1159 1160 for (Item i : possibles) { 1161 int d = (int) Math.round(Math.sqrt(Math.pow(Math.abs(i.getX() - x), 1162 2) 1163 + Math.pow(Math.abs(i.getY() - y), 2))); 1164 1165 // System.out.println(d); 1166 if (d <= distance) { 1167 distance = d; 1168 1169 // dots take precedence over lines 1170 if ((!(closest instanceof Dot && i instanceof Line)) 1171 && (!(closest instanceof Text && i instanceof Line))) 1172 closest = i; 1173 1174 } 1175 1176 } 1177 1178 return closest; 1179 } 1180 1181 public synchronized static Item getCurrentItem() { 1182 return onItem(DisplayIO.getCurrentFrame(), DisplayIO.getMouseX(), 1183 FrameMouseActions.getY(), true); 1184 } 1185 1186 public static Polygon getEnlosingPolygon() { 1187 Collection<Item> enclosure = getEnclosingLineEnds(); 1188 if (enclosure == null || enclosure.size() == 0) 1189 return null; 1190 1191 return enclosure.iterator().next().getEnclosedShape(); 1192 } 1193 1194 /** 1195 * 1196 * @param currentItem 1197 * @return 1198 */ 1199 public static Collection<Item> getCurrentItems() { 1200 return getCurrentItems(getCurrentItem()); 1201 } 1202 1203 public static Collection<Item> getCurrentItems(Item currentItem) { 1204 1205 Collection<Item> enclosure = getEnclosingLineEnds(); 1206 if (enclosure == null || enclosure.size() == 0) 1207 return null; 1208 1209 Item firstItem = enclosure.iterator().next(); 1210 1211 Collection<Item> enclosed = getItemsEnclosedBy(DisplayIO 1212 .getCurrentFrame(), firstItem.getEnclosedShape()); 1213 1214 // Brook: enclosed widgets are to be fully enclosed, never partially 1215 /* 1216 * MIKE says: but doesnt this mean that widgets are treated differently 1217 * from ALL other object which only need to be partially enclosed to be 1218 * picked up 1219 */ 1220 List<InteractiveWidget> enclosedWidgets = new LinkedList<InteractiveWidget>(); 1221 for (Item i : enclosed) { 1222 // Don't want to lose the highlighting from the current item 1223 if(i == currentItem || enclosure.contains(i)) { 1224 continue; 1225 } 1226 // Don't want to lose the highlighting of connected Dots 1227 if(i instanceof Dot && i.getHighlightMode() == HighlightMode.Connected) { 1228 for(Line l : i.getLines()) { 1229 if(l.getOppositeEnd(i).getHighlightMode() == HighlightMode.Normal) { 1230 continue; 1231 } 1232 } 1233 } 1234 if (i instanceof WidgetCorner) { 1235 if (!enclosedWidgets.contains(((WidgetCorner) i) 1236 .getWidgetSource())) 1237 enclosedWidgets.add(((WidgetCorner) i).getWidgetSource()); 1238 } 1239 i.setHighlightMode(Item.HighlightMode.None); 1240 } 1241 1242 for (InteractiveWidget iw : enclosedWidgets) { 1243 for (Item i : iw.getItems()) { 1244 if (!enclosed.contains(i)) { 1245 enclosed.add(i); 1246 } 1247 } 1248 } 1249 1250 return enclosed; 1251 } 1252 1253 public static Collection<Item> getEnclosingLineEnds() { 1254 return getEnclosingLineEnds(new Point(DisplayIO.getMouseX(), 1255 FrameMouseActions.getY())); 1256 } 1257 1258 public static Collection<Item> getEnclosingLineEnds(Point position) { 1259 // update enclosed shapes 1260 Frame current = DisplayIO.getCurrentFrame(); 1261 List<Item> items = current.getItems(); 1262 1263 // Remove all items that are connected to freeItems 1264 List<Item> freeItems = new ArrayList<Item>(FreeItems.getInstance()); 1265 while (freeItems.size() > 0) { 1266 Item item = freeItems.get(0); 1267 Collection<Item> connected = item.getAllConnected(); 1268 items.removeAll(connected); 1269 freeItems.removeAll(connected); 1270 } 1271 1272 List<Item> used = new ArrayList<Item>(0); 1273 1274 while (items.size() > 0) { 1275 Item i = items.get(0); 1276 items.remove(i); 1277 if (i.isEnclosed()) { 1278 Polygon p = i.getEnclosedShape(); 1279 if (p.contains(position.x, position.y)) { 1280 used.add(i); 1281 items.removeAll(i.getEnclosingDots()); 1282 } 1283 } 1284 } 1285 1286 if (used.size() == 0) 1287 return null; 1288 1289 // if there is only one possibility, return it 1290 if (used.size() == 1) { 1291 return used.get(0).getEnclosingDots(); 1292 // otherwise, determine which polygon is closest to the cursor 1293 } else { 1294 Collections.sort(used, new Comparator<Item>() { 1295 public int compare(Item d1, Item d2) { 1296 Polygon p1 = d1.getEnclosedShape(); 1297 Polygon p2 = d2.getEnclosedShape(); 1298 1299 int closest = Integer.MAX_VALUE; 1300 int close2 = Integer.MAX_VALUE; 1301 1302 int mouseX = DisplayIO.getMouseX(); 1303 int mouseY = FrameMouseActions.getY(); 1304 1305 for (int i = 0; i < p1.npoints; i++) { 1306 int diff = Math.abs(p1.xpoints[i] - mouseX) 1307 + Math.abs(p1.ypoints[i] - mouseY); 1308 int diff2 = Integer.MAX_VALUE; 1309 1310 if (i < p2.npoints) 1311 diff2 = Math.abs(p2.xpoints[i] - mouseX) 1312 + Math.abs(p2.ypoints[i] - mouseY); 1313 1314 if (diff < Math.abs(closest)) { 1315 close2 = closest; 1316 closest = diff; 1317 } else if (diff < Math.abs(close2)) 1318 close2 = diff; 1319 1320 if (diff2 < Math.abs(closest)) { 1321 close2 = closest; 1322 closest = -diff2; 1323 } else if (diff2 < Math.abs(close2)) 1324 close2 = diff2; 1325 } 1326 1327 if (closest > 0 && close2 > 0) 1328 return -10; 1329 1330 if (closest < 0 && close2 < 0) 1331 return 10; 1332 1333 if (closest > 0) 1334 return -10; 1335 1336 return 10; 1337 } 1338 1339 }); 1340 1341 return used.get(0).getEnclosingDots(); 1342 } 1343 } 1344 1345 // TODO Remove this method!! 1346 // Can just getItemsWithin be used? 1347 public static Collection<Item> getItemsEnclosedBy(Frame frame, Polygon poly) { 1348 Collection<Item> contained = frame.getItemsWithin(poly); 1349 1350 Collection<Item> results = new LinkedHashSet<Item>(contained.size()); 1351 1352 // check for correct permissions 1353 for (Item item : contained) { 1354 // if the item is on the frame 1355 if (item.getParent() == frame || item.getParent() == null) { 1356 // item.Permission = Permission.full; 1357 results.add(item); 1358 // otherwise, it must be on an overlay frame 1359 } else { 1360 for (Overlay overlay : frame.getOverlays()) { 1361 if (overlay.Frame == item.getParent()) { 1362 item.setOverlayPermission(overlay.permission); 1363 results.add(item); 1364 break; 1365 } 1366 } 1367 } 1368 } 1369 1370 return results; 1371 } 1372 1373 /** 1374 * Fills the given Frame with default profile tags 1375 */ 1376 public static void CreateDefaultProfile(String username, Frame profile) { 1377 Text title = profile.getTitleItem(); 1378 if (username.equals(UserSettings.DEFAULT_PROFILE_NAME)) { 1379 title.setText("Default Profile Frame"); 1380 } else { 1381 title.setText(username + "'s Profile Frame"); 1382 } 1383 1384 // int spacing = 50; 1385 final int intialYPos = 75; 1386 int xPos = 75; 1387 int yPos = intialYPos; 1388 1389 // yPos += spacing; 1390 // profile.addText(xPos, yPos, "@HomeFrame", null, profile.getName()); 1391 // yPos += spacing; 1392 // String defaultFrameName = profile.getFramesetName() + "0"; 1393 // profile.addText(xPos, yPos, "@DefaultFrame", null, defaultFrameName); 1394 // yPos += spacing; 1395 // 1396 // profile.addText(xPos, yPos, "@InitialWidth: " 1397 // + UserSettings.InitialWidth, null); 1398 // yPos += spacing; 1399 // 1400 // profile.addText(xPos, yPos, "@InitialHeight: " 1401 // + UserSettings.InitialHeight, null); 1402 // yPos += spacing; 1403 // 1404 // Text t = profile.addText(xPos, yPos, "@ItemTemplate", null); 1405 // t.setColor(null); 1406 // 1407 // yPos += spacing; 1408 // t = profile.addText(xPos, yPos, "@AnnotationTemplate", null); 1409 // t.setColor(Color.gray); 1410 // 1411 // yPos += spacing; 1412 // t = profile.addText(xPos, yPos, "@CommentTemplate", null); 1413 // t.setColor(Color.green.darker()); 1414 // 1415 // yPos += spacing; 1416 // t = profile.addText(xPos, yPos, "@StatsTemplate", null); 1417 // t.setColor(Color.BLACK); 1418 // t.setBackgroundColor(new Color(0.9F, 0.9F, 0.9F)); 1419 // t.setFamily(Text.MONOSPACED_FONT); 1420 // t.setSize(14); 1421 1422 Text t; 1423 1424 xPos = 300; 1425 //yPos = intialYPos + spacing; 1426 yPos = 100; 1427 1428 // Load documentation and start pages 1429 extractResources(); 1430 1431 // Add documentation links 1432 File helpDirectory = new File(FrameIO.HELP_PATH); 1433 if (helpDirectory != null) { 1434 File[] helpFramesets = helpDirectory.listFiles(); 1435 if (helpFramesets != null) { 1436 1437 // Add the title for the help index 1438 Text help = profile 1439 .addText(xPos, yPos, "@Expeditee Help", null); 1440 help.setSize(25); 1441 help.setFontStyle("Bold"); 1442 help.setFamily("SansSerif"); 1443 help.setColor(UserSettings.ColorWheel.get()[3]); 1444 1445 xPos += 25; 1446 System.out.println("Installing frameset: "); 1447 1448 for (File helpFrameset : helpFramesets) { 1449 String framesetName = helpFrameset.getName(); 1450 if (!FrameIO.isValidFramesetName(framesetName)) 1451 continue; 1452 System.out.println(" " + framesetName); 1453 Frame indexFrame = FrameIO.LoadFrame(framesetName + '1'); 1454 // Look through the folder for help index pages 1455 if (indexFrame != null 1456 && ItemUtils.FindTag(indexFrame.getItems(), 1457 "@HelpIndex") != null) { 1458 //yPos += spacing; 1459 yPos += 30; 1460 t = profile.addText(xPos, yPos, '@' + indexFrame 1461 .getFramesetName(), null); 1462 t.setLink(indexFrame.getName()); 1463 t.setColor(Color.gray); 1464 } 1465 } 1466 } 1467 } 1468 1469 xPos = 50; 1470 yPos = 100; 1471 1472 // Populate Start Pages and Settings 1473 File framesetDirectory = new File(FrameIO.FRAME_PATH); 1474 1475 if(framesetDirectory.exists()) { 1476 File[] startpagesFramesets = framesetDirectory.listFiles(); 1477 1478 if(startpagesFramesets != null) { 1479 // Add Start Page title 1480 Text templates = profile.addText(xPos, yPos, "@Start Pages", null); 1481 templates.setSize(25); 1482 templates.setFontStyle("Bold"); 1483 templates.setFamily("SansSerif"); 1484 templates.setColor(UserSettings.ColorWheel.get()[3]); 1485 1486 xPos += 25; 1487 1488 // Start Pages should be the first frame in its own frameset + frameset name should be present in FrameUtils.startPages[]. 1489 for(File startpagesFrameset : startpagesFramesets) { 1490 String framesetName = startpagesFrameset.getName(); 1491 1492 // Only add link if frameset is a startpage 1493 for(int i = 0; i < startPages.length ; i++) { 1494 if(framesetName.equals(startPages[i])) { 1495 Frame indexFrame = FrameIO.LoadFrame(framesetName + '1'); 1496 1497 // Add start page link 1498 if(indexFrame != null) { 1499 yPos += 30; 1500 t = profile.addText(xPos, yPos, '@' + indexFrame.getFramesetName(), null); 1501 t.setLink(indexFrame.getName()); 1502 t.setColor(Color.gray); 1503 } 1504 } 1505 } 1506 } 1507 } 1508 } 1509 1510 FrameIO.SaveFrame(profile); 1511 1512 // Populate settings frameset 1513 Settings.Init(); 1514 t = profile.addText(550, 100, "@Settings", null); 1515 t.setSize((float) 25.0); 1516 t.setFamily("SansSerif"); 1517 t.setFontStyle("Bold"); 1518 t.setColor(Color.gray); 1519 Settings.generateSettingsTree(t); 1520 1521 FrameIO.SaveFrame(profile); 1522 } 1523 1524 private static void checkTDFCItemWaiting(Frame currentFrame) { 1525 Item tdfcItem = FrameUtils.getTdfcItem(); 1526 // if there is a TDFC Item waiting 1527 if (tdfcItem != null) { 1528 boolean change = currentFrame.hasChanged(); 1529 boolean saved = currentFrame.isSaved(); 1530 // Save the parent of the item if it has not been saved 1531 if (!change && !saved) { 1532 tdfcItem.setLink(null); 1533 tdfcItem.getParent().setChanged(true); 1534 FrameIO.SaveFrame(tdfcItem.getParent()); 1535 FrameGraphics.Repaint(); 1536 } else { 1537 SessionStats.CreatedFrame(); 1538 } 1539 1540 setTdfcItem(null); 1541 } 1542 } 1543 1544 public static void setTdfcItem(Item _tdfcItem) { 1545 FrameUtils._tdfcItem = _tdfcItem; 1546 } 1547 1548 public static Item getTdfcItem() { 1549 return FrameUtils._tdfcItem; 1550 } 1551 1552 private static Item _tdfcItem = null; 1553 1554 public static void setLastEdited(Text lastEdited) { 1555 1556 // If the lastEdited is being changed then check if its @i 1557 Frame toReparse = null; 1558 Frame toRecalculate = null; 1559 Frame toUpdateObservers = null; 1560 1561 if (LastEdited == null) { 1562 // System.out.print("N"); 1563 } else if (LastEdited != null) { 1564 // System.out.print("T"); 1565 Frame parent = LastEdited.getParentOrCurrentFrame(); 1566 1567 if (lastEdited != LastEdited) { 1568 if (LastEdited.startsWith("@i")) { 1569 // Check if its an image that can be resized to fit a box 1570 // around it 1571 String text = LastEdited.getText(); 1572 if (text.startsWith("@i:") 1573 && !Character.isDigit(text 1574 .charAt(text.length() - 1))) { 1575 Collection<Item> enclosure = FrameUtils 1576 .getEnclosingLineEnds(LastEdited.getPosition()); 1577 if (enclosure != null) { 1578 for (Item i : enclosure) { 1579 if (i.isLineEnd() && i.isEnclosed()) { 1580 DisplayIO.getCurrentFrame().removeAllItems( 1581 enclosure); 1582 Rectangle rect = i.getEnclosedRectangle(); 1583 LastEdited 1584 .setText(LastEdited.getText() 1585 + " " 1586 + Math.round(rect 1587 .getWidth())); 1588 LastEdited.setPosition(new Point(rect.x, 1589 rect.y)); 1590 LastEdited.setThickness(i.getThickness()); 1591 LastEdited.setBorderColor(i.getColor()); 1592 break; 1593 } 1594 } 1595 FrameMouseActions.deleteItems(enclosure, false); 1596 } 1597 } 1598 toReparse = parent; 1599 } else if (LastEdited.recalculateWhenChanged()) { 1600 toRecalculate = parent; 1601 } 1602 1603 if (parent.hasObservers()) { 1604 toUpdateObservers = parent; 1605 } 1606 // Update the formula if in XRay mode 1607 if (FrameGraphics.isXRayMode() && LastEdited.hasFormula()) { 1608 LastEdited.setFormula(LastEdited.getText()); 1609 } 1610 } 1611 if (lastEdited != LastEdited && LastEdited.getText().length() == 0) { 1612 parent.removeItem(LastEdited); 1613 } 1614 } 1615 LastEdited = lastEdited; 1616 1617 if (!FrameGraphics.isXRayMode()) { 1618 if (toReparse != null) { 1619 Parse(toReparse, false, false); 1620 } else { 1621 if (toRecalculate != null) { 1622 toRecalculate.recalculate(); 1623 } 1624 1625 if (toUpdateObservers != null) { 1626 toUpdateObservers.notifyObservers(false); 1627 } 1628 } 1629 } 1630 } 1631 1632 /** 1633 * Extracts files/folders from the assets/resources folder directly into ${PARENT_FOLDER} (~/.expeditee) 1634 */ 1635 private static void extractResources() { 1627 } 1628 toReparse = parent; 1629 } else if (LastEdited.recalculateWhenChanged()) { 1630 toRecalculate = parent; 1631 } 1632 1633 if (parent.hasObservers()) { 1634 toUpdateObservers = parent; 1635 } 1636 // Update the formula if in XRay mode 1637 if (FrameGraphics.isXRayMode() && LastEdited.hasFormula()) { 1638 LastEdited.setFormula(LastEdited.getText()); 1639 } 1640 } 1641 if (lastEdited != LastEdited && LastEdited.getText().length() == 0) { 1642 parent.removeItem(LastEdited); 1643 } 1644 } 1645 LastEdited = lastEdited; 1646 1647 if (!FrameGraphics.isXRayMode()) { 1648 if (toReparse != null) { 1649 Parse(toReparse, false, false); 1650 } else { 1651 if (toRecalculate != null) { 1652 toRecalculate.recalculate(); 1653 } 1654 1655 if (toUpdateObservers != null) { 1656 toUpdateObservers.notifyObservers(false); 1657 } 1658 } 1659 } 1660 } 1661 1662 /** 1663 * Extracts files/folders from the assets/resources folder directly into 1664 * ${PARENT_FOLDER} (~/.expeditee) 1665 */ 1666 private static void extractResources() { 1636 1667 System.out.println("Extracting/Installing resources:"); 1637 1668 try { … … 1689 1720 1690 1721 // Copy files from the source folder to the profile folder 1722 } else if (docURL.getProtocol().equals("bundleresource")) { 1723 final URLConnection urlConnection = docURL.openConnection(); 1724 final Class<?> c = urlConnection.getClass(); 1725 final java.lang.reflect.Method toInvoke = c.getMethod("getFileURL"); 1726 final URL fileURL = (URL)toInvoke.invoke(urlConnection); 1727 BryceSaysPleaseNameMe(new File(fileURL.getPath())); 1691 1728 } else { 1692 1729 File folder = new File(docURL.toURI().getPath()); 1693 LinkedList<File> items = new LinkedList<File>(); 1694 items.addAll(Arrays.asList(folder.listFiles())); 1695 LinkedList<File> files = new LinkedList<File>(); 1696 String res = "org" + File.separator + "expeditee" + File.separator + "assets" + File.separator + "resources"; 1697 int resLength = res.length(); 1698 1699 while (items.size() > 0) { 1700 File file = items.remove(0); 1701 if(file.isFile()) { 1702 if(!file.getName().contains(".svn")) { 1703 files.add(file); 1704 } 1705 } else { 1706 if (!file.getName().contains(".svn")) { 1707 items.addAll(Arrays.asList(file.listFiles())); 1708 } 1709 } 1710 } 1711 for (File file : files) { 1712 System.out.println(file.getPath()); 1713 File out = new File(FrameIO.PARENT_FOLDER + file.getPath().substring(file.getPath().indexOf(res) + resLength)); 1714 if(out.exists()) { 1715 continue; 1716 } 1717 out.getParentFile().mkdirs(); 1718 FileOutputStream fOut = null; 1719 FileInputStream fIn = null; 1720 try { 1721 // System.out.println(out.getPath()); 1722 fOut = new FileOutputStream(out); 1723 fIn = new FileInputStream(file); 1724 byte[] bBuffer = new byte[1024]; 1725 int nLen; 1726 while ((nLen = fIn.read(bBuffer)) > 0) { 1727 fOut.write(bBuffer, 0, nLen); 1728 } 1729 fOut.flush(); 1730 } catch (Exception e) { 1731 e.printStackTrace(); 1732 } finally { 1733 if(fOut != null) { 1734 fOut.close(); 1735 } 1736 if(fIn != null) { 1737 fIn.close(); 1738 } 1739 } 1740 1741 } 1730 BryceSaysPleaseNameMe(folder); 1742 1731 } 1743 1732 } … … 1748 1737 } 1749 1738 1750 public static Text getLastEdited(){1751 return LastEdited;1752 }1753 1754 public static Collection<Text> getCurrentTextItems() {1755 Collection<Text> currentTextItems = new LinkedHashSet<Text>();1756 Collection<Item> currentItems = getCurrentItems(null);1757 if (currentItems != null) {1758 for (Item i : getCurrentItems(null)) {1759 if (i instanceof Text && !i.isLineEnd()) {1760 currentTextItems.add((Text) i);1761 }1739 private static void BryceSaysPleaseNameMe(File folder) throws IOException { 1740 LinkedList<File> items = new LinkedList<File>(); 1741 items.addAll(Arrays.asList(folder.listFiles())); 1742 LinkedList<File> files = new LinkedList<File>(); 1743 String res = "org" + File.separator + "expeditee" + File.separator + "assets" + File.separator + "resources"; 1744 int resLength = res.length(); 1745 1746 while (items.size() > 0) { 1747 File file = items.remove(0); 1748 if(file.isFile()) { 1749 if(!file.getName().contains(".svn")) { 1750 files.add(file); 1762 1751 } 1763 } 1764 return currentTextItems; 1765 } 1752 } else { 1753 if (!file.getName().contains(".svn")) { 1754 items.addAll(Arrays.asList(file.listFiles())); 1755 } 1756 } 1757 } 1758 for (File file : files) { 1759 System.out.println(file.getPath()); 1760 File out = new File(FrameIO.PARENT_FOLDER + file.getPath().substring(file.getPath().indexOf(res) + resLength)); 1761 if(out.exists()) { 1762 continue; 1763 } 1764 out.getParentFile().mkdirs(); 1765 FileOutputStream fOut = null; 1766 FileInputStream fIn = null; 1767 try { 1768 // System.out.println(out.getPath()); 1769 fOut = new FileOutputStream(out); 1770 fIn = new FileInputStream(file); 1771 byte[] bBuffer = new byte[1024]; 1772 int nLen; 1773 while ((nLen = fIn.read(bBuffer)) > 0) { 1774 fOut.write(bBuffer, 0, nLen); 1775 } 1776 fOut.flush(); 1777 } catch (Exception e) { 1778 e.printStackTrace(); 1779 } finally { 1780 if(fOut != null) { 1781 fOut.close(); 1782 } 1783 if(fIn != null) { 1784 fIn.close(); 1785 } 1786 } 1787 1788 } 1789 } 1790 1791 public static Text getLastEdited() { 1792 return LastEdited; 1793 } 1794 1795 public static Collection<Text> getCurrentTextItems() { 1796 Collection<Text> currentTextItems = new LinkedHashSet<Text>(); 1797 Collection<Item> currentItems = getCurrentItems(null); 1798 if (currentItems != null) { 1799 for (Item i : getCurrentItems(null)) { 1800 if (i instanceof Text && !i.isLineEnd()) { 1801 currentTextItems.add((Text) i); 1802 } 1803 } 1804 } 1805 return currentTextItems; 1806 } 1766 1807 }
Note:
See TracChangeset
for help on using the changeset viewer.