From 9297625ca7f0c40ee924423e3c2c25ea73c39820 Mon Sep 17 00:00:00 2001 From: JordanMartinez Date: Thu, 14 Jan 2016 09:35:36 -0800 Subject: [PATCH 1/6] Renamed Paragraph to NormalParagraph so that later commits will be easier to understand when interface `Paragraph` is implemented . --- .../richtext/demo/richtext/RichText.java | 6 +- .../richtext/EditableStyledDocument.java | 62 +++++++++---------- .../{Paragraph.java => NormalParagraph.java} | 62 +++++++++---------- .../org/fxmisc/richtext/ParagraphBox.java | 4 +- .../org/fxmisc/richtext/ParagraphText.java | 6 +- .../richtext/ReadOnlyStyledDocument.java | 26 ++++---- .../org/fxmisc/richtext/StyledDocument.java | 2 +- .../fxmisc/richtext/StyledDocumentBase.java | 28 ++++----- .../org/fxmisc/richtext/StyledTextArea.java | 28 ++++----- .../org/fxmisc/richtext/TextEditingArea.java | 2 +- 10 files changed, 113 insertions(+), 113 deletions(-) rename richtextfx/src/main/java/org/fxmisc/richtext/{Paragraph.java => NormalParagraph.java} (82%) diff --git a/richtextfx-demos/src/main/java/org/fxmisc/richtext/demo/richtext/RichText.java b/richtextfx-demos/src/main/java/org/fxmisc/richtext/demo/richtext/RichText.java index 3cec92be8..d88d76d2d 100644 --- a/richtextfx-demos/src/main/java/org/fxmisc/richtext/demo/richtext/RichText.java +++ b/richtextfx-demos/src/main/java/org/fxmisc/richtext/demo/richtext/RichText.java @@ -35,7 +35,7 @@ import org.fxmisc.flowless.VirtualizedScrollPane; import org.fxmisc.richtext.AreaFactory; -import org.fxmisc.richtext.Paragraph; +import org.fxmisc.richtext.NormalParagraph; import org.fxmisc.richtext.StyleSpans; import org.fxmisc.richtext.StyledTextArea; import org.reactfx.SuspendableNo; @@ -150,7 +150,7 @@ protected boolean computeValue() { int startPar = area.offsetToPosition(selection.getStart(), Forward).getMajor(); int endPar = area.offsetToPosition(selection.getEnd(), Backward).getMajor(); - List> pars = area.getParagraphs().subList(startPar, endPar + 1); + List> pars = area.getParagraphs().subList(startPar, endPar + 1); @SuppressWarnings("unchecked") Optional[] alignments = pars.stream().map(p -> p.getParagraphStyle().alignment).distinct().toArray(Optional[]::new); @@ -331,7 +331,7 @@ private void updateParagraphStyleInSelection(Function update int startPar = area.offsetToPosition(selection.getStart(), Forward).getMajor(); int endPar = area.offsetToPosition(selection.getEnd(), Backward).getMajor(); for(int i = startPar; i <= endPar; ++i) { - Paragraph paragraph = area.getParagraph(i); + NormalParagraph paragraph = area.getParagraph(i); area.setParagraphStyle(i, updater.apply(paragraph.getParagraphStyle())); } } diff --git a/richtextfx/src/main/java/org/fxmisc/richtext/EditableStyledDocument.java b/richtextfx/src/main/java/org/fxmisc/richtext/EditableStyledDocument.java index f00e17cbb..17fc6ea0c 100644 --- a/richtextfx/src/main/java/org/fxmisc/richtext/EditableStyledDocument.java +++ b/richtextfx/src/main/java/org/fxmisc/richtext/EditableStyledDocument.java @@ -32,7 +32,7 @@ * on styled text, but not worrying about additional aspects such as * caret or selection. */ -final class EditableStyledDocument extends StyledDocumentBase>> { +final class EditableStyledDocument extends StyledDocumentBase>> { /* ********************************************************************** * * * @@ -65,7 +65,7 @@ final class EditableStyledDocument extends StyledDocumentBase> getParagraphs() { + public ObservableList> getParagraphs() { return FXCollections.unmodifiableObservableList(paragraphs); } @@ -163,7 +163,7 @@ public ReadOnlyStyledDocument snapshot() { @SuppressWarnings("unchecked") EditableStyledDocument(S initialStyle, PS initialParagraphStyle) { - super(FXCollections.observableArrayList(new Paragraph<>(initialParagraphStyle, "", initialStyle))); + super(FXCollections.observableArrayList(new NormalParagraph<>(initialParagraphStyle, "", initialStyle))); this.initialStyle = initialStyle; this.initialParagraphStyle = initialParagraphStyle; } @@ -198,17 +198,17 @@ public void replace(int start, int end, StyledDocument replacement) { int lastParTo = end2D.getMinor(); // Get the leftovers after cutting out the deletion - Paragraph firstPar = paragraphs.get(firstParIdx).trim(firstParFrom); - Paragraph lastPar = paragraphs.get(lastParIdx).subSequence(lastParTo); + NormalParagraph firstPar = paragraphs.get(firstParIdx).trim(firstParFrom); + NormalParagraph lastPar = paragraphs.get(lastParIdx).subSequence(lastParTo); - List> replacementPars = replacement.getParagraphs(); + List> replacementPars = replacement.getParagraphs(); - List> newPars = join(firstPar, replacementPars, lastPar); + List> newPars = join(firstPar, replacementPars, lastPar); setAll(firstParIdx, lastParIdx + 1, newPars); // update length, invalidate text int replacementLength = - replacementPars.stream().mapToInt(Paragraph::length).sum() + + replacementPars.stream().mapToInt(NormalParagraph::length).sum() + replacementPars.size() - 1; int newLength = length.getValue() - (end - start) + replacementLength; length.suspendWhile(() -> { // don't publish length change until text is invalidated @@ -239,22 +239,22 @@ public void setStyle(int from, int to, S style) { int lastParTo = end.getMinor(); if(firstParIdx == lastParIdx) { - Paragraph p = paragraphs.get(firstParIdx); + NormalParagraph p = paragraphs.get(firstParIdx); p = p.restyle(firstParFrom, lastParTo, style); paragraphs.set(firstParIdx, p); } else { int affectedPars = lastParIdx - firstParIdx + 1; - List> restyledPars = new ArrayList<>(affectedPars); + List> restyledPars = new ArrayList<>(affectedPars); - Paragraph firstPar = paragraphs.get(firstParIdx); + NormalParagraph firstPar = paragraphs.get(firstParIdx); restyledPars.add(firstPar.restyle(firstParFrom, firstPar.length(), style)); for(int i = firstParIdx + 1; i < lastParIdx; ++i) { - Paragraph p = paragraphs.get(i); + NormalParagraph p = paragraphs.get(i); restyledPars.add(p.restyle(style)); } - Paragraph lastPar = paragraphs.get(lastParIdx); + NormalParagraph lastPar = paragraphs.get(lastParIdx); restyledPars.add(lastPar.restyle(0, lastParTo, style)); setAll(firstParIdx, lastParIdx + 1, restyledPars); @@ -263,7 +263,7 @@ public void setStyle(int from, int to, S style) { } public void setStyle(int paragraph, S style) { - Paragraph p = paragraphs.get(paragraph); + NormalParagraph p = paragraphs.get(paragraph); int start = position(paragraph, 0).toOffset(); int end = start + p.length(); @@ -280,7 +280,7 @@ public void setStyle(int paragraph, int fromCol, int toCol, S style) { int end = parOffset + toCol; try(Guard commitOnClose = beginStyleChange(start, end)) { - Paragraph p = paragraphs.get(paragraph); + NormalParagraph p = paragraphs.get(paragraph); p = p.restyle(fromCol, toCol, style); paragraphs.set(paragraph, p); } @@ -311,23 +311,23 @@ public void setStyleSpans(int from, StyleSpans styleSpans) { int lastParTo = end.getMinor(); if(firstParIdx == lastParIdx) { - Paragraph p = paragraphs.get(firstParIdx); - Paragraph q = p.restyle(firstParFrom, styleSpans); + NormalParagraph p = paragraphs.get(firstParIdx); + NormalParagraph q = p.restyle(firstParFrom, styleSpans); if(q != p) { paragraphs.set(firstParIdx, q); } } else { - Paragraph firstPar = paragraphs.get(firstParIdx); + NormalParagraph firstPar = paragraphs.get(firstParIdx); Position spansFrom = styleSpans.position(0, 0); Position spansTo = spansFrom.offsetBy(firstPar.length() - firstParFrom, Backward); - Paragraph q = firstPar.restyle(firstParFrom, styleSpans.subView(spansFrom, spansTo)); + NormalParagraph q = firstPar.restyle(firstParFrom, styleSpans.subView(spansFrom, spansTo)); if(q != firstPar) { paragraphs.set(firstParIdx, q); } spansFrom = spansTo.offsetBy(1, Forward); // skip the newline for(int i = firstParIdx + 1; i < lastParIdx; ++i) { - Paragraph par = paragraphs.get(i); + NormalParagraph par = paragraphs.get(i); spansTo = spansFrom.offsetBy(par.length(), Backward); q = par.restyle(0, styleSpans.subView(spansFrom, spansTo)); if(q != par) { @@ -336,7 +336,7 @@ public void setStyleSpans(int from, StyleSpans styleSpans) { spansFrom = spansTo.offsetBy(1, Forward); // skip the newline } - Paragraph lastPar = paragraphs.get(lastParIdx); + NormalParagraph lastPar = paragraphs.get(lastParIdx); spansTo = spansFrom.offsetBy(lastParTo, Backward); q = lastPar.restyle(0, styleSpans.subView(spansFrom, spansTo)); if(q != lastPar) { @@ -354,8 +354,8 @@ public void setStyleSpans(int paragraph, int from, StyleSpans style int end = start + len; try(Guard commitOnClose = beginStyleChange(start, end)) { - Paragraph p = paragraphs.get(paragraph); - Paragraph q = p.restyle(from, styleSpans); + NormalParagraph p = paragraphs.get(paragraph); + NormalParagraph q = p.restyle(from, styleSpans); if(q != p) { paragraphs.set(paragraph, q); } @@ -364,13 +364,13 @@ public void setStyleSpans(int paragraph, int from, StyleSpans style public void setParagraphStyle(int parIdx, PS style) { ensureValidParagraphIndex(parIdx); - Paragraph par = paragraphs.get(parIdx); + NormalParagraph par = paragraphs.get(parIdx); int len = par.length(); int start = position(parIdx, 0).toOffset(); int end = start + len; try(Guard commitOnClose = beginStyleChange(start, end)) { - Paragraph q = par.setParagraphStyle(style); + NormalParagraph q = par.setParagraphStyle(style); paragraphs.set(parIdx, q); } } @@ -405,7 +405,7 @@ private int fullLength(int par) { } private int terminatorLengthToSkip(Position pos) { - Paragraph par = paragraphs.get(pos.getMajor()); + NormalParagraph par = paragraphs.get(pos.getMajor()); int skipSum = 0; while(pos.getMinor() == par.length() && pos.getMajor() < paragraphs.size() - 1) { skipSum += 1; @@ -433,14 +433,14 @@ private Guard beginStyleChange(int start, int end) { return () -> styleChangeDone.push(null); } - private List> join(Paragraph first, List> middle, Paragraph last) { + private List> join(NormalParagraph first, List> middle, NormalParagraph last) { int m = middle.size(); if(m == 0) { return Arrays.asList(first.concat(last)); } else if(m == 1) { return Arrays.asList(first.concat(middle.get(0)).concat(last)); } else { - List> res = new ArrayList<>(middle.size()); + List> res = new ArrayList<>(middle.size()); res.add(first.concat(middle.get(0))); res.addAll(middle.subList(1, m - 1)); res.add(middle.get(m-1).concat(last)); @@ -450,7 +450,7 @@ private List> join(Paragraph first, List> pars) { + private void setAll(int startIdx, int endIdx, Collection> pars) { if(startIdx > 0 || endIdx < paragraphs.size()) { paragraphs.subList(startIdx, endIdx).clear(); // note that paragraphs remains non-empty at all times paragraphs.addAll(startIdx, pars); @@ -467,7 +467,7 @@ S getStyleForInsertionAt(Position insertionPos) { if(useInitialStyleForInsertion.get()) { return initialStyle; } else { - Paragraph par = paragraphs.get(insertionPos.getMajor()); + NormalParagraph par = paragraphs.get(insertionPos.getMajor()); return par.getStyleAtPosition(insertionPos.getMinor()); } } @@ -480,7 +480,7 @@ PS getParagraphStyleForInsertionAt(Position insertionPos) { if(useInitialStyleForInsertion.get()) { return initialParagraphStyle; } else { - Paragraph par = paragraphs.get(insertionPos.getMajor()); + NormalParagraph par = paragraphs.get(insertionPos.getMajor()); return par.getParagraphStyle(); } } diff --git a/richtextfx/src/main/java/org/fxmisc/richtext/Paragraph.java b/richtextfx/src/main/java/org/fxmisc/richtext/NormalParagraph.java similarity index 82% rename from richtextfx/src/main/java/org/fxmisc/richtext/Paragraph.java rename to richtextfx/src/main/java/org/fxmisc/richtext/NormalParagraph.java index ed70850bc..dbc27e236 100644 --- a/richtextfx/src/main/java/org/fxmisc/richtext/Paragraph.java +++ b/richtextfx/src/main/java/org/fxmisc/richtext/NormalParagraph.java @@ -11,7 +11,7 @@ import org.fxmisc.richtext.TwoDimensional.Position; -public final class Paragraph implements CharSequence { +public final class NormalParagraph implements CharSequence { @SafeVarargs private static List list(T head, T... tail) { @@ -29,16 +29,16 @@ private static List list(T head, T... tail) { private final TwoLevelNavigator navigator; private final PS paragraphStyle; - public Paragraph(PS paragraphStyle, String text, S style) { + public NormalParagraph(PS paragraphStyle, String text, S style) { this(paragraphStyle, new StyledText<>(text, style)); } @SafeVarargs - public Paragraph(PS paragraphStyle, StyledText text, StyledText... texts) { + public NormalParagraph(PS paragraphStyle, StyledText text, StyledText... texts) { this(paragraphStyle, list(text, texts)); } - Paragraph(PS paragraphStyle, List> segments) { + NormalParagraph(PS paragraphStyle, List> segments) { assert !segments.isEmpty(); this.segments = segments; this.paragraphStyle = paragraphStyle; @@ -77,7 +77,7 @@ public String substring(int from) { return toString().substring(from); } - public Paragraph concat(Paragraph p) { + public NormalParagraph concat(NormalParagraph p) { if(length() == 0) { return p; } @@ -94,16 +94,16 @@ public Paragraph concat(Paragraph p) { segs.addAll(segments.subList(0, segments.size()-1)); segs.add(segment); segs.addAll(p.segments.subList(1, p.segments.size())); - return new Paragraph<>(paragraphStyle, segs); + return new NormalParagraph<>(paragraphStyle, segs); } else { List> segs = new ArrayList<>(segments.size() + p.segments.size()); segs.addAll(segments); segs.addAll(p.segments); - return new Paragraph<>(paragraphStyle, segs); + return new NormalParagraph<>(paragraphStyle, segs); } } - public Paragraph concat(CharSequence str) { + public NormalParagraph concat(CharSequence str) { if(str.length() == 0) { return this; } @@ -111,10 +111,10 @@ public Paragraph concat(CharSequence str) { List> segs = new ArrayList<>(segments); int lastIdx = segments.size() - 1; segs.set(lastIdx, segments.get(lastIdx).concat(str)); - return new Paragraph<>(paragraphStyle, segs); + return new NormalParagraph<>(paragraphStyle, segs); } - public Paragraph insert(int offset, CharSequence str) { + public NormalParagraph insert(int offset, CharSequence str) { if(offset < 0 || offset > length()) { throw new IndexOutOfBoundsException(String.valueOf(offset)); } @@ -126,15 +126,15 @@ public Paragraph insert(int offset, CharSequence str) { StyledText replacement = seg.spliced(segPos, segPos, str); List> segs = new ArrayList<>(segments); segs.set(segIdx, replacement); - return new Paragraph<>(paragraphStyle, segs); + return new NormalParagraph<>(paragraphStyle, segs); } @Override - public Paragraph subSequence(int start, int end) { + public NormalParagraph subSequence(int start, int end) { return trim(end).subSequence(start); } - public Paragraph trim(int length) { + public NormalParagraph trim(int length) { if(length >= length()) { return this; } else { @@ -143,11 +143,11 @@ public Paragraph trim(int length) { List> segs = new ArrayList<>(segIdx + 1); segs.addAll(segments.subList(0, segIdx)); segs.add(segments.get(segIdx).subSequence(0, pos.getMinor())); - return new Paragraph<>(paragraphStyle, segs); + return new NormalParagraph<>(paragraphStyle, segs); } } - public Paragraph subSequence(int start) { + public NormalParagraph subSequence(int start) { if(start < 0) { throw new IllegalArgumentException("start must not be negative (was: " + start + ")"); } else if(start == 0) { @@ -158,40 +158,40 @@ public Paragraph subSequence(int start) { List> segs = new ArrayList<>(segments.size() - segIdx); segs.add(segments.get(segIdx).subSequence(pos.getMinor())); segs.addAll(segments.subList(segIdx + 1, segments.size())); - return new Paragraph<>(paragraphStyle, segs); + return new NormalParagraph<>(paragraphStyle, segs); } else { throw new IndexOutOfBoundsException(start + " not in [0, " + length() + "]"); } } - public Paragraph delete(int start, int end) { + public NormalParagraph delete(int start, int end) { return trim(start).concat(subSequence(end)); } - public Paragraph restyle(S style) { - return new Paragraph<>(paragraphStyle, toString(), style); + public NormalParagraph restyle(S style) { + return new NormalParagraph<>(paragraphStyle, toString(), style); } - public Paragraph restyle(int from, int to, S style) { + public NormalParagraph restyle(int from, int to, S style) { if(from >= length()) { return this; } else { to = Math.min(to, length()); - Paragraph left = subSequence(0, from); - Paragraph middle = new Paragraph<>(paragraphStyle, substring(from, to), style); - Paragraph right = subSequence(to); + NormalParagraph left = subSequence(0, from); + NormalParagraph middle = new NormalParagraph<>(paragraphStyle, substring(from, to), style); + NormalParagraph right = subSequence(to); return left.concat(middle).concat(right); } } - public Paragraph restyle(int from, StyleSpans styleSpans) { + public NormalParagraph restyle(int from, StyleSpans styleSpans) { int len = styleSpans.length(); if(styleSpans.equals(getStyleSpans(from, from + len))) { return this; } - Paragraph left = trim(from); - Paragraph right = subSequence(from + len); + NormalParagraph left = trim(from); + NormalParagraph right = subSequence(from + len); String middleString = substring(from, from + len); List> middleSegs = new ArrayList<>(styleSpans.getSpanCount()); @@ -202,13 +202,13 @@ public Paragraph restyle(int from, StyleSpans styleSpans) { middleSegs.add(new StyledText<>(text, span.getStyle())); offset = end; } - Paragraph middle = new Paragraph<>(paragraphStyle, middleSegs); + NormalParagraph middle = new NormalParagraph<>(paragraphStyle, middleSegs); return left.concat(middle).concat(right); } - public Paragraph setParagraphStyle(PS paragraphStyle) { - return new Paragraph<>(paragraphStyle, segments); + public NormalParagraph setParagraphStyle(PS paragraphStyle) { + return new NormalParagraph<>(paragraphStyle, segments); } /** @@ -314,8 +314,8 @@ public String toString() { @Override public boolean equals(Object other) { - if(other instanceof Paragraph) { - Paragraph that = (Paragraph) other; + if(other instanceof NormalParagraph) { + NormalParagraph that = (NormalParagraph) other; return Objects.equals(this.paragraphStyle, that.paragraphStyle) && Objects.equals(this.segments, that.segments); } else { diff --git a/richtextfx/src/main/java/org/fxmisc/richtext/ParagraphBox.java b/richtextfx/src/main/java/org/fxmisc/richtext/ParagraphBox.java index 6e31a4395..f26bada8a 100644 --- a/richtextfx/src/main/java/org/fxmisc/richtext/ParagraphBox.java +++ b/richtextfx/src/main/java/org/fxmisc/richtext/ParagraphBox.java @@ -69,7 +69,7 @@ public ObjectProperty> graphicFactoryProperty() { public void setIndex(int index) { this.index.setValue(index); } public int getIndex() { return index.getValue(); } - ParagraphBox(Paragraph par, BiConsumer applyStyle, BiConsumer applyParagraphStyle) { + ParagraphBox(NormalParagraph par, BiConsumer applyStyle, BiConsumer applyParagraphStyle) { this.getStyleClass().add("paragraph-box"); this.text = new ParagraphText<>(par, applyStyle); applyParagraphStyle.accept(this.text, par.getParagraphStyle()); @@ -107,7 +107,7 @@ public String toString() { public Property selectionProperty() { return text.selectionProperty(); } - Paragraph getParagraph() { + NormalParagraph getParagraph() { return text.getParagraph(); } diff --git a/richtextfx/src/main/java/org/fxmisc/richtext/ParagraphText.java b/richtextfx/src/main/java/org/fxmisc/richtext/ParagraphText.java index 73352e4f1..53b560e36 100644 --- a/richtextfx/src/main/java/org/fxmisc/richtext/ParagraphText.java +++ b/richtextfx/src/main/java/org/fxmisc/richtext/ParagraphText.java @@ -39,7 +39,7 @@ public ObjectProperty highlightTextFillProperty() { public ObjectProperty selectionProperty() { return selection; } public void setSelection(IndexRange sel) { selection.set(sel); } - private final Paragraph paragraph; + private final NormalParagraph paragraph; private final Path caretShape = new Path(); private final Path selectionShape = new Path(); @@ -53,7 +53,7 @@ public ObjectProperty highlightTextFillProperty() { caretShape.visibleProperty().bind(caretVisible); } - public ParagraphText(Paragraph par, BiConsumer applyStyle) { + public ParagraphText(NormalParagraph par, BiConsumer applyStyle) { this.paragraph = par; getStyleClass().add("paragraph-text"); @@ -118,7 +118,7 @@ public ParagraphText(Paragraph par, BiConsumer applyS } } - public Paragraph getParagraph() { + public NormalParagraph getParagraph() { return paragraph; } diff --git a/richtextfx/src/main/java/org/fxmisc/richtext/ReadOnlyStyledDocument.java b/richtextfx/src/main/java/org/fxmisc/richtext/ReadOnlyStyledDocument.java index 4129c2013..cc7e5b6bb 100644 --- a/richtextfx/src/main/java/org/fxmisc/richtext/ReadOnlyStyledDocument.java +++ b/richtextfx/src/main/java/org/fxmisc/richtext/ReadOnlyStyledDocument.java @@ -11,7 +11,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -public class ReadOnlyStyledDocument extends StyledDocumentBase>> { +public class ReadOnlyStyledDocument extends StyledDocumentBase>> { private static final Pattern LINE_TERMINATOR = Pattern.compile("\r\n|\r|\n"); @@ -20,17 +20,17 @@ public static ReadOnlyStyledDocument fromString(String str, S sty int n = 1; while(m.find()) ++n; - List> res = new ArrayList<>(n); + List> res = new ArrayList<>(n); int start = 0; m.reset(); while(m.find()) { String s = str.substring(start, m.start()); - res.add(new Paragraph<>(paragraphStyle, s, style)); + res.add(new NormalParagraph<>(paragraphStyle, s, style)); start = m.end(); } String last = str.substring(start); - res.add(new Paragraph<>(paragraphStyle, last, style)); + res.add(new NormalParagraph<>(paragraphStyle, last, style)); return new ReadOnlyStyledDocument<>(res, ADOPT); } @@ -42,7 +42,7 @@ enum ParagraphsPolicy { static Codec> codec(Codec tCodec, Codec pCodec) { return new Codec>() { - private final Codec>> codec = Codec.listCodec(paragraphCodec(tCodec, pCodec)); + private final Codec>> codec = Codec.listCodec(paragraphCodec(tCodec, pCodec)); @Override public String getName() { @@ -64,8 +64,8 @@ public StyledDocument decode(DataInputStream is) throws IOException { }; } - private static Codec> paragraphCodec(Codec tCodec, Codec pCodec) { - return new Codec>() { + private static Codec> paragraphCodec(Codec tCodec, Codec pCodec) { + return new Codec>() { private final Codec>> segmentsCodec = Codec.listCodec(styledTextCodec(tCodec)); @Override @@ -74,16 +74,16 @@ public String getName() { } @Override - public void encode(DataOutputStream os, Paragraph p) throws IOException { + public void encode(DataOutputStream os, NormalParagraph p) throws IOException { pCodec.encode(os, p.getParagraphStyle()); segmentsCodec.encode(os, p.getSegments()); } @Override - public Paragraph decode(DataInputStream is) throws IOException { + public NormalParagraph decode(DataInputStream is) throws IOException { PS paragraphStyle = pCodec.decode(is); List> segments = segmentsCodec.decode(is); - return new Paragraph<>(paragraphStyle, segments); + return new NormalParagraph<>(paragraphStyle, segments); } }; } @@ -117,7 +117,7 @@ public StyledText decode(DataInputStream is) throws IOException { private String text = null; - ReadOnlyStyledDocument(List> paragraphs, ParagraphsPolicy policy) { + ReadOnlyStyledDocument(List> paragraphs, ParagraphsPolicy policy) { super(policy == ParagraphsPolicy.ADOPT ? paragraphs : new ArrayList<>(paragraphs)); } @@ -138,11 +138,11 @@ public String getText() { } @Override - public List> getParagraphs() { + public List> getParagraphs() { return Collections.unmodifiableList(paragraphs); } private int computeLength() { - return paragraphs.stream().mapToInt(Paragraph::length).sum() + paragraphs.size() - 1; + return paragraphs.stream().mapToInt(NormalParagraph::length).sum() + paragraphs.size() - 1; } } diff --git a/richtextfx/src/main/java/org/fxmisc/richtext/StyledDocument.java b/richtextfx/src/main/java/org/fxmisc/richtext/StyledDocument.java index ed9eeb6ed..036d73b57 100644 --- a/richtextfx/src/main/java/org/fxmisc/richtext/StyledDocument.java +++ b/richtextfx/src/main/java/org/fxmisc/richtext/StyledDocument.java @@ -29,5 +29,5 @@ public interface StyledDocument extends CharSequence, TwoDimensional { StyleSpans getStyleSpans(int paragraph); StyleSpans getStyleSpans(int paragraph, int from, int to); - List> getParagraphs(); + List> getParagraphs(); } diff --git a/richtextfx/src/main/java/org/fxmisc/richtext/StyledDocumentBase.java b/richtextfx/src/main/java/org/fxmisc/richtext/StyledDocumentBase.java index 737dd943d..387063550 100644 --- a/richtextfx/src/main/java/org/fxmisc/richtext/StyledDocumentBase.java +++ b/richtextfx/src/main/java/org/fxmisc/richtext/StyledDocumentBase.java @@ -11,7 +11,7 @@ import javafx.scene.control.IndexRange; -abstract class StyledDocumentBase>> +abstract class StyledDocumentBase>> implements StyledDocument { protected final L paragraphs; @@ -50,8 +50,8 @@ public String getText(IndexRange range) { public String getText(int start, int end) { return sub( start, end, - Paragraph::toString, - Paragraph::substring, + NormalParagraph::toString, + NormalParagraph::substring, pars -> String.join("\n", pars)); } @@ -77,7 +77,7 @@ public StyledDocument subSequence(int start, int end) { start, end, p -> p, (p, a, b) -> p.subSequence(a, b), - (List> pars) -> new ReadOnlyStyledDocument<>(pars, ADOPT)); + (List> pars) -> new ReadOnlyStyledDocument<>(pars, ADOPT)); } @Override @@ -87,11 +87,11 @@ public StyledDocument subDocument(int paragraphIndex) { @Override public final StyledDocument concat(StyledDocument that) { - List> pars1 = this.getParagraphs(); - List> pars2 = that.getParagraphs(); + List> pars1 = this.getParagraphs(); + List> pars2 = that.getParagraphs(); int n1 = pars1.size(); int n2 = pars2.size(); - List> pars = new ArrayList<>(n1 + n2 - 1); + List> pars = new ArrayList<>(n1 + n2 - 1); pars.addAll(pars1.subList(0, n1 - 1)); pars.add(pars1.get(n1 - 1).concat(pars2.get(0))); pars.addAll(pars2.subList(1, n2)); @@ -150,18 +150,18 @@ public StyleSpans getStyleSpans(int from, int to) { List> subSpans = new ArrayList<>(affectedPars); if(startParIdx == endParIdx) { - Paragraph par = paragraphs.get(startParIdx); + NormalParagraph par = paragraphs.get(startParIdx); subSpans.add(par.getStyleSpans(start.getMinor(), end.getMinor())); } else { - Paragraph startPar = paragraphs.get(startParIdx); + NormalParagraph startPar = paragraphs.get(startParIdx); subSpans.add(startPar.getStyleSpans(start.getMinor(), startPar.length() + 1)); for(int i = startParIdx + 1; i < endParIdx; ++i) { - Paragraph par = paragraphs.get(i); + NormalParagraph par = paragraphs.get(i); subSpans.add(par.getStyleSpans(0, par.length() + 1)); } - Paragraph endPar = paragraphs.get(endParIdx); + NormalParagraph endPar = paragraphs.get(endParIdx); subSpans.add(endPar.getStyleSpans(0, end.getMinor())); } @@ -226,8 +226,8 @@ private interface SubMap { */ private R sub( int start, int end, - Function, P> map, - SubMap, P> subMap, + Function, P> map, + SubMap, P> subMap, Function, R> combine) { Position start2D = navigator.offsetToPosition(start, Forward); @@ -244,7 +244,7 @@ private R sub( if(p1 == p2) { pars.add(subMap.subrange(paragraphs.get(p1), col1, col2)); } else { - Paragraph par1 = paragraphs.get(p1); + NormalParagraph par1 = paragraphs.get(p1); pars.add(subMap.subrange(par1, col1, par1.length())); for(int i = p1 + 1; i < p2; ++i) { diff --git a/richtextfx/src/main/java/org/fxmisc/richtext/StyledTextArea.java b/richtextfx/src/main/java/org/fxmisc/richtext/StyledTextArea.java index 3002b76e1..5d6be773e 100644 --- a/richtextfx/src/main/java/org/fxmisc/richtext/StyledTextArea.java +++ b/richtextfx/src/main/java/org/fxmisc/richtext/StyledTextArea.java @@ -374,8 +374,8 @@ public Optional, Codec>> getStyleCodecs() { @Override public final ObservableValue caretColumnProperty() { return caretColumn; } // paragraphs - private final SuspendableList> paragraphs; - @Override public ObservableList> getParagraphs() { + private final SuspendableList> paragraphs; + @Override public ObservableList> getParagraphs() { return paragraphs; } @@ -434,7 +434,7 @@ public Optional, Codec>> getStyleCodecs() { private final Val> _popupAnchorAdjustment; - private final VirtualFlow, Cell, ParagraphBox>> virtualFlow; + private final VirtualFlow, Cell, ParagraphBox>> virtualFlow; // used for two-level navigation, where on the higher level are // paragraphs and on the lower level are lines within a paragraph @@ -679,7 +679,7 @@ public StyledTextArea(S initialStyle, BiConsumer applyStyle, virtualFlow = VirtualFlow.createVertical( getParagraphs(), par -> { - Cell, ParagraphBox> cell = createCell( + Cell, ParagraphBox> cell = createCell( par, applyStyle, initialParagraphStyle, @@ -780,7 +780,7 @@ CharacterHit hit(ParagraphBox.CaretOffsetX x, TwoDimensional.Position targetLine } CharacterHit hit(ParagraphBox.CaretOffsetX x, double y) { - VirtualFlowHit, ParagraphBox>> hit = virtualFlow.hit(0.0, y); + VirtualFlowHit, ParagraphBox>> hit = virtualFlow.hit(0.0, y); if(hit.isBeforeCells()) { return CharacterHit.insertionAt(0); } else if(hit.isAfterCells()) { @@ -812,7 +812,7 @@ CharacterHit hit(ParagraphBox.CaretOffsetX x, double y) { * @param y */ public CharacterHit hit(double x, double y) { - VirtualFlowHit, ParagraphBox>> hit = virtualFlow.hit(x, y); + VirtualFlowHit, ParagraphBox>> hit = virtualFlow.hit(x, y); if(hit.isBeforeCells()) { return CharacterHit.insertionAt(0); } else if(hit.isAfterCells()) { @@ -837,7 +837,7 @@ public CharacterHit hit(double x, double y) { */ TwoDimensional.Position currentLine() { int parIdx = getCurrentParagraph(); - Cell, ParagraphBox> cell = virtualFlow.getCell(parIdx); + Cell, ParagraphBox> cell = virtualFlow.getCell(parIdx); int lineIdx = cell.getNode().getCurrentLineIndex(); return _position(parIdx, lineIdx); } @@ -856,7 +856,7 @@ public String getText(int paragraph) { return paragraphs.get(paragraph).toString(); } - public Paragraph getParagraph(int index) { + public NormalParagraph getParagraph(int index) { return paragraphs.get(index); } @@ -1019,7 +1019,7 @@ void show(double y) { void showCaretAtBottom() { int parIdx = getCurrentParagraph(); - Cell, ParagraphBox> cell = virtualFlow.getCell(parIdx); + Cell, ParagraphBox> cell = virtualFlow.getCell(parIdx); Bounds caretBounds = cell.getNode().getCaretBounds(); double y = caretBounds.getMaxY(); virtualFlow.showAtOffset(parIdx, getViewportHeight() - y); @@ -1027,7 +1027,7 @@ void showCaretAtBottom() { void showCaretAtTop() { int parIdx = getCurrentParagraph(); - Cell, ParagraphBox> cell = virtualFlow.getCell(parIdx); + Cell, ParagraphBox> cell = virtualFlow.getCell(parIdx); Bounds caretBounds = cell.getNode().getCaretBounds(); double y = caretBounds.getMinY(); virtualFlow.showAtOffset(parIdx, -y); @@ -1040,7 +1040,7 @@ void requestFollowCaret() { private void followCaret() { int parIdx = getCurrentParagraph(); - Cell, ParagraphBox> cell = virtualFlow.getCell(parIdx); + Cell, ParagraphBox> cell = virtualFlow.getCell(parIdx); Bounds caretBounds = cell.getNode().getCaretBounds(); double graphicWidth = cell.getNode().getGraphicPrefWidth(); Bounds region = extendLeft(caretBounds, graphicWidth); @@ -1224,8 +1224,8 @@ protected void layoutChildren() { * * * ********************************************************************** */ - private Cell, ParagraphBox> createCell( - Paragraph paragraph, + private Cell, ParagraphBox> createCell( + NormalParagraph paragraph, BiConsumer applyStyle, PS initialParagraphStyle, BiConsumer applyParagraphStyle) { @@ -1262,7 +1262,7 @@ private Cell, ParagraphBox> createCell( }, selectionProperty(), box.indexProperty()); box.selectionProperty().bind(cellSelection); - return new Cell, ParagraphBox>() { + return new Cell, ParagraphBox>() { @Override public ParagraphBox getNode() { return box; diff --git a/richtextfx/src/main/java/org/fxmisc/richtext/TextEditingArea.java b/richtextfx/src/main/java/org/fxmisc/richtext/TextEditingArea.java index 6bc865ea3..3569011ad 100644 --- a/richtextfx/src/main/java/org/fxmisc/richtext/TextEditingArea.java +++ b/richtextfx/src/main/java/org/fxmisc/richtext/TextEditingArea.java @@ -91,7 +91,7 @@ public interface TextEditingArea { /** * Unmodifiable observable list of paragraphs in this text area. */ - ObservableList> getParagraphs(); + ObservableList> getParagraphs(); /********************* From 70af4c64a057fc454e40aea0c00116db6dbce22d Mon Sep 17 00:00:00 2001 From: JordanMartinez Date: Thu, 14 Jan 2016 16:21:43 -0800 Subject: [PATCH 2/6] Partial commit: created Paragraph interface which EmptyParagraph and NormalParagraph will implement. --- .../org/fxmisc/richtext/EmptyParagraph.java | 170 ++++++++++++++++++ .../java/org/fxmisc/richtext/Paragraph.java | 70 ++++++++ 2 files changed, 240 insertions(+) create mode 100644 richtextfx/src/main/java/org/fxmisc/richtext/EmptyParagraph.java create mode 100644 richtextfx/src/main/java/org/fxmisc/richtext/Paragraph.java diff --git a/richtextfx/src/main/java/org/fxmisc/richtext/EmptyParagraph.java b/richtextfx/src/main/java/org/fxmisc/richtext/EmptyParagraph.java new file mode 100644 index 000000000..1ad6a86e4 --- /dev/null +++ b/richtextfx/src/main/java/org/fxmisc/richtext/EmptyParagraph.java @@ -0,0 +1,170 @@ +package org.fxmisc.richtext; + +import javafx.scene.control.IndexRange; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Objects; + +public class EmptyParagraph implements Paragraph { + + public static final IndexRange EMPTY_RANGE = new IndexRange(0,0); + + private final List> segments = new ArrayList<>(0); + private final PS paragraphStyle; + private final S emptyTextStyle; + + EmptyParagraph(PS paragraphStyle, S emptyTextStyle) { + this.paragraphStyle = paragraphStyle; + this.emptyTextStyle = emptyTextStyle; + } + + public List> getSegments() { + return Collections.unmodifiableList(segments); + } + + public PS getParagraphStyle() { + return paragraphStyle; + } + + @Override + public int length() { + return 0; + } + + @Override + public char charAt(int index) { + return '\n'; + } + + public String substring(int from, int to) { + return ""; + } + + public String substring(int from) { + return ""; + } + + public Paragraph concat(Paragraph p) { + return p; + } + + // Refactor: use this to find cases where a CharSequence is used + public Paragraph concat(CharSequence str) { + throw new UnsupportedOperationException( + "Empty Paragraph cannot create a new NormalParagraph because " + + "it doesn't know what Style object to pass for the NormalParagraph's constructor. " + + "Use `concat(Paragraph p)` instead" + ); + } + + public Paragraph insert(int offset, Paragraph p) { + return p; + } + + // Refactor: use this to find cases where a CharSequence is used + public Paragraph insert(int offset, CharSequence str) { + throw new UnsupportedOperationException( + "Empty Paragraph cannot create a new NormalParagraph because " + + "it doesn't know what Style object to pass for the NormalParagraph's constructor. " + + "Use `concat(Paragraph p)` instead" + ); + } + + @Override + public Paragraph subSequence(int start, int end) { + return this; + } + + public Paragraph trim(int length) { + return this; + } + + public Paragraph subSequence(int start) { + return this; + } + + public Paragraph delete(int start, int end) { + return this; + } + + public Paragraph restyle(S style) { + return this; + } + + public Paragraph restyle(int from, int to, S style) { + return this; + } + + public Paragraph restyle(int from, StyleSpans styleSpans) { + return this; + } + + public Paragraph setParagraphStyle(PS paragraphStyle) { + return new EmptyParagraph<>(paragraphStyle, emptyTextStyle); + } + + /** + * Returns the style of character with the given index. + * If {@code charIdx < 0}, returns the style at the beginning of this paragraph. + * If {@code charIdx >= this.length()}, returns the style at the end of this paragraph. + */ + public S getStyleOfChar(int charIdx) { + return emptyTextStyle; + } + + /** + * Returns the style at the given position. That is the style of the + * character immediately preceding {@code position}. If {@code position} + * is 0, then the style of the first character (index 0) in this paragraph + * is returned. If this paragraph is empty, then some style previously used + * in this paragraph is returned. + * If {@code position > this.length()}, then it is equivalent to + * {@code position == this.length()}. + * + *

In other words, {@code getStyleAtPosition(p)} is equivalent to + * {@code getStyleOfChar(p-1)}. + */ + public S getStyleAtPosition(int position) { + return emptyTextStyle; + } + + /** + * Returns the range of homogeneous style that includes the given position. + * If {@code position} points to a boundary between two styled ranges, + * then the range preceding {@code position} is returned. + */ + public IndexRange getStyleRangeAtPosition(int position) { + return EMPTY_RANGE; + } + + public StyleSpans getStyleSpans() { + return new StyleSpansBuilder(1) + .add(emptyTextStyle, 0) + .create(); + } + + public StyleSpans getStyleSpans(int from, int to) { + return getStyleSpans(); + } + + /** + * Returns the string content of this paragraph (an empty string), + * excluding the line terminator. + */ + @Override + public String toString() { + return ""; + } + + @Override + public boolean equals(Object other) { + if (other instanceof EmptyParagraph) { + EmptyParagraph that = (EmptyParagraph) other; + return Objects.equals(this.paragraphStyle, that.paragraphStyle); + } else { + return false; + } + } +} diff --git a/richtextfx/src/main/java/org/fxmisc/richtext/Paragraph.java b/richtextfx/src/main/java/org/fxmisc/richtext/Paragraph.java new file mode 100644 index 000000000..7e3067781 --- /dev/null +++ b/richtextfx/src/main/java/org/fxmisc/richtext/Paragraph.java @@ -0,0 +1,70 @@ +package org.fxmisc.richtext; + +import javafx.scene.control.IndexRange; + +import java.util.List; + +public interface Paragraph extends CharSequence { + + public List> getSegments(); + + public PS getParagraphStyle(); + + public String substring(int from, int to); + + public String substring(int from); + + public Paragraph concat(Paragraph p); + + public Paragraph concat(CharSequence str); + + public Paragraph insert(int offset, CharSequence str); + + public Paragraph trim(int length); + + public Paragraph subSequence(int start); + + public Paragraph subSequence(int start, int end); + + public Paragraph delete(int start, int end); + + public Paragraph restyle(S style); + + public Paragraph restyle(int from, int to, S style); + + public Paragraph restyle(int from, StyleSpans styleSpans); + + public Paragraph setParagraphStyle(PS paragraphStyle); + + /** + * Returns the style of character with the given index. + * If {@code charIdx < 0}, returns the style at the beginning of this paragraph. + * If {@code charIdx >= this.length()}, returns the style at the end of this paragraph. + */ + public S getStyleOfChar(int charIdx); + + /** + * Returns the style at the given position. That is the style of the + * character immediately preceding {@code position}. If {@code position} + * is 0, then the style of the first character (index 0) in this paragraph + * is returned. If this paragraph is empty, then some style previously used + * in this paragraph is returned. + * If {@code position > this.length()}, then it is equivalent to + * {@code position == this.length()}. + * + *

In other words, {@code getStyleAtPosition(p)} is equivalent to + * {@code getStyleOfChar(p-1)}. + */ + public S getStyleAtPosition(int position); + + /** + * Returns the range of homogeneous style that includes the given position. + * If {@code position} points to a boundary between two styled ranges, + * then the range preceding {@code position} is returned. + */ + public IndexRange getStyleRangeAtPosition(int position); + + public StyleSpans getStyleSpans(); + + public StyleSpans getStyleSpans(int from, int to); +} From ebe04acbeb7f42c1e5e0146d2ed9751c9e9265fd Mon Sep 17 00:00:00 2001 From: JordanMartinez Date: Thu, 14 Jan 2016 16:24:22 -0800 Subject: [PATCH 3/6] Partial Commit: Made NormalParagraph implement Paragraph interface --- .../org/fxmisc/richtext/NormalParagraph.java | 44 +++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/richtextfx/src/main/java/org/fxmisc/richtext/NormalParagraph.java b/richtextfx/src/main/java/org/fxmisc/richtext/NormalParagraph.java index dbc27e236..0e341c409 100644 --- a/richtextfx/src/main/java/org/fxmisc/richtext/NormalParagraph.java +++ b/richtextfx/src/main/java/org/fxmisc/richtext/NormalParagraph.java @@ -11,7 +11,7 @@ import org.fxmisc.richtext.TwoDimensional.Position; -public final class NormalParagraph implements CharSequence { +public final class NormalParagraph implements Paragraph { @SafeVarargs private static List list(T head, T... tail) { @@ -77,7 +77,7 @@ public String substring(int from) { return toString().substring(from); } - public NormalParagraph concat(NormalParagraph p) { + public Paragraph concat(Paragraph p) { if(length() == 0) { return p; } @@ -87,23 +87,23 @@ public NormalParagraph concat(NormalParagraph p) { } StyledText left = segments.get(segments.size() - 1); - StyledText right = p.segments.get(0); + StyledText right = p.getSegments().get(0); if(Objects.equals(left.getStyle(), right.getStyle())) { StyledText segment = left.concat(right); - List> segs = new ArrayList<>(segments.size() + p.segments.size() - 1); + List> segs = new ArrayList<>(segments.size() + p.getSegments().size() - 1); segs.addAll(segments.subList(0, segments.size()-1)); segs.add(segment); - segs.addAll(p.segments.subList(1, p.segments.size())); + segs.addAll(p.getSegments().subList(1, p.getSegments().size())); return new NormalParagraph<>(paragraphStyle, segs); } else { - List> segs = new ArrayList<>(segments.size() + p.segments.size()); + List> segs = new ArrayList<>(segments.size() + p.getSegments().size()); segs.addAll(segments); - segs.addAll(p.segments); + segs.addAll(p.getSegments()); return new NormalParagraph<>(paragraphStyle, segs); } } - public NormalParagraph concat(CharSequence str) { + public Paragraph concat(CharSequence str) { if(str.length() == 0) { return this; } @@ -114,7 +114,7 @@ public NormalParagraph concat(CharSequence str) { return new NormalParagraph<>(paragraphStyle, segs); } - public NormalParagraph insert(int offset, CharSequence str) { + public Paragraph insert(int offset, CharSequence str) { if(offset < 0 || offset > length()) { throw new IndexOutOfBoundsException(String.valueOf(offset)); } @@ -130,11 +130,11 @@ public NormalParagraph insert(int offset, CharSequence str) { } @Override - public NormalParagraph subSequence(int start, int end) { + public Paragraph subSequence(int start, int end) { return trim(end).subSequence(start); } - public NormalParagraph trim(int length) { + public Paragraph trim(int length) { if(length >= length()) { return this; } else { @@ -147,7 +147,7 @@ public NormalParagraph trim(int length) { } } - public NormalParagraph subSequence(int start) { + public Paragraph subSequence(int start) { if(start < 0) { throw new IllegalArgumentException("start must not be negative (was: " + start + ")"); } else if(start == 0) { @@ -164,34 +164,34 @@ public NormalParagraph subSequence(int start) { } } - public NormalParagraph delete(int start, int end) { + public Paragraph delete(int start, int end) { return trim(start).concat(subSequence(end)); } - public NormalParagraph restyle(S style) { + public Paragraph restyle(S style) { return new NormalParagraph<>(paragraphStyle, toString(), style); } - public NormalParagraph restyle(int from, int to, S style) { + public Paragraph restyle(int from, int to, S style) { if(from >= length()) { return this; } else { to = Math.min(to, length()); - NormalParagraph left = subSequence(0, from); - NormalParagraph middle = new NormalParagraph<>(paragraphStyle, substring(from, to), style); - NormalParagraph right = subSequence(to); + Paragraph left = subSequence(0, from); + Paragraph middle = new NormalParagraph<>(paragraphStyle, substring(from, to), style); + Paragraph right = subSequence(to); return left.concat(middle).concat(right); } } - public NormalParagraph restyle(int from, StyleSpans styleSpans) { + public Paragraph restyle(int from, StyleSpans styleSpans) { int len = styleSpans.length(); if(styleSpans.equals(getStyleSpans(from, from + len))) { return this; } - NormalParagraph left = trim(from); - NormalParagraph right = subSequence(from + len); + Paragraph left = trim(from); + Paragraph right = subSequence(from + len); String middleString = substring(from, from + len); List> middleSegs = new ArrayList<>(styleSpans.getSpanCount()); @@ -207,7 +207,7 @@ public NormalParagraph restyle(int from, StyleSpans styleSpa return left.concat(middle).concat(right); } - public NormalParagraph setParagraphStyle(PS paragraphStyle) { + public Paragraph setParagraphStyle(PS paragraphStyle) { return new NormalParagraph<>(paragraphStyle, segments); } From 6d0894a64f185bb051614f9b26d8f1808b3c43e1 Mon Sep 17 00:00:00 2001 From: JordanMartinez Date: Thu, 14 Jan 2016 17:15:52 -0800 Subject: [PATCH 4/6] Partial Commit: Made StyledDoc-related classes switch from NormalParagraph to Paragraph. EditableStyledDocument details - Constructor now initializes itself with an EmptyParagraph - Replace method checks for NormalParagraphs that should be EmptyParagraphs because their length == 0 - getStyleForInsertionAt(Position) will return `initialStyle` if that boolean property is true or if the Paragraph returned is EmptyParagraph ReadOnlyStyledDocument details - The following were adjusted to account for saving/loading an EmptyParagraph or NormalParagraph: - fromString() method - Codecs --- .../richtext/EditableStyledDocument.java | 74 ++++++++++--------- .../richtext/ReadOnlyStyledDocument.java | 42 +++++++---- .../org/fxmisc/richtext/StyledDocument.java | 2 +- .../fxmisc/richtext/StyledDocumentBase.java | 28 +++---- 4 files changed, 84 insertions(+), 62 deletions(-) diff --git a/richtextfx/src/main/java/org/fxmisc/richtext/EditableStyledDocument.java b/richtextfx/src/main/java/org/fxmisc/richtext/EditableStyledDocument.java index 17fc6ea0c..1bbdcc1be 100644 --- a/richtextfx/src/main/java/org/fxmisc/richtext/EditableStyledDocument.java +++ b/richtextfx/src/main/java/org/fxmisc/richtext/EditableStyledDocument.java @@ -32,7 +32,7 @@ * on styled text, but not worrying about additional aspects such as * caret or selection. */ -final class EditableStyledDocument extends StyledDocumentBase>> { +final class EditableStyledDocument extends StyledDocumentBase>> { /* ********************************************************************** * * * @@ -65,7 +65,7 @@ final class EditableStyledDocument extends StyledDocumentBase> getParagraphs() { + public ObservableList> getParagraphs() { return FXCollections.unmodifiableObservableList(paragraphs); } @@ -163,7 +163,7 @@ public ReadOnlyStyledDocument snapshot() { @SuppressWarnings("unchecked") EditableStyledDocument(S initialStyle, PS initialParagraphStyle) { - super(FXCollections.observableArrayList(new NormalParagraph<>(initialParagraphStyle, "", initialStyle))); + super(FXCollections.observableArrayList(new EmptyParagraph<>(initialParagraphStyle, initialStyle))); this.initialStyle = initialStyle; this.initialParagraphStyle = initialParagraphStyle; } @@ -197,18 +197,24 @@ public void replace(int start, int end, StyledDocument replacement) { int lastParIdx = end2D.getMajor(); int lastParTo = end2D.getMinor(); - // Get the leftovers after cutting out the deletion - NormalParagraph firstPar = paragraphs.get(firstParIdx).trim(firstParFrom); - NormalParagraph lastPar = paragraphs.get(lastParIdx).subSequence(lastParTo); + Paragraph firstParCheck = paragraphs.get(firstParIdx); + Paragraph firstPar = firstParFrom == 0 + // If firstParFrom is 0, then the trimmed NormalParagraph's length == 0 + ? new EmptyParagraph<>(initialParagraphStyle, initialStyle) + // Get the leftovers after cutting out the deletion + : firstParCheck.trim(firstParFrom); - List> replacementPars = replacement.getParagraphs(); + Paragraph lastPar = paragraphs.get(lastParIdx).subSequence(lastParTo); + if (lastPar.length() == 0) lastPar = new EmptyParagraph<>(initialParagraphStyle, initialStyle); - List> newPars = join(firstPar, replacementPars, lastPar); + List> replacementPars = replacement.getParagraphs(); + + List> newPars = join(firstPar, replacementPars, lastPar); setAll(firstParIdx, lastParIdx + 1, newPars); // update length, invalidate text int replacementLength = - replacementPars.stream().mapToInt(NormalParagraph::length).sum() + + replacementPars.stream().mapToInt(Paragraph::length).sum() + replacementPars.size() - 1; int newLength = length.getValue() - (end - start) + replacementLength; length.suspendWhile(() -> { // don't publish length change until text is invalidated @@ -239,22 +245,22 @@ public void setStyle(int from, int to, S style) { int lastParTo = end.getMinor(); if(firstParIdx == lastParIdx) { - NormalParagraph p = paragraphs.get(firstParIdx); + Paragraph p = paragraphs.get(firstParIdx); p = p.restyle(firstParFrom, lastParTo, style); paragraphs.set(firstParIdx, p); } else { int affectedPars = lastParIdx - firstParIdx + 1; - List> restyledPars = new ArrayList<>(affectedPars); + List> restyledPars = new ArrayList<>(affectedPars); - NormalParagraph firstPar = paragraphs.get(firstParIdx); + Paragraph firstPar = paragraphs.get(firstParIdx); restyledPars.add(firstPar.restyle(firstParFrom, firstPar.length(), style)); for(int i = firstParIdx + 1; i < lastParIdx; ++i) { - NormalParagraph p = paragraphs.get(i); + Paragraph p = paragraphs.get(i); restyledPars.add(p.restyle(style)); } - NormalParagraph lastPar = paragraphs.get(lastParIdx); + Paragraph lastPar = paragraphs.get(lastParIdx); restyledPars.add(lastPar.restyle(0, lastParTo, style)); setAll(firstParIdx, lastParIdx + 1, restyledPars); @@ -263,7 +269,7 @@ public void setStyle(int from, int to, S style) { } public void setStyle(int paragraph, S style) { - NormalParagraph p = paragraphs.get(paragraph); + Paragraph p = paragraphs.get(paragraph); int start = position(paragraph, 0).toOffset(); int end = start + p.length(); @@ -280,7 +286,7 @@ public void setStyle(int paragraph, int fromCol, int toCol, S style) { int end = parOffset + toCol; try(Guard commitOnClose = beginStyleChange(start, end)) { - NormalParagraph p = paragraphs.get(paragraph); + Paragraph p = paragraphs.get(paragraph); p = p.restyle(fromCol, toCol, style); paragraphs.set(paragraph, p); } @@ -311,23 +317,23 @@ public void setStyleSpans(int from, StyleSpans styleSpans) { int lastParTo = end.getMinor(); if(firstParIdx == lastParIdx) { - NormalParagraph p = paragraphs.get(firstParIdx); - NormalParagraph q = p.restyle(firstParFrom, styleSpans); + Paragraph p = paragraphs.get(firstParIdx); + Paragraph q = p.restyle(firstParFrom, styleSpans); if(q != p) { paragraphs.set(firstParIdx, q); } } else { - NormalParagraph firstPar = paragraphs.get(firstParIdx); + Paragraph firstPar = paragraphs.get(firstParIdx); Position spansFrom = styleSpans.position(0, 0); Position spansTo = spansFrom.offsetBy(firstPar.length() - firstParFrom, Backward); - NormalParagraph q = firstPar.restyle(firstParFrom, styleSpans.subView(spansFrom, spansTo)); + Paragraph q = firstPar.restyle(firstParFrom, styleSpans.subView(spansFrom, spansTo)); if(q != firstPar) { paragraphs.set(firstParIdx, q); } spansFrom = spansTo.offsetBy(1, Forward); // skip the newline for(int i = firstParIdx + 1; i < lastParIdx; ++i) { - NormalParagraph par = paragraphs.get(i); + Paragraph par = paragraphs.get(i); spansTo = spansFrom.offsetBy(par.length(), Backward); q = par.restyle(0, styleSpans.subView(spansFrom, spansTo)); if(q != par) { @@ -336,7 +342,7 @@ public void setStyleSpans(int from, StyleSpans styleSpans) { spansFrom = spansTo.offsetBy(1, Forward); // skip the newline } - NormalParagraph lastPar = paragraphs.get(lastParIdx); + Paragraph lastPar = paragraphs.get(lastParIdx); spansTo = spansFrom.offsetBy(lastParTo, Backward); q = lastPar.restyle(0, styleSpans.subView(spansFrom, spansTo)); if(q != lastPar) { @@ -354,8 +360,8 @@ public void setStyleSpans(int paragraph, int from, StyleSpans style int end = start + len; try(Guard commitOnClose = beginStyleChange(start, end)) { - NormalParagraph p = paragraphs.get(paragraph); - NormalParagraph q = p.restyle(from, styleSpans); + Paragraph p = paragraphs.get(paragraph); + Paragraph q = p.restyle(from, styleSpans); if(q != p) { paragraphs.set(paragraph, q); } @@ -364,13 +370,13 @@ public void setStyleSpans(int paragraph, int from, StyleSpans style public void setParagraphStyle(int parIdx, PS style) { ensureValidParagraphIndex(parIdx); - NormalParagraph par = paragraphs.get(parIdx); + Paragraph par = paragraphs.get(parIdx); int len = par.length(); int start = position(parIdx, 0).toOffset(); int end = start + len; try(Guard commitOnClose = beginStyleChange(start, end)) { - NormalParagraph q = par.setParagraphStyle(style); + Paragraph q = par.setParagraphStyle(style); paragraphs.set(parIdx, q); } } @@ -405,7 +411,7 @@ private int fullLength(int par) { } private int terminatorLengthToSkip(Position pos) { - NormalParagraph par = paragraphs.get(pos.getMajor()); + Paragraph par = paragraphs.get(pos.getMajor()); int skipSum = 0; while(pos.getMinor() == par.length() && pos.getMajor() < paragraphs.size() - 1) { skipSum += 1; @@ -433,14 +439,14 @@ private Guard beginStyleChange(int start, int end) { return () -> styleChangeDone.push(null); } - private List> join(NormalParagraph first, List> middle, NormalParagraph last) { + private List> join(Paragraph first, List> middle, Paragraph last) { int m = middle.size(); if(m == 0) { return Arrays.asList(first.concat(last)); } else if(m == 1) { return Arrays.asList(first.concat(middle.get(0)).concat(last)); } else { - List> res = new ArrayList<>(middle.size()); + List> res = new ArrayList<>(middle.size()); res.add(first.concat(middle.get(0))); res.addAll(middle.subList(1, m - 1)); res.add(middle.get(m-1).concat(last)); @@ -450,7 +456,7 @@ private List> join(NormalParagraph first, List> pars) { + private void setAll(int startIdx, int endIdx, Collection> pars) { if(startIdx > 0 || endIdx < paragraphs.size()) { paragraphs.subList(startIdx, endIdx).clear(); // note that paragraphs remains non-empty at all times paragraphs.addAll(startIdx, pars); @@ -467,8 +473,10 @@ S getStyleForInsertionAt(Position insertionPos) { if(useInitialStyleForInsertion.get()) { return initialStyle; } else { - NormalParagraph par = paragraphs.get(insertionPos.getMajor()); - return par.getStyleAtPosition(insertionPos.getMinor()); + Paragraph par = paragraphs.get(insertionPos.getMajor()); + return par instanceof EmptyParagraph + ? initialStyle + : par.getStyleAtPosition(insertionPos.getMinor()); } } @@ -480,7 +488,7 @@ PS getParagraphStyleForInsertionAt(Position insertionPos) { if(useInitialStyleForInsertion.get()) { return initialParagraphStyle; } else { - NormalParagraph par = paragraphs.get(insertionPos.getMajor()); + Paragraph par = paragraphs.get(insertionPos.getMajor()); return par.getParagraphStyle(); } } diff --git a/richtextfx/src/main/java/org/fxmisc/richtext/ReadOnlyStyledDocument.java b/richtextfx/src/main/java/org/fxmisc/richtext/ReadOnlyStyledDocument.java index cc7e5b6bb..bb84e0bc1 100644 --- a/richtextfx/src/main/java/org/fxmisc/richtext/ReadOnlyStyledDocument.java +++ b/richtextfx/src/main/java/org/fxmisc/richtext/ReadOnlyStyledDocument.java @@ -11,7 +11,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -public class ReadOnlyStyledDocument extends StyledDocumentBase>> { +public class ReadOnlyStyledDocument extends StyledDocumentBase>> { private static final Pattern LINE_TERMINATOR = Pattern.compile("\r\n|\r|\n"); @@ -20,17 +20,23 @@ public static ReadOnlyStyledDocument fromString(String str, S sty int n = 1; while(m.find()) ++n; - List> res = new ArrayList<>(n); + List> res = new ArrayList<>(n); int start = 0; m.reset(); while(m.find()) { String s = str.substring(start, m.start()); - res.add(new NormalParagraph<>(paragraphStyle, s, style)); + res.add(s.isEmpty() + ? new EmptyParagraph<>(paragraphStyle, style) + : new NormalParagraph<>(paragraphStyle, s, style) + ); start = m.end(); } String last = str.substring(start); - res.add(new NormalParagraph<>(paragraphStyle, last, style)); + res.add(last.isEmpty() + ? new EmptyParagraph<>(paragraphStyle, style) + : new NormalParagraph<>(paragraphStyle, last, style) + ); return new ReadOnlyStyledDocument<>(res, ADOPT); } @@ -42,7 +48,7 @@ enum ParagraphsPolicy { static Codec> codec(Codec tCodec, Codec pCodec) { return new Codec>() { - private final Codec>> codec = Codec.listCodec(paragraphCodec(tCodec, pCodec)); + private final Codec>> codec = Codec.listCodec(paragraphCodec(tCodec, pCodec)); @Override public String getName() { @@ -64,8 +70,8 @@ public StyledDocument decode(DataInputStream is) throws IOException { }; } - private static Codec> paragraphCodec(Codec tCodec, Codec pCodec) { - return new Codec>() { + private static Codec> paragraphCodec(Codec tCodec, Codec pCodec) { + return new Codec>() { private final Codec>> segmentsCodec = Codec.listCodec(styledTextCodec(tCodec)); @Override @@ -74,16 +80,24 @@ public String getName() { } @Override - public void encode(DataOutputStream os, NormalParagraph p) throws IOException { + public void encode(DataOutputStream os, Paragraph p) throws IOException { pCodec.encode(os, p.getParagraphStyle()); - segmentsCodec.encode(os, p.getSegments()); + if (p instanceof EmptyParagraph) { + List> list = new ArrayList<>(1); + list.add(new StyledText("", p.getStyleAtPosition(0))); + segmentsCodec.encode(os, list); + } else { + segmentsCodec.encode(os, p.getSegments()); + } } @Override - public NormalParagraph decode(DataInputStream is) throws IOException { + public Paragraph decode(DataInputStream is) throws IOException { PS paragraphStyle = pCodec.decode(is); List> segments = segmentsCodec.decode(is); - return new NormalParagraph<>(paragraphStyle, segments); + return segments.get(0).length() == 0 + ? new EmptyParagraph<>(paragraphStyle, segments.get(0).getStyle()) + : new NormalParagraph<>(paragraphStyle, segments); } }; } @@ -117,7 +131,7 @@ public StyledText decode(DataInputStream is) throws IOException { private String text = null; - ReadOnlyStyledDocument(List> paragraphs, ParagraphsPolicy policy) { + ReadOnlyStyledDocument(List> paragraphs, ParagraphsPolicy policy) { super(policy == ParagraphsPolicy.ADOPT ? paragraphs : new ArrayList<>(paragraphs)); } @@ -138,11 +152,11 @@ public String getText() { } @Override - public List> getParagraphs() { + public List> getParagraphs() { return Collections.unmodifiableList(paragraphs); } private int computeLength() { - return paragraphs.stream().mapToInt(NormalParagraph::length).sum() + paragraphs.size() - 1; + return paragraphs.stream().mapToInt(Paragraph::length).sum() + paragraphs.size() - 1; } } diff --git a/richtextfx/src/main/java/org/fxmisc/richtext/StyledDocument.java b/richtextfx/src/main/java/org/fxmisc/richtext/StyledDocument.java index 036d73b57..ed9eeb6ed 100644 --- a/richtextfx/src/main/java/org/fxmisc/richtext/StyledDocument.java +++ b/richtextfx/src/main/java/org/fxmisc/richtext/StyledDocument.java @@ -29,5 +29,5 @@ public interface StyledDocument extends CharSequence, TwoDimensional { StyleSpans getStyleSpans(int paragraph); StyleSpans getStyleSpans(int paragraph, int from, int to); - List> getParagraphs(); + List> getParagraphs(); } diff --git a/richtextfx/src/main/java/org/fxmisc/richtext/StyledDocumentBase.java b/richtextfx/src/main/java/org/fxmisc/richtext/StyledDocumentBase.java index 387063550..737dd943d 100644 --- a/richtextfx/src/main/java/org/fxmisc/richtext/StyledDocumentBase.java +++ b/richtextfx/src/main/java/org/fxmisc/richtext/StyledDocumentBase.java @@ -11,7 +11,7 @@ import javafx.scene.control.IndexRange; -abstract class StyledDocumentBase>> +abstract class StyledDocumentBase>> implements StyledDocument { protected final L paragraphs; @@ -50,8 +50,8 @@ public String getText(IndexRange range) { public String getText(int start, int end) { return sub( start, end, - NormalParagraph::toString, - NormalParagraph::substring, + Paragraph::toString, + Paragraph::substring, pars -> String.join("\n", pars)); } @@ -77,7 +77,7 @@ public StyledDocument subSequence(int start, int end) { start, end, p -> p, (p, a, b) -> p.subSequence(a, b), - (List> pars) -> new ReadOnlyStyledDocument<>(pars, ADOPT)); + (List> pars) -> new ReadOnlyStyledDocument<>(pars, ADOPT)); } @Override @@ -87,11 +87,11 @@ public StyledDocument subDocument(int paragraphIndex) { @Override public final StyledDocument concat(StyledDocument that) { - List> pars1 = this.getParagraphs(); - List> pars2 = that.getParagraphs(); + List> pars1 = this.getParagraphs(); + List> pars2 = that.getParagraphs(); int n1 = pars1.size(); int n2 = pars2.size(); - List> pars = new ArrayList<>(n1 + n2 - 1); + List> pars = new ArrayList<>(n1 + n2 - 1); pars.addAll(pars1.subList(0, n1 - 1)); pars.add(pars1.get(n1 - 1).concat(pars2.get(0))); pars.addAll(pars2.subList(1, n2)); @@ -150,18 +150,18 @@ public StyleSpans getStyleSpans(int from, int to) { List> subSpans = new ArrayList<>(affectedPars); if(startParIdx == endParIdx) { - NormalParagraph par = paragraphs.get(startParIdx); + Paragraph par = paragraphs.get(startParIdx); subSpans.add(par.getStyleSpans(start.getMinor(), end.getMinor())); } else { - NormalParagraph startPar = paragraphs.get(startParIdx); + Paragraph startPar = paragraphs.get(startParIdx); subSpans.add(startPar.getStyleSpans(start.getMinor(), startPar.length() + 1)); for(int i = startParIdx + 1; i < endParIdx; ++i) { - NormalParagraph par = paragraphs.get(i); + Paragraph par = paragraphs.get(i); subSpans.add(par.getStyleSpans(0, par.length() + 1)); } - NormalParagraph endPar = paragraphs.get(endParIdx); + Paragraph endPar = paragraphs.get(endParIdx); subSpans.add(endPar.getStyleSpans(0, end.getMinor())); } @@ -226,8 +226,8 @@ private interface SubMap { */ private R sub( int start, int end, - Function, P> map, - SubMap, P> subMap, + Function, P> map, + SubMap, P> subMap, Function, R> combine) { Position start2D = navigator.offsetToPosition(start, Forward); @@ -244,7 +244,7 @@ private R sub( if(p1 == p2) { pars.add(subMap.subrange(paragraphs.get(p1), col1, col2)); } else { - NormalParagraph par1 = paragraphs.get(p1); + Paragraph par1 = paragraphs.get(p1); pars.add(subMap.subrange(par1, col1, par1.length())); for(int i = p1 + 1; i < p2; ++i) { From e8f812768bd804857e9902eb5285cf89a3107620 Mon Sep 17 00:00:00 2001 From: JordanMartinez Date: Thu, 14 Jan 2016 17:26:30 -0800 Subject: [PATCH 5/6] Final Commit: Made View-related classes (and RichText demo) switch from NormalParagraph to Paragraph ParagraphText details - When ParagraphText is displaying an EmptyParagraph, it will seem like the paragraph and the caret aren't visible. To fix this, an empty TextExt was added. There is probably a better way to make the line and caret appear. Additionally, the caret's height might not appear to be the same elsewhere in the area if the initialStyle used in EditableStyledDocument doesn't specify what the fontsize should be of the text. - There's probably now a way to show that a newline char is highlighted when user selects something by `new TextExt(" ")` rather than `new TextExt("")`. For example, when a user selects multiple lines and one of them is an EmptyParagraph, the TextExt could be used to show that that line is selected. As of now, there is no indication of this to the user. --- .../richtext/demo/richtext/RichText.java | 6 +-- .../org/fxmisc/richtext/ParagraphBox.java | 4 +- .../org/fxmisc/richtext/ParagraphText.java | 44 ++++++++++++++----- .../org/fxmisc/richtext/StyledTextArea.java | 28 ++++++------ .../org/fxmisc/richtext/TextEditingArea.java | 2 +- 5 files changed, 52 insertions(+), 32 deletions(-) diff --git a/richtextfx-demos/src/main/java/org/fxmisc/richtext/demo/richtext/RichText.java b/richtextfx-demos/src/main/java/org/fxmisc/richtext/demo/richtext/RichText.java index d88d76d2d..3cec92be8 100644 --- a/richtextfx-demos/src/main/java/org/fxmisc/richtext/demo/richtext/RichText.java +++ b/richtextfx-demos/src/main/java/org/fxmisc/richtext/demo/richtext/RichText.java @@ -35,7 +35,7 @@ import org.fxmisc.flowless.VirtualizedScrollPane; import org.fxmisc.richtext.AreaFactory; -import org.fxmisc.richtext.NormalParagraph; +import org.fxmisc.richtext.Paragraph; import org.fxmisc.richtext.StyleSpans; import org.fxmisc.richtext.StyledTextArea; import org.reactfx.SuspendableNo; @@ -150,7 +150,7 @@ protected boolean computeValue() { int startPar = area.offsetToPosition(selection.getStart(), Forward).getMajor(); int endPar = area.offsetToPosition(selection.getEnd(), Backward).getMajor(); - List> pars = area.getParagraphs().subList(startPar, endPar + 1); + List> pars = area.getParagraphs().subList(startPar, endPar + 1); @SuppressWarnings("unchecked") Optional[] alignments = pars.stream().map(p -> p.getParagraphStyle().alignment).distinct().toArray(Optional[]::new); @@ -331,7 +331,7 @@ private void updateParagraphStyleInSelection(Function update int startPar = area.offsetToPosition(selection.getStart(), Forward).getMajor(); int endPar = area.offsetToPosition(selection.getEnd(), Backward).getMajor(); for(int i = startPar; i <= endPar; ++i) { - NormalParagraph paragraph = area.getParagraph(i); + Paragraph paragraph = area.getParagraph(i); area.setParagraphStyle(i, updater.apply(paragraph.getParagraphStyle())); } } diff --git a/richtextfx/src/main/java/org/fxmisc/richtext/ParagraphBox.java b/richtextfx/src/main/java/org/fxmisc/richtext/ParagraphBox.java index f26bada8a..6e31a4395 100644 --- a/richtextfx/src/main/java/org/fxmisc/richtext/ParagraphBox.java +++ b/richtextfx/src/main/java/org/fxmisc/richtext/ParagraphBox.java @@ -69,7 +69,7 @@ public ObjectProperty> graphicFactoryProperty() { public void setIndex(int index) { this.index.setValue(index); } public int getIndex() { return index.getValue(); } - ParagraphBox(NormalParagraph par, BiConsumer applyStyle, BiConsumer applyParagraphStyle) { + ParagraphBox(Paragraph par, BiConsumer applyStyle, BiConsumer applyParagraphStyle) { this.getStyleClass().add("paragraph-box"); this.text = new ParagraphText<>(par, applyStyle); applyParagraphStyle.accept(this.text, par.getParagraphStyle()); @@ -107,7 +107,7 @@ public String toString() { public Property selectionProperty() { return text.selectionProperty(); } - NormalParagraph getParagraph() { + Paragraph getParagraph() { return text.getParagraph(); } diff --git a/richtextfx/src/main/java/org/fxmisc/richtext/ParagraphText.java b/richtextfx/src/main/java/org/fxmisc/richtext/ParagraphText.java index 53b560e36..2fafa4619 100644 --- a/richtextfx/src/main/java/org/fxmisc/richtext/ParagraphText.java +++ b/richtextfx/src/main/java/org/fxmisc/richtext/ParagraphText.java @@ -39,7 +39,7 @@ public ObjectProperty highlightTextFillProperty() { public ObjectProperty selectionProperty() { return selection; } public void setSelection(IndexRange sel) { selection.set(sel); } - private final NormalParagraph paragraph; + private final Paragraph paragraph; private final Path caretShape = new Path(); private final Path selectionShape = new Path(); @@ -53,7 +53,7 @@ public ObjectProperty highlightTextFillProperty() { caretShape.visibleProperty().bind(caretVisible); } - public ParagraphText(NormalParagraph par, BiConsumer applyStyle) { + public ParagraphText(Paragraph par, BiConsumer applyStyle) { this.paragraph = par; getStyleClass().add("paragraph-text"); @@ -93,17 +93,37 @@ public ParagraphText(NormalParagraph par, BiConsumer // } // }); - // populate with text nodes - for(StyledText segment: par.getSegments()) { - TextExt t = new TextExt(segment.toString()); + if (par instanceof NormalParagraph) { + // populate with text nodes + for (StyledText segment : par.getSegments()) { + TextExt t = new TextExt(segment.toString()); + t.setTextOrigin(VPos.TOP); + t.getStyleClass().add("text"); + applyStyle.accept(t, segment.getStyle()); + + // XXX: binding selectionFill to textFill, + // see the note at highlightTextFill + t.impl_selectionFillProperty().bind(t.fillProperty()); + + getChildren().add(t); + + // add corresponding background node (empty) + + Path backgroundShape = new Path(); + backgroundShape.setManaged(false); + backgroundShape.setStrokeWidth(0); + backgroundShape.layoutXProperty().bind(leftInset); + backgroundShape.layoutYProperty().bind(topInset); + backgroundShapes.add(backgroundShape); + getChildren().add(0, backgroundShape); + } + } else { + // insure that caret appears + // by insuring that this region takes up space + // by adding an empty TextExt + TextExt t = new TextExt(""); t.setTextOrigin(VPos.TOP); t.getStyleClass().add("text"); - applyStyle.accept(t, segment.getStyle()); - - // XXX: binding selectionFill to textFill, - // see the note at highlightTextFill - t.impl_selectionFillProperty().bind(t.fillProperty()); - getChildren().add(t); // add corresponding background node (empty) @@ -118,7 +138,7 @@ public ParagraphText(NormalParagraph par, BiConsumer } } - public NormalParagraph getParagraph() { + public Paragraph getParagraph() { return paragraph; } diff --git a/richtextfx/src/main/java/org/fxmisc/richtext/StyledTextArea.java b/richtextfx/src/main/java/org/fxmisc/richtext/StyledTextArea.java index 5d6be773e..3002b76e1 100644 --- a/richtextfx/src/main/java/org/fxmisc/richtext/StyledTextArea.java +++ b/richtextfx/src/main/java/org/fxmisc/richtext/StyledTextArea.java @@ -374,8 +374,8 @@ public Optional, Codec>> getStyleCodecs() { @Override public final ObservableValue caretColumnProperty() { return caretColumn; } // paragraphs - private final SuspendableList> paragraphs; - @Override public ObservableList> getParagraphs() { + private final SuspendableList> paragraphs; + @Override public ObservableList> getParagraphs() { return paragraphs; } @@ -434,7 +434,7 @@ public Optional, Codec>> getStyleCodecs() { private final Val> _popupAnchorAdjustment; - private final VirtualFlow, Cell, ParagraphBox>> virtualFlow; + private final VirtualFlow, Cell, ParagraphBox>> virtualFlow; // used for two-level navigation, where on the higher level are // paragraphs and on the lower level are lines within a paragraph @@ -679,7 +679,7 @@ public StyledTextArea(S initialStyle, BiConsumer applyStyle, virtualFlow = VirtualFlow.createVertical( getParagraphs(), par -> { - Cell, ParagraphBox> cell = createCell( + Cell, ParagraphBox> cell = createCell( par, applyStyle, initialParagraphStyle, @@ -780,7 +780,7 @@ CharacterHit hit(ParagraphBox.CaretOffsetX x, TwoDimensional.Position targetLine } CharacterHit hit(ParagraphBox.CaretOffsetX x, double y) { - VirtualFlowHit, ParagraphBox>> hit = virtualFlow.hit(0.0, y); + VirtualFlowHit, ParagraphBox>> hit = virtualFlow.hit(0.0, y); if(hit.isBeforeCells()) { return CharacterHit.insertionAt(0); } else if(hit.isAfterCells()) { @@ -812,7 +812,7 @@ CharacterHit hit(ParagraphBox.CaretOffsetX x, double y) { * @param y */ public CharacterHit hit(double x, double y) { - VirtualFlowHit, ParagraphBox>> hit = virtualFlow.hit(x, y); + VirtualFlowHit, ParagraphBox>> hit = virtualFlow.hit(x, y); if(hit.isBeforeCells()) { return CharacterHit.insertionAt(0); } else if(hit.isAfterCells()) { @@ -837,7 +837,7 @@ public CharacterHit hit(double x, double y) { */ TwoDimensional.Position currentLine() { int parIdx = getCurrentParagraph(); - Cell, ParagraphBox> cell = virtualFlow.getCell(parIdx); + Cell, ParagraphBox> cell = virtualFlow.getCell(parIdx); int lineIdx = cell.getNode().getCurrentLineIndex(); return _position(parIdx, lineIdx); } @@ -856,7 +856,7 @@ public String getText(int paragraph) { return paragraphs.get(paragraph).toString(); } - public NormalParagraph getParagraph(int index) { + public Paragraph getParagraph(int index) { return paragraphs.get(index); } @@ -1019,7 +1019,7 @@ void show(double y) { void showCaretAtBottom() { int parIdx = getCurrentParagraph(); - Cell, ParagraphBox> cell = virtualFlow.getCell(parIdx); + Cell, ParagraphBox> cell = virtualFlow.getCell(parIdx); Bounds caretBounds = cell.getNode().getCaretBounds(); double y = caretBounds.getMaxY(); virtualFlow.showAtOffset(parIdx, getViewportHeight() - y); @@ -1027,7 +1027,7 @@ void showCaretAtBottom() { void showCaretAtTop() { int parIdx = getCurrentParagraph(); - Cell, ParagraphBox> cell = virtualFlow.getCell(parIdx); + Cell, ParagraphBox> cell = virtualFlow.getCell(parIdx); Bounds caretBounds = cell.getNode().getCaretBounds(); double y = caretBounds.getMinY(); virtualFlow.showAtOffset(parIdx, -y); @@ -1040,7 +1040,7 @@ void requestFollowCaret() { private void followCaret() { int parIdx = getCurrentParagraph(); - Cell, ParagraphBox> cell = virtualFlow.getCell(parIdx); + Cell, ParagraphBox> cell = virtualFlow.getCell(parIdx); Bounds caretBounds = cell.getNode().getCaretBounds(); double graphicWidth = cell.getNode().getGraphicPrefWidth(); Bounds region = extendLeft(caretBounds, graphicWidth); @@ -1224,8 +1224,8 @@ protected void layoutChildren() { * * * ********************************************************************** */ - private Cell, ParagraphBox> createCell( - NormalParagraph paragraph, + private Cell, ParagraphBox> createCell( + Paragraph paragraph, BiConsumer applyStyle, PS initialParagraphStyle, BiConsumer applyParagraphStyle) { @@ -1262,7 +1262,7 @@ private Cell, ParagraphBox> createCell( }, selectionProperty(), box.indexProperty()); box.selectionProperty().bind(cellSelection); - return new Cell, ParagraphBox>() { + return new Cell, ParagraphBox>() { @Override public ParagraphBox getNode() { return box; diff --git a/richtextfx/src/main/java/org/fxmisc/richtext/TextEditingArea.java b/richtextfx/src/main/java/org/fxmisc/richtext/TextEditingArea.java index 3569011ad..6bc865ea3 100644 --- a/richtextfx/src/main/java/org/fxmisc/richtext/TextEditingArea.java +++ b/richtextfx/src/main/java/org/fxmisc/richtext/TextEditingArea.java @@ -91,7 +91,7 @@ public interface TextEditingArea { /** * Unmodifiable observable list of paragraphs in this text area. */ - ObservableList> getParagraphs(); + ObservableList> getParagraphs(); /********************* From 4d86628b96ad7dc95bf012f79d23ea0a25dca027 Mon Sep 17 00:00:00 2001 From: JordanMartinez Date: Thu, 14 Jan 2016 21:09:53 -0800 Subject: [PATCH 6/6] Moved `SubMap` and its implementation into `EditableStyledDocument` so that `StyledDocument`s that are used to initialize a new `RichTextChange` don't have any `NormalParagraph` instances in their respective paragraphs when those instances length is 0. Instead, remaps the paragraphs to `EmptyParagraph` objects using `EditableStyledDocument`'s `initialStyle` and `initialParagraphStyle`. --- .../fxmisc/richtext/EditableStyledDocument.java | 14 ++++++++++++++ .../org/fxmisc/richtext/RichTextChange.java | 17 +++++++++++++++++ .../org/fxmisc/richtext/StyledDocumentBase.java | 6 +++--- 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/richtextfx/src/main/java/org/fxmisc/richtext/EditableStyledDocument.java b/richtextfx/src/main/java/org/fxmisc/richtext/EditableStyledDocument.java index 1bbdcc1be..287571398 100644 --- a/richtextfx/src/main/java/org/fxmisc/richtext/EditableStyledDocument.java +++ b/richtextfx/src/main/java/org/fxmisc/richtext/EditableStyledDocument.java @@ -492,4 +492,18 @@ PS getParagraphStyleForInsertionAt(Position insertionPos) { return par.getParagraphStyle(); } } + + @Override + public StyledDocument subSequence(int start, int end) { + return sub( + start, end, + p -> p, + (p, a, b) -> { + Paragraph unknownPar = p.subSequence(a, b); + return unknownPar.length() == 0 + ? new EmptyParagraph(initialParagraphStyle, initialStyle) + : unknownPar; + }, + (List> pars) -> new ReadOnlyStyledDocument<>(pars, ADOPT)); + } } diff --git a/richtextfx/src/main/java/org/fxmisc/richtext/RichTextChange.java b/richtextfx/src/main/java/org/fxmisc/richtext/RichTextChange.java index abf0f2754..60ef641be 100644 --- a/richtextfx/src/main/java/org/fxmisc/richtext/RichTextChange.java +++ b/richtextfx/src/main/java/org/fxmisc/richtext/RichTextChange.java @@ -4,6 +4,12 @@ public class RichTextChange extends TextChange, Ric public RichTextChange(int position, StyledDocument removed, StyledDocument inserted) { super(position, removed, inserted); + System.out.println("\n"); + System.out.println(System.nanoTime()); + System.out.println("Checking removed doc"); + checkDocPars(removed); + System.out.println("Checking inserted doc"); + checkDocPars(inserted); } @Override @@ -20,4 +26,15 @@ protected final StyledDocument sub(StyledDocument doc, int from, i protected final RichTextChange create(int position, StyledDocument removed, StyledDocument inserted) { return new RichTextChange<>(position, removed, inserted); } + + private void checkDocPars(StyledDocument doc) { + doc.getParagraphs().stream().forEach(x -> { + boolean shouldBeEmptyPar = x.length() == 0; + if (shouldBeEmptyPar) { + if (x.getClass().getSimpleName().equals("NormalParagraph")) { + throw new IllegalStateException("An Empty Paragraph cannot be a NormalParagraph"); + } + } + }); + } } diff --git a/richtextfx/src/main/java/org/fxmisc/richtext/StyledDocumentBase.java b/richtextfx/src/main/java/org/fxmisc/richtext/StyledDocumentBase.java index 737dd943d..5b37965f7 100644 --- a/richtextfx/src/main/java/org/fxmisc/richtext/StyledDocumentBase.java +++ b/richtextfx/src/main/java/org/fxmisc/richtext/StyledDocumentBase.java @@ -204,11 +204,11 @@ public final int hashCode() { /************************************************************************** * * - * Private methods * + * Package-Private methods * * * **************************************************************************/ - private interface SubMap { + interface SubMap { B subrange(A par, int start, int end); } @@ -224,7 +224,7 @@ private interface SubMap { * @param

type to which paragraphs are mapped. * @param type of the resulting sub-document. */ - private R sub( + final R sub( int start, int end, Function, P> map, SubMap, P> subMap,