Autopsy  4.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
DateAxis.java
Go to the documentation of this file.
1 /*
2  * The MIT License (MIT)
3  *
4  * Copyright (c) 2013, Christian Schudt
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  *
24  *
25  *
26  */
27 package org.sleuthkit.autopsy.timeline.ui.detailview;
28 
29 import java.util.ArrayList;
30 import java.util.Collections;
31 import java.util.List;
32 import javafx.beans.property.ObjectProperty;
33 import javafx.beans.property.ObjectPropertyBase;
34 import javafx.beans.property.ReadOnlyDoubleProperty;
35 import javafx.beans.property.ReadOnlyDoubleWrapper;
36 import javafx.scene.chart.Axis;
37 import org.joda.time.DateTime;
38 import org.joda.time.Interval;
41 
52 final class DateAxis extends Axis<DateTime> {
53 
54  private ObjectProperty<DateTime> lowerBound = new ObjectPropertyBase<DateTime>() {
55  @Override
56  protected void invalidated() {
57  if (!isAutoRanging()) {
58  invalidateRange();
59  requestAxisLayout();
60  }
61  }
62 
63  @Override
64  public Object getBean() {
65  return DateAxis.this;
66  }
67 
68  @Override
69  public String getName() {
70  return "lowerBound"; // NON-NLS
71  }
72  };
73 
79  private DateTime maxDate;
80 
86  private DateTime minDate;
87 
88  private RangeDivisionInfo rangeDivisionInfo;
89 
90  private final ReadOnlyDoubleWrapper tickSpacing = new ReadOnlyDoubleWrapper();
91 
92  private final ObjectProperty<DateTime> upperBound = new ObjectPropertyBase<DateTime>() {
93  @Override
94  protected void invalidated() {
95  if (!isAutoRanging()) {
96  invalidateRange();
97  requestAxisLayout();
98  }
99  }
100 
101  @Override
102  public Object getBean() {
103  return DateAxis.this;
104  }
105 
106  @Override
107  public String getName() {
108  return "upperBound"; // NON-NLS
109  }
110  };
111 
116  DateAxis() {
117  setAutoRanging(false);
118  }
119 
120  @Override
121  public double getDisplayPosition(DateTime date) {
122  final double length = -200 + (getSide().isHorizontal() ? getWidth() : getHeight());
123 
124  // Get the difference between the max and min date.
125  double diff = getUpperBound().getMillis() - getLowerBound().getMillis();
126 
127  // Get the actual range of the visible area.
128  // The minimal date should start at the zero position, that's why we subtract it.
129  double range = length - getZeroPosition();
130 
131  // Then get the difference from the actual date to the min date and divide it by the total difference.
132  // We get a value between 0 and 1, if the date is within the min and max date.
133  double d = (date.getMillis() - getLowerBound().getMillis()) / diff;
134 
135  // Multiply this percent value with the range and add the zero offset.
136  if (getSide().isVertical()) {
137  return getHeight() - d * range + getZeroPosition();
138  } else {
139  return d * range + getZeroPosition();
140  }
141  }
142 
150  public final DateTime getLowerBound() {
151  return lowerBound.get();
152  }
153 
161  public final void setLowerBound(DateTime date) {
162  lowerBound.set(date);
163  }
164 
172  public final DateTime getUpperBound() {
173  return upperBound.get();
174  }
175 
183  public final void setUpperBound(DateTime date) {
184  upperBound.set(date);
185  }
186 
187  @Override
188  public DateTime getValueForDisplay(double displayPosition) {
189  final double length = - 200 + (getSide().isHorizontal() ? getWidth() : getHeight());
190 
191  // Get the difference between the max and min date.
192  double diff = getUpperBound().getMillis() - getLowerBound().getMillis();
193 
194  // Get the actual range of the visible area.
195  // The minimal date should start at the zero position, that's why we subtract it.
196  double range = length - getZeroPosition();
197 
198  if (getSide().isVertical()) {
199  // displayPosition = getHeight() - ((date - lowerBound) / diff) * range + getZero
200  // date = displayPosition - getZero - getHeight())/range * diff + lowerBound
201  return new DateTime((long) ((displayPosition - getZeroPosition() - getHeight()) / -range * diff + getLowerBound().getMillis()), TimeLineController.getJodaTimeZone());
202  } else {
203  // displayPosition = ((date - lowerBound) / diff) * range + getZero
204  // date = displayPosition - getZero)/range * diff + lowerBound
205  return new DateTime((long) ((displayPosition - getZeroPosition()) / range * diff + getLowerBound().getMillis()), TimeLineController.getJodaTimeZone());
206  }
207  }
208 
209  @Override
210  public double getZeroPosition() {
211  return 0;
212  }
213 
214  @Override
215  public void invalidateRange(List<DateTime> list) {
216  super.invalidateRange(list);
217 
218  Collections.sort(list);
219  if (list.isEmpty()) {
220  minDate = maxDate = new DateTime();
221  } else if (list.size() == 1) {
222  minDate = maxDate = list.get(0);
223  } else if (list.size() > 1) {
224  minDate = list.get(0);
225  maxDate = list.get(list.size() - 1);
226  }
227  }
228 
229  @Override
230  public boolean isValueOnAxis(DateTime date) {
231  return date.getMillis() > getLowerBound().getMillis() && date.getMillis() < getUpperBound().getMillis();
232  }
233 
234  @Override
235  public double toNumericValue(DateTime date) {
236  return date.getMillis();
237  }
238 
239  @Override
240  public DateTime toRealValue(double v) {
241  return new DateTime((long) v);
242  }
243 
244  @Override
245  protected Interval autoRange(double length) {
246  if (isAutoRanging()) {
247  return new Interval(minDate, maxDate);
248  } else {
249  if (getLowerBound() == null || getUpperBound() == null) {
250  return null;
251  }
252  return getRange();
253  }
254  }
255 
256  @Override
257  protected List<DateTime> calculateTickValues(double length, Object range) {
258  List<DateTime> tickDates = new ArrayList<>();
259  if (range == null) {
260  return tickDates;
261  }
262  rangeDivisionInfo = RangeDivisionInfo.getRangeDivisionInfo((Interval) range);
263  final DateTime lowerBound1 = getLowerBound();
264  final DateTime upperBound1 = getUpperBound();
265 
266  if (lowerBound1 == null || upperBound1 == null) {
267  return tickDates;
268  }
269  DateTime lower = lowerBound1.withZone(TimeLineController.getJodaTimeZone());
270  DateTime upper = upperBound1.withZone(TimeLineController.getJodaTimeZone());
271 
272  DateTime current = lower;
273  // Loop as long we exceeded the upper bound.
274  while (current.isBefore(upper)) {
275  tickDates.add(current);
276  current = current.plus(rangeDivisionInfo.getPeriodSize().getPeriod());//.add(interval.interval, interval.amount);
277  }
278 
279  // At last add the upper bound.
280  tickDates.add(upper);
281 
282  // If there are at least three dates, check if the gap between the lower date and the second date is at least half the gap of the second and third date.
283  // Do the same for the upper bound.
284  // If gaps between dates are to small, remove one of them.
285  // This can occur, e.g. if the lower bound is 25.12.2013 and years are shown. Then the next year shown would be 2014 (01.01.2014) which would be too narrow to 25.12.2013.
286  if (tickDates.size() > 2) {
287  DateTime secondDate = tickDates.get(1);
288  DateTime thirdDate = tickDates.get(2);
289  DateTime lastDate = tickDates.get(tickDates.size() - 2);
290  DateTime previousLastDate = tickDates.get(tickDates.size() - 3);
291 
292  // If the second date is too near by the lower bound, remove it.
293  if (secondDate.getMillis() - lower.getMillis() < (thirdDate.getMillis() - secondDate.getMillis()) / 2) {
294  tickDates.remove(lower);
295  }
296 
297  // If difference from the upper bound to the last date is less than the half of the difference of the previous two dates,
298  // we better remove the last date, as it comes to close to the upper bound.
299  if (upper.getMillis() - lastDate.getMillis() < (lastDate.getMillis() - previousLastDate.getMillis()) / 2) {
300  tickDates.remove(lastDate);
301  }
302  }
303 
304  if (tickDates.size() >= 2) {
305  tickSpacing.set(getDisplayPosition(tickDates.get(1)) - getDisplayPosition(tickDates.get(0)));
306  } else if (tickDates.size() >= 4) {
307  tickSpacing.set(getDisplayPosition(tickDates.get(2)) - getDisplayPosition(tickDates.get(1)));
308  }
309  return tickDates;
310  }
311 
312  @Override
313  protected Interval getRange() {
314  return new Interval(getLowerBound(), getUpperBound());
315  }
316 
317  @Override
318  protected String getTickMarkLabel(DateTime date) {
319  return rangeDivisionInfo.getTickFormatter().print(date);
320  }
321 
322  @Override
323  protected void layoutChildren() {
324  super.layoutChildren();
325  }
326 
332  @Override
333  protected void setRange(Object range, boolean animating) {
334  rangeDivisionInfo = RangeDivisionInfo.getRangeDivisionInfo((Interval) range);
335  setLowerBound(new DateTime(rangeDivisionInfo.getLowerBound(), TimeLineController.getJodaTimeZone()));
336  setUpperBound(new DateTime(rangeDivisionInfo.getUpperBound(), TimeLineController.getJodaTimeZone()));
337  }
338 
339  ReadOnlyDoubleProperty getTickSpacing() {
340  return tickSpacing.getReadOnlyProperty();
341  }
342 }
static RangeDivisionInfo getRangeDivisionInfo(Interval timeRange)

Copyright © 2012-2015 Basis Technology. Generated on: Wed Apr 6 2016
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.