jfregularline.java

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

JAVA
1,295
字号
   /**
    *   Mirror this object by a x coordinate. We make a left-right mirror here.
    *
    *   @param baseX  A mirror base x coordinate.
    *
    */ 	
   public void mirrorBy(double baseX){
	startMoveLabel();
   	m_regularLine.mirrorBy(baseX);
   	initNodes();
	m_portList.mirrorBy(baseX);
	finishMoveLabel();
   }

   /**
    *   Reverse this object by a central y coordinate of this object. We make a up-down flip here.
    */ 	
   public void flipBy(){
   	JFPoint center	=m_regularLine.getCenter();
   	flipBy(center.getY());
   }

   /**
    *   Reverse this object by a y coordinate. We make a up-down flip here.
    *
    *   @param baseY  A flip base y coordinate.
    *
    */ 	
   public void flipBy(double baseY){
	startMoveLabel();
   	m_regularLine.flipBy(baseY);
   	initNodes();
	m_portList.flipBy(baseY);
	finishMoveLabel();
   }

   /**
    *   Draw current object's arrows.
    */ 	
   protected void  drawArrow(Graphics g){
  	double zoom	=getZoomScale();
   	int lineWidth	=m_lineFormat.getLineWidth();
   	Color c		=m_lineFormat.getLineColor();
   	int startArrow	=m_arrow.getStartArrow();
   	int endArrow	=m_arrow.getEndArrow();

	int nodeCount	=m_regularLine.getNodeCount();
 
	JFPoint  startPoint1   	=m_regularLine.getNode(0);
	JFPoint  startPoint2  	=m_regularLine.getNextNode(0,false);
	JFPoint  endPoint1   	=m_regularLine.getNode(nodeCount-1);
	JFPoint  endPoint2   	=m_regularLine.getNextNode(nodeCount-1,true);

	if (zoom!=1.0){	
		startPoint1	=new JFPoint(startPoint1.getX() * zoom, startPoint1.getY() * zoom);
		startPoint2	=new JFPoint(startPoint2.getX() * zoom, startPoint2.getY() * zoom);
		endPoint1	=new JFPoint(endPoint1.getX() * zoom, endPoint1.getY() * zoom);
		endPoint2	=new JFPoint(endPoint2.getX() * zoom, endPoint2.getY() * zoom);
	}

   	Arrow.drawArrow(startArrow,lineWidth,startPoint2,startPoint1,g,c);
   	Arrow.drawArrow(endArrow,lineWidth,endPoint2,endPoint1,g,c);
   }	


   
   /**
    *   Draw a node list.
    *
    *   @param  nodeList A node list to be drawn.
    *
    *   @param g current drawing canvas.
    *   @param  isXorMode If is in xor mode now.
    *
    */ 	
   private void  drawList(List nodeList,Graphics g,boolean isXorMode){
	
  	double zoom	=getZoomScale();
	int   i=0;	
	float x=0;
	float y=0; 
	float lastx=0;
	float lasty=0;
   	
   	//pick up each nodes of line, and draw them as a poly line.
        GeneralPath line= new GeneralPath(GeneralPath.WIND_EVEN_ODD); 
        Iterator it=nodeList.iterator();
        while (it!=null && it.hasNext()){
        	Object obj=it.next();

        	if (obj instanceof JFPointNode){
        		if (((JFPointNode)obj).getNodeType()==JFPointNode.NODETYPE_END){
        			x	=(float)((JFPointNode)obj).getX();
        			y	=(float)((JFPointNode)obj).getY();
        		}else{
        			continue;
        		}

        	}else if (obj instanceof RegularNode){
        		if (((RegularNode)obj).getNodeType()==JFPointNode.NODETYPE_END){
        			x	=(float)((RegularNode)obj).getXOffset();
        			y	=(float)((RegularNode)obj).getYOffset();
        		}else{
        			continue;
        		}

        	}else{
        		continue;
        	}   
        	
        	x	=(float)(x * zoom);
        	y	=(float)(y * zoom);
        	
        	
        	i++;
        	if (i==1)
			line.moveTo(x,y);
		else{   
		 	//line segment from last point to this point must be a vertical or horizontal line!
			if ((int)Math.abs(lastx-x)!=0 && (int)Math.abs(lasty-y)!=0)
			   line.moveTo(x,y);
			else
			   line.lineTo(x,y);
		}
		lastx	=x;
		lasty	=y;
        }

   	if (!isXorMode)
   		m_lineFormat.setGraphics(g);
   	((Graphics2D)g).draw(line);   

	//set the default graphics stroke and color.
	if (!isXorMode)
		m_lineFormat.initGraphics(g);        
   	
   }

   /**
    *   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);


   	//A JFRegularLine should always consisted by it's nodes.
   	ObjectList nodeList = getNodeList();
	drawList(nodeList.getList(),g,isXorMode);

        if (!isXorMode)
		restoreTransparencyComposite(g);
	
	if (!isXorMode){   	
   		drawPort(g);   	
   		drawArrow(g);
   		drawLabel(g); 	
   	}
   }


   /**
    *   Init all ports of this regular line.
    *   An object will always has its one or more stable ports and some customized ports,
    *   for JFRegularLine, it will has two stable ports as below,
    *   port1 at start point of the line.
    *   port2 at end point of the line.
    */ 	
   protected void initPorts(){
   	try{
                m_portList.clear();
   		int nodeCount	=m_regularLine.getNodeCount();
   			
   		if (nodeCount<2) return;
   			
		JFPoint  startPoint1   	=m_regularLine.getNode(0);
		JFPoint  startPoint2  	=m_regularLine.getNextNode(0,false);
		JFPoint  endPoint1   	=m_regularLine.getNode(nodeCount-1);
		JFPoint  endPoint2   	=m_regularLine.getNextNode(nodeCount-1,true);
			
		//port at start point1
		m_portList.addPort(new Port(this,Port.PORTTYPE_DEFAULT,startPoint1,startPoint2,startPoint1));

		//port at end point1
		m_portList.addPort(new Port(this,Port.PORTTYPE_DEFAULT,endPoint1,endPoint2,endPoint1));

   	}catch(Exception e){
   	}

	m_portList.setZoomScale(getZoomScale());
   }

   /**
    *   Set a port list of this shape. 
    * 
    *   @param portList  A new port list.
    *   @param shapeList  All shape objects in a list.
    *
    */ 	
   public void setPortList(ObjectList portList,ObjectList shapeList){
   	if (portList==null)
   		return;
   		
   	try{
   		m_portList	=(PortList)portList.clone();
		//re-set parent.
   		Iterator it	=m_portList.getList().iterator();
   		while (it!=null && it.hasNext()){
			Port port	=(Port)it.next();
			port.setParent(this);
			port.attachRealPort(shapeList);
   		}
   	}catch(Exception e){
   	}
   }

   /**
    *   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_regularLine.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 move a node, we have some important nodes here.
    */ 	
   private  JFPoint m_moveNode		=new JFPoint();
   private  JFPoint m_priorNode1	=new JFPoint();
   private  JFPoint m_priorNode2	=new JFPoint();
   private  JFPoint m_nextNode1		=new JFPoint();
   private  JFPoint m_nextNode2		=new JFPoint();
   private  int     m_moveNodeType	=0;
   private  int	    m_endNodeCount	=0;
   
   /**
    *   Start move a node.
    * 
    *   @param  node The node will be moved.
    *
    */ 	
   public void  startMoveNode(Node node){
	try{
		startMoveLabel();
	
		//initiate move nodes paramters.
		m_moveNode.setValue(GeomConst.LARGE_VALUE,GeomConst.LARGE_VALUE);
		m_priorNode1.setValue(GeomConst.LARGE_VALUE,GeomConst.LARGE_VALUE);
		m_priorNode2.setValue(GeomConst.LARGE_VALUE,GeomConst.LARGE_VALUE);
		m_nextNode1.setValue(GeomConst.LARGE_VALUE,GeomConst.LARGE_VALUE);
		m_nextNode2.setValue(GeomConst.LARGE_VALUE,GeomConst.LARGE_VALUE);
		m_moveNodeType	=0;
   		m_endNodeCount	=0;

   		int nodeCount	=m_regularLine.getNodeCount();
   		if (nodeCount<2) return;

		int index	=m_nodeList.getIndexByObjectId(node.getObjectId());
		if (index<0) return;
	
		JFPointNode 	moveNode	=m_regularLine.getNode(index);
		JFPointNode	priorNode1	=m_regularLine.getNextNode(index,true);
		JFPointNode	priorNode2	=m_regularLine.getNextNode(priorNode1,true);
		JFPointNode	nextNode1	=m_regularLine.getNextNode(index,false);
		JFPointNode	nextNode2	=m_regularLine.getNextNode(nextNode1,false);
		
		
		m_moveNodeType	=moveNode.getNodeType();
   		m_endNodeCount	=m_regularLine.getNodeCount(JFPointNode.NODETYPE_END);
		if (moveNode!=null)	m_moveNode.setValue(moveNode);
		if (priorNode1!=null)	m_priorNode1.setValue(priorNode1);
		if (priorNode2!=null)	m_priorNode2.setValue(priorNode2);
		if (nextNode1!=null)	m_nextNode1.setValue(nextNode1);
		if (nextNode2!=null)	m_nextNode2.setValue(nextNode2);

	}catch(Exception e){
	}
   }
  

   /**
    *   Draw and drag last point to specified position.
    *   This method will be called while dragging and drawing a new node for regularline.
    *
    *   @param  x,&nbsp;y  A new dragging position.
    *
    *   @param g current drawing canvas.
    *
    */ 	
   public void  drawNewNodeTo(double x, double y,Graphics g){
        List  nodeList	=m_regularLine.getDragLinePoints(x,y);
	drawList(nodeList,g,true);
   }
  
   
   /**
    *   Move/adjust a node of current object.
    * 
    *   @param  node Currently moving node.
    *
    *   @param  x,&nbsp;y Moving offsets.
    *
    *   @param g current drawing canvas.
    *
    */ 	
   public void  moveNode(Node node, double x, double y,Graphics g){
	if (node!=null && node instanceof RegularNode){
		int index	=m_nodeList.getIndexByObjectId(node.getObjectId());
		if (index<0) return;
		
	   	List  moveList	=m_regularLine.getMoveLinePoints(index,x,y,false);
		
		if (g!=null)		
 			drawList(moveList,g,true);
 		node.setXOffset(x);
 		node.setYOffset(y);
	}
   }

   /**
    *   Move/adjust a port of current object.
    *   A move port event will always occured by relative objects' moving event.
    * 
    *   @param  port Currently moving port.
    *   @param  x,&nbsp;y new position of this port.
    *   @return True if successfully moved, false otherwise.
    *
    */ 	
   public boolean  movePort(Port port, double x, double y){
       if (port==null || port.getParentId()!=getObjectId())
        return false;
 
       //not allowed to move customized ports.
       if (port.getPortType()==Port.PORTTYPE_CUSTOM)
         return false;

       int portIndex        =m_portList.getIndex(port);

       RegularNode node;
       RegularNode bakNode; //baknode is the opposite node of node above.
       JFPoint  bakNodePos=new JFPoint();
       try{
                if (portIndex==0){
                        //the start node.
       		        node    =(RegularNode)m_nodeList.getByIndex(0);
       		        
       		        bakNode	=(RegularNode)m_nodeList.getByIndex(m_nodeList.size()-1);
       		        bakNodePos.setValue(bakNode.getNodePoint());
                }else if (portIndex==1){
                        //the end node.
       		        node    =(RegularNode)m_nodeList.getByIndex(m_nodeList.size()-1);
       		        
       		        bakNode	=(RegularNode)m_nodeList.getByIndex(0);
       		        bakNodePos.setValue(bakNode.getNodePoint());
                }else{
                        return false;
                }
        }catch(Exception e){
                return false;
        }

        //move the port relative nodes will move both nodes and ports.
        startMoveNode(node);
        moveNode(node,x,y,null);
        finishMoveNode(node,x,y,null);  

	//if the bak node(opposite node of the node above) was moved, here to move back it.
        if (!bakNode.getNodePoint().equals(bakNodePos,true)){  
        	startMoveNode(bakNode);
        	moveNode(bakNode,bakNodePos.getX(),bakNodePos.getY(),null);
        	finishMoveNode(bakNode,bakNodePos.getX(),bakNodePos.getY(),null);
	}        
        return true;
   }


	
   /**
    *   When move regularLine node, all of its relational ports will be moved concurrently,
    * 
    *   @param  x,y   new position of moving node.
    *
    */ 	
   public void finishMoveRegularLineNode(double x, double y){
	
	
	/**
	 *  For moving regular line node, we need to consider following situations so we can 
	 *  correctly adjust the relational ports.
	 *
	 *  1. a port is always between two END points(not mid points or sub middle points!), sometimes the port position 
	 *     has the same position as one of the two END points(e.g. start port and end port),
	 *
	 *  2. when a node is moved to a new position, consider the regularLine's constructing rules,
	 *     automatically combining the same slope lines(same slope and continous lines, same slope here means 
	 *     continuous vertical or horizontal lines), so this node, or its relational nodes will
	 *     no longer exist(will disappear) sometimes. 
	 *
	 *  3. the movement of a mid node will move itself and the relational two end points. 
	 *
	 *  4. a sub middle node can be moved into an new END point, so we must make a decision that if the port between the two 
	 *     relational END points will lie on left or right side of this new END point.
	 *
	 */

    	if (!m_priorNode1.isValid() && !m_nextNode1.isValid())

⌨️ 快捷键说明

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