Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,10 @@

public class PlainTextChange extends TextChange<String, PlainTextChange> {

private final ChangeType type;

public PlainTextChange(int position, String removed, String inserted) {
super(position, removed, inserted);
if (insertedLength() == 0) {
if (removedLength() == 0) {
throw new IllegalStateException(String.format("Cannot get the type of a change that neither inserts nor deletes anything." +
"removed=%s inserted=%s", removed, inserted));
} else {
type = ChangeType.DELETION;
}
} else if (removedLength() == 0) {
type = ChangeType.INSERTION;
} else {
type = ChangeType.REPLACEMENT;
}
}

@Override
public final ChangeType getType() { return type; }

@Override
protected int removedLength() {
return removed.length();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,10 @@

public class RichTextChange<PS, SEG, S> extends TextChange<StyledDocument<PS, SEG, S>, RichTextChange<PS, SEG, S>> {

private final ChangeType type;

public RichTextChange(int position, StyledDocument<PS, SEG, S> removed, StyledDocument<PS, SEG, S> inserted) {
super(position, removed, inserted);
if (insertedLength() == 0) {
if (removedLength() == 0) {
if (!removed.equals(inserted)) {
type = ChangeType.RESTYLED_PARAGRAPH;
} else {
throw new IllegalStateException(String.format("Cannot get the type of a change that neither inserts nor deletes anything." +
"removed=%s inserted=%s", removed, inserted));
}
} else {
type = ChangeType.DELETION;
}
} else if (removedLength() == 0) {
type = ChangeType.INSERTION;
} else {
type = ChangeType.REPLACEMENT;
}
}

@Override
public final ChangeType getType() { return type; }

@Override
protected int removedLength() {
return removed.length();
Expand Down
39 changes: 24 additions & 15 deletions richtextfx/src/main/java/org/fxmisc/richtext/model/TextChange.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,39 @@

public abstract class TextChange<S, Self extends TextChange<S, Self>> {

public static enum ChangeType {
/**
* Indicates whether this change can be merged with another change if they are both {@link #INSERTION} or
* both {@link #DELETION}.
*/
public static enum MergeType {
/** Indicates that the change will insert something but not remove anything */
INSERTION,
/** Indicates that the change will delete something but not insert anything */
DELETION,
/** Indicates that the change will remove something and insert something as its replacement.
* For {@link PlainTextChange}s, the replacement will only be content.
* For {@link RichTextChange}s, the replacement may only be the style, only the content, or a mix of both.
* Style changes may change the style of the paragraph's content or a non-empty {@link Paragraph}
* ({@code p.length() > 0}) */
REPLACEMENT,
/** Indicates that the paragraph style of an empty {@link Paragraph} ({@code p.length() == 0}) was changed */
RESTYLED_PARAGRAPH
/** Indicates that the change is a style change, a replacement or something other than the other two types */
NONE,
}


protected final int position;
protected final S removed;
protected final S inserted;
protected final MergeType mergeType;

public TextChange(int position, S removed, S inserted) {
this.position = position;
this.removed = removed;
this.inserted = inserted;

if (insertedLength() == 0) {
mergeType = removedLength() != 0
? MergeType.DELETION
: MergeType.NONE;
} else if (removedLength() == 0) {
mergeType = MergeType.INSERTION;
} else {
mergeType = MergeType.NONE;
}
}

public int getPosition() { return position; };
Expand All @@ -37,25 +46,25 @@ public TextChange(int position, S removed, S inserted) {
public Self invert() { return create(position, inserted, removed); }
public int getRemovalEnd() { return position + removedLength(); }
public int getInsertionEnd() { return position + insertedLength(); }
public final MergeType getMergeType() { return mergeType; };

public abstract ChangeType getType();
protected abstract int removedLength();
protected abstract int insertedLength();
protected abstract S concat(S a, S b);
protected abstract S sub(S s, int from, int to);
protected abstract Self create(int position, S removed, S inserted);

/**
* Merges this change with the given change only if the end of this change's inserted text
* equals the latter's position and both are either insertion or deletion changes.
* Merges this change with the given change only if the end of this change's inserted text equals the
* latter's position and both are either {@link MergeType#INSERTION} or {@link MergeType#DELETION} changes.
*
* @param latter change to merge with this change.
* @return a new merged change if changes can be merged,
* {@code null} otherwise.
*/
public Optional<Self> mergeWith(Self latter) {
if((this.getType() == ChangeType.INSERTION || this.getType() == ChangeType.DELETION)
&& this.getType() == latter.getType()
if((this.mergeType == MergeType.INSERTION || this.mergeType == MergeType.DELETION)
&& this.mergeType == latter.mergeType
&& this.getInsertionEnd() == latter.position) {
S removedText = concat(this.removed, latter.removed);
S addedText = concat(this.inserted, latter.inserted);
Expand Down Expand Up @@ -87,7 +96,7 @@ public final String toString() {
return
this.getClass().getSimpleName() + "{\n" +
"\tposition: " + position + "\n" +
"\ttype: " + getType() + "\n" +
"\tmergeType: " + mergeType + "\n" +
"\tremoved: " + removed + "\n" +
"\tinserted: " + inserted + "\n" +
"}";
Expand Down