Autopsy 4.22.1
Graphical digital forensics platform for The Sleuth Kit and other tools.
ZoomSettingsPane.java
Go to the documentation of this file.
1/*
2 * Autopsy Forensic Browser
3 *
4 * Copyright 2013-18 Basis Technology Corp.
5 * Contact: carrier <at> sleuthkit <dot> org
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19package org.sleuthkit.autopsy.timeline.zooming;
20
21import java.lang.reflect.InvocationTargetException;
22import java.util.function.Function;
23import java.util.logging.Level;
24import javafx.application.Platform;
25import javafx.beans.InvalidationListener;
26import javafx.beans.binding.BooleanBinding;
27import javafx.beans.property.ReadOnlyObjectProperty;
28import javafx.fxml.FXML;
29import javafx.scene.control.Label;
30import javafx.scene.control.Slider;
31import javafx.scene.control.TitledPane;
32import javafx.util.StringConverter;
33import org.controlsfx.control.Notifications;
34import org.openide.util.NbBundle;
35import org.sleuthkit.autopsy.coreutils.Logger;
36import org.sleuthkit.autopsy.timeline.FXMLConstructor;
37import org.sleuthkit.autopsy.timeline.EventsModel;
38import org.sleuthkit.autopsy.timeline.TimeLineController;
39import org.sleuthkit.autopsy.timeline.ViewMode;
40import org.sleuthkit.autopsy.timeline.utils.RangeDivision;
41import org.sleuthkit.datamodel.TimelineEvent;
42import org.sleuthkit.datamodel.TskCoreException;
43import org.sleuthkit.datamodel.TimelineEventType;
44import org.sleuthkit.datamodel.TimelineLevelOfDetail;
45
52public class ZoomSettingsPane extends TitledPane {
53
54 private static final Logger logger = Logger.getLogger(ZoomSettingsPane.class.getName());
55
56 @FXML
57 private Label zoomLabel;
58
59 @FXML
60 private Label descrLODLabel;
61 @FXML
62 private Slider descrLODSlider;
63
64 @FXML
65 private Label typeZoomLabel;
66 @FXML
67 private Slider typeZoomSlider;
68
69 @FXML
70 private Label timeUnitLabel;
71 @FXML
72 private Slider timeUnitSlider;
73
76
82 @SuppressWarnings("this-escape")
84 this.controller = controller;
85 this.filteredEvents = controller.getEventsModel();
86 FXMLConstructor.construct(this, "ZoomSettingsPane.fxml"); // NON-NLS
87 }
88
89 @NbBundle.Messages({
90 "ZoomSettingsPane.descrLODLabel.text=Description Detail:",
91 "ZoomSettingsPane.typeZoomLabel.text=Event Type:",
92 "ZoomSettingsPane.timeUnitLabel.text=Time Units:",
93 "ZoomSettingsPane.zoomLabel.text=Zoom"})
94 public void initialize() {
95 zoomLabel.setText(Bundle.ZoomSettingsPane_zoomLabel_text());
96
97 typeZoomSlider.setMin(1); //don't show ROOT_TYPE
98 typeZoomSlider.setMax(TimelineEventType.HierarchyLevel.values().length - 1);
99 configureSliderListeners(typeZoomSlider,
100 controller::pushEventTypeZoom,
101 filteredEvents.eventTypesHierarchyLevelProperty(),
102 TimelineEventType.HierarchyLevel.class,
103 TimelineEventType.HierarchyLevel::ordinal,
104 Function.identity());
105 typeZoomLabel.setText(Bundle.ZoomSettingsPane_typeZoomLabel_text());
106
107 descrLODSlider.setMax(TimelineLevelOfDetail.values().length - 1);
108 configureSliderListeners(descrLODSlider,
109 controller::pushDescrLOD,
110 filteredEvents.descriptionLODProperty(),
111 TimelineLevelOfDetail.class,
112 TimelineLevelOfDetail::ordinal,
113 Function.identity());
114 descrLODLabel.setText(Bundle.ZoomSettingsPane_descrLODLabel_text());
115 //the description slider is only usefull in the detail view
116 descrLODSlider.disableProperty().bind(controller.viewModeProperty().isEqualTo(ViewMode.COUNTS));
117
125 timeUnitSlider.setMax(TimeUnits.values().length - 2);
126 configureSliderListeners(timeUnitSlider,
127 controller::pushTimeUnit,
128 filteredEvents.timeRangeProperty(),
129 TimeUnits.class,
130 //for the purposes of this slider we want the TimeUnit one bigger than RangeDivision indicates
131 modelTimeRange -> RangeDivision.getRangeDivision(modelTimeRange, TimeLineController.getJodaTimeZone()).getPeriodSize().ordinal() - 1,
132 index -> index + 1); //compensate for the -1 above when mapping to the Enum whose displayName will be shown at index
133 timeUnitLabel.setText(Bundle.ZoomSettingsPane_timeUnitLabel_text());
134
135 //hide the whole panel in list mode
136 BooleanBinding notListMode = controller.viewModeProperty().isNotEqualTo(ViewMode.LIST);
137 visibleProperty().bind(notListMode);
138 managedProperty().bind(notListMode);
139
140 }
141
179 @NbBundle.Messages({"ZoomSettingsPane.sliderChange.errorText=Error responding to slider value change."})
180
181 private <DriverType, EnumType extends Enum<EnumType>> void configureSliderListeners(
182 Slider slider,
183 CheckedConsumer<EnumType> sliderValueConsumer,
184 ReadOnlyObjectProperty<DriverType> modelProperty,
185 Class<EnumType> enumClass,
186 Function<DriverType, Integer> driverValueMapper,
187 Function<Integer, Integer> labelIndexMapper) {
188
189 //set the tick labels to the enum displayNames
190 slider.setLabelFormatter(new EnumSliderLabelFormatter<>(enumClass, labelIndexMapper));
191
192 //make a listener to responds to slider value changes (by updating the view)
193 final InvalidationListener sliderListener = observable -> {
194 //only process event if the slider value is not changing (user has released slider thumb)
195 if (slider.isValueChanging() == false) {
196 //convert slider value to EnumType and pass to consumer
197 EnumType sliderValueAsEnum = enumClass.getEnumConstants()[Math.round((float) slider.getValue())];
198 try {
199 sliderValueConsumer.accept(sliderValueAsEnum);
200 } catch (TskCoreException exception) {
201 logger.log(Level.SEVERE, "Error responding to slider value change.", exception);
202 Notifications.create().owner(getScene().getWindow())
203 .text(Bundle.ZoomSettingsPane_sliderChange_errorText())
204 .showError();
205 }
206 }
207 };
208 //attach listener
209 slider.valueProperty().addListener(sliderListener);
210 slider.valueChangingProperty().addListener(sliderListener);
211
212 //set intial value of slider
213 slider.setValue(driverValueMapper.apply(modelProperty.get()));
214
215 //handle changes in the model property
216 modelProperty.addListener(modelProp -> {
217 //remove listener to avoid circular updates
218 slider.valueProperty().removeListener(sliderListener);
219 slider.valueChangingProperty().removeListener(sliderListener);
220
221 Platform.runLater(() -> {
222 //sync value of slider to model property value
223 slider.setValue(driverValueMapper.apply(modelProperty.get()));
224
225 //reattach listener
226 slider.valueProperty().addListener(sliderListener);
227 slider.valueChangingProperty().addListener(sliderListener);
228 });
229 });
230 }
231
240 static private class EnumSliderLabelFormatter<EnumType extends Enum<EnumType>> extends StringConverter<Double> {
241
245 private final Class<EnumType> clazz;
251 private final Function<Integer, Integer> indexAdjsuter;
252
253 EnumSliderLabelFormatter(Class<EnumType> enumClass, Function<Integer, Integer> indexMapper) {
254 this.clazz = enumClass;
255 this.indexAdjsuter = indexMapper;
256 }
257
258 @Override
259 public String toString(Double dbl) {
260 /* Get the displayName of the EnumType whose index is the given dbl
261 * after it has been narrowed and then adjusted. At one point there
262 * was an interface, DisplayNameProvider, but that was inappropriate
263 * to put in TSK only to support these sliders, so now we use
264 * reflection instead.
265 */
266 EnumType enumConstant = clazz.getEnumConstants()[indexAdjsuter.apply(dbl.intValue())];
267 try {
268 return (String) clazz.getMethod("getDisplayName", (Class<?>[]) null).invoke(enumConstant, (Object[]) null);
269 } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
270 return enumConstant.toString();
271 }
272 }
273
274 @Override
275 public Double fromString(String string) {
276 throw new UnsupportedOperationException("This method should not be used. This EnumSliderLabelFormatter is being used in an unintended way.");
277 }
278 }
279
285 @FunctionalInterface
286 private interface CheckedConsumer<T> {
287
288 void accept(T input) throws TskCoreException;
289 }
290}
synchronized static Logger getLogger(String name)
Definition Logger.java:124
static void construct(Node node, String fxmlFileName)
static RangeDivision getRangeDivision(Interval timeRange, DateTimeZone timeZone)

Copyright © 2012-2024 Sleuth Kit Labs. Generated on:
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.