Repository: incubator-wave Updated Branches: refs/heads/master 74a91efe2 -> f698cd9a1
Text marked as deleted keeps the style properties of the source text. Project: http://git-wip-us.apache.org/repos/asf/incubator-wave/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-wave/commit/f698cd9a Tree: http://git-wip-us.apache.org/repos/asf/incubator-wave/tree/f698cd9a Diff: http://git-wip-us.apache.org/repos/asf/incubator-wave/diff/f698cd9a Branch: refs/heads/master Commit: f698cd9a1f783a3d6f30017aa9646d5f80a7c3dc Parents: 74a91ef Author: Denis Konovalchik <[email protected]> Authored: Fri Sep 12 19:12:19 2014 +0600 Committer: Andrew Kaplanov <[email protected]> Committed: Fri Sep 12 19:12:19 2014 +0600 ---------------------------------------------------------------------- .../editor/content/DiffHighlightingFilter.java | 95 +++++++++++++++++--- .../content/misc/StyleAnnotationHandler.java | 18 +--- .../model/conversation/AnnotationConstants.java | 23 +++++ 3 files changed, 107 insertions(+), 29 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/f698cd9a/src/org/waveprotocol/wave/client/editor/content/DiffHighlightingFilter.java ---------------------------------------------------------------------- diff --git a/src/org/waveprotocol/wave/client/editor/content/DiffHighlightingFilter.java b/src/org/waveprotocol/wave/client/editor/content/DiffHighlightingFilter.java index 30b4af2..cbf4a2f 100644 --- a/src/org/waveprotocol/wave/client/editor/content/DiffHighlightingFilter.java +++ b/src/org/waveprotocol/wave/client/editor/content/DiffHighlightingFilter.java @@ -22,17 +22,21 @@ package org.waveprotocol.wave.client.editor.content; import com.google.gwt.dom.client.Document; import com.google.gwt.dom.client.Element; import com.google.gwt.dom.client.Node; +import com.google.gwt.dom.client.Style; import org.waveprotocol.wave.client.common.util.DomHelper; +import org.waveprotocol.wave.client.editor.content.misc.StyleAnnotationHandler; import org.waveprotocol.wave.client.editor.content.paragraph.LineRendering; import org.waveprotocol.wave.client.editor.impl.DiffManager; import org.waveprotocol.wave.client.editor.impl.DiffManager.DiffType; + +import org.waveprotocol.wave.model.conversation.AnnotationConstants; +import org.waveprotocol.wave.model.document.AnnotationInterval; import org.waveprotocol.wave.model.document.MutableAnnotationSet; import org.waveprotocol.wave.model.document.operation.AnnotationBoundaryMap; import org.waveprotocol.wave.model.document.operation.Attributes; import org.waveprotocol.wave.model.document.operation.AttributesUpdate; import org.waveprotocol.wave.model.document.operation.DocOp; -import org.waveprotocol.wave.model.document.operation.DocOpComponentType; import org.waveprotocol.wave.model.document.operation.DocOpCursor; import org.waveprotocol.wave.model.document.operation.ModifiableDocument; import org.waveprotocol.wave.model.document.util.Annotations; @@ -40,9 +44,13 @@ import org.waveprotocol.wave.model.operation.OperationException; import org.waveprotocol.wave.model.util.CollectionUtils; import org.waveprotocol.wave.model.util.IntMap; import org.waveprotocol.wave.model.util.Preconditions; -import org.waveprotocol.wave.model.util.ReadableIntMap.ProcV; +import org.waveprotocol.wave.model.util.ReadableIntMap; +import org.waveprotocol.wave.model.util.ReadableStringMap; +import org.waveprotocol.wave.model.util.ReadableStringSet; +import org.waveprotocol.wave.model.util.StringMap; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; /** @@ -51,6 +59,7 @@ import java.util.List; * Operations applied will be rendered as diffs. * * @author [email protected] (Daniel Danilatos) + * @author [email protected] (Denis Konovalchik) */ public class DiffHighlightingFilter implements ModifiableDocument { @@ -151,7 +160,7 @@ public class DiffHighlightingFilter implements ModifiableDocument { final int size = inner.size(); - deleteInfos.each(new ProcV<Object>() { + deleteInfos.each(new ReadableIntMap.ProcV<Object>() { public void apply(int location, Object _item) { assert location <= size; @@ -255,6 +264,7 @@ public class DiffHighlightingFilter implements ModifiableDocument { currentDeleteLocation = currentLocation; } + @Override public void deleteElementStart(String type, Attributes attrs) { if (diffDepth == 0 && isOutsideInsertionAnnotation()) { ContentElement currentElement = (ContentElement) inner.getCurrentNode(); @@ -314,18 +324,17 @@ public class DiffHighlightingFilter implements ModifiableDocument { } } + @Override public void deleteCharacters(String text) { if (diffDepth == 0 && isOutsideInsertionAnnotation()) { - int location = currentLocation; - int endLocation = location + text.length(); + int endLocation = currentLocation + text.length(); updateDeleteInfo(); - int scanLocation = location; + int scanLocation = currentLocation; int nextScanLocation; do { - DeleteInfo surroundedInfo = (DeleteInfo) inner.getAnnotation(scanLocation, DIFF_DELETE_KEY); nextScanLocation = inner.firstAnnotationChange(scanLocation, endLocation, @@ -334,14 +343,8 @@ public class DiffHighlightingFilter implements ModifiableDocument { nextScanLocation = endLocation; } - int index = scanLocation - location; - int nextIndex = nextScanLocation - location; + saveDeletedText(text, currentLocation, scanLocation, nextScanLocation); - Element e = Document.get().createSpanElement(); - DiffManager.styleElement(e, DiffType.DELETE); - e.setInnerText(text.substring(index, nextIndex)); - - currentDeleteInfo.htmlElements.add(e); if (surroundedInfo != null) { currentDeleteInfo.htmlElements.addAll(surroundedInfo.htmlElements); } @@ -354,25 +357,89 @@ public class DiffHighlightingFilter implements ModifiableDocument { target.deleteCharacters(text); } + @Override public void annotationBoundary(AnnotationBoundaryMap map) { target.annotationBoundary(map); } + @Override public void replaceAttributes(Attributes oldAttrs, Attributes newAttrs) { currentLocation++; target.replaceAttributes(oldAttrs, newAttrs); } + @Override public void retain(int itemCount) { currentLocation += itemCount; target.retain(itemCount); } + @Override public void updateAttributes(AttributesUpdate attrUpdate) { currentLocation++; target.updateAttributes(attrUpdate); } + /** + * Creates text spans reflecting every combination of text formatting annotation values. + * + * @param text text to be saved + * @param textLocation location of the text beginning in the document + * @param startLocation start location of the deleted block + * @param finishLocation finish location of the deleted block + */ + private void saveDeletedText(String text, int textLocation, int startLocation, int finishLocation) { + // TODO(dyukon): This solution supports only text styles (weight, decoration, font etc.) + // which can be applied to text SPANs. + // It's necessary to add support for paragraph styles (headers ordered/numbered lists, + // indents) which cannot be kept in text SPANs. + Iterator<AnnotationInterval<Object>> aiIterator = inner.annotationIntervals( + startLocation, finishLocation, AnnotationConstants.DELETED_STYLE_KEYS).iterator(); + if (aiIterator.hasNext()) { // Some annotations are changed throughout deleted text + while (aiIterator.hasNext()) { + AnnotationInterval<Object> ai = aiIterator.next(); + createDeleteElement(text.substring(ai.start() - textLocation, ai.end() - textLocation), + ai.annotations()); + } + } else { // No annotations are changed throughout deleted text + createDeleteElement(text.substring(startLocation - textLocation, finishLocation - textLocation), + findDeletedStyleAnnotations(startLocation)); + } + } + + private ReadableStringMap<Object> findDeletedStyleAnnotations(final int location) { + final StringMap<Object> annotations = CollectionUtils.createStringMap(); + AnnotationConstants.DELETED_STYLE_KEYS.each(new ReadableStringSet.Proc() { + @Override + public void apply(String key) { + annotations.put(key, inner.getAnnotation(location, key)); + } + }); + return annotations; + } + + private void createDeleteElement(String innerText, ReadableStringMap<Object> annotations) { + Element element = Document.get().createSpanElement(); + applyAnnotationsToElement(element, annotations); + DiffManager.styleElement(element, DiffType.DELETE); + element.setInnerText(innerText); + currentDeleteInfo.htmlElements.add(element); + } + + private void applyAnnotationsToElement(Element element, ReadableStringMap<Object> annotations) { + final Style style = element.getStyle(); + annotations.each(new ReadableStringMap.ProcV<Object>() { + @Override + public void apply(String key, Object value) { + if (value != null && value instanceof String) { + String styleValue = (String) value; + if (!styleValue.isEmpty()) { + style.setProperty(StyleAnnotationHandler.suffix(key), styleValue); + } + } + } + }); + } }; /** http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/f698cd9a/src/org/waveprotocol/wave/client/editor/content/misc/StyleAnnotationHandler.java ---------------------------------------------------------------------- diff --git a/src/org/waveprotocol/wave/client/editor/content/misc/StyleAnnotationHandler.java b/src/org/waveprotocol/wave/client/editor/content/misc/StyleAnnotationHandler.java index f0a68f8..52bc016 100644 --- a/src/org/waveprotocol/wave/client/editor/content/misc/StyleAnnotationHandler.java +++ b/src/org/waveprotocol/wave/client/editor/content/misc/StyleAnnotationHandler.java @@ -29,8 +29,6 @@ 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.DocumentContext; -import org.waveprotocol.wave.model.util.CollectionUtils; -import org.waveprotocol.wave.model.util.ReadableStringSet; import java.util.HashMap; import java.util.Map; @@ -49,7 +47,7 @@ public class StyleAnnotationHandler implements AnnotationMutationHandler { * @param key * @return style suffix */ - private static final String suffix(String key) { + public static final String suffix(String key) { return key.substring(AnnotationConstants.STYLE_PREFIX.length() + 1); } @@ -74,12 +72,13 @@ public class StyleAnnotationHandler implements AnnotationMutationHandler { registries.getAnnotationHandlerRegistry().registerHandler(AnnotationConstants.STYLE_PREFIX, handler); registries.getAnnotationHandlerRegistry().registerBehaviour(AnnotationConstants.STYLE_PREFIX, new DefaultAnnotationBehaviour(AnnotationFamily.CONTENT)); - painterRegistry.registerPaintFunction(KEYS, renderFunc); + painterRegistry.registerPaintFunction(AnnotationConstants.STYLE_KEYS, renderFunc); } private final AnnotationPainter painter; private static final PaintFunction renderFunc = new PaintFunction() { + @Override public Map<String, String> apply(Map<String, Object> from, boolean isEditing) { Map<String, String> map = new HashMap<String, String>(); for (Map.Entry<String, Object> entry : from.entrySet()) { @@ -91,17 +90,6 @@ public class StyleAnnotationHandler implements AnnotationMutationHandler { } }; - public static final ReadableStringSet KEYS = CollectionUtils.newStringSet( - AnnotationConstants.STYLE_BG_COLOR, - AnnotationConstants.STYLE_COLOR, - AnnotationConstants.STYLE_FONT_FAMILY, - AnnotationConstants.STYLE_FONT_SIZE, - AnnotationConstants.STYLE_FONT_STYLE, - AnnotationConstants.STYLE_FONT_WEIGHT, - AnnotationConstants.STYLE_TEXT_DECORATION, - AnnotationConstants.STYLE_VERTICAL_ALIGN - ); - /** * @param painter painter to use for rendering */ http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/f698cd9a/src/org/waveprotocol/wave/model/conversation/AnnotationConstants.java ---------------------------------------------------------------------- diff --git a/src/org/waveprotocol/wave/model/conversation/AnnotationConstants.java b/src/org/waveprotocol/wave/model/conversation/AnnotationConstants.java index 3fe9284..dbceaf5 100644 --- a/src/org/waveprotocol/wave/model/conversation/AnnotationConstants.java +++ b/src/org/waveprotocol/wave/model/conversation/AnnotationConstants.java @@ -19,6 +19,9 @@ package org.waveprotocol.wave.model.conversation; +import org.waveprotocol.wave.model.util.CollectionUtils; +import org.waveprotocol.wave.model.util.ReadableStringSet; + /** * Constants useful for annotations * Refer to the conversation specification for more detailed information. @@ -45,6 +48,26 @@ public class AnnotationConstants { public static final String STYLE_VERTICAL_ALIGN = STYLE_PREFIX + "/verticalAlign"; + public static final ReadableStringSet STYLE_KEYS = CollectionUtils.newStringSet( + AnnotationConstants.STYLE_BG_COLOR, + AnnotationConstants.STYLE_COLOR, + AnnotationConstants.STYLE_FONT_FAMILY, + AnnotationConstants.STYLE_FONT_SIZE, + AnnotationConstants.STYLE_FONT_STYLE, + AnnotationConstants.STYLE_FONT_WEIGHT, + AnnotationConstants.STYLE_TEXT_DECORATION, + AnnotationConstants.STYLE_VERTICAL_ALIGN + ); + + public static final ReadableStringSet DELETED_STYLE_KEYS = CollectionUtils.newStringSet( + AnnotationConstants.STYLE_COLOR, + AnnotationConstants.STYLE_FONT_FAMILY, + AnnotationConstants.STYLE_FONT_SIZE, + AnnotationConstants.STYLE_FONT_STYLE, + AnnotationConstants.STYLE_FONT_WEIGHT, + AnnotationConstants.STYLE_VERTICAL_ALIGN + ); + // User /** Prefix for user annotations. */
