Autopsy 4.22.1
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 */
27package org.sleuthkit.autopsy.timeline.ui.detailview;
28
29import java.util.ArrayList;
30import java.util.Collections;
31import java.util.List;
32import javafx.beans.property.ObjectProperty;
33import javafx.beans.property.ObjectPropertyBase;
34import javafx.beans.property.ReadOnlyDoubleProperty;
35import javafx.beans.property.ReadOnlyDoubleWrapper;
36import javafx.scene.chart.Axis;
37import org.joda.time.DateTime;
38import org.joda.time.Interval;
39import org.sleuthkit.autopsy.timeline.TimeLineController;
40import org.sleuthkit.autopsy.timeline.utils.RangeDivision;
41
52final class DateAxis extends Axis<DateTime> {
53
54 private ObjectProperty<DateTime> lowerBound = new ObjectPropertyBase<DateTime>(new DateTime(0)) {
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 RangeDivision rangeDivisionInfo;
89
90 private final ReadOnlyDoubleWrapper tickSpacing = new ReadOnlyDoubleWrapper();
91
92 private final ObjectProperty<DateTime> upperBound = new ObjectPropertyBase<DateTime>(new DateTime(1)) {
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 setTickLabelGap(0);
118 setAutoRanging(false);
119 setTickLabelsVisible(false);
120 setTickLength(0);
121 setTickMarkVisible(false);
122 }
123
124 @Override
125 public double getDisplayPosition(DateTime date) {
126 final double length = -200 + (getSide().isHorizontal() ? getWidth() : getHeight());
127
128 // Get the difference between the max and min date.
129 double diff = getUpperBound().getMillis() - getLowerBound().getMillis();
130
131 // Get the actual range of the visible area.
132 // The minimal date should start at the zero position, that's why we subtract it.
133 double range = length - getZeroPosition();
134
135 // Then get the difference from the actual date to the min date and divide it by the total difference.
136 // We get a value between 0 and 1, if the date is within the min and max date.
137 double d = (date.getMillis() - getLowerBound().getMillis()) / diff;
138
139 // Multiply this percent value with the range and add the zero offset.
140 if (getSide().isVertical()) {
141 return getHeight() - d * range + getZeroPosition();
142 } else {
143 return d * range + getZeroPosition();
144 }
145 }
146
154 public DateTime getLowerBound() {
155 return lowerBound.get();
156 }
157
165 public void setLowerBound(DateTime date) {
166 lowerBound.set(date);
167 }
168
176 public DateTime getUpperBound() {
177 return upperBound.get();
178 }
179
187 public void setUpperBound(DateTime date) {
188 upperBound.set(date);
189 }
190
191 @Override
192 public DateTime getValueForDisplay(double displayPosition) {
193 final double length = - 200 + (getSide().isHorizontal() ? getWidth() : getHeight());
194
195 // Get the difference between the max and min date.
196 double diff = getUpperBound().getMillis() - getLowerBound().getMillis();
197
198 // Get the actual range of the visible area.
199 // The minimal date should start at the zero position, that's why we subtract it.
200 double range = length - getZeroPosition();
201
202 if (getSide().isVertical()) {
203 // displayPosition = getHeight() - ((date - lowerBound) / diff) * range + getZero
204 // date = displayPosition - getZero - getHeight())/range * diff + lowerBound
205 return new DateTime((long) ((displayPosition - getZeroPosition() - getHeight()) / -range * diff + getLowerBound().getMillis()), TimeLineController.getJodaTimeZone());
206 } else {
207 // displayPosition = ((date - lowerBound) / diff) * range + getZero
208 // date = displayPosition - getZero)/range * diff + lowerBound
209 return new DateTime((long) ((displayPosition - getZeroPosition()) / range * diff + getLowerBound().getMillis()), TimeLineController.getJodaTimeZone());
210 }
211 }
212
213 @Override
214 public double getZeroPosition() {
215 return 0;
216 }
217
218 @Override
219 public void invalidateRange(List<DateTime> list) {
220 super.invalidateRange(list);
221
222 Collections.sort(list);
223 if (list.isEmpty()) {
224 minDate = maxDate = new DateTime();
225 } else if (list.size() == 1) {
226 minDate = maxDate = list.get(0);
227 } else if (list.size() > 1) {
228 minDate = list.get(0);
229 maxDate = list.get(list.size() - 1);
230 }
231 }
232
233 @Override
234 public boolean isValueOnAxis(DateTime date) {
235 return date.getMillis() > getLowerBound().getMillis() && date.getMillis() < getUpperBound().getMillis();
236 }
237
238 @Override
239 public double toNumericValue(DateTime date) {
240 return date.getMillis();
241 }
242
243 @Override
244 public DateTime toRealValue(double v) {
245 return new DateTime((long) v);
246 }
247
248 @Override
249 protected Interval autoRange(double length) {
250 if (isAutoRanging()) {
251 return new Interval(minDate, maxDate);
252 } else {
253 if (getLowerBound() == null || getUpperBound() == null) {
254 return null;
255 }
256 return getRange();
257 }
258 }
259
260 @Override
261 protected List<DateTime> calculateTickValues(double length, Object range) {
262 List<DateTime> tickDates = new ArrayList<>();
263 if (range == null) {
264 return tickDates;
265 }
266 rangeDivisionInfo = RangeDivision.getRangeDivision((Interval) range, TimeLineController.getJodaTimeZone());
267 final DateTime lowerBound1 = getLowerBound();
268 final DateTime upperBound1 = getUpperBound();
269
270 if (lowerBound1 == null || upperBound1 == null) {
271 return tickDates;
272 }
273 DateTime lower = lowerBound1.withZone(TimeLineController.getJodaTimeZone());
274 DateTime upper = upperBound1.withZone(TimeLineController.getJodaTimeZone());
275
276 DateTime current = lower;
277 // Loop as long we exceeded the upper bound.
278 while (current.isBefore(upper)) {
279 tickDates.add(current);
280 current = current.plus(rangeDivisionInfo.getPeriodSize().toUnitPeriod());//.add(interval.interval, interval.amount);
281 }
282
283 // At last add the upper bound.
284 tickDates.add(upper);
285
286 // 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.
287 // Do the same for the upper bound.
288 // If gaps between dates are to small, remove one of them.
289 // 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.
290 if (tickDates.size() > 2) {
291 DateTime secondDate = tickDates.get(1);
292 DateTime thirdDate = tickDates.get(2);
293 DateTime lastDate = tickDates.get(tickDates.size() - 2);
294 DateTime previousLastDate = tickDates.get(tickDates.size() - 3);
295
296 // If the second date is too near by the lower bound, remove it.
297 if (secondDate.getMillis() - lower.getMillis() < (thirdDate.getMillis() - secondDate.getMillis()) / 2) {
298 tickDates.remove(lower);
299 }
300
301 // If difference from the upper bound to the last date is less than the half of the difference of the previous two dates,
302 // we better remove the last date, as it comes to close to the upper bound.
303 if (upper.getMillis() - lastDate.getMillis() < (lastDate.getMillis() - previousLastDate.getMillis()) / 2) {
304 tickDates.remove(lastDate);
305 }
306 }
307
308 if (tickDates.size() >= 2) {
309 tickSpacing.set(getDisplayPosition(tickDates.get(1)) - getDisplayPosition(tickDates.get(0)));
310 } else if (tickDates.size() >= 4) {
311 tickSpacing.set(getDisplayPosition(tickDates.get(2)) - getDisplayPosition(tickDates.get(1)));
312 }
313 return tickDates;
314 }
315
316 @Override
317 protected Interval getRange() {
318 return new Interval(getLowerBound(), getUpperBound());
319 }
320
321 @Override
322 protected String getTickMarkLabel(DateTime date) {
323 return rangeDivisionInfo.getTickFormatter().print(date);
324 }
325
331 @Override
332 protected void setRange(Object range, boolean animating) {
333 rangeDivisionInfo = RangeDivision.getRangeDivision((Interval) range, TimeLineController.getJodaTimeZone());
334 setLowerBound(new DateTime(rangeDivisionInfo.getLowerBound(), TimeLineController.getJodaTimeZone()));
335 setUpperBound(new DateTime(rangeDivisionInfo.getUpperBound(), TimeLineController.getJodaTimeZone()));
336 }
337
338 ReadOnlyDoubleProperty getTickSpacing() {
339 return tickSpacing.getReadOnlyProperty();
340 }
341}

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