package ch.unifr.pai.twice.widgets.client;
/*
* Copyright 2013 Oliver Schmid
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.util.HashMap;
import java.util.Map;
import ch.unifr.pai.twice.widgets.client.events.UndoableRemoteKeyPressEvent;
import ch.unifr.pai.twice.widgets.client.events.UndoableRemoteKeyPressEvent.UndoableRemoteKeyPressHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.user.client.Command;
/**
* Handler for an {@link UndoableRemoteKeyPressEvent}
*
* @author Oliver Schmid
*
*/
public class UndoableRemoteKeyPressHandlerImpl implements UndoableRemoteKeyPressHandler {
private String value;
private final Map<String, Integer> cursorPositions = new HashMap<String, Integer>();
private final Command updateCallback;
private int thisCursorPos;
public String getValue() {
return value;
}
public Map<String, Integer> getCursorPositions() {
return cursorPositions;
}
public void setValue(String value) {
this.value = value;
updateCallback.execute();
}
public void setCursorPositions(Map<String, Integer> positions) {
for (String p : positions.keySet()) {
cursorPositions.put(p, positions.get(p).intValue());
}
updateCallback.execute();
}
@Override
public void onEvent(UndoableRemoteKeyPressEvent event) {
String device = event.getOriginatingDevice();
if (event.getKeyCode() != null) {
switch (event.getKeyCode()) {
case KeyCodes.KEY_DELETE:
delete(device);
break;
case KeyCodes.KEY_BACKSPACE:
bckspc(device);
break;
}
}
else if (event.getText() != null) {
addChar(event.getText(), device);
}
Integer cursorPos = event.getCursorPos();
if (cursorPos != null) {
if (cursorPos > 0) {
shiftCursorPosRight(device, cursorPos);
}
else {
shiftCursorPosLeft(device, Math.abs(cursorPos));
}
}
}
@Override
public void undo(UndoableRemoteKeyPressEvent event) {
value = event.getStorageProperty("value");
}
@Override
public void saveState(UndoableRemoteKeyPressEvent event) {
event.setStorageProperty("value", value);
}
public UndoableRemoteKeyPressHandlerImpl(Command updateCallback) {
this.updateCallback = updateCallback;
}
public int getThisCursorPos() {
return thisCursorPos;
}
public int getCursorPos(String device) {
Integer pos = cursorPositions.get(device);
return pos == null ? 0 : pos;
}
private void delete(String device) {
if (thisCursorPos < value.length()) {
value = value.substring(0, thisCursorPos) + value.substring(thisCursorPos + 1);
shiftAll(thisCursorPos, device, -1);
updateCallback.execute();
}
}
private void bckspc(String device) {
if (thisCursorPos > 0 && value != null && value.length() > 0) {
value = value.substring(0, thisCursorPos - 1) + (thisCursorPos < value.length() ? value.substring(thisCursorPos) : "");
shiftAll(thisCursorPos + 1, device, -1);
updateCallback.execute();
}
}
private void shiftCursorPosLeft(String device, int amount) {
int pos = thisCursorPos;
if (pos >= amount) {
thisCursorPos = pos - amount;
updateCallback.execute();
}
}
private void shiftCursorPosRight(String device, int amount) {
int pos = thisCursorPos;
if (value != null && pos + amount <= value.length()) {
thisCursorPos = pos + amount;
updateCallback.execute();
}
}
private void addChar(String text, String device) {
StringBuilder sb = new StringBuilder();
if (value != null && thisCursorPos > -1)
sb.append(value.substring(0, Math.min(value.length(), thisCursorPos)));
sb.append(text);
if (value != null && thisCursorPos > -1 && thisCursorPos < value.length()) {
sb.append(value.substring(Math.min(value.length(), thisCursorPos)));
}
value = sb.toString();
shiftAll(thisCursorPos, device, text.length());
updateCallback.execute();
}
private void shiftAll(int curPos, String device, int amount) {
if ((amount > 0 && curPos <= thisCursorPos) || (amount < 0 && curPos > thisCursorPos))
thisCursorPos = thisCursorPos + amount;
for (String s : cursorPositions.keySet()) {
int p = cursorPositions.get(s);
// if (!s.equals(device)) {
// shift right
if ((amount < 0 && curPos < p) || (amount > 0 && curPos > p))
cursorPositions.put(s, p + amount);
// }
}
updateCallback.execute();
}
}