Skip to content

Commit

Permalink
Autoscroll on drag. Closes #116.
Browse files Browse the repository at this point in the history
  • Loading branch information
TomasMikula committed Feb 28, 2015
1 parent da69914 commit 311126e
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import static org.fxmisc.wellbehaved.event.EventPattern.*;
import static org.reactfx.EventStreams.*;
import javafx.event.EventHandler;
import javafx.geometry.Bounds;
import javafx.geometry.Point2D;
import javafx.scene.control.IndexRange;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseButton;
Expand All @@ -19,7 +21,10 @@
import org.fxmisc.wellbehaved.event.EventHandlerHelper;
import org.fxmisc.wellbehaved.event.EventHandlerTemplate;
import org.fxmisc.wellbehaved.skin.Behavior;
import org.reactfx.EventStream;
import org.reactfx.Subscription;
import org.reactfx.value.Val;
import org.reactfx.value.Var;

import com.sun.javafx.PlatformUtil;

Expand Down Expand Up @@ -180,6 +185,8 @@ private double getTargetCaretOffset() {
return targetCaretOffset;
}

private final Var<Point2D> autoscrollTo = Var.newSimpleVar(null);

/* ********************************************************************** *
* Constructors *
* ********************************************************************** */
Expand All @@ -204,6 +211,26 @@ public StyledTextAreaBehavior(StyledTextAreaVisual<?> visual) {
EventHandlerHelper.remove(area.onKeyPressedProperty(), keyPressedHandler);
EventHandlerHelper.remove(area.onKeyTypedProperty(), keyTypedHandler);
});

// setup auto-scroll
Val<Point2D> projection = Val.combine(
autoscrollTo,
view.layoutBoundsProperty(),
StyledTextAreaBehavior::project);
Val<Point2D> distance = Val.combine(
autoscrollTo,
projection,
Point2D::subtract);
EventStream<Point2D> deltas = nonNullValuesOf(distance)
.emitBothOnEach(animationFrames())
.map(t -> t.map((ds, nanos) -> ds.multiply(nanos / 100_000_000.0)));
valuesOf(autoscrollTo).flatMap(p -> p == null
? never() // automatically stops the scroll animation
: deltas)
.subscribe(ds -> {
view.scrollBy(ds);
projection.ifPresent(this::dragTo);
});
}

/* ********************************************************************** *
Expand Down Expand Up @@ -410,20 +437,32 @@ private void mouseDragged(MouseEvent e) {
return;
}

// get the position within text
CharacterHit hit = view.hit(e.getX(), e.getY());
Point2D p = new Point2D(e.getX(), e.getY());
if(view.getLayoutBounds().contains(p)) {
dragTo(p);
autoscrollTo.setValue(null); // stops auto-scroll
} else {
autoscrollTo.setValue(p); // starts auto-scroll
}

e.consume();
}

private void dragTo(Point2D p) {
CharacterHit hit = view.hit(p.getX(), p.getY());

if(dragSelection == DragState.DRAG ||
dragSelection == DragState.POTENTIAL_DRAG) { // MOUSE_DRAGGED may arrive even before DRAG_DETECTED
area.positionCaret(hit.getInsertionIndex());
} else {
area.moveTo(hit.getInsertionIndex(), SelectionPolicy.ADJUST);
}

e.consume();
}

private void mouseReleased(MouseEvent e) {
// stop auto-scroll
autoscrollTo.setValue(null);

// don't respond if disabled
if(area.isDisabled()) {
return;
Expand All @@ -446,4 +485,14 @@ private void mouseReleased(MouseEvent e) {
dragSelection = DragState.NO_DRAG;
e.consume();
}

private static Point2D project(Point2D p, Bounds bounds) {
double x = clamp(p.getX(), bounds.getMinX(), bounds.getMaxX());
double y = clamp(p.getY(), bounds.getMinY(), bounds.getMaxY());
return new Point2D(x, y);
}

private static double clamp(double x, double min, double max) {
return Math.min(Math.max(x, min), max);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,11 @@ protected void layoutChildren() {
* *
* ********************************************************************** */

void scrollBy(Point2D deltas) {
virtualFlow.scrollX(deltas.getX());
virtualFlow.scrollY(deltas.getY());
}

void show(double y) {
virtualFlow.show(y);
}
Expand Down

0 comments on commit 311126e

Please sign in to comment.