package com.github.donkirkby.vograbulary.russian;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import com.github.donkirkby.vograbulary.LetterDisplay;
import com.github.donkirkby.vograbulary.LetterDisplayFactory;
/**
* Control the display of one of the target words. This abstract class must
* have a concrete subclass for each platform that sets the position and
* content of the two text fields.
* @author don
*
*/
public abstract class TargetDisplay {
/** get the x position of the drag button for the target */
public abstract int getDragX();
/** set the x position of the drag button for the target */
public abstract void setDragX(int x);
/** is the drag button for the target visible? */
public abstract boolean isDragVisible();
/** set the visibility of the drag button for the target */
public abstract void setDragVisible(boolean isDragVisible);
/** is the insert button visible? */
public abstract boolean isInsertVisible();
/** set the visibility of the insert button. */
public abstract void setInsertVisible(boolean isInsertVisible);
private LetterDisplayFactory factory;
private List<LetterDisplay> letters = new ArrayList<>();
private Puzzle puzzle;
private int dragStartX;
private TargetDisplay other;
private int visibleBoundary;
private int sign;
private int screenWidth;
public TargetDisplay(LetterDisplayFactory factory) {
this.factory = factory;
}
public void setOther(TargetDisplay other) {
this.other = other;
other.other = this;
}
public void setPuzzle(Puzzle puzzle) {
this.puzzle = puzzle;
other.puzzle = puzzle;
setText(puzzle.getTarget(0));
other.setText(puzzle.getTarget(1));
setDragVisible(false);
other.setDragVisible(false);
setInsertVisible(true);
this.sign = other.sign = 0;
}
public void setText(String text) {
for (LetterDisplay letterDisplay : letters) {
factory.destroy(letterDisplay);
}
letters.clear();
for (int i = 0; i < text.length(); i++) {
LetterDisplay letter = factory.create(text.substring(i, i+1));
letters.add(letter);
}
}
public String getText() {
StringBuilder builder = new StringBuilder();
for (LetterDisplay letterDisplay : letters) {
builder.append(letterDisplay.getLetter());
}
return builder.toString();
}
public TargetDisplay getOther() {
return other;
}
public void dragStart(int x) {
dragStartX = x;
if (sign == 0) {
// first drag
setInsertVisible(false);
sign = (int)Math.signum(other.getLettersLeft() - getLettersLeft());
other.sign = -sign;
boolean isOtherMovingLeft = sign > 0;
other.recordLetterStartPositions(isOtherMovingLeft);
}
visibleBoundary =
screenWidth/2
- getLettersWidth() * (1+sign)/2
- other.getLettersWidth() * sign;
}
private void recordLetterStartPositions(boolean isMovingLeft) {
for (LetterDisplay letterDisplay : letters) {
letterDisplay.recordStartPosition();
letterDisplay.setMovingLeft(isMovingLeft);
}
}
public void drag(int x) {
int offset = x - dragStartX;
translate(offset);
for (LetterDisplay letterDisplay : letters) {
letterDisplay.setLeft(letterDisplay.getLeft() + offset);
}
other.surround(getLettersLeft(), getLettersRight());
other.setDragVisible(sign*getLettersLeft() <= sign*visibleBoundary);
}
public void dragStop() {
if (other.isDragVisible()) {
this.sign = other.sign = 0;
}
}
public int getLettersRight() {
return letters.get(letters.size()-1).getRight();
}
public int getLettersLeft() {
return letters.get(0).getLeft();
}
public int getLettersWidth() {
return getLettersRight() - getLettersLeft();
}
private void surround(int left, int right) {
List<LetterDisplay> before = new ArrayList<>();
List<LetterDisplay> after = new ArrayList<>();
for (LetterDisplay letterDisplay : letters) {
letterDisplay.split(left, right, before, after);
}
if (before.size() == 0 || after.size() == 0) {
puzzle.clearTargets();
}
else {
puzzle.setTargetWord(sign == 1 ? 0 : 1);
puzzle.setTargetCharacter(before.size());
}
if (before.size() > 0 && letters.get(letters.size()-1).getStartRight() > left) {
int leftEdge = left;
for (int i = before.size()-1; i >= 0; i--) {
LetterDisplay letterDisplay = letters.get(i);
letterDisplay.setRight(leftEdge);
leftEdge = letterDisplay.getLeft();
}
}
if (after.size() > 0 && letters.get(0).getStartLeft() < right) {
int rightEdge = right;
for (LetterDisplay letterDisplay : after) {
letterDisplay.setLeft(rightEdge);
rightEdge = letterDisplay.getRight();
}
}
}
private void translate(int offset) {
setDragX(getDragX() + offset);
}
public List<LetterDisplay> getLetters() {
return Collections.unmodifiableList(letters);
}
public void layout() {
int nextX = screenWidth / 2;
for (LetterDisplay letterDisplay : letters) {
nextX += letterDisplay.getWidth();
}
other.setDragX(nextX);
for (LetterDisplay letterDisplay : other.letters) {
letterDisplay.setLeft(nextX);
nextX += letterDisplay.getWidth();
}
nextX = screenWidth - nextX;
setDragX(nextX);
for (LetterDisplay letterDisplay : letters) {
letterDisplay.setLeft(nextX);
nextX += letterDisplay.getWidth();
}
}
/** Get the width of the screen that the display should be centred on. */
public int getScreenWidth() {
return screenWidth;
}
/** Set the width of the screen that the display should be centred on. */
public void setScreenWidth(int screenWidth) {
this.screenWidth = other.screenWidth = screenWidth;
}
}