19 package org.sleuthkit.autopsy.timeline.ui.filtering;
21 import javafx.application.Platform;
22 import javafx.beans.Observable;
23 import javafx.collections.FXCollections;
24 import javafx.collections.ObservableMap;
25 import javafx.event.ActionEvent;
26 import javafx.fxml.FXML;
27 import javafx.scene.control.Button;
28 import javafx.scene.control.ContextMenu;
29 import javafx.scene.control.ListCell;
30 import javafx.scene.control.ListView;
31 import javafx.scene.control.Menu;
32 import javafx.scene.control.MenuItem;
33 import javafx.scene.control.SplitPane;
34 import javafx.scene.control.TitledPane;
35 import javafx.scene.control.TreeItem;
36 import javafx.scene.control.TreeTableColumn;
37 import javafx.scene.control.TreeTableRow;
38 import javafx.scene.control.TreeTableView;
39 import javafx.scene.image.Image;
40 import javafx.scene.image.ImageView;
41 import javafx.scene.layout.BorderPane;
42 import org.controlsfx.control.action.Action;
43 import org.controlsfx.control.action.ActionUtils;
44 import org.openide.util.NbBundle;
65 private static final Image
TICK =
new Image(
"org/sleuthkit/autopsy/timeline/images/tick.png");
77 private TreeTableColumn<AbstractFilter, AbstractFilter>
treeColumn;
80 private TreeTableColumn<AbstractFilter, AbstractFilter>
legendColumn;
93 private final ObservableMap<String, Boolean>
expansionMap = FXCollections.observableHashMap();
98 "Timeline.ui.filtering.menuItem.all=all",
99 "FilterSetPanel.defaultButton.text=Default",
100 "Timeline.ui.filtering.menuItem.none=none",
101 "Timeline.ui.filtering.menuItem.only=only",
102 "Timeline.ui.filtering.menuItem.others=others",
103 "Timeline.ui.filtering.menuItem.select=select",
104 "FilterSetPanel.hiddenDescriptionsListView.unhideAndRm=Unhide and remove from list",
105 "FilterSetPanel.hiddenDescriptionsListView.remove=Remove from list",
106 "FilsetSetPanel.hiddenDescriptionsPane.displayName=Hidden Descriptions"})
108 assert applyButton != null :
"fx:id=\"applyButton\" was not injected: check your FXML file 'FilterSetPanel.fxml'.";
110 ActionUtils.configureButton(
new ApplyFiltersAction(), applyButton);
111 defaultButton.setText(Bundle.FilterSetPanel_defaultButton_text());
112 hiddenDescriptionsPane.setText(Bundle.FilsetSetPanel_hiddenDescriptionsPane_displayName());
114 filterTreeTable.getStylesheets().addAll(
FilterSetPanel.class.getResource(
"FilterTable.css").toExternalForm());
117 filterTreeTable.setRowFactory((TreeTableView<Filter> param) -> {
118 final TreeTableRow<Filter> row =
new TreeTableRow<>();
120 MenuItem all =
new MenuItem(Bundle.Timeline_ui_filtering_menuItem_all());
121 all.setOnAction(e -> {
122 row.getTreeItem().getParent().getChildren().forEach((TreeItem<Filter> t) -> {
123 t.getValue().setSelected(Boolean.TRUE);
126 MenuItem none =
new MenuItem(Bundle.Timeline_ui_filtering_menuItem_none());
127 none.setOnAction(e -> {
128 row.getTreeItem().getParent().getChildren().forEach((TreeItem<Filter> t) -> {
129 t.getValue().setSelected(Boolean.FALSE);
133 MenuItem only =
new MenuItem(Bundle.Timeline_ui_filtering_menuItem_only());
134 only.setOnAction(e -> {
135 row.getTreeItem().getParent().getChildren().forEach((TreeItem<Filter> t) -> {
136 if (t == row.getTreeItem()) {
137 t.getValue().setSelected(Boolean.TRUE);
139 t.getValue().setSelected(Boolean.FALSE);
143 MenuItem others =
new MenuItem(Bundle.Timeline_ui_filtering_menuItem_others());
144 others.setOnAction(e -> {
145 row.getTreeItem().getParent().getChildren().forEach((TreeItem<Filter> t) -> {
146 if (t == row.getTreeItem()) {
147 t.getValue().setSelected(Boolean.FALSE);
149 t.getValue().setSelected(Boolean.TRUE);
153 final ContextMenu rowMenu =
new ContextMenu();
154 Menu select =
new Menu(Bundle.Timeline_ui_filtering_menuItem_select());
155 select.setOnAction(e -> {
156 row.getItem().setSelected(!row.getItem().isSelected());
158 select.getItems().addAll(all, none, only, others);
159 rowMenu.getItems().addAll(select);
160 row.setContextMenu(rowMenu);
166 treeColumn.setCellValueFactory(param -> param.getValue().valueProperty());
167 treeColumn.setCellFactory(col ->
new FilterCheckBoxCellFactory<>().forTreeTable(col));
170 legendColumn.setCellValueFactory(param -> param.getValue().valueProperty());
171 legendColumn.setCellFactory(col ->
new LegendCell(this.controller));
173 expansionMap.put(
new TypeFilter(RootEventType.getInstance()).getDisplayName(),
true);
175 Action defaultFiltersAction =
new ResetFilters(controller);
176 defaultButton.setOnAction(defaultFiltersAction);
177 defaultButton.disableProperty().bind(defaultFiltersAction.disabledProperty());
185 this.filteredEvents.
timeRangeProperty().addListener((Observable observable2) -> {
188 this.filteredEvents.
filterProperty().addListener((Observable o) -> {
194 hiddenDescriptionsListView.setCellFactory((ListView<DescriptionFilter> param) -> {
195 final ListCell<DescriptionFilter> forList =
new FilterCheckBoxCellFactory<DescriptionFilter>().forList();
197 forList.itemProperty().addListener((Observable observable) -> {
198 if (forList.getItem() == null) {
199 forList.setContextMenu(null);
201 forList.setContextMenu(
new ContextMenu(
new MenuItem() {
203 forList.getItem().selectedProperty().addListener((observable, wasSelected, isSelected) -> {
204 configureText(isSelected);
207 configureText(forList.getItem().selectedProperty().get());
208 setOnAction((ActionEvent event) -> {
213 private void configureText(Boolean newValue) {
215 setText(Bundle.FilterSetPanel_hiddenDescriptionsListView_unhideAndRm());
217 setText(Bundle.FilterSetPanel_hiddenDescriptionsListView_remove());
230 position = splitPane.getDividerPositions()[0];
231 splitPane.setDividerPositions(1);
232 hiddenDescriptionsPane.setExpanded(
false);
233 hiddenDescriptionsPane.setCollapsible(
false);
234 hiddenDescriptionsPane.setDisable(
true);
236 splitPane.setDividerPositions(position);
237 hiddenDescriptionsPane.setDisable(
false);
238 hiddenDescriptionsPane.setCollapsible(
true);
239 hiddenDescriptionsPane.setExpanded(
true);
240 hiddenDescriptionsPane.setCollapsible(
false);
255 Platform.runLater(() -> {
260 @NbBundle.Messages({
"FilterSetPanel.applyButton.text=Apply",
261 "FilterSetPanel.applyButton.longText=(Re)Apply filters"})
265 super(Bundle.FilterSetPanel_applyButton_text());
266 setLongText(Bundle.FilterSetPanel_applyButton_longText());
267 setGraphic(
new ImageView(TICK));
268 setEventHandler((ActionEvent t) -> {
275 Platform.runLater(() -> {
ListView< DescriptionFilter > hiddenDescriptionsListView
FilteredEventsModel getEventsModel()
final ObservableMap< String, Boolean > expansionMap
synchronized ReadOnlyObjectProperty< VisualizationMode > viewModeProperty()
FilterSetPanel(TimeLineController controller)
synchronized ReadOnlyObjectProperty< EventTypeZoomLevel > eventTypeZoomProperty()
synchronized ReadOnlyObjectProperty< RootFilter > filterProperty()
synchronized RootFilter getFilter()
FilteredEventsModel filteredEvents
TitledPane hiddenDescriptionsPane
synchronized void pushFilters(RootFilter filter)
TimeLineController controller
synchronized ReadOnlyObjectProperty< DescriptionLoD > descriptionLODProperty()
TreeTableView< Filter > filterTreeTable
static void construct(Node node, String fxmlFileName)
synchronized ReadOnlyObjectProperty< Interval > timeRangeProperty()
TreeTableColumn< AbstractFilter, AbstractFilter > treeColumn
ObservableList< DescriptionFilter > getQuickHideFilters()
TreeTableColumn< AbstractFilter, AbstractFilter > legendColumn