19 package org.sleuthkit.autopsy.timeline.ui.detailview;
 
   21 import java.util.List;
 
   23 import javafx.application.Platform;
 
   24 import javafx.beans.binding.Bindings;
 
   25 import javafx.beans.property.ReadOnlyObjectProperty;
 
   26 import javafx.beans.property.ReadOnlyObjectWrapper;
 
   27 import javafx.collections.FXCollections;
 
   28 import javafx.collections.ObservableList;
 
   29 import javafx.event.EventHandler;
 
   30 import javafx.geometry.Insets;
 
   31 import javafx.geometry.Orientation;
 
   32 import javafx.geometry.Pos;
 
   33 import javafx.scene.input.MouseEvent;
 
   34 import javafx.scene.layout.CornerRadii;
 
   35 import javafx.scene.layout.Pane;
 
   36 import org.joda.time.DateTime;
 
   37 import org.openide.util.NbBundle;
 
   45 @NbBundle.Messages({
"EventBundleNodeBase.toolTip.loading=loading..."})
 
   46 abstract class MultiEventNodeBase< BundleType extends MultiEvent<ParentType>, ParentType extends MultiEvent<BundleType>, ParentNodeType extends MultiEventNodeBase<
 
   47         ParentType, BundleType, ?>> extends EventNodeBase<BundleType> {
 
   49     static final CornerRadii CORNER_RADII_3 = 
new CornerRadii(3);
 
   50     static final CornerRadii CORNER_RADII_1 = 
new CornerRadii(1);
 
   52     final ObservableList<EventNodeBase<?>> subNodes = FXCollections.observableArrayList();
 
   53     final Pane subNodePane = 
new Pane();
 
   55     private final ReadOnlyObjectWrapper<TimelineLevelOfDetail> descLOD = 
new ReadOnlyObjectWrapper<>();
 
   57     MultiEventNodeBase(DetailsChartLane<?> chartLane, BundleType event, ParentNodeType parentNode) {
 
   58         super(event, parentNode, chartLane);
 
   59         setDescriptionLOD(event.getDescriptionLevel());
 
   61         setAlignment(Pos.TOP_LEFT);
 
   62         setMaxWidth(USE_PREF_SIZE);
 
   63         infoHBox.setMaxWidth(USE_PREF_SIZE);
 
   64         subNodePane.setPrefWidth(USE_COMPUTED_SIZE);
 
   65         subNodePane.setMinWidth(USE_PREF_SIZE);
 
   66         subNodePane.setMaxWidth(USE_PREF_SIZE);
 
   71         heightProperty().addListener(heightProp -> chartLane.requestLayout());
 
   73                 -> setLayoutX(chartLane.getXAxis().getDisplayPosition(
new DateTime(event.getStartMillis())) - getLayoutXCompensation())
 
   77         infoHBox.setPadding(
new Insets(2, 3, 2, 3));
 
   78         infoHBox.setAlignment(Pos.TOP_LEFT);
 
   80         Bindings.bindContent(subNodePane.getChildren(), subNodes);
 
   83     public ReadOnlyObjectProperty<TimelineLevelOfDetail> descriptionLoDProperty() {
 
   84         return descLOD.getReadOnlyProperty();
 
   87     final TimelineLevelOfDetail getDescriptionLevel() {
 
   94     final void setDescriptionLOD(
final TimelineLevelOfDetail descriptionLoD) {
 
   95         descLOD.set(descriptionLoD);
 
   99     public List<EventNodeBase<?>> getSubNodes() {
 
  104     final String getDescription() {
 
  105         return getEvent().getDescription();
 
  109     final Set<Long> getEventIDs() {
 
  110         return getEvent().getEventIDs();
 
  114     public Orientation getContentBias() {
 
  115         return Orientation.HORIZONTAL;
 
  119     protected void layoutChildren() {
 
  120         chartLane.layoutEventBundleNodes(subNodes, 0);
 
  121         super.layoutChildren();
 
  124     abstract EventNodeBase<?> createChildNode(ParentType rawChild) 
throws TskCoreException;
 
  127     abstract EventHandler<MouseEvent> getDoubleClickHandler();