package org.waveprotocol.wave.client.doodad.annotation.jso; import org.waveprotocol.wave.client.common.util.JsoStringMap; import org.waveprotocol.wave.client.common.util.JsoView; import org.waveprotocol.wave.client.editor.content.CMutableDocument; import org.waveprotocol.wave.client.editor.content.ContentElement; import org.waveprotocol.wave.client.editor.content.ContentNode; import org.waveprotocol.wave.model.document.AnnotationInterval; import org.waveprotocol.wave.model.document.util.DocHelper; import org.waveprotocol.wave.model.document.util.Point; import org.waveprotocol.wave.model.document.util.Range; import org.waveprotocol.wave.model.util.CollectionUtils; import org.waveprotocol.wave.model.util.ReadableStringMap.ProcV; import org.waveprotocol.wave.model.util.StringMap; import com.google.gwt.core.client.JavaScriptObject; import com.google.gwt.dom.client.Node; /** * A single native Js class to handle different document and editor ranged stuff. * * @author pablojan@gmail.com (Pablo Ojanguren) * */ public class JsoRange extends JavaScriptObject { public static class Builder { JsoView jso; JsoView annotations; CMutableDocument doc; int start; int end; int length; public static Builder create(CMutableDocument doc) { return new Builder(doc); } protected Builder(CMutableDocument doc) { this.jso = JsoView.create(); this.doc = doc; } public Builder range(int start, int end, int length) { this.start = start; this.end = end; this.length = length; return this; } public Builder range(Range r) { return range(r.getStart(), r.getEnd(), r.getEnd() - r.getStart() + 1); } public Builder range(ContentElement contentElement) { start = contentElement.getContext().locationMapper().getLocation(contentElement); end = contentElement.getContext().locationMapper().getLocation(contentElement.getNextSibling()); length = DocHelper.getItemSize(doc, contentElement); return this; } public Builder annotation(String key, String value) { if (annotations == null) { annotations = JsoView.create(); } annotations.setString(key, value); return this; } public Builder annotations(JsoStringMap<String> map) { annotations = map.backend; return this; } public Builder annotationInterval(AnnotationInterval<String> interval) { range(interval.start(), interval.end(), interval.length()); interval.annotations().each(new ProcV<String>() { @Override public void apply(String key, String value) { annotation(key, value); } }); return this; } public JsoRange build() { jso.setNumber("start", start); jso.setNumber("end", end); jso.setNumber("lenght", length); if (annotations != null) jso.setJso("annotations", annotations); Node node = null; Point<ContentNode> point = doc.locate(start); if (point != null) node = point.getCanonicalNode().getImplNodeletRightwards(); jso.setJso("node", node); functionize(jso, doc); return jso.cast(); } private native void functionize(JavaScriptObject jso, CMutableDocument doc) /*-{ if (jso != null && typeof jso.start == "number" && typeof jso.end == "number") jso.text = @org.waveprotocol.wave.client.doodad.annotation.jso.JsoRange::getRangeText(IILorg/waveprotocol/wave/client/editor/content/CMutableDocument;)(jso.start, jso.end, doc); else jso = ""; }-*/; } public final native int start() /*-{ return this.start; }-*/; public final native int end() /*-{ return this.end; }-*/; private final native JsoView getAnnotationsJsoView() /*-{ return this.annotations; }-*/; public final StringMap<String> getAnnotations() { StringMap<String> map = CollectionUtils.<String>createStringMap(); JsoView annotations = getAnnotationsJsoView(); annotations.each(new ProcV<String>(){ @Override public void apply(String key, String value) { map.put(key, value); } }); return map; } private static String getRangeText(int start, int end, CMutableDocument doc) { return DocHelper.getText(doc, start, end); } private static void deleteRangeText(int start, int end, CMutableDocument doc) { doc.deleteRange(start, end); } protected JsoRange() { } }