final Multimap<Object, HandlerRegistration> HANDLER_REGISTRATION_MAP
= HashMultimap.create();
final EntityChangeStreamImpl entityChangeStream = new EntityChangeStreamImpl(engine, entity);
final EntityStreamRegistration entityStreamRegistration
= engine.getPeerState().addEntityStream(entityChangeStream);
widget.setValue(entity.getState().get());
HANDLER_REGISTRATION_MAP.put(widget, widget.addKeyDownHandler(new KeyDownHandler() {
@Override
public void onKeyDown(final KeyDownEvent event) {
if (shouldIgnoreKeyPress(event)) {
return;
}
if (widget.getSelectedText().length() > 0) {
stopEvents();
entityChangeStream.notifyDelete(widget.getCursorPos(), widget.getSelectedText());
startEvents();
}
else if (event.getNativeKeyCode() == KeyCodes.KEY_BACKSPACE) {
stopEvents();
final int index = widget.getCursorPos() - 1;
entityChangeStream.notifyDelete(index, " ");
startEvents();
}
else if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) {
stopEvents();
entityChangeStream.notifyInsert(widget.getCursorPos(), "\n");
startEvents();
}
}
}));
HANDLER_REGISTRATION_MAP.put(widget, widget.addKeyPressHandler(new KeyPressHandler() {
@Override
public void onKeyPress(final KeyPressEvent event) {
if (event.getUnicodeCharCode() != 13 && event.getUnicodeCharCode() != 0) {
stopEvents();
entityChangeStream.notifyInsert(widget.getCursorPos(), String.valueOf(event.getCharCode()));
startEvents();
}
}
}));
DOM.setEventListener(widget.getElement(), new EventListener() {
@Override
public void onBrowserEvent(Event event) {
if (event.getTypeInt() == Event.ONPASTE) {
final String before = (String) entity.getState().get();
new Timer() {
@Override
public void run() {
final String after = (String) widget.getValue();
final DiffUtil.Delta diff = DiffUtil.diff(before, after);
stopEvents();
entityChangeStream.notifyInsert(diff.getCursor(), diff.getDeltaText());
startEvents();
}
}.schedule(1);
}
widget.onBrowserEvent(event);
}
});
attachCutHandler(widget.getElement(), new Runnable() {
@Override
public void run() {
stopEvents();
entityChangeStream.notifyDelete(widget.getCursorPos(), widget.getSelectedText());
startEvents();
}
});
attachTextDragHandler(widget.getElement(), new Runnable() {
@Override
public void run() {
stopEvents();
entityChangeStream.notifyDelete(widget.getCursorPos(), widget.getSelectedText());
entityChangeStream.flush();
startEvents();
}
},
new Runnable() {
@Override
public void run() {
final String old = (String) entity.getState().get();
new Timer() {
@Override
public void run() {
final DiffUtil.Delta diff = DiffUtil.diff(old, (String) widget.getValue());
if (diff.getDeltaText().length() > 0) {
stopEvents();
entityChangeStream.notifyInsert(diff.getCursor(), diff.getDeltaText());
startEvents();
}
}
}.schedule(1);
}
}
);
final ListenerRegistration listenerRegistration
= entity.getState().addStateChangeListener(new StateChangeListener() {
@Override
public int getCursorPos() {
return widget.getCursorPos();
}
@Override
public void onStateChange(final int newCursorPos, final Object newValue) {
if (NO_PROPAGATE_STATE_CHANGE) {
return;
}
widget.setValue(newValue, false);
widget.setCursorPos(newCursorPos);
}
});
DOM.sinkEvents(widget.getElement(), DOM.getEventsSunk(widget.getElement()) | Event.ONPASTE);
final Timer timer = new Timer() {
@Override
public void run() {
entityChangeStream.flush();
}
};
timer.scheduleRepeating(500);
return new AtomizerSession() {
@Override
public void end() {
entityChangeStream.close();
timer.cancel();
logger.info("END ATOMIZER SESSION");
entityStreamRegistration.remove();
listenerRegistration.remove();
final Collection<HandlerRegistration> values = HANDLER_REGISTRATION_MAP.values();
for (final HandlerRegistration value : values) {
value.removeHandler();
}