/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package DrawTop;

import java.awt.*;
import java.awt.geom.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
//import javax.swing.border.Border.*;
import geomExtension.*;
import shape.*;
import menu.*;
import textBox.*;
import util.*;

public class MousePositionLS implements MouseListener, MouseMotionListener {

    Point2D startPoint = null;
    Point2D currentPoint = null;
    public static boolean popupTrigger;
    boolean clicked;
    public Point2D clickedPoint = null;
    private int infoCount = 0;
    private int maxInfos = 50;
    MousePositionInfo[] infos = new MousePositionInfo[maxInfos];
    ArrayList hitList = new ArrayList();
    ShapeContainer highlightContainer=null;
    static int idNumber = 0;
    public static int debug = 0;

    public MousePositionLS() {
        this.activateListener(true);
        for (int i = 0; i < maxInfos; i++) {
            this.infos[i] = new MousePositionInfo();
        }
    }

    private void activateListener(boolean activate) {
        if (activate && !this.isMouseListener() && !this.isMouseMotionListener()) {
            JComponent listenerPanel = ObjectTable.getListenerPanel("MousePositionLS");
            listenerPanel.addMouseListener(this);
            listenerPanel.addMouseMotionListener(this);
        }
        if (!activate && this.isMouseListener() && this.isMouseMotionListener()) {
            JComponent listenerPanel = ObjectTable.getListenerPanel("MousePositionLS");
            listenerPanel.removeMouseListener(this);
            listenerPanel.removeMouseMotionListener(this);
        }
    }

    private boolean isMouseListener() {
        ListenerPanel listenerPanel = ObjectTable.getListenerPanel("MousePositionLS");
        MouseListener[] mouseLS = listenerPanel.getMouseListeners();
        boolean isRegistered = false;
        for (int i = 0; i < mouseLS.length; i++) {
            if (this.equals(mouseLS[i])) {
                isRegistered = true;
            }
        }
        return isRegistered;
    }

    private boolean isMouseMotionListener() {
        ListenerPanel listenerPanel = ObjectTable.getListenerPanel("MousePositionLS");
        MouseMotionListener[] mouseMotionLS = listenerPanel.getMouseMotionListeners();
        boolean isRegistered = false;
        for (int i = 0; i < mouseMotionLS.length; i++) {
            if (this.equals(mouseMotionLS[i])) {
                isRegistered = true;
            }
        }
        return isRegistered;
    }

    public void mousePressed(MouseEvent e) {
        //System.out.println("** MousePositionLS.mousePressed");
        double scale = DrawParameters.getScale();
        double X = e.getX() / scale;
        double Y = e.getY() / scale;
        this.startPoint = new Point2D.Double(X, Y);
        this.clicked = false;
        popupTrigger = false;
        if (e.isPopupTrigger()) {
            popupTrigger = true;
        }
        int key = e.getModifiersEx();
        int ctrl = 0;
        if ((key & InputEvent.BUTTON2_DOWN_MASK) != 0) {
            ctrl = 2;
        }
        if ((key & InputEvent.BUTTON3_DOWN_MASK) != 0) {
            ctrl = 3;
        }
        if (ctrl == 2 || ctrl == 3) {
            for (int i = 0; i < this.infoCount; i++) {
                this.infos[i].setRightButtonPressed(true);
            }
        }
        //-----------------------------------------------//
        this.displayMousePosition("mousePressed", X, Y);
        //-----------------------------------------------//
    }

    public void mouseDragged(MouseEvent e) {
        double scale = DrawParameters.getScale();
        double X = e.getX() / scale;
        double Y = e.getY() / scale;
        this.currentPoint = new Point2D.Double(X, Y);
        this.infoCount = 0;
        /*------------------------------------*/
        this.createMousePositionInfo(X, Y);
        /*------------------------------------*/
        //-------------------------------------------------//
        this.displayMousePosition("mouseDragged", X, Y);
        //------------------------------------------------//
    }

    public void mouseReleased(MouseEvent e) {
        //System.out.println("** MousePositionLS mouseReleased");
        double scale = DrawParameters.getScale();
        double X = e.getX() / scale;
        double Y = e.getY() / scale;
        this.currentPoint = new Point2D.Double(X, Y);
        if (e.isPopupTrigger()) {
            popupTrigger = true;
        }
        //-----------------------------------------------//
        this.displayMousePosition("mouseReleased", X, Y);
        //-----------------------------------------------//
        // equivalent to clicked
    }

    public void mouseClicked(MouseEvent e) {
        //System.out.println("** MousePositionLS mouseClicked");
        double scale = DrawParameters.getScale();
        double X = e.getX() / scale;
        double Y = e.getY() / scale;
        this.currentPoint = new Point2D.Double(X, Y);
        this.clicked = true;
        Point2D clickedPoint = new Point2D.Double(X, Y);
        this.displayMousePosition("mouseClicked", X, Y, false);
        boolean createShapeLS = ObjectTable.getListenerPanel().isMouseListener("CreateShapeLS");
        if (createShapeLS) {
            return;
        }
        //---------------------------------------------------------------//
        if (debug >0) System.out.println("** MousePositionLS this.allMouseEventsCompleted()="+
                this.allMouseEventsCompleted()+", SelectionLS.popupTrigger="+SelectionLS.popupTrigger+
                ", MousePositionLS.popupTrigger="+MousePositionLS.popupTrigger);
        //if (SelectionLS.popupTrigger || MousePositionLS.popupTrigger){
        if (this.allMouseEventsCompleted()
                && (SelectionLS.popupTrigger || MousePositionLS.popupTrigger)) {
            if (debug >=0) System.out.println("** MousePositionLS ExecPopupMenu");
            ExecPopupMenu execPopupMenu = ObjectTable.getExecPopupMenu("");
            execPopupMenu.show(new Point((int) X, (int) Y));
            MousePositionLS.popupTrigger = false;
            SelectionLS.popupTrigger = false;
        }
        //---------------------------------------------------------------//
        DrawPanel drawPanel = ObjectTable.getDrawPanel("");
        DrawShapeUtil.clearTempShape("MousePositionLS.pt");
        drawPanel.repaint("MousePositionLS");
    }

    public void mouseMoved(MouseEvent e) {
        //System.out.println("** MousePositionLS mouseMoved");
        double scale = DrawParameters.getScale();
        double X = e.getX() / scale;
        double Y = e.getY() / scale;
        this.currentPoint = new Point2D.Double(X, Y);
        this.infoCount = 0;
        //------------------------------------//
        this.createMousePositionInfo(X, Y);
        //------------------------------------//
        //-----------------------------------------------//
        this.displayMousePosition("mouseMoved", X, Y);
        //----------------------------------------------//
        int position = 0;
        //boolean selected = false;
        MousePositionInfo[] rankedInfos = this.getMousePositionInfoForSelection();
        if (rankedInfos.length > 0) {
            position = rankedInfos[0].getPosition();
        }
        Cursor newCursor = DrawParameters.DEFAULT_CURSOR;
        switch (position) {
            case MousePositionInfo.BOUNDINGBOX_BOUNDARY:
                newCursor = DrawParameters.DEFAULT_CURSOR;
                break;
            case MousePositionInfo.SELECTION_BOX:
                newCursor = DrawParameters.MOVE_CURSOR;
                break;
            case MousePositionInfo.INSIDE_BOUNDINGBOX:
                newCursor = DrawParameters.DEFAULT_CURSOR;
                break;
            case MousePositionInfo.NW_RESIZE:
                newCursor = DrawParameters.NW_RESIZE_CURSOR;
                break;
            case MousePositionInfo.NE_RESIZE:
                newCursor = DrawParameters.NE_RESIZE_CURSOR;
                break;
            case MousePositionInfo.SE_RESIZE:
                newCursor = DrawParameters.SE_RESIZE_CURSOR;
                break;
            case MousePositionInfo.SW_RESIZE:
                newCursor = DrawParameters.SW_RESIZE_CURSOR;
                break;
            case MousePositionInfo.N_RESIZE:
                newCursor = DrawParameters.N_RESIZE_CURSOR;
                break;
            case MousePositionInfo.E_RESIZE:
                newCursor = DrawParameters.E_RESIZE_CURSOR;
                break;
            case MousePositionInfo.S_RESIZE:
                newCursor = DrawParameters.S_RESIZE_CURSOR;
                break;
            case MousePositionInfo.W_RESIZE:
                newCursor = DrawParameters.W_RESIZE_CURSOR;
                break;
            case MousePositionInfo.END_POINT:
                newCursor = DrawParameters.CROSSHAIR_CURSOR;
                break;
            case MousePositionInfo.CONTROL_POINT:
                newCursor = DrawParameters.CROSSHAIR_CURSOR;
                break;
            case MousePositionInfo.SHAPE_BOUNDARY: {
            }
            case MousePositionInfo.INSIDE_SHAPE: {
            }
            case MousePositionInfo.TEXTBOX_BOUNDARY: {
                newCursor = DrawParameters.DEFAULT_CURSOR;
                boolean selected = false;
                String inf = "";
                boolean isActiveTextBox = false;
                if (rankedInfos.length > 0) {
                    selected = rankedInfos[0].getContainer().isSelected();
                    inf = rankedInfos[0].getInformation();
                    isActiveTextBox = rankedInfos[0].getShapeContainerInGroup().isEditableTextBox();
                }
                if (selected) {
                    newCursor = DrawParameters.MOVE_CURSOR;
                }
                if (isActiveTextBox) {
                    if (inf.equals("top") || inf.equals("bottom")) {
                        //newCursor = DrawParameters.UPDOWN_CURSOR;
                        newCursor = DrawParameters.N_RESIZE_CURSOR;
                    }
                    if (inf.equals("left") || inf.equals("right")) {
                        newCursor = DrawParameters.W_RESIZE_CURSOR;
                        //newCursor = DrawParameters.LEFTRIGHT_CURSOR;
                    }
                }
                break;
            }
            case MousePositionInfo.INSIDE_TEXT:
                newCursor = DrawParameters.TEXT_CURSOR;
                break;
        }
        DrawParameters.CURRENT_CURSOR = newCursor;
        ObjectTable.getDrawMain().setCursor(newCursor);
    }//mouseMoved

    public void mouseEntered(MouseEvent e) {
        ObjectTable.getDrawMain().setCursor(DrawParameters.DEFAULT_CURSOR);
    }

    public void mouseExited(MouseEvent e) {
        ObjectTable.getDrawMain().setCursor(DrawParameters.DEFAULT_CURSOR);
    }

    public Point2D getMousePoint(){
        return this.currentPoint;
    }

    public void displayMousePosition(String mouseAction, double X, double Y) {
        String shapeId = "null";
        String message = " MousePositionLS :  mouse action= " + mouseAction + ": ";
        message += "  x,y=" + (int) X + "," + (int) Y;
        if (this.infoCount == 0) {
            message += " outside draw area";
        }
        MousePositionInfo[] rankedInfos = this.getMousePositionInfoForSelection();
      //Shows on the Status Panel
        for (int i = 0; i < rankedInfos.length; i++) {
            ShapeContainer container = rankedInfos[i].getContainer();
            ShapeContainer shapeContainerInGroup = rankedInfos[i].getShapeContainerInGroup();

            int position = rankedInfos[i].getPosition();
            //if(position==MousePositionInfo.INSIDE_DRAWAREA) continue;
            if (container == null) continue;
            shapeId = container.getShapeId();
            if (shapeId == null||shapeId.equals("")) continue;

            boolean group = false;
            String shapeIdInGroup="";
            if(shapeContainerInGroup!=null) shapeIdInGroup=shapeContainerInGroup.getShapeId();
            if (shapeIdInGroup!=null&&!shapeIdInGroup.equals("")&&
                    !shapeIdInGroup.equals(shapeId)) {
                group = true;
            }
            if (rankedInfos.length > 1) {
                message += "   [" + i + "]";
            }
            message += ": "
                    + MousePositionInfo.getPositionStringInDetail(position);

            if (group) {
                message += ", " + shapeContainerInGroup.getShapeId() + " / " + shapeId;
            } else {
                message += ", " + shapeId;
            }

            if (rankedInfos[i].isRightButtonPressed()) {
                message += ",  right button Pressed";
            }
            if (rankedInfos[i].getContainer().isSelected()) {
                message += ",  selected";
            }
        }
        message += "   ";
        StatusPanel statusPanel = ObjectTable.getStatusPanel();
        statusPanel.showText(0, message, "MousePositionLS");
        if(ObjectTable.getContainerManager().getEditableTextBox()==null){
            statusPanel.showText(1, "", "MousePositionLS");
        }

      //Highlihghting
        boolean highlightable=true;
        if(DrawParameters.MODE!=Command.NORMAL_MODE) highlightable=false;
        boolean refresh=false;
        ShapeContainer container=null;
        if(rankedInfos.length>0){
            container = rankedInfos[0].getContainer();
            if(container!=null&&!container.equals(this.highlightContainer)) {
                if(this.highlightContainer!=null) this.highlightContainer.setHighlighting(false);
                if(!container.isSelected()&&highlightable) container.setHighlighting(true);
                else container.setHighlighting(false);
                this.highlightContainer=container;
                refresh=true;
            }
        }else{
            if(this.highlightContainer!=null) this.highlightContainer.setHighlighting(false);
            this.highlightContainer=null;
            refresh=true;
       }
       if(refresh) ObjectTable.getDrawPanel().repaint();
    }

    public void displayMousePosition(String mouseAction, double X, double Y, boolean print) {
        displayMousePosition(mouseAction, X,  Y);
        MousePositionInfo[] rankedInfos = this.getMousePositionInfoForSelection();
        if(!print) return;
        //String shapeId = "null";
        String message = " MousePositionLS :  mouse action= " + mouseAction + ": ";
        message += "  x,y=" + (int) X + "," + (int) Y;
        if (this.infoCount == 0) {
            message += " outside draw area";
        }
        System.out.println(message);
        for (int i = 0; i < rankedInfos.length; i++) {
            System.out.println(" ["+i+"]"+ rankedInfos[i].toString());
        }
    }
    
    public MousePositionInfo[] getMousePositionInfoForSelection() {
        int[] ranks = new int[this.infoCount];
        MousePositionInfo[] rankedInfos = new MousePositionInfo[0];
        if (this.infoCount == 0) {
            return rankedInfos;
        }
        int rank = 0;
        int rankDigit = 10000;
        ContainerManager manager=ObjectTable.getContainerManager();
        Vector vec=manager.getAllShapeContainers();
        for (int i = 0; i < this.infoCount; i++) {
            ShapeContainer container = this.infos[i].getContainer();
            ShapeContainer child=this.infos[i].getShapeContainerInGroup();
            if(child!=null) container=child;
            int index=vec.indexOf(container);
            int position = this.infos[i].getPosition();
            rank = 0;
            if (position >= MousePositionInfo.NW_RESIZE
                    && position <= MousePositionInfo.W_RESIZE) {
                rank = 10 * rankDigit + index;
            }
            if (position == MousePositionInfo.END_POINT
                    || position == MousePositionInfo.CONTROL_POINT) {
                rank = 10 * rankDigit + index;
            }
            if (position == MousePositionInfo.SELECTION_BOX) {
                rank = 9 * rankDigit + index;
            }
            if (position == MousePositionInfo.INSIDE_TEXT) {
                rank = 8 * rankDigit + index;
            }
            if (position == MousePositionInfo.SHAPE_BOUNDARY) {
                rank = 7 * rankDigit + index;
            }
            if (position == MousePositionInfo.TEXTBOX_BOUNDARY) {
                rank = 6 * rankDigit + index;
            }
            if (position == MousePositionInfo.INSIDE_TEXTBOX) {
                rank = 5 * rankDigit + index;
            }
            if (position == MousePositionInfo.INSIDE_SHAPE) {
                rank = 4* rankDigit + index;
            }
            if (position == MousePositionInfo.BOUNDINGBOX_BOUNDARY
                    || position == MousePositionInfo.INSIDE_BOUNDINGBOX) {
                rank = 3 * rankDigit + index;
            }
            ranks[i] = rank;
        }

        int[] indices = Util.indexedSimpleSort(ranks);
        Vector vector = new Vector();
        for (int i = 0; i < this.infoCount; i++) {
            if (ranks[indices[i]] > 0) {
                MousePositionInfo info = (MousePositionInfo) this.infos[indices[i]].clone();
                vector.add(0, info);
            }
        }
        int size = vector.size();
        if (size == 0) {
            return rankedInfos;
        }
        rankedInfos = new MousePositionInfo[size];
        for (int i = 0; i < size; i++) {
            rankedInfos[i] = (MousePositionInfo) vector.get(i);
        }
        return rankedInfos;
    }

    public MousePositionInfo getMousePositionInfoForMoveResize() {
        int[] ranks = new int[this.infoCount];
        MousePositionInfo[] rankedInfos = new MousePositionInfo[0];
        if (this.infoCount == 0) {
            return null;
        }
        int rank = 0;
        int rankDigit = 100000;
        ContainerManager manager = ObjectTable.getContainerManager();
        Vector vec = manager.getAllShapeContainers();
        for (int i = 0; i < this.infoCount; i++) {
            ShapeContainer container = this.infos[i].getContainer();
            int index=vec.indexOf(container);
            int position = this.infos[i].getPosition();
            rank = 0;
            if (!container.isSelected()) {
                continue;
            }

            if (position >= MousePositionInfo.NW_RESIZE
                    && position <= MousePositionInfo.W_RESIZE
                    || position == MousePositionInfo.END_POINT) {
                rank = 10 * rankDigit + index;
            }
            if (position >= MousePositionInfo.TEXTBOX_BOUNDARY) {
                rank = 9 * rankDigit + index;
            }
            if (position == MousePositionInfo.SHAPE_BOUNDARY) {
                rank = 8 * rankDigit + index;
            }
            if (position == MousePositionInfo.SELECTION_BOX) {
                rank = 7 * rankDigit + index;
            }
            if (position == MousePositionInfo.INSIDE_SHAPE) {
                rank = 6 * rankDigit + index;
            }
            ranks[i] = rank;
        }
        int[] indices = Util.indexedSimpleSort(ranks);
        Vector vector = new Vector();
        for (int i = 0; i < this.infoCount; i++) {
            if (ranks[indices[i]] > 0) {
                MousePositionInfo info = (MousePositionInfo) this.infos[indices[i]].clone();
                vector.add(0, info);
            }
        }
        int size = vector.size();
        if (size == 0) {
            return null;
        }
        rankedInfos = new MousePositionInfo[size];
        for (int i = 0; i < size; i++) {
            rankedInfos[i] = (MousePositionInfo) vector.get(i);
        }
        return rankedInfos[0];
    }

    public MousePositionInfo[] getAllMousePositionInfo() {
        MousePositionInfo[] mousePositionInfos = new MousePositionInfo[this.infoCount];
        for (int i = 0; i < this.infoCount; i++) {
            mousePositionInfos[i] = this.infos[i];
        }
        return mousePositionInfos;
    }

//pressed, released and clicked ?
    public boolean mouseEventCompleted() {
        return this.clicked;
    }

    public boolean allMouseEventsCompleted() {
        boolean completed = false;
        SelectionLS selectionLS = ObjectTable.getSelectionLS("MousePositionLS");
        if (selectionLS.mouseEventCompleted() && this.mouseEventCompleted()) {
            completed = true;
        }
        return completed;
    }

    private void createMousePositionInfo(double X, double Y) {
        this.infoCount = 0;
        ContainerManager containerManager = ObjectTable.getContainerManager("Edit");
        ShapeContainer[] containers = containerManager.getContainers();
        int size = 0;
        if (containers != null) {
            size = containers.length;
        }
        MousePositionInfo info = new MousePositionInfo();
        for (int i = size - 1; i >= 0; i--) {
            int containerType = containers[i].getContainerType();
            if (containerType == ShapeContainer.GROUP) {
                ShapeContainer shapeContainer = (ShapeContainer) containers[i];
                //----------------------------------------------//
                this.createMousePositionOfGroup(X, Y, shapeContainer);
                //----------------------------------------------//
            }
            if (containerType == ShapeContainer.SHAPE) {
                //-------------------------------------------------------------//
                this.createMousePositionOfShape(X, Y, (ShapeContainer) containers[i]);
                //-------------------------------------------------------------//
                //}
            }
        }
        return;
    }

    private void createMousePositionOfShape(double X, double Y,
            ShapeContainer shapeContainer) {
        boolean selected;
        int position = 0;
        String inf = "";
        Rectangle2D boundingBox = shapeContainer.getBoundingBox();
        if (boundingBox == null) {
            return;
        }
        selected = shapeContainer.isSelected();
        double maxOffset = DrawParameters.DrawAreaOffset;
        Rectangle2D drawBoundingBox = ShapeElementUtil.getEnlargedRectangle(boundingBox, maxOffset, maxOffset);
        //----------------------------------------//
        int pos = ptOnBox(X, Y, drawBoundingBox);
        //-----------------------------------------//
        if (pos >= MousePositionInfo.BOUNDINGBOX_BOUNDARY) {
            position = MousePositionInfo.INSIDE_DRAWAREA;
        }
        if (position == 0) {
            return;
        }

        double scale = DrawParameters.Scale;
        double delta = DrawParameters.SelectionBoxOffset / scale;
        Rectangle2D largeBoundingBox = ShapeElementUtil.getEnlargedRectangle(boundingBox, delta, delta);
        selected = shapeContainer.isSelected();
        //------------------------------------//
        pos = ptOnBox(X, Y, largeBoundingBox);
        //------------------------------------//

        if (selected && pos == MousePositionInfo.BOUNDINGBOX_BOUNDARY) {
            position = MousePositionInfo.SELECTION_BOX;
            //-----------------------------------------------------//
            int onMark = onResizeMark(X, Y, largeBoundingBox);
            //----------------------------------------------------//
            if (onMark != 0) {
                position = onMark;
            }
            this.setMousePosition(shapeContainer, shapeContainer, null, position,
                    new Point2D.Double(X, Y), inf);
            return;
        }

        //-------------------------------//
        pos = ptOnBox(X, Y, boundingBox);
        //--------------------------------//
        //if(pos==0)  return;  // outside
        if (pos == MousePositionInfo.BOUNDINGBOX_BOUNDARY||
                pos == MousePositionInfo.INSIDE_BOUNDINGBOX) {
            position = MousePositionInfo.BOUNDINGBOX_BOUNDARY;
        }
        this.setMousePosition(shapeContainer, shapeContainer, null, position,
                new Point2D.Double(X, Y), inf);

        //---------------------------------------//
        pos = this.ptOnShape(X, Y, shapeContainer);
        //---------------------------------------//
        if (pos > 0) {
            position = pos;
            this.setMousePosition(shapeContainer, shapeContainer, null, position,
                    new Point2D.Double(X, Y), inf);
        }

        Rectangle2D textArea = null;
        Rectangle2D textLayoutArea = null;
        if (shapeContainer.getTextBox() != null) {
            textArea = shapeContainer.getTextBox().getTextArea();
            textLayoutArea = shapeContainer.getTextBox().getTextLayoutArea();
        }
        //inside TextArea, insideText
        if (textArea != null) {
            //-------------------------------------------//
            pos = ptOnBox(X, Y, textArea);
            int posLayout = ptOnBox(X, Y, textLayoutArea);
            //-------------------------------------------//
            if (pos == MousePositionInfo.BOUNDINGBOX_BOUNDARY ) {
                position = MousePositionInfo.TEXTBOX_BOUNDARY;
                inf = this.ptInfOnBox(X, Y, textArea);
                this.setMousePosition(shapeContainer, shapeContainer, shapeContainer.getTextBox(),
                        position, new Point2D.Double(X, Y), inf);
            }
            if (pos == MousePositionInfo.INSIDE_BOUNDINGBOX ) {
                position = MousePositionInfo.INSIDE_TEXTBOX;
                inf = this.ptInfOnBox(X, Y, textArea);
                this.setMousePosition(shapeContainer, shapeContainer, shapeContainer.getTextBox(),
                        position, new Point2D.Double(X, Y), inf);
            }
            if (posLayout == MousePositionInfo.INSIDE_BOUNDINGBOX) {
                position = MousePositionInfo.INSIDE_TEXT;
                inf = this.ptInfOnBox(X, Y, textLayoutArea);
                this.setMousePosition(shapeContainer, shapeContainer, shapeContainer.getTextBox(),
                        position, new Point2D.Double(X, Y), inf);
            }
        }

        Point2D[] endPTs = new Point2D[2];
        if (shapeContainer.getElement() != null) {
            endPTs = shapeContainer.getElement().getEndPTs();
            //--------------------------------------//
            int onEndPoint = onPoint(X, Y, endPTs);
            //--------------------------------------//
            if (onEndPoint >= 0) {
                position = MousePositionInfo.END_POINT;
                this.setMousePosition(shapeContainer, shapeContainer, null, position,
                        new Point2D.Double(X, Y), inf);
                return;
            }
        }

        if (shapeContainer.getMode() == Command.MODIFYING_SHAPE_MODE
                && selected && position >= MousePositionInfo.INSIDE_DRAWAREA) {
            Point2D[] ctrlPTs = null;
            ShapeElement shapeElement = shapeContainer.getElement();
            if (shapeElement != null) {
                ctrlPTs = shapeElement.getModifierPTs();
            }
            position = 0;
            //---------------------------------------------------------------------//
            if (onPoint(X, Y, ctrlPTs) >= 0) {
                position = MousePositionInfo.CONTROL_POINT;
            }
            if (onPoint(X, Y, endPTs) >= 0) {
                position = MousePositionInfo.END_POINT;
            }
            //--------------------------------------------------------------------//
            if (position > 0) {
                this.setMousePosition(shapeContainer, shapeContainer, null, position,
                        new Point2D.Double(X, Y), inf);
            }
        }
    }

    private void createMousePositionOfGroup(double X, double Y, ShapeContainer groupContainer) {
        boolean selected;
        double scale = DrawParameters.Scale;
        double delta = DrawParameters.SelectionBoxOffset / scale;
        int position = 0;
        String inf = "";
        Rectangle2D boundingBox = groupContainer.getBoundingBox();
        Rectangle2D largeBoundingBox = ShapeElementUtil.getEnlargedRectangle(boundingBox, delta, delta);
        if (boundingBox == null) {
            return;
        }
        selected = groupContainer.isSelected();
        //-----------------------------------------//
        int pos = ptOnBox(X, Y, largeBoundingBox);
        //-----------------------------------------//
        if (pos == 0) {
            return;
        }
        // selected? and on Boundary?
        if (selected && pos == MousePositionInfo.BOUNDINGBOX_BOUNDARY) {
            position = MousePositionInfo.SELECTION_BOX;
            // check selection mark and resize mark
            //----------------------------------------------------//
            int onMark = onResizeMark(X, Y, largeBoundingBox);
            //----------------------------------------------------//
            if (onMark != 0) {
                position = onMark;
            }
            this.setMousePosition(groupContainer, null, null,
                    position, new Point2D.Double(X, Y), inf);
            return;
        }
        //--------------------------------//
        pos = ptOnBox(X, Y, boundingBox);
        //--------------------------------//
        if (pos == 0) {
            return;  // outside
        }
        if (pos > 0) {
            position = pos;
            this.setMousePosition(groupContainer, null, null,
                    position, new Point2D.Double(X, Y), inf);
        }

        // check inside text
        GroupElement groupElement = (GroupElement) groupContainer.getElement();
        ShapeContainer[] shapeContainers = groupElement.getGroupedSingleShapeContainers();
        int size = shapeContainers.length;

        for (int i = size - 1; i >= 0; i--) {
            this.createMousePositionOfShapeInGroup(X, Y, groupContainer, shapeContainers[i]);
        }
    }

    private void createMousePositionOfShapeInGroup(double X, double Y,
            ShapeContainer groupContainer, ShapeContainer shapeContainer) {
        boolean selected;
        int position = 0;
        String inf = "";
        Rectangle2D boundingBox = shapeContainer.getBoundingBox();
        if (boundingBox == null) {
            return;
        }

        double scale = DrawParameters.Scale;
        double delta = DrawParameters.SelectionBoxOffset / scale;

        int pos=0;
        //-------------------------------------//
        pos = this.ptOnShape(X, Y, shapeContainer);
        //-------------------------------------//
        if (pos > 0) {
            position = pos;
            this.setMousePosition(groupContainer, shapeContainer, null, position,
                    new Point2D.Double(X, Y), inf);
        }

        Rectangle2D textArea = null;
        if (shapeContainer.getTextBox() != null) {
            textArea = shapeContainer.getTextBox().getTextArea();
        }
        if (textArea != null) {
        //if (textArea != null && position >= MousePositionInfo.BOUNDINGBOX_BOUNDARY) {
            //--------------------------//
            pos = ptOnBox(X, Y, textArea);
            //--------------------------//
            if (pos == MousePositionInfo.BOUNDINGBOX_BOUNDARY ) {
                position = MousePositionInfo.TEXTBOX_BOUNDARY;
                inf = this.ptInfOnBox(X, Y, textArea);
                this.setMousePosition(groupContainer, shapeContainer, shapeContainer.getTextBox(),
                        position, new Point2D.Double(X, Y), inf);
            }

            if (pos == MousePositionInfo.INSIDE_BOUNDINGBOX) {
                position = MousePositionInfo.INSIDE_TEXT;
                this.setMousePosition(groupContainer, shapeContainer, shapeContainer.getTextBox(),
                        position, new Point2D.Double(X, Y), inf);
            }
        }
    }

    private int ptOnShape(double X, double Y, ShapeContainer shapeContainer) {
        double scale = DrawParameters.Scale;
        double margin = 1.2;
        double delta = 0.5 * margin * DrawParameters.Mark_NormalSize / scale;
        //double delta=0.5*margin*DrawParameters.Mark_NormalSize;
        Shape shape = shapeContainer.getElement().getShape();
        boolean closed = shapeContainer.getElement().isClosed();
        int position = 0;
        if (!closed) {
            Curve2D curve = shapeContainer.getElement().getCurve2D();
            Point2D pt = new Point2D.Double(X, Y);
            CurvePT curvePT = Curve2DUtil.getShortestLine(pt, curve);
            if (Vector2D.dist(pt, curvePT.getP()) < delta) {
                position = MousePositionInfo.SHAPE_BOUNDARY;
            }
        } else {
            boolean north = shape.contains(X, Y - delta);
            boolean south = shape.contains(X, Y + delta);
            boolean west = shape.contains(X - delta, Y);
            boolean east = shape.contains(X + delta, Y);
            if (north || south || west || east) {
                position = MousePositionInfo.SHAPE_BOUNDARY;
            }
            if (north && south && west && east) {
                position = MousePositionInfo.INSIDE_SHAPE;
            }
        }

        return position;
    }

    private int ptOnBox(double X, double Y, Rectangle2D box) {
        double scale = DrawParameters.Scale;
        double delta = 0.5 * DrawParameters.Mark_NormalSize / scale;
        //double delta=0.5*DrawParameters.Mark_NormalSize;
        int boundary = MousePositionInfo.BOUNDINGBOX_BOUNDARY;
        int inside = MousePositionInfo.INSIDE_BOUNDINGBOX;
		int position = 0;
		if(box==null) return position;
        boolean top = box.contains(X, Y - delta);
        boolean bottom = box.contains(X, Y + delta);
        boolean left = box.contains(X - delta, Y);
        boolean right = box.contains(X + delta, Y);
        
        if (top || bottom || left || right) {
            position = boundary;
        }
        if (top && bottom && left && right) {
            position = inside;
        }
        return position;
    }

    private String ptInfOnBox(double X, double Y, Rectangle2D box) {
        double scale = DrawParameters.Scale;
        double delta = 0.5 * DrawParameters.Mark_NormalSize / scale;
		String str = "outside";
		if(box==null) return str;
        double x0 = box.getX();
        double y0 = box.getY();
        double w = box.getWidth();
        double h = box.getHeight();
        Rectangle2D topBox = new Rectangle2D.Double(x0, y0 + h - delta, w, 2.0 * delta);
        Rectangle2D bottomBox = new Rectangle2D.Double(x0, y0 - delta, w, 2.0 * delta);
        Rectangle2D leftBox = new Rectangle2D.Double(x0 - delta, y0, 2.0 * delta, h);
        Rectangle2D rightBox = new Rectangle2D.Double(x0 + w - delta, y0, 2.0 * delta, h);
        boolean top = topBox.contains(X, Y);
        boolean bottom = bottomBox.contains(X, Y);
        boolean left = leftBox.contains(X, Y);
        boolean right = rightBox.contains(X, Y);
        //String str = "outside";
        if (box.contains(X, Y)) {
            str = "inside";
        }
        if (top) {
            str = "top";
        }
        if (bottom) {
            str = "bottom";
        }
        if (left) {
            str = "left";
        }
        if (right) {
            str = "right";
        }
        return str;
    }

    private int onPoint(double X, double Y, Point2D[] points) {
        if (points == null) {
            return -1;
        }
        double scale = DrawParameters.Scale;
        int size = 0;
        if (points != null) {
            size = points.length;
        }
        double delta = 0.5 * DrawParameters.Mark_NormalSize / scale;
        //double delta=0.5*DrawParameters.Mark_NormalSize;
        int index = -1;
        for (int i = 0; i < size; i++) {
            double x = points[i].getX();
            double y = points[i].getY();
            if (boxContains(X, Y, delta, x, y)) {
                index = i;
                break;
            }
        }
        return index;
    }

    private int onResizeMark(double X, double Y, Rectangle2D rectangle) {
        double scale = DrawParameters.Scale;
        double delta = 0.5 * DrawParameters.Mark_NormalSize / scale;
        //double delta=0.5*DrawParameters.Mark_NormalSize;
        double x = rectangle.getX();
        double y = rectangle.getY();
        double w = rectangle.getWidth();
        double h = rectangle.getHeight();
        double markX = x, markY = y;
        if (boxContains(X, Y, delta, markX, markY)) {
            return MousePositionInfo.NW_RESIZE;
        }
        markX = x + w;
        if (boxContains(X, Y, delta, markX, markY)) {
            return MousePositionInfo.NE_RESIZE;
        }
        markY = y + h;
        if (boxContains(X, Y, delta, markX, markY)) {
            return MousePositionInfo.SE_RESIZE;
        }
        markX = x;
        if (boxContains(X, Y, delta, markX, markY)) {
            return MousePositionInfo.SW_RESIZE;
        }
        markX = x + w / 2;
        markY = y;
        if (boxContains(X, Y, delta, markX, markY)) {
            return MousePositionInfo.N_RESIZE;
        }
        markX = x + w;
        markY = y + h / 2;
        if (boxContains(X, Y, delta, markX, markY)) {
            return MousePositionInfo.E_RESIZE;
        }
        markX = x + w / 2;
        markY = y + h;
        if (boxContains(X, Y, delta, markX, markY)) {
            return MousePositionInfo.S_RESIZE;
        }
        markX = x;
        markY = y + h / 2;
        if (boxContains(X, Y, delta, markX, markY)) {
            return MousePositionInfo.W_RESIZE;
        }
        return 0;
    }

    private boolean boxContains(double X, double Y, double delta, double boxX, double boxY) {

        if (X < boxX - delta) {
            return false;
        }
        if (X > boxX + delta) {
            return false;
        }
        if (Y < boxY - delta) {
            return false;
        }
        if (Y > boxY + delta) {
            return false;
        }
        return true;
    }

    private void setMousePosition(ShapeContainer container, ShapeContainer shapeContainerInGroup,
            TextBox textBox, int position, Point2D point, String inf) {
        if (this.infoCount < this.maxInfos) {
            this.infos[infoCount].setContainer(container);
            this.infos[infoCount].setShapeContainerInGroup(shapeContainerInGroup);
            this.infos[infoCount].setTextBox(textBox);
            this.infos[infoCount].setPosition(position);
            this.infos[infoCount].setPoint(point);
            this.infos[infoCount].setMouseStatus("");
            this.infos[infoCount].setRightButtonPressed(false);
            this.infos[infoCount].setInformation(inf);
            this.infoCount++;
        } else {
            System.err.println("*** Warning MousePositionInfo: Num. of infos excedded max");
        }
    }
} 
