Autopsy  4.16.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
ImageTagCreator.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2019 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.contentviewers.imagetagging;
20 
21 import java.beans.PropertyChangeEvent;
22 import java.beans.PropertyChangeListener;
23 import java.beans.PropertyChangeSupport;
24 import javafx.event.EventHandler;
25 import javafx.scene.image.ImageView;
26 import javafx.scene.input.MouseEvent;
27 import javafx.scene.paint.Color;
28 import javafx.scene.shape.Rectangle;
29 
36 public final class ImageTagCreator extends Rectangle {
37 
38  //Origin of the drag event.
39  private double rectangleOriginX, rectangleOriginY;
40 
41  //Rectangle lines should be 1.5% of the image. This level of thickness has
42  //a good balance between visual acuity and loss of selection at the borders
43  //of the image.
44  private final static double LINE_THICKNESS_PERCENT = 1.5;
45  private final double minArea;
46 
47  //Used to update listeners of the new tag boundaries
48  private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
49 
50  private final EventHandler<MouseEvent> mousePressed;
51  private final EventHandler<MouseEvent> mouseDragged;
52  private final EventHandler<MouseEvent> mouseReleased;
53 
54  //Handles the unregistering this ImageTagCreator from mouse press, mouse drag,
55  //and mouse release events of the source image.
56  private final Runnable disconnectRunnable;
57 
64  public ImageTagCreator(ImageView image) {
65  setStroke(Color.RED);
66  setFill(Color.RED.deriveColor(0, 0, 0, 0));
67 
68  //Calculate how many pixels the stroke width should be to guarentee
69  //a consistent % of image consumed by the rectangle border.
70  double min = Math.min(image.getImage().getWidth(), image.getImage().getHeight());
71  double lineThicknessPixels = min * LINE_THICKNESS_PERCENT / 100.0;
72  setStrokeWidth(lineThicknessPixels);
73  minArea = lineThicknessPixels * lineThicknessPixels;
74  setVisible(false);
75 
76  this.mousePressed = (MouseEvent event) -> {
77  if (event.isSecondaryButtonDown()) {
78  return;
79  }
80 
81  //Reset box on new click.
83  rectangleOriginX = event.getX();
84  rectangleOriginY = event.getY();
85 
86  setX(rectangleOriginX);
87  setY(rectangleOriginY);
88  };
89 
90  image.addEventHandler(MouseEvent.MOUSE_PRESSED, this.mousePressed);
91 
92  this.mouseDragged = (MouseEvent event) -> {
93  if (event.isSecondaryButtonDown()) {
94  return;
95  }
96 
97  double currentX = event.getX(), currentY = event.getY();
98 
103  double newX = Math.min(Math.max(currentX, image.getX())
104  + lineThicknessPixels / 2, image.getImage().getWidth() - lineThicknessPixels / 2);
105  double newY = Math.min(Math.max(currentY, image.getY())
106  + lineThicknessPixels / 2, image.getImage().getHeight() - lineThicknessPixels / 2);
107 
108  setVisible(true);
109  double offsetX = newX - rectangleOriginX;
110  if (offsetX < 0) {
111  setX(newX);
112  }
113  setWidth(Math.abs(offsetX));
114 
115  double offsetY = newY - rectangleOriginY;
116  if (offsetY < 0) {
117  setY(newY);
118  }
119  setHeight(Math.abs(offsetY));
120  };
121 
122  image.addEventHandler(MouseEvent.MOUSE_DRAGGED, this.mouseDragged);
123 
124  this.mouseReleased = event -> {
125  //Reject any drags that are too small to count as a meaningful tag.
126  //Meaningful is described as having an area that is visible that is
127  //not consumed by the thickness of the stroke.
128  if ((this.getWidth() - this.getStrokeWidth())
129  * (this.getHeight() - this.getStrokeWidth()) <= minArea) {
130  defaultSettings();
131  return;
132  }
133 
134  this.pcs.firePropertyChange(new PropertyChangeEvent(this, "New Tag",
135  null, new ImageTagRegion()
136  .setX(this.getX())
137  .setY(this.getY())
138  .setWidth(this.getWidth())
139  .setHeight(this.getHeight())
140  .setStrokeThickness(lineThicknessPixels)));
141  };
142 
143  image.addEventHandler(MouseEvent.MOUSE_RELEASED, this.mouseReleased);
144 
145  //Used to remove itself from mouse events on the source image
146  disconnectRunnable = () -> {
147  defaultSettings();
148  image.removeEventHandler(MouseEvent.MOUSE_RELEASED, mouseReleased);
149  image.removeEventHandler(MouseEvent.MOUSE_DRAGGED, mouseDragged);
150  image.removeEventHandler(MouseEvent.MOUSE_PRESSED, mousePressed);
151  };
152  }
153 
161  public void addNewTagListener(PropertyChangeListener listener) {
162  this.pcs.addPropertyChangeListener(listener);
163  }
164 
168  public void disconnect() {
169  this.disconnectRunnable.run();
170  }
171 
175  private void defaultSettings() {
176  setWidth(0);
177  setHeight(0);
178  setVisible(false);
179  }
180 }

Copyright © 2012-2020 Basis Technology. Generated on: Tue Sep 22 2020
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.