DasherJava / src / dasherJava / core / startStop / TwoBoxesStartStopHandler.java
TwoBoxesStartStopHandler.java
Raw
package dasherJava.core.startStop;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import dasherJava.DasherJava;
import dasherJava.core.alphabets.RGBAColor;
import dasherJava.core.world.SquareWorldView;
import dasherJava.core.world.WorldGraphics.WorldGraphicsDrawCommand;
import dasherJava.core.world.WorldGraphics.WorldGraphicsFillRectCommand;

public class TwoBoxesStartStopHandler implements StartStopHandler<SquareWorldView> {
	
	private TwoBoxesState twoBoxesState = TwoBoxesState.OUTSIDE_FIRST_BOX;
	private long waitStartTime;
	
	@Override
	public StartStopAction processInput(float inputX, float inputY, boolean started, SquareWorldView parameters) {
		if (started && twoBoxesState!=TwoBoxesState.STARTED) { //externally started
			twoBoxesState=TwoBoxesState.STARTED;
			return StartStopAction.NOTHING_BUT_NEED_REPAINT;
		}
		if (!started && twoBoxesState==TwoBoxesState.STARTED) { //externally stopped
			if (getBox(inputX, inputY)==StartBox.FIRST_BOX) { //already in first box
				twoBoxesState=TwoBoxesState.WAITING_IN_FIRST_BOX;
				waitStartTime=System.nanoTime();
			} else twoBoxesState=TwoBoxesState.OUTSIDE_FIRST_BOX; //outside of first box
			return StartStopAction.NOTHING_BUT_NEED_REPAINT;
		}
		switch (twoBoxesState) {
			case OUTSIDE_FIRST_BOX:
				if (getBox(inputX, inputY)==StartBox.FIRST_BOX) { //entered first box
					twoBoxesState=TwoBoxesState.WAITING_IN_FIRST_BOX;
					waitStartTime=System.nanoTime();
					return StartStopAction.NOTHING_BUT_NEED_REPAINT;
				}
				break;
			case WAITING_IN_FIRST_BOX:
				if (getBox(inputX, inputY)!=StartBox.FIRST_BOX) { //cancel switch to second box
					twoBoxesState=TwoBoxesState.OUTSIDE_FIRST_BOX;
					return StartStopAction.NOTHING_BUT_NEED_REPAINT;
				}
				if (System.nanoTime()-waitStartTime>=DasherJava.getSettings().getFirstBoxHoldTime()*1000000L) {
					//switch to second box
					if (getBox(inputX, inputY)==StartBox.SECOND_BOX) //already in second box
						twoBoxesState=TwoBoxesState.WAITING_IN_SECOND_BOX;
					else twoBoxesState=TwoBoxesState.OUTSIDE_SECOND_BOX; //outside of second box
					waitStartTime=System.nanoTime();
					return StartStopAction.NOTHING_BUT_NEED_REPAINT;
				}
				break;
			case OUTSIDE_SECOND_BOX:
				if (getBox(inputX, inputY)==StartBox.SECOND_BOX) { //entered second box
					twoBoxesState=TwoBoxesState.WAITING_IN_SECOND_BOX;
					waitStartTime=System.nanoTime();
					return StartStopAction.NOTHING_BUT_NEED_REPAINT;
				}
				if (System.nanoTime()-waitStartTime>=DasherJava.getSettings().getFirstBoxResetTime()*1000000L) {
					//switch back to first box
					if (getBox(inputX, inputY)==StartBox.FIRST_BOX) { //already in first box
						twoBoxesState=TwoBoxesState.WAITING_IN_FIRST_BOX;
						waitStartTime=System.nanoTime();
					} else twoBoxesState=TwoBoxesState.OUTSIDE_FIRST_BOX; //outside of first box
					return StartStopAction.NOTHING_BUT_NEED_REPAINT;
				}
				break;
			case WAITING_IN_SECOND_BOX:
				if (getBox(inputX, inputY)!=StartBox.SECOND_BOX) { //cancel start
					twoBoxesState=TwoBoxesState.OUTSIDE_SECOND_BOX;
					return StartStopAction.NOTHING_BUT_NEED_REPAINT;
				}
				if (System.nanoTime()-waitStartTime>=DasherJava.getSettings().getSecondBoxHoldTime()*1000000L) {
					//start
					twoBoxesState=TwoBoxesState.STARTED;
					return StartStopAction.START;
				}
				break;
			case STARTED:
				break;
		}
		return StartStopAction.NOTHING;
	}
	
	@Override
	public List<WorldGraphicsDrawCommand> getUIDrawCommands(SquareWorldView parameters) {
		if (twoBoxesState==TwoBoxesState.STARTED) return Collections.emptyList();
		boolean secondBox = twoBoxesState==TwoBoxesState.OUTSIDE_SECOND_BOX
				|| twoBoxesState==TwoBoxesState.WAITING_IN_SECOND_BOX;
		int boxHeight = secondBox
				? Math.round(DasherJava.getSettings().getSecondBoxSize()*parameters.getHeight()/2.0f)
				: Math.round(DasherJava.getSettings().getFirstBoxSize()*parameters.getHeight()/2.0f);
		int leftInset = secondBox
				? Math.round(DasherJava.getSettings().getSecondBoxLeftInset()*parameters.getWidth()/2.0f)
				: Math.round(DasherJava.getSettings().getFirstBoxLeftInset()*parameters.getWidth()/2.0f);
		int rightInset = secondBox
				? Math.round(DasherJava.getSettings().getSecondBoxRightInset()*parameters.getWidth()/2.0f)
				: Math.round(DasherJava.getSettings().getFirstBoxRightInset()*parameters.getWidth()/2.0f);
		int boxY = secondBox ? parameters.getHeight()/2 : parameters.getHeight()/2-boxHeight;
		RGBAColor color = secondBox ? DasherJava.getGUIColors().getSecondStartBoxColor()
				: DasherJava.getGUIColors().getFirstStartBoxColor();
		float outlineThickness =
				secondBox
						? twoBoxesState==TwoBoxesState.WAITING_IN_SECOND_BOX
								? DasherJava.getSettings().getSecondBoxOutlineThicknessHold()
								: DasherJava.getSettings().getSecondBoxOutlineThickness()
						: twoBoxesState==TwoBoxesState.WAITING_IN_FIRST_BOX
								? DasherJava.getSettings().getFirstBoxOutlineThicknessHold()
								: DasherJava.getSettings().getFirstBoxOutlineThickness();
		List<WorldGraphicsDrawCommand> uiDrawCommands = new ArrayList<>(1);
		uiDrawCommands.add(new WorldGraphicsFillRectCommand(leftInset, boxY,
				parameters.getWidth()-leftInset-rightInset, boxHeight, null, color, outlineThickness));
		return uiDrawCommands;
	}
	
	private static StartBox getBox(float inputX, float inputY) {
		if (inputY>=-DasherJava.getSettings().getFirstBoxSize() && inputY<0.0f
				&& inputX>=-1.0f+DasherJava.getSettings().getFirstBoxLeftInset()
				&& inputX<=1.0f-DasherJava.getSettings().getFirstBoxRightInset()) return StartBox.FIRST_BOX;
		if (inputY>=0.0f && inputY<=DasherJava.getSettings().getSecondBoxSize()
				&& inputX>=-1.0f+DasherJava.getSettings().getSecondBoxLeftInset()
				&& inputX<=1.0f-DasherJava.getSettings().getSecondBoxRightInset()) return StartBox.SECOND_BOX;
		return StartBox.NO_BOX;
	}
	
	private enum TwoBoxesState {
		OUTSIDE_FIRST_BOX,
		WAITING_IN_FIRST_BOX,
		OUTSIDE_SECOND_BOX,
		WAITING_IN_SECOND_BOX,
		STARTED
	}
	
	private enum StartBox {
		NO_BOX,
		FIRST_BOX,
		SECOND_BOX
	}
}