Autopsy  4.12.0
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  */
19 package org.sleuthkit.autopsy.timeline.zooming;
20 
21 import java.lang.reflect.InvocationTargetException;
22 import java.util.function.Function;
23 import java.util.logging.Level;
24 import javafx.application.Platform;
25 import javafx.beans.InvalidationListener;
26 import javafx.beans.binding.BooleanBinding;
27 import javafx.beans.property.ReadOnlyObjectProperty;
28 import javafx.fxml.FXML;
29 import javafx.scene.control.Label;
30 import javafx.scene.control.Slider;
31 import javafx.scene.control.TitledPane;
32 import javafx.util.StringConverter;
33 import org.controlsfx.control.Notifications;
34 import org.openide.util.NbBundle;
41 import org.sleuthkit.datamodel.TimelineEvent;
42 import org.sleuthkit.datamodel.TskCoreException;
43 import org.sleuthkit.datamodel.TimelineEventType;
44 
51 public class ZoomSettingsPane extends TitledPane {
52 
53  private static final Logger logger = Logger.getLogger(ZoomSettingsPane.class.getName());
54 
55  @FXML
56  private Label zoomLabel;
57 
58  @FXML
59  private Label descrLODLabel;
60  @FXML
61  private Slider descrLODSlider;
62 
63  @FXML
64  private Label typeZoomLabel;
65  @FXML
66  private Slider typeZoomSlider;
67 
68  @FXML
69  private Label timeUnitLabel;
70  @FXML
71  private Slider timeUnitSlider;
72 
75 
81  public ZoomSettingsPane(TimeLineController controller) {
82  this.controller = controller;
83  this.filteredEvents = controller.getEventsModel();
84  FXMLConstructor.construct(this, "ZoomSettingsPane.fxml"); // NON-NLS
85  }
86 
87  @NbBundle.Messages({
88  "ZoomSettingsPane.descrLODLabel.text=Description Detail:",
89  "ZoomSettingsPane.typeZoomLabel.text=Event Type:",
90  "ZoomSettingsPane.timeUnitLabel.text=Time Units:",
91  "ZoomSettingsPane.zoomLabel.text=Zoom"})
92  public void initialize() {
93  zoomLabel.setText(Bundle.ZoomSettingsPane_zoomLabel_text());
94 
95  typeZoomSlider.setMin(1); //don't show ROOT_TYPE
96  typeZoomSlider.setMax(TimelineEventType.TypeLevel.values().length - 1);
97  configureSliderListeners(typeZoomSlider,
98  controller::pushEventTypeZoom,
99  filteredEvents.eventTypeZoomProperty(),
100  TimelineEventType.TypeLevel.class,
101  TimelineEventType.TypeLevel::ordinal,
102  Function.identity());
103  typeZoomLabel.setText(Bundle.ZoomSettingsPane_typeZoomLabel_text());
104 
105  descrLODSlider.setMax(TimelineEvent.DescriptionLevel.values().length - 1);
106  configureSliderListeners(descrLODSlider,
107  controller::pushDescrLOD,
108  filteredEvents.descriptionLODProperty(),
109  TimelineEvent.DescriptionLevel.class,
110  TimelineEvent.DescriptionLevel::ordinal,
111  Function.identity());
112  descrLODLabel.setText(Bundle.ZoomSettingsPane_descrLODLabel_text());
113  //the description slider is only usefull in the detail view
114  descrLODSlider.disableProperty().bind(controller.viewModeProperty().isEqualTo(ViewMode.COUNTS));
115 
123  timeUnitSlider.setMax(TimeUnits.values().length - 2);
124  configureSliderListeners(timeUnitSlider,
125  controller::pushTimeUnit,
126  filteredEvents.timeRangeProperty(),
127  TimeUnits.class,
128  //for the purposes of this slider we want the TimeUnit one bigger than RangeDivision indicates
129  modelTimeRange -> RangeDivision.getRangeDivision(modelTimeRange, TimeLineController.getJodaTimeZone()).getPeriodSize().ordinal() - 1,
130  index -> index + 1); //compensate for the -1 above when mapping to the Enum whose displayName will be shown at index
131  timeUnitLabel.setText(Bundle.ZoomSettingsPane_timeUnitLabel_text());
132 
133  //hide the whole panel in list mode
134  BooleanBinding notListMode = controller.viewModeProperty().isNotEqualTo(ViewMode.LIST);
135  visibleProperty().bind(notListMode);
136  managedProperty().bind(notListMode);
137 
138  }
139 
177  @NbBundle.Messages({"ZoomSettingsPane.sliderChange.errorText=Error responding to slider value change."})
178 
179  private <DriverType, EnumType extends Enum<EnumType>> void configureSliderListeners(
180  Slider slider,
181  CheckedConsumer<EnumType> sliderValueConsumer,
182  ReadOnlyObjectProperty<DriverType> modelProperty,
183  Class<EnumType> enumClass,
184  Function<DriverType, Integer> driverValueMapper,
185  Function<Integer, Integer> labelIndexMapper) {
186 
187  //set the tick labels to the enum displayNames
188  slider.setLabelFormatter(new EnumSliderLabelFormatter<>(enumClass, labelIndexMapper));
189 
190  //make a listener to responds to slider value changes (by updating the view)
191  final InvalidationListener sliderListener = observable -> {
192  //only process event if the slider value is not changing (user has released slider thumb)
193  if (slider.isValueChanging() == false) {
194  //convert slider value to EnumType and pass to consumer
195  EnumType sliderValueAsEnum = enumClass.getEnumConstants()[Math.round((float) slider.getValue())];
196  try {
197  sliderValueConsumer.accept(sliderValueAsEnum);
198  } catch (TskCoreException exception) {
199  logger.log(Level.SEVERE, "Error responding to slider value change.", exception);
200  Notifications.create().owner(getScene().getWindow())
201  .text(Bundle.ZoomSettingsPane_sliderChange_errorText())
202  .showError();
203  }
204  }
205  };
206  //attach listener
207  slider.valueProperty().addListener(sliderListener);
208  slider.valueChangingProperty().addListener(sliderListener);
209 
210  //set intial value of slider
211  slider.setValue(driverValueMapper.apply(modelProperty.get()));
212 
213  //handle changes in the model property
214  modelProperty.addListener(modelProp -> {
215  //remove listener to avoid circular updates
216  slider.valueProperty().removeListener(sliderListener);
217  slider.valueChangingProperty().removeListener(sliderListener);
218 
219  Platform.runLater(() -> {
220  //sync value of slider to model property value
221  slider.setValue(driverValueMapper.apply(modelProperty.get()));
222 
223  //reattach listener
224  slider.valueProperty().addListener(sliderListener);
225  slider.valueChangingProperty().addListener(sliderListener);
226  });
227  });
228  }
229 
238  static private class EnumSliderLabelFormatter<EnumType extends Enum<EnumType>> extends StringConverter<Double> {
239 
243  private final Class<EnumType> clazz;
249  private final Function<Integer, Integer> indexAdjsuter;
250 
251  EnumSliderLabelFormatter(Class<EnumType> enumClass, Function<Integer, Integer> indexMapper) {
252  this.clazz = enumClass;
253  this.indexAdjsuter = indexMapper;
254  }
255 
256  @Override
257  public String toString(Double dbl) {
258  /* Get the displayName of the EnumType whose index is the given dbl
259  * after it has been narrowed and then adjusted. At one point there
260  * was an interface, DisplayNameProvider, but that was inappropriate
261  * to put in TSK only to support these sliders, so now we use
262  * reflection instead.
263  */
264  EnumType enumConstant = clazz.getEnumConstants()[indexAdjsuter.apply(dbl.intValue())];
265  try {
266  return (String) clazz.getMethod("getDisplayName", (Class<?>[]) null).invoke(enumConstant, (Object[]) null);
267  } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
268  return enumConstant.toString();
269  }
270  }
271 
272  @Override
273  public Double fromString(String string) {
274  throw new UnsupportedOperationException("This method should not be used. This EnumSliderLabelFormatter is being used in an unintended way.");
275  }
276  }
277 
283  @FunctionalInterface
284  private interface CheckedConsumer<T> {
285 
286  void accept(T input) throws TskCoreException;
287  }
288 }
synchronized ReadOnlyObjectProperty< TimelineEventType.TypeLevel > eventTypeZoomProperty()
synchronized ReadOnlyObjectProperty< TimelineEvent.DescriptionLevel > descriptionLODProperty()
synchronized ReadOnlyObjectProperty< Interval > timeRangeProperty()
synchronized ReadOnlyObjectProperty< ViewMode > viewModeProperty()
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-2018 Basis Technology. Generated on: Wed Sep 18 2019
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.