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.comm.serverPush.client.ServerPushEventBus; import ch.unifr.pai.twice.widgets.client.events.UndoableRemoteKeyPressEvent; import com.google.gwt.event.dom.client.KeyCodes; import com.google.gwt.user.client.Command; public class RemoteTextInputInterpreter{ private String value; private Map<String, Integer> cursorPositions = new HashMap<String, Integer>(); private 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(); } public RemoteTextInputInterpreter(Command updateCallback, ServerPushEventBus eventBus, String source){ this.updateCallback = updateCallback; eventBus.addHandlerToSource(UndoableRemoteKeyPressEvent.TYPE, source, new UndoableRemoteKeyPressEvent.UndoableRemoteKeyPressHandler() { @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 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(); } }