Skip to content

Commit

Permalink
trim paragraphs using reference comparison instead of object comparis…
Browse files Browse the repository at this point in the history
…on (issues FXMisc#777 and FXMisc#788)

(borrowed code from ReactFX, which uses same license as RichTextFX)
  • Loading branch information
DevCharly committed Dec 21, 2018
1 parent c2aff4e commit 635c28b
Showing 1 changed file with 73 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.ListIterator;

import org.reactfx.EventSource;
import org.reactfx.EventStream;
Expand All @@ -19,6 +20,8 @@
import org.reactfx.collection.QuasiListModification;
import org.reactfx.collection.SuspendableList;
import org.reactfx.collection.UnmodifiableByDefaultLiveList;
import org.reactfx.util.Tuple2;
import org.reactfx.util.Tuples;
import org.reactfx.value.SuspendableVal;
import org.reactfx.value.Val;

Expand All @@ -43,7 +46,7 @@ protected Subscription observeInputs() {
return parChangesList.subscribe(list -> {
ListChangeAccumulator<Paragraph<PS, SEG, S>> accumulator = new ListChangeAccumulator<>();
for (MaterializedListModification<Paragraph<PS, SEG, S>> mod : list) {
mod = mod.trim();
mod = trim(mod);

// add the quasiListModification itself, not as a quasiListChange, in case some overlap
accumulator.add(QuasiListModification.create(mod.getFrom(), mod.getRemoved(), mod.getAddedSize()));
Expand Down Expand Up @@ -217,4 +220,73 @@ private void updateMulti(
parChangesList.push(parChanges);
});
}

/**
* Copy of org.reactfx.collection.MaterializedListModification.trim()
* that uses reference comparison instead of equals().
*/
private MaterializedListModification<Paragraph<PS, SEG, S>> trim(MaterializedListModification<Paragraph<PS, SEG, S>> mod) {
return commonPrefixSuffixLengths(mod.getRemoved(), mod.getAdded()).map((pref, suff) -> {
if(pref == 0 && suff == 0) {
return mod;
} else {
return MaterializedListModification.create(
mod.getFrom() + pref,
mod.getRemoved().subList(pref, mod.getRemovedSize() - suff),
mod.getAdded().subList(pref, mod.getAddedSize() - suff));
}
});
}

/**
* Copy of org.reactfx.util.Lists.commonPrefixSuffixLengths()
* that uses reference comparison instead of equals().
*/
private static Tuple2<Integer, Integer> commonPrefixSuffixLengths(List<?> l1, List<?> l2) {
int n1 = l1.size();
int n2 = l2.size();

if(n1 == 0 || n2 == 0) {
return Tuples.t(0, 0);
}

int pref = commonPrefixLength(l1, l2);
if(pref == n1 || pref == n2) {
return Tuples.t(pref, 0);
}

int suff = commonSuffixLength(l1, l2);

return Tuples.t(pref, suff);
}

/**
* Copy of org.reactfx.util.Lists.commonPrefixLength()
* that uses reference comparison instead of equals().
*/
private static int commonPrefixLength(List<?> l, List<?> m) {
ListIterator<?> i = l.listIterator();
ListIterator<?> j = m.listIterator();
while(i.hasNext() && j.hasNext()) {
if(i.next() != j.next()) {
return i.nextIndex() - 1;
}
}
return i.nextIndex();
}

/**
* Copy of org.reactfx.util.Lists.commonSuffixLength()
* that uses reference comparison instead of equals().
*/
private static int commonSuffixLength(List<?> l, List<?> m) {
ListIterator<?> i = l.listIterator(l.size());
ListIterator<?> j = m.listIterator(m.size());
while(i.hasPrevious() && j.hasPrevious()) {
if(i.previous() != j.previous()) {
return l.size() - i.nextIndex() - 1;
}
}
return l.size() - i.nextIndex();
}
}

0 comments on commit 635c28b

Please sign in to comment.