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 + -
显示快捷键?