fix scroll speed management

simplify scroll speed management, and scroll bounds WIP, cleanup

cleanup and comments
This commit is contained in:
millmanorama 2015-11-06 10:15:04 -05:00 committed by jmillman
parent fbe626ea8e
commit e2b4f59738
2 changed files with 74 additions and 87 deletions

View File

@ -54,8 +54,6 @@ import static javafx.scene.input.KeyCode.PAGE_DOWN;
import static javafx.scene.input.KeyCode.PAGE_UP; import static javafx.scene.input.KeyCode.PAGE_UP;
import static javafx.scene.input.KeyCode.UP; import static javafx.scene.input.KeyCode.UP;
import javafx.scene.input.KeyEvent; import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.input.ScrollEvent;
import javafx.scene.layout.HBox; import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane; import javafx.scene.layout.Pane;
import javafx.scene.layout.Priority; import javafx.scene.layout.Priority;
@ -93,53 +91,91 @@ public class DetailViewPane extends AbstractVisualizationPane<DateTime, EventClu
private final static Logger LOGGER = Logger.getLogger(DetailViewPane.class.getName()); private final static Logger LOGGER = Logger.getLogger(DetailViewPane.class.getName());
private MultipleSelectionModel<TreeItem<EventBundle<?>>> treeSelectionModel; private static final double LINE_SCROLL_PERCENTAGE = .10;
private static final double PAGE_SCROLL_PERCENTAGE = .70;
//these three could be injected from fxml but it was causing npe's
private final DateAxis dateAxis = new DateAxis(); private final DateAxis dateAxis = new DateAxis();
private final Axis<EventCluster> verticalAxis = new EventAxis(); private final Axis<EventCluster> verticalAxis = new EventAxis();
private final ScrollBar vertScrollBar = new ScrollBar();
private final Region scrollBarSpacer = new Region();
private MultipleSelectionModel<TreeItem<EventBundle<?>>> treeSelectionModel;
private final ObservableList<EventBundleNodeBase<?, ?, ?>> highlightedNodes = FXCollections.synchronizedObservableList(FXCollections.observableArrayList());
//private access to barchart data //private access to barchart data
private final Map<EventType, XYChart.Series<DateTime, EventCluster>> eventTypeToSeriesMap = new ConcurrentHashMap<>(); private final Map<EventType, XYChart.Series<DateTime, EventCluster>> eventTypeToSeriesMap = new ConcurrentHashMap<>();
private final ScrollBar vertScrollBar = new ScrollBar();
private final Region region = new Region();
private final ObservableList<EventBundleNodeBase<?, ?, ?>> highlightedNodes = FXCollections.synchronizedObservableList(FXCollections.observableArrayList());
public ObservableList<EventBundle<?>> getEventBundles() { public ObservableList<EventBundle<?>> getEventBundles() {
return chart.getEventBundles(); return chart.getEventBundles();
} }
public DetailViewPane(TimeLineController controller, Pane partPane, Pane contextPane, Region bottomLeftSpacer) {
super(controller, partPane, contextPane, bottomLeftSpacer);
settingsNodes = new ArrayList<>(new DetailViewSettingsPane().getChildrenUnmodifiable());
public DetailViewPane(TimeLineController controller, Pane partPane, Pane contextPane, Region spacer) { //initialize chart;
super(controller, partPane, contextPane, spacer);
chart = new EventDetailsChart(controller, dateAxis, verticalAxis, selectedNodes); chart = new EventDetailsChart(controller, dateAxis, verticalAxis, selectedNodes);
setChartClickHandler(); setChartClickHandler(); //can we push this into chart
chart.setData(dataSets); chart.setData(dataSets);
setCenter(chart); setCenter(chart);
//bind layout fo axes and spacers
chart.setPrefHeight(USE_COMPUTED_SIZE); dateAxis.setTickLabelGap(0);
settingsNodes = new ArrayList<>(new DetailViewSettingsPane().getChildrenUnmodifiable());
vertScrollBar.setOrientation(Orientation.VERTICAL);
VBox vBox = new VBox();
VBox.setVgrow(vertScrollBar, Priority.ALWAYS);
vBox.getChildren().add(vertScrollBar);
vBox.getChildren().add(region);
setRight(vBox);
dateAxis.setAutoRanging(false); dateAxis.setAutoRanging(false);
region.minHeightProperty().bind(dateAxis.heightProperty()); dateAxis.setTickLabelsVisible(false);
vertScrollBar.visibleAmountProperty().bind(chart.heightProperty().multiply(100).divide(chart.maxVScrollProperty())); dateAxis.getTickMarks().addListener((Observable observable) -> layoutDateLabels());
requestLayout(); dateAxis.getTickSpacing().addListener(observable -> layoutDateLabels());
bottomLeftSpacer.minWidthProperty().bind(verticalAxis.widthProperty().add(verticalAxis.tickLengthProperty()));
bottomLeftSpacer.prefWidthProperty().bind(verticalAxis.widthProperty().add(verticalAxis.tickLengthProperty()));
bottomLeftSpacer.maxWidthProperty().bind(verticalAxis.widthProperty().add(verticalAxis.tickLengthProperty()));
scrollBarSpacer.minHeightProperty().bind(dateAxis.heightProperty());
//configure scrollbar
vertScrollBar.setOrientation(Orientation.VERTICAL);
vertScrollBar.maxProperty().bind(chart.maxVScrollProperty().subtract(chart.heightProperty()));
vertScrollBar.visibleAmountProperty().bind(chart.heightProperty());
vertScrollBar.visibleProperty().bind(vertScrollBar.visibleAmountProperty().greaterThanOrEqualTo(0));
VBox.setVgrow(vertScrollBar, Priority.ALWAYS);
setRight(new VBox(vertScrollBar, scrollBarSpacer));
//interpret scroll events to the scrollBar
this.setOnScroll(scrollEvent ->
vertScrollBar.valueProperty().set(clampScroll(vertScrollBar.getValue() - scrollEvent.getDeltaY())));
//request focus for keyboard scrolling
setOnMouseClicked(mouseEvent -> requestFocus());
//interpret scroll related keys to scrollBar
this.setOnKeyPressed((KeyEvent t) -> {
switch (t.getCode()) {
case PAGE_UP:
incrementScrollValue(-PAGE_SCROLL_PERCENTAGE);
t.consume();
break;
case PAGE_DOWN:
incrementScrollValue(PAGE_SCROLL_PERCENTAGE);
t.consume();
break;
case KP_UP:
case UP:
incrementScrollValue(-LINE_SCROLL_PERCENTAGE);
t.consume();
break;
case KP_DOWN:
case DOWN:
incrementScrollValue(LINE_SCROLL_PERCENTAGE);
t.consume();
break;
}
});
//scrollbar value change handler. This forwards changes in scroll bar to chart
this.vertScrollBar.valueProperty().addListener(observable -> chart.setVScroll(vertScrollBar.getValue()));
//maintain highlighted effect on correct nodes
highlightedNodes.addListener((ListChangeListener.Change<? extends EventBundleNodeBase<?, ?, ?>> change) -> { highlightedNodes.addListener((ListChangeListener.Change<? extends EventBundleNodeBase<?, ?, ?>> change) -> {
while (change.next()) { while (change.next()) {
change.getAddedSubList().forEach(node -> { change.getAddedSubList().forEach(node -> {
node.applyHighlightEffect(true); node.applyHighlightEffect(true);
@ -149,71 +185,24 @@ public class DetailViewPane extends AbstractVisualizationPane<DateTime, EventClu
}); });
} }
}); });
//request focus for keyboard scrolling
setOnMouseClicked((MouseEvent t) -> {
requestFocus();
});
//These scroll related handlers don't affect any other view or the model, so they are handled internally
//mouse wheel scroll handler
this.onScrollProperty().set((ScrollEvent t) -> {
vertScrollBar.valueProperty().set(Math.max(0, Math.min(100, vertScrollBar.getValue() - t.getDeltaY() / 200.0)));
});
this.setOnKeyPressed((KeyEvent t) -> {
switch (t.getCode()) {
case PAGE_UP:
incrementScrollValue(-70);
break;
case PAGE_DOWN:
incrementScrollValue(70);
break;
case KP_UP:
case UP:
incrementScrollValue(-10);
break;
case KP_DOWN:
case DOWN:
incrementScrollValue(10);
break;
}
t.consume();
});
//scrollbar handler
this.vertScrollBar.valueProperty().addListener((o, oldValue, newValue) -> {
chart.setVScroll(newValue.doubleValue() / 100.0);
});
spacer.minWidthProperty().bind(verticalAxis.widthProperty().add(verticalAxis.tickLengthProperty()));
spacer.prefWidthProperty().bind(verticalAxis.widthProperty().add(verticalAxis.tickLengthProperty()));
spacer.maxWidthProperty().bind(verticalAxis.widthProperty().add(verticalAxis.tickLengthProperty()));
dateAxis.setTickLabelsVisible(false);
dateAxis.getTickMarks().addListener((Observable observable) -> {
layoutDateLabels();
});
dateAxis.getTickSpacing().addListener((Observable observable) -> {
layoutDateLabels();
});
dateAxis.setTickLabelGap(0);
selectedNodes.addListener((Observable observable) -> { selectedNodes.addListener((Observable observable) -> {
highlightedNodes.clear(); highlightedNodes.clear();
selectedNodes.stream().forEach((tn) -> { selectedNodes.stream().forEach((tn) -> {
for (EventBundleNodeBase<?, ?, ?> n : chart.getNodes((EventBundleNodeBase<?, ?, ?> t) -> for (EventBundleNodeBase<?, ?, ?> n : chart.getNodes((EventBundleNodeBase<?, ?, ?> t) ->
t.getDescription().equals(tn.getDescription()))) { t.getDescription().equals(tn.getDescription()))) {
highlightedNodes.add(n); highlightedNodes.add(n);
} }
}); });
}); });
} }
private void incrementScrollValue(int factor) { private void incrementScrollValue(double factor) {
vertScrollBar.valueProperty().set(Math.max(0, Math.min(100, vertScrollBar.getValue() + factor * (chart.getHeight() / chart.maxVScrollProperty().get())))); vertScrollBar.valueProperty().set(clampScroll(vertScrollBar.getValue() + factor * chart.getHeight()));
}
private Double clampScroll(Double value) {
return Math.max(0, Math.min(vertScrollBar.getMax() + 50, value));
} }
public void setSelectionModel(MultipleSelectionModel<TreeItem<EventBundle<?>>> selectionModel) { public void setSelectionModel(MultipleSelectionModel<TreeItem<EventBundle<?>>> selectionModel) {
@ -472,5 +461,4 @@ public class DetailViewPane extends AbstractVisualizationPane<DateTime, EventClu
public Action newHideDescriptionAction(String description, DescriptionLoD descriptionLoD) { public Action newHideDescriptionAction(String description, DescriptionLoD descriptionLoD) {
return chart.new HideDescriptionAction(description, descriptionLoD); return chart.new HideDescriptionAction(description, descriptionLoD);
} }
} }

View File

@ -425,9 +425,8 @@ public final class EventDetailsChart extends XYChart<DateTime, EventCluster> imp
return getNodes(x -> true); return getNodes(x -> true);
} }
synchronized void setVScroll(double d) { synchronized void setVScroll(double vScrollValue) {
final double h = maxY.get() - (getHeight() * .9); nodeGroup.setTranslateY(-vScrollValue);
nodeGroup.setTranslateY(-d * h);
} }
private void clearGuideLine() { private void clearGuideLine() {