PnnedEventsChart is better integrated interms of respecting settings and selection

This commit is contained in:
jmillman 2016-02-24 15:28:43 -05:00
parent 38af730c58
commit 4acaed2557
9 changed files with 172 additions and 152 deletions

View File

@ -0,0 +1,91 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.sleuthkit.autopsy.timeline.ui.detailview;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleObjectProperty;
/**
*
*/
public class DetailViewLayoutSettings {
/**
* true == truncate all the labels to the greater of the size of their
* timespan indicator or the value of truncateWidth. false == don't truncate
* the labels, alow them to extend past the timespan indicator and off the
* edge of the screen
*/
final SimpleBooleanProperty truncateAll = new SimpleBooleanProperty(false);
/**
* the width to truncate all labels to if truncateAll is true. adjustable
* via slider if truncateAll is true
*/
final SimpleDoubleProperty truncateWidth = new SimpleDoubleProperty(200.0);
/**
* true == layout each event type in its own band, false == mix all the
* events together during layout
*/
private final SimpleBooleanProperty bandByType = new SimpleBooleanProperty(false);
/**
* true == enforce that no two events can share the same 'row', leading to
* sparser but possibly clearer layout. false == put unrelated events in the
* same 'row', creating a denser more compact layout
*/
private final SimpleBooleanProperty oneEventPerRow = new SimpleBooleanProperty(false);
/**
* how much detail of the description to show in the ui
*/
private final SimpleObjectProperty<DescriptionVisibility> descrVisibility =
new SimpleObjectProperty<>(DescriptionVisibility.SHOWN);
public synchronized SimpleBooleanProperty bandByTypeProperty() {
return bandByType;
}
SimpleBooleanProperty oneEventPerRowProperty() {
return oneEventPerRow;
}
SimpleDoubleProperty truncateWidthProperty() {
return truncateWidth;
}
SimpleBooleanProperty truncateAllProperty() {
return truncateAll;
}
SimpleObjectProperty< DescriptionVisibility> descrVisibilityProperty() {
return descrVisibility;
}
synchronized void setBandByType(Boolean t1) {
bandByType.set(t1);
}
boolean getBandByType() {
return bandByType.get();
}
boolean getTruncateAll() {
return truncateAll.get();
}
double getTruncateWidth() {
return truncateWidth.get();
}
boolean getOneEventPerRow() {
return oneEventPerRow.get();
}
DescriptionVisibility getDescrVisibility() {
return descrVisibility.get();
}
}

View File

@ -89,6 +89,7 @@ public class DetailViewPane extends AbstractVisualizationPane<DateTime, EventStr
private final ObservableList<EventNodeBase<?>> highlightedNodes = FXCollections.synchronizedObservableList(FXCollections.observableArrayList()); private final ObservableList<EventNodeBase<?>> highlightedNodes = FXCollections.synchronizedObservableList(FXCollections.observableArrayList());
private final ScrollingWrapper<EventStripe, EventDetailsChart> mainView; private final ScrollingWrapper<EventStripe, EventDetailsChart> mainView;
private final ScrollingWrapper<TimeLineEvent, PinnedEventsChart> pinnedView; private final ScrollingWrapper<TimeLineEvent, PinnedEventsChart> pinnedView;
private final DetailViewLayoutSettings layoutSettings;
public ObservableList<EventStripe> getEventStripes() { public ObservableList<EventStripe> getEventStripes() {
return chart.getEventStripes(); return chart.getEventStripes();
@ -107,10 +108,12 @@ public class DetailViewPane extends AbstractVisualizationPane<DateTime, EventStr
public DetailViewPane(TimeLineController controller, Pane partPane, Pane contextPane, Region bottomLeftSpacer) { public DetailViewPane(TimeLineController controller, Pane partPane, Pane contextPane, Region bottomLeftSpacer) {
super(controller, partPane, contextPane, bottomLeftSpacer); super(controller, partPane, contextPane, bottomLeftSpacer);
layoutSettings = new DetailViewLayoutSettings();
//initialize chart; //initialize chart;
chart = new EventDetailsChart(controller, detailsChartDateAxis, verticalAxis, selectedNodes); chart = new EventDetailsChart(controller, detailsChartDateAxis, verticalAxis, selectedNodes, layoutSettings);
mainView = new ScrollingWrapper<>(chart); mainView = new ScrollingWrapper<>(chart);
PinnedEventsChart pinnedChart = new PinnedEventsChart(controller, pinnedDateAxis, new EventAxis<>()); PinnedEventsChart pinnedChart = new PinnedEventsChart(controller, pinnedDateAxis, new EventAxis<>(), selectedNodes, layoutSettings);
pinnedView = new ScrollingWrapper<>(pinnedChart); pinnedView = new ScrollingWrapper<>(pinnedChart);
pinnedChart.setMinSize(100, 100); pinnedChart.setMinSize(100, 100);
setChartClickHandler(); //can we push this into chart setChartClickHandler(); //can we push this into chart
@ -270,14 +273,14 @@ public class DetailViewPane extends AbstractVisualizationPane<DateTime, EventStr
assert oneEventPerRowBox != null : "fx:id=\"oneEventPerRowBox\" was not injected: check your FXML file 'DetailViewSettings.fxml'."; // NON-NLS assert oneEventPerRowBox != null : "fx:id=\"oneEventPerRowBox\" was not injected: check your FXML file 'DetailViewSettings.fxml'."; // NON-NLS
assert truncateAllBox != null : "fx:id=\"truncateAllBox\" was not injected: check your FXML file 'DetailViewSettings.fxml'."; // NON-NLS assert truncateAllBox != null : "fx:id=\"truncateAllBox\" was not injected: check your FXML file 'DetailViewSettings.fxml'."; // NON-NLS
assert truncateWidthSlider != null : "fx:id=\"truncateAllSlider\" was not injected: check your FXML file 'DetailViewSettings.fxml'."; // NON-NLS assert truncateWidthSlider != null : "fx:id=\"truncateAllSlider\" was not injected: check your FXML file 'DetailViewSettings.fxml'."; // NON-NLS
bandByTypeBox.selectedProperty().bindBidirectional(chart.bandByTypeProperty()); bandByTypeBox.selectedProperty().bindBidirectional(layoutSettings.bandByTypeProperty());
truncateAllBox.selectedProperty().bindBidirectional(chart.truncateAllProperty()); truncateAllBox.selectedProperty().bindBidirectional(layoutSettings.truncateAllProperty());
oneEventPerRowBox.selectedProperty().bindBidirectional(chart.oneEventPerRowProperty()); oneEventPerRowBox.selectedProperty().bindBidirectional(layoutSettings.oneEventPerRowProperty());
truncateSliderLabel.disableProperty().bind(truncateAllBox.selectedProperty().not()); truncateSliderLabel.disableProperty().bind(truncateAllBox.selectedProperty().not());
truncateSliderLabel.setText(NbBundle.getMessage(DetailViewPane.class, "DetailViewPane.truncateSliderLabel.text")); truncateSliderLabel.setText(NbBundle.getMessage(DetailViewPane.class, "DetailViewPane.truncateSliderLabel.text"));
final InvalidationListener sliderListener = o -> { final InvalidationListener sliderListener = o -> {
if (truncateWidthSlider.isValueChanging() == false) { if (truncateWidthSlider.isValueChanging() == false) {
chart.getTruncateWidth().set(truncateWidthSlider.getValue()); layoutSettings.truncateWidthProperty().set(truncateWidthSlider.getValue());
} }
}; };
truncateWidthSlider.valueProperty().addListener(sliderListener); truncateWidthSlider.valueProperty().addListener(sliderListener);
@ -285,11 +288,11 @@ public class DetailViewPane extends AbstractVisualizationPane<DateTime, EventStr
descrVisibility.selectedToggleProperty().addListener((observable, oldToggle, newToggle) -> { descrVisibility.selectedToggleProperty().addListener((observable, oldToggle, newToggle) -> {
if (newToggle == countsRadio) { if (newToggle == countsRadio) {
chart.descrVisibilityProperty().set(DescriptionVisibility.COUNT_ONLY); layoutSettings.descrVisibilityProperty().set(DescriptionVisibility.COUNT_ONLY);
} else if (newToggle == showRadio) { } else if (newToggle == showRadio) {
chart.descrVisibilityProperty().set(DescriptionVisibility.SHOWN); layoutSettings.descrVisibilityProperty().set(DescriptionVisibility.SHOWN);
} else if (newToggle == hiddenRadio) { } else if (newToggle == hiddenRadio) {
chart.descrVisibilityProperty().set(DescriptionVisibility.HIDDEN); layoutSettings.descrVisibilityProperty().set(DescriptionVisibility.HIDDEN);
} }
}); });

View File

@ -101,16 +101,10 @@ final public class EventClusterNode extends MultiEventNodeBase<EventCluster, Eve
getChildren().addAll(subNodePane, infoHBox); getChildren().addAll(subNodePane, infoHBox);
if (parentNode == null) { if (parentNode == null) {
setDescriptionVisibiltiyImpl(DescriptionVisibility.SHOWN); setDescriptionVisibiltiyImpl(DescriptionVisibility.SHOWN);
} }
} }
@Override
void applyHighlightEffect(boolean applied) {
// throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override @Override
void setDescriptionVisibiltiyImpl(DescriptionVisibility descrVis) { void setDescriptionVisibiltiyImpl(DescriptionVisibility descrVis) {
final int size = getEventCluster().getSize(); final int size = getEventCluster().getSize();

View File

@ -38,9 +38,6 @@ import javafx.beans.InvalidationListener;
import javafx.beans.Observable; import javafx.beans.Observable;
import javafx.beans.property.ReadOnlyDoubleProperty; import javafx.beans.property.ReadOnlyDoubleProperty;
import javafx.beans.property.ReadOnlyDoubleWrapper; import javafx.beans.property.ReadOnlyDoubleWrapper;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.FXCollections; import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener; import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList; import javafx.collections.ObservableList;
@ -113,6 +110,7 @@ public final class EventDetailsChart extends XYChart<DateTime, EventStripe> impl
private Set<String> activeQuickHidefilters; private Set<String> activeQuickHidefilters;
@ThreadConfined(type = ThreadConfined.ThreadType.JFX)//at start of layout pass @ThreadConfined(type = ThreadConfined.ThreadType.JFX)//at start of layout pass
private double descriptionWidth; private double descriptionWidth;
private final DetailViewLayoutSettings layoutSettings;
@Override @Override
public ContextMenu getChartContextMenu() { public ContextMenu getChartContextMenu() {
@ -157,40 +155,9 @@ public final class EventDetailsChart extends XYChart<DateTime, EventStripe> impl
private final ObservableList< EventNodeBase<?>> sortedStripeNodes = stripeNodes.sorted(Comparator.comparing(EventNodeBase<?>::getStartMillis)); private final ObservableList< EventNodeBase<?>> sortedStripeNodes = stripeNodes.sorted(Comparator.comparing(EventNodeBase<?>::getStartMillis));
private final Map<EventCluster, Line> projectionMap = new ConcurrentHashMap<>(); private final Map<EventCluster, Line> projectionMap = new ConcurrentHashMap<>();
/** EventDetailsChart(TimeLineController controller, DateAxis dateAxis, final Axis<EventStripe> verticalAxis, ObservableList<EventNodeBase<?>> selectedNodes, DetailViewLayoutSettings layoutSettings) {
* true == layout each event type in its own band, false == mix all the
* events together during layout
*/
private final SimpleBooleanProperty bandByType = new SimpleBooleanProperty(false);
/**
* true == enforce that no two events can share the same 'row', leading to
* sparser but possibly clearer layout. false == put unrelated events in the
* same 'row', creating a denser more compact layout
*/
private final SimpleBooleanProperty oneEventPerRow = new SimpleBooleanProperty(false);
/**
* how much detail of the description to show in the ui
*/
private final SimpleObjectProperty<DescriptionVisibility> descrVisibility =
new SimpleObjectProperty<>(DescriptionVisibility.SHOWN);
/**
* true == truncate all the labels to the greater of the size of their
* timespan indicator or the value of truncateWidth. false == don't truncate
* the labels, alow them to extend past the timespan indicator and off the
* edge of the screen
*/
final SimpleBooleanProperty truncateAll = new SimpleBooleanProperty(false);
/**
* the width to truncate all labels to if truncateAll is true. adjustable
* via slider if truncateAll is true
*/
final SimpleDoubleProperty truncateWidth = new SimpleDoubleProperty(200.0);
EventDetailsChart(TimeLineController controller, DateAxis dateAxis, final Axis<EventStripe> verticalAxis, ObservableList<EventNodeBase<?>> selectedNodes) {
super(dateAxis, verticalAxis); super(dateAxis, verticalAxis);
this.layoutSettings = layoutSettings;
this.controller = controller; this.controller = controller;
this.filteredEvents = this.controller.getEventsModel(); this.filteredEvents = this.controller.getEventsModel();
@ -224,11 +191,11 @@ public final class EventDetailsChart extends XYChart<DateTime, EventStripe> impl
getPlotChildren().add(nodeGroup); getPlotChildren().add(nodeGroup);
//add listener for events that should trigger layout //add listener for events that should trigger layout
bandByType.addListener(layoutInvalidationListener); layoutSettings.bandByTypeProperty().addListener(layoutInvalidationListener);
oneEventPerRow.addListener(layoutInvalidationListener); layoutSettings.oneEventPerRowProperty().addListener(layoutInvalidationListener);
truncateAll.addListener(layoutInvalidationListener); layoutSettings.truncateAllProperty().addListener(layoutInvalidationListener);
truncateWidth.addListener(layoutInvalidationListener); layoutSettings.truncateAllProperty().addListener(layoutInvalidationListener);
descrVisibility.addListener(layoutInvalidationListener); layoutSettings.descrVisibilityProperty().addListener(layoutInvalidationListener);
getController().getQuickHideFilters().addListener(layoutInvalidationListener); getController().getQuickHideFilters().addListener(layoutInvalidationListener);
//this is needed to allow non circular binding of the guideline and timerangeRect heights to the height of the chart //this is needed to allow non circular binding of the guideline and timerangeRect heights to the height of the chart
@ -289,19 +256,11 @@ public final class EventDetailsChart extends XYChart<DateTime, EventStripe> impl
intervalSelector = null; intervalSelector = null;
} }
public synchronized SimpleBooleanProperty bandByTypeProperty() {
return bandByType;
}
@Override @Override
public IntervalSelector<DateTime> newIntervalSelector() { public IntervalSelector<DateTime> newIntervalSelector() {
return new DetailIntervalSelector(this); return new DetailIntervalSelector(this);
} }
synchronized void setBandByType(Boolean t1) {
bandByType.set(t1);
}
/** /**
* get the DateTime along the x-axis that corresponds to the given * get the DateTime along the x-axis that corresponds to the given
* x-coordinate in the coordinate system of this {@link EventDetailsChart} * x-coordinate in the coordinate system of this {@link EventDetailsChart}
@ -326,22 +285,6 @@ public final class EventDetailsChart extends XYChart<DateTime, EventStripe> impl
getChartChildren().add(getIntervalSelector()); getChartChildren().add(getIntervalSelector());
} }
SimpleBooleanProperty oneEventPerRowProperty() {
return oneEventPerRow;
}
SimpleDoubleProperty getTruncateWidth() {
return truncateWidth;
}
SimpleBooleanProperty truncateAllProperty() {
return truncateAll;
}
SimpleObjectProperty< DescriptionVisibility> descrVisibilityProperty() {
return descrVisibility;
}
/** /**
* @see note in main section of class JavaDoc * @see note in main section of class JavaDoc
* *
@ -446,9 +389,9 @@ public final class EventDetailsChart extends XYChart<DateTime, EventStripe> impl
.collect(Collectors.toSet()); .collect(Collectors.toSet());
//This dosn't change during a layout pass and is expensive to compute per node. So we do it once at the start //This dosn't change during a layout pass and is expensive to compute per node. So we do it once at the start
descriptionWidth = truncateAll.get() ? truncateWidth.get() : USE_PREF_SIZE; descriptionWidth = layoutSettings.getTruncateAll() ? layoutSettings.getTruncateWidth() : USE_PREF_SIZE;
if (bandByType.get()) { if (layoutSettings.getBandByType()) {
sortedStripeNodes.stream() sortedStripeNodes.stream()
.collect(Collectors.groupingBy(EventNodeBase<?>::getEventType)).values() .collect(Collectors.groupingBy(EventNodeBase<?>::getEventType)).values()
.forEach(inputNodes -> maxY.set(layoutEventBundleNodes(inputNodes, maxY.get()))); .forEach(inputNodes -> maxY.set(layoutEventBundleNodes(inputNodes, maxY.get())));
@ -547,7 +490,7 @@ public final class EventDetailsChart extends XYChart<DateTime, EventStripe> impl
double xRight = xLeft + w + MINIMUM_EVENT_NODE_GAP; double xRight = xLeft + w + MINIMUM_EVENT_NODE_GAP;
//initial test position //initial test position
double yTop = (oneEventPerRow.get()) double yTop = (layoutSettings.getOneEventPerRow())
? (localMax + MINIMUM_EVENT_NODE_GAP)// if onePerRow, just put it at end ? (localMax + MINIMUM_EVENT_NODE_GAP)// if onePerRow, just put it at end
: computeYTop(minY, h, maxXatY, xLeft, xRight); : computeYTop(minY, h, maxXatY, xLeft, xRight);
@ -607,19 +550,19 @@ public final class EventDetailsChart extends XYChart<DateTime, EventStripe> impl
* *
* Set layout paramaters on the given node and layout its children * Set layout paramaters on the given node and layout its children
* *
* @param bundleNode the Node to layout * @param eventNode the Node to layout
* @param descriptionWdith the maximum width for the description text * @param descriptionWdith the maximum width for the description text
*/ */
private void layoutBundleHelper(final EventNodeBase< ?> bundleNode) { private void layoutBundleHelper(final EventNodeBase< ?> eventNode) {
//make sure it is shown //make sure it is shown
bundleNode.setVisible(true); eventNode.setVisible(true);
bundleNode.setManaged(true); eventNode.setManaged(true);
//apply advanced layout description visibility options //apply advanced layout description visibility options
bundleNode.setDescriptionVisibility(descrVisibility.get()); eventNode.setDescriptionVisibility(layoutSettings.getDescrVisibility());
bundleNode.setMaxDescriptionWidth(descriptionWidth); eventNode.setMaxDescriptionWidth(descriptionWidth);
//do recursive layout //do recursive layout
bundleNode.layoutChildren(); eventNode.layoutChildren();
} }
/** /**

View File

@ -277,7 +277,20 @@ public abstract class EventNodeBase<Type extends TimeLineEvent> extends StackPan
abstract void setDescriptionVisibiltiyImpl(DescriptionVisibility get); abstract void setDescriptionVisibiltiyImpl(DescriptionVisibility get);
abstract void applyHighlightEffect(boolean b); /**
* apply the 'effect' to visually indicate highlighted nodes
*
* @param applied true to apply the highlight 'effect', false to remove it
*/
synchronized void applyHighlightEffect(boolean applied) {
if (applied) {
descrLabel.setStyle("-fx-font-weight: bold;"); // NON-NLS
setBackground(highlightedBackground);
} else {
descrLabel.setStyle("-fx-font-weight: normal;"); // NON-NLS
setBackground(defaultBackground);
}
}
void applyHighlightEffect() { void applyHighlightEffect() {
applyHighlightEffect(true); applyHighlightEffect(true);

View File

@ -84,21 +84,7 @@ final public class EventStripeNode extends MultiEventNodeBase<EventStripe, Event
return getEventBundle(); return getEventBundle();
} }
/**
* apply the 'effect' to visually indicate highlighted nodes
*
* @param applied true to apply the highlight 'effect', false to remove it
*/
@Override
public synchronized void applyHighlightEffect(boolean applied) {
if (applied) {
descrLabel.setStyle("-fx-font-weight: bold;"); // NON-NLS
setBackground(highlightedBackground);
} else {
descrLabel.setStyle("-fx-font-weight: normal;"); // NON-NLS
setBackground(defaultBackground);
}
}
@Override @Override
void installActionButtons() { void installActionButtons() {

View File

@ -225,13 +225,6 @@ public abstract class MultiEventNodeBase< BundleType extends MultiEvent<ParentTy
} }
} }
/**
* apply the 'effect' to visually indicate highlighted nodes
*
* @param applied true to apply the highlight 'effect', false to remove it
*/
abstract void applyHighlightEffect(boolean applied);
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public List<EventNodeBase<?>> getSubNodes() { public List<EventNodeBase<?>> getSubNodes() {
return subNodes; return subNodes;

View File

@ -26,7 +26,10 @@ import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.MissingResourceException; import java.util.MissingResourceException;
import java.util.stream.Collectors;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.beans.property.ReadOnlyDoubleProperty; import javafx.beans.property.ReadOnlyDoubleProperty;
import javafx.beans.property.ReadOnlyDoubleWrapper; import javafx.beans.property.ReadOnlyDoubleWrapper;
import javafx.collections.FXCollections; import javafx.collections.FXCollections;
@ -94,6 +97,14 @@ public final class PinnedEventsChart extends XYChart<DateTime, TimeLineEvent> im
* the maximum y value used so far during the most recent layout pass * the maximum y value used so far during the most recent layout pass
*/ */
private final ReadOnlyDoubleWrapper maxY = new ReadOnlyDoubleWrapper(0.0); private final ReadOnlyDoubleWrapper maxY = new ReadOnlyDoubleWrapper(0.0);
private final ObservableList<EventNodeBase<?>> selectedNodes;
private final DetailViewLayoutSettings layoutSettings;
/**
* listener that triggers chart layout pass
*/
private final InvalidationListener layoutInvalidationListener = (Observable o) -> {
layoutPlotChildren();
};
/** /**
* *
@ -102,9 +113,9 @@ public final class PinnedEventsChart extends XYChart<DateTime, TimeLineEvent> im
* @param verticalAxis the value of verticalAxis * @param verticalAxis the value of verticalAxis
* @param selectedNodes1 the value of selectedNodes1 * @param selectedNodes1 the value of selectedNodes1
*/ */
PinnedEventsChart(TimeLineController controller, DateAxis dateAxis, final Axis<TimeLineEvent> verticalAxis) { PinnedEventsChart(TimeLineController controller, DateAxis dateAxis, final Axis<TimeLineEvent> verticalAxis, ObservableList<EventNodeBase<?>> selectedNodes, DetailViewLayoutSettings layoutSettings) {
super(dateAxis, verticalAxis); super(dateAxis, verticalAxis);
this.layoutSettings = layoutSettings;
this.controller = controller; this.controller = controller;
this.filteredEvents = this.controller.getEventsModel(); this.filteredEvents = this.controller.getEventsModel();
@ -134,11 +145,12 @@ public final class PinnedEventsChart extends XYChart<DateTime, TimeLineEvent> im
setData(FXCollections.observableArrayList()); setData(FXCollections.observableArrayList());
getData().add(series); getData().add(series);
// //add listener for events that should trigger layout // //add listener for events that should trigger layout
// bandByType.addListener(layoutInvalidationListener); layoutSettings.bandByTypeProperty().addListener(layoutInvalidationListener);
// oneEventPerRow.addListener(layoutInvalidationListener); layoutSettings.oneEventPerRowProperty().addListener(layoutInvalidationListener);
// truncateAll.addListener(layoutInvalidationListener); layoutSettings.truncateAllProperty().addListener(layoutInvalidationListener);
// truncateWidth.addListener(layoutInvalidationListener); layoutSettings.truncateAllProperty().addListener(layoutInvalidationListener);
// descrVisibility.addListener(layoutInvalidationListener); layoutSettings.descrVisibilityProperty().addListener(layoutInvalidationListener);
getController().getQuickHideFilters().addListener(layoutInvalidationListener);
// getController().getQuickHideFilters().addListener(layoutInvalidationListener); // getController().getQuickHideFilters().addListener(layoutInvalidationListener);
// //this is needed to allow non circular binding of the guideline and timerangeRect heights to the height of the chart // //this is needed to allow non circular binding of the guideline and timerangeRect heights to the height of the chart
@ -168,9 +180,7 @@ public final class PinnedEventsChart extends XYChart<DateTime, TimeLineEvent> im
requestChartLayout(); requestChartLayout();
}); });
this.selectedNodes = selectedNodes;
// this.selectedNodes = selectedNodes;
// selectedNodes.addListener(new SelectionChangeHandler());
} }
@Override @Override
@ -233,7 +243,7 @@ public final class PinnedEventsChart extends XYChart<DateTime, TimeLineEvent> im
@Override @Override
public ObservableList<EventNodeBase<?>> getSelectedNodes() { public ObservableList<EventNodeBase<?>> getSelectedNodes() {
return FXCollections.observableArrayList(); return selectedNodes;
} }
@Override @Override
@ -257,7 +267,9 @@ public final class PinnedEventsChart extends XYChart<DateTime, TimeLineEvent> im
double xRight = xLeft + w + MINIMUM_EVENT_NODE_GAP; double xRight = xLeft + w + MINIMUM_EVENT_NODE_GAP;
//initial test position //initial test position
double yTop = computeYTop(minY, h, maxXatY, xLeft, xRight); double yTop = (layoutSettings.getOneEventPerRow())
? (localMax + MINIMUM_EVENT_NODE_GAP)// if onePerRow, just put it at end
: computeYTop(minY, h, maxXatY, xLeft, xRight);
localMax = Math.max(yTop + h, localMax); localMax = Math.max(yTop + h, localMax);
@ -301,17 +313,15 @@ public final class PinnedEventsChart extends XYChart<DateTime, TimeLineEvent> im
// .map(DescriptionFilter::getDescription) // .map(DescriptionFilter::getDescription)
// .collect(Collectors.toSet()); // .collect(Collectors.toSet());
//This dosn't change during a layout pass and is expensive to compute per node. So we do it once at the start //This dosn't change during a layout pass and is expensive to compute per node. So we do it once at the start
descriptionWidth = /* descriptionWidth = layoutSettings.getTruncateAll() ? layoutSettings.getTruncateWidth() : USE_PREF_SIZE;
* truncateAll.get() ? truncateWidth.get() :
*/ USE_PREF_SIZE;
// if (bandByType.get()) { if (layoutSettings.getBandByType()) {
// sortedStripeNodes.stream() sortedEventNodes.stream()
// .collect(Collectors.groupingBy(EventStripeNode::getEventType)).values() .collect(Collectors.groupingBy(EventNodeBase<?>::getEventType)).values()
// .forEach(inputNodes -> maxY.set(layoutEventBundleNodes(inputNodes, maxY.get()))); .forEach(inputNodes -> maxY.set(layoutEventBundleNodes(inputNodes, maxY.get())));
// } else { } else {
maxY.set(layoutEventBundleNodes(sortedEventNodes.sorted(Comparator.comparing(EventNodeBase::getStartMillis)), 0)); maxY.set(layoutEventBundleNodes(sortedEventNodes.sorted(Comparator.comparing(EventNodeBase<?>::getStartMillis)), 0));
// } }
setCursor(null); setCursor(null);
} }
@ -326,6 +336,7 @@ public final class PinnedEventsChart extends XYChart<DateTime, TimeLineEvent> im
public synchronized void setVScroll(double vScrollValue) { public synchronized void setVScroll(double vScrollValue) {
nodeGroup.setTranslateY(-vScrollValue); nodeGroup.setTranslateY(-vScrollValue);
} }
public ReadOnlyDoubleProperty maxVScrollProperty() { public ReadOnlyDoubleProperty maxVScrollProperty() {
return maxY.getReadOnlyProperty(); return maxY.getReadOnlyProperty();
} }
@ -402,8 +413,8 @@ public final class PinnedEventsChart extends XYChart<DateTime, TimeLineEvent> im
eventNode.setVisible(true); eventNode.setVisible(true);
eventNode.setManaged(true); eventNode.setManaged(true);
//apply advanced layout description visibility options //apply advanced layout description visibility options
eventNode.setDescriptionVisibility(DescriptionVisibility.SHOWN); eventNode.setDescriptionVisibility(layoutSettings.getDescrVisibility());
eventNode.setMaxDescriptionWidth(USE_PREF_SIZE); eventNode.setMaxDescriptionWidth(descriptionWidth);
//do recursive layout //do recursive layout
eventNode.layoutChildren(); eventNode.layoutChildren();

View File

@ -127,21 +127,7 @@ final class SingleEventNode extends EventNodeBase<SingleEvent> {
chart.requestTimelineChartLayout(); chart.requestTimelineChartLayout();
} }
/**
* apply the 'effect' to visually indicate highlighted nodes
*
* @param applied true to apply the highlight 'effect', false to remove it
*/
@Override
public synchronized void applyHighlightEffect(boolean applied) {
if (applied) {
descrLabel.setStyle("-fx-font-weight: bold;"); // NON-NLS
setBackground(highlightedBackground);
} else {
descrLabel.setStyle("-fx-font-weight: normal;"); // NON-NLS
setBackground(defaultBackground);
}
}
/** /**
* @param w the maximum width the description label should have * @param w the maximum width the description label should have