/* * File : EditableRectangle.java * Created : 26-feb-2002 13:32 * 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 java.awt.geom.*; import java.awt.*; /** * * @author allastar * @version 1.0 */ public class EditableRectangle extends Rectangle2D.Double implements EditableShape, Cloneable{ protected boolean selected=false; protected int border=-1; private int selectedBorder=-1; protected Point2D p1, p2, p3, p4; protected Point2D lastP1, lastP2; /** Creates new EditableRectangle */ public EditableRectangle(Point2D ini, Point2D end){ super(); setLimits(ini, end); } public EditableRectangle(int x, int y, int width, int height){ super(); setLimits(x, y, width, height); } public void setLimits(int x, int y, int width, int height){ if (width<0){ width*=-1; x-=width; } if (height<0){ height*=-1; y-=height; } p1=new Point2D.Double(x,y); p2=new Point2D.Double(x+width, y+height); p3=new Point2D.Double(); p4=new Point2D.Double(); lastP1=new Point2D.Double(1,1); lastP2=new Point2D.Double(1,1); setRect(p1,p2); } public void setLimits(Point2D ini, Point2D end){ p1=new Point2D.Double(); p2=new Point2D.Double(); p3=new Point2D.Double(); p4=new Point2D.Double(); lastP1=new Point2D.Double(1,1); lastP2=new Point2D.Double(1,1); setRect(ini, end); } public EditableShape[] divide(double x, double y) { //Deixara de ser un Rectangle. Retornem un array amb 5 linies return divide(x, y, true); } public EditableShape[] divide(double x, double y, boolean newPoint){ //Retornem un array amb les noves linies del Rectangle. Si newPoint=true partim la recta que conte (x,y) EditableShape[] lines=new EditableShape[5]; lines[0]=new EditableLine2D(p1,p3); lines[1]=new EditableLine2D(p3,p2); lines[2]=new EditableLine2D(p2,p4); lines[3]=new EditableLine2D(p4,p1); if (newPoint){ double minDist=((EditableLine2D)lines[0]).ptLineDistSq(x,y); short nearestLine=0; for (short i=1;i<4;i++){ double dist=((EditableLine2D)lines[i]).ptLineDistSq(x,y); if (dist<minDist){ minDist=dist; nearestLine=i; } } Point2D p=new Point2D.Double(x,y); Point2D p1=((EditableLine2D)lines[nearestLine]).getP1(); Point2D p2=((EditableLine2D)lines[nearestLine]).getP2(); lines[nearestLine]=new EditableLine2D(p1,p); lines[4]=new EditableLine2D(p,p2); } return lines; } public void setSelected(boolean b) { selected=b; } public double distanceTo(double x, double y) { Line2D l1=new Line2D.Double(p1,p3); Line2D l2=new Line2D.Double(p3,p2); Line2D l3=new Line2D.Double(p2,p4); Line2D l4=new Line2D.Double(p4,p1); double d1=l1.ptLineDistSq(x,y); double d2=l2.ptLineDistSq(x,y); double d3=l3.ptLineDistSq(x,y); double d4=l4.ptLineDistSq(x,y); double d5,d6; if (d1<d2) d5=d1; else d5=d2; if (d3<d4) d6=d3; else d6=d4; if (d5<d6) return d5; else return d6; } public boolean hasClickedBorder(double x, double y, boolean needSelected) { boolean hasClicked=false; if (!needSelected || selected){ Rectangle r1=new Rectangle((int)p1.getX()-(EditableShapeConstants.selectLength/2),(int)p1.getY()-(EditableShapeConstants.selectLength/2),EditableShapeConstants.selectLength,EditableShapeConstants.selectLength); Rectangle r2=new Rectangle((int)p2.getX()-(EditableShapeConstants.selectLength/2),(int)p2.getY()-(EditableShapeConstants.selectLength/2),EditableShapeConstants.selectLength,EditableShapeConstants.selectLength); Rectangle r3=new Rectangle((int)p3.getX()-(EditableShapeConstants.selectLength/2),(int)p3.getY()-(EditableShapeConstants.selectLength/2),EditableShapeConstants.selectLength,EditableShapeConstants.selectLength); Rectangle r4=new Rectangle((int)p4.getX()-(EditableShapeConstants.selectLength/2),(int)p4.getY()-(EditableShapeConstants.selectLength/2),EditableShapeConstants.selectLength,EditableShapeConstants.selectLength); if (r1.contains(x,y)){ border=1; hasClicked=true; } else if (r2.contains(x,y)){ border=2; hasClicked=true; } else if (r3.contains(x,y)){ border=3; hasClicked=true; } else if (r4.contains(x,y)){ border=4; hasClicked=true; } } return hasClicked; } public void paintSelection(java.awt.Graphics g) { g.setColor(Color.black); drawBorders(g); g.setColor(EditableShapeConstants.selectedColor); } public boolean isSelected() { return selected; } public void aproximateNearestBorder(double x, double y) { //getNearestBorder(x,y).setLocation(x,y); boolean b=hasClickedBorder(x,y,false); //Marca la cantonada mes propera changeBorder(x,y); //Posa la cantonada mes propera a (x,y) en la posicio (x,y) } public void paintWithColor(java.awt.Graphics g, int drawingMode, java.awt.Color c) { g.setColor(EditableShapeConstants.BORDER_COLOR); drawBorders(g); if (selected){ paintSelection(g); } else if (drawingMode==PolygonDrawPanel.NEW_POINT){ g.setColor(Color.red); drawBorders(g); g.setColor(c); } else g.setColor(c); g.drawRect((int)getX(),(int)getY(),(int)getWidth(),(int)getHeight()); } public void transform(java.awt.geom.AffineTransform aTransf) { aTransf.transform(p1,p1); aTransf.transform(p2,p2); setRect(p1,p2); } public boolean isAdjacentTo(java.awt.geom.Point2D p) { if (p.equals(p1)||p.equals(p2)||p.equals(p3)||p.equals(p4)) return true; else return false; } public boolean isInto(java.awt.geom.Rectangle2D r) { return (r.intersects(this));//||r.contains(this)); } public java.awt.geom.Point2D getEndPoint() { return p2; } private void setRect(Point2D ini, Point2D end){ if (!(lastP1.equals(ini) && lastP2.equals(end))){ p1=ini; p2=end; p3.setLocation(p2.getX(),p1.getY()); p4.setLocation(p1.getX(),p2.getY()); double x=Math.min(p1.getX(),p2.getX()); double y=Math.min(p1.getY(),p2.getY()); double width=Math.abs(p2.getX()-p1.getX()); double height=Math.abs(p2.getY()-p1.getY()); //System.out.println("x:"+x+" y:"+y+" w:"+width+" h:"+height); setRect(x,y,width,height); lastP1=(Point2D)p1.clone(); lastP2=(Point2D)p2.clone(); } } public void changeBorder(double x, double y) { Point2D newPoint=new Point2D.Double(x,y); if (border==1){ setRect(newPoint,p2); } else if (border==2){ setRect(p1,newPoint); } else if (border==3){ p1.setLocation(p1.getX(),newPoint.getY()); p2.setLocation(newPoint.getX(),p2.getY()); setRect(p1,p2); } else if (border==4){ p1.setLocation(newPoint.getX(),p1.getY()); p2.setLocation(p2.getX(),newPoint.getY()); setRect(p1,p2); } } public void drawBorders(java.awt.Graphics g) { g.drawRect((int)p1.getX()-(EditableShapeConstants.selectLength/2),(int)p1.getY()-(EditableShapeConstants.selectLength/2),EditableShapeConstants.selectLength,EditableShapeConstants.selectLength); g.drawRect((int)p2.getX()-(EditableShapeConstants.selectLength/2),(int)p2.getY()-(EditableShapeConstants.selectLength/2),EditableShapeConstants.selectLength,EditableShapeConstants.selectLength); g.drawRect((int)p3.getX()-(EditableShapeConstants.selectLength/2),(int)p3.getY()-(EditableShapeConstants.selectLength/2),EditableShapeConstants.selectLength,EditableShapeConstants.selectLength); g.drawRect((int)p4.getX()-(EditableShapeConstants.selectLength/2),(int)p4.getY()-(EditableShapeConstants.selectLength/2),EditableShapeConstants.selectLength,EditableShapeConstants.selectLength); g.setColor(EditableShapeConstants.SELECTED_BORDER_COLOR); if (selectedBorder==1){ g.fillRect((int)p1.getX()-(EditableShapeConstants.selectLength/2),(int)p1.getY()-(EditableShapeConstants.selectLength/2),EditableShapeConstants.selectLength,EditableShapeConstants.selectLength); } else if (selectedBorder==2){ g.fillRect((int)p2.getX()-(EditableShapeConstants.selectLength/2),(int)p2.getY()-(EditableShapeConstants.selectLength/2),EditableShapeConstants.selectLength,EditableShapeConstants.selectLength); } else if (selectedBorder==3){ g.fillRect((int)p3.getX()-(EditableShapeConstants.selectLength/2),(int)p3.getY()-(EditableShapeConstants.selectLength/2),EditableShapeConstants.selectLength,EditableShapeConstants.selectLength); } else if (selectedBorder==4){ g.fillRect((int)p4.getX()-(EditableShapeConstants.selectLength/2),(int)p4.getY()-(EditableShapeConstants.selectLength/2),EditableShapeConstants.selectLength,EditableShapeConstants.selectLength); } } public java.awt.geom.Point2D getInitialPoint() { return getLocation(); } public void paint(java.awt.Graphics g, int drawingMode) { paintWithColor(g,drawingMode,EditableShapeConstants.defaultColor); } public java.awt.geom.Point2D getNearestBorder(double x, double y) { double d1=p1.distance(x,y); double d2=p2.distance(x,y); double d3=p3.distance(x,y); double d4=p4.distance(x,y); Point2D p5,p6; if (d1<d2) p5=p1; else p5=p2; if (d3<d4) p6=p3; else p6=p4; if (p5.distance(x,y)<p6.distance(x,y)) return p5; else return p6; } public Point2D getLocation(){ //return p1; return new Point2D.Double(getX(),getY()); } /*public Rectangle2D getRectangle(){ return new Rectangle2D.Double(getX(),getY(),getWidth(),getHeight()); }*/ public Object clone(){ return new EditableRectangle(getLocation(),new Point2D.Double(getLocation().getX()+getWidth(),getLocation().getY()+getHeight())); } public java.awt.geom.Point2D[] getBorders() { return new Point2D[]{p1,p2,p3,p4}; } public void selectBorder(double x, double y) { Point2D p=new Point2D.Double(x,y); if (p1.equals(p)) selectedBorder=1; else if (p2.equals(p)) selectedBorder=2; else if (p3.equals(p)) selectedBorder=3; else if (p4.equals(p)) selectedBorder=4; else selectedBorder=-1; } public void deselectBorder(){ selectedBorder=-1; } public boolean hasSelectedBorder(){ return (selectedBorder!=-1); } public java.awt.geom.Point2D getNotSelectedBorder(){ if (selectedBorder==1) return p1; else if (selectedBorder==2) return p2; else if (selectedBorder==3) return p3; else return p4; } }