jfroundedrectangle.java

来自「用Java开发的、实现类似Visio功能的应用程序源码」· Java 代码 · 共 476 行

JAVA
476
字号
/**
 *    $Id:JFRoundedRectangle.java $
 *
 *    Copyright 2004 ~ 2005  JingFei International Cooperation LTD. All rights reserved. *
 */
package com.jfimagine.jfgraph.shape.rectangle;


import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;

import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.geom.GeneralPath;
import java.awt.BasicStroke;

import com.jfimagine.jfdom.Document;
import com.jfimagine.jfdom.Element;

import com.jfimagine.jfgraph.shape.rectangle.AbstractRectangle;
import com.jfimagine.jfgraph.shape.base.Node;
import com.jfimagine.jfgraph.shape.base.Port;
import com.jfimagine.jfgraph.shape.base.AbstractObject;
import com.jfimagine.jfgraph.shape.base.ShapeConst;
import com.jfimagine.jfgraph.shape.base.JFVersion;

import com.jfimagine.jfgraph.geom.JFPoint;
import com.jfimagine.jfgraph.geom.LineSeg;
import com.jfimagine.jfgraph.geom.Rect;
import com.jfimagine.jfgraph.geom.RoundedRect;
import com.jfimagine.jfgraph.geom.Arc;

 
import com.jfimagine.utils.log.*;
 
 /**
 * JFRoundedRectangle class.  
 * A rectangle class used to represents regular rectangle, parallelogram, trapezoid and isoceles trapezoid.
 *
 * @author     CookieMaker    
 *
 * @version $Revision: 1.00 $
 */  
 public class JFRoundedRectangle extends AbstractRectangle{

   /**
    *   A XML string tag represents a rounded rectangle.
    */
   public  static final String	 XML_ROUNDEDRECTANGLE		="JFRoundedRectangle";

   /**
    *   A XML string tag represents the corner radius of this rounded rectangle.
    */
   public  static final String	 XML_CORNERRADIUS		="cornerRadius";

   /**an internal log utility*/
   private JFLogger m_logger=JFLogManager.getLogger(this.getClass());
   
   /**
    *   Constructor for rectangle
    */
   public JFRoundedRectangle(){
   	setObjectType(ShapeConst.SHAPETYPE_RECT_ROUNDED);
   	setXMLTag(XML_ROUNDEDRECTANGLE);
   	m_rect	=new RoundedRect();
   }	

   /**
    *   Constructor for round rectangle.
    *
    *   @param x  X coordiate.
    *
    *   @param y  Y coordiate.
    *
    *   @param w  Width of this round rectangle.
    *
    *   @param h  Height of this round rectangle.
    *
    */ 	
   public JFRoundedRectangle(double x, double y, double w, double h){
   	setObjectType(ShapeConst.SHAPETYPE_RECT_ROUNDED);
   	setXMLTag(XML_ROUNDEDRECTANGLE);

   	m_rect	=new RoundedRect();

	addNode(x,y);
	addNode(x+w,y+h);
	   	
   	finishDrawing();
   }
   
   /**
    *   get the radius of current rounded rectangle.
    *
    *   @return The radius.
    *
    */ 	
   public double getRadius(){
   	return ((RoundedRect)m_rect).getRadius();
   }
 
   /**
    *   set the radius of current rounded rectangle.
    *
    *   @param radius The radius.
    *
    */ 	
   public void setRadius(double radius){
   	((RoundedRect)m_rect).setRadius(radius);
   }

   /**
    *   set default radius of current rounded rectangle.
    *
    */ 	
   public void setDefaultRadius(){
   	//get a radius that is 1/4 of a minimum side's length.
   	double sideLen=0;
   	JFPoint leftTop		=m_rect.getVertex(Rect.VERTEXTYPE_LEFTTOP);
   	JFPoint rightTop	=m_rect.getVertex(Rect.VERTEXTYPE_RIGHTTOP);
   	JFPoint leftBottom	=m_rect.getVertex(Rect.VERTEXTYPE_LEFTBOTTOM);
   	sideLen	=Math.min(leftTop.distance(rightTop),leftTop.distance(leftBottom));
   	sideLen	/=4;
   	setRadius(sideLen);
   }


   /**
    *   Creates a new AbstractObject of the same class and with the same contents as this object.
    *   This method implements the method defined in AbstractObject.
    * 
    *   @return  A clone of this class.
    *
    */ 	
  protected AbstractObject cloneMe() throws CloneNotSupportedException{
  	return new JFRoundedRectangle();
  }

   /**
    *   Init all ports of this diamond
    *   An object will always has its one or more stable ports and some customized ports,
    *   for dimond, it will has four stable ports as below,
    *   port1 at middle left,
    *   port2 at middle top,
    *   port3 at middle right,
    *   port4 at middle bottom,
    */ 	
   protected void initPorts(){

   	if (m_portList.size()==0){
   		try{
			LineSeg line;
   			Port port;
			
			//left
			line	=m_rect.getSide(Rect.SIDETYPE_LEFT);
   			port 	=new Port();
   			port.setFirstPoint(line.getPoint1());
   			port.setSecondPoint(line.getPoint2());
   			port.setPortPoint(line.getPoint1().midPoint(line.getPoint2()));
   			port.setParent(this);
   			m_portList.add(port);
   			
   			//top
			line	=m_rect.getSide(Rect.SIDETYPE_TOP);
   			port 	=new Port();
   			port.setFirstPoint(line.getPoint1());
   			port.setSecondPoint(line.getPoint2());
   			port.setPortPoint(line.getPoint1().midPoint(line.getPoint2()));
   			port.setParent(this);
   			m_portList.add(port);

			//right
			line	=m_rect.getSide(Rect.SIDETYPE_RIGHT);
   			port 	=new Port();
   			port.setFirstPoint(line.getPoint1());
   			port.setSecondPoint(line.getPoint2());
   			port.setPortPoint(line.getPoint1().midPoint(line.getPoint2()));
   			port.setParent(this);
   			m_portList.add(port);

			//bottom
			line	=m_rect.getSide(Rect.SIDETYPE_BOTTOM);
   			port 	=new Port();
   			port.setFirstPoint(line.getPoint1());
   			port.setSecondPoint(line.getPoint2());
   			port.setPortPoint(line.getPoint1().midPoint(line.getPoint2()));
   			port.setParent(this);
   			m_portList.add(port);
   			
   		}catch(Exception e){
   		}
   	}     
	
	m_portList.setZoomScale(getZoomScale());
   }



   /**
    *   Add a new node for current node list.
    *   here this method will always be called by DrawState class or any drawing class.
    * 
    *   @param x, y Coordinates of a new node.
    *
    */ 	
   public void addNode(double x, double y){
	super.addNode(x,y);
	
	if (m_nodeAdded>1){
   		//left-top point and right-bottom point:
   		JFPoint pnt1	=m_firstNode;
   		JFPoint	pnt2	=new JFPoint(x,y);
		    	
   		m_rect.setVertex(Rect.VERTEXTYPE_LEFTTOP,pnt1.getX(),pnt1.getY());
   		m_rect.setVertex(Rect.VERTEXTYPE_RIGHTTOP,x,pnt1.getY());
   		m_rect.setVertex(Rect.VERTEXTYPE_LEFTBOTTOM,pnt1.getX(),y);
   		m_rect.setVertex(Rect.VERTEXTYPE_RIGHTBOTTOM,x,y);
   		
		setDefaultRadius();
   		initNodes();
   	}
   }  


   /**
    *   Move/adjust a node of current object.
    * 
    *   @param  node Currently moving node.
    *
    *   @param  x, y Moving offsets.
    *
    *   @param g current drawing canvas.
    *
    */ 	
   public void  moveNode(Node node, double x, double y,Graphics g){
   	super.moveNode(node,x,y,g);

	if (node!=null){
		if (node.getXOffset()!=x || node.getYOffset()!=y){
			//move node and draw a new dragging shape.
			int vertexType	=getVertexTypeByNode(node);
   			m_rect.moveVertex(vertexType,x,y,Rect.VERTEXMOVETYPE_RECTANGLE);
			
			setDefaultRadius();
   			//init shape nodes.
			initNodes();
		   		
   			//draw current moving node and its relational lines
   			draw(g,true);
   		}
	}
   }

   /**
    *   Start move a node.
    * 
    *   @param  node The node will be moved.
    *
    */ 	
   public void  startMoveNode(Node node){
   	m_originalRect	=new RoundedRect((RoundedRect)m_rect); 
   	startMoveLabel();
   }

   /**
    *   finish move/adjust a node of current object.
    * 
    *   @param  node Currently moving node.
    *
    *   @param  x, y Moving offsets.
    *
    *   @param g current drawing canvas.
    *
    */ 	
   public void  finishMoveNode(Node node, double x, double y,Graphics g){
   	finishMoveLabel();
	LineSeg originalLine;
	LineSeg line;
   	
   	originalLine	=m_originalRect.getSide(Rect.SIDETYPE_TOP);
   	line		=m_rect.getSide(Rect.SIDETYPE_TOP);
	m_portList.movePort(originalLine.getPoint1(),originalLine.getPoint2(),line.getPoint1(),line.getPoint2());

   	originalLine	=m_originalRect.getSide(Rect.SIDETYPE_RIGHT);
   	line		=m_rect.getSide(Rect.SIDETYPE_RIGHT);
	m_portList.movePort(originalLine.getPoint1(),originalLine.getPoint2(),line.getPoint1(),line.getPoint2());

   	originalLine	=m_originalRect.getSide(Rect.SIDETYPE_BOTTOM);
   	line		=m_rect.getSide(Rect.SIDETYPE_BOTTOM);
	m_portList.movePort(originalLine.getPoint1(),originalLine.getPoint2(),line.getPoint1(),line.getPoint2());

   	originalLine	=m_originalRect.getSide(Rect.SIDETYPE_LEFT);
   	line		=m_rect.getSide(Rect.SIDETYPE_LEFT);
	m_portList.movePort(originalLine.getPoint1(),originalLine.getPoint2(),line.getPoint1(),line.getPoint2());

   }



   /**
    *   A temporary rectangle for drawing.
    */
   private	Rect	cornerRect;

   
   /**
    *   Draw current object on graphic canvas.
    * 
    *   @param  g  A graphic canvas.	
    *   @param  isXorMode If is in xor mode now.
    *
    */ 	
   public void  draw(Graphics g,boolean isXorMode){
   	if (g==null)
   		return;  

   	//if user hide this shape, we'll draw an 'invisible' bounds here.	
   	if (isInvisible()){
   		drawInvisibleBounds(g,isXorMode);
   		return;
   	}	

        if (!isXorMode)
		setTransparencyComposite(g);

  	double zoom	=getZoomScale();

	if (cornerRect==null)
		cornerRect	=new Rect();
		
   	//draw rounded corners.
   	RoundedRect rRect=(RoundedRect)m_rect;

   	JFPoint leftTop	 	=null;
   	JFPoint rightTop 	=null;
   	JFPoint rightBottom 	=null;
   	JFPoint leftBottom	=null;
   	GeneralPath path= new GeneralPath(GeneralPath.WIND_EVEN_ODD); 

    	rRect.getCornerRect(Rect.VERTEXTYPE_LEFTTOP,cornerRect);
   	leftTop	 	=cornerRect.getVertex(Rect.VERTEXTYPE_LEFTTOP);
   	rightTop 	=cornerRect.getVertex(Rect.VERTEXTYPE_RIGHTTOP);
   	rightBottom 	=cornerRect.getVertex(Rect.VERTEXTYPE_RIGHTBOTTOM);
   	leftBottom	=cornerRect.getVertex(Rect.VERTEXTYPE_LEFTBOTTOM);
	path.moveTo((float)(leftBottom.getX()*zoom),(float)(leftBottom.getY()*zoom));
	path.quadTo((float)(leftTop.getX()*zoom),(float)(leftTop.getY()*zoom),(float)(rightTop.getX()*zoom), (float)(rightTop.getY()*zoom));

    	rRect.getCornerRect(Rect.VERTEXTYPE_RIGHTTOP,cornerRect);
   	leftTop	 	=cornerRect.getVertex(Rect.VERTEXTYPE_LEFTTOP);
   	rightTop 	=cornerRect.getVertex(Rect.VERTEXTYPE_RIGHTTOP);
   	rightBottom 	=cornerRect.getVertex(Rect.VERTEXTYPE_RIGHTBOTTOM);
   	leftBottom	=cornerRect.getVertex(Rect.VERTEXTYPE_LEFTBOTTOM);
	path.lineTo((float)(leftBottom.getX()*zoom),(float)(leftBottom.getY()*zoom));
	path.quadTo((float)(leftTop.getX()*zoom),(float)(leftTop.getY()*zoom),(float)(rightTop.getX()*zoom), (float)(rightTop.getY()*zoom));

    	rRect.getCornerRect(Rect.VERTEXTYPE_RIGHTBOTTOM,cornerRect);
   	leftTop	 	=cornerRect.getVertex(Rect.VERTEXTYPE_LEFTTOP);
   	rightTop 	=cornerRect.getVertex(Rect.VERTEXTYPE_RIGHTTOP);
   	rightBottom 	=cornerRect.getVertex(Rect.VERTEXTYPE_RIGHTBOTTOM);
   	leftBottom	=cornerRect.getVertex(Rect.VERTEXTYPE_LEFTBOTTOM);
	path.lineTo((float)(leftBottom.getX()*zoom),(float)(leftBottom.getY()*zoom));
	path.quadTo((float)(leftTop.getX()*zoom),(float)(leftTop.getY()*zoom),(float)(rightTop.getX()*zoom), (float)(rightTop.getY()*zoom));

    	rRect.getCornerRect(Rect.VERTEXTYPE_LEFTBOTTOM,cornerRect);
   	leftTop	 	=cornerRect.getVertex(Rect.VERTEXTYPE_LEFTTOP);
   	rightTop 	=cornerRect.getVertex(Rect.VERTEXTYPE_RIGHTTOP);
   	rightBottom 	=cornerRect.getVertex(Rect.VERTEXTYPE_RIGHTBOTTOM);
   	leftBottom	=cornerRect.getVertex(Rect.VERTEXTYPE_LEFTBOTTOM);
	path.lineTo((float)(leftBottom.getX()*zoom),(float)(leftBottom.getY()*zoom));
	path.quadTo((float)(leftTop.getX()*zoom),(float)(leftTop.getY()*zoom),(float)(rightTop.getX()*zoom), (float)(rightTop.getY()*zoom));
	
   	path.closePath();

	try{                   
   		if (!isXorMode){
   			Rect rect	=getBounds();
   			rect.setValue(rect.getX() * zoom, rect.getY() * zoom, rect.getWidth() * zoom, rect.getHeight() * zoom);
   			m_fillFormat.draw(g,path,rect);
   			m_lineFormat.draw(g,path);
   		}else{
   			Graphics2D	g2=(Graphics2D)g;
   			g2.setStroke(new BasicStroke(1));
   			g2.setColor(Color.black);
   			g2.draw(path);
   		}

        	if (!isXorMode)
			restoreTransparencyComposite(g);
		        
		if (!isXorMode){   	
   			drawPort(g);
			drawLabel(g);
   		}
   	
   	}catch(Exception e){
   		m_logger.error("draw: "+e);	
   	}
   }   
 
 
   /**
    *   Append necessary xml child for current element,
    *   this method will be called internally by toDOM.
    * 
    *   @param  element A XML element to append child xml nodes
    *   @param version A file version notification so this object can obey the rules to save data.
    *
    */ 	
  protected void appendChildToDOM(Element element,JFVersion version){
  	if (element==null)
  		return;
  			
  	super.appendChildToDOM(element,version);
  		
    	element.addChild(new Element(XML_CORNERRADIUS,getRadius()));
  }


   /**
    *   Extract needed xml child from current element,
    *   this method will be called internally by fromDOM.
    * 
    *   @param  element An element used to extract needed xml child
    *   @param version A file version notification so this object can obey the rules to fetch data.
    *
    */ 	
  protected void extractChildFromDOM(Element element,JFVersion version){

      	if (element==null)
  	  	return;

      	super.extractChildFromDOM(element,version);
	setRadius(Element.getDoubleValue(element.getChild(XML_CORNERRADIUS)));
  }

 
   /**
    *   Save this object to a binary stream 
    * 
    *   @param stream An binary output stream
    *
    *   @param version A file version notification so this object can obey the rules to save data.
    *
    *   @exception  java.io.IOException
    *
    */ 	
  public void saveToStream(com.jfimagine.utils.io.JFWriter stream,JFVersion version) throws IOException{
	 super.saveToStream(stream,version);
	 stream.writeDouble(getRadius());
  }

   /**
    *   Load object data from a binary stream <br>
    * 
    *   @param stream An binary input stream
    *
    *   @param skipHead Skip head 'TYPE' check, an shape object should always 
    *   has its own shape-type stored, if this shape-type has already been readed,
    *   this loadFromStream should/could not read the type anymore.
    *
    *   @param version A file version notification so this object can obey the rules to fetch data.
    *
    *   @exception  java.io.IOException
    *
    */ 	
  public void loadFromStream(com.jfimagine.utils.io.JFReader stream,boolean skipHead,JFVersion version) throws IOException{
	super.loadFromStream(stream,skipHead,version);
	setRadius(stream.readDouble());
  }


   
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?