package org.waveprotocol.wave.client.doodad.annotation; import java.util.HashMap; import java.util.Map; import org.waveprotocol.wave.client.common.util.JsoView; import org.waveprotocol.wave.client.editor.content.AnnotationPainter; import org.waveprotocol.wave.client.editor.content.AnnotationPainter.PaintFunction; import org.waveprotocol.wave.client.editor.content.ContentElement; import org.waveprotocol.wave.client.editor.content.ContentNode; import org.waveprotocol.wave.client.editor.content.PainterRegistry; import org.waveprotocol.wave.client.editor.content.Registries; import org.waveprotocol.wave.client.editor.content.misc.AnnotationPaint; import org.waveprotocol.wave.model.document.AnnotationBehaviour.AnnotationFamily; import org.waveprotocol.wave.model.document.AnnotationBehaviour.DefaultAnnotationBehaviour; import org.waveprotocol.wave.model.document.AnnotationMutationHandler; import org.waveprotocol.wave.model.document.util.AnnotationRegistry; import org.waveprotocol.wave.model.document.util.DocumentContext; import org.waveprotocol.wave.model.util.CollectionUtils; import org.waveprotocol.wave.model.util.ReadableStringMap.ProcV; /** * A generic handler to support new (non paragraph) annotations. * * @author Pablo Ojanguren (pablojan@gmail.com) * */ public class GeneralAnnotationHandler implements AnnotationMutationHandler { public interface Activator { public boolean shouldFireEvent(); } private static GeneralAnnotationHandler handlerInstance = null; private final AnnotationPainter painter; public static String getSafeKey(String key) { return key.replace("/", "-"); } /** * Logic to set paint attributes for the annotation (see {@link AnnotationPaint}). * Eventually, these attributes are rendered to HTML by {@link AnnotationSpreadRenderer}. */ private static class RenderFunc implements PaintFunction { private final String key; private final String cssClass; private final JsoView cssStyle; public RenderFunc(String key, String cssClass, JsoView cssStyle) { this.key = key; this.cssClass = cssClass; this.cssStyle = cssStyle; } public Map<String, String> apply(Map<String, Object> from, boolean isEditing) { Map<String, String> ret = new HashMap<String, String>(); for (String key : from.keySet()) { if (this.key.equals(key)) { String safeKey = getSafeKey(key); String safeValue = from.get(key).toString(); // <l:s v-comment="1234"> ret.put(AnnotationPaint.VALUE_ATTR_PREFIX + safeKey, safeValue); // <l:s el-comment="comment"> ... </l:s> ret.put(AnnotationPaint.EVENT_LISTENER_ATTR_PREFIX + safeKey, key); // <l:s ml-comment="comment"> ... </l:s> ret.put(AnnotationPaint.MUTATION_LISTENER_ATTR_PREFIX + safeKey, key); // <l:s class-comment="?"> .. </l:s> if (cssClass != null) ret.put(AnnotationPaint.CLASS_ATTR, cssClass); if (cssStyle != null) { cssStyle.each(new ProcV<String>() { @Override public void apply(String styleName, String styleValue) { ret.put(styleName, styleValue); } }); } } } return ret; } } /** * * * @param registries * @param key * @param mutationHanlder * @param eventHandler */ public static void register(Registries registries, String key, String cssClass, JsoView cssStyle) { PainterRegistry painterRegistry = registries.getPaintRegistry(); if (handlerInstance == null) handlerInstance = new GeneralAnnotationHandler(painterRegistry.getPainter()); AnnotationRegistry annotationRegistry = registries.getAnnotationHandlerRegistry(); annotationRegistry.registerHandler(key, handlerInstance); annotationRegistry.registerBehaviour(key, new DefaultAnnotationBehaviour(AnnotationFamily.CONTENT)); // Register painter to update attributes of the local view painterRegistry.registerPaintFunction(CollectionUtils.newStringSet(key), new RenderFunc(key, cssClass, cssStyle)); // TODO (pablojan) Not sure if boundary functions are required //painterRegistry.registerBoundaryFunction(,); } public GeneralAnnotationHandler(AnnotationPainter painter) { this.painter = painter; } @Override public <N, E extends N, T extends N> void handleAnnotationChange(DocumentContext<N, E, T> bundle, int start, int end, String key, Object newValue) { painter.scheduleRepaint(bundle, start, end); } public static boolean isAnnotationNode(ContentNode node) { ContentElement element = node.asElement(); if (element == null) return false; return element.getTagName().equals(AnnotationPaint.SPREAD_FULL_TAGNAME); } }