package oripa.paint.core;
import java.awt.geom.Point2D;
/**
* a frame work of State pattern with undo,
* which can get back to previous state.
*
* Call doAction() to perform the action of the state.
* The flow of processing is:
* doAction(): onAct() -> quit proccessing if onAct() returns false -> onResult() -> finish!;
* unDo(): undoAction() -> finish!
* both method returns ActionState to be used next time.
* @author koji
*
*/
public abstract class AbstractActionState implements ActionState {
private Class<? extends ActionState> next, prev;
public AbstractActionState(){
initialize();
}
/**
* set next state class and previous state class here.
*/
protected abstract void initialize();
protected void setNextClass(Class<? extends ActionState> next){
this.next = next;
}
protected void setPreviousClass(Class<? extends ActionState> prev){
this.prev = prev;
}
/**
* first this method calls onAct(), then calls onResult()
* if onAct() returns true.
*
* @return A new instance of next state.
* if class of next state is not set (or is null),
* returns {@value this}.
*/
@Override
public final ActionState doAction(PaintContext context,
Point2D.Double currentPoint, boolean freeSelection) {
boolean success = onAct(context, currentPoint, freeSelection);
if(success == false){
// return this.cloneForNext();
return this;
}
onResult(context);
ActionState nextState = getNextState();
return nextState;
}
/**
* defines what to do after onAct() succeeded.
* @param context
*/
protected abstract void onResult(PaintContext context);
/**
* defines the job of this class.
*
* @param context information relating mouse action.
* @param currentPoint current point of mouse cursor.
* @param doSpecial true if you want switch the action.
* @return true if the action succeeded, otherwise false.
*/
protected abstract boolean onAct(PaintContext context,
Point2D.Double currentPoint, boolean doSpecial);
/**
* cancel the current actions and returns previous state.
* @return Previous state
*/
@Override
public final ActionState undo(PaintContext context) {
undoAction(context);
ActionState prevState = getPreviousState();
return prevState;
}
/**
* implement undo action. clean up the garbages!
* (and change previous state class if you need.)
* @param context
*/
protected abstract void undoAction(PaintContext context);
@Override
public void setNextState(ActionState state){
next = state.getClass();
}
@Override
public void setPreviousState(ActionState state){
prev = state.getClass();
}
@Override
public ActionState getNextState() {
return createInstance(next);
}
@Override
public ActionState getPreviousState() {
return createInstance(prev);
}
private ActionState createInstance(Class<? extends ActionState> c){
ActionState state = null;
if(c == null){
return this;
}
try {
state = c.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw new RuntimeException(e);
}
return state;
}
}