Ignore:
Timestamp:
05/10/18 16:04:51 (6 years ago)
Author:
davidb
Message:

Reworking of the code-base to separate logic from graphics. This version of Expeditee now supports a JFX graphics as an alternative to SWING

File:
1 edited

Legend:

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

    r1064 r1102  
    1919package org.expeditee.gui;
    2020
    21 import java.awt.Color;
    22 import java.awt.Image;
    23 import java.awt.Point;
    24 import java.awt.Rectangle;
    25 import java.awt.Toolkit;
    26 import java.awt.datatransfer.Clipboard;
    27 import java.awt.datatransfer.DataFlavor;
    28 import java.awt.datatransfer.Transferable;
    29 import java.awt.event.ActionEvent;
    30 import java.awt.event.ActionListener;
    31 import java.awt.event.KeyEvent;
    3221import java.awt.event.MouseEvent;
    33 import java.awt.event.MouseListener;
    34 import java.awt.event.MouseMotionListener;
    35 import java.awt.event.MouseWheelEvent;
    36 import java.awt.event.MouseWheelListener;
    3722import java.text.NumberFormat;
    3823import java.util.ArrayList;
     
    4530import java.util.List;
    4631import java.util.Set;
    47 import java.util.TimerTask;
    48 
    49 import javax.swing.Timer;
    5032
    5133import org.expeditee.actions.Actions;
    5234import org.expeditee.actions.Misc;
    5335import org.expeditee.actions.Navigation;
     36import org.expeditee.core.AxisAlignedBoxBounds;
     37import org.expeditee.core.Colour;
     38import org.expeditee.core.OSManager;
     39import org.expeditee.core.Point;
     40import org.expeditee.core.swing.SwingConversions;
     41import org.expeditee.gio.gesture.Gesture;
     42import org.expeditee.gio.gesture.GestureListener;
    5443import org.expeditee.gui.indirect.mouse.IndirectMouseActions;
    5544import org.expeditee.gui.indirect.mouse.MouseAction;
     
    7160import org.expeditee.items.UserAppliedPermission;
    7261import org.expeditee.items.XRayable;
    73 import org.expeditee.items.widgets.ButtonWidget;
     62/*import org.expeditee.items.widgets.ButtonWidget; TODO: Reinstate. cts16
    7463import org.expeditee.items.widgets.InteractiveWidget;
    7564import org.expeditee.items.widgets.WidgetCorner;
    76 import org.expeditee.items.widgets.WidgetEdge;
     65import org.expeditee.items.widgets.WidgetEdge;*/
    7766import org.expeditee.settings.UserSettings;
    7867import org.expeditee.settings.experimental.ExperimentalFeatures;
    7968import org.expeditee.stats.SessionStats;
    8069
    81 public class FrameMouseActions implements MouseListener, MouseMotionListener,
    82                 MouseWheelListener {
     70public class FrameMouseActions
     71{
    8372
    8473        private static int _lastMouseClickModifiers = 0;
     
    9281                        @Override
    9382                        public List<Item> exec(MouseInfo info) {
    94                                 //if user is not pointing at something,this is a back
     83                                //if user is not pointing at something, this is a back
    9584                                if (info.isControlDown || info.isShiftDown)
    9685                                        forward();
     
    10594                                // check for TDFC permission
    10695                                if (!info.clicked.hasPermission(UserAppliedPermission.createFrames)) {
    107                                         MessageBay
    108                                                         .displayMessage("Insufficient permission to TDFC (Top Down Frame Creation) from that item");
     96                                        MessageBay.displayMessage("Insufficient permission to TDFC (Top Down Frame Creation) from that item");
    10997                                        return null;
    11098                                }
     
    178166                                copies.add(new Line(d[3], d[0], current.getNextItemID()));
    179167
    180                                 new Constraint(d[0], d[1], current.getNextItemID(),
    181                                                 Constraint.HORIZONTAL);
    182                                 new Constraint(d[2], d[3], current.getNextItemID(),
    183                                                 Constraint.HORIZONTAL);
    184                                 new Constraint(d[1], d[2], current.getNextItemID(),
    185                                                 Constraint.VERTICAL);
    186                                 new Constraint(d[3], d[0], current.getNextItemID(),
    187                                                 Constraint.VERTICAL);
     168                                new Constraint(d[0], d[1], current.getNextItemID(), Constraint.HORIZONTAL);
     169                                new Constraint(d[2], d[3], current.getNextItemID(), Constraint.HORIZONTAL);
     170                                new Constraint(d[1], d[2], current.getNextItemID(), Constraint.VERTICAL);
     171                                new Constraint(d[3], d[0], current.getNextItemID(), Constraint.VERTICAL);
    188172
    189173                                anchor(new ArrayList<Item>(copies));
     
    233217                                Collection<Item> enclosed = getFullyEnclosedItems(info.clickedIn);
    234218                                if (enclosed.size() == 0) {
    235                                         MessageBay
    236                                                         .displayMessage("Insufficient permission to copy items");
     219                                        MessageBay.displayMessage("Insufficient permission to copy items");
    237220                                } else {
    238221                                        copies = copy(enclosed);
     
    308291                                List<Item> copies = new ArrayList<Item>();
    309292                                if (info.clicked != null) {
    310                                         Collection<Item> leftOver = merge(FreeItems
    311                                                         .getInstance(), info.clicked);
     293                                        Collection<Item> leftOver = merge(FreeItems.getInstance(), info.clicked);
    312294                                        anchor(leftOver);
    313295                                }
    314296                                // This is executed when the user is putting down a line
    315297                                // endpoint and unreeling. ie. Normal unreeling
    316                                 copies = ItemUtils.UnreelLine(FreeItems.getInstance(),
    317                                                 _controlDown);
    318 
    319                                 if (copies == null)
    320                                         copies = copy(FreeItems.getInstance());
     298                                copies = ItemUtils.UnreelLine(FreeItems.getInstance(), _controlDown);
     299
     300                                if (copies == null) copies = copy(FreeItems.getInstance());
     301                               
    321302                                anchor(FreeItems.getInstance());
    322                                 for (Item i : copies)
    323                                         i.setOffset(0, 0);
     303                                for (Item i : copies) i.setOffset(0, 0);
    324304                                // need to move to prevent cursor dislocation
    325305                                move(copies);
     
    354334                                                        if (next instanceof Line)
    355335                                                                continue;
    356                                                         double distance = Point.distance(currentX,
    357                                                                         currentY, next.getX(), next.getY());
     336                                                        double distance = Point.distance((int) currentX, (int) currentY, next.getX(), next.getY());
    358337                                                        if (distance < shortestDistance) {
    359338                                                                shortestDistance = distance;
     
    469448                        public List<Item> exec(MouseInfo info) {
    470449                                List<Item> copies = new ArrayList<Item>();
    471                                 Item on = FrameUtils.onItem(DisplayIO.getCurrentFrame(), Math
    472                                                 .round(MouseX), Math.round(MouseY), true);
     450                                Item on = FrameUtils.onItem(DisplayIO.getCurrentFrame(), Math.round(MouseX), Math.round(MouseY), true);
    473451                                // If we have permission to copy this item then pick it up
    474452                                if (on != null && on.isLineEnd()
     
    479457                                }
    480458
    481                                 if (on instanceof WidgetEdge) {
     459/*                              if (on instanceof WidgetEdge) { TODO: Reinstate. cts16
    482460                                        // Don't allow the user to break widget edges.
    483461                                        // Note: had to return here because random dots would
     
    485463                                        // with create line.
    486464                                        return copies;
    487                                 }
     465                                }*/
    488466
    489467                                // if its on a line then split the line and put a point on it and
     
    519497                                List<Item> copies = new ArrayList<Item>();
    520498                                ArrayList<Item> toPickup = new ArrayList<Item>(info.clickedIn.size());
    521                                 for (Item ip : info.clickedIn)
    522                                         if (ip.hasPermission(UserAppliedPermission.full))
    523                                                 toPickup.add(ip);
     499                                for (Item ip : info.clickedIn) {
     500                                        if (ip.hasPermission(UserAppliedPermission.full)) toPickup.add(ip);
     501                                }
    524502                                pickup(toPickup);
    525503                                // otherwise the user is creating a line
     
    532510                                List<Item> items = new ArrayList<Item>();
    533511                                // BROOK: WIDGET RECTANGLES DONT ALLOW DISCONNECTION
    534                                 if (info.clicked instanceof Line && !(info.clicked instanceof WidgetEdge)) {
     512                                if (info.clicked instanceof Line/* && !(info.clicked instanceof WidgetEdge) TODO: Reinstate. cts16*/) {
    535513                                        // Check if within 20% of the end of the line
    536514                                        Line l = (Line) info.clicked;
    537                                         Item toDisconnect = l.getEndPointToDisconnect(_lastMouseClick
    538                                                         .getX(), _lastMouseClick.getY());
     515                                        Item toDisconnect = l.getEndPointToDisconnect(_lastMouseClick.getX(), _lastMouseClick.getY());
    539516
    540517                                        if (toDisconnect == null) {
     
    696673
    697674        public static FrameMouseActions getInstance() {
    698                 if (_instance == null)
    699                         _instance = new FrameMouseActions();
     675                if (_instance == null) _instance = new FrameMouseActions();
     676               
    700677                return _instance;
    701678        }
     
    708685        private static final int MINIMUM_RANGE_DEPRESS_TIME = 250;
    709686
    710         private static final int RECTANGLE_TO_POINT_THRESHOLD = 20;
    711 
    712687        private static Date _lastMouseClickDate = new Date();
    713688
     
    717692
    718693        public static final int BIG_MOUSE_PAUSE = 750;
    719 
    720         public static final int CONTEXT_FREESPACE = 0;
    721 
    722         public static final int CONTEXT_AT_TEXT = 1;
    723 
    724         public static final int CONTEXT_AT_LINE = 2;
    725 
    726         public static final int CONTEXT_AT_DOT = 3;
    727 
    728         public static final int CONTEXT_AT_ENCLOSURE = 4;
    729694
    730695        public static int _alpha = -1;
     
    765730        private static boolean _extrude = false;
    766731
    767         // keeps track of the last highlighted Item
    768         private static Item _lastHighlightedItem = null;
    769 
    770732        // keeps track of the item being 'ranged out' if there is one.
    771733        private static Text _lastRanged = null;
     
    773735        // keeps track of the picture being cropped if there is one
    774736        private static Picture _lastCropped = null;
    775 
    776         // true if lastItem only has highlighting removed when a new item is
    777         // highlighted
    778         private static boolean _lastHoldsHighlight = false;
    779 
    780         private static boolean _forceArrowCursor = true;
    781 
    782         // the current context of the cursor
    783         private static int _context = 0;
    784 
    785         public static void setForceArrow(boolean val) {
    786                 _forceArrowCursor = val;
    787         }
    788737
    789738        public static int getContext() {
     
    807756                                public void actionPerformed(ActionEvent ae) {
    808757                                        // check if we are in free space
    809                                         if (_lastClickedOn == null
    810                                                         && FreeItems.getInstance().size() == 0) {
     758                                        if (_lastClickedOn == null && FreeItems.getInstance().size() == 0) {
    811759                                                // System.out.println("SuperBack!");
    812760                                                _MouseTimer.setDelay(ZERO_MOUSE_PAUSE);
     
    829777                        });
    830778
    831         private static void setPulse(boolean pulseOn) {
    832                 if (_pulseOn == pulseOn) {
    833                         return;
    834                 }
     779        private static void setPulse(boolean pulseOn)
     780        {
     781                if (_pulseOn == pulseOn) return;
     782
    835783                int amount = PULSE_AMOUNT;
    836                 if (!pulseOn) {
    837                         amount *= -1;
    838                         }
     784                if (!pulseOn) amount *= -1;
    839785                _pulseOn = pulseOn;
    840786
     
    859805                                }
    860806                        });
    861 
    862         public void mouseClicked(MouseEvent e) {
    863         }
    864807
    865808        /**
     
    874817
    875818        private void ProccessMousePressedEvent(MouseEvent e, int modifiersEx) {
    876                 // System.out.println("MousePressed " + e.getX() + "," + e.getY() + " "
    877                 // + e.getWhen());
     819                // System.out.println("MousePressed " + e.getX() + "," + e.getY() + " " + e.getWhen());
    878820
    879821                // TODO WHY DID I NOT COMMENT THIS LINE!! MIKE SAYS
    880                 if (LastRobotX != null) {
     822/*              if (LastRobotX != null) {
    881823                        _RobotTimer.stop();
    882824                        LastRobotX = null;
     
    894836                MouseX = panStartX;
    895837                MouseY = panStartY;
    896                 }
     838                }*/
    897839
    898840                // System.out.println(modifiersEx);
    899                 if (_mouseDown == 0)
    900                         _lastMouseClickDate = new Date();
     841                if (_mouseDown == 0) _lastMouseClickDate = new Date();
    901842
    902843                int buttonPressed = e.getButton();
     
    916857                 * backup stack.
    917858                 */
    918                 if (on == null || buttonPressed != MouseEvent.BUTTON1
    919                                 || !on.isFrameName()) {
     859                if (on == null || buttonPressed != MouseEvent.BUTTON1 || !on.isFrameName()) {
    920860                        Navigation.ResetLastAddToBack();
    921861                }
    922862
    923                 SessionStats.MouseClicked(e.getButton());
     863                //SessionStats.MouseClicked(e.getButton());
    924864                if (buttonPressed == MouseEvent.BUTTON1) {
    925                         SessionStats.AddFrameEvent("Ld");
     865                        //SessionStats.AddFrameEvent("Ld");
    926866                        _extrude = false;
    927867                } else if (buttonPressed == MouseEvent.BUTTON2) {
    928                         SessionStats.AddFrameEvent("Md");
     868                        //SessionStats.AddFrameEvent("Md");
    929869                        _extrude = false;
    930870                } else if (buttonPressed == MouseEvent.BUTTON3) {
    931                         SessionStats.AddFrameEvent("Rd");
     871                        //SessionStats.AddFrameEvent("Rd");
    932872
    933873                        // Check if the user picked up a paint brush
    934                         if (FreeItems.getInstance().size() == 1
    935                                         && FreeItems.getItemAttachedToCursor().isAutoStamp()) {
    936                                 int delay = (int) (FreeItems.getItemAttachedToCursor()
    937                                                 .getAutoStamp() * 1000);
     874                        if (FreeItems.getInstance().size() == 1 && FreeItems.getItemAttachedToCursor().isAutoStamp()) {
     875                                int delay = (int) (FreeItems.getItemAttachedToCursor().getAutoStamp() * 1000);
    938876                                if (delay < 10) {
    939877                                        _autoStamp = true;
     
    958896                 */
    959897                if (_lastClickedOn == null && FreeItems.getInstance().size() == 0) {
    960                         // System.out.println(e.getClickCount());
    961898                        if (e.getClickCount() >= 2) {
    962899                                _MouseTimer.start();
    963900                        }
    964                 } else if (_lastClickedOn != null
    965                                 && FreeItems.getInstance().size() == 0
    966                                 && e.getButton() == MouseEvent.BUTTON3) {
     901                } else if (     _lastClickedOn != null &&
     902                                        FreeItems.getInstance().size() == 0 &&
     903                                        e.getButton() == MouseEvent.BUTTON3)
     904                {
    967905                        _ExtrudeMouseTimer.start();
    968 
    969906                } else {
    970907                        _MouseTimer.start();
     
    994931                        _isDelete = false;
    995932                        _isNoOp = true;
    996                 } else
     933                } else {
    997934                        _isDelete = false;
     935                }
    998936
    999937                // This must happen before the previous code
    1000938                // This is when the user is anchoring something
    1001                 if (buttonPressed != MouseEvent.BUTTON1
    1002                                 && (_context == CONTEXT_FREESPACE || _context == CONTEXT_AT_ENCLOSURE)
    1003                                 && FreeItems.itemsAttachedToCursor()) {
    1004                         FrameGraphics.changeHighlightMode(_lastHighlightedItem,
    1005                                         Item.HighlightMode.None);
     939                if (    buttonPressed != MouseEvent.BUTTON1 &&
     940                                (_context == CONTEXT_FREESPACE || _context == CONTEXT_AT_ENCLOSURE) &&
     941                                FreeItems.hasItemsAttachedToCursor())
     942                {
     943                        FrameGraphics.changeHighlightMode(_lastHighlightedItem, Item.HighlightMode.None);
    1006944
    1007945                        _lastHighlightedItem = FreeItems.getItemAttachedToCursor();
     
    1010948                        }
    1011949                        FrameGraphics.Repaint();
    1012                         // this is when the user is picking something up
     950                // this is when the user is picking something up
    1013951                } else if (_lastHighlightedItem != null) {
    1014952                        if (!(_lastHighlightedItem instanceof Line)) {
    1015                                 _lastHighlightedItem
    1016                                                 .setHighlightColor(Item.DEPRESSED_HIGHLIGHT);
     953                                _lastHighlightedItem.setHighlightColor(Item.DEPRESSED_HIGHLIGHT);
    1017954                        } else {
    1018955                                for (Item i : _lastHighlightedItem.getAllConnected()) {
     
    1027964                        _lastRanged = (Text) on;
    1028965                        // set start-drag point
    1029                         _lastRanged.setSelectionStart(DisplayIO.getMouseX(),
    1030                                         FrameMouseActions.getY());
     966                        _lastRanged.setSelectionStart(DisplayIO.getMouseX(), DisplayIO.getMouseY());
    1031967                }
    1032968
     
    1040976                }
    1041977
    1042                 if (on != null && on instanceof Picture
    1043                                 && e.getButton() == MouseEvent.BUTTON3 && !_isDelete) {
     978                if (on != null && on instanceof Picture && e.getButton() == MouseEvent.BUTTON3 && !_isDelete) {
    1044979                        _lastCropped = (Picture) on;
    1045980                        // set start crop point
    1046                         _lastCropped.setStartCrop(DisplayIO.getMouseX(), FrameMouseActions
    1047                                         .getY());
     981                        _lastCropped.setStartCrop(DisplayIO.getMouseX(), DisplayIO.getMouseY());
    1048982                        _lastCropped.setShowCrop(true);
    1049983                }
     
    1055989                // System.out.println("Released " + e.getX() + "," + e.getY() + " " +
    1056990                // e.getWhen());
    1057                 FrameUtils.ResponseTimer.restart();
     991//              FrameUtils.ResponseTimer.restart();
    1058992                _autoStampTimer.stop();
    1059993                _autoStamp = false;
     
    1063997                // the user probably wants to click away the popup - therefore ignore
    1064998                // the event
    1065                 boolean shouldConsume = PopupManager.getInstance()
    1066                                 .shouldConsumeBackClick();
     999/*              boolean shouldConsume = PopupManager.getInstance().shouldConsumeBackClick(); TODO: Reinstate. cts16
    10671000                PopupManager.getInstance().hideAutohidePopups();
    10681001                if (shouldConsume && e.getButton() == MouseEvent.BUTTON1) {
    10691002                        return; // consume back click event
    1070                 }
     1003                }*/
    10711004
    10721005                // _lastMovedDistance = new Point(e.getX() - _lastMouseClick.getX(), e
     
    10841017                // They are probably trying to pick something up in this case
    10851018                if (lastRanged != null) {
    1086                         long depressTime = (new Date()).getTime()
    1087                                         - _lastMouseClickDate.getTime();
     1019                        long depressTime = (new Date()).getTime() - _lastMouseClickDate.getTime();
    10881020                        // double changeInDistance =
    10891021                        // e.getPoint().distance(_currentMouseClick.getPoint());
     
    10921024                        // System.out.println(depressTime);
    10931025
    1094                         if (depressTime < MINIMUM_RANGE_DEPRESS_TIME
    1095                                         || lastRanged.getSelectionSize() <= 0) {// Text.MINIMUM_RANGED_CHARS)
     1026                        if (depressTime < MINIMUM_RANGE_DEPRESS_TIME || lastRanged.getSelectionSize() <= 0) {// Text.MINIMUM_RANGED_CHARS)
    10961027                                // {
    10971028                                lastRanged.clearSelection();
     
    11451076
    11461077                        if (_lastHighlightedItem != null)
    1147                                 FrameGraphics.changeHighlightMode(_lastHighlightedItem,
    1148                                                 Item.HighlightMode.None);
    1149 
    1150                         if (FreeItems.itemsAttachedToCursor()) {
     1078                                FrameGraphics.changeHighlightMode(_lastHighlightedItem, Item.HighlightMode.None);
     1079
     1080                        if (FreeItems.hasItemsAttachedToCursor()) {
    11511081                                move(FreeItems.getInstance());
    11521082                        }
     
    11741104                                        lastRanged.replaceSelectedText(((Text) i).getText());
    11751105                                        FreeItems.getInstance().clear();
    1176                                 } else
     1106                                } else {
    11771107                                        lastRanged.cutSelectedText();
     1108                                }
    11781109                                lastRanged.clearSelection();
    11791110                                FrameGraphics.Repaint();
     
    12311162                                // Check if the user is trying to range an item for which they
    12321163                                // do not have permission to do so... or it is the frame name
    1233                                 if (!lastRanged.hasPermission(UserAppliedPermission.full)
    1234                                                 || lastRanged.isFrameName()) {
    1235                                         MessageBay
    1236                                                         .displayMessage("Insufficient permission to cut text");
     1164                                if (!lastRanged.hasPermission(UserAppliedPermission.full) || lastRanged.isFrameName()) {
     1165                                        MessageBay.displayMessage("Insufficient permission to cut text");
    12371166                                        lastRanged.clearSelection();
    12381167                                        FrameGraphics.Repaint();
     
    12411170                                // if the entire text is selected and its not a line end then
    12421171                                // pickup the item
    1243                                 boolean entireText = lastRanged.getSelectionSize() == lastRanged
    1244                                                 .getLength();
     1172                                boolean entireText = lastRanged.getSelectionSize() == lastRanged.getLength();
    12451173                                if (entireText && !lastRanged.isLineEnd()) {
    12461174                                        lastRanged.clearSelection();
     
    12621190                                // do not have permission to do so... or it is the frame name
    12631191                                if (!lastRanged.hasPermission(UserAppliedPermission.copy)) {
    1264                                         MessageBay
    1265                                                         .displayMessage("Insufficient permission to copy text");
     1192                                        MessageBay.displayMessage("Insufficient permission to copy text");
    12661193                                        lastRanged.clearSelection();
    12671194                                        FrameGraphics.Repaint();
     
    12721199
    12731200                        ranged.setParent(null);
    1274                         ranged.setPosition(DisplayIO.getMouseX(), FrameMouseActions.getY());
     1201                        ranged.setPosition(DisplayIO.getMouseX(), DisplayIO.getMouseY());
    12751202                        pickup(ranged);
    12761203                        lastRanged.clearSelection();
     
    13031230                                // MIKE put the code below up here
    13041231                                _lastCropped.clearCropping();
    1305                                 FrameGraphics.changeHighlightMode(_lastCropped,
    1306                                                 HighlightMode.None);
     1232                                FrameGraphics.changeHighlightMode(_lastCropped, HighlightMode.None);
    13071233                                _lastCropped = null;
    13081234                                FrameGraphics.Repaint();
     
    13411267
    13421268                // error, we should have returned by now
    1343                 System.out.println("Error: mouseReleased should have returned by now. "
    1344                                 + e);
     1269                System.out.println("Error: mouseReleased should have returned by now. " + e);
    13451270        }
    13461271
     
    13481273         * This method handles all left-click actions
    13491274         */
    1350         private void leftButton(Item clicked, Collection<Item> clickedIn,
    1351                         boolean isShiftDown, boolean isControlDown) {
     1275        private void leftButton(Item clicked, Collection<Item> clickedIn, boolean isShiftDown, boolean isControlDown)
     1276        {
    13521277               
    13531278                //Gets the current frame
     
    13551280               
    13561281                //Checks if the current frame is an overlay
    1357                 if(f.getOverlays() != null && FrameUtils.getCurrentItem() != null){
     1282                if (f.getOverlays() != null && FrameUtils.getCurrentItem() != null) {
    13581283                        Item i = FrameUtils.getCurrentItem();
    13591284                       
    13601285                        //Checks if the item clicked in the overlay is a Rubbish Bin. If it is, delete the item attached to the cursor and return.
    1361                         if(i instanceof WidgetCorner){
     1286/*                      if(i instanceof WidgetCorner){ TODO: Reinstate. cts16
    13621287                               
    13631288                                try{
     
    13751300                                        e.printStackTrace();
    13761301                                }
    1377                         }
     1302                        }*/
    13781303                       
    13791304                        Item on = _lastClickedOn;
     
    13871312                        // Check if the user is nearby another item...
    13881313                        int mouseX = DisplayIO.getMouseX();
    1389                         int mouseY = FrameMouseActions.getY();
     1314                        int mouseY = DisplayIO.getMouseY();
    13901315                        // System.out.println(mouseX + "," + mouseY);
    13911316                        for (Item i : DisplayIO.getCurrentFrame().getItems()) {
     
    14111336               
    14121337                // If the user clicked into a widgets free space...
    1413                 if (clicked == null && _lastClickedIn != null
    1414                                 && _lastClickedIn.size() >= 4) {
     1338                if (clicked == null && _lastClickedIn != null && _lastClickedIn.size() >= 4) {
    14151339
    14161340                        // Check to see if the user clicked into a widgets empty space
    1417                         InteractiveWidget iw = null;
     1341/*                      InteractiveWidget iw = null; TODO: Reinstate. cts16
    14181342
    14191343                        for (Item i : _lastClickedIn) {
     
    14411365                                assert (widgetLink != null);
    14421366                                clicked = widgetLink;
    1443                         } else {
     1367                        } else*/ {
    14441368                                for (Item i : _lastClickedIn) {
    14451369                                        /*
     
    14641388                        Picture clickedOnPicture = (Picture)clicked;
    14651389                        Frame current_frame = DisplayIO.getCurrentFrame();
    1466                         Color bg_col = current_frame.getBackgroundColor();
     1390                        Colour bg_col = current_frame.getBackgroundColor();
    14671391                        if (clickedOnPicture.MouseOverBackgroundPixel(mouseX,mouseY,bg_col)) {
    14681392                                // Make 'clicked' null, effectively causing a back() operation
     
    14751399                        boolean hasLinkOrAction = clicked.hasLink() || clicked.hasAction();
    14761400
    1477                         if ((hasLinkOrAction && !clicked
    1478                                         .hasPermission(UserAppliedPermission.followLinks))
    1479                                         || (!hasLinkOrAction && !clicked
    1480                                                         .hasPermission(UserAppliedPermission.createFrames))) {
     1401                        if ((hasLinkOrAction && !clicked.hasPermission(UserAppliedPermission.followLinks))
     1402                                        || (!hasLinkOrAction && !clicked.hasPermission(UserAppliedPermission.createFrames)))
     1403                        {
    14811404                                Item editTarget = clicked.getEditTarget();
    14821405                                if (editTarget != clicked) {
     
    14841407                                                clicked = editTarget;
    14851408                                        } else {
    1486                                                 MessageBay
    1487                                                                 .displayMessage("Insufficient permission to perform action on item");
     1409                                                MessageBay.displayMessage("Insufficient permission to perform action on item");
    14881410                                                return;
    14891411                                        }
     
    14941416
    14951417                        // actions take priority
    1496                         if (_lastMouseClick != null && !_lastMouseClick.isControlDown()
    1497                                         && clickedOn.hasAction()) {
     1418                        if (_lastMouseClick != null && !_lastMouseClick.isControlDown() && clickedOn.hasAction()) {
    14981419                                IndirectMouseActions.getInstance().getExecuteActionAction().exec(new MouseInfo(clicked, clickedIn, isShiftDown, isControlDown));
    14991420                        } else if (clickedOn.getLink() != null) {
    15001421                                IndirectMouseActions.getInstance().getFollowLinkAction().exec(new MouseInfo(clicked, clickedIn, isShiftDown, isControlDown));
    1501                                 // no link is found, perform TDFC
     1422                        // no link is found, perform TDFC
    15021423                        } else {
    15031424                                /*
     
    15191440        }
    15201441
    1521         private static boolean doMerging(Item clicked) {
    1522                 if (clicked == null)
    1523                         return false;
    1524 
    1525                 // // Brook: widgets do not merge
    1526                 // if (clicked instanceof WidgetCorner)
    1527                 // return false;
    1528                 //
    1529                 // // Brook: widgets do not merge
    1530                 // if (clicked instanceof WidgetEdge)
    1531                 // return false;
    1532 
    1533                 // System.out.println(FreeItems.getInstance().size());
    1534                 if (isRubberBandingCorner()) {
    1535                         if (clicked.isLineEnd()
    1536                                         || clicked.getAllConnected().contains(
    1537                                                         FreeItems.getItemAttachedToCursor())) {
    1538                                 return true;
    1539                         }
    1540                 }
    1541 
    1542                 if (FreeItems.getInstance().size() > 2)
    1543                         return false;
    1544 
    1545                 Item attachedToCursor = FreeItems.getItemAttachedToCursor();
    1546 
    1547                 if (clicked instanceof Text
    1548                                 && !(attachedToCursor instanceof Text || attachedToCursor
    1549                                                 .isLineEnd())) {
    1550                         return false;
    1551                 }
    1552 
    1553                 if (clicked instanceof Picture) {
    1554                         int mouseX = DisplayIO.getMouseX();
    1555                         int mouseY = FrameMouseActions.getY();
    1556                         Picture clickedOnPicture = (Picture)clicked;
    1557                         Frame current_frame = DisplayIO.getCurrentFrame();
    1558                         Color bg_col = current_frame.getBackgroundColor();
    1559                         if (clickedOnPicture.MouseOverBackgroundPixel(mouseX,mouseY,bg_col)) {
    1560                                 // Make 'clicked' null, effectively causing a back() operation
    1561                                 return false;
    1562                         }
    1563                 }
    1564                
    1565                 return true;
    1566         }
    1567 
    15681442        public static void middleButton() {
    15691443                Item currentItem = FrameUtils.getCurrentItem();
     
    15821456        public static void leftButton() {
    15831457                Item currentItem = FrameUtils.getCurrentItem();
    1584                 getInstance().leftButton(currentItem,
    1585                                 FrameUtils.getCurrentItems(currentItem), false, false);
     1458                getInstance().leftButton(currentItem, FrameUtils.getCurrentItems(currentItem), false, false);
    15861459                updateCursor();
    15871460        }
     
    15901463         * This method handles all middle-click actions
    15911464         */
    1592         private void middleButton(Item clicked, Collection<Item> clickedIn,
    1593                         boolean isShiftDown) {
     1465        private void middleButton(Item clicked, Collection<Item> clickedIn, boolean isShiftDown)
     1466        {
    15941467               
    15951468                // If the user clicked into a widgets free space...
     
    15981471
    15991472                        // Check to see if the use clicked into a widgets empty space
    1600                         InteractiveWidget iw = null;
     1473/*                      InteractiveWidget iw = null; TODO: Reinstate. cts16
    16011474
    16021475                        for (Item i : _lastClickedIn) {
     
    16171490                                        return;
    16181491                                }
    1619                         }
     1492                        }*/
    16201493                }
    16211494                // if the cursor has Items attached
    1622                 if (FreeItems.itemsAttachedToCursor()) {
    1623                         // if the user is pointing at something, merge the items (if
    1624                         // possible)
     1495                if (FreeItems.hasItemsAttachedToCursor()) {
     1496                        // if the user is pointing at something, merge the items (if possible)
    16251497                        if (doMerging(clicked)) {
    16261498                                IndirectMouseActions.getInstance().getDeleteItemsAction().exec(new MouseInfo(clicked, clickedIn, false, false));
     
    16351507                                Picture clickedOnPicture = (Picture)clicked;
    16361508                                Frame current_frame = DisplayIO.getCurrentFrame();
    1637                                 Color bg_col = current_frame.getBackgroundColor();
     1509                                Colour bg_col = current_frame.getBackgroundColor();
    16381510                                if (clickedOnPicture.MouseOverBackgroundPixel(mouseX,mouseY,bg_col)) {
    16391511                                        clicked = null; // Effectively make it as if they haven't clicked on anything
     
    16451517                                if (!clicked.hasPermission(UserAppliedPermission.full)) {
    16461518                                        Item editTarget = clicked.getEditTarget();
    1647                                         if (editTarget != clicked
    1648                                                         && editTarget.hasPermission(UserAppliedPermission.full)) {
     1519                                        if (editTarget != clicked && editTarget.hasPermission(UserAppliedPermission.full)) {
    16491520                                                clicked = editTarget;
    16501521                                        } else {
    1651                                                 MessageBay
    1652                                                 .displayMessage("Insufficient permission to pick up item");
     1522                                                MessageBay.displayMessage("Insufficient permission to pick up item");
    16531523                                                return;
    16541524                                        }
     
    16631533                }
    16641534                SessionStats.MovedItems(FreeItems.getInstance());
    1665         }
    1666 
    1667         private static Item getFirstFreeLineEnd() {
    1668                 for (Item i : FreeItems.getInstance())
    1669                         if (i.isLineEnd())
    1670                                 return i;
    1671                 return null;
    1672         }
    1673 
    1674         private static boolean isRubberBandingCorner() {
    1675                 return getShapeCorner(FreeItems.getInstance()) != null;
    1676         }
    1677 
    1678         /**
    1679          * Gets the rectangle corner from the list of items that are part of a
    1680          * rectangle.
    1681          *
    1682          * @param partialRectangle
    1683          *            a corner and its two connecting lines.
    1684          * @return the rectangle corner or null if the list of items is not part of
    1685          *         a rectangle.
    1686          */
    1687         private static Item getShapeCorner(List<Item> partialRectangle) {
    1688                 if (partialRectangle.size() < 3)
    1689                         return null;
    1690                 Item lineEnd = null;
    1691                 // only one lineEnd will be present for rectangles
    1692                 // All other items must be lines
    1693                 for (Item i : partialRectangle) {
    1694                         if (i.isLineEnd()) {
    1695                                 if (lineEnd == null) {
    1696                                         lineEnd = i;
    1697                                 } else {
    1698                                         return null;
    1699                                 }
    1700                         } else if (!(i instanceof Line)) {
    1701                                 return null;
    1702                         }
    1703                 }
    1704                 // if this is at least the corner of two connected lines
    1705                 if (lineEnd != null && lineEnd.getAllConnected().size() >= 5)
    1706                         return lineEnd;
    1707 
    1708                 return null;
    17091535        }
    17101536
     
    17191545
    17201546                        // Check to see if the use clicked into a widgets empty space
    1721                         InteractiveWidget iw = null;
     1547/*                      InteractiveWidget iw = null; TODO: Reinstate. cts16
    17221548
    17231549                        for (Item i : _lastClickedIn) {
     
    17381564                                        return;
    17391565                                }
    1740                         }
     1566                        }*/
    17411567                }
    17421568               
     
    17441570
    17451571                List<Item> copies = null;
    1746                 if (FreeItems.itemsAttachedToCursor()) {
    1747                         if (FreeItems.getInstance().size() == 1
    1748                                         && FreeItems.getItemAttachedToCursor().isAutoStamp()) {
     1572                if (FreeItems.hasItemsAttachedToCursor()) {
     1573                        if (FreeItems.getInstance().size() == 1 && FreeItems.getItemAttachedToCursor().isAutoStamp()) {
    17491574                                // Dont stamp if the user is painting... because we dont want to
    17501575                                // save any of the items created!
    17511576                                return;
    1752                                 // if the user is clicking on something, merge the items
    1753                                 // unless it is a point onto something other than a lineEnd or a
    1754                                 // dot
     1577                        // if the user is clicking on something, merge the items unless
     1578                        // it is a point onto something other than a lineEnd or a dot
    17551579                        } else if (clicked != null
    17561580                        // TODO Change the items merge methods so the logic is simplified
     
    17581582                                                        || clicked instanceof Dot || clicked.isLineEnd())) {
    17591583                                // check permissions
    1760                                 if (!clicked.hasPermission(UserAppliedPermission.full)
    1761                                                 && clicked.getParent().getNameItem() != clicked) {
    1762                                         MessageBay
    1763                                                         .displayMessage("Insufficient permission to merge items");
     1584                                if (!clicked.hasPermission(UserAppliedPermission.full) && clicked.getParent().getNameItem() != clicked) {
     1585                                        MessageBay.displayMessage("Insufficient permission to merge items");
    17641586                                        return;
    17651587                                }
    1766                                 if (clicked instanceof Text || clicked instanceof Dot
    1767                                                 || clicked instanceof XRayable) {
     1588                                if (clicked instanceof Text || clicked instanceof Dot || clicked instanceof XRayable) {
    17681589                                        if (isRubberBandingCorner()) {
    17691590                                                copies = IndirectMouseActions.getInstance().getMergeGroupAction().exec(new MouseInfo(clicked, clickedIn, false, false));
    17701591                                                // line onto something
    1771                                         } else if (FreeItems.getInstance().size() == 2
    1772                                         /* && clicked instanceof XRayable */) {
     1592                                        } else if (FreeItems.getInstance().size() == 2 /* && clicked instanceof XRayable */) {
    17731593                                                copies = IndirectMouseActions.getInstance().getMergeTwoItemsAction().exec(new MouseInfo(clicked, clickedIn, false, false));
    17741594                                        } else if (FreeItems.getInstance().size() == 1) {
     
    17781598                                        }
    17791599                                } else {
    1780                                         copies = ItemUtils.UnreelLine(FreeItems.getInstance(),
    1781                                                         _controlDown);
    1782                                         if (copies == null)
    1783                                                 copies = copy(FreeItems.getInstance());
     1600                                        copies = ItemUtils.UnreelLine(FreeItems.getInstance(), _controlDown);
     1601                                        if (copies == null) copies = copy(FreeItems.getInstance());
    17841602                                        for (Item i : copies) {
    17851603                                                i.setOffset(0, 0);
     
    17891607                                        pickup(copies);
    17901608                                }
    1791                                 // otherwise, anchor the items
     1609                        // otherwise, anchor the items
    17921610                        } else {
    17931611                                // check if this is anchoring a rectangle
     
    18121630                                Picture clickedOnPicture = (Picture)clicked;
    18131631                                Frame current_frame = DisplayIO.getCurrentFrame();
    1814                                 Color bg_col = current_frame.getBackgroundColor();
     1632                                Colour bg_col = current_frame.getBackgroundColor();
    18151633                                if (clickedOnPicture.MouseOverBackgroundPixel(mouseX,mouseY,bg_col)) {
    18161634                                        clicked = null; // Effectively make it as if they haven't clicked on anything
     
    18231641                                if (clicked.isLineEnd()) {
    18241642                                        if (!clicked.hasPermission(UserAppliedPermission.full)) {
    1825                                                 MessageBay
    1826                                                                 .displayMessage("Insufficient permission to unreel");
     1643                                                MessageBay.displayMessage("Insufficient permission to unreel");
    18271644                                                return;
    18281645                                        }
     
    18331650                                                clicked = editTarget;
    18341651                                        } else {
    1835                                                 MessageBay
    1836                                                                 .displayMessage("Insufficient permission to copy");
     1652                                                MessageBay.displayMessage("Insufficient permission to copy");
    18371653                                                return;
    18381654                                        }
     
    18461662                                        // otherwise, create a rectangle
    18471663                                } else {
    1848                                         Item on = FrameUtils.onItem(DisplayIO.getCurrentFrame(),
    1849                                                         MouseX, MouseY, true);
     1664                                        Item on = FrameUtils.onItem(DisplayIO.getCurrentFrame(), MouseX, MouseY, true);
    18501665                                        // if its on a line then create a line from that line
    18511666                                        if (on instanceof Line && on.hasPermission(UserAppliedPermission.full)) {
     
    18601675                updateCursor();
    18611676                FrameGraphics.Repaint();
    1862         }
    1863 
    1864         /**
    1865          *
    1866          */
    1867         private static void stampItemsOnCursor(boolean save) {
    1868                 List<Item> copies = copy(FreeItems.getInstance());
    1869                 // MIKE: what does the below 2 lines do?
    1870                 for (Item i : copies) {
    1871                         i.setOffset(0, 0);
    1872                         i.setSave(save);
    1873                 }
    1874                 // The below code has a little problem withflicker when stamp
    1875                 // and dragging
    1876                 move(FreeItems.getInstance());
    1877                 for (Item i : copies) {
    1878                         i.setHighlightMode(HighlightMode.None);
    1879                 }
    1880                 anchor(copies);
    18811677        }
    18821678
     
    19071703        }
    19081704
    1909         /**
    1910          * Marks the items as not belonging to any specific frame. When picking up
    1911          * items the parent will be automatically cleared for items on the current
    1912          * frame but not for overlay items. This method ensures that overlay items
    1913          * will also be cleared. This is useful when picking up copies of items from
    1914          * an overlay (with the right mouse button) to ensure that the copy will be
    1915          * anchored on the current frame rather than the overlay. When items are
    1916          * picked up with the middle button clearParent should NOT be called.
    1917          *
    1918          * @param items
    1919          *            to have their parent cleared
    1920          */
    1921         private static void clearParent(List<Item> items) {
    1922                 for (Item i : items) {
    1923                         // The next line is only necessary for circles...
    1924                         // Need to clean up/refactory some of this stuff
    1925                         i.getParentOrCurrentFrame().removeItem(i);
    1926                         i.setParent(null);
    1927                 }
    1928         }
    1929 
    1930         private static boolean inWindow = false;
    1931         /**
    1932          * event called when mouse exits window
    1933          * (can't use MouseListener callback since that callback doesn't
    1934          *  correctly receive all mouse exit events)
    1935          */
    1936         public static void mouseExitedWindow(MouseEvent e) {
    1937                 inWindow = false;
    1938                 // System.out.println("Left window");
    1939                 if(FreeItems.itemsAttachedToCursor()) {
    1940                         boolean cut = true;
    1941                         for(Item i : FreeItems.getInstance()) {
    1942                                 for(Item j : i.getAllConnected()) {
    1943                                         if(!FreeItems.getInstance().contains(j)) {
    1944                                                 cut = false;
    1945                                                 break;
    1946                                         }
    1947                                 }
    1948                         }
    1949                         if(cut) {
    1950                                 ItemSelection.cut();
    1951                         }
    1952                 }
    1953         }
    1954        
    1955         public void mouseEntered(MouseEvent e) {
    1956                 // check if we are entering the window from outside of the window, or if we were just over a widget
    1957                 if(!inWindow) {
    1958                         inWindow = true;
    1959                         // if there is expeditee data on the clipboard that has not yet been autoPasted, autoPaste it
    1960                 Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
    1961                 Transferable content = c.getContents(null);
    1962                 try {
    1963                         if(content.isDataFlavorSupported(ItemSelection.expDataFlavor)) {        // Expeditee data
    1964                                 ExpDataHandler expData = (ExpDataHandler)content.getTransferData(ItemSelection.expDataFlavor);
    1965                                 if(expData.autoPaste) {
    1966                                         List<Item> items = new ExpClipReader(FrameMouseActions.getX(), FrameMouseActions.getY()).read(expData.items);
    1967                                         // generate new IDs and pickup
    1968                                         FrameMouseActions.pickup(ItemUtils.CopyItems(items));
    1969                                         // update the clipboard contents so they won't be autoPasted again
    1970                                         expData.autoPaste = false;
    1971                                         String stringData = "";
    1972                                         Image imageData = null;
    1973                                         if(content.isDataFlavorSupported(DataFlavor.stringFlavor)) {
    1974                                                 stringData = (String) content.getTransferData(DataFlavor.stringFlavor);
    1975                                         }
    1976                                         if(content.isDataFlavorSupported(DataFlavor.imageFlavor)) {
    1977                                                 imageData = (Image) content.getTransferData(DataFlavor.imageFlavor);
    1978                                         }
    1979                                         c.setContents(new ItemSelection(stringData, imageData, expData), null);
    1980                                 }
    1981                         }
    1982                 } catch(Exception ex) {
    1983                         ex.printStackTrace();
    1984                 }
    1985                 }
    1986         }
    1987 
    1988         public void mouseExited(MouseEvent e) {
    1989         }
     1705//      public void mouseExited(MouseEvent e) {
     1706//      }
    19901707
    19911708        private boolean _overFrame;
    19921709        private int panStartX, panStartY;
    19931710        private boolean _isPanOp;
     1711       
    19941712        public void mouseDragged(MouseEvent e) {
    19951713                _lastMouseDragged = e;
     
    19981716                // Stop the longDepress mouse timer if the user drags above a threshold
    19991717                if (_MouseTimer.isRunning()) {
    2000                         if (Math.abs(e.getX() - _lastMouseClick.getX())
    2001                                         + Math.abs(e.getY() - _lastMouseClick.getY()) > 10)
     1718                        if (Math.abs(e.getX() - _lastMouseClick.getX()) + Math.abs(e.getY() - _lastMouseClick.getY()) > 10) {
    20021719                                _MouseTimer.stop();
     1720                        }
    20031721                }
    20041722
     
    20071725                }
    20081726
    2009                 /*
    2010                  * Have the free items follow the cursor if the user clicks in freespace
    2011                  * then moves.
    2012                  */
     1727                // Have the free items follow the cursor if the user clicks in freespace then moves.
    20131728                if (FreeItems.getInstance().size() > 0 && _lastClickedOn == null) {
    20141729                        mouseMoved(e);
     
    20171732               
    20181733                // panning the frame when dragging the mouse while shift-leftclicking
    2019                 if(ExperimentalFeatures.MousePan.get() && _overFrame && e.isShiftDown() &&
     1734/*              if(ExperimentalFeatures.MousePan.get() && _overFrame && e.isShiftDown() &&
    20201735                                (e.getModifiersEx() & MouseEvent.BUTTON1_DOWN_MASK) != 0 &&
    2021                                 (_isPanOp || (Math.max(Math.abs(panStartX - e.getX()), Math.abs(panStartY - e.getY())) > 5))) {
     1736                                (_isPanOp || (Math.max(Math.abs(panStartX - e.getX()), Math.abs(panStartY - e.getY())) > 5)))
     1737                {
    20221738                        int dX = (int) (e.getX() - MouseX);
    20231739                        int dY = (int) (e.getY() - MouseY);
     
    20261742                        MouseY = e.getY();
    20271743                        _isPanOp = true;
    2028                 }
     1744                }*/
    20291745
    20301746                // check if user is dragging across a text item
     
    20361752
    20371753                        int distance = _lastRanged.getY() - FrameMouseActions.getY();
    2038                         if (distance <= 0)
    2039                                 distance = FrameMouseActions.getY() - _lastRanged.getY()
    2040                                                 - _lastRanged.getBoundsHeight();
     1754                        if (distance <= 0) distance = FrameMouseActions.getY() - _lastRanged.getY() - _lastRanged.getBoundsHeight();
    20411755
    20421756                        if (distance > UserSettings.NoOpThreshold.get()) {
     
    20451759                        } else {
    20461760                                // update the ranged section
    2047                                 _lastRanged.setSelectionEnd(DisplayIO.getMouseX(),
    2048                                                 FrameMouseActions.getY());
     1761                                _lastRanged.setSelectionEnd(DisplayIO.getMouseX(), DisplayIO.getMouseY());
    20491762                                _isNoOp = false;
    20501763                        }
    20511764
    2052                         DisplayIO.setTextCursor(_lastRanged, Text.NONE, false, e
    2053                                         .isShiftDown(), e.isControlDown(), false);
     1765                        DisplayIO.setTextCursor(_lastRanged, Text.NONE, false, e.isShiftDown(), e.isControlDown(), false);
    20541766                        FrameGraphics.Repaint();
    20551767                        return;
     
    20581770                // if the user is dragging across a picture
    20591771                if (_lastCropped != null) {
    2060                         // If shift is down then the distance moved is the same in the x and
    2061                         // y
     1772                        // If shift is down then the distance moved is the same in the x and y
    20621773                        MouseX = e.getX();
    20631774                        MouseY = e.getY();
     
    20671778                                int deltaY = Math.abs(e.getY() - _lastMouseClick.getY());
    20681779                                if (deltaX > deltaY) {
    2069                                         MouseY = _lastMouseClick.getY() + deltaX
    2070                                                         * (e.getY() > _lastMouseClick.getY() ? 1 : -1);
     1780                                        MouseY = _lastMouseClick.getY() + deltaX * (e.getY() > _lastMouseClick.getY() ? 1 : -1);
    20711781                                } else {
    2072                                         MouseX = _lastMouseClick.getX() + deltaY
    2073                                                         * (e.getX() > _lastMouseClick.getX() ? 1 : -1);
     1782                                        MouseX = _lastMouseClick.getX() + deltaY * (e.getX() > _lastMouseClick.getX() ? 1 : -1);
    20741783                                }
    20751784                        }
    20761785                        // update the ranged section
    2077                         _lastCropped.setEndCrop(DisplayIO.getMouseX(), FrameMouseActions
    2078                                         .getY());
     1786                        _lastCropped.setEndCrop(DisplayIO.getMouseX(), DisplayIO.getMouseY());
    20791787
    20801788                        FrameGraphics.Repaint();
     
    20821790                }
    20831791
    2084                 /*
    2085                  * This is the context of a user clicking in freespace an dragging onto
    2086                  * the edge of a line
    2087                  */
    2088                 if ((_mouseDown == MouseEvent.BUTTON2 || _mouseDown == MouseEvent.BUTTON3)
    2089                                 && _lastClickedOn == null && _lastClickedIn == null) {
    2090                         Item on = FrameUtils.onItem(DisplayIO.getCurrentFrame(), e.getX(),
    2091                                         e.getY(), true);
     1792                // This is the context of a user clicking in freespace an dragging onto
     1793                // the edge of a line
     1794                if (    (_mouseDown == MouseEvent.BUTTON2 || _mouseDown == MouseEvent.BUTTON3) &&
     1795                                _lastClickedOn == null &&
     1796                                _lastClickedIn == null)
     1797                {
     1798                        Item on = FrameUtils.onItem(DisplayIO.getCurrentFrame(), e.getX(), e.getY(), true);
    20921799
    20931800                        if (FreeItems.getInstance().size() == 0) {
     
    21011808                                        on.setHighlightMode(Item.HighlightMode.Normal);
    21021809                                } else if (_lastHighlightedItem != null) {
    2103                                         _lastHighlightedItem
    2104                                                         .setHighlightMode(Item.HighlightMode.None);
     1810                                        _lastHighlightedItem.setHighlightMode(Item.HighlightMode.None);
    21051811                                        _lastHighlightedItem = null;
    21061812                                }
     
    21101816                // Use the below calculation for better speed. If it causes problems
    21111817                // switch back to the Euclidean distance calculation
    2112                 if (Math.abs(MouseX - e.getX()) > UserSettings.NoOpThreshold.get()
    2113                                 || Math.abs(MouseY - e.getY()) > UserSettings.NoOpThreshold.get())
     1818                if (    Math.abs(MouseX - e.getX()) > UserSettings.NoOpThreshold.get() ||
     1819                                Math.abs(MouseY - e.getY()) > UserSettings.NoOpThreshold.get())
     1820                {
    21141821                        _isNoOp = true;
    2115 
     1822                }
     1823               
    21161824                FrameGraphics.Repaint();
    21171825        }
    21181826
    21191827        private static MouseEvent _lastMouseMoved = null;
    2120 
    2121         private static Integer LastRobotX = null;
    2122 
    2123         private static Integer LastRobotY = null;
    2124 
    2125         // For some reason... sometimes the mouse move gets lost when moving the
    2126         // mouse really quickly after clicking...
    2127         // Use this timer to make sure it gets reset eventually if the Robot
    2128         // generated event never arrives.
    2129         private static Timer _RobotTimer = new Timer(200, new ActionListener() {
    2130                 public void actionPerformed(ActionEvent ae) {
    2131                         _RobotTimer.stop();
    2132                         LastRobotX = null;
    2133                         LastRobotY = null;
    2134                         // System.out.println("RobotTimer");
    2135                 }
    2136         });
    21371828
    21381829        private static Timer _autoStampTimer = new Timer(200, new ActionListener() {
     
    21521843        }
    21531844
    2154         public static boolean isControlDown() {
    2155                 return _controlDown;
    2156         }
    2157 
    2158         public static boolean isShiftDown() {
    2159                 return _shiftDown;
    2160         }
    2161 
    2162         public static void setLastRobotMove(float x, float y) {
    2163                 // Make sure the system is in the right state while waiting for the
    2164                 // Robots event to arrive.
    2165                 MouseX = x;
    2166                 MouseY = y;
    2167                 // System.out.println("MouseMoved: " + MouseX + "," + MouseY + " " +
    2168                 // System.currentTimeMillis());
    2169                 LastRobotX = Math.round(x);
    2170                 LastRobotY = Math.round(y);
    2171                 _RobotTimer.start();
    2172         }
    2173 
    2174         public static boolean isWaitingForRobot() {
    2175                 return LastRobotX != null;
    2176         }
    2177 
    21781845        /**
    21791846         * Updates the stored mouse position and highlights any items as necessary.
     
    21831850        }
    21841851
    2185         private void mouseMoved(MouseEvent e, boolean shiftStateChanged) {
    2186                 // System.out.println("mouseMoved");
    2187                 // System.out.println(_context);
    2188                 if (_context == CONTEXT_FREESPACE)
    2189                         FrameKeyboardActions.resetEnclosedItems();
    2190                 // System.out.println(e.getX() + "," + e.getY() + " " + e.getWhen());
    2191                 if (LastRobotX != null) {
    2192                         // Wait until the last Robot mouse move event arrives before
    2193                         // processing other events
    2194                         if (/* FreeItems.getInstance().size() == 0 || */
    2195                         (LastRobotX == e.getX() && LastRobotY == e.getY())) {
    2196                                 LastRobotX = null;
    2197                                 LastRobotY = null;
    2198                                 _RobotTimer.stop();
    2199                         } else {
    2200                                 // System.out.println("Ignored: " +
    2201                                 // FreeItems.getInstance().size());
    2202                                 return;
    2203                         }
    2204                 }
    2205 
    2206                 MouseX = e.getX();
    2207                 MouseY = e.getY();
    2208                
    2209                 // System.out.println(MouseX + "," + MouseY);
    2210 
    2211                 // Moving the mouse a certain distance removes the last edited text if
    2212                 // it is empty
    2213                 Text lastEdited = FrameUtils.getLastEdited();
    2214                 if (lastEdited != null && lastEdited.getText().length() == 0
    2215                                 && lastEdited.getPosition().distance(e.getPoint()) > 20) {
    2216                         FrameUtils.setLastEdited(null);
    2217                 }
    2218 
    2219                 // If shift is down then the movement is constrained
    2220                 if (_controlDown && FreeItems.getInstance().size() > 0) {
    2221                         // Check if we are rubber banding a line
    2222                         if (shiftStateChanged && rubberBanding()) {
    2223                                 // Get the line end that is being rubber banded
    2224                                 Item thisEnd = FreeItems.getInstance().get(0).isLineEnd() ? FreeItems
    2225                                                 .getInstance().get(0)
    2226                                                 : FreeItems.getInstance().get(1);
    2227                                 Line line = (Line) (FreeItems.getInstance().get(0).isLineEnd() ? FreeItems
    2228                                                 .getInstance().get(1)
    2229                                                 : FreeItems.getInstance().get(0));
    2230                                 Item otherEnd = line.getOppositeEnd(thisEnd);
    2231                                 int deltaX = Math.abs(e.getX() - otherEnd.getX());
    2232                                 int deltaY = Math.abs(e.getY() - otherEnd.getY());
    2233                                 // Check if its a vertical line
    2234                                 if (deltaX < deltaY / 2) {
    2235                                         // otherEnd.setX(thisEnd.getX());
    2236                                         // MouseX = otherEnd.getX();
    2237                                         if (shiftStateChanged) {
    2238                                                 new Constraint(thisEnd, otherEnd, thisEnd
    2239                                                                 .getParentOrCurrentFrame().getNextItemID(),
    2240                                                                 Constraint.VERTICAL);
    2241                                         }
    2242                                 }
    2243                                 // Check if its horizontal
    2244                                 else if (deltaY <= deltaX / 2) {
    2245                                         // MouseY = otherEnd.getY();
    2246                                         // otherEnd.setY(thisEnd.getY());
    2247                                         if (shiftStateChanged) {
    2248                                                 new Constraint(thisEnd, otherEnd, thisEnd
    2249                                                                 .getParentOrCurrentFrame().getNextItemID(),
    2250                                                                 Constraint.HORIZONTAL);
    2251                                         }
    2252                                 } else {
    2253                                         // Add DIAGONAL constraints
    2254                                         // if (deltaX > deltaY) {
    2255                                         // otherEnd.setY(thisEnd.getY() + deltaX
    2256                                         // * (e.getY() < otherEnd.getY() ? 1 : -1));
    2257                                         // } else {
    2258                                         // otherEnd.setX(thisEnd.getX() + deltaY
    2259                                         // * (e.getX() < otherEnd.getX() ? 1 : -1));
    2260                                         // }
    2261                                         if (shiftStateChanged) {
    2262                                                 int constraint = Constraint.DIAGONAL_NEG;
    2263                                                 // Check if the slope is positive
    2264                                                 if ((thisEnd.getY() - otherEnd.getY())
    2265                                                                 / (double) (thisEnd.getX() - otherEnd.getX()) > 0.0) {
    2266                                                         constraint = Constraint.DIAGONAL_POS;
    2267                                                 }
    2268 
    2269                                                 new Constraint(thisEnd, otherEnd, thisEnd
    2270                                                                 .getParentOrCurrentFrame().getNextItemID(),
    2271                                                                 constraint);
    2272                                         }
    2273                                 }
    2274                         }// If its a lineend attached to two lines lengthen the shorter
    2275                         // so it is the same length as the longer line
    2276                         else if (FreeItems.getInstance().size() == 3) {
    2277                                 // check if we are rubber banding the corner of a shape
    2278                                 Item thisEnd = getShapeCorner(FreeItems.getInstance());
    2279                                 if (thisEnd != null) {
    2280                                         Line line1 = thisEnd.getLines().get(0);
    2281                                         Line line2 = thisEnd.getLines().get(1);
    2282                                         // Check if the two lines are constrained and hence it is a
    2283                                         // rectangle
    2284                                         Integer c1 = line1.getPossibleConstraint();
    2285                                         Integer c2 = line2.getPossibleConstraint();
    2286 
    2287                                         if (c1 != null && c2 != null) {
    2288                                                 // This is the case of a constrained rectangle
    2289                                                 if ((c2 == Constraint.VERTICAL || c2 == Constraint.HORIZONTAL)
    2290                                                                 && (c1 == Constraint.VERTICAL || c1 == Constraint.HORIZONTAL)
    2291                                                                 && (c1 != c2)) {
    2292                                                         Line vLine = line2;
    2293                                                         Line hLine = line1;
    2294                                                         if (c1 == Constraint.VERTICAL) {
    2295                                                                 vLine = line1;
    2296                                                                 hLine = line2;
    2297                                                         }
    2298                                                         Item hOtherEnd = hLine.getOppositeEnd(thisEnd);
    2299                                                         Item vOtherEnd = vLine.getOppositeEnd(thisEnd);
    2300 
    2301                                                         double vLength = Math
    2302                                                                         .abs(vOtherEnd.getY() - MouseY);
    2303                                                         double hLength = Math
    2304                                                                         .abs(hOtherEnd.getX() - MouseX);
    2305 
    2306                                                         if (vLength > hLength) {
    2307                                                                 MouseX = Math.round(hOtherEnd.getX() + vLength
    2308                                                                                 * (MouseX > hOtherEnd.getX() ? 1 : -1));
    2309                                                         } else /* if (hLength > vLength) */{
    2310                                                                 MouseY = Math.round(vOtherEnd.getY() + hLength
    2311                                                                                 * (MouseY > vOtherEnd.getY() ? 1 : -1));
    2312                                                         }
    2313                                                 }
    2314                                                 // } else if (c2 != null) {
    2315                                                 //
    2316                                                 // } // Other wise it is a not constrained shape so
    2317                                                 // constrain
    2318                                                 // the two lines lengths to be equal
    2319                                         } else {
    2320                                                 Item lineEnd1 = line1.getOppositeEnd(thisEnd);
    2321                                                 Item lineEnd2 = line2.getOppositeEnd(thisEnd);
    2322                                                 double l1 = Line.getLength(lineEnd1.getPosition(), e
    2323                                                                 .getPoint());
    2324                                                 double l2 = Line.getLength(lineEnd2.getPosition(), e
    2325                                                                 .getPoint());
    2326                                                 double l3 = Line.getLength(lineEnd1.getPosition(),
    2327                                                                 lineEnd2.getPosition());
    2328                                                 // l1 needs to be the shorter end
    2329                                                 if (l1 > l2) {
    2330                                                         Item temp = lineEnd1;
    2331                                                         lineEnd1 = lineEnd2;
    2332                                                         lineEnd2 = temp;
    2333                                                         double tempL = l1;
    2334                                                         l1 = l2;
    2335                                                         l2 = tempL;
    2336                                                 }
    2337                                                 // Now use the cosine rule to calculate the angle
    2338                                                 // between l1 and l3
    2339                                                 double cosTheta = (l1 * l1 + l3 * l3 - l2 * l2)
    2340                                                                 / (2 * l1 * l3);
    2341                                                 // now calculate the new length for the lines using cos
    2342                                                 // rule
    2343                                                 double l_new = l3 / (2 * cosTheta);
    2344                                                 double ratio = l_new / l1;
    2345                                                 MouseX = Math.round((e.getX() - lineEnd1.getX())
    2346                                                                 * ratio)
    2347                                                                 + lineEnd1.getX();
    2348                                                 MouseY = Math.round((e.getY() - lineEnd1.getY())
    2349                                                                 * ratio)
    2350                                                                 + lineEnd1.getY();
    2351 
    2352                                         }
    2353                                 }
    2354                         }
    2355                 } else if (shiftStateChanged && !_controlDown && rubberBanding()) {
    2356                         // Get the line end that is being rubber banded
    2357                         Item thisEnd = FreeItems.getInstance().get(0).isLineEnd() ? FreeItems
    2358                                         .getInstance().get(0)
    2359                                         : FreeItems.getInstance().get(1);
    2360                         thisEnd.removeAllConstraints();
    2361                 }
    2362 
    2363                 if (_lastMouseMoved == null)
    2364                         _lastMouseMoved = e;
    2365 
    2366                 _lastMouseMoved = e;
    2367 
    2368                 refreshHighlights();
    2369 
    2370                 if (FreeItems.hasCursor()) {
    2371                         move(FreeItems.getCursor(), true);
    2372                 }
    2373 
    2374                 if (FreeItems.itemsAttachedToCursor()) {
    2375                         move(FreeItems.getInstance());
    2376                         // System.out.println(FreeItems.getInstance().size());
    2377                 }
    2378 
    2379                 if (_forceArrowCursor)
    2380                         updateCursor();
    2381 
    2382                 _forceArrowCursor = true;
    2383         }
    2384 
    23851852       
    2386         public void refreshHighlights() {
    2387                 // ByMike: Get the item the mouse is hovering over
    2388                 Item click = FrameUtils.getCurrentItem();
    2389                 Item on = null;
    2390                 // System.out.println(click);
    2391                 if (click != null) {
    2392                         on = click;
    2393                         // set the context
    2394                         if (on instanceof Line)
    2395                                 _context = CONTEXT_AT_LINE;
    2396                         else if (on instanceof Dot)
    2397                                 _context = CONTEXT_AT_DOT;
    2398                         else if (on instanceof Text) {
    2399                                 _context = CONTEXT_AT_TEXT;
    2400                         }
    2401                         if (FreeItems.getInstance().size() > 0)
    2402                                 _alpha = 60;
    2403                         else
    2404                                 _alpha = -1;
    2405                 } else {
    2406                         _context = CONTEXT_FREESPACE;
    2407                         _alpha = -1;
    2408                 }
    2409 
    2410                 // if the user is pointing at an item, highlight it
    2411                 if (on != null && !FreeItems.getInstance().contains(on)) {
    2412                         // if the user can spot-weld, show the virtual spot
    2413                         if (FreeItems.getInstance().size() == 2 && on instanceof Line) {
    2414                                 Line line = (Line) on;
    2415                                 Item freeItem0 = FreeItems.getInstance().get(0);
    2416                                 Item freeItem1 = FreeItems.getInstance().get(1);
    2417                                 Item lineEnd = freeItem0.isLineEnd() ? freeItem0 : (freeItem1
    2418                                                 .isLineEnd() ? freeItem1 : null);
    2419                                 if (lineEnd != null) {
    2420                                         if (_mouseDown == 0)
    2421                                                 line.showVirtualSpot(lineEnd, DisplayIO.getMouseX(),
    2422                                                                 FrameMouseActions.getY());
    2423                                 } else
    2424                                         // The user is pointing at another point or text item
    2425                                         // etc
    2426                                         FrameGraphics.changeHighlightMode(on,
    2427                                                         Item.HighlightMode.Normal);
    2428                         } else {
    2429                                 // FrameGraphics.ChangeSelectionMode(on,
    2430                                 // Item.SelectedMode.Connected);
    2431                                 // TODO: The method below is for the most part redundant                               
    2432                                
    2433                                 on = FrameGraphics.Highlight(on.getEditTarget());
    2434                         }
    2435                         // if the last item highlighted is still highlighted, clear it
    2436                         if (_lastHoldsHighlight) {
    2437                                 _lastHoldsHighlight = false;
    2438                                 for (Item i : DisplayIO.getCurrentFrame().getItems())
    2439                                         if (i.isHighlighted() && i != on)
    2440                                                 FrameGraphics.changeHighlightMode(i,
    2441                                                                 Item.HighlightMode.None);
    2442                         }
    2443 
    2444                         // if the user is not pointing at an item, check for enclosure
    2445                         // highlighting
    2446                 } else if (on == null) {
    2447                         Collection<Item> enclosure = FrameUtils.getEnclosingLineEnds();
    2448                         if (enclosure != null && enclosure.size() > 0) {
    2449                                 Item firstLineEnd = enclosure.iterator().next();
    2450                                 HighlightMode hm;
    2451                                 if(isShiftDown()) {
    2452                                         hm = HighlightMode.Connected;
    2453                                 } else {
    2454                                         hm = HighlightMode.Enclosed;
    2455                                 }
    2456                                 if (firstLineEnd.getLines().size() > 1 &&
    2457                                 // check that the enclosure is not part of a point being
    2458                                                 // dragged in space
    2459                                                 !ContainsOneOf(enclosure, FreeItems.getInstance())) {
    2460                                         on = firstLineEnd.getLines().get(0);
    2461                                         // System.out.println(on == null ? "Null" :
    2462                                         // on.toString());
    2463                                         FrameGraphics.changeHighlightMode(on, hm);
    2464                                 } else if (firstLineEnd instanceof XRayable) {
    2465                                         on = firstLineEnd;
    2466                                         FrameGraphics.changeHighlightMode(firstLineEnd, hm);
    2467                                 }
    2468                                 _context = CONTEXT_AT_ENCLOSURE;
    2469                         } else if (_lastHighlightedItem != null) {
    2470                                 // System.out.println("LastHighlightedItem");
    2471                                 _lastHoldsHighlight = false;
    2472                         }
    2473                 }
    2474 
    2475                 // disable cursor changes when the cursor has items attached
    2476                 if (FreeItems.itemsAttachedToCursor()
    2477                                 && DisplayIO.getCursor() != Item.TEXT_CURSOR)
    2478                         _forceArrowCursor = false;
    2479 
    2480                 // setLastHighlightedItem(on);
    2481 
    2482                 if (_lastHighlightedItem != null && _lastHighlightedItem != on
    2483                                 && !_lastHoldsHighlight) {
    2484                         // Turn off the highlighting only if
    2485                         // the last highlighted item is not connected to the currentItem
    2486                         // Otherwise we get flickering in transition from connected to
    2487                         // normal mode while moving the cursor along a line.
    2488                         if (on == null
    2489                                         || (!on.getAllConnected().contains(_lastHighlightedItem))) {
    2490                                 FrameGraphics.changeHighlightMode(_lastHighlightedItem,
    2491                                                 Item.HighlightMode.None);
    2492                         }
    2493                 }
    2494 
    2495                 _lastHighlightedItem = on;
    2496 
    2497         }
    2498 
    2499         private boolean ContainsOneOf(Collection<Item> enclosure,
    2500                         Collection<Item> freeItems) {
    2501                 if (freeItems == null)
    2502                         return false;
    2503                 for (Item i : freeItems) {
    2504                         if (enclosure.contains(i))
    2505                                 return true;
    2506                 }
    2507                 return false;
    2508         }
    2509 
    2510         /**
    2511          * Checks if lines are being rubber banded.
    2512          *
    2513          * @return true if the user is rubberBanding one or more lines
    2514          */
    2515         private static boolean rubberBanding() {
    2516                 if (FreeItems.getInstance().size() != 2) {
    2517                         return false;
    2518                 }
    2519 
    2520                 // if rubber-banding, there will be 1 lineend and the rest will be lines
    2521                 boolean foundLineEnd = false;
    2522                 for (Item i : FreeItems.getInstance()) {
    2523                         if (i.isLineEnd()) {
    2524                                 if (foundLineEnd) {
    2525                                         return false;
    2526                                 }
    2527                                 foundLineEnd = true;
    2528                         } else if (!(i instanceof Line) || !i.isVisible()) {
    2529                                 return false;
    2530                         }
    2531                 }
    2532                 return true;
    2533         }
    2534 
    2535         /**
    2536          * Updates the current mouse cursor to whatever it should be. i.e. Hidden
    2537          * when rubber-banding lines, otherwise default (arrow)
    2538          */
    2539         public static void updateCursor() {
    2540                 if (rubberBanding()) {
    2541                         DisplayIO.setCursor(Item.HIDDEN_CURSOR);
    2542                         return;
    2543                 }
    2544                 // This is to make sure the TEXT_CURSOR doesnt get inadvertantly turned
    2545                 // off!
    2546                 Item on = FrameUtils.getCurrentItem();
    2547                 if (on != null && on instanceof Text) {
    2548                         return;
    2549                 }
    2550                 DisplayIO.setCursor(Item.DEFAULT_CURSOR);
    2551         }
    2552 
    2553         public static void setHighlightHold(boolean hold) {
    2554                 _lastHoldsHighlight = hold;
    2555         }
    2556 
    2557         public static void resetOffset() {
    2558                 if (FreeItems.itemsAttachedToCursor()) {
    2559                         _offX = DisplayIO.getMouseX()
    2560                                         - FreeItems.getInstance().get(0).getX()
    2561                                         + FreeItems.getInstance().get(0).getOffset().x;
    2562                         _offY = getY() - FreeItems.getInstance().get(0).getY()
    2563                                         + FreeItems.getInstance().get(0).getOffset().y;
    2564                 }
    2565         }
    2566 
    2567         /**
    2568          * Moves the items to the current mouse position (plus the current offset)
    2569          *
    2570          * @param toMove
    2571          */
    2572         static void move(Collection<Item> toMove) {
    2573                 move(toMove, false);
    2574         }
    2575 
    2576         static void move(Collection<Item> toMove, boolean cursor) {
    2577 
    2578                 // Gets the origin of the first item to move
    2579                 int xPos = (DisplayIO.getMouseX() - (cursor ? 0 : _offX));
    2580 
    2581                 Item firstDot = toMove.iterator().next();
    2582 
    2583                 int deltax = firstDot.getX() - xPos;
    2584                 int deltay = firstDot.getY() - (getY() - (cursor ? 0 : _offY));
    2585 
    2586                 for (Item move : toMove) {
    2587                         move.setPosition(move.getX() - deltax, move.getY() - deltay);
    2588 
    2589                         if (!cursor && move instanceof Text) {
    2590                                 ((Text) move).setAlpha(_alpha);
    2591                         }
    2592                 }
    2593 
    2594                 FrameGraphics.requestRefresh(true);
    2595                 // FrameGraphics.refresh(true);
    2596         }
    2597 
    2598         private static void load(String toLoad, boolean addToHistory) {
    2599                 if (FrameIO.isValidFrameName(toLoad)) {
    2600                         DisplayIO.clearBackedUpFrames();
    2601                         FrameUtils.DisplayFrame(toLoad, addToHistory, true);
    2602                 } else {
    2603                         MessageBay.errorMessage(toLoad + " is not a valid frame name.");
    2604                 }
    2605         }
    2606 
    2607         private static void back() {
    2608                 DisplayIO.Back();
    2609 
    2610                 // repaint things if necessary
    2611                 if (FreeItems.itemsAttachedToCursor())
    2612                         move(FreeItems.getInstance());
    2613 
    2614                 if (FreeItems.hasCursor())
    2615                         move(FreeItems.getCursor(), true);
    2616         }
    2617 
    2618         private static void forward() {
    2619                 DisplayIO.Forward();
    2620 
    2621                 // repaint things if necessary
    2622                 if (FreeItems.itemsAttachedToCursor())
    2623                         move(FreeItems.getInstance());
    2624 
    2625                 if (FreeItems.hasCursor())
    2626                         move(FreeItems.getCursor(), true);
    2627         }
    2628 
    2629         /**
    2630          * Returns true if the mouse moved during TDFC. This will happen if there is
    2631          * a start annotation item on the frame.
    2632          *
    2633          * @param linker
    2634          * @return
    2635          */
    2636         public static boolean tdfc(Item linker) throws RuntimeException {
    2637                 // if this is a non-usable item
    2638                 if (linker.getID() < 0)
    2639                         return false;
    2640 
    2641                 // Check if its an image that can be resized to fit a box
    2642                 // around it
    2643                 String text = linker.getText();
    2644                 boolean isVector = text.equals("@v") || text.equals("@av");
    2645                 boolean isFrameImage = text.equals("@f");
    2646                 boolean isBitmap = false; // text.equals("@b");
    2647 
    2648                 if (isVector || isFrameImage || isBitmap) {
    2649                         Collection<Item> enclosure = FrameUtils.getEnclosingLineEnds(linker
    2650                                         .getPosition());
    2651                         if (enclosure != null) {
    2652                                 for (Item i : enclosure) {
    2653                                         if (i.isLineEnd() && i.isEnclosed()) {
    2654                                                 if (!isVector)
    2655                                                         DisplayIO.getCurrentFrame().removeAllItems(
    2656                                                                         enclosure);
    2657                                                 Rectangle rect = i.getEnclosedRectangle();
    2658                                                 long width = Math.round(rect.getWidth());
    2659                                                 if (isVector) {
    2660                                                         NumberFormat nf = Vector.getNumberFormatter();
    2661                                                         linker.setText(linker.getText()
    2662                                                                         + ": "
    2663                                                                         + nf.format((width / FrameGraphics
    2664                                                                                         .getMaxFrameSize().getWidth())));
    2665                                                 } else {
    2666                                                         linker.setText(linker.getText() + ": " + width);
    2667                                                 }
    2668 
    2669                                                 linker.setPosition(new Point(rect.x, rect.y));
    2670                                                 linker.setThickness(i.getThickness());
    2671                                                 linker.setBorderColor(i.getColor());
    2672                                                 break;
    2673                                         }
    2674                                 }
    2675                                 if (!isVector)
    2676                                         FrameMouseActions.deleteItems(enclosure, false);
    2677                         }
    2678                 }
    2679 
    2680                 boolean mouseMoved;
    2681 
    2682                 linker.getParent().setChanged(true);
    2683 
    2684                 Frame next = FrameIO.CreateNewFrame(linker, _onFrameAction);
    2685 
    2686                 linker.setLink("" + next.getNumber());
    2687 
    2688                 for (Item i : next.getTextItems()) {
    2689                         // Set the link for @Parent annotation item if one
    2690                         if (ItemUtils.startsWithTag(i, ItemUtils.TAG_PARENT)
    2691                                         && i.getLink() == null) {
    2692                                 Frame parent = linker.getParentOrCurrentFrame();
    2693                                 i.setLink(parent.getName());
    2694                         } else if (ItemUtils.startsWithTag(i, ItemUtils.TAG_BACKUP, false)) {
    2695                                 // Delink backup tag if it is on the frame
    2696                                 i.setLink(null);
    2697                         }
    2698                 }
    2699 
    2700                 FrameUtils.DisplayFrame(next, true, true);
    2701                 FrameUtils.setTdfcItem(linker);
    2702 
    2703                 mouseMoved = next.moveMouseToDefaultLocation();
    2704                 // this needs to be done if the user doesnt move the mouse before doing
    2705                 // tdfc while the cursor is set to the text cursor
    2706                 DisplayIO.setCursor(Item.DEFAULT_CURSOR);
    2707                 // This needs to be done in case there was a @start on the frame which
    2708                 // triggers changed to be set to true when it should stay as false
    2709                 next.setChanged(false);
    2710                 return mouseMoved;
    2711         }
    2712 
    2713         /**
    2714          * Creates a new Text item and fills it with particular attributes extracted
    2715          * from the given Item. Note: Users always have permission to extract
    2716          * attributes, so it is not checked.
    2717          *
    2718          * @param toExtract
    2719          *            Item containing the Item to extract the attributes from.
    2720          */
    2721         private static void extractAttributes(Item toExtract) {
    2722                 if (toExtract == null || toExtract == null)
    2723                         return;
    2724 
    2725                 if (FreeItems.itemsAttachedToCursor())
    2726                         return;
    2727 
    2728                 Item attribs;
    2729                 Item item = toExtract;
    2730                 // Extract the frames attributes when the user clicks on the frame name
    2731                 FrameGraphics.changeHighlightMode(item, HighlightMode.None);
    2732                 if (item.isFrameName())
    2733                         attribs = AttributeUtils.extractAttributes(item.getParent());
    2734                 else {
    2735                         attribs = AttributeUtils.extractAttributes(item);
    2736                 }
    2737 
    2738                 if (attribs == null)
    2739                         MessageBay
    2740                                         .displayMessage("All attributes of that item are default values.");
    2741                 else {
    2742                         // Give the attribute text item the color of the item for which
    2743                         // attributes are being extracted.
    2744                         // attribs.setColor(item.getColor());
    2745                         pickup(attribs);
    2746                 }
    2747         }
    2748 
    2749         public static void delete(Item toDelete) {
    2750                 boolean bRecalculate = false;
    2751 
    2752                 FrameUtils.setLastEdited(null);
    2753                 _offX = _offY = 0;
    2754 
    2755                 Frame currentFrame = DisplayIO.getCurrentFrame();
    2756                 // check if the user is pointing at the frame's framename
    2757                 if (toDelete != null && toDelete == currentFrame.getNameItem()) {
    2758                         currentFrame.clear(false);
    2759                         FrameGraphics.Repaint();
    2760                         return;
    2761                 }
    2762 
    2763                 // if the user is deleting items attached to the cursor
    2764                 if (FreeItems.itemsAttachedToCursor()) {
    2765                         // if this is an item-swap
    2766                         if (FreeItems.getInstance().size() == 1
    2767                                         && FreeItems.getInstance().get(0) instanceof Text
    2768                                         && toDelete != null && toDelete instanceof Text) {
    2769 
    2770                                 // check permissions
    2771                                 if (!toDelete.hasPermission(UserAppliedPermission.full)) {
    2772                                         MessageBay
    2773                                                         .displayMessage("Insufficient permission to swap Item text");
    2774                                         return;
    2775                                 }
    2776                                 Text anchored = (Text) toDelete;
    2777                                 Text free = (Text) FreeItems.getInstance().get(0);
    2778                                 SessionStats.DeletedItem(free);
    2779                                 // List<String> temp = anchored.getText();
    2780                                 anchored.setText(free.getText());
    2781                                 anchored.setFormula(free.getFormula());
    2782 
    2783                                 // free.setTextList(temp);
    2784                                 FreeItems.getInstance().clear();
    2785 
    2786                                 anchored.getParent().setChanged(true);
    2787 
    2788                                 bRecalculate |= free.recalculateWhenChanged();
    2789                                 bRecalculate |= anchored.recalculateWhenChanged();
    2790 
    2791                                 // update the offset since the text has changed
    2792                                 _offX = DisplayIO.getMouseX() - anchored.getX()
    2793                                                 + anchored.getOffset().x;
    2794                                 _offY = getY() - anchored.getY() + anchored.getOffset().y;
    2795                         } else {
    2796                                 // if shift is pressed delete the entire shape attached to the dot
    2797                                 if(isShiftDown()) {
    2798                                 List<Item> tmp = new ArrayList<Item>(FreeItems.getInstance());
    2799                                 for(Item i : tmp) {
    2800                                         // remove entire rectangles instead of just the corner
    2801                                         if(i instanceof Dot) {
    2802                                                 FreeItems.getInstance().addAll(i.getAllConnected());
    2803                                                 for(Item j : i.getAllConnected()) {
    2804                                                         if(j instanceof Dot) {
    2805                                                                 FreeItems.getInstance().addAll(j.getLines());
    2806                                                         }
    2807                                                 }
    2808                                         }
    2809                                 }
    2810                                 }
    2811                                 deleteItems(FreeItems.getInstance());
    2812                         }
    2813                         // reset the mouse cursor
    2814                         updateCursor();
    2815                         // the user is not pointing at an item
    2816                 } else if (toDelete == null) {
    2817                
    2818                         // if the user is pointing inside a closed shape, delete it
    2819                        
    2820                         Collection<Item> items = null;
    2821                         // if shift is down, only delete the enclosing shape (ignore the items inside)
    2822                         if(isShiftDown()) {
    2823                                 Collection<Item> tmp = FrameUtils.getEnclosingLineEnds();
    2824                                 if(tmp != null) {
    2825                                         items = new ArrayList<Item>();
    2826                                         items.addAll(tmp);
    2827                                 for(Item i : tmp) {
    2828                                         if(i instanceof Dot) {
    2829                                                 items.addAll(((Dot)i).getLines());
    2830                                         }
    2831                                 }
    2832                                 }
    2833                         } else {
    2834                                 items = FrameUtils.getCurrentItems(null);
    2835                         }
    2836                        
    2837                         if (items != null) {
    2838                                 Collection<Item> toRemove = new LinkedHashSet<Item>(items
    2839                                                 .size());
    2840                                 for (Item ip : items) {
    2841                                         if (ip.hasPermission(UserAppliedPermission.full)) {
    2842                                                 // Only include lines if one of their enpoints are also
    2843                                                 // being removed
    2844                                                 if (ip instanceof Line) {
    2845                                                         Line l = (Line) ip;
    2846                                                         Item end = l.getEndItem();
    2847                                                         Item start = l.getStartItem();
    2848 
    2849                                                         // If one end of a line is being deleted, remove the
    2850                                                         // other end if all its connecting lines are being
    2851                                                         // deleted
    2852                                                         if (items.contains(end)) {
    2853                                                                 if (!items.contains(start)
    2854                                                                                 && items.containsAll(start.getLines())) {
    2855                                                                         toRemove.add(start);
    2856                                                                 }
    2857                                                         } else if (items.contains(start)) {
    2858                                                                 if (items.containsAll(end.getLines())) {
    2859                                                                         toRemove.add(end);
    2860                                                                 }
    2861                                                         } else {
    2862                                                                 continue;
    2863                                                         }
    2864                                                 }
    2865                                                 toRemove.add(ip);
    2866                                         }
    2867                                 }
    2868 
    2869                                 deleteItems(toRemove);
    2870 
    2871                                 // reset the mouse cursor
    2872                                 updateCursor();
    2873                                 FrameGraphics.Repaint();
    2874 
    2875                                 // otherwise this is an undo command
    2876                         } else {
    2877                                 if(isControlDown()) {
    2878                                         DisplayIO.getCurrentFrame().redo();
    2879                                 } else {
    2880                                         DisplayIO.getCurrentFrame().undo();
    2881                                 }
    2882                         }
    2883                         return;
    2884                         // this is a delete command
    2885                 } else {
    2886                        
    2887                         // Special case if toDelete item is an image: only want to delete if over non-background pixel color
    2888                         if (toDelete instanceof Picture) {
    2889                                 int mouseX = DisplayIO.getMouseX();
    2890                                 int mouseY = FrameMouseActions.getY();
    2891                                 Picture clickedOnPicture = (Picture)toDelete;
    2892                                 Frame current_frame = DisplayIO.getCurrentFrame();
    2893                                 Color bg_col = current_frame.getBackgroundColor();
    2894                                 if (clickedOnPicture.MouseOverBackgroundPixel(mouseX,mouseY,bg_col)) {
    2895                                         // behave as if Redo/Undo request, then return
    2896                                         if(isControlDown()) {
    2897                                                 DisplayIO.getCurrentFrame().redo();
    2898                                         } else {
    2899                                                 DisplayIO.getCurrentFrame().undo();
    2900                                         }
    2901                                         return;
    2902                                 }
    2903                                 // If get to here, then user clicked on an image (non-trival pixel color),
    2904                                 // so go ahead and let it be deleted in the usual way
    2905                         }
    2906                                
    2907                        
    2908                         // check permissions
    2909                         if (!toDelete.hasPermission(UserAppliedPermission.full)) {
    2910                                 Item editTarget = toDelete.getEditTarget();
    2911                                 if (editTarget != toDelete
    2912                                                 && editTarget.hasPermission(UserAppliedPermission.full)) {
    2913                                         toDelete = editTarget;
    2914                                 } else {
    2915                                         MessageBay
    2916                                                         .displayMessage("Insufficient permission to delete item");
    2917                                         return;
    2918                                 }
    2919                         }
    2920 
    2921                         Frame parent = toDelete.getParent();
    2922                         if (parent != null) {
    2923                                 parent.setChanged(true);
    2924                         }
    2925                         Collection<Item> toUndo = null;
    2926                         if (toDelete.isLineEnd()) {
    2927                                 // delete the entire connected shape if shift is down
    2928                                 if(isShiftDown()) {
    2929                                         List<Item> tmp = new ArrayList<Item>();
    2930                                         tmp.add(toDelete);
    2931                                         // remove entire shape instead of just the corner
    2932                                         tmp.addAll(toDelete.getAllConnected());
    2933                                         for(Item j : toDelete.getAllConnected()) {
    2934                                                 if(j instanceof Dot) {
    2935                                                         tmp.addAll(j.getLines());
    2936                                                 }
    2937                                         }
    2938                                         deleteItems(tmp);
    2939                                         return;
    2940                                 } else {
    2941                                         toUndo = deleteLineEnd(toDelete);
    2942                                 }
    2943                                 // delete the entire connected shape if shift is down, unless we're hovering the end of the line
    2944                         } else if (toDelete instanceof WidgetEdge) { // must notify
    2945                                 // widgets that they
    2946                                 // are being deleted
    2947                                 ((WidgetEdge) toDelete).getWidgetSource().onDelete();
    2948                                 toUndo = toDelete.getConnected();
    2949                         } else if (toDelete instanceof Line && isShiftDown() ||
    2950                                         toDelete.getHighlightMode() == Item.HighlightMode.Disconnect) {
    2951                                 Line line = (Line) toDelete;
    2952                                 Item start = line.getStartItem();
    2953                                 Item end = line.getEndItem();
    2954                                 Collection<Item> delete = new LinkedList<Item>();
    2955                                 delete.add(toDelete);
    2956                                 if (end.getLines().size() == 1) {
    2957                                         delete.add(end);
    2958                                 } else {
    2959                                         end.removeLine(line);
    2960                                 }
    2961                                 if (start.getLines().size() == 1) {
    2962                                         delete.add(start);
    2963                                 } else {
    2964                                         start.removeLine(line);
    2965                                 }
    2966                                 toUndo = delete;
    2967                         } else {
    2968                                 bRecalculate |= toDelete.recalculateWhenChanged();
    2969                                 toUndo = toDelete.getConnected(); // copy(toDelete.getConnected());
    2970                         }
    2971                         SessionStats.DeletedItems(toUndo);
    2972                         if (parent != null) {
    2973                                 parent.addToUndoDelete(toUndo);
    2974                                 parent.removeAllItems(toUndo); // toDelete.getConnected()
    2975                         }
    2976                         // reset the mouse cursor
    2977                         updateCursor();
    2978                         if (parent != null)
    2979                                 // ItemUtils.EnclosedCheck(parent.getItems());
    2980                                 ItemUtils.Justify(parent);
    2981                         if (toDelete.hasOverlay()) {
    2982                                 FrameUtils.Parse(parent, false, false);
    2983                                 FrameGraphics.requestRefresh(false);
    2984                         }
    2985 
    2986                         DisplayIO.setCursor(Item.DEFAULT_CURSOR);
    2987 
    2988                 }
    2989 
    2990                 currentFrame.notifyObservers(bRecalculate);
    2991 
    2992                 FrameGraphics.Repaint();
    2993         }
    2994 
    2995         public static void deleteItems(Collection<Item> itemList) {
    2996                 deleteItems(itemList, true);
    2997         }
    2998 
    2999         public static void deleteItems(Collection<Item> itemList, boolean addToUndo) {
    3000                 boolean bReparse = false;
    3001                 boolean bRecalculate = false;
    3002 
    3003                 SessionStats.DeletedItems(itemList);
    3004                 List<Frame> modifiedFrames = new LinkedList<Frame>();
    3005                 // Get a list of all the modified frames
    3006                 for (Item i : itemList) {
    3007                         Frame parent = i.getParent();
    3008                         if (parent != null)
    3009                                 modifiedFrames.add(parent);
    3010                         i.setHighlightMode(HighlightMode.None);
    3011                         bReparse |= i.hasOverlay();
    3012                         bRecalculate |= i.recalculateWhenChanged();
    3013                 }
    3014                 // If they are all free items then add the current frame
    3015                 if (modifiedFrames.size() == 0) {
    3016                         modifiedFrames.add(DisplayIO.getCurrentFrame());
    3017                 }
    3018 
    3019                 Collection<Item> toUndo = new LinkedHashSet<Item>();
    3020                 // disconnect any connected items
    3021                 for (Item i : itemList) {
    3022 
    3023                         // Only delete the current item if have not already deleted.
    3024                         // This is especially important for heavy duty widgets - so they
    3025                         // do not have to expire several times per delete.
    3026                         if (toUndo.contains(i))
    3027                                 continue;
    3028 
    3029                         // Make sure text items attached to cursor are reset back to the
    3030                         // transparency they should have.
    3031                         if (i instanceof Text) {
    3032                                 ((Text) i).setAlpha(-1);
    3033                         }
    3034 
    3035                         if (i.getLines().size() > 0) {
    3036 
    3037                                 Collection<Item> toDelete = deleteLineEnd(i);
    3038                                 if (addToUndo) {
    3039                                         // add the copied items to the undo stack
    3040                                         for (Item itemToUndo : toDelete) {
    3041 
    3042                                                 if (!toUndo.contains(itemToUndo))
    3043                                                         toUndo.add(itemToUndo);
    3044 
    3045                                         }
    3046                                 }
    3047                         } else if (!toUndo.contains(i)) {
    3048                                 if (addToUndo)
    3049                                         toUndo.add(i); // Why was is this a copy
    3050                         }
    3051                 }
    3052 
    3053                 for (Frame f : modifiedFrames) {
    3054                         f.removeAllItems(itemList);
    3055                         // ItemUtils.EnclosedCheck(f.getItems());
    3056                         ItemUtils.Justify(f);
    3057                 }
    3058                 // TODO: How should undelete deal with undo when items are removed from
    3059                 // the current frame as well as the overlay frame
    3060                 Frame currentFrame = DisplayIO.getCurrentFrame();
    3061                 currentFrame.addToUndoDelete(itemList);
    3062                 itemList.clear();
    3063                 if (bReparse) {
    3064                         FrameUtils.Parse(currentFrame, false, false);
    3065                         /*
    3066                          * TODO check if I need to recalculate even if reparse occurs, here
    3067                          * and in anchor, pickup etc
    3068                          */
    3069                 } else {
    3070                         currentFrame.notifyObservers(bRecalculate);
    3071                 }
    3072 
    3073         }
    3074 
    3075         private static Collection<Item> deleteLineEnd(Item lineEnd) {
    3076 
    3077                 if (lineEnd instanceof WidgetCorner) { // Brook
    3078 
    3079                         WidgetCorner wc = (WidgetCorner) lineEnd;
    3080                         Frame parent = wc.getWidgetSource().getParentFrame();
    3081 
    3082                         // Remove from the parent frame
    3083                         if (parent != null) {
    3084                                 parent.removeAllItems(wc.getWidgetSource().getItems());
    3085                         }
    3086 
    3087                         wc.getWidgetSource().onDelete(); // Changes the widgets
    3088                         // corner/edges ID's...
    3089 
    3090                         return wc.getWidgetSource().getItems();
    3091 
    3092                 } else {
    3093 
    3094                         // // create a backup copy of the dot and its lines
    3095                         // List<Item> copy = copy(lineEnd.getConnected());
    3096                         //                     
    3097                         // // Remove lines from their anchored dots
    3098                         // // note: the line is kept so that it can be properly restored
    3099                         // for (Item ic : copy) {
    3100                         // if (ic instanceof Line) {
    3101                         // Line line = (Line) ic;
    3102                         // // Remove the line from the item that is not the copy of the
    3103                         // // line end being deletedF
    3104                         // if (!copy.contains(line.getStartItem()))
    3105                         // line.getStartItem().removeLine(line);
    3106                         // if (!copy.contains(line.getEndItem()))
    3107                         // line.getEndItem().removeLine(line);
    3108                         // }
    3109                         // }
    3110 
    3111                         Collection<Item> copy = lineEnd.getConnected();
    3112 
    3113                         // remove all lines being deleted
    3114                         for (Item ic : lineEnd.getConnected()) {
    3115                                 if (ic instanceof Line
    3116                                                 && ((Line) ic).getOppositeEnd(lineEnd) != null) {
    3117                                         Line line = (Line) ic;
    3118 
    3119                                         // Invalidate the line to make sure we dont get any ghost
    3120                                         // arrowheads.
    3121                                         ic.invalidateAll();
    3122 
    3123                                         Item d = line.getOppositeEnd(lineEnd);
    3124                                         d.removeLine(line);
    3125 
    3126                                         // if the dot was only part of one line, it can be
    3127                                         // removed
    3128                                         if (d.getLines().size() == 0) {
    3129                                                 if (d.getParent() != null)
    3130                                                         d.getParent().removeItem(d);
    3131                                                 if (!copy.contains(d))
    3132                                                         copy.add(d);
    3133                                         }
    3134 
    3135                                         if (lineEnd.getParent() != null)
    3136                                                 lineEnd.getParent().removeItem(ic);
    3137                                 }
    3138                         }
    3139                         return copy;
    3140                 }
    3141         }
    3142 
    3143         private static void removeAllLinesExcept(Item from, Item but) {
    3144                 List<Line> lines = new LinkedList<Line>();
    3145                 lines.addAll(from.getLines());
    3146                 for (Line line : lines)
    3147                         if (line.getOppositeEnd(from) != but)
    3148                                 from.removeLine(line);
    3149 
    3150                 List<Constraint> consts = new LinkedList<Constraint>();
    3151                 consts.addAll(from.getConstraints());
    3152                 for (Constraint c : consts)
    3153                         if (c.getOppositeEnd(from) != but)
    3154                                 from.removeConstraint(c);
    3155         }
    3156 
    3157         public static Collection<Item> merge(List<Item> merger, Item mergee) {
    3158                 assert (mergee != null);
    3159                 if (mergee.isFrameName()) {
    3160                         return mergee.getParent().merge(merger);
    3161                 }
    3162 
    3163                 // if(mergee instanceof XRayable)
    3164                 // return merger;
    3165 
    3166                 // check for rectangle merging
    3167                 if (merger.size() == 3 && mergee.getLines().size() == 2) {
    3168                         Item corner = getShapeCorner(merger);
    3169                         // if this is a corner of a shape
    3170                         if (corner != null) {
    3171                                 Collection<Item> allConnected = corner.getAllConnected();
    3172                                 // Check if we are collapsing a rectangle
    3173                                 if (allConnected.size() == 8 && allConnected.contains(mergee)) {
    3174                                         DisplayIO.setCursorPosition(mergee.getPosition());
    3175                                         DisplayIO.getCurrentFrame().removeAllItems(allConnected);
    3176 
    3177                                         // find the point opposite corner...
    3178                                         Item opposite = null;
    3179                                         List<Line> lines = corner.getLines();
    3180                                         for (Line l : lines) {
    3181                                                 allConnected.remove(l.getOppositeEnd(corner));
    3182                                         }
    3183                                         allConnected.remove(corner);
    3184                                         for (Item i : allConnected) {
    3185                                                 if (i.isLineEnd()) {
    3186                                                         opposite = i;
    3187                                                         break;
    3188                                                 }
    3189                                         }
    3190                                         assert (opposite != null);
    3191 
    3192                                         // check if the rectangle is small enough that it should be
    3193                                         // collapsed to a single point
    3194                                         int x1 = Math.abs(opposite.getX() - mergee.getX());
    3195                                         int x2 = Math.abs(opposite.getY() - mergee.getY());
    3196                                         int distance = (int) Math.sqrt(Math.pow(x1, 2)
    3197                                                         + Math.pow(x2, 2));
    3198 
    3199                                         if (distance < RECTANGLE_TO_POINT_THRESHOLD) {
    3200                                                 mergee.removeAllConstraints();
    3201                                                 mergee.removeAllLines();
    3202                                                 mergee.setThickness(4 * mergee.getThickness());
    3203                                                 return mergee.getAllConnected();
    3204                                         } else {
    3205                                                 removeAllLinesExcept(mergee, opposite);
    3206                                                 removeAllLinesExcept(opposite, mergee);
    3207 
    3208                                                 return mergee.getAllConnected();
    3209                                         }
    3210                                 }
    3211                         }
    3212                 }
    3213 
    3214                 List<Item> remain = new ArrayList<Item>();
    3215                 Item res = null;
    3216 
    3217                 for (Item i : merger) {                 
    3218                         if (!i.isVisible())
    3219                                 continue;
    3220                         // check for link merging
    3221                         if (i instanceof Text
    3222                                         && FrameIO.isValidFrameName((((Text) i).getFirstLine()))
    3223                                         && FrameIO.canAccessFrame((((Text) i).getFirstLine()))) {
    3224                                 // check that we can actually access the frame this link
    3225                                 // corresponds to
    3226                                 mergee.setLink(((Text) i).getFirstLine());
    3227                         } else {
    3228                                 // check for attribute merging
    3229                                 if (i instanceof Text && !i.isLineEnd()) {
    3230                                         Text txt = (Text) i;
    3231 
    3232                                         // if this is not an attribute merge
    3233                                         if (!AttributeUtils.setAttribute(mergee, txt)) {
    3234                                                 // set mouse position for text merges
    3235                                                 if (mergee instanceof Text) {
    3236                                                         ((Text) mergee).insertText(txt.getText(), DisplayIO
    3237                                                                         .getMouseX(), FrameMouseActions.getY());
    3238                                                         //Delete the item which had its text merged
    3239                                                         txt.delete();
    3240                                                         return remain;
    3241                                                 } else if (mergee instanceof WidgetCorner) {
    3242                                                         if (merger.size() == 1 && txt.getLink() != null) {
    3243                                                                 // If the text item is linked then use that
    3244                                                                 ((WidgetCorner) mergee).setLink(txt
    3245                                                                                 .getAbsoluteLink(), txt);
    3246                                                         } else {
    3247                                                                 remain.addAll(merger);
    3248                                                         }
    3249                                                         return remain;
    3250                                                 } else if (mergee instanceof WidgetEdge) {
    3251                                                         if (merger.size() == 1 && txt.getLink() != null) {
    3252                                                                 // If the text item is linked then use that
    3253                                                                 ((WidgetEdge) mergee).setLink(txt
    3254                                                                                 .getAbsoluteLink(), txt);
    3255                                                         } else {
    3256                                                                 remain.addAll(merger);
    3257                                                         }
    3258                                                         return remain;
    3259                                                 } else if (mergee instanceof Dot) {
    3260                                                         DisplayIO.setCursorPosition(mergee.getPosition());
    3261                                                         txt.setPosition(mergee.getPosition());
    3262                                                         txt.setThickness(mergee.getThickness());
    3263                                                         Frame parent = mergee.getParent();
    3264                                                         parent.removeItem(mergee);
    3265                                                         anchor(txt);
    3266                                                         // change the end points of the lines to the text
    3267                                                         // item
    3268                                                         while (mergee.getLines().size() > 0) {
    3269                                                                 Line l = mergee.getLines().get(0);
    3270                                                                 l.replaceLineEnd(mergee, txt);
    3271                                                         }
    3272                                                         break;
    3273                                                 }
    3274 
    3275                                                 // TODO tidy this up...
    3276                                                 // Dot override doesnt use the x and y coords
    3277                                                 // Text does... but could be removed
    3278                                                 res = mergee.merge(i, DisplayIO.getMouseX(), getY());
    3279                                                 if (res != null) {
    3280                                                         remain.add(res);
    3281                                                 }
    3282                                         }
    3283                                 } else {
    3284                                         if (mergee.isLineEnd()) {
    3285                                                 DisplayIO.setCursorPosition(mergee.getPosition());
    3286                                         }
    3287                                         // Moving the cursor ensures shapes are anchored correctly
    3288                                         res = mergee.merge(i, DisplayIO.getMouseX(), getY());
    3289                                         if (res != null)
    3290                                                 remain.addAll(res.getConnected());
    3291 
    3292                                 }
    3293                         }
    3294                 }
    3295                 updateCursor();
    3296 
    3297                 mergee.getParent().setChanged(true);
    3298 
    3299                 ItemUtils.EnclosedCheck(mergee.getParent().getItems());
    3300                 // Mike: Why does parse frame have to be called?!?
    3301                 FrameUtils.Parse(mergee.getParent());
    3302 
    3303                 return remain;
    3304         }
    3305 
    3306         /**
    3307          * Picks up an item on a frame.
    3308          *
    3309          * @param toGrab
    3310          *            item to be picked up
    3311          * @param removeItem
    3312          *            true if the item should be removed from the frame
    3313          */
    3314         public static void pickup(Item toGrab) {
    3315                 if (toGrab.isFrameName())
    3316                         return;
    3317 
    3318                 if (!toGrab.hasPermission(UserAppliedPermission.full)) {
    3319                         if (toGrab.getEditTarget() != toGrab) {
    3320                                 pickup(toGrab.getEditTarget());
    3321                         } else {
    3322                                 MessageBay
    3323                                                 .displayMessage("Insufficient permission pickup the item");
    3324                         }
    3325                         return;
    3326                 }
    3327 
    3328                 if (toGrab instanceof Circle)
    3329                         toGrab.setHighlightMode(HighlightMode.Connected);
    3330                 // Dont set the highlight mode if a vector is being picked up
    3331                 else if (toGrab.isVisible()) {
    3332                         toGrab.setHighlightMode(HighlightMode.Normal);
    3333                 }
    3334 
    3335                 // Brook: If the widget corner is being picked up. Instead refer to
    3336                 // picking up the edge for fixed-sized widgets so it is not so confusing
    3337                 if (toGrab instanceof WidgetCorner) {
    3338                         WidgetCorner wc = (WidgetCorner) toGrab;
    3339                         if (wc.getWidgetSource().isFixedSize()) {
    3340                                 for (Item i : toGrab.getConnected()) {
    3341                                         if (i instanceof WidgetEdge) {
    3342                                                 toGrab = i;
    3343                                                 break;
    3344                                         }
    3345                                 }
    3346                         }
    3347                 }
    3348                 pickup(toGrab.getConnected());
    3349         }
    3350 
    3351         public static void pickup(Collection<Item> toGrab) {
    3352                 if (toGrab == null || toGrab.size() == 0)
    3353                         return;
    3354 
    3355                 boolean bReparse = false;
    3356                 boolean bRecalculate = false;
    3357 
    3358                 Frame currentFrame = DisplayIO.getCurrentFrame();
    3359                 String currentFrameName = currentFrame.getName();
    3360                 Iterator<Item> iter = toGrab.iterator();
    3361                 while (iter.hasNext()) {
    3362                         Item i = iter.next();
    3363                         if (!i.hasPermission(UserAppliedPermission.full)) {
    3364                                 iter.remove();
    3365                                 continue;
    3366                         }
    3367                         if (i.equals(_lastHighlightedItem))
    3368                                 _lastHighlightedItem = null;
    3369 
    3370                         bRecalculate |= i.recalculateWhenChanged();
    3371                         // i.setSelectedMode(SelectedMode.None);
    3372                         // Check if it has a relative link if so make it absolute
    3373                         i.setAbsoluteLink();
    3374                         // parent may be null
    3375                         if (i.getParent() != null) {
    3376                                 i.getParent().removeItem(i);
    3377                                 if (currentFrameName.equals(i.getParent().getName()))
    3378                                         i.setParent(null);
    3379                         }
    3380                         FreeItems.getInstance().add(i);
    3381                         i.setFloating(true);
    3382                         // If its a vector pick up a copy of the stuff on the vector frame
    3383                         if (i.hasVector()) {
    3384                                 bReparse = true;
    3385 
    3386                                 Frame overlayFrame = FrameIO.LoadFrame(i.getAbsoluteLink());
    3387                                 Collection<Item> copies = ItemUtils.CopyItems(overlayFrame
    3388                                                 .getNonAnnotationItems(false), i.getVector());
    3389                                 for (Item copy : copies) {
    3390                                         FreeItems.getInstance().add(copy);
    3391                                         copy.setEditTarget(i);
    3392                                         copy.setFloating(true);
    3393                                         copy.setParent(null);
    3394                                         // copy.setHighlightMode(HighlightMode.Connected);
    3395                                 }
    3396                         }
    3397                 }
    3398                 currentFrame.change();
    3399 
    3400                 _lastHighlightedItem = null;
    3401                 updateCursor();
    3402 
    3403                 // if there are multiple items in the list, determine which to use for
    3404                 // offset calculations
    3405                 if (toGrab.size() > 1) {
    3406                         for (Item i : toGrab) {
    3407                                 // MIKE: Movement goes haywire if these are removed because Line
    3408                                 // class returns 0 for getX
    3409                                 if (!(i instanceof Line) && !(i instanceof XRayable)) {
    3410                                         _offX = DisplayIO.getMouseX() - i.getX() + i.getOffset().x;
    3411                                         _offY = getY() - i.getY() + i.getOffset().y;
    3412 
    3413                                         // make the offset item the first item in the list (so
    3414                                         // move method knows which item to use)
    3415                                         FreeItems.getInstance().set(
    3416                                                         FreeItems.getInstance().indexOf(i),
    3417                                                         FreeItems.getInstance().get(0));
    3418                                         FreeItems.getInstance().set(0, i);
    3419                                         break;
    3420                                 }
    3421                         }
    3422 
    3423                         move(FreeItems.getInstance());
    3424                         ItemUtils.EnclosedCheck(toGrab);
    3425                         // otherwise, just use the first item
    3426                 } else if (toGrab.size() == 1) {
    3427                         Item soleItem = toGrab.iterator().next();
    3428                         _offX = DisplayIO.getMouseX() - soleItem.getX()
    3429                                         + soleItem.getOffset().x;
    3430                         _offY = getY() - soleItem.getY() + soleItem.getOffset().y;
    3431                         // Now call move so that if we are on a message in the message box
    3432                         // It doesnt appear up the top of the scree!!
    3433                         move(toGrab);
    3434                 } else {
    3435                         MessageBay
    3436                                         .displayMessage("Insufficient permission to pickup the items");
    3437                 }
    3438                 if (bReparse)
    3439                         FrameUtils.Parse(currentFrame, false, false);
    3440                 else
    3441                         currentFrame.notifyObservers(bRecalculate);
    3442 
    3443                 FrameGraphics.Repaint();
    3444         }
    3445 
    3446         private static Line createLine() {
    3447                 Frame current = DisplayIO.getCurrentFrame();
    3448                 // create the two endpoints
    3449                 Item end = DisplayIO.getCurrentFrame().createDot();
    3450                 Item start = DisplayIO.getCurrentFrame().createDot();
    3451 
    3452                 // create the Line
    3453                 Line line = new Line(start, end, current.getNextItemID());
    3454                 line.autoArrowheadLength();
    3455 
    3456                 // anchor the start
    3457                 anchor(start);
    3458 
    3459                 // attach the line to the cursor
    3460                 pickup(end);
    3461                 _lastHighlightedItem = null;
    3462 
    3463                 // TODO figure out how to get the end to highlight
    3464                 // end.setSelectedMode(SelectedMode.Normal);
    3465                 // end.setSelectedMode(SelectedMode.None);
    3466 
    3467                 return line;
    3468         }
    3469 
    3470         /**
    3471          * Returns a list of copies of the list passed in
    3472          *
    3473          * @param toCopy
    3474          *            The list of items to copy
    3475          * @return A List of copied Items
    3476          */
    3477         private static List<Item> copy(Collection<Item> toCopy) {
    3478                 return ItemUtils.CopyItems(toCopy);
    3479         }
    3480 
    3481         public static void anchor(Item toAnchor, boolean checkEnclosure) {
    3482                 // Only anchor items we have full permission over... i.e. don't anchor vector items
    3483                 if (!toAnchor.hasPermission(UserAppliedPermission.full))
    3484                         return;
    3485 
    3486                 toAnchor.anchor();
    3487 
    3488                 if (checkEnclosure) {
    3489                         ItemUtils.EnclosedCheck(toAnchor.getParentOrCurrentFrame()
    3490                                         .getItems());
    3491                         FrameGraphics.Repaint();
    3492                 }
    3493         }
    3494 
    3495         public static void anchor(Item toAnchor) {
    3496                 anchor(toAnchor, true);
    3497         }
    3498 
    3499         public static void anchor(Collection<Item> toAnchor) {
    3500                 boolean bReparse = false;
    3501                 boolean bRecalculate = false;
    3502                 // Need to make sure we check enclosure for overlays etc
    3503                 Set<Frame> checkEnclosure = new HashSet<Frame>();
    3504 
    3505                 // Create a clone of toAnchor since in the proccess of anchoring items
    3506                 // they can change the state of the toAnchor collection and thus create
    3507                 // concurrent modification exceptions.
    3508                 // This is especially needed for widgets being removed when anchored:
    3509                 // since they
    3510                 // currently are composed of 8 items this is vital. In the new revision
    3511                 // of
    3512                 // widgets being implemented as a single item this this can be
    3513                 // depreciated
    3514                 // however it may be useful for other applications.
    3515                 Collection<Item> toAnchorCopy = new ArrayList<Item>(toAnchor);
    3516 
    3517                 for (Item i : toAnchorCopy) {
    3518                         if (toAnchor.contains(i)) { // since to anchor could change while
    3519                                 // anchoring
    3520                                 // if (!i.hasVector())
    3521                                 anchor(i, false);
    3522                                 checkEnclosure.add(i.getParentOrCurrentFrame());
    3523                                 bReparse |= i.hasOverlay();
    3524                                 bRecalculate |= i.recalculateWhenChanged();
    3525                         }
    3526                 }
    3527 
    3528                 toAnchor.clear();
    3529                 // Check enclosure for all the frames of the items that were anchored
    3530                 for (Frame f : checkEnclosure) {
    3531                         // ItemUtils.EnclosedCheck(f.getItems());
    3532                         ItemUtils.Justify(f);
    3533                 }
    3534 
    3535                 Frame currentFrame = DisplayIO.getCurrentFrame();
    3536                 if (bReparse)
    3537                         FrameUtils.Parse(currentFrame, false, false);
    3538                 else {
    3539                         currentFrame.notifyObservers(bRecalculate);
    3540                 }
    3541                 FrameGraphics.Repaint();
    3542         }
     1853
     1854       
     1855
     1856
     1857       
     1858
     1859       
     1860
     1861       
    35431862
    35441863        /*
     
    35541873
    35551874                if (FreeItems.getInstance().size() == 2) {
    3556                         if ((FreeItems.getInstance().get(0).isLineEnd() && FreeItems
    3557                                         .getInstance().get(1) instanceof Line)
    3558                                         || (FreeItems.getInstance().get(1).isLineEnd() && FreeItems
    3559                                                         .getInstance().get(0) instanceof Line)) {
    3560 
     1875                        if ((FreeItems.getInstance().get(0).isLineEnd() && FreeItems.getInstance().get(1) instanceof Line) ||
     1876                                        (FreeItems.getInstance().get(1).isLineEnd() && FreeItems.getInstance().get(0) instanceof Line))
     1877                        {
    35611878                                Line line;
    35621879                                if (FreeItems.getInstance().get(0) instanceof Line)
     
    35821899                        }
    35831900
    3584                         FrameKeyboardActions.functionKey(rotationType, 1, arg0
    3585                                         .isShiftDown(), arg0.isControlDown());
     1901                        FrameKeyboardActions.functionKey(rotationType, 1, arg0.isShiftDown(), arg0.isControlDown());
    35861902
    35871903                } else if (clicks >= MOUSE_WHEEL_THRESHOLD) {
     
    36181934         */
    36191935        public static int getLastMouseButton() {
    3620                 if (_lastMouseClick == null)
    3621                         return MouseEvent.NOBUTTON;
     1936                if (_lastMouseClick == null) return MouseEvent.NOBUTTON;
    36221937
    36231938                return _lastMouseClick.getButton();
     
    36251940
    36261941        public static boolean isDelete(int modifiersEx) {
    3627 
    3628                 int onMask = MouseEvent.BUTTON3_DOWN_MASK
    3629                                 | MouseEvent.BUTTON2_DOWN_MASK;
     1942                int onMask = MouseEvent.BUTTON3_DOWN_MASK | MouseEvent.BUTTON2_DOWN_MASK;
    36301943                return (modifiersEx & onMask) == onMask;
    36311944        }
    36321945
    36331946        public static boolean isGetAttributes(int modifiersEx) {
    3634                 int onMask = MouseEvent.BUTTON3_DOWN_MASK
    3635                                 | MouseEvent.BUTTON1_DOWN_MASK;
     1947                int onMask = MouseEvent.BUTTON3_DOWN_MASK | MouseEvent.BUTTON1_DOWN_MASK;
    36361948                return (modifiersEx & onMask) == onMask;
    36371949        }
    36381950
    36391951        public static boolean isTwoClickNoOp(int modifiersEx) {
    3640                 int onMask = MouseEvent.BUTTON2_DOWN_MASK
    3641                                 | MouseEvent.BUTTON1_DOWN_MASK;
     1952                int onMask = MouseEvent.BUTTON2_DOWN_MASK | MouseEvent.BUTTON1_DOWN_MASK;
    36421953                return (modifiersEx & onMask) == onMask;
    36431954        }
     
    37052016        }
    37062017
    3707         public static Item getlastHighlightedItem() {
    3708                 return _lastHighlightedItem;
    3709         }
    3710 
    37112018        public static Point getPosition() {
    37122019                return new Point(getX(), getY());
     
    37222029                getInstance().refreshHighlights();
    37232030        }
     2031
     2032        @Override
     2033        public void onGesture(Gesture gesture) {
     2034                // TODO Auto-generated method stub
     2035               
     2036        }
    37242037}
Note: See TracChangeset for help on using the changeset viewer.