Logo Search packages:      
Sourcecode: jclic version File versions  Download package

PolygonDrawPanel.java

/*
 * File    : PolygonDrawPanel.java
 * Created : 17-may-2002 10:20
 * By      : allastar
 *
 * JClic - Authoring and playing system for educational activities
 *
 * Copyright (C) 2000 - 2005 Francesc Busquets & Departament
 * d'Educacio de la Generalitat de Catalunya
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details (see the LICENSE file).
 */

package edu.xtec.jclic.shapers;

import edu.xtec.util.StrUtils;

/**
 *
 * @author  allastar
 * @version 1.0
 */

import java.awt.*;
import java.awt.geom.*;
import java.awt.event.*;
import java.util.Vector;
import javax.swing.*;

public class PolygonDrawPanel implements java.awt.event.MouseMotionListener, java.awt.event.MouseListener{
    
    private Vector vShapes; //Vector that contains the polygon currently being modified
    private static Vector vCopied;
    private Vector vRedrawingLines,vRedrawingLinesBeforeModify,vShapeBeforeModify;
    private Vector vPointListeners;
    private double iniX,iniY,finX,finY,lastFinX,lastFinY;
    private Point2D iniPoint=null,lastPoint=null;
    private boolean bSelectedPoint=false;
    private double zoomX=0,zoomY=0,zoomH=-1,zoomW=-1;
    private boolean creatingRect=false,creatingEllipse=false, creatingPolygon=false, bRedrawingLines=false, bSelectingArea=false;
    private boolean bResizing=false;
    private int resizingDirection=NO_RESIZING;
    private boolean bSpecialLine=false;
    private boolean bMoving=false;
    private EditableShape specialLine=null;
    private int drawingMode=SELECTING;
    static double defaultSensibility=1.5;
    private AffineTransform at;
    private Vector vDrawnBorders=null;
    private Shape current=null;
    
    private JComponent container;
    
    private short INITIAL=0;
    private short END=1;
    
    public static final int SELECTING=1;
    public static final int MOVING=2;
    public static final int NEW_POINT=4;
    public static final int DRAWING_RECT=5;
    public static final int DRAWING_ELLIPSE=6;
    public static final int DRAWING_POLYGON=7;
    public static final int ZOOM=12;
    
    public static final int NO_RESIZING=-1;
    public static final int EAST=0;
    public static final int SOUTH=1;
    public static final int SOUTH_EAST=2;
    
    private int backgroundComposite=0;
    
    protected  HolesEditorPanel hep;
    protected boolean canResize;
    protected Rectangle lastPreviewArea;
    
    static Cursor[] cursors=null;
    public static final int PEN_CURSOR=0;
    public static final int CIRCLE_CURSOR=1;
    
    protected Shape esborram=null;
    
    /** Creates new PolygonDrawPanel */
    public PolygonDrawPanel(int width, int height, HolesEditorPanel hep, boolean canResize) {
        this.hep=hep;
        this.canResize=canResize;
        vShapes=new Vector();
        if(vCopied==null)
            vCopied=new Vector();
        
        vRedrawingLines=new Vector();
        vRedrawingLinesBeforeModify=new Vector();
        vPointListeners=new Vector();
        at=new AffineTransform();
        initDrawnBorders();
        
        if(cursors==null){
            cursors=new Cursor[2];
            Toolkit tk=Toolkit.getDefaultToolkit();
            cursors[PEN_CURSOR]=tk.createCustomCursor(edu.xtec.util.ResourceManager.getImageIcon("cursors/llapis.gif").getImage(), new Point(12,24), "pen");
            cursors[CIRCLE_CURSOR]=tk.createCustomCursor(edu.xtec.util.ResourceManager.getImageIcon("cursors/cercle.gif").getImage(), new Point(16,16), "circle");
        }
        hep.addKeyListener(new PolygonDrawPanel.KeyHandler());
    }
    
    public void setDrawingMode(int drawingMode){
        if(this.drawingMode!=drawingMode){
            this.drawingMode=drawingMode;
            if(creatingPolygon)
                joinPolygon();
            if(drawingMode!=NEW_POINT && drawingMode!=SELECTING) {
                endPolygon();
            }
            hep.repaint(0);
        }
    }
    
    public int getVisibleWidth(){
        return hep.getPreviewPanel().getWidth();
    }
    
    public int getVisibleHeight(){
        return hep.getPreviewPanel().getHeight();
    }
    
    public void initDrawnBorders(){
        if(vDrawnBorders!=null)
            vDrawnBorders.clear();
        else
            vDrawnBorders=new Vector();
        for(int i=0;i<hep.getNumShapes();i++){
            if(i!=hep.currentShape){
                Shape s=hep.getHoles().getShape(i,hep.previewArea);
                if(s!=null)
                    vDrawnBorders.addAll(getBorders(s));
            }
        }
    }
    
    private java.util.Vector getBorders(Shape s){
        // Utility function that returns the points that define the "segments" of the polygon 's'.
        int xIni=0; int yIni=0;
        
        if(s==null)
            return null;
        java.util.Vector vPoints=new java.util.Vector();
        double x,y;
        if(s instanceof GeneralPath){
            GeneralPath gp=(GeneralPath)s;
            PathIterator it=gp.getPathIterator(new AffineTransform());
            double[] coords=new double[6];
            while (!it.isDone()){
                int type=it.currentSegment(coords);
                switch (type){
                    case PathIterator.SEG_MOVETO:
                        x=coords[0]; y=coords[1];
                        vPoints.add(new Rectangle((int)(x+xIni)-(EditableShapeConstants.selectLength/2),(int)(y+yIni)-(EditableShapeConstants.selectLength/2),EditableShapeConstants.selectLength,EditableShapeConstants.selectLength));
                        break;
                    case PathIterator.SEG_LINETO:
                        x=coords[0]; y=coords[1];
                        vPoints.add(new Rectangle((int)(x+xIni)-(EditableShapeConstants.selectLength/2),(int)(y+yIni)-(EditableShapeConstants.selectLength/2),EditableShapeConstants.selectLength,EditableShapeConstants.selectLength));
                        break;
                    case PathIterator.SEG_CUBICTO:
                        x=coords[4]; y=coords[5];
                        vPoints.add(new Rectangle((int)(x+xIni)-(EditableShapeConstants.selectLength/2),(int)(y+yIni)-(EditableShapeConstants.selectLength/2),EditableShapeConstants.selectLength,EditableShapeConstants.selectLength));
                        break;
                    case PathIterator.SEG_QUADTO:
                        x=coords[2]; y=coords[3];
                        vPoints.add(new Rectangle((int)(x+xIni)-(EditableShapeConstants.selectLength/2),(int)(y+yIni)-(EditableShapeConstants.selectLength/2),EditableShapeConstants.selectLength,EditableShapeConstants.selectLength));
                        break;
                    case PathIterator.SEG_CLOSE:
                        break;
                    default:
                }
                it.next();
            }
        }
        return vPoints;
    }
    
    public void paint(java.awt.Graphics2D g){
        
        Graphics2D g2d=(Graphics2D)g;
        EditableShape current=null;
        
        if(EditableShapeConstants.showDrawnPoints)
            paintDrawnBorders(g);
        
        java.util.Enumeration e=vShapes.elements();
        while (e.hasMoreElements()){
            current=(EditableShape)e.nextElement();
            if(bSpecialLine && current==specialLine)
                current.paintWithColor(g,drawingMode,EditableShapeConstants.CUT_COLOR);
            else
                current.paintWithColor(g,drawingMode,EditableShapeConstants.ACTIVE_COLOR);
        }
        if(bMoving)
            paintMoved(g);        
        if(creatingRect){
            g.setColor(EditableShapeConstants.selectedColor);
            EditableRectangle rect=new EditableRectangle((int)iniX,(int)iniY,(int)(finX-iniX),(int)(finY-iniY));
            rect.paintWithColor(g,drawingMode,EditableShapeConstants.selectedColor);
        }
        if(creatingEllipse){
            g.setColor(EditableShapeConstants.selectedColor);
            EditableEllipse2D ellipse=new EditableEllipse2D((int)iniX,(int)iniY,(int)(finX-iniX),(int)(finY-iniY));
            ellipse.paintWithColor(g,drawingMode,EditableShapeConstants.selectedColor);
        }
        if(creatingPolygon){
            if(lastPoint!=null){
                EditableLine2D el=new EditableLine2D(lastPoint.getX(),lastPoint.getY(),finX,finY);
                el.paintWithColor(g,drawingMode,EditableShapeConstants.selectedColor);
            }
        }
    }
    
    public void drawGrid(java.awt.Graphics g, int gridWidth){
        if(gridWidth<=1)
            return;
        int width=(int)(hep.previewArea.getWidth());
        int height=(int)(hep.previewArea.getHeight());
        g.setColor(EditableShapeConstants.gridColor);
        for (double i=hep.previewArea.x;i<=hep.previewArea.x+width;i+=(gridWidth*hep.xFactor)){
            //from 0 in order to avoid changes in the location of the grid when zoomed
            //vertical
            g.drawLine((int)i,hep.previewArea.y,(int)i,(int)(hep.previewArea.y+height));
        }
        for (double i=hep.previewArea.y;i<=hep.previewArea.y+height;i+=(gridWidth*hep.yFactor)){
            //horitzontal
            g.drawLine(hep.previewArea.x,(int)i,(int)(hep.previewArea.x+width),(int)i);
        }
    }
    
    protected void paintDrawnBorders(java.awt.Graphics2D g){
        java.util.Enumeration eDr=vDrawnBorders.elements();
        while (eDr.hasMoreElements()){
            Rectangle r=(Rectangle)eDr.nextElement();
            double x=r.getX();
            double y=r.getY();
            double w=r.getWidth();
            double h=r.getHeight();
            x=x+(w/4);
            y=y+(h/4);
            w=w/2;
            h=h/2;
            g.setColor(EditableShapeConstants.DRAWN_BORDER_COLOR);
            g.fillRect((int)x,(int)y,(int)w,(int)h);
        }
    }
    
    private void paintMoved(java.awt.Graphics2D g){
        EditableShape current;
        java.util.Enumeration e=vCopied.elements();
        while (e.hasMoreElements()){
            current=(EditableShape)e.nextElement();
            EditableShape copied=(EditableShape)current.clone();
            copied.transform(AffineTransform.getTranslateInstance(finX-iniX,finY-iniY));
            copied.paintWithColor(g,drawingMode,EditableShapeConstants.movingColor);
        }
    }
    
    public void updateView(){
        Vector v=getGeneralPath();
        if(lastPreviewArea==null)
            lastPreviewArea=hep.previewArea;
        if(v.size()>0){
            move(hep.previewArea.x-lastPreviewArea.x,hep.previewArea.y-lastPreviewArea.y,false,false);
        }
        try{
            lastPreviewArea=(Rectangle)(hep.previewArea.clone());
        }
        catch(Exception e){
            System.err.println("Error updating view:\n"+e);
        }
    }
    
    public void setShapeData(ShapeData sd, double x, double y, double scaleX, double scaleY){
        //x,y indicate the current position
        clean();
        current=(sd!=null)?sd.getShape(hep.previewArea):null;
        double firstX=-1,firstY=-1;
        if(sd.primitiveType>=0 && sd.primitivePoints!=null && sd.primitivePoints.length>3){
            EditableShape es=null;
            double xTr=(sd.primitivePoints[0]*hep.previewArea.getWidth())+hep.previewArea.getX();
            double yTr=(sd.primitivePoints[1]*hep.previewArea.getHeight())+hep.previewArea.getY();
            double wSc=sd.primitivePoints[2]*hep.previewArea.getWidth();
            double hSc=sd.primitivePoints[3]*hep.previewArea.getHeight();
            switch (sd.primitiveType){
                case ShapeData.RECTANGLE:
                    es=new EditableRectangle((int)xTr,(int)yTr,(int)wSc,(int)hSc);
                    vShapes.add(es);
                    break;
                case ShapeData.ELLIPSE:
                    es=new EditableEllipse2D((int)xTr,(int)yTr,(int)wSc,(int)hSc);
                    vShapes.add(es);
                    break;
            }
        }
        else{
            Shape s=sd.getShape(hep.previewArea);
            if(s instanceof GeneralPath){
                GeneralPath gp=(GeneralPath)s;
                PathIterator it=gp.getPathIterator(new AffineTransform());
                double[] coords=new double[6];
                while (!it.isDone()){
                    int type=it.currentSegment(coords);
                    switch (type){
                        case PathIterator.SEG_MOVETO:
                            x=coords[0]; y=coords[1];
                            if(firstX==-1){ //To close
                                firstX=x;
                                firstY=y;
                            }
                            break;
                        case PathIterator.SEG_LINETO:
                            vShapes.add(new EditableLine2D(x,y,coords[0],coords[1]));
                            x=coords[0]; y=coords[1];
                            break;
                        case PathIterator.SEG_CUBICTO:
                            vShapes.add(new EditableCubicCurve2D(x,y,coords[0],coords[1],coords[2],coords[3],coords[4],coords[5]));
                            x=coords[4]; y=coords[5];
                            break;
                        case PathIterator.SEG_QUADTO:
                            vShapes.add(new EditableQuadCurve2D(x,y,coords[0],coords[1],coords[2],coords[3]));
                            x=coords[2]; y=coords[3];
                            break;
                        case PathIterator.SEG_CLOSE:
                            if(firstX!=-1 && (x!=firstX || y!=firstY)){
                                vShapes.add(new EditableLine2D(x,y,firstX,firstY));
                                x=firstX;y=firstY;
                            }
                            break;
                        default:
                            break;
                    }
                    it.next();
                }
                if(firstX!=-1 && (x!=firstX || y!=firstY)){
                    // That's to be sure that the shape is always closed
                    vShapes.add(new EditableLine2D(x,y,firstX,firstY));
                }
            }
        }
        removeDrawnBorders(sd);
    }
    
    public void clean(){
        vShapes=new Vector();
        vRedrawingLines=new Vector();
        vRedrawingLinesBeforeModify=new Vector();
    }
    
    
    public boolean selectDrawnShape(Point2D p) {
        endPolygon();
        for (int i=0;i<hep.getNumShapes();i++){
            Shape s=hep.getHoles().getShape(i,hep.previewArea);
            if(s.contains(p) && hep.currentShape!=i){
                hep.setCurrentShape(i);
                setShapeData(hep.getHoles().getShapeData(i),0,0,1,1);
                return true;
            }
        }
        hep.setCurrentShape(hep.getHoles().getNumCells()+1);
        clean();
        return false;
    }
    
    public void selectShape(int iIndex){
        if(iIndex<0)
            return;
        ShapeData sd=hep.getHoles().getShapeData(iIndex);
        if(sd!=null){
            setShapeData(sd,0,0,1,1);
        }
    }
    
    private EditableShape aproximationToLine(double x, double y){
        return aproximationToLine(x,y,null);
    }
    
    private EditableShape aproximationToLine(double x, double y, Vector vRedrawingLines){
        //returns an EditableShape when there is a corner at (x,y) that not belongs to the lines in
        //the Vector vRedrawingLines. Otherwise returns null
        EditableShape current=null;
        java.util.Enumeration e=vShapes.elements();
        while (e.hasMoreElements()){
            current=(EditableShape)e.nextElement();
            if(vRedrawingLines==null || !vRedrawingLines.contains(current))
                if(current.hasClickedBorder((int)x,(int)y,false))
                    return current;
        }
        return null;
    }
    
    private Point2D getTransformedPoint(Point2D p, boolean mustBeOnGrid){
        //mustBeOnGrid is used to discard the approach
        Point2D mousePoint=new Point2D.Double(p.getX(),p.getY());
        if(EditableShapeConstants.gridWidth!=-1 && EditableShapeConstants.pointsOnGrid && mustBeOnGrid)
            moveToGrid(mousePoint);
        return mousePoint;
    }
    
    private void moveToGrid(Point2D p){
        //Moves the supplied point to the closest grid point
        int x=(int)p.getX();
        int y=(int)p.getY();
        
        x-=hep.previewArea.getX();
        y-=hep.previewArea.getY();
        
        double wd=EditableShapeConstants.gridWidth*hep.xFactor;
        int w=(int)wd;
        if(w==-1)
            return;
        
        int xLeft=(int)(((int)(x/wd))*wd);
        if((x-xLeft)<(w/2))
            x=xLeft;
        else
            x=(int)(((int)((x+w-1)/wd))*wd);
        
        int yUp=(int)(((int)(y/wd))*wd);
        if((y-yUp)<(w/2))
            y=yUp;
        else
            y=(int)(((int)((y+w-1)/wd))*wd);
        x+=hep.previewArea.getX();
        y+=hep.previewArea.getY();
        p.setLocation(x,y);
    }
    
    public Point2D aproximationToDrawnBorder(double x, double y){
        // Returns true if a rectangle in vDrawnBorders contains the point (x,y)
        java.util.Enumeration e=vDrawnBorders.elements();
        while (e.hasMoreElements()){
            Rectangle2D r=(Rectangle2D)e.nextElement();
            if(r.contains(x,y))
                return new Point2D.Double(r.getX()+(r.getWidth()/2),r.getY()+(r.getHeight()/2));
        }
        return null;
    }
    
    
    protected void redrawingLines(double x, double y){ //moves all the selected shapes containing (x,y) in one of its corners
        EditableShape current=null;
        java.util.Enumeration e=vRedrawingLines.elements();
        while (e.hasMoreElements()){
            current=(EditableShape)e.nextElement();
            current.changeBorder(x,y);
        }
    }
    
    private void cleanZoom(){
        zoomX=0;
        zoomY=0;
        zoomW=-1;
        zoomH=-1;
        at=new AffineTransform();
        cancelCurrentOperations();
        bSelectingArea=false;
        hep.repaint(0);
    }
    
    public void cancelCurrentOperations(){
        creatingRect=false;
        creatingEllipse=false;
    }
    
    public void cut(double x, double y){
        copy(false);
        clean();
        bMoving=true;
        iniX=x;
        iniY=y;
        finX=iniX;
        finY=iniY;
    }
    
    public void cut(){
        cut(-1,-1);
    }
    
    public void copy(boolean needSelected){
        vCopied.clear();
        EditableShape current=null;
        java.util.Enumeration e=vShapes.elements();
        while (e.hasMoreElements()){
            current=(EditableShape)((EditableShape)e.nextElement()).clone();
            if(!needSelected || current.isSelected()){
                vCopied.add(current);
            }
        }
    }
    
    public void paste(){
        bMoving=true;
        iniX=-1; iniY=-1; finX=-1; finY=-1;
        paste(5,5);
    }
    
    public void paste(double x, double y){
        Vector newCopied=new Vector();
        deSelectAll();
        EditableShape current=null;
        java.util.Enumeration e=vCopied.elements();
        while (e.hasMoreElements()){
            current=(EditableShape)e.nextElement();
            EditableShape copied=(EditableShape)current.clone();
            copied.transform(AffineTransform.getTranslateInstance(x,y));
            copied.setSelected(true);
            vShapes.add(copied);
            newCopied.add(copied); //to avoid overlap of shapes when the user makes "paste" two times
        }
        vCopied=newCopied;
    }
    
    public void deSelectAll(){
        EditableShape current=null;
        java.util.Enumeration e=vShapes.elements();
        while (e.hasMoreElements()){
            current=(EditableShape)e.nextElement();
            current.setSelected(false);
        }
        bSelectedPoint=false;
        hep.repaint(0);
    }
    
    private EditableShape nearestLine(double x, double y){
        EditableShape nearest=null;
        EditableShape current=null;
        double distance=0;
        double currentDistance;
        java.util.Enumeration e=vShapes.elements();
        while (e.hasMoreElements()){
            current=(EditableShape)e.nextElement();
            currentDistance=current.distanceTo(x,y);
            if(nearest==null || (currentDistance<distance)){
                distance=currentDistance;
                nearest=current;
            }
        }
        return nearest;
    }
    
    private void clicatISeleccionada(int x, int y, boolean needSelected){
        //With needSelected=false it's not necessary to have selected a shape in order to drag it
        // leaves in vRedrawingLines the selected lines with one point near the supplied co-ordinates (x,y)
        Point2D redrawingPoint=null;
        EditableShape current=null;
        vRedrawingLines.clear();
        java.util.Enumeration e=vShapes.elements();
        while (e.hasMoreElements()){
            current=(EditableShape)e.nextElement();
            if((!needSelected || current.isSelected()) && current.hasClickedBorder(x,y,needSelected)){
                Point2D p=current.getNearestBorder(x,y);
                if(redrawingPoint==null || redrawingPoint.equals(p)){
                    redrawingPoint=p;
                    vRedrawingLines.add(current);
                }
            }
        }
        vRedrawingLinesBeforeModify=cloneVector(vRedrawingLines);
    }
    
    private Vector cloneVector(Vector v){
        Vector vClone=new Vector();
        if(v!=null){
            java.util.Enumeration e=v.elements();
            while (e.hasMoreElements()){
                EditableShape es=(EditableShape)e.nextElement();
                vClone.add(es.clone());
            }
        }
        return vClone;
    }
    
    private void divideShape(EditableShape specialLine,double x, double y){
        if(specialLine!=null){
            EditableShape[] shapes=specialLine.divide(x,y);
            if(shapes!=null){
                // -> The two following lines are necessary in order to grant the connection of the resulting shape
                // Dividing two times in the same point can create an independent line out of the shape
                Vector vCheckPoint=new Vector();
                vCheckPoint.addAll(vShapes);
                vShapes.remove(specialLine);
                for (int i=0;i<shapes.length;i++){
                    if(shapes[i]!=null)
                        vShapes.add(shapes[i]);
                }
                boolean bValidate=validateShape();
                if(!bValidate)
                    vShapes=vCheckPoint;
            }
            hep.updateView();
        }
        hep.repaint(0);
    }
    
    private boolean validateShape(){
        return (getGeneralPath().size()==1);
    }
    
    public Vector getGeneralPath(){
        Vector vGpaths=new Vector();
        GeneralPath currentPolygon=new GeneralPath();
        Vector shapes=new Vector();
        shapes.addAll(vShapes);
        if(!(shapes.size()>0)) 
            return vGpaths;
        EditableShape current=(EditableShape)shapes.get(0);
        shapes.remove(current);
        currentPolygon.append(current,true);
        short notUsedPoint=END; //indicates the side of the last shape non-adjacent to anyone
        while (shapes.size()>0){
            EditableShape shape=getAdjacent(shapes,current,notUsedPoint);
            if(shape!=null){
                currentPolygon.append(shape,true);
                notUsedPoint=getNotUsed(current,shape); //returns the point of the shape non-adjacent to "current"
                shapes.remove(shape);
                current=shape;
            }
            else{
                vGpaths.add(currentPolygon);
                currentPolygon=new GeneralPath();
                notUsedPoint=END;
                current=(EditableShape)shapes.get(0);
                shapes.remove(current);
                currentPolygon.append(current,true);
            }
        }
        vGpaths.add(currentPolygon);
        return vGpaths;
    }
    
    private short getNotUsed(EditableShape current, EditableShape shape){ //returns the point of the shape non-adjacent to "current"
        if(shape.getInitialPoint().equals(current.getInitialPoint())||shape.getInitialPoint().equals(current.getEndPoint()))
            return END;
        else
            return INITIAL;
    }
    
    private EditableShape getAdjacent(Vector shapes, EditableShape sh, short notUsedPoint){
        java.util.Enumeration e=shapes.elements();
        Point2D p;
        if(notUsedPoint==INITIAL)
            p=sh.getInitialPoint();
        else
            p=sh.getEndPoint();
        while(e.hasMoreElements()){
            EditableShape shape=(EditableShape)e.nextElement();
            if(shape.isAdjacentTo(p))
                return shape;
        }
        return null;
    }
    
    public boolean hasSelectedDrawnShape(Point2D p) {
        for (int i=0;i<hep.getNumShapes();i++){
            Shape s=hep.getHoles().getShape(i,hep.previewArea);
            if(s.contains(p)) {
                return true;
            }
        }
        return false;
    }
    
    private double distanceToNearest(double x, double y){
        EditableShape nearest=nearestLine(x,y);
        if(nearest!=null)
            return nearest.distanceTo(x,y);
        else
            return -1;
    }
    
    public void deleteSelected(boolean isCut){
        if(hasSelectedPoint()){
            joinAdjacentsToSelectedPoint();
            bSelectedPoint=false;
        }
        else{
            EditableShape current=null;
            Vector vShapesCopy=new Vector();
            boolean allSelected=true, noneSelected=true;
            vShapesCopy.addAll(vShapes);
            java.util.Enumeration e=vShapesCopy.elements();
            while (e.hasMoreElements()){
                current=(EditableShape)e.nextElement();
                if(!current.isSelected())
                    allSelected=false;
                else{
                    noneSelected=false;
                    if(isCut || vShapes.size()>=4){ //Avoid to delete objects when there are only 3 or less elements, unless is a "cut"
                        vShapes.remove(current);
                        if(!isCut)
                            joinAdjacentsTo(current,vShapes);
                    }
                }
            }
            //allSelected indicates if all the object was selected
            if(allSelected || noneSelected){
                vShapes.clear();
                this.current=null;
                hep.getHoles().removeShape(hep.currentShape);
                hep.setCurrentShape(hep.getHoles().getNumCells());
            }
        }
    }
    
    private void joinAdjacentsTo(EditableShape current, Vector vShapes){
        //All the shapes in vShapes will converge in one of the "current" points.
        EditableShape s1=getAdjacent(vShapes,current,INITIAL);
        if(s1!=null){ //Always
            s1.hasClickedBorder(current.getInitialPoint().getX(),current.getInitialPoint().getY(),false);
            //hasClickedBorder marks the shape corner nearest to the supplied point. Calling
            //changeBorder this corner will be modified to the new point.
            s1.changeBorder(current.getEndPoint().getX(),current.getEndPoint().getY());
        }
    }
    
    private void joinAdjacentsToSelectedPoint(){
        EditableShape current=null, other=null;
        if(vShapes.size()!=1 && vShapes.size()<=3)
            return;
        java.util.Enumeration e=vShapes.elements();
        int count=0;
        boolean bFinish=false;
        while (e.hasMoreElements() && !bFinish){
            current=(EditableShape)e.nextElement();
            if(current.hasSelectedBorder()){
                if(current instanceof EditableRectangle){
                    Point2D p=current.getNotSelectedBorder();
                    convertToSimpleShapes();
                    selectBorder(p.getX(),p.getY());
                    joinAdjacentsToSelectedPoint();
                    bFinish=true;
                }
                else{
                    count++;
                    if(count==1)
                        other=current;
                    else{
                        Point2D p1=current.getNotSelectedBorder();
                        Point2D p2=other.getNotSelectedBorder();
                        vShapes.add(new EditableLine2D(p1,p2));
                        vShapes.remove(current);
                        vShapes.remove(other);
                    }
                }
            }
        }
        hep.repaint(0);
    }
    
    private void setEndToVector(double finX, double finY, Vector vRedrawingLines){
        //approach of all the lines of vRedrawingLines to the point finX, finY
        EditableShape current=null;
        java.util.Enumeration e=vRedrawingLines.elements();
        while (e.hasMoreElements()){
            current=(EditableShape)e.nextElement();
            current.aproximateNearestBorder(finX,finY);
        }
    }
    
    public boolean hasSelectedPoint(){
        return bSelectedPoint;
    }
    
    public Vector getSelectedShapes(){
        Vector v=new Vector();
        java.util.Enumeration e=vShapes.elements();
        EditableShape current;
        while (e.hasMoreElements()){
            current=(EditableShape)e.nextElement();
            if(current.isSelected())
                v.add(current);
        }
        return v;
    }
    
    public int getNumShapes(){
        return vShapes.size();
    }
    
    public void deleteCurrent(){
        clean();
        current=null;
    }
    
    public ShapeData getShapeData(){
        ShapeData sd=null;
        AffineTransform at=AffineTransform.getScaleInstance((1/hep.previewArea.getWidth()),(1/hep.previewArea.getHeight()));
        at.concatenate(AffineTransform.getTranslateInstance(-hep.previewArea.x,-hep.previewArea.y));
        if(getNumShapes()==1){ //Is a rectangle or a ellipse
            EditableShape es=(EditableShape)((EditableShape)vShapes.elements().nextElement()).clone();
            es.transform(at);
            Shape s;
            if(es instanceof EditableEllipse2D)
                s=((EditableEllipse2D)es).getEllipse();
            else
                s=es;
            sd=ShapeData.getShapeData(s, null, false);
        }
        else{
            Vector v=getGeneralPath(); //Get only the first polygon found (should be unique)
            if(v.size()>0){
                GeneralPath gp=(GeneralPath)(v.elements().nextElement());
                Shape s=gp.createTransformedShape(at);
                sd=ShapeData.getShapeData(s, null);
            }
        }
        return sd;
    }
    
    public void endPolygon(){
        endPolygon(false,true);
    }
    
    public void endPolygon(boolean changeShape, boolean updateList){
        endPolygon(changeShape,updateList,-1);
    }
    
    public void endPolygon(boolean changeShape, boolean updateList, int iNextShape){
        ShapeData sd=getShapeData();
        addCurrentDrawnBorders(sd);
        endPolygon(sd,changeShape,updateList,iNextShape);
        if(sd!=null)
            clean();
        bSelectedPoint=false;
    }
    
    private void addCurrentDrawnBorders(ShapeData sd){
        if(sd!=null && hep!=null){
            Shape s=sd.getShape(hep.previewArea);
            vDrawnBorders.addAll(getBorders(s));
        }
    }
    
    private void removeDrawnBorders(ShapeData sd){
        Shape s=sd.getShape(hep.previewArea);
        vDrawnBorders.removeAll(getBorders(s)); //removeAll removes all the instances of the elements passed over the Vector (only one instance is needed)
    }
    
    public void endPolygon(ShapeData sd, boolean changeShape, boolean updateList,int iNextShape){
        //Save the created/modified polygon. changeShape indicates if we "come" from a tab key.
        if(sd!=null){
            
            addCurrentDrawnBorders(sd);
            
            if(hep.currentShape<hep.getHoles().getNumCells()){ //hep.currentShape has been modified
                hep.getHoles().modifyShape(hep.currentShape,sd);
                hep.updateView();
            }
            else{ //A comment ahs been created
                sd.comment=StrUtils.secureString(sd.comment, ""+hep.currentShape);
                hep.getHoles().addShape(sd);
                hep.updateList();
                hep.updateView();
            }
        }
        int iCurrentShape=hep.currentShape+1;
        if(changeShape){
            if(iNextShape>=0)
                iCurrentShape=iNextShape;
            else
                iCurrentShape=iCurrentShape%hep.getHoles().getNumCells();
        }
        else iCurrentShape=hep.getHoles().getNumCells(); //Next one will be new
        if(hep.currentShape!=iCurrentShape)
            hep.setCurrentShape(iCurrentShape);
    }
    
    private void aplicateTransformation(AffineTransform aTransf, boolean needSelected){
        EditableShape current=null;
        java.util.Enumeration e=vShapes.elements();
        while (e.hasMoreElements()){
            current=(EditableShape)e.nextElement();
            if(!needSelected || current.isSelected()){
                current.transform(aTransf);
            }
        }
    }
    
    public void move(int xInc, int yInc, boolean needSelected, boolean moveAll){ //moveAll indicates if we want to move also the inactive objects
        AffineTransform aTransf=AffineTransform.getTranslateInstance(xInc,yInc);
        aplicateTransformation(aTransf, needSelected);
        hep.repaint(0);
    }
    
    public void scale(double xInc, double yInc, boolean needSelected, boolean scaleAll){
        Point2D center=getCenter(scaleAll);
        AffineTransform aTransf=AffineTransform.getTranslateInstance(center.getX(),center.getY());
        aTransf.concatenate(AffineTransform.getScaleInstance(xInc,yInc));
        aTransf.concatenate(AffineTransform.getTranslateInstance(-center.getX(),-center.getY()));
        aplicateTransformation(aTransf, needSelected);
        hep.repaint(0);
    }
    
    public void rotate(double theta, boolean needSelected, boolean rotateAll){
        convertToSimpleShapes(); //If it is a triangle, it will be necessary to convert it to lines in order to rotate the shape
        Point2D center=getCenter(rotateAll);
        AffineTransform aTransf=AffineTransform.getRotateInstance(theta,center.getX(),center.getY());
        aplicateTransformation(aTransf,needSelected);
        hep.repaint(0);
    }
    
    private Point2D getCenter(boolean cellCenter){
        //Returns the central point of the edited shape when cellCenter==false, otherwise, returns the center of the cell
        if(!cellCenter){
            EditableShape current=null;
            GeneralPath gp=new GeneralPath();
            java.util.Enumeration e=vShapes.elements();
            while (e.hasMoreElements()){
                current=(EditableShape)e.nextElement();
                gp.append(current,false);
            }
            Rectangle2D r=gp.getBounds(); //to calculate the central point
            return new Point2D.Double(r.getCenterX(),r.getCenterY());
        }
        else return new Point2D.Double(hep.getPreviewPanel().getX(),hep.getPreviewPanel().getY());
    }
    
    private void convertToSimpleShapes(){
        //If the edited shape is a rectangle or a ellipse, transform it to a set of segments or cubic lines
        EditableShape current=null;
        java.util.Enumeration e=vShapes.elements();
        while (e.hasMoreElements()){
            current=(EditableShape)e.nextElement();
            if(current instanceof EditableRectangle){ //Rectangular shapes must be converted to simple shapes in order to rotate it
                vShapes.remove(current);
                EditableShape[] lines=((EditableRectangle)current).divide(-1,-1,false); //Do no add any point
                for (int i=0;i<lines.length;i++)
                    if(lines[i]!=null)
                        vShapes.add(lines[i]);
            }
        }
    }
    
    private EditableShape getSelectedShape(boolean hasToBeALine){ //Returns the selected line when there is only one
        java.util.Enumeration e=vShapes.elements();
        EditableShape current, selected=null;
        int i=0;
        while (e.hasMoreElements() && i<2){
            current=(EditableShape)e.nextElement();
            if(current.isSelected()){
                if(!hasToBeALine || current instanceof EditableLine2D){
                    selected=current;
                    i++;
                }
                else{
                    i=2; //Do nothing
                }
            }
        }
        if(i==1)
            return selected;
        else
            return null;
    }
    
    public void convertToBezier(){
        EditableShape selected=getSelectedShape(false);
        if(selected!=null){
            double x1=selected.getInitialPoint().getX();
            double y1=selected.getInitialPoint().getY();
            double x2=selected.getEndPoint().getX();
            double y2=selected.getEndPoint().getY();
            double ctrl1x=x1+((x2-x1)/3);
            double ctrl2x=x1+(2*((x2-x1)/3));
            double ctrl1y=y1+((y2-y1)/3);
            double ctrl2y=y1+(2*((y2-y1)/3));
            EditableCubicCurve2D bez=new EditableCubicCurve2D(x1,y1,ctrl1x,ctrl1y,ctrl2x,ctrl2y,x2,y2);
            bez.setSelected(true);
            vShapes.remove(selected);
            vShapes.add(bez);
        }
    }
    
    public void convertToQuad(){
        EditableShape selected=getSelectedShape(false);
        if(selected!=null){
            double x1=selected.getInitialPoint().getX();
            double y1=selected.getInitialPoint().getY();
            double x2=selected.getEndPoint().getX();
            double y2=selected.getEndPoint().getY();
            double ctrlx=x1+((x2-x1)/2);
            double ctrly=y1+((y2-y1)/2);
            EditableQuadCurve2D quad=new EditableQuadCurve2D(x1,y1,ctrlx,ctrly,x2,y2);
            quad.setSelected(true);
            vShapes.remove(selected);
            vShapes.add(quad);
        }
    }
    
    public void convertToLine(){
        EditableShape selected=getSelectedShape(false);
        if(selected!=null && !(selected instanceof EditableRectangle)){
            EditableLine2D line=new EditableLine2D(selected.getInitialPoint(),selected.getEndPoint());
            line.setSelected(true);
            vShapes.remove(selected);
            vShapes.add(line);
        }
        else if(selected!=null && selected instanceof EditableRectangle){ //Convert a rectangle into four lines
            vShapes.remove(selected);
            EditableShape[] lines=((EditableRectangle)selected).divide(-1,-1,false); //Do not add any point
            for (int i=0;i<lines.length;i++)
                if (lines[i]!=null)
                    vShapes.add(lines[i]);
        }
    }
    
    public void notifyShapeChanged(){
        java.util.Enumeration e=vPointListeners.elements();
        while (e.hasMoreElements()){
            PointListener pl=(PointListener)e.nextElement();
            pl.shapeChanged();
        }
    }
    
    public void addPointListener(PointListener listener){
        vPointListeners.add(listener);
    }
    
    public void undoLastMove(Vector vRedrawingLines, Vector vRedrawingLinesBeforeModify){
        vShapes.removeAll(vRedrawingLines);
        vShapes.addAll(vRedrawingLinesBeforeModify);
        vRedrawingLines.clear();
    }
    
    private boolean isIntoArea(Vector vShapes, boolean move){
        boolean isInto=true;
        Rectangle2D r=new Rectangle2D.Double(hep.previewArea.getX()-1,hep.previewArea.getY()-1,hep.previewArea.getWidth()+2,hep.previewArea.getHeight()+2);
        java.util.Enumeration e=vShapes.elements();
        Point2D[] borders;
        while (e.hasMoreElements() && isInto){
            EditableShape es;
            if(!move)
                es=(EditableShape)e.nextElement();
            else{
                es=(EditableShape)((EditableShape)e.nextElement()).clone();
                es.transform(AffineTransform.getTranslateInstance(finX-iniX,finY-iniY));
            }
            
            borders=es.getBorders();
            if(borders==null)
                continue;
            for(int j=0;j<borders.length && isInto ;j++)
                isInto=r.contains(borders[j]);
        }
        return isInto;
    }
    
    private void joinPolygon(){
        if(vShapes.size()>=2){
            vShapes.add(new EditableLine2D(lastPoint.getX(),lastPoint.getY(),iniPoint.getX(),iniPoint.getY()));
        }
        else vShapes.clear();
        creatingPolygon=false;
        lastPoint=null;
        iniPoint=null;
        if(bSelectedPoint)
            deselectBorder();
        bSelectedPoint=false;
        hep.setDrawingMode(SELECTING);
    }
    
    public void mouseDragged(java.awt.event.MouseEvent mouseEvent) {
        if((mouseEvent.getModifiers()&java.awt.event.MouseEvent.BUTTON1_MASK)==0)
            return; //Button 1 was not pressed
        Point2D mousePoint=getTransformedPoint(mouseEvent.getPoint(),true);
        
        if(bMoving)
            hep.setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
        
        if(mousePoint.getX()<hep.previewArea.x 
        || mousePoint.getY()<hep.previewArea.y 
        || mousePoint.getX()>hep.previewArea.x+hep.previewArea.getWidth() 
        || mousePoint.getY()>hep.previewArea.y+hep.previewArea.getHeight()){
            return;
        }
        
        vShapeBeforeModify=(drawingMode==SELECTING && !bMoving)?cloneVector(vRedrawingLines):cloneVector(vCopied);
        EditableShape near=null;
        
        Point2D nearDrawn=aproximationToDrawnBorder(mouseEvent.getX(),mouseEvent.getY());
        if(nearDrawn!=null && EditableShapeConstants.pointsOnGrid){
            finX=nearDrawn.getX();
            finY=nearDrawn.getY();
        }
        else{
            finX=mousePoint.getX();
            finY=mousePoint.getY();
        }
        
        if(creatingRect||creatingEllipse){
            near=aproximationToLine(finX,finY);
            hep.getPreviewPanel().repaint(0);
        }
        else if(bRedrawingLines){
            redrawingLines(finX,finY);
            near=aproximationToLine(finX,finY,vRedrawingLines); //we are over a shape corner not selected near (at less)...
            hep.repaint(0);
        }
        else if(bMoving || esInterior(finX,finY)){
            near=nearestLine(finX,finY);
            if(near!=null){
                double d=near.distanceTo(finX,finY);
                if(!bMoving && d>(EditableShapeConstants.selectLength/2))
                    cut(finX,finY);
            }
            hep.repaint(0);
        }
        if(creatingRect||creatingEllipse||bRedrawingLines){
            if((near!=null || nearDrawn!=null) && EditableShapeConstants.pointsOnGrid)
                hep.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
            else
                hep.setCursor(cursors[PEN_CURSOR]);
        }
        boolean b=isIntoArea((drawingMode==SELECTING && !bMoving)?vRedrawingLines:vCopied,(bMoving));
        if(!b){
            if(drawingMode==SELECTING && !bMoving){
                undoLastMove(vRedrawingLines,vShapeBeforeModify);
                finX=lastFinX;
                finY=lastFinY;
            }
            if(bMoving){
                finX=lastFinX;
                finY=lastFinY;
            }
        }
        else {
            lastFinX=finX;
            lastFinY=finY;
        }
        
        if(bResizing)
            setResizingCursor(resizingDirection);
    }
    
    protected boolean esCantonada(double x, double y){
        EditableShape near=aproximationToLine(x,y);
        return (near!=null || aproximationToDrawnBorder(x,y)!=null);
    }
    
    protected boolean esSobreFigura(double x, double y){
        int minimumDistance=Math.max(Math.max(2,EditableShapeConstants.selectLength/2),EditableShapeConstants.gridWidth);
        double dist=distanceToNearest(x,y);
        return (dist>=0 && dist<minimumDistance);
    }
    
    protected boolean esInterior(double x, double y){
        return (current!=null && current.contains(x,y));
    }
    
    public void mouseMoved(java.awt.event.MouseEvent mouseEvent) {
        
        double x,y;
        Point2D mousePoint=mouseEvent.getPoint();
        
        boolean esCantonada=esCantonada(mouseEvent.getPoint().getX(),mouseEvent.getPoint().getY());
        if(drawingMode==NEW_POINT || (esCantonada && EditableShapeConstants.pointsOnGrid)){
            x=mousePoint.getX();
            y=mousePoint.getY();
        }
        else{
            x=mousePoint.getX();
            y=mousePoint.getY();
        }
        
        if(x<hep.previewArea.x || y<hep.previewArea.y || x>hep.previewArea.x+hep.previewArea.getWidth() || y>hep.previewArea.y+hep.previewArea.getHeight())
            return;
        if(drawingMode!=NEW_POINT){
            if(esCantonada && (!creatingPolygon || EditableShapeConstants.pointsOnGrid))
                hep.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
            else if(creatingPolygon)
                hep.setCursor(cursors[PEN_CURSOR]);
            else if(!bMoving && esSobreFigura(x,y))
                hep.setCursor(cursors[CIRCLE_CURSOR]);
            else if(esInterior(x,y)) 
                hep.setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
            else 
                hep.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
        }
        if(drawingMode==NEW_POINT){
            if(esSobreFigura(x,y)){
                bSpecialLine=true; //temporally paint it in another color
                specialLine=nearestLine(x,y);
                hep.setCursor(cursors[PEN_CURSOR]);
                hep.repaint(0);
            }
            else{
                boolean willRepaint=bSpecialLine;
                bSpecialLine=false;
                hep.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
                if(willRepaint)
                    hep.repaint(0);
            }
        }
        if(bMoving){
            if(iniX==-1){
                deleteSelected(true);
                iniX=x;
                iniY=y;
            }
            finX=x;
            finY=y;
            hep.repaint(0);
        }
        if(creatingPolygon) {
            finX=x;
            finY=y;
            hep.repaint(0);
        }
        if(canResize){
            if(!bResizing){
                int resizing=getResizing(mousePoint);
                if(resizing!=NO_RESIZING)
                    setResizingCursor(resizing);
            }
            else 
                setResizingCursor(resizingDirection);
        }
    }
    
    protected int getResizing(Point2D mousePoint){
        if(!canResize)
            return NO_RESIZING;
        ShapeData sd=hep.getHoles().getEnclosingShapeData();
        Rectangle r=hep.getPreviewArea();
        double width=r.getWidth();
        double height=r.getHeight();
        AffineTransform at=AffineTransform.getTranslateInstance(-hep.previewArea.x,-hep.previewArea.y);
        at.transform(mousePoint,mousePoint);
        if(mousePoint.getX()==(width-1) && mousePoint.getY()==(height-1))
            return SOUTH_EAST;
        else if(mousePoint.getX()==(width-1))
            return EAST;
        else if (mousePoint.getY()==(height-1))
            return SOUTH;
        else
            return NO_RESIZING;
    }
    
    protected void setResizingCursor(int resizing){
        if(resizing==EAST)
            hep.setCursor(Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR),false);
        else if(resizing==SOUTH)
            hep.setCursor(Cursor.getPredefinedCursor(Cursor.S_RESIZE_CURSOR),false);
        else if(resizing==SOUTH_EAST)
            hep.setCursor(Cursor.getPredefinedCursor(Cursor.SE_RESIZE_CURSOR),false);
    }
    
    protected void selectBorder(double x, double y){
        java.util.Enumeration e=vShapes.elements();
        while (e.hasMoreElements()){
            EditableShape s=(EditableShape)e.nextElement();
            s.selectBorder(x,y);
        }
    }
    
    protected void deselectBorder(){
        java.util.Enumeration e=vShapes.elements();
        while (e.hasMoreElements()){
            EditableShape s=(EditableShape)e.nextElement();
            s.deselectBorder();
        }
    }
    
    protected boolean removeNullLines(java.util.Vector vRedrawingLines){
        //Removes from vRedrawingLines all the lines having the two points in (approximately) the same co-ordinates
        boolean canRemove=false;
        java.util.Enumeration e=vRedrawingLines.elements();
        while (e.hasMoreElements() && !canRemove){
            EditableShape s=(EditableShape)e.nextElement();
            if(s instanceof EditableLine2D){
                Point2D [] p=s.getBorders();
                if(p.length>1){
                    Rectangle r=new Rectangle((int)(p[0].getX())-(EditableShapeConstants.selectLength/2),(int)(p[0].getY())-(EditableShapeConstants.selectLength/2),EditableShapeConstants.selectLength,EditableShapeConstants.selectLength);
                    if(r.contains(p[1].getX(),p[1].getY())){
                        //This line is prescindible
                        if(vShapes.size()>=4){ //Do not delete any element when there are only 3 or les (except if it's a cut)
                            canRemove=true;
                            vShapes.remove(s);
                            joinAdjacentsTo(s,vShapes);
                        }
                    }
                }
            }
        }
        return canRemove;
    }
    
    public void mouseClicked(java.awt.event.MouseEvent mouseEvent) {
        Point2D mousePoint=mouseEvent.getPoint();
        boolean bSobreFigura=esSobreFigura(mousePoint.getX(),mousePoint.getY());
        if(drawingMode!=NEW_POINT && drawingMode!=DRAWING_POLYGON && !bSobreFigura && selectDrawnShape(mousePoint) && !creatingPolygon){
            notifyShapeChanged();
            hep.repaint(0);
        }
        else if(drawingMode!=NEW_POINT && bSobreFigura && !creatingPolygon){
            EditableShape line=nearestLine(mousePoint.getX(),mousePoint.getY());
            if(line!=null){ //The caller wants to select a fragment of the polygon
                if(esCantonada(mousePoint.getX(),mousePoint.getY())) {
                    Point2D p=line.getNearestBorder(mousePoint.getX(),mousePoint.getY());
                    deSelectAll();
                    bSelectedPoint=true;
                    selectBorder(p.getX(),p.getY());
                    hep.repaint(0);
                }
                else{
                    if(bSelectedPoint)
                        deselectBorder();
                    bSelectedPoint=false;
                    if(line.isSelected())
                        line.setSelected(false);
                    else{
                        if((mouseEvent.getModifiers()&java.awt.event.MouseEvent.SHIFT_MASK)==0)
                            deSelectAll();
                        line.setSelected(true);
                    }
                    notifyShapeChanged();
                    hep.repaint(0);
                }
            }
        }
        if(creatingPolygon){
            if(mouseEvent.getClickCount()==2)
                joinPolygon();
            else{                
                mousePoint=mouseEvent.getPoint();                
                EditableShape near=aproximationToLine(mousePoint.getX(),mousePoint.getY(),vRedrawingLines);
                Point2D nearDrawn=null;
                Point2D nearDrawnOther=aproximationToDrawnBorder(mousePoint.getX(),mousePoint.getY());
                if(near!=null){ // if the ending point is near the mouse, approximate to it
                    nearDrawn=near.getNearestBorder(mousePoint.getX(),mousePoint.getY());
                }
                
                if(nearDrawnOther!=null && EditableShapeConstants.pointsOnGrid){
                    finX=nearDrawnOther.getX();
                    finY=nearDrawnOther.getY();
                }
                else{
                    mousePoint=getTransformedPoint(mouseEvent.getPoint(),true);
                    finX=mousePoint.getX();
                    finY=mousePoint.getY();
                }
                
                if(lastPoint!=null){ // isn't the first point
                    if(nearDrawn!=null && iniPoint.getX()==nearDrawn.getX() && iniPoint.getY()==nearDrawn.getY()){//Has clicked over the starting point of the polygon
                        if(vShapes.size()>=2)
                            joinPolygon();
                    }
                    else{
                        if(nearDrawn==null){ //Points cannot be repeated                            
                            vShapes.add(new EditableLine2D(lastPoint.getX(),lastPoint.getY(),finX,finY));
                            lastPoint=new Point2D.Double(finX,finY);
                        }
                    }
                }
                else { //it's the first point
                    iniPoint=new Point2D.Double(finX,finY);
                    lastPoint=iniPoint;
                }
            }
        }
    }
    
    public void mouseEntered(java.awt.event.MouseEvent mouseEvent) {
    }
    
    public void mouseExited(java.awt.event.MouseEvent mouseEvent) {
    }
    
    public void mousePressed(java.awt.event.MouseEvent mouseEvent) {
        Point2D mousePoint=getTransformedPoint(mouseEvent.getPoint(),drawingMode!=SELECTING); //when selecting, the point doesn't must be in the grid
        int x=(int)mousePoint.getX();
        int y=(int)mousePoint.getY();
        
        if(canResize){
            int resizing=getResizing(mousePoint);
            if(resizing!=NO_RESIZING){
                if(drawingMode!=SELECTING)
                    hep.setDrawingMode(SELECTING);
                bResizing=true;
                resizingDirection=resizing;
            }
        }
        
        if(x<hep.previewArea.x || y<hep.previewArea.y 
        || x>hep.previewArea.x+hep.previewArea.getWidth() || y>hep.previewArea.y+hep.previewArea.getHeight())
            return;
        if(bMoving){ //CTRL+X has been pressed while moving a shape
            paste(finX-iniX,finY-iniY);
            bMoving=false;
        }
        iniX=x;
        iniY=y;
        
        if(drawingMode==SELECTING && !bMoving){
            clicatISeleccionada(x,y,false); //false: drag is possible despite of having the shape selected or unselected
            if(vRedrawingLines.size()>0)
                bRedrawingLines=true; //Redraw lines when clicking on a corner
        }
        else if((drawingMode==DRAWING_RECT || drawingMode==DRAWING_ELLIPSE || drawingMode==DRAWING_POLYGON)&&!hasSelectedDrawnShape(mouseEvent.getPoint())){
            if(drawingMode==DRAWING_RECT)
                creatingRect=true;
            else if(drawingMode==DRAWING_ELLIPSE)
                creatingEllipse=true;
            else
                creatingPolygon=true;
            EditableShape near=aproximationToLine(x,y);
            Point2D pNear=aproximationToDrawnBorder(x,y);
            if (near!=null){
                pNear=near.getNearestBorder(x,y);
            }
            if (pNear!=null){
                iniX=pNear.getX();
                iniY=pNear.getY();
            }
            else{
                iniX=x;
                iniY=y;
            }
            finX=iniX;
            finY=iniY;
            hep.repaint(0);
        }
        else if(drawingMode==NEW_POINT){
            EditableShape lineToDivide=specialLine;
            EditableShape near=aproximationToLine(x,y,null);
            Point2D nearDrawn=null;
            boolean isSelect=false;
            if(near!=null)
                nearDrawn=near.getNearestBorder(x,y);
            if(drawingMode==NEW_POINT && (lineToDivide!=null && bSpecialLine 
            && (nearDrawn==null || lineToDivide instanceof EditableEllipse2D 
                || lineToDivide instanceof EditableCubicCurve2D 
                || lineToDivide instanceof EditableQuadCurve2D))){ //A point is added only when the current point is not over another one
                divideShape(lineToDivide,x,y);
            }
            else{
                isSelect=selectDrawnShape(mouseEvent.getPoint());
            }
            if(!isSelect){ //A point has been added, or a click has been done out of any shape
                hep.setDrawingMode(SELECTING);
            }
        }
    }
    
    public void mouseReleased(java.awt.event.MouseEvent mouseEvent) {
        if((mouseEvent.getModifiers()&java.awt.event.MouseEvent.BUTTON1_MASK)==0){//The button 1 was not pressed
            return;
        }
        if(bMoving){
            paste(finX-iniX,finY-iniY);
            bMoving=false;
            deSelectAll();
        }
        
        Point2D mousePoint=mouseEvent.getPoint();
        
        EditableShape near=aproximationToLine(mousePoint.getX(),mousePoint.getY(),vRedrawingLines);
        Point2D nearDrawnPropi=null;
        Point2D nearDrawn=aproximationToDrawnBorder(mousePoint.getX(),mousePoint.getY()); //Corner of a non-active polygon
        if(near!=null || nearDrawn!=null)
            hep.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
        else
            hep.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
        if(near!=null){ // if there is any nearest point, approximate the ending point to it
            nearDrawnPropi=near.getNearestBorder(mousePoint.getX(),mousePoint.getY()); //Corner of the active polygon
        }
        
        mousePoint=getTransformedPoint(mouseEvent.getPoint(),true);
        if(!(mousePoint.getX()<hep.previewArea.x || mousePoint.getY()<hep.previewArea.y 
           || mousePoint.getX()>hep.previewArea.x+hep.previewArea.getWidth() 
           || mousePoint.getY()>hep.previewArea.y+hep.previewArea.getHeight())){
            if(nearDrawn!=null && EditableShapeConstants.pointsOnGrid){ //Only when approaching
                finX=nearDrawn.getX();
                finY=nearDrawn.getY();
            }
            else{
                finX=mousePoint.getX(); //This point is maintained as long as the pointer remains into the drawing area
                finY=mousePoint.getY();
            }
        }
        
        if((drawingMode==SELECTING && !bMoving && nearDrawnPropi!=null)|| (!creatingPolygon && vShapes.size()>1 && !validateShape())){
            boolean canRemove=removeNullLines(vRedrawingLines);
            if(!canRemove){
                undoLastMove(vRedrawingLines,vRedrawingLinesBeforeModify);
                finX=iniX;
                finY=iniY;
            }
        }
        else if(bRedrawingLines){
            setEndToVector(finX,finY,vRedrawingLines);
            bRedrawingLines=false;
            vRedrawingLines.clear();
            vRedrawingLinesBeforeModify.clear();
        }
        if(creatingRect){
            creatingRect=false;
            vShapes.add(new EditableRectangle((int)iniX,(int)iniY,(int)(finX-iniX),(int)(finY-iniY)));
            if(hep.currentShape>=hep.getHoles().getNumCells()){ //Reserve space for the new rectangle when confirmed(in order to give it a name)
                ShapeData sd=new ShapeData();
                sd.comment = ""+hep.currentShape;
                hep.getHoles().addShape(sd);
                hep.updateList();
            }
        }
        if(creatingEllipse){
            creatingEllipse=false;
            vShapes.add(new EditableEllipse2D((int)iniX,(int)iniY,(int)(finX-iniX),(int)(finY-iniY)));
            if(hep.currentShape>=hep.getHoles().getNumCells()){ //Reserve space for the new rectangle when confirmed(in order to give it a name)
                ShapeData sd=new ShapeData();
                sd.comment = ""+hep.currentShape;
                hep.getHoles().addShape(sd);
                hep.updateList();
            }
        }
        
        if(bResizing){
            if(resizingDirection!=NO_RESIZING){
                double x=mousePoint.getX();
                double y=mousePoint.getY();
                double xInc=x-iniX;
                double yInc=y-iniY;
                if(resizingDirection==EAST)
                    yInc=0;
                else if(resizingDirection==SOUTH)
                    xInc=0;
                hep.incDrawingArea(xInc,yInc);
            }
            bResizing=false;
        }
        
        ShapeData sd=getShapeData();
        current=(sd!=null)?sd.getShape(hep.previewArea):null; //Update the modifications to the shape
        bSelectingArea=false;
        hep.repaint(0);
        if(!creatingPolygon)
            notifyShapeChanged();
    }
    
    public class KeyHandler extends KeyAdapter{
        public void keyPressed(KeyEvent e){
            if(e.getKeyCode()==e.VK_DELETE){
                deleteSelected(false);
                hep.shapeChanged();
            }
        }
    }
    
    private double viewIniX=-1;
    private double viewIniY=-1;
    
}

Generated by  Doxygen 1.6.0   Back to index