@VisibleForTesting
void writeSelection(MutableAnnotationSet.Persistent document, FocusedRange selection,
String compositionState, double currentTimeMillis) {
// TODO(danilatos): Use focus and not end
Range range = selection == null ? null : selection.asRange();
String rangeKey = SelectionAnnotationHandler.rangeKey(sessionId);
String endKey = SelectionAnnotationHandler.endKey(sessionId);
String dataKey = SelectionAnnotationHandler.dataKey(sessionId);
String value = address;
int size = document.size();
// If we have a selection, then continually update regardless of old value,
// to refresh the timestamp.
if (range != null) {
document.setAnnotation(0, size, dataKey, address + "," + currentTimeMillis + ","
+ (compositionState != null ? compositionState : ""));
}
// TODO(danilatos): This fiddliness is necessary to avoid gratuitous
// re-rendering.
// Later the code can just use the resetAnnotation method, which will be
// MUCH
// simpler, once we have proper fine-granularity notifications.
int currentFocus = document.firstAnnotationChange(0, size, endKey, null);
int currentEnd = document.lastAnnotationChange(0, size, rangeKey, null);
if (currentEnd == -1) {
currentEnd = currentFocus;
}
if (currentEnd != -1) {
// if old selection is annotated
int currentStart = document.firstAnnotationChange(0, size, rangeKey, null);
if (currentStart == -1 || currentStart > currentEnd) {
currentStart = currentEnd;
}
if (range != null) {
// if new selection exists
int newStart = range.getStart();
int newEnd = range.getEnd();
int newFocus = selection.getFocus();
if (newFocus < currentFocus) {
document.setAnnotation(newFocus, currentFocus, endKey, value);
} else if (newFocus > currentFocus) {
document.setAnnotation(currentFocus, newFocus, endKey, null);
}
if (currentStart >= newEnd || newStart >= currentEnd) {
// If not overlapping
document.setAnnotation(currentStart, currentEnd, rangeKey, null);
document.setAnnotation(newStart, newEnd, rangeKey, value);
} else {
// If overlapping
if (currentStart < newStart) {
document.setAnnotation(currentStart, newStart, rangeKey, null);
} else if (currentStart > newStart) {
document.setAnnotation(newStart, currentStart, rangeKey, value);
}
if (currentEnd < newEnd) {
document.setAnnotation(currentEnd, newEnd, rangeKey, value);
} else if (currentEnd > newEnd) {
document.setAnnotation(newEnd, currentEnd, rangeKey, null);
}
}
} else {
// no new selection, clear old one
document.setAnnotation(currentFocus, size, endKey, null);
document.setAnnotation(currentStart, currentEnd, rangeKey, null);
document.setAnnotation(0, size, dataKey, null);
}
} else {
// no old selection
if (range != null) {
// new selection exists
document.setAnnotation(selection.getFocus(), size, endKey, value);
document.setAnnotation(range.getStart(), range.getEnd(), rangeKey, value);
}
}
}