Merge pull request #912 from millmanorama/timeline-3.1.1_fixes

don't expand type filters by default
This commit is contained in:
Richard Cordovano 2014-10-22 14:55:54 -04:00
commit cf230c42bc
9 changed files with 71 additions and 41 deletions

View File

@ -59,6 +59,9 @@ public class RootEventType implements EventType {
private static class RootEventTypeHolder { private static class RootEventTypeHolder {
private static final RootEventType INSTANCE = new RootEventType(); private static final RootEventType INSTANCE = new RootEventType();
private RootEventTypeHolder() {
}
} }
@Override @Override
@ -76,8 +79,6 @@ public class RootEventType implements EventType {
return Arrays.asList(BaseTypes.values()); return Arrays.asList(BaseTypes.values());
} }
@Override @Override
public String getIconBase() { public String getIconBase() {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.

View File

@ -13,7 +13,6 @@ import javafx.beans.property.SimpleBooleanProperty;
public abstract class AbstractFilter implements Filter { public abstract class AbstractFilter implements Filter {
private final SimpleBooleanProperty active = new SimpleBooleanProperty(true); private final SimpleBooleanProperty active = new SimpleBooleanProperty(true);
private final SimpleBooleanProperty disabled = new SimpleBooleanProperty(false); private final SimpleBooleanProperty disabled = new SimpleBooleanProperty(false);
@Override @Override
@ -42,7 +41,7 @@ public abstract class AbstractFilter implements Filter {
} }
@Override @Override
public boolean isdisabled() { public boolean isDisabled() {
return disabled.get(); return disabled.get();
} }
@ -50,4 +49,7 @@ public abstract class AbstractFilter implements Filter {
public String getStringCheckBox() { public String getStringCheckBox() {
return "[" + (isActive() ? "x" : " ") + "]"; return "[" + (isActive() ? "x" : " ") + "]";
} }
} }

View File

@ -76,6 +76,5 @@ public interface Filter {
SimpleBooleanProperty getDisabledProperty(); SimpleBooleanProperty getDisabledProperty();
boolean isdisabled(); boolean isDisabled();
} }

View File

@ -37,7 +37,7 @@ public class HideKnownFilter extends AbstractFilter {
public HideKnownFilter copyOf() { public HideKnownFilter copyOf() {
HideKnownFilter hideKnownFilter = new HideKnownFilter(); HideKnownFilter hideKnownFilter = new HideKnownFilter();
hideKnownFilter.setActive(isActive()); hideKnownFilter.setActive(isActive());
hideKnownFilter.setDisabled(isdisabled()); hideKnownFilter.setDisabled(isDisabled());
return hideKnownFilter; return hideKnownFilter;
} }

View File

@ -10,15 +10,15 @@ import javafx.collections.ObservableList;
/** Intersection(And) filter */ /** Intersection(And) filter */
public class IntersectionFilter extends CompoundFilter { public class IntersectionFilter extends CompoundFilter {
public IntersectionFilter(ObservableList<Filter> subFilters) { public IntersectionFilter(ObservableList<Filter> subFilters) {
super(subFilters); super(subFilters);
} }
public IntersectionFilter() { public IntersectionFilter() {
super(FXCollections.<Filter>observableArrayList()); super(FXCollections.<Filter>observableArrayList());
} }
@Override @Override
public IntersectionFilter copyOf() { public IntersectionFilter copyOf() {
IntersectionFilter filter = new IntersectionFilter(FXCollections.observableArrayList( IntersectionFilter filter = new IntersectionFilter(FXCollections.observableArrayList(
@ -26,20 +26,22 @@ public class IntersectionFilter extends CompoundFilter {
.map(Filter::copyOf) .map(Filter::copyOf)
.collect(Collectors.toList()))); .collect(Collectors.toList())));
filter.setActive(isActive()); filter.setActive(isActive());
filter.setDisabled(isdisabled()); filter.setDisabled(isDisabled());
return filter; return filter;
} }
@Override @Override
public String getDisplayName() { public String getDisplayName() {
return "Intersection"; return "Intersection" + getSubFilters().stream()
.map(Filter::getDisplayName)
.collect(Collectors.joining(",", "[", "]"));
} }
@Override @Override
public String getHTMLReportString() { public String getHTMLReportString() {
return getSubFilters().stream().filter(Filter::isActive).map(Filter::getHTMLReportString).collect(Collectors.joining("</li><li>", "<ul><li>", "</li></ul>")); return getSubFilters().stream().filter(Filter::isActive).map(Filter::getHTMLReportString).collect(Collectors.joining("</li><li>", "<ul><li>", "</li></ul>"));
} }
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (obj == null) { if (obj == null) {
@ -49,11 +51,11 @@ public class IntersectionFilter extends CompoundFilter {
return false; return false;
} }
final IntersectionFilter other = (IntersectionFilter) obj; final IntersectionFilter other = (IntersectionFilter) obj;
if (isActive() != other.isActive()) { if (isActive() != other.isActive()) {
return false; return false;
} }
for (int i = 0; i < getSubFilters().size(); i++) { for (int i = 0; i < getSubFilters().size(); i++) {
if (getSubFilters().get(i).equals(other.getSubFilters().get(i)) == false) { if (getSubFilters().get(i).equals(other.getSubFilters().get(i)) == false) {
return false; return false;
@ -61,7 +63,7 @@ public class IntersectionFilter extends CompoundFilter {
} }
return true; return true;
} }
@Override @Override
public int hashCode() { public int hashCode() {
int hash = 7; int hash = 7;

View File

@ -56,7 +56,7 @@ public class TextFilter extends AbstractFilter {
synchronized public TextFilter copyOf() { synchronized public TextFilter copyOf() {
TextFilter textFilter = new TextFilter(getText()); TextFilter textFilter = new TextFilter(getText());
textFilter.setActive(isActive()); textFilter.setActive(isActive());
textFilter.setDisabled(isdisabled()); textFilter.setDisabled(isDisabled());
return textFilter; return textFilter;
} }

View File

@ -42,7 +42,7 @@ public class TypeFilter extends UnionFilter {
private TypeFilter(EventType et, boolean recursive) { private TypeFilter(EventType et, boolean recursive) {
super(FXCollections.observableArrayList()); super(FXCollections.observableArrayList());
this.eventType = et; this.eventType = et;
if (recursive) { // add subfilters for each subtype if (recursive) { // add subfilters for each subtype
for (EventType subType : et.getSubTypes()) { for (EventType subType : et.getSubTypes()) {
this.getSubFilters().add(new TypeFilter(subType)); this.getSubFilters().add(new TypeFilter(subType));
@ -57,11 +57,11 @@ public class TypeFilter extends UnionFilter {
public TypeFilter(EventType et) { public TypeFilter(EventType et) {
this(et, true); this(et, true);
} }
public EventType getEventType() { public EventType getEventType() {
return eventType; return eventType;
} }
@Override @Override
public String getDisplayName() { public String getDisplayName() {
return eventType == RootEventType.getInstance() ? "Event Type Filter" : eventType.getDisplayName(); return eventType == RootEventType.getInstance() ? "Event Type Filter" : eventType.getDisplayName();
@ -76,21 +76,21 @@ public class TypeFilter extends UnionFilter {
public Image getFXImage() { public Image getFXImage() {
return eventType.getFXImage(); return eventType.getFXImage();
} }
@Override @Override
public TypeFilter copyOf() { public TypeFilter copyOf() {
//make a nonrecursive copy of this filter //make a nonrecursive copy of this filter
final TypeFilter typeFilter = new TypeFilter(eventType, false); final TypeFilter typeFilter = new TypeFilter(eventType, false);
typeFilter.setActive(isActive()); typeFilter.setActive(isActive());
typeFilter.setDisabled(isdisabled()); typeFilter.setDisabled(isDisabled());
//add a copy of each subfilter //add a copy of each subfilter
this.getSubFilters().forEach((Filter t) -> { this.getSubFilters().forEach((Filter t) -> {
typeFilter.getSubFilters().add(t.copyOf()); typeFilter.getSubFilters().add(t.copyOf());
}); });
return typeFilter; return typeFilter;
} }
@Override @Override
public String getHTMLReportString() { public String getHTMLReportString() {
String string = getEventType().getDisplayName() + getStringCheckBox(); String string = getEventType().getDisplayName() + getStringCheckBox();
@ -99,7 +99,7 @@ public class TypeFilter extends UnionFilter {
} }
return string; return string;
} }
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (obj == null) { if (obj == null) {
@ -109,15 +109,15 @@ public class TypeFilter extends UnionFilter {
return false; return false;
} }
final TypeFilter other = (TypeFilter) obj; final TypeFilter other = (TypeFilter) obj;
if (isActive() != other.isActive()) { if (isActive() != other.isActive()) {
return false; return false;
} }
if (this.eventType != other.eventType) { if (this.eventType != other.eventType) {
return false; return false;
} }
for (int i = 0; i < getSubFilters().size(); i++) { for (int i = 0; i < getSubFilters().size(); i++) {
if (getSubFilters().get(i).equals(other.getSubFilters().get(i)) == false) { if (getSubFilters().get(i).equals(other.getSubFilters().get(i)) == false) {
return false; return false;
@ -125,12 +125,12 @@ public class TypeFilter extends UnionFilter {
} }
return true; return true;
} }
@Override @Override
public int hashCode() { public int hashCode() {
int hash = 7; int hash = 7;
hash = 67 * hash + Objects.hashCode(this.eventType); hash = 67 * hash + Objects.hashCode(this.eventType);
return hash; return hash;
} }
} }

View File

@ -20,6 +20,9 @@ package org.sleuthkit.autopsy.timeline.ui.filtering;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.beans.Observable; import javafx.beans.Observable;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableMap;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.scene.control.Button; import javafx.scene.control.Button;
import javafx.scene.control.CheckBox; import javafx.scene.control.CheckBox;
@ -67,6 +70,8 @@ public class FilterSetPanel extends BorderPane implements TimeLineView {
private TimeLineController controller; private TimeLineController controller;
private final ObservableMap<String, Boolean> expansionMap = FXCollections.observableHashMap();
@FXML @FXML
void initialize() { void initialize() {
assert applyButton != null : "fx:id=\"applyButton\" was not injected: check your FXML file 'FilterSetPanel.fxml'."; assert applyButton != null : "fx:id=\"applyButton\" was not injected: check your FXML file 'FilterSetPanel.fxml'.";
@ -138,6 +143,7 @@ public class FilterSetPanel extends BorderPane implements TimeLineView {
public FilterSetPanel() { public FilterSetPanel() {
FXMLConstructor.construct(this, "FilterSetPanel.fxml"); FXMLConstructor.construct(this, "FilterSetPanel.fxml");
expansionMap.put("Event Type Filter", Boolean.TRUE);
} }
@Override @Override
@ -152,16 +158,14 @@ public class FilterSetPanel extends BorderPane implements TimeLineView {
@Override @Override
public void setModel(FilteredEventsModel filteredEvents) { public void setModel(FilteredEventsModel filteredEvents) {
this.filteredEvents = filteredEvents; this.filteredEvents = filteredEvents;
refresh(); refresh();
this.filteredEvents.filter().addListener((Observable o) -> { this.filteredEvents.filter().addListener((Observable o) -> {
refresh(); refresh();
}); });
} }
private void refresh() { private void refresh() {
filterTreeTable.setRoot(new FilterTreeItem(this.filteredEvents.filter().get().copyOf())); filterTreeTable.setRoot(new FilterTreeItem(this.filteredEvents.filter().get().copyOf(), expansionMap));
} }
/** /**
@ -171,23 +175,29 @@ public class FilterSetPanel extends BorderPane implements TimeLineView {
private static class FilterCheckBoxCell extends TreeTableCell<AbstractFilter, AbstractFilter> { private static class FilterCheckBoxCell extends TreeTableCell<AbstractFilter, AbstractFilter> {
private final CheckBox checkBox = new CheckBox(); private final CheckBox checkBox = new CheckBox();
private SimpleBooleanProperty activeProperty;
@Override @Override
protected void updateItem(AbstractFilter item, boolean empty) { protected void updateItem(AbstractFilter item, boolean empty) {
super.updateItem(item, empty); super.updateItem(item, empty);
Platform.runLater(() -> { Platform.runLater(() -> {
if (activeProperty != null) {
checkBox.selectedProperty().unbindBidirectional(activeProperty);
}
checkBox.disableProperty().unbind();
if (item == null) { if (item == null) {
setText(null); setText(null);
setGraphic(null); setGraphic(null);
checkBox.selectedProperty().unbind();
checkBox.disableProperty().unbind();
} else { } else {
setText(item.getDisplayName()); setText(item.getDisplayName());
checkBox.selectedProperty().bindBidirectional(item.getActiveProperty()); activeProperty = item.getActiveProperty();
checkBox.selectedProperty().bindBidirectional(activeProperty);
checkBox.disableProperty().bind(item.getDisabledProperty()); checkBox.disableProperty().bind(item.getDisabledProperty());
setGraphic(checkBox); setGraphic(checkBox);
} }
}); });
} }
} }
} }

View File

@ -1,5 +1,8 @@
package org.sleuthkit.autopsy.timeline.ui.filtering; package org.sleuthkit.autopsy.timeline.ui.filtering;
import javafx.beans.Observable;
import javafx.collections.MapChangeListener;
import javafx.collections.ObservableMap;
import javafx.scene.control.TreeItem; import javafx.scene.control.TreeItem;
import org.sleuthkit.autopsy.timeline.filters.CompoundFilter; import org.sleuthkit.autopsy.timeline.filters.CompoundFilter;
import org.sleuthkit.autopsy.timeline.filters.Filter; import org.sleuthkit.autopsy.timeline.filters.Filter;
@ -16,15 +19,28 @@ public class FilterTreeItem extends TreeItem<Filter> {
* be made for them added added to the children of this * be made for them added added to the children of this
* FilterTreeItem * FilterTreeItem
*/ */
public FilterTreeItem(Filter f) { public FilterTreeItem(Filter f, ObservableMap<String, Boolean> expansionMap) {
super(f); super(f);
setExpanded(true);
expansionMap.addListener((MapChangeListener.Change<? extends String, ? extends Boolean> change) -> {
if (change.getKey() == f.getDisplayName()) {
setExpanded(expansionMap.get(change.getKey()));
}
});
if (expansionMap.get(f.getDisplayName()) != null) {
setExpanded(expansionMap.get(f.getDisplayName()));
}
expandedProperty().addListener((Observable observable) -> {
expansionMap.put(f.getDisplayName(), isExpanded());
});
if (f instanceof CompoundFilter) { if (f instanceof CompoundFilter) {
CompoundFilter cf = (CompoundFilter) f; CompoundFilter cf = (CompoundFilter) f;
for (Filter af : cf.getSubFilters()) { for (Filter af : cf.getSubFilters()) {
getChildren().add(new FilterTreeItem(af)); getChildren().add(new FilterTreeItem(af, expansionMap));
} }
} }
} }