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);
@Override
public SimpleBooleanProperty getSelectedProperty() {
public SimpleBooleanProperty selectedProperty() {
return selected;
}
@ -64,7 +64,7 @@ public abstract class AbstractFilter implements Filter {
return "[" + (isSelected() ? "x" : " ") + "]"; // NON-NLS
}
final boolean isActive() {
public final boolean isActive() {
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) {
for (SubFilterType sf : newSubfilters) {
//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.
setSelected(getSubFilters().parallelStream().anyMatch(Filter::isSelected));
});

View File

@ -66,7 +66,7 @@ public interface Filter {
void setSelected(Boolean act);
SimpleBooleanProperty getSelectedProperty();
SimpleBooleanProperty selectedProperty();
/*
* 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() {
super();
getSelectedProperty().set(false);
selectedProperty().set(false);
}
@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.FilteredEventsModel;
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.ui.TimeLineChart;
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) {
this.controller = controller;
setModel(this.controller.getEventsModel());
getController().getQuickHideMasks().addListener(layoutInvalidationListener);
}
@Override
@ -477,6 +479,7 @@ public final class EventDetailChart extends XYChart<DateTime, EventCluster> impl
for (Series<DateTime, EventCluster> series : sortedSeriesList) {
hiddenPartition = series.getData().stream().map(Data::getNode).map(EventStripeNode.class::cast)
.collect(Collectors.partitioningBy(node -> getController().getQuickHideMasks().stream()
.filter(AbstractFilter::isActive)
.anyMatch(mask -> mask.getDescription().equals(node.getDescription()))));
layoutNodesHelper(hiddenPartition.get(true), hiddenPartition.get(false), minY, 0);
@ -485,6 +488,7 @@ public final class EventDetailChart extends XYChart<DateTime, EventCluster> impl
} else {
hiddenPartition = stripeNodeMap.values().stream()
.collect(Collectors.partitioningBy(node -> getController().getQuickHideMasks().stream()
.filter(AbstractFilter::isActive)
.anyMatch(mask -> mask.getDescription().equals(node.getDescription()))));
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 {
/**
*
* @param description the value of description
*/
HideDescriptionAction(String description, DescriptionLOD descriptionLoD) {
super("Hide");
setGraphic(new ImageView(HIDE));
setEventHandler((ActionEvent t) -> {
getController().getQuickHideMasks().add(
new DescriptionFilter(descriptionLoD,
description,
DescriptionFilter.FilterMode.EXCLUDE));
setRequiresLayout(true);
requestChartLayout();
DescriptionFilter descriptionFilter = new DescriptionFilter(descriptionLoD,
description,
DescriptionFilter.FilterMode.EXCLUDE);
descriptionFilter.selectedProperty().addListener(layoutInvalidationListener);
getController().getQuickHideMasks().add(descriptionFilter);
});
}
}
@ -807,8 +806,6 @@ public final class EventDetailChart extends XYChart<DateTime, EventCluster> impl
getController().getQuickHideMasks().removeIf(descriptionFilter ->
descriptionFilter.getDescriptionLoD().equals(descriptionLoD)
&& 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
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)
legendColumn.setCellValueFactory(param -> param.getValue().valueProperty());
@ -194,18 +194,18 @@ final public class FilterSetPanel extends BorderPane implements TimeLineView {
this.setModel(timeLineController.getEventsModel());
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 -> {
applyFilters();
});