do all quickhiding in memory, refector some filter stuff

This commit is contained in:
jmillman 2015-09-30 16:43:08 -04:00
parent 8aa67c830e
commit db03049385
9 changed files with 142 additions and 92 deletions

View File

@ -0,0 +1,74 @@
/**
* *************************************************************************
** This data and information is proprietary to, and a valuable trade secret *
* of, Basis Technology Corp. It is given in confidence by Basis Technology *
* and may only be used as permitted under the license agreement under which *
* it has been distributed, and in no other way. * * Copyright (c) 2014 Basis
* Technology Corp. All rights reserved. * * The technical data and information
* provided herein are provided with * `limited rights', and the computer
* software provided herein is provided * with `restricted rights' as those
* terms are defined in DAR and ASPR * 7-104.9(a).
* *************************************************************************
*/
package org.sleuthkit.autopsy.coreutils;
import java.util.function.Supplier;
import javafx.scene.control.IndexedCell;
import javafx.scene.control.ListCell;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TreeTableCell;
import javafx.scene.control.TreeTableColumn;
/**
* an abstract base class for Cell factories. This class provides the basic
* infrustructure for implementations to be able to create similar cells for
* listview, tableviews or treetableviews via the appropriate method call.
* Implementations need only implement the abstract configureCell method in the
* same spirit as IndexedCell.updateItem
*/
public abstract class AbstractFXCellFactory<X, Y> {
public TreeTableCell< X, Y> forTreeTable(TreeTableColumn< X, Y> column) {
return new AbstractTreeTableCell();
}
public TableCell<X, Y> forTable(TableColumn<X, Y> column) {
return new AbstractTableCell();
}
public ListCell< Y> forList() {
return new AbstractListCell();
}
protected abstract void configureCell(IndexedCell<? extends Y> cell, Y item, boolean empty, Supplier<X> supplier);
private class AbstractTableCell extends TableCell<X, Y> {
@Override
@SuppressWarnings({"unchecked"}) //we know it will be X but there is a flaw in getTableRow return type
protected void updateItem(Y item, boolean empty) {
super.updateItem(item, empty);
configureCell(this, item, empty, (() -> (X) this.getTableRow().getItem()));
}
}
private class AbstractTreeTableCell extends TreeTableCell<X, Y> {
@Override
protected void updateItem(Y item, boolean empty) {
super.updateItem(item, empty);
configureCell(this, item, empty, (() -> this.getTreeTableRow().getItem()));
}
}
private class AbstractListCell extends ListCell< Y> {
@Override
@SuppressWarnings("unchecked") //for a list X should always equal Y
protected void updateItem(Y item, boolean empty) {
super.updateItem(item, empty);
configureCell(this, item, empty, () -> (X) this.getItem());
}
}
}

View File

@ -30,7 +30,7 @@ public abstract class AbstractFilter implements Filter {
private final SimpleBooleanProperty disabled = new SimpleBooleanProperty(false); private final SimpleBooleanProperty disabled = new SimpleBooleanProperty(false);
@Override @Override
public SimpleBooleanProperty getSelectedProperty() { public SimpleBooleanProperty selectedProperty() {
return selected; return selected;
} }
@ -64,7 +64,7 @@ public abstract class AbstractFilter implements Filter {
return "[" + (isSelected() ? "x" : " ") + "]"; // NON-NLS return "[" + (isSelected() ? "x" : " ") + "]"; // NON-NLS
} }
final boolean isActive() { public final boolean isActive() {
return isSelected() && (isDisabled() == false); return isSelected() && (isDisabled() == false);
} }
} }

View File

@ -72,7 +72,7 @@ public abstract class CompoundFilter<SubFilterType extends Filter> extends Abstr
private void addSubFilterListeners(List<? extends SubFilterType> newSubfilters) { private void addSubFilterListeners(List<? extends SubFilterType> newSubfilters) {
for (SubFilterType sf : newSubfilters) { for (SubFilterType sf : newSubfilters) {
//if a subfilter changes active state //if a subfilter changes active state
sf.getSelectedProperty().addListener((Observable observable) -> { sf.selectedProperty().addListener((Observable observable) -> {
//set this filter acttive af any of the subfilters are active. //set this filter acttive af any of the subfilters are active.
setSelected(getSubFilters().parallelStream().anyMatch(Filter::isSelected)); setSelected(getSubFilters().parallelStream().anyMatch(Filter::isSelected));
}); });

View File

@ -66,7 +66,7 @@ public interface Filter {
void setSelected(Boolean act); void setSelected(Boolean act);
SimpleBooleanProperty getSelectedProperty(); SimpleBooleanProperty selectedProperty();
/* /*
* TODO: disabled state only affects the state of the checkboxes in the ui * TODO: disabled state only affects the state of the checkboxes in the ui

View File

@ -33,7 +33,7 @@ public class HideKnownFilter extends AbstractFilter {
public HideKnownFilter() { public HideKnownFilter() {
super(); super();
getSelectedProperty().set(false); selectedProperty().set(false);
} }
@Override @Override

View File

@ -79,6 +79,7 @@ import org.sleuthkit.autopsy.timeline.datamodel.EventCluster;
import org.sleuthkit.autopsy.timeline.datamodel.EventStripe; import org.sleuthkit.autopsy.timeline.datamodel.EventStripe;
import org.sleuthkit.autopsy.timeline.datamodel.FilteredEventsModel; import org.sleuthkit.autopsy.timeline.datamodel.FilteredEventsModel;
import org.sleuthkit.autopsy.timeline.datamodel.eventtype.EventType; import org.sleuthkit.autopsy.timeline.datamodel.eventtype.EventType;
import org.sleuthkit.autopsy.timeline.filters.AbstractFilter;
import org.sleuthkit.autopsy.timeline.filters.DescriptionFilter; import org.sleuthkit.autopsy.timeline.filters.DescriptionFilter;
import org.sleuthkit.autopsy.timeline.ui.TimeLineChart; import org.sleuthkit.autopsy.timeline.ui.TimeLineChart;
import org.sleuthkit.autopsy.timeline.zooming.DescriptionLOD; import org.sleuthkit.autopsy.timeline.zooming.DescriptionLOD;
@ -325,6 +326,7 @@ public final class EventDetailChart extends XYChart<DateTime, EventCluster> impl
public synchronized void setController(TimeLineController controller) { public synchronized void setController(TimeLineController controller) {
this.controller = controller; this.controller = controller;
setModel(this.controller.getEventsModel()); setModel(this.controller.getEventsModel());
getController().getQuickHideMasks().addListener(layoutInvalidationListener);
} }
@Override @Override
@ -477,6 +479,7 @@ public final class EventDetailChart extends XYChart<DateTime, EventCluster> impl
for (Series<DateTime, EventCluster> series : sortedSeriesList) { for (Series<DateTime, EventCluster> series : sortedSeriesList) {
hiddenPartition = series.getData().stream().map(Data::getNode).map(EventStripeNode.class::cast) hiddenPartition = series.getData().stream().map(Data::getNode).map(EventStripeNode.class::cast)
.collect(Collectors.partitioningBy(node -> getController().getQuickHideMasks().stream() .collect(Collectors.partitioningBy(node -> getController().getQuickHideMasks().stream()
.filter(AbstractFilter::isActive)
.anyMatch(mask -> mask.getDescription().equals(node.getDescription())))); .anyMatch(mask -> mask.getDescription().equals(node.getDescription()))));
layoutNodesHelper(hiddenPartition.get(true), hiddenPartition.get(false), minY, 0); layoutNodesHelper(hiddenPartition.get(true), hiddenPartition.get(false), minY, 0);
@ -485,6 +488,7 @@ public final class EventDetailChart extends XYChart<DateTime, EventCluster> impl
} else { } else {
hiddenPartition = stripeNodeMap.values().stream() hiddenPartition = stripeNodeMap.values().stream()
.collect(Collectors.partitioningBy(node -> getController().getQuickHideMasks().stream() .collect(Collectors.partitioningBy(node -> getController().getQuickHideMasks().stream()
.filter(AbstractFilter::isActive)
.anyMatch(mask -> mask.getDescription().equals(node.getDescription())))); .anyMatch(mask -> mask.getDescription().equals(node.getDescription()))));
layoutNodesHelper(hiddenPartition.get(true), hiddenPartition.get(false), 0, 0); layoutNodesHelper(hiddenPartition.get(true), hiddenPartition.get(false), 0, 0);
} }
@ -779,20 +783,15 @@ public final class EventDetailChart extends XYChart<DateTime, EventCluster> impl
class HideDescriptionAction extends Action { class HideDescriptionAction extends Action {
/**
*
* @param description the value of description
*/
HideDescriptionAction(String description, DescriptionLOD descriptionLoD) { HideDescriptionAction(String description, DescriptionLOD descriptionLoD) {
super("Hide"); super("Hide");
setGraphic(new ImageView(HIDE)); setGraphic(new ImageView(HIDE));
setEventHandler((ActionEvent t) -> { setEventHandler((ActionEvent t) -> {
getController().getQuickHideMasks().add( DescriptionFilter descriptionFilter = new DescriptionFilter(descriptionLoD,
new DescriptionFilter(descriptionLoD, description,
description, DescriptionFilter.FilterMode.EXCLUDE);
DescriptionFilter.FilterMode.EXCLUDE)); descriptionFilter.selectedProperty().addListener(layoutInvalidationListener);
setRequiresLayout(true); getController().getQuickHideMasks().add(descriptionFilter);
requestChartLayout();
}); });
} }
} }
@ -807,8 +806,6 @@ public final class EventDetailChart extends XYChart<DateTime, EventCluster> impl
getController().getQuickHideMasks().removeIf(descriptionFilter -> getController().getQuickHideMasks().removeIf(descriptionFilter ->
descriptionFilter.getDescriptionLoD().equals(descriptionLoD) descriptionFilter.getDescriptionLoD().equals(descriptionLoD)
&& descriptionFilter.getDescription().equals(description)); && descriptionFilter.getDescription().equals(description));
setRequiresLayout(true);
requestChartLayout();
}); });
} }
} }

View File

@ -1,63 +0,0 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2015 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.timeline.ui.filtering;
import javafx.application.Platform;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.scene.control.CheckBox;
import javafx.scene.control.TreeTableCell;
import org.sleuthkit.autopsy.timeline.TimeLineController;
import org.sleuthkit.autopsy.timeline.filters.AbstractFilter;
/**
* A {@link TreeTableCell} that represents the active state of a
* {@link AbstractFilter} as a checkbox
*/
class FilterCheckBoxCell extends TreeTableCell<AbstractFilter, AbstractFilter> {
private final CheckBox checkBox = new CheckBox();
private SimpleBooleanProperty activeProperty;
private final TimeLineController controller;
FilterCheckBoxCell(TimeLineController controller) {
this.controller = controller;
}
@Override
protected void updateItem(AbstractFilter item, boolean empty) {
super.updateItem(item, empty);
Platform.runLater(() -> {
if (activeProperty != null) {
checkBox.selectedProperty().unbindBidirectional(activeProperty);
}
checkBox.disableProperty().unbind();
if (item == null) {
setText(null);
setGraphic(null);
} else {
setText(item.getDisplayName());
activeProperty = item.getSelectedProperty();
checkBox.selectedProperty().bindBidirectional(activeProperty);
checkBox.disableProperty().bind(item.getDisabledProperty());
setGraphic(checkBox);
}
});
}
}

View File

@ -0,0 +1,42 @@
/*
* 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.filtering;
import java.util.function.Supplier;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.scene.control.CheckBox;
import javafx.scene.control.IndexedCell;
import org.sleuthkit.autopsy.coreutils.AbstractFXCellFactory;
import org.sleuthkit.autopsy.timeline.filters.AbstractFilter;
class FilterCheckBoxCellFactory<X extends AbstractFilter> extends AbstractFXCellFactory<X, X> {
private final CheckBox checkBox = new CheckBox();
private SimpleBooleanProperty selectedProperty;
private SimpleBooleanProperty disabledProperty;
@Override
protected void configureCell(IndexedCell<? extends X> cell, X item, boolean empty, Supplier<X> supplier) {
if (selectedProperty != null) {
checkBox.selectedProperty().unbindBidirectional(selectedProperty);
}
if (disabledProperty != null) {
checkBox.disableProperty().unbindBidirectional(disabledProperty);
}
if (item == null) {
cell.setText(null);
cell.setGraphic(null);
} else {
cell.setText(item.getDisplayName());
selectedProperty = item.selectedProperty();
checkBox.selectedProperty().bindBidirectional(selectedProperty);
disabledProperty = item.getDisabledProperty();
checkBox.disableProperty().bindBidirectional(disabledProperty);
cell.setGraphic(checkBox);
}
}
}

View File

@ -156,7 +156,7 @@ final public class FilterSetPanel extends BorderPane implements TimeLineView {
//configure tree column to show name of filter and checkbox //configure tree column to show name of filter and checkbox
treeColumn.setCellValueFactory(param -> param.getValue().valueProperty()); treeColumn.setCellValueFactory(param -> param.getValue().valueProperty());
treeColumn.setCellFactory(col -> new FilterCheckBoxCell(controller)); treeColumn.setCellFactory(col -> new FilterCheckBoxCellFactory().forTreeTable(col));
//configure legend column to show legend (or othe supplamantal ui, eg, text field for text filter) //configure legend column to show legend (or othe supplamantal ui, eg, text field for text filter)
legendColumn.setCellValueFactory(param -> param.getValue().valueProperty()); legendColumn.setCellValueFactory(param -> param.getValue().valueProperty());
@ -194,18 +194,18 @@ final public class FilterSetPanel extends BorderPane implements TimeLineView {
this.setModel(timeLineController.getEventsModel()); this.setModel(timeLineController.getEventsModel());
hiddenDescriptionsListView.setItems(controller.getQuickHideMasks()); hiddenDescriptionsListView.setItems(controller.getQuickHideMasks());
hiddenDescriptionsListView.setCellFactory((ListView<DescriptionFilter> param) -> new ListCellImpl()); hiddenDescriptionsListView.setCellFactory((ListView<DescriptionFilter> param) -> {
final ListCell<DescriptionFilter> forList = new FilterCheckBoxCellFactory<DescriptionFilter>().forList();
forList.setContextMenu(new ContextMenu(new MenuItem("unhide and remove from list") {
{
setOnAction((ActionEvent event) -> {
controller.getQuickHideMasks().remove(forList.getItem());
});
}
}));
return forList;
});
// .addListener((ListChangeListener.Change<? extends DescriptionFilter> c) -> {
// while (c.next()) {
// DescriptionsExclusionFilter descriptionExclusionFilter = ((RootFilter) filterTreeTable.getRoot().getValue()).getDescriptionsExclusionfilter();
//
// for (DescriptionFilter filter : c.getAddedSubList()) {
// descriptionExclusionFilter.setSelected(true);
// descriptionExclusionFilter.addSubFilter(filter);
// }
// }
// });
controller.viewModeProperty().addListener(observable -> { controller.viewModeProperty().addListener(observable -> {
applyFilters(); applyFilters();
}); });