/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package shape;

import java.awt.*;
import java.awt.geom.*;
import DrawTop.*;
import shape.*;
import geomExtension.*;
import util.*;

public class DrawShapeUtil{

    //static ConnectorMark connectorMark=new ConnectorMark();
    static Color boxColor=new Color(0x9900FF);  // purple
    static DrawPanel drawPanel=ObjectTable.getDrawPanel();
    static int debug=0;
    
    public static void drawShapeElement(Graphics g, ShapeContainer shapeContainer){
        ShapeElement shapeElement=shapeContainer.getElement();
        int type=shapeElement.getTypeE();
        boolean closed=shapeElement.isClosed();
        //if(!closed){
        if((type==Command.LINE||type==Command.POLYLINE)&&!closed){
       //Line can be attached with arrows on the edges.
            drawLineElement(g, shapeContainer);
        } else if(type==Command.IMAGE){
            drawImageElement(g, shapeContainer);
        } else{
            drawStandardElement(g, shapeContainer);
        }
        drawConnectorMark(g, shapeContainer);
        drawNodeMark(g, shapeContainer);
        drawCharacteristicMark(g, shapeContainer);
    }
    
    
    private static void drawStandardElement(Graphics g, ShapeContainer shapeContainer){
        Graphics2D g2=(Graphics2D)g;
        ShapeElement shapeElement=shapeContainer.getElement();
        Curve2D curve2D=shapeElement.getCurve2D();

        PaintStyle paintStyle=shapeContainer.getPaintStyle();

        boolean blinking=shapeContainer.isBlinking();
        BlinkingShape blinkingShape=ObjectTable.getBlinkingShape();

        if(curve2D==null) return;
        Rectangle currentClip=g2.getClipBounds();
        Color currentColor=g2.getColor();
        Stroke currentStroke=g2.getStroke();
        
        double lineWidth=(double)paintStyle.getLineWidth();
        double enLarge=0.5d*lineWidth+10d;
        Rectangle2D enlargedBoundingBox
                =ShapeElementUtil.getEnlargedRectangle(shapeElement.getBoundingBox(), enLarge, enLarge);
        if(enlargedBoundingBox!=null) g2.setClip(enlargedBoundingBox);
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        Color fillColor=paintStyle.getFillColor();
        g2.setColor(fillColor);
      //-----------------------------------------------------------//  
        if(curve2D.isClosed()&&fillColor!=null) {
            if(!blinking||blinkingShape.isVisible()){
                g2.fill(curve2D.getShape());
            }
        }
      //-----------------------------------------------------------//  
        Stroke stroke=paintStyle.getLineStroke();
        g2.setStroke(stroke);
        Color lineColor=paintStyle.getLineColor();
        g2.setColor(lineColor);
      //---------------------------------------------------------------------------//
        if(curve2D!=null&&lineColor!=null) {
            if(!blinking||blinkingShape.isVisible()){
                g2.draw(curve2D.getShape());
            }
        }
      //---------------------------------------------------------------------------//
        if(DrawParameters.DRAW_BOUNDINGBOX) {
            g2.setColor(boxColor);
            g2.setStroke(currentStroke);
            g2.draw(curve2D.getBoundingBox());
            g2.setColor(currentColor);
        }
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
        DrawShapeUtil.drawClosedMessage(g, shapeContainer);

        g2.setStroke(currentStroke);
        g2.setColor(currentColor);
        g2.setClip(currentClip); 
    }

    private static void drawImageElement(Graphics g, ShapeContainer shapeContainer){
        Graphics2D g2=(Graphics2D)g;
        ShapeElement shapeElement=shapeContainer.getElement();
        Curve2D curve2D=shapeElement.getCurve2D();
        ImageElement imageElement=(ImageElement)shapeElement;
        //ShapeContainer container=shapeElement.getShapeContainer();
        PaintStyle paintStyle=shapeContainer.getPaintStyle();
        boolean blinking=shapeContainer.isBlinking();
        BlinkingShape blinkingShape=ObjectTable.getBlinkingShape();
        
        if(curve2D==null) return;
        Rectangle currentClip=g2.getClipBounds();
        Color currentColor=g2.getColor();
        Stroke currentStroke=g2.getStroke();
        
        double lineWidth=(double)paintStyle.getLineWidth();
        double enLarge=0.5d*lineWidth+10d;
        Rectangle2D enlargedBoundingBox
                =ShapeElementUtil.getEnlargedRectangle(shapeElement.getBoundingBox(), enLarge, enLarge);
        if(enlargedBoundingBox!=null) g2.setClip(enlargedBoundingBox);

        g2.setColor(Color.WHITE);
        if(!blinking||blinkingShape.isVisible()){
            g2.fill(curve2D.getShape());
        }
        g2.setColor(currentColor);
        Rectangle2D shrinkedRect
                =ShapeElementUtil.getShrinkedRectangle(curve2D.getBoundingBox(), lineWidth, lineWidth);
        if(shrinkedRect!=null){
            g.drawImage(imageElement.getBufferedImage(),
                (int)shrinkedRect.getX(), (int)shrinkedRect.getY(), 
                (int)shrinkedRect.getWidth(), (int)shrinkedRect.getHeight(), null);
        }
        shrinkedRect=ShapeElementUtil.getShrinkedRectangle(curve2D.getBoundingBox(), 0.5*lineWidth, 0.5*lineWidth);
        Stroke stroke=paintStyle.getLineStroke();
        g2.setStroke(stroke);
        Color lineColor=paintStyle.getLineColor();
        g2.setColor(lineColor);
        if(shrinkedRect!=null) {
            if(!blinking||blinkingShape.isVisible()){
                g2.draw(shrinkedRect);
            }
        }
        g2.setStroke(currentStroke);
        g2.setColor(currentColor);
        g2.setClip(currentClip);
    }
    
    private static void drawLineElement(Graphics g, ShapeContainer shapeContainer){
        Graphics2D g2=(Graphics2D)g;
        ShapeElement shapeElement=shapeContainer.getElement();
        Curve2D curve2D=shapeElement.getCurve2D();
        PaintStyle paintStyle=shapeContainer.getPaintStyle();
        boolean blinking=shapeContainer.isBlinking();
        BlinkingShape blinkingShape=ObjectTable.getBlinkingShape();
        
        if(curve2D==null) return;
        Rectangle currentClip=g2.getClipBounds();
        Color currentColor=g2.getColor();
        Stroke currentStroke=g2.getStroke();
        //Composite currentComposit=g2.getComposite();
       
        double lineWidth=(double)paintStyle.getLineWidth();
        double enLarge=0.5d*lineWidth+10d;
        Rectangle2D enlargedBoundingBox
                =ShapeElementUtil.getEnlargedRectangle(shapeElement.getBoundingBox(), enLarge, enLarge);
        
        if(enlargedBoundingBox!=null) g2.setClip(enlargedBoundingBox);
        Color fillColor=shapeElement.getShapeContainer().getPaintStyle().getFillColor();
        g2.setColor(fillColor);  
        if(curve2D.isClosed()&&fillColor!=null) {
            if(!blinking||blinkingShape.isVisible()){
                g2.fill(curve2D.getShape());
            }
        }
        //g2.setComposite(currentComposit);
        Stroke stroke=paintStyle.getLineStroke();
        g2.setStroke(stroke);
        Color lineColor=paintStyle.getLineColor();
        g2.setColor(lineColor);
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        
        if(!blinking||blinkingShape.isVisible()){
            DrawShapeUtil.drawLine(g, shapeContainer);
        } 
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
        if(DrawParameters.DRAW_BOUNDINGBOX) {
            g2.setColor(boxColor);
            g2.setStroke(currentStroke);
            g2.draw(curve2D.getBoundingBox());
            g2.setColor(currentColor);
        }
        
        DrawShapeUtil.drawClosedMessage(g, shapeContainer);
        //g2.setComposite(currentComposit);
        g2.setStroke(currentStroke);
        g2.setColor(currentColor);
        g2.setClip(currentClip);
    }
    
     private static void drawClosedMessage(Graphics g, ShapeContainer shapeContainer){
         
        ShapeElement shapeElement=shapeContainer.getElement();
        int type=shapeElement.getTypeE();
        if(type!=Command.POLYLINE&&type!=Command.CUBIC_CURVE
                &&type!=Command.GENERAL_CURVE) return;
        int mode=shapeElement.getShapeContainer().getMode();
         
        Color currentColor=null;
        Graphics2D g2=(Graphics2D)g;
        //double delta=DrawParameters.ClosedTolerance;
        Curve2D curve2D=shapeElement.getCurve2D();
        int numseg=curve2D.getNumOfSegments();
        double dist=Vector2D.dist(new Vector2D(curve2D.getP(0)), new Vector2D(curve2D.getP(numseg)));
        DrawShapeUtil.clearTempShape("ClosedMessage");
        if(numseg>1&&dist<DrawParameters.ClosedTolerance){
            currentColor=g2.getColor();
            g2.setColor(Color.red);
            Rectangle2D box=curve2D.getBoundingBox();
            //Point2D centerP=new Point2D.Double(box.getCenterX(), box.getCenterY());
            Rectangle2D mark=new Rectangle2D.Double(box.getCenterX(), box.getCenterY(),0,0);
            int x=(int)(box.getX()+0.5*box.getWidth()-10);
            int y=(int)(box.getY()+0.5*box.getHeight()-10);
            g2.setFont(DrawParameters.Font14Plain);
            Point2D messagePoint=null;
            if(mode==Command.CREATING_MODE||mode==Command.MOVING_ENDPT_MODE||
                    mode==Command.MODIFYING_SHAPE_MODE){
                messagePoint=new Point2D.Double(box.getCenterX()-10, box.getCenterY());
                DrawShapeUtil.drawTempShape("ClosedMessage", mark, null, null, null,
                    "closed !", messagePoint, Color.RED);
            }
            if(mode==Command.CREATING_MODE){
                messagePoint=new Point2D.Double(box.getCenterX()-130, box.getCenterY()+16);
                DrawShapeUtil.drawTempShape("ClosedMessage", null, null, null, null,
                    "Recommend right button click to finish", messagePoint, Color.RED);
                messagePoint=new Point2D.Double(box.getCenterX()-130, box.getCenterY()+32);
                DrawShapeUtil.drawTempShape("ClosedMessage", null, null, null, null,
                    "You can always add a text box by 'util- add text box' menu",
                    messagePoint, Color.RED);
            }
            g2.setColor(currentColor);
        }
     }
     
    private static void drawLine(Graphics g, ShapeContainer shapeContainer){
        Graphics2D g2=(Graphics2D)g;
        ShapeElement shapeElement=shapeContainer.getElement();
        PaintStyle paintStyle=shapeElement.getShapeContainer().getPaintStyle();
        Color currentColor=g2.getColor();
        g2.setStroke(paintStyle.getDefaultStroke());
        Stroke currentStroke=g2.getStroke();
        Stroke stroke=paintStyle.getLineStroke();
        g2.setStroke(stroke);
        Color lineColor=paintStyle.getLineColor();
        g2.setColor(lineColor);
        Curve2D line=shapeElement.getCurve2D();

        if(paintStyle.startArrowType>0||paintStyle.endArrowType>0)
            line=DrawShapeUtil.getTrimmedLine(shapeContainer);
        if(line!=null) g2.draw(line.getShape());
        Stroke arrowStroke=paintStyle.getArrowStroke();
        g2.setStroke(arrowStroke);
        Polyline2DE arrowShape=null;

        if(paintStyle.startArrowType>0){
            ArrowShape arrow=DrawShapeUtil.createArrowShape(0, shapeContainer);
            arrowShape=arrow.getArrowShape();
            if(paintStyle.startArrowType==2) g2.fill(arrowShape.getShape());
            if(paintStyle.startArrowType>=1) g2.draw(arrowShape.getShape());
        }
        if(paintStyle.endArrowType>0){
            ArrowShape arrow=DrawShapeUtil.createArrowShape(1, shapeContainer);
            arrowShape=arrow.getArrowShape();
            if(paintStyle.endArrowType==2) g2.fill(arrowShape.getShape());
            if(paintStyle.endArrowType>=1) g2.draw(arrowShape.getShape());
        }
        g2.setStroke(currentStroke);
        g2.setColor(currentColor);
     }

    private static Curve2D getTrimmedLine(ShapeContainer shapeContainer){
        ShapeElement shapeElement=shapeContainer.getElement();
        PaintStyle paintStyle=shapeContainer.getPaintStyle();
        double startTrim=0.0d; 
        double endTrim=0.0d;
        double trimFactor=1d/Math.tan(0.5d*ArrowShape.ArrowAngle);
        if(paintStyle.startArrowType>0) {
            if(paintStyle.startArrowType==1) 
                startTrim=0.6d*paintStyle.lineWidth*trimFactor;
            if(paintStyle.startArrowType==2) 
                startTrim=0.6d*paintStyle.lineWidth*trimFactor;
        }
        if(paintStyle.endArrowType>0) {
            if(paintStyle.endArrowType==1) 
                endTrim=0.6d*paintStyle.lineWidth*trimFactor;
            if(paintStyle.endArrowType==2) 
                endTrim=0.6d*paintStyle.lineWidth*trimFactor;
        }
        int type=shapeElement.getTypeE();
        Curve2D newLine=null;
        if(type==Command.LINE){
            Line2DE line=(Line2DE)shapeElement.getCurve2D();
            newLine=line.getTrimmedLine(startTrim, endTrim);
        }
        if(type==Command.POLYLINE){
            Polyline2DE polyLine=(Polyline2DE)shapeElement.getCurve2D();
            newLine=polyLine.getTrimmedPolyline(startTrim, endTrim);
        }
        if(debug>0) System.out.println("++ PaintStyleUtility startArrowType="+paintStyle.startArrowType+
                ", endArrowType=" +paintStyle.endArrowType+
                ", cutLengthAtStart="+startTrim+", endTrim="+endTrim);
        return newLine;
    }


    private static ArrowShape createArrowShape(int position , ShapeContainer shapeContainer){
        ShapeElement shapeElement=shapeContainer.getElement();
        PaintStyle paintStyle=shapeElement.getShapeContainer().getPaintStyle();
        Vector2D pt=null;
        Vector2D tangent=null;
        Curve2D curve=shapeElement.getCurve2D();
        int numSeg=curve.getNumOfSegments();
        double t=0;
        if(position==1) t=numSeg;
        pt=new Vector2D(curve.getP(t));
        tangent=curve.getTangent(t);
        if(position==0) tangent=Vector2D.multiply(-1d,tangent);
        int arrowtype=paintStyle.startArrowType;
        if(position==1) arrowtype=paintStyle.endArrowType;
        ArrowShape arrow=new ArrowShape(arrowtype, (double)paintStyle.lineWidth, pt, tangent);
        return arrow;
    }

  
    private static void drawNodeMark(Graphics g, ShapeContainer shapeContainer){
        Graphics2D g2=(Graphics2D)g;
        ShapeElement shapeElement=shapeContainer.getElement();
        Curve2D curve=shapeElement.getCurve2D();
        if(!DrawParameters.DRAW_NODE_POINTS) return;
        if(shapeElement==null||curve==null) return;
        int type=shapeElement.getTypeE();
        if(type!=Command.POLYLINE&&type!=Command.CUBIC_CURVE
                &&type!=Command.GENERAL_CURVE) return;
        double scale=DrawParameters.Scale;
        double markSize=4d/scale;
        Rectangle2D nodeMark
                =new Rectangle2D.Double(-0.5d*markSize,-0.5d*markSize, markSize, markSize);
        BasicStroke stroke=new BasicStroke((float)(1.5/scale), BasicStroke.CAP_SQUARE, 
                    BasicStroke.JOIN_MITER, 10.0f);
        Color currentColor=g2.getColor();
        AffineTransform currentTransform=g2.getTransform();
        Stroke currentStroke=g2.getStroke();
        g2.setStroke(stroke);
        int numSeg=0;
        numSeg=curve.getNumOfSegments();
        for(int i=0;i<=numSeg;i++){
            Point2D position=curve.getP(i);
            double moveX=position.getX();
            double moveY=position.getY();
            g2.translate(moveX, moveY);
            g2.setColor(Color.WHITE);
            g2.draw(nodeMark);
            g2.setColor(Color.BLUE);
            g2.fill(nodeMark);
            g2.translate(-moveX, -moveY);
        }
        g2.setStroke(currentStroke);
        g2.setColor(currentColor);
        g2.setTransform(currentTransform);
    }
    
    private static void drawCharacteristicMark(Graphics g, ShapeContainer shapeContainer){
        Graphics2D g2=(Graphics2D)g;
        ShapeElement shapeElement=shapeContainer.getElement();
        Curve2D curve=shapeElement.getCurve2D();
        if(!DrawParameters.DRAW_CHARACTERISTIC_POINTS) return;
        if(shapeElement==null||curve==null) return;
        double scale=DrawParameters.Scale;
        double markSize=4d/scale;
        Rectangle2D nodeMark
                =new Rectangle2D.Double(-0.5d*markSize,-0.5d*markSize, markSize, markSize);
        BasicStroke stroke=new BasicStroke((float)(1.5/scale), BasicStroke.CAP_SQUARE, 
                    BasicStroke.JOIN_MITER, 10.0f);
        Color currentColor=g2.getColor();
        AffineTransform currentTransform=g2.getTransform();
        Stroke currentStroke=g2.getStroke();
        g2.setStroke(stroke);
        CurvePT[] curvePTs=curve.getCharacteristicPoints();
        for(int i=0;i<curvePTs.length;i++){
            Point2D position=curvePTs[i].getP();
            double t=curvePTs[i].getParameter();
            double moveX=position.getX();
            double moveY=position.getY();
            g2.translate(moveX, moveY);
            if(Math.abs(t-(int)t)<1.0e-12){
                g2.setColor(Color.WHITE);
                g2.draw(nodeMark);
                g2.setColor(Color.BLUE);
                g2.fill(nodeMark);
            } else{
                g2.setColor(Color.WHITE);
                g2.draw(nodeMark);
                g2.setColor(Color.BLUE);
                g2.fill(nodeMark);
            }
            g2.translate(-moveX, -moveY);
        }
        g2.setStroke(currentStroke);
        g2.setColor(currentColor);
        g2.setTransform(currentTransform);
    }
    
    private static void drawConnectorMark(Graphics g, ShapeContainer shapeContainer){
        Graphics2D g2=(Graphics2D)g;
        ShapeElement shapeElement=shapeContainer.getElement();

    }
    
    public static void drawSelection(Graphics g, ShapeContainer shapeContainer){
        ShapeElement shapeElement=shapeContainer.getElement();
        int type=shapeElement.getTypeE();
        if(type==Command.LINE){
            drawLineSelection(g,shapeContainer);
        } else{
            drawSelectionBox(g,shapeContainer);
        }
    }
    
     private static void drawSelectionBox(Graphics g, ShapeContainer shapeContainer){
         Graphics2D g2=(Graphics2D)g;
         if(DrawParameters.DrawMode!=DrawParameters.DrawOnScreen) return;
         boolean unmovable=false;
         String from="DrawShapeUtil";
         //"unmovable" property is unavailable   2012.10.31
         boolean resizable=shapeContainer.getBooleanProperty("Enable_Resizing", from);
         boolean aspectRatio=shapeContainer.getBooleanProperty("Keep_Aspect_Ratio",from);
         boolean connector=shapeContainer.getBooleanProperty("Keep_Connector_Connections",from);
         boolean ungrouping=shapeContainer.getBooleanProperty("Enable_Ungrouping",from);
         ShapeElement shapeElement=shapeContainer.getElement();
         double scale=DrawParameters.Scale;
         Font smallFont=new Font(Font.DIALOG, Font.PLAIN, (int)(12/scale));
         double offset=DrawParameters.SelectionBoxOffset/scale;
         double markNSize=DrawParameters.Mark_NormalSize/scale;
         double markSSize=DrawParameters.Mark_SmallSize/scale;
         float linewidth=(float)(1.0/scale);
         Stroke defaultStroke10=PaintStyle.getDefaultStroke(linewidth);
         linewidth=(float)(1.5/scale);
         Stroke defaultStroke15=PaintStyle.getDefaultStroke(linewidth);
         
         //double halfMarkSize=markSize/2;
         Rectangle2D boundingBox=shapeElement.getBoundingBox();
         if(boundingBox==null||boundingBox.getWidth()==0&&boundingBox.getHeight()==0) return;
         Rectangle2D selectionBox=ShapeElementUtil.getEnlargedRectangle(boundingBox, offset, offset);
         double X=selectionBox.getX();
         double Y=selectionBox.getY();
         double W=selectionBox.getWidth();
         double H=selectionBox.getHeight();
         double markSize = markNSize;
         double halfMarkSize=markSize/2;
         Color markFillColor=Color.white;
         Color markLineColor=Color.black;
         int type=shapeElement.getTypeE();
       // draw end point marks of curve
         if((type==Command.POLYLINE||type==Command.CUBIC_CURVE||
                 type==Command.GENERAL_CURVE)){
            Curve2D[] curves=shapeElement.getCurve2D().getSubPaths();
            for(int i=0;i<curves.length;i++){
                if(curves[i].isClosed()) continue;
                Point2D startPT=curves[i].getP(0);
                int nseg=curves[i].getNumOfSegments();
                Point2D endPT=curves[i].getP(nseg);
                g2.setStroke(defaultStroke15);
                if (unmovable||!resizable||aspectRatio) {
                    markFillColor = Color.DARK_GRAY;
                    markLineColor = Color.DARK_GRAY;
                    g2.setStroke(defaultStroke10);
                    markSize = markSSize;
                }
                Rectangle2D mark=new Rectangle.Double(0,0,markSize,markSize);
                double x=startPT.getX()-halfMarkSize;
                double y=startPT.getY()-halfMarkSize;
                Stroke currentStroke=g2.getStroke();
                g2.setStroke(defaultStroke15);
                g2.translate(x, y);
                g2.setColor(markFillColor);
                g2.fill(mark);
                g2.setColor(markLineColor);
                g2.draw(mark);
                g2.translate(-x, -y);
                x=endPT.getX()-halfMarkSize;
                y=endPT.getY()-halfMarkSize;
                g2.translate(x, y);
                g2.setColor(markFillColor);
                g2.fill(mark);
                g2.setColor(markLineColor);
                g2.draw(mark);
                g2.translate(-x, -y);
                g2.setStroke(currentStroke);
            }
         }

       // draw selection box
         markSize=markNSize;
         halfMarkSize=markSize/2;
         Color currentColor=g2.getColor();
         g2.setColor(Color.LIGHT_GRAY);

         Composite currentComposit=g2.getComposite();
         float alfa=((AlphaComposite)currentComposit).getAlpha();
         AlphaComposite ac = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f*alfa );
         g2.setComposite( ac );
         Stroke currentStroke=g2.getStroke();
         if(!unmovable){
            Rectangle2D selectionFrame=new Rectangle2D.Double(X-halfMarkSize, Y-halfMarkSize, W, markSize);
            g2.fill(selectionFrame);
            selectionFrame=new Rectangle2D.Double(X-halfMarkSize, Y+H-halfMarkSize, W, markSize);
            g2.fill(selectionFrame);
            selectionFrame=new Rectangle2D.Double(X-halfMarkSize, Y-halfMarkSize, markSize, H+markSize);
            g2.fill(selectionFrame);
            selectionFrame=new Rectangle2D.Double(X+W-halfMarkSize, Y-halfMarkSize, markSize, H+markSize);
            g2.fill(selectionFrame);

         } else {
             g2.setColor(Color.DARK_GRAY);
             g2.setStroke(defaultStroke15);
             g2.draw(selectionBox);
         }
         g2.setComposite(currentComposit);
         g2.setColor(currentColor);
         g2.setStroke(currentStroke);

         if(unmovable||!resizable||aspectRatio||!connector||!ungrouping){
             Font currentFont=g2.getFont();
             g2.setColor(Color.RED);
             g2.setFont(smallFont);
             float xx=(float)(X+halfMarkSize+5);
             float yy=(float)(Y+H+halfMarkSize);
             String str="";
             if(unmovable){
                str="unable moving";
                g2.drawString(str, xx, yy);
                //xx+=(float)(70/scale);
                yy+=(float)(16/scale);
             }
             if(!resizable){
                str="unable resizing";
                g2.drawString(str, xx, yy);
                //xx+=(float)(70/scale);
                yy+=(float)(16/scale);
             }
             if(aspectRatio){
                str="keep aspect ratio";
                g2.drawString(str, xx, yy);
                //xx+=(float)(70/scale);
                yy+=(float)(16/scale);
             }
             if(!connector){
                str="ignore connectors";
                g2.drawString(str, xx, yy);
                yy+=(float)(16/scale);
             }
             if(!ungrouping){
                str="unable ungrouping";
                g2.drawString(str, xx, yy);
                //xx+=(float)(70/scale);
             }
             g2.setFont(currentFont);
             g2.setColor(currentColor);
         }

       // draw resize NW, SW, SE, NE  marks at corner
         markLineColor=Color.BLACK;
         markFillColor=Color.WHITE;
         AffineTransform currentTransform=g2.getTransform();
         if(resizable){
            g2.setStroke(defaultStroke10);
            Ellipse2D circle=new Ellipse2D.Double(X-halfMarkSize, Y-halfMarkSize,
                    markSize, markSize);
            g2.setColor(markFillColor);
            g2.fill(circle);
            g2.translate(W, 0d); g2.fill(circle);
            g2.translate(0d, H); g2.fill(circle);
            g2.translate(-W, 0d); g2.fill(circle);
            g2.translate(0d, -H);
            g2.setColor(markLineColor);
            g2.draw(circle);
            g2.translate(W, 0d); g2.draw(circle);
            g2.translate(0d, H); g2.draw(circle);
            g2.translate(-W, 0d); g2.draw(circle);
            g2.translate(0d, -H);
         }
       // draw resize N, W, S, E  marks at center of selection frame
         if(resizable&&!aspectRatio){
            Rectangle2D rect=new Rectangle.Double(X+0.5d*W-halfMarkSize,
                    Y-halfMarkSize, markSize, markSize);
            g2.setColor(markFillColor);
            g2.fill(rect);
            g2.translate(0.5d*W, 0.5d*H); g2.fill(rect);
            g2.translate(-0.5d*W, 0.5d*H); g2.fill(rect);
            g2.translate(-0.5d*W, -0.5d*H); g2.fill(rect);
            g2.translate(0.5d*W, -0.5d*H);
            g2.setColor(markLineColor);
            g2.draw(rect);
            g2.translate(0.5d*W, 0.5d*H); g2.draw(rect);
            g2.translate(-0.5d*W, 0.5d*H); g2.draw(rect);
            g2.translate(-0.5d*W, -0.5d*H); g2.draw(rect);
            g2.translate(0.5d*W, -0.5d*H);
            g2.setTransform(currentTransform);
            g2.setColor(currentColor);
         }
     }

     private static void drawLineSelection(Graphics g, ShapeContainer shapeContainer){
         Graphics2D g2=(Graphics2D)g;
         if(DrawParameters.DrawMode!=DrawParameters.DrawOnScreen) return;
         boolean unmovable=false;
         String from="DrawShapeUtil";
         //boolean unmovable=shapeContainer.getBooleanProperty("UnMovable","DrawShapeUtil");
         boolean resizable=shapeContainer.getBooleanProperty("Enable_Resizing", from);
         boolean lineDirection=shapeContainer.getBooleanProperty("Keep_Line_Direction", from);
         boolean connector=shapeContainer.getBooleanProperty("Keep_Connector_Connections", from);
         ShapeElement shapeElement=shapeContainer.getElement();
         PaintStyle paintStyle=shapeElement.getShapeContainer().getPaintStyle();
         double scale=DrawParameters.Scale;
         Font smallFont=new Font(Font.DIALOG, Font.PLAIN, (int)(12/scale));
         double markNSize=DrawParameters.Mark_NormalSize/scale;
         double markSSize=DrawParameters.Mark_SmallSize/scale;
         float linewidth10=(float)(1.0/scale);
         Stroke defaultStroke10=PaintStyle.getDefaultStroke(linewidth10);
         float linewidth15=(float)(1.5/scale);
         Stroke defaultStroke15=PaintStyle.getDefaultStroke(linewidth15);
         AlphaComposite ac = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f);
         Line2DE line=(Line2DE)shapeElement.getCurve2D();
         if(line==null) return;
         double X1=line.getX1();
         double Y1=line.getY1();
         double X2=line.getX2();
         double Y2=line.getY2();
         Stroke currentStroke=g2.getStroke();
         Composite currentComposit=g2.getComposite();
         //
         //g2.setComposite( ac );
         g2.setColor(paintStyle.getLineColor());
         Color markFillColor=Color.WHITE;
         Color markLineColor=Color.BLACK;
         Color currentColor=g2.getColor();
         g2.setStroke(defaultStroke15);
         double markSize=markNSize;
         if(unmovable||!resizable){
             markFillColor = Color.DARK_GRAY;
             markLineColor = Color.DARK_GRAY;
             g2.setColor(paintStyle.getLineColor());
             markSize=markSSize;
         }
         Rectangle2D rect=new Rectangle.Double(0, 0, markSize, markSize);
         double halfMarkSize=0.5*markSize;
         double x=X1-halfMarkSize;
         double y=Y1-halfMarkSize;
         g2.setColor(markFillColor);
         g2.translate(x, y);
         g2.fill(rect);
         g2.setColor(markLineColor);
         g2.draw(rect);
         g2.translate(-x, -y);

         x=X2-halfMarkSize;
         y=Y2-halfMarkSize;
         g2.setColor(markFillColor);
         g2.translate(x, y);
         g2.fill(rect);
         g2.setColor(markLineColor);
         g2.draw(rect);
         g2.translate(-x, -y);

         double X=0.5*(X1+X2);
         double Y=0.5*(Y1+Y2);
         if(unmovable||!resizable||lineDirection||!connector){
             Font currentFont=g2.getFont();
             g2.setColor(Color.RED);
             g2.setFont(smallFont);
             float xx=(float)(X-30/scale);
             float yy=(float)(Y);
             String str="";
             if(unmovable){
                str="unable moving";
                g2.drawString(str, xx, yy);
                yy+=(float)(16/scale);
             }
             if(!resizable){
                str="unable resizing";
                g2.drawString(str, xx, yy);
                yy+=(float)(16/scale);
             }
             if(lineDirection){
                str="keep line direction";
                g2.drawString(str, xx, yy);
                yy+=(float)(16/scale);
             }
             if(!connector){
                str="ignore connectors";
                g2.drawString(str, xx, yy);
                //x+=(float)(100*scale);
             }
             g2.setFont(currentFont);
             g2.setColor(currentColor);
         }
         g2.setComposite(currentComposit);
         g2.setColor(currentColor);
         g2.setStroke(currentStroke);
     }

    public static void drawSegmentModifiers(Graphics g, ShapeContainer shapeContainer){
        //System.out.println("*** drawSegmentModifier");
        Graphics2D g2=(Graphics2D)g;
        ShapeElement element=shapeContainer.getElement();
        double scale=DrawParameters.Scale;
        double markSize=DrawParameters.Mark_SmallSize/scale;
        double halfMarkSize=markSize/2;
        Color markFillColor=Color.BLUE;
        Color markLineColor=Color.BLUE;
        float linewidth=(float)(1.0/scale);
        Stroke defaultStroke10=PaintStyle.getDefaultStroke(linewidth);
        Rectangle2D mark=new Rectangle.Double(0,0,markSize,markSize);
        Color currentColor=g2.getColor();
        Stroke currentStroke=g2.getStroke();
        AffineTransform currentTransform=g2.getTransform();
         
        Rectangle2D boundingBox=element.getBoundingBox();
        boundingBox=ShapeElementUtil.getEnlargedRectangle(boundingBox, 4, 4);
        g2.setStroke(defaultStroke10);
        g2.setColor(Color.LIGHT_GRAY);
        g2.draw(boundingBox);
        g2.setTransform(currentTransform);
        SegmentModifier[] modifiers=element.getSegmentModifiers();
        int size=0;
        if(modifiers!=null) size=modifiers.length;
        Point2D PT=null;
        Shape shape=null;
        g2.setColor(Color.BLUE);
        for(int i=0;i<size;i++){
            int type=modifiers[i].getType();
            if(type!=SegmentModifier.SegmentP) continue;
            double x=modifiers[i].getP().getX()-halfMarkSize;
            double y=modifiers[i].getP().getY()-halfMarkSize;
            g2.translate(x, y);
            g2.setColor(markFillColor);
            g2.fill(mark);
            g2.setColor(markLineColor);
            g2.draw(mark);
            g2.translate(-x, -y);
        }
       //draw control point on edge  
        for(int i=0;i<size;i++) {
            int type=modifiers[i].getType();
            if(type!=SegmentModifier.SegmentMP) continue;
            PT=modifiers[i].getP();
            if(PT==null) continue;
            double x=PT.getX()-halfMarkSize;
            double y=PT.getY()-halfMarkSize;
            g2.translate(x, y);
            g2.setColor(Color.WHITE);
            g2.fill(mark);
            g2.setColor(markLineColor);
            g2.draw(mark);
            g2.translate(-x, -y);
        }
       // draw tangent line
         for(int i=0;i<size;i++) {
            int type=modifiers[i].getType();
            if(type!=SegmentModifier.Tangent) continue;
             int jointType=modifiers[i].getJointType();
             if(jointType!=SegmentModifier.Smooth&&jointType!=SegmentModifier.Cusp) continue;
             Segment2D tangentIn=modifiers[i].getTangentIn();
             Segment2D tangentOut=modifiers[i].getTangentOut();
             if(tangentIn!=null){
                Line2D line=(Line2D)tangentIn.getShape();
                if( Vector2D.dist(line.getP1(),line.getP2())>1.0e-1) g2.draw(line);
             }
             if(jointType==SegmentModifier.Cusp) {
                if(tangentOut!=null){
                    Line2D line=(Line2D)tangentOut.getShape();
                    if( Vector2D.dist(line.getP1(),line.getP2())>1.0e-1) g2.draw(line);
                }
             }
         }
       // draw end points of tangent line  
         for(int i=0;i<size;i++) {
            int type=modifiers[i].getType();
            if(type!=SegmentModifier.Tangent) continue;
             PT=modifiers[i].getTinP1();
             if(PT!=null){
                double x=PT.getX()-halfMarkSize;
                double y=PT.getY()-halfMarkSize;
                g2.translate(x, y);
                g2.setColor(Color.WHITE);
                g2.fill(mark);
                g2.setColor(markLineColor);
                g2.draw(mark);
                g2.translate(-x, -y);
             }
             PT=modifiers[i].getTinP2();
             if(PT!=null){
                double x=PT.getX()-halfMarkSize;
                double y=PT.getY()-halfMarkSize;
                g2.translate(x, y);
                g2.setColor(Color.WHITE);
                g2.fill(mark);
                g2.setColor(markLineColor);
                g2.draw(mark);
                g2.translate(-x, -y);
             }
             if(modifiers[i].getJointType()==SegmentModifier.Cusp) {
                PT=modifiers[i].getToutP1();
                if(PT!=null){
                    double x=PT.getX()-halfMarkSize;
                    double y=PT.getY()-halfMarkSize;
                    g2.translate(x, y);
                    g2.setColor(Color.WHITE);
                    g2.fill(mark);
                    g2.setColor(markLineColor);
                    g2.draw(mark);
                    g2.translate(-x, -y);
                }
                PT=modifiers[i].getToutP2();
                if(PT!=null){
                    double x=PT.getX()-halfMarkSize;
                    double y=PT.getY()-halfMarkSize;
                    g2.translate(x, y);
                    g2.setColor(Color.WHITE);
                    g2.fill(mark);
                    g2.setColor(markLineColor);
                    g2.draw(mark);
                    g2.translate(-x, -y);
                }
             }
         }
         g2.setColor(currentColor);
         g2.setStroke(currentStroke);
    }
/*
    public static void drawUnselectableAreas(Graphics g){

        if (!DrawParameters.DRAW_UNSELECTABLEAREA) return;
        Graphics2D g2=(Graphics2D)g;

        //ShapeContainer container=shapeElement.getShapeContainer();
        UnselectableAreas areasObject = ObjectTable.getSelectionLS().getUnselectableAreas();
        Shape[] shapes=null;
        if (areasObject != null) {
            shapes = areasObject.getShapes();
        }

        Rectangle currentClip=g2.getClipBounds();
        Color currentColor=g2.getColor();
        Stroke currentStroke=g2.getStroke();

        double enLarge=3d;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
        Composite currentComposit = g2.getComposite();
        AlphaComposite ac = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.3f);
        g2.setComposite(ac);
        for (int i = 0; i < shapes.length; i++) {
            g2.setColor(boxColor);
            g2.fill(shapes[i]);
            g2.setColor(currentColor);
            g2.draw(shapes[i]);
        }
        
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_OFF);

        g2.setStroke(currentStroke);
        g2.setColor(currentColor);
        g2.setClip(currentClip);
        g2.setComposite(currentComposit);
    }
*/
    public static void drawTempShape(String id, Point2D point, int size,
            String message, Color color){
        double scale=DrawParameters.getScale();
        int markSize=DrawParameters.Mark_SmallSize;
        if(size>0) markSize=size;
        double x=point.getX()-0.5*markSize/scale;
        double y=point.getY()-0.5*markSize/scale;
        Rectangle2D mark=new Rectangle2D.Double(x, y, markSize/scale, markSize/scale);
        DrawPanel drawPanel=ObjectTable.getDrawPanel();
        TempShape drawMark=new TempShape(id, mark, null, color, color, message, null, color,
                DrawParameters.DefaultFont);
        ObjectTable.getTempShapeManager("DrawShapeUtil").addTempShape(drawMark);
    }

    public static void drawTempShape(String id, Shape shape, Stroke stroke,
            Color lineColor,  Color fillColor, String message, Point2D messagePosition,
            Color messageColor){
        DrawPanel drawPanel=ObjectTable.getDrawPanel();
        TempShape drawMark=new TempShape(id, shape, stroke, lineColor, fillColor, message, 
                messagePosition, messageColor, DrawParameters.DefaultFont);
        ObjectTable.getTempShapeManager("DrawShapeUtil").addTempShape(drawMark);
    }

    public static void removeTempShape(String id, Point2D point) {
        DrawPanel drawPanel = ObjectTable.getDrawPanel();
        ObjectTable.getTempShapeManager("DrawShapeUtil").removeTempShape(id, point);
    }

    public static void clearTempShape(String id) {
        DrawPanel drawPanel = ObjectTable.getDrawPanel();
        ObjectTable.getTempShapeManager("DrawShapeUtil").clearTempShape(id);
    }

    public static void clearAllTempShapes() {
        DrawPanel drawPanel = ObjectTable.getDrawPanel();
        ObjectTable.getTempShapeManager().clearAllTempShapes();
    }

} 