diff --git a/richtextfx/src/main/java/org/fxmisc/richtext/EditableStyledDocument.java b/richtextfx/src/main/java/org/fxmisc/richtext/EditableStyledDocument.java index 9fba43067..13be8e999 100644 --- a/richtextfx/src/main/java/org/fxmisc/richtext/EditableStyledDocument.java +++ b/richtextfx/src/main/java/org/fxmisc/richtext/EditableStyledDocument.java @@ -20,10 +20,39 @@ public interface EditableStyledDocument extends StyledDocument { ReadOnlyStyledDocument snapshot(); default EventStream plainChanges() { + /* + The following code might seem a bit strange, but here's why it's used: + If a rich change is emitted that only changes the style, then inserted and removed are equal. + So, we want to exclude those style changes and only include changes where the actual text was modified + (e.g. some text was inserted/removed) + + If we use the following code, "getText() is repeated twice: + richChanges().filterMap( + // excludes style changes + c -> c.inserted.getText().equals(c.removed.getText()), // first time + c -> new PlainTextChange(c.position, c.removed.getText(), c.inserted.getText() // second time + ) + + To prevent code repetition, we could map the RichTextChange to a PlainTextChange and then filter out + the PlainTextChanges that don't actually change anything (the RichTextChange was merely a style change) + However, this produces unneeded PlainTextChange objects. + + So, to reduce code repetition and use less memory, the following approach is used. + */ return richChanges() - // only allow changes that added/removed text; exclude style changes - .filter(c -> c.insertedLength() != 0 || c.removedLength() != 0) - .map(c -> new PlainTextChange(c.position, c.removed.getText(), c.inserted.getText())); + .map(c -> { + String inserted = c.inserted.getText(); + String removed = c.removed.getText(); + if (!inserted.equals(removed)) { + // if reached, the rich change was an actual text change, not a style change... + return new PlainTextChange(c.position, removed, inserted); + } else { + // if reached, the rich change was a style change; text wasn't modified + return null; + } + }) + // now filter out the null values (the style changes) to insure no null events are emitted + .filter(c -> c != null); } EventStream> richChanges();