Skip to content

Commit c73aacb

Browse files
Merge pull request #529 from JordanMartinez/refactorCode
Reposition code and refactor / add javadoc to #526 & #528
2 parents ce3bf9b + ce27fd3 commit c73aacb

5 files changed

Lines changed: 139 additions & 76 deletions

File tree

richtextfx/src/main/java/org/fxmisc/richtext/BoundedSelection.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@
4444
* then just write the much simpler {@code BoundedSelection<?, ?, ?> selection}</b>.
4545
* </p>
4646
*
47+
* @see Caret
48+
* @see UnboundedSelection
49+
*
4750
* @param <PS> type for {@link StyledDocument}'s paragraph style; only necessary when using the "selectedDocument"
4851
* getter or property
4952
* @param <SEG> type for {@link StyledDocument}'s segment type; only necessary when using the "selectedDocument"

richtextfx/src/main/java/org/fxmisc/richtext/BoundedSelectionImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
import java.util.Optional;
1818

19-
public class BoundedSelectionImpl<PS, SEG, S> implements BoundedSelection<PS, SEG, S> {
19+
final class BoundedSelectionImpl<PS, SEG, S> implements BoundedSelection<PS, SEG, S> {
2020

2121
private final UnboundedSelection<PS, SEG, S> delegate;
2222
@Override public ObservableValue<IndexRange> rangeProperty() { return delegate.rangeProperty(); }

richtextfx/src/main/java/org/fxmisc/richtext/GenericStyledArea.java

Lines changed: 75 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -315,52 +315,6 @@ private static int clamp(int min, int val, int max) {
315315
@Override public Duration getMouseOverTextDelay() { return mouseOverTextDelay.get(); }
316316
@Override public ObjectProperty<Duration> mouseOverTextDelayProperty() { return mouseOverTextDelay; }
317317

318-
private final BooleanProperty autoScrollOnDragDesired = new SimpleBooleanProperty(true);
319-
public final void setAutoScrollOnDragDesired(boolean val) { autoScrollOnDragDesired.set(val); }
320-
public final boolean isAutoScrollOnDragDesired() { return autoScrollOnDragDesired.get(); }
321-
322-
private final Property<Consumer<MouseEvent>> onOutsideSelectionMousePress = new SimpleObjectProperty<>(e -> {
323-
CharacterHit hit = hit(e.getX(), e.getY());
324-
moveTo(hit.getInsertionIndex(), SelectionPolicy.CLEAR);
325-
});
326-
public final void setOnOutsideSelectionMousePress(Consumer<MouseEvent> consumer) { onOutsideSelectionMousePress.setValue(consumer); }
327-
public final Consumer<MouseEvent> getOnOutsideSelectionMousePress() { return onOutsideSelectionMousePress.getValue(); }
328-
329-
private final Property<Consumer<MouseEvent>> onInsideSelectionMousePressRelease = new SimpleObjectProperty<>(e -> {
330-
CharacterHit hit = hit(e.getX(), e.getY());
331-
moveTo(hit.getInsertionIndex(), SelectionPolicy.CLEAR);
332-
});
333-
public final void setOnInsideSelectionMousePressRelease(Consumer<MouseEvent> consumer) { onInsideSelectionMousePressRelease.setValue(consumer); }
334-
public final Consumer<MouseEvent> getOnInsideSelectionMousePressRelease() { return onInsideSelectionMousePressRelease.getValue(); }
335-
336-
private final Property<Consumer<Point2D>> onNewSelectionDrag = new SimpleObjectProperty<>(p -> {
337-
CharacterHit hit = hit(p.getX(), p.getY());
338-
moveTo(hit.getInsertionIndex(), SelectionPolicy.ADJUST);
339-
});
340-
public final void setOnNewSelectionDrag(Consumer<Point2D> consumer) { onNewSelectionDrag.setValue(consumer); }
341-
public final Consumer<Point2D> getOnNewSelectionDrag() { return onNewSelectionDrag.getValue(); }
342-
343-
private final Property<Consumer<MouseEvent>> onNewSelectionDragEnd = new SimpleObjectProperty<>(e -> {
344-
CharacterHit hit = hit(e.getX(), e.getY());
345-
moveTo(hit.getInsertionIndex(), SelectionPolicy.ADJUST);
346-
});
347-
public final void setOnNewSelectionDragEnd(Consumer<MouseEvent> consumer) { onNewSelectionDragEnd.setValue(consumer); }
348-
public final Consumer<MouseEvent> getOnNewSelectionDragEnd() { return onNewSelectionDragEnd.getValue(); }
349-
350-
private final Property<Consumer<Point2D>> onSelectionDrag = new SimpleObjectProperty<>(p -> {
351-
CharacterHit hit = hit(p.getX(), p.getY());
352-
displaceCaret(hit.getInsertionIndex());
353-
});
354-
public final void setOnSelectionDrag(Consumer<Point2D> consumer) { onSelectionDrag.setValue(consumer); }
355-
public final Consumer<Point2D> getOnSelectionDrag() { return onSelectionDrag.getValue(); }
356-
357-
private final Property<Consumer<MouseEvent>> onSelectionDrop = new SimpleObjectProperty<>(e -> {
358-
CharacterHit hit = hit(e.getX(), e.getY());
359-
moveSelectedText(hit.getInsertionIndex());
360-
});
361-
@Override public final void setOnSelectionDrop(Consumer<MouseEvent> consumer) { onSelectionDrop.setValue(consumer); }
362-
@Override public final Consumer<MouseEvent> getOnSelectionDrop() { return onSelectionDrop.getValue(); }
363-
364318
private final ObjectProperty<IntFunction<? extends Node>> paragraphGraphicFactory = new SimpleObjectProperty<>(null);
365319
@Override
366320
public void setParagraphGraphicFactory(IntFunction<? extends Node> factory) { paragraphGraphicFactory.set(factory); }
@@ -415,6 +369,60 @@ public Optional<Tuple2<Codec<PS>, Codec<SEG>>> getStyleCodecs() {
415369
@Override
416370
public void setEstimatedScrollY(double value) { virtualFlow.estimatedScrollYProperty().setValue(value); }
417371

372+
/* ********************************************************************** *
373+
* *
374+
* Mouse Behavior Hooks *
375+
* *
376+
* Hooks for overriding some of the default mouse behavior *
377+
* *
378+
* ********************************************************************** */
379+
380+
private final Property<Consumer<MouseEvent>> onOutsideSelectionMousePress = new SimpleObjectProperty<>(e -> {
381+
CharacterHit hit = hit(e.getX(), e.getY());
382+
moveTo(hit.getInsertionIndex(), SelectionPolicy.CLEAR);
383+
});
384+
public final void setOnOutsideSelectionMousePress(Consumer<MouseEvent> consumer) { onOutsideSelectionMousePress.setValue(consumer); }
385+
public final Consumer<MouseEvent> getOnOutsideSelectionMousePress() { return onOutsideSelectionMousePress.getValue(); }
386+
387+
private final Property<Consumer<MouseEvent>> onInsideSelectionMousePressRelease = new SimpleObjectProperty<>(e -> {
388+
CharacterHit hit = hit(e.getX(), e.getY());
389+
moveTo(hit.getInsertionIndex(), SelectionPolicy.CLEAR);
390+
});
391+
public final void setOnInsideSelectionMousePressRelease(Consumer<MouseEvent> consumer) { onInsideSelectionMousePressRelease.setValue(consumer); }
392+
public final Consumer<MouseEvent> getOnInsideSelectionMousePressRelease() { return onInsideSelectionMousePressRelease.getValue(); }
393+
394+
private final Property<Consumer<Point2D>> onNewSelectionDrag = new SimpleObjectProperty<>(p -> {
395+
CharacterHit hit = hit(p.getX(), p.getY());
396+
moveTo(hit.getInsertionIndex(), SelectionPolicy.ADJUST);
397+
});
398+
public final void setOnNewSelectionDrag(Consumer<Point2D> consumer) { onNewSelectionDrag.setValue(consumer); }
399+
public final Consumer<Point2D> getOnNewSelectionDrag() { return onNewSelectionDrag.getValue(); }
400+
401+
private final Property<Consumer<MouseEvent>> onNewSelectionDragEnd = new SimpleObjectProperty<>(e -> {
402+
CharacterHit hit = hit(e.getX(), e.getY());
403+
moveTo(hit.getInsertionIndex(), SelectionPolicy.ADJUST);
404+
});
405+
public final void setOnNewSelectionDragEnd(Consumer<MouseEvent> consumer) { onNewSelectionDragEnd.setValue(consumer); }
406+
public final Consumer<MouseEvent> getOnNewSelectionDragEnd() { return onNewSelectionDragEnd.getValue(); }
407+
408+
private final Property<Consumer<Point2D>> onSelectionDrag = new SimpleObjectProperty<>(p -> {
409+
CharacterHit hit = hit(p.getX(), p.getY());
410+
displaceCaret(hit.getInsertionIndex());
411+
});
412+
public final void setOnSelectionDrag(Consumer<Point2D> consumer) { onSelectionDrag.setValue(consumer); }
413+
public final Consumer<Point2D> getOnSelectionDrag() { return onSelectionDrag.getValue(); }
414+
415+
private final Property<Consumer<MouseEvent>> onSelectionDrop = new SimpleObjectProperty<>(e -> {
416+
CharacterHit hit = hit(e.getX(), e.getY());
417+
moveSelectedText(hit.getInsertionIndex());
418+
});
419+
@Override public final void setOnSelectionDrop(Consumer<MouseEvent> consumer) { onSelectionDrop.setValue(consumer); }
420+
@Override public final Consumer<MouseEvent> getOnSelectionDrop() { return onSelectionDrop.getValue(); }
421+
422+
// not a hook, but still plays a part in the default mouse behavior
423+
private final BooleanProperty autoScrollOnDragDesired = new SimpleBooleanProperty(true);
424+
public final void setAutoScrollOnDragDesired(boolean val) { autoScrollOnDragDesired.set(val); }
425+
public final boolean isAutoScrollOnDragDesired() { return autoScrollOnDragDesired.get(); }
418426

419427
/* ********************************************************************** *
420428
* *
@@ -615,7 +623,7 @@ public GenericStyledArea(
615623
this.applyParagraphStyle = applyParagraphStyle;
616624
this.segmentOps = segmentOps;
617625

618-
undoManager = UndoUtils.createUndoManager(this);
626+
undoManager = UndoUtils.defaultUndoManager(this);
619627

620628
// allow tab traversal into area
621629
setFocusTraversable(true);
@@ -647,13 +655,6 @@ public GenericStyledArea(
647655
IntUnaryOperator cellLength = i -> virtualFlow.getCell(i).getNode().getLineCount();
648656
navigator = new TwoLevelNavigator(cellCount, cellLength);
649657

650-
// relayout the popup when any of its settings values change (besides the caret being dirty)
651-
EventStream<?> popupAlignmentDirty = invalidationsOf(popupAlignmentProperty());
652-
EventStream<?> popupAnchorAdjustmentDirty = invalidationsOf(popupAnchorAdjustmentProperty());
653-
EventStream<?> popupAnchorOffsetDirty = invalidationsOf(popupAnchorOffsetProperty());
654-
EventStream<?> popupDirty = merge(popupAlignmentDirty, popupAnchorAdjustmentDirty, popupAnchorOffsetDirty);
655-
subscribeTo(popupDirty, x -> layoutPopup());
656-
657658
viewportDirty = merge(
658659
// no need to check for width & height invalidations as scroll values update when these do
659660

@@ -677,17 +678,6 @@ public GenericStyledArea(
677678

678679
visibleParagraphs = LiveList.map(virtualFlow.visibleCells(), c -> c.getNode().getParagraph()).suspendable();
679680

680-
// Adjust popup anchor by either a user-provided function,
681-
// or user-provided offset, or don't adjust at all.
682-
Val<UnaryOperator<Point2D>> userOffset = Val.map(
683-
popupAnchorOffsetProperty(),
684-
offset -> anchor -> anchor.add(offset));
685-
_popupAnchorAdjustment =
686-
Val.orElse(
687-
popupAnchorAdjustmentProperty(),
688-
userOffset)
689-
.orElseConst(UnaryOperator.identity());
690-
691681
final Suspendable omniSuspendable = Suspendable.combine(
692682
beingUpdated, // must be first, to be the last one to release
693683

@@ -703,6 +693,26 @@ public GenericStyledArea(
703693
.subscribe(evt -> Event.fireEvent(this, evt));
704694

705695
new StyledTextAreaBehavior(this);
696+
697+
// Code below this point is deprecated Popup API. It will be removed in the future
698+
699+
// relayout the popup when any of its settings values change (besides the caret being dirty)
700+
EventStream<?> popupAlignmentDirty = invalidationsOf(popupAlignmentProperty());
701+
EventStream<?> popupAnchorAdjustmentDirty = invalidationsOf(popupAnchorAdjustmentProperty());
702+
EventStream<?> popupAnchorOffsetDirty = invalidationsOf(popupAnchorOffsetProperty());
703+
EventStream<?> popupDirty = merge(popupAlignmentDirty, popupAnchorAdjustmentDirty, popupAnchorOffsetDirty);
704+
subscribeTo(popupDirty, x -> layoutPopup());
705+
706+
// Adjust popup anchor by either a user-provided function,
707+
// or user-provided offset, or don't adjust at all.
708+
Val<UnaryOperator<Point2D>> userOffset = Val.map(
709+
popupAnchorOffsetProperty(),
710+
offset -> anchor -> anchor.add(offset));
711+
_popupAnchorAdjustment =
712+
Val.orElse(
713+
popupAnchorAdjustmentProperty(),
714+
userOffset)
715+
.orElseConst(UnaryOperator.identity());
706716
}
707717

708718
/* ********************************************************************** *

richtextfx/src/main/java/org/fxmisc/richtext/UnboundedSelectionImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
import static org.reactfx.EventStreams.invalidationsOf;
2626
import static org.reactfx.EventStreams.merge;
2727

28-
public final class UnboundedSelectionImpl<PS, SEG, S> implements UnboundedSelection<PS, SEG, S> {
28+
final class UnboundedSelectionImpl<PS, SEG, S> implements UnboundedSelection<PS, SEG, S> {
2929

3030
private final SuspendableVal<IndexRange> range;
3131
@Override public final IndexRange getRange() { return range.getValue(); }

richtextfx/src/main/java/org/fxmisc/richtext/util/UndoUtils.java

Lines changed: 59 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,35 +9,85 @@
99

1010
import java.util.function.Consumer;
1111

12+
/**
13+
* A class filled with factory methods to help easily construct an {@link UndoManager} for a {@link GenericStyledArea}.
14+
*/
1215
public final class UndoUtils {
1316

1417
private UndoUtils() {
1518
throw new IllegalStateException("UndoUtils cannot be instantiated");
1619
}
1720

18-
public static <PS, SEG, S> UndoManager createUndoManager(GenericStyledArea<PS, SEG, S> area) {
21+
/**
22+
* Constructs an UndoManager with an unlimited history:
23+
* if {@link GenericStyledArea#isPreserveStyle() the area's preserveStyle flag is true}, the returned UndoManager
24+
* can undo/redo {@link RichTextChange}s; otherwise, it can undo/redo {@link PlainTextChange}s.
25+
*/
26+
public static <PS, SEG, S> UndoManager defaultUndoManager(GenericStyledArea<PS, SEG, S> area) {
1927
return area.isPreserveStyle()
2028
? richTextUndoManager(area)
2129
: plainTextUndoManager(area);
2230
}
2331

24-
public static <PS, SEG, S> UndoManager richTextUndoManager(GenericStyledArea<PS, SEG, S> area) {
32+
/* ********************************************************************** *
33+
* *
34+
* UndoManager Factory Methods *
35+
* *
36+
* Code that constructs different kinds of UndoManagers for an area *
37+
* *
38+
* ********************************************************************** */
39+
40+
/**
41+
* Returns an UndoManager with an unlimited history that can undo/redo {@link RichTextChange}s.
42+
*/
43+
public static <PS, SEG, S> UndoManager<RichTextChange<PS, SEG, S>> richTextUndoManager(GenericStyledArea<PS, SEG, S> area) {
2544
return richTextUndoManager(area, UndoManagerFactory.unlimitedHistoryFactory());
2645
}
2746

28-
public static <PS, SEG, S> UndoManager richTextUndoManager(GenericStyledArea<PS, SEG, S> area,
47+
/**
48+
* Returns an UndoManager that can undo/redo {@link RichTextChange}s.
49+
*/
50+
public static <PS, SEG, S> UndoManager<RichTextChange<PS, SEG, S>> richTextUndoManager(GenericStyledArea<PS, SEG, S> area,
2951
UndoManagerFactory factory) {
30-
Consumer<RichTextChange<PS, SEG, S>> apply = change -> area.replace(change.getPosition(), change.getPosition() + change.getRemoved().length(), change.getInserted());
31-
return factory.create(area.richChanges(), RichTextChange::invert, apply, TextChange::mergeWith, TextChange::isIdentity);
52+
return factory.create(area.richChanges(), TextChange::invert, applyRichTextChange(area), TextChange::mergeWith, TextChange::isIdentity);
3253
};
3354

34-
public static <PS, SEG, S> UndoManager plainTextUndoManager(GenericStyledArea<PS, SEG, S> area) {
55+
/**
56+
* Returns an UndoManager with an unlimited history that can undo/redo {@link PlainTextChange}s.
57+
*/
58+
public static <PS, SEG, S> UndoManager<PlainTextChange> plainTextUndoManager(GenericStyledArea<PS, SEG, S> area) {
3559
return plainTextUndoManager(area, UndoManagerFactory.unlimitedHistoryFactory());
3660
}
3761

38-
public static <PS, SEG, S> UndoManager plainTextUndoManager(GenericStyledArea<PS, SEG, S> area,
62+
/**
63+
* Returns an UndoManager that can undo/redo {@link PlainTextChange}s.
64+
*/
65+
public static <PS, SEG, S> UndoManager<PlainTextChange> plainTextUndoManager(GenericStyledArea<PS, SEG, S> area,
3966
UndoManagerFactory factory) {
40-
Consumer<PlainTextChange> apply = change -> area.replaceText(change.getPosition(), change.getPosition() + change.getRemoved().length(), change.getInserted());
41-
return factory.create(area.plainTextChanges(), PlainTextChange::invert, apply, TextChange::mergeWith, TextChange::isIdentity);
67+
return factory.create(area.plainTextChanges(), TextChange::invert, applyPlainTextChange(area), TextChange::mergeWith, TextChange::isIdentity);
68+
}
69+
70+
/* ********************************************************************** *
71+
* *
72+
* Change Appliers *
73+
* *
74+
* Code that handles how a change should be applied to the area *
75+
* *
76+
* ********************************************************************** */
77+
78+
/**
79+
* Applies a {@link PlainTextChange} to the given area when the {@link UndoManager}'s change stream emits an event
80+
* by {@code area.replaceText(change.getPosition(), change.getRemovalEnd(), change.getInserted()}.
81+
*/
82+
public static <PS, SEG, S> Consumer<PlainTextChange> applyPlainTextChange(GenericStyledArea<PS, SEG, S> area) {
83+
return change -> area.replaceText(change.getPosition(), change.getRemovalEnd(), change.getInserted());
84+
}
85+
86+
/**
87+
* Applies a {@link PlainTextChange} to the given area when the {@link UndoManager}'s change stream emits an event
88+
* by {@code area.replace(change.getPosition(), change.getRemovalEnd(), change.getInserted()}.
89+
*/
90+
public static <PS, SEG, S> Consumer<RichTextChange<PS, SEG, S>> applyRichTextChange(GenericStyledArea<PS, SEG, S> area) {
91+
return change -> area.replace(change.getPosition(), change.getRemovalEnd(), change.getInserted());
4292
}
4393
}

0 commit comments

Comments
 (0)