package oripa.paint.core;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import javax.vecmath.Vector2d;
import oripa.paint.EditMode;
import oripa.paint.GraphicMouseActionInterface;
import oripa.paint.ScreenUpdaterInterface;
import oripa.paint.geometry.GeometricOperation;
import oripa.paint.util.ElementSelector;
import oripa.value.OriLine;
import oripa.viewsetting.main.ScreenUpdater;
public abstract class GraphicMouseAction implements GraphicMouseActionInterface {
private EditMode editMode = EditMode.INPUT;
private boolean needSelect = false;
private ActionState state;
protected void log(double x, double y){
System.out.println(x + "," + y);
}
protected void log(Vector2d p){
if(p == null){
return;
}
log(p.x, p.y);
}
protected final void setActionState(ActionState state){
this.state = state;
}
protected final ActionState getActionState(){
return state;
}
protected final boolean currentStateIs(Class<? extends ActionState> s){
return state.equals(s);
}
/* (非 Javadoc)
* @see oripa.paint.core.GraphicMouseActionInterface#needSelect()
*/
@Override
public final boolean needSelect() {
return needSelect;
}
protected final void setNeedSelect(boolean selectable) {
this.needSelect = selectable;
}
protected final void setEditMode(EditMode mode){
editMode = mode;
}
/* (非 Javadoc)
* @see oripa.paint.core.GraphicMouseActionInterface#getEditMode()
*/
@Override
public final EditMode getEditMode(){
return editMode;
}
/* (非 Javadoc)
* @see oripa.paint.core.GraphicMouseActionInterface#destroy(oripa.paint.core.PaintContext)
*/
@Override
public void destroy(PaintContext context){
context.clear(false);
}
/* (非 Javadoc)
* @see oripa.paint.core.GraphicMouseActionInterface#recover(oripa.paint.core.PaintContext)
*/
@Override
public void recover(PaintContext context){
}
/* (非 Javadoc)
* @see oripa.paint.core.GraphicMouseActionInterface#onLeftClick(oripa.paint.core.PaintContext, java.awt.geom.AffineTransform, boolean)
*/
@Override
public GraphicMouseActionInterface onLeftClick(PaintContext context,
AffineTransform affine, boolean differentAction){
Point2D.Double clickPoint = context.getLogicalMousePoint();
doAction(context, clickPoint, differentAction);
return this;
}
/* (非 Javadoc)
* @see oripa.paint.core.GraphicMouseActionInterface#doAction(oripa.paint.core.PaintContext, java.awt.geom.Point2D.Double, boolean)
*/
@Override
public void doAction(PaintContext context, Point2D.Double point, boolean differntAction){
state = state.doAction(context,
point, differntAction);
// TODO move this variable to parameter
ScreenUpdaterInterface screenUpdater = ScreenUpdater.getInstance();
screenUpdater.updateScreen();
}
/* (非 Javadoc)
* @see oripa.paint.core.GraphicMouseActionInterface#onRightClick(oripa.paint.core.PaintContext, java.awt.geom.AffineTransform, boolean)
*/
@Override
public void onRightClick(PaintContext context, AffineTransform affine,
boolean differentAction) {
undo(context);
}
/* (非 Javadoc)
* @see oripa.paint.core.GraphicMouseActionInterface#undo(oripa.paint.core.PaintContext)
*/
@Override
public void undo(PaintContext context){
state = BasicUndo.undo(state, context);
}
/* (非 Javadoc)
* @see oripa.paint.core.GraphicMouseActionInterface#onMove(oripa.paint.core.PaintContext, java.awt.geom.AffineTransform, boolean)
*/
@Override
public Vector2d onMove(
PaintContext context, AffineTransform affine, boolean differentAction) {
setCandidateVertexOnMove(context, differentAction);
setCandidateLineOnMove(context);
return context.pickCandidateV;
}
protected final void setCandidateVertexOnMove(
PaintContext context, boolean differentAction) {
context.pickCandidateV = GeometricOperation.pickVertex(
context, differentAction);
}
protected final void setCandidateLineOnMove(PaintContext context) {
context.pickCandidateL = GeometricOperation.pickLine(
context);
}
/* (非 Javadoc)
* @see oripa.paint.core.GraphicMouseActionInterface#onPress(oripa.paint.core.PaintContext, java.awt.geom.AffineTransform, boolean)
*/
@Override
public abstract void onPress(PaintContext context, AffineTransform affine, boolean differentAction);
/* (非 Javadoc)
* @see oripa.paint.core.GraphicMouseActionInterface#onDrag(oripa.paint.core.PaintContext, java.awt.geom.AffineTransform, boolean)
*/
@Override
public abstract void onDrag(PaintContext context, AffineTransform affine, boolean differentAction);
/* (非 Javadoc)
* @see oripa.paint.core.GraphicMouseActionInterface#onRelease(oripa.paint.core.PaintContext, java.awt.geom.AffineTransform, boolean)
*/
@Override
public abstract void onRelease(PaintContext context, AffineTransform affine, boolean differentAction);
/* (非 Javadoc)
* @see oripa.paint.core.GraphicMouseActionInterface#onDraw(java.awt.Graphics2D, oripa.paint.core.PaintContext)
*/
@Override
public void onDraw(Graphics2D g2d, PaintContext context){
drawPickedLines(g2d, context);
drawPickedVertices(g2d, context);
}
private void drawPickedLines(Graphics2D g2d, PaintContext context){
for(int i = 0; i < context.getLineCount(); i++){
g2d.setColor(LineSetting.LINE_COLOR_PICKED);
g2d.setStroke(LineSetting.STROKE_PICKED);
OriLine line = context.getLine(i);
drawLine(g2d, line);
}
}
private void drawPickedVertices(Graphics2D g2d, PaintContext context){
ElementSelector selector = new ElementSelector();
for(int i = 0; i < context.getVertexCount(); i++){
g2d.setColor(selector.selectColorByLineType(PaintConfig.inputLineType));
Vector2d vertex = context.getVertex(i);
drawVertex(g2d, context, vertex.x, vertex.y);
}
}
/**
* draw a picked vertex as an small rectangle at (x, y)
* @param g2d
* @param context
* @param x
* @param y
*/
protected void drawVertex(Graphics2D g2d, PaintContext context,
double x, double y){
double scale = context.scale;
g2d.fill(new Rectangle2D.Double(x - 5.0 / scale,
y - 5.0 / scale, 10.0 / scale, 10.0 / scale));
}
protected void drawPickCandidateVertex(Graphics2D g2d, PaintContext context){
if (context.pickCandidateV != null) {
g2d.setColor(LineSetting.LINE_COLOR_CANDIDATE);
Vector2d candidate = context.pickCandidateV;
drawVertex(g2d, context, candidate.x, candidate.y);
}
}
protected void drawLine(Graphics2D g2d, OriLine line){
g2d.draw(new Line2D.Double(line.p0.x, line.p0.y,
line.p1.x, line.p1.y));
}
protected void drawLine(Graphics2D g2d, Vector2d p0, Vector2d p1){
g2d.draw(new Line2D.Double(p0.x, p0.y,
p1.x, p1.y));
}
protected void drawPickCandidateLine(Graphics2D g2d, PaintContext context){
if (context.pickCandidateL!= null) {
g2d.setColor(LineSetting.LINE_COLOR_CANDIDATE);
OriLine candidate = context.pickCandidateL;
drawLine(g2d, candidate);
}
}
/**
* draws the line between the most recently selected vertex and
* the closest vertex sufficiently to the mouse cursor.
* if every vertex is far from cursor, this method uses the cursor point
* instead of close vertex.
* @param g2d
* @param context
*/
protected void drawTemporaryLine(Graphics2D g2d, PaintContext context){
ElementSelector selector = new ElementSelector();
if(context.getVertexCount() > 0){
Vector2d picked = context.peekVertex();
Color color = selector.selectColorByLineType(PaintConfig.inputLineType);
g2d.setColor(color);
drawLine(g2d, picked, GeometricOperation.getCandidateVertex(context, true));
}
}
}