Skip to content

Commit

Permalink
Merge pull request #64 from Arcnor/master
Browse files Browse the repository at this point in the history
Workaround to correct trackpad scrolling gestures under macOS
  • Loading branch information
JordanMartinez authored Apr 8, 2018
2 parents 6466073 + 040613b commit 7eb0a6b
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 3 deletions.
33 changes: 33 additions & 0 deletions src/main/java/org/fxmisc/flowless/CellListManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import javafx.collections.ObservableList;
import javafx.scene.Node;
import javafx.scene.input.ScrollEvent;

import org.reactfx.EventStreams;
import org.reactfx.Subscription;
Expand All @@ -18,6 +19,7 @@
*/
final class CellListManager<T, C extends Cell<T, ? extends Node>> {

private final Node owner;
private final CellPool<T, C> cellPool;
private final MemoizationList<C> cells;
private final LiveList<C> presentCells;
Expand All @@ -26,8 +28,10 @@ final class CellListManager<T, C extends Cell<T, ? extends Node>> {
private final Subscription presentCellsSubscription;

public CellListManager(
Node owner,
ObservableList<T> items,
Function<? super T, ? extends C> cellFactory) {
this.owner = owner;
this.cellPool = new CellPool<>(cellFactory);
this.cells = LiveList.map(items, this::cellForItem).memoize();
this.presentCells = cells.memoizedItems();
Expand Down Expand Up @@ -96,9 +100,38 @@ private C cellForItem(T item) {
// It will be made visible when it is positioned.
node.setVisible(false);

if (cell.isReusable()) {
// if cell is reused i think adding event handler
// would cause resource leakage.
node.setOnScroll(this::pushScrollEvent);
node.setOnScrollStarted(this::pushScrollEvent);
node.setOnScrollFinished(this::pushScrollEvent);
} else {
node.addEventHandler(ScrollEvent.ANY, this::pushScrollEvent);
}

return cell;
}

/**
* Push scroll events received by cell nodes directly to
* the 'owner' Node. (Generally likely to be a VirtualFlow
* but not required.)
*
* Normal bubbling of scroll events gets interrupted during
* a scroll gesture when the Cell's Node receiving the event
* has moved out of the viewport and is thus removed from
* the Navigator's children list. This breaks expected trackpad
* scrolling behaviour, at least on macOS.
*
* So here we take over event-bubbling duties for ScrollEvent
* and push them ourselves directly to the given owner.
*/
private void pushScrollEvent(ScrollEvent se) {
owner.fireEvent(se);
se.consume();
}

private void presentCellsChanged(QuasiListModification<? extends C> mod) {
// add removed cells back to the pool
for(C cell: mod.getRemoved()) {
Expand Down
6 changes: 3 additions & 3 deletions src/main/java/org/fxmisc/flowless/VirtualFlow.java
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ private VirtualFlow(
this.getStyleClass().add("virtual-flow");
this.items = items;
this.orientation = orientation;
this.cellListManager = new CellListManager<>(items, cellFactory);
this.cellListManager = new CellListManager<>(this, items, cellFactory);
this.gravity.set(gravity);
MemoizationList<C> cells = cellListManager.getLazyCellList();
this.sizeTracker = new SizeTracker(orientation, layoutBoundsProperty(), cells);
Expand All @@ -183,7 +183,7 @@ private VirtualFlow(
lengthOffsetEstimate = sizeTracker.lengthOffsetEstimateProperty().asVar(this::setLengthOffset);

// scroll content by mouse scroll
this.addEventHandler(ScrollEvent.SCROLL, se -> {
this.addEventHandler(ScrollEvent.ANY, se -> {
scrollXBy(-se.getDeltaX());
scrollYBy(-se.getDeltaY());
se.consume();
Expand Down Expand Up @@ -634,4 +634,4 @@ public StyleableProperty<Gravity> getStyleableProperty(VirtualFlow virtualFlow)
public List<CssMetaData<? extends Styleable, ?>> getCssMetaData() {
return getClassCssMetaData();
}
}
}

0 comments on commit 7eb0a6b

Please sign in to comment.