abstractrectangle.java

来自「用Java开发的、实现类似Visio功能的应用程序源码」· Java 代码 · 共 1,128 行 · 第 1/3 页

JAVA
1,128
字号
    *   Get a node by vertex type.
    *   
    *   @param vertexType Vertex type of current node.
    *   @return A node of current rectangle.
    */ 	
   public Node getNodeByVertexType(int vertexType){
   	try{
   	   	switch(vertexType){
   	   		case Rect.VERTEXTYPE_LEFTTOP:
   	   			return (Node)m_nodeList.getByIndex(0);
   	   		case Rect.VERTEXTYPE_RIGHTTOP:
	   	   		return (Node)m_nodeList.getByIndex(1);
   	   		case Rect.VERTEXTYPE_LEFTBOTTOM:
   	   			return (Node)m_nodeList.getByIndex(2);
   	   		case Rect.VERTEXTYPE_RIGHTBOTTOM:
   	   			return (Node)m_nodeList.getByIndex(3);
   	   	}
   	 }catch(Exception e){
   	 }
   	return null;
   }

   /**
    *   Get vertex type by a node.
    *   
    *   @param node A node of this rectangle.
    *   @return the vertex type of this node.
    */ 	
   public int getVertexTypeByNode(Node node){

   	int vertexType = Rect.VERTEXTYPE_LEFTTOP;
	
	if (node!=null)
   		if (node.equals(getNodeByVertexType(Rect.VERTEXTYPE_LEFTTOP)))
   			vertexType =Rect.VERTEXTYPE_LEFTTOP;
   		else if (node.equals(getNodeByVertexType(Rect.VERTEXTYPE_RIGHTTOP)))
   			vertexType =Rect.VERTEXTYPE_RIGHTTOP;
   		else if (node.equals(getNodeByVertexType(Rect.VERTEXTYPE_LEFTBOTTOM)))
   			vertexType =Rect.VERTEXTYPE_LEFTBOTTOM;
   		else if (node.equals(getNodeByVertexType(Rect.VERTEXTYPE_RIGHTBOTTOM)))
   			vertexType =Rect.VERTEXTYPE_RIGHTBOTTOM;
   	
   	return vertexType;
   }

   /**
    *   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){
   	//increase node added number.
   	m_nodeAdded++;
	if (m_nodeAdded>2) m_nodeAdded=2;
	   	
   	//for a rectangular shape, the first node is to decide the left-top vertex,
   	//and the second noe is the last node to decide the right-bottom vertex.
   	if (m_nodeAdded==1){
   		m_firstNode.setValue(x,y);
   	}
   }

   /**
    *   Remove last node added by addNode method.
    *   @return Last node that remained.
    *
    */ 	
   public Node removeLastNode(){
   	//for rectanglular shape, removeLastNode is same as remove all nodes.
   	m_nodeAdded=0;
   	return null;
   }   

   /**
    *   If a rectanglue has been drew.
    *   @return True when complete, false otherwise.
    *
    */ 	
   public boolean ifCompleteDrawing(){
   	//two nodes added will decide a rectangle.
   	return (m_nodeAdded==2);
   }

   /**
    *   Finish drawing object.
    *
    */ 	
   public boolean finishDrawing(){
   	initNodes();
   	initPorts();
   	initLabel();
   	return true;
   }


   /**
    *   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();
   	GeneralPath path= new GeneralPath(GeneralPath.WIND_EVEN_ODD); 

   	LineSeg left	 	=m_rect.getSide(Rect.SIDETYPE_LEFT);
   	LineSeg top	 	=m_rect.getSide(Rect.SIDETYPE_TOP);
   	LineSeg right	 	=m_rect.getSide(Rect.SIDETYPE_RIGHT);
   	LineSeg bottom		=m_rect.getSide(Rect.SIDETYPE_BOTTOM);

   	path.moveTo((float)(left.getX1()*zoom),	(float)(left.getY1()*zoom));
   	path.lineTo((float)(left.getX2()*zoom),	(float)(left.getY2()*zoom));
   	path.lineTo((float)(top.getX2()*zoom),(	float)(top.getY2()*zoom));
   	path.lineTo((float)(right.getX2()*zoom),(float)(right.getY2()*zoom));
   	path.lineTo((float)(bottom.getX2()*zoom),(float)(bottom.getY2()*zoom));
   	path.closePath();  
   	
   	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);
   	}
        

   }



   /**
    *   Test if current object intersects with a specified point.
    * 
    *   @param  pnt A JFPoint used to test intersection.
    *
    */ 	
   public boolean  intersects(JFPoint pnt){
   	if (isInvisible()){
   		return getBounds().contains(pnt);
   	}else{
   		//we use intersects but not contains here, for an accurate pick.
   		return m_rect.intersects(pnt,GeomConst.PICK_OFFSET) || m_rect.contains(pnt);
   	}
   }
 

   /**
    *   Test if current object intersects with a specified rectangle.
    * 
    *   @param  rect A Rect used to test intersection.
    *
    */ 	
   public boolean  intersects(Rect rect){
   	if (isInvisible()){
   		return getBounds().intersects(rect);
   	}else{
   		return m_rect.intersects(rect);
   	}
   }

   /**
    *   Add a new port to this shape.
    *   @param x,y Current picking position.
    *
    */ 	
   public Port addPort(double x,double y){
   		
   	JFPoint startPoint	=new JFPoint();
   	JFPoint endPoint	=new JFPoint();
   	JFPoint portPoint	=new JFPoint();
   	
	if (!m_rect.canAddPort(x,y,startPoint,endPoint,portPoint))
		return null;

	Port newPort=m_portList.addPort(new Port(this,Port.PORTTYPE_CUSTOM,startPoint,endPoint,portPoint));
	m_portList.setZoomScale(getZoomScale());
	
	return newPort;
   }


   /**
    * When moving a node, in some cases, e.g. ctrl key or shift key pressed to force preserving 
    * the form of a shape, or force equilateral shapes, we need to recalculate the actual moving
    * node's position.
    *
    *  @param movePos Desire moving position of a node.
    *  @param moveCase Move case of a node, normal, shift key pressed or ctrl key pressed
    *  @return The actual moving position of a node.
    *
    */	  
   public JFPoint getMoveNodePos(Node node,JFPoint movePos,int moveCase){
   	if (node==null || movePos==null)
   		return null;

  	
   	switch (moveCase){
   		case ShapeConst.MOVEMENT_NORMAL:
   			return movePos;

   		case ShapeConst.MOVEMENT_SHIFTDOWN:
   		case ShapeConst.MOVEMENT_CTRLDOWN:
        		int vertexType	=getVertexTypeByNode(node);
        		
        		JFPoint base,neibor1,neibor2;
        		
        		//get the base vertex(peer point of current vertex),and other two neibor vertexes.
        		switch (vertexType){
   				case Rect.VERTEXTYPE_LEFTTOP:
   					base		=m_rect.getVertex(m_rect.VERTEXTYPE_RIGHTBOTTOM);
   					neibor1         =m_rect.getVertex(m_rect.VERTEXTYPE_RIGHTTOP);
   					neibor2		=m_rect.getVertex(m_rect.VERTEXTYPE_LEFTBOTTOM);
   					break;

   				case Rect.VERTEXTYPE_RIGHTBOTTOM:
   					base		=m_rect.getVertex(m_rect.VERTEXTYPE_LEFTTOP);
   					neibor1         =m_rect.getVertex(m_rect.VERTEXTYPE_RIGHTTOP);
   					neibor2		=m_rect.getVertex(m_rect.VERTEXTYPE_LEFTBOTTOM);
   					break;
   					
   				case Rect.VERTEXTYPE_RIGHTTOP:
   					base		=m_rect.getVertex(m_rect.VERTEXTYPE_LEFTBOTTOM);
   					neibor1         =m_rect.getVertex(m_rect.VERTEXTYPE_LEFTTOP);
   					neibor2		=m_rect.getVertex(m_rect.VERTEXTYPE_RIGHTBOTTOM);
   					break;
   				
   				case Rect.VERTEXTYPE_LEFTBOTTOM:
   					base		=m_rect.getVertex(m_rect.VERTEXTYPE_RIGHTTOP);
   					neibor1         =m_rect.getVertex(m_rect.VERTEXTYPE_LEFTTOP);
   					neibor2		=m_rect.getVertex(m_rect.VERTEXTYPE_RIGHTBOTTOM);
   					break;
   				
   				default:
   					return movePos;
   			}
			
			//two new neibors(upright feet) generated by move pos.   	                
   	                LineSeg line	=new LineSeg();
   	                line.setValue(base,neibor1);
   	                JFPoint newNeibor1 =line.uprightFoot(movePos.getX(),movePos.getY());
   	                double slope1	   =line.getSlope();
   	                
   	                line.setValue(base,neibor2);
   	                JFPoint newNeibor2 =line.uprightFoot(movePos.getX(),movePos.getY());
   	                double slope2	   =line.getSlope();	
			
			//distances from base to neibors.
			double distance1	=base.distance(newNeibor1);
			double distance2	=base.distance(newNeibor2);
			   	                
   	        	//generate new moving pos by base,newNeibor1 and newNeibor2
   	        	JFPoint newMovePos;
   	        	boolean direction;
   	                if (distance1>distance2){
   	                	direction	=JFVector.underClockwiseSide(newNeibor1,movePos,newNeibor1,newNeibor2);
   	                	newMovePos	=newNeibor1.nearPoint(slope2,distance1,newNeibor2,direction);
   	                	//newNeibor2	=base.nearPoint(newNeibor2,distance1);
   	        	}else{
   	                	direction	=JFVector.underClockwiseSide(newNeibor2,movePos,newNeibor2,newNeibor1);
   	                	newMovePos	=newNeibor2.nearPoint(slope1,distance2,newNeibor1,direction);
   	        		//newNeibor1	=base.nearPoint(newNeibor1,distance2);
   	        	}
			
			return newMovePos;   	        	
   	}

   	
   	return movePos;
   }



   protected Rect m_originalRect;
   /**
    *   Start move a node.
    * 
    *   @param  node The node will be moved.
    *
    */ 	
   public void  startMoveNode(Node node){
   	m_originalRect	=new Rect(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();
	m_portList.movePort(m_originalRect.getVertex(Rect.VERTEXTYPE_LEFTTOP),m_originalRect.getVertex(Rect.VERTEXTYPE_RIGHTTOP),
			    m_rect.getVertex(Rect.VERTEXTYPE_LEFTTOP),m_rect.getVertex(Rect.VERTEXTYPE_RIGHTTOP));

	m_portList.movePort(m_originalRect.getVertex(Rect.VERTEXTYPE_RIGHTTOP),m_originalRect.getVertex(Rect.VERTEXTYPE_RIGHTBOTTOM),
			    m_rect.getVertex(Rect.VERTEXTYPE_RIGHTTOP),m_rect.getVertex(Rect.VERTEXTYPE_RIGHTBOTTOM));

	m_portList.movePort(m_originalRect.getVertex(Rect.VERTEXTYPE_RIGHTBOTTOM),m_originalRect.getVertex(Rect.VERTEXTYPE_LEFTBOTTOM),
			    m_rect.getVertex(Rect.VERTEXTYPE_RIGHTBOTTOM),m_rect.getVertex(Rect.VERTEXTYPE_LEFTBOTTOM));

	m_portList.movePort(m_originalRect.getVertex(Rect.VERTEXTYPE_LEFTBOTTOM),m_originalRect.getVertex(Rect.VERTEXTYPE_LEFTTOP),
			    m_rect.getVertex(Rect.VERTEXTYPE_LEFTBOTTOM),m_rect.getVertex(Rect.VERTEXTYPE_LEFTTOP));

   }


   /**
    *   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){
	if (node!=null){
		if (node.getXOffset()==x && node.getYOffset()==y){
			//only eliminate old dragging shape here
			draw(g,true);
		}
		else{
			//processing issues by sub-classes
   		}
	}
   }


   /**
    *   Scale current object by specified points and scale percent.
    *   We only support a concurrent width-height scale here, suppose width as the length from
    *   basePoint to refPoint1, height as the length from basePoint to refPoint2, and 
    *   one scale percent acts on both width and height.
    *
    *   @param basePoint A base point that is unmovable.
    *   @param refPoint1 A 'width' reference point.
    *   @param refPoint2 A 'height' reference point.
    *   @param scale A reference scale percent.
    *

⌨️ 快捷键说明

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