Changeset 769


Ignore:
Timestamp:
01/28/14 17:52:45 (10 years ago)
Author:
bln4
Message:

When constructing the default frame it now considers the possibility that resources might be in a bundleresource.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/expeditee/gui/FrameUtils.java

    r755 r769  
    99import java.io.FileInputStream;
    1010import java.io.FileOutputStream;
     11import java.io.IOException;
    1112import java.io.InputStream;
    1213import java.net.JarURLConnection;
    1314import java.net.URL;
     15import java.net.URLConnection;
    1416import java.util.ArrayList;
    1517import java.util.Arrays;
     
    5153public class FrameUtils {
    5254
    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.
    58176         */
    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
    79626         */
    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         * } }
    911040         */
    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                            }
    1511534                        }
    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;
    2161623                                }
     1624                            }
     1625                            FrameMouseActions.deleteItems(enclosure, false);
    2171626                        }
    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() {
    16361667                System.out.println("Extracting/Installing resources:");
    16371668                try     {
     
    16891720                               
    16901721                        // 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()));
    16911728                        } else {
    16921729                                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);
    17421731                        }
    17431732                }
     
    17481737        }
    17491738
    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);
    17621751                        }
    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    }
    17661807}
Note: See TracChangeset for help on using the changeset viewer.