Autopsy  4.19.3
Graphical digital forensics platform for The Sleuth Kit and other tools.
ImageTag.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 
22 // TODO: See JIRA-6693
23 //import com.sun.javafx.event.EventDispatchChainImpl;
24 import java.beans.PropertyChangeEvent;
25 import java.beans.PropertyChangeListener;
26 import java.beans.PropertyChangeSupport;
27 import javafx.collections.ListChangeListener;
28 import javafx.scene.Cursor;
29 import javafx.scene.Group;
30 import javafx.scene.Node;
31 import javafx.scene.control.Tooltip;
32 import javafx.scene.image.ImageView;
33 import javafx.scene.input.MouseEvent;
34 import javafx.scene.paint.Color;
35 import javafx.scene.shape.Circle;
36 import javafx.scene.shape.Rectangle;
38 
48 public final class ImageTag extends Group {
49 
50  // Used to tell the 8 edit handles to hide if this tag is no longer selected
51 // private final EventDispatchChainImpl ALL_CHILDREN;
52 
53  private final PhysicalTag physicalTag;
54 
55  //Notifies listeners that the user has editted the tag boundaries
56  private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
57 
58  //The underlying presistent tag details that this image tag originates from
60 
61  public ImageTag(ContentViewerTag<ImageTagRegion> contentViewerTag, ImageView image) {
62 // ALL_CHILDREN = new EventDispatchChainImpl();
63  this.appTag = contentViewerTag;
64 
65 // this.getChildren().addListener((ListChangeListener<Node>) change -> {
66 // change.next();
67 // change.getAddedSubList().forEach((node) -> ALL_CHILDREN.append(node.getEventDispatcher()));
68 // });
69 
70  ImageTagRegion details = contentViewerTag.getDetails();
71  physicalTag = new PhysicalTag(details);
72 
73  //Defines the max allowable boundary that a user may drag any given handle.
74  Boundary dragBoundary = (x, y) -> {
75  double boundingX = image.getX();
76  double boundingY = image.getY();
77  double width = image.getImage().getWidth();
78  double height = image.getImage().getHeight();
79 
80  return x > boundingX + details.getStrokeThickness() / 2
81  && x < boundingX + width - details.getStrokeThickness() / 2
82  && y > boundingY + details.getStrokeThickness() / 2
83  && y < boundingY + height - details.getStrokeThickness() / 2;
84  };
85 
86  EditHandle bottomLeft = new EditHandle(physicalTag)
87  .setPosition(Position.bottom(), Position.left())
88  .setDrag(dragBoundary, Draggable.bottom(), Draggable.left());
89 
90  EditHandle bottomRight = new EditHandle(physicalTag)
91  .setPosition(Position.bottom(), Position.right())
92  .setDrag(dragBoundary, Draggable.bottom(), Draggable.right());
93 
94  EditHandle topLeft = new EditHandle(physicalTag)
95  .setPosition(Position.top(), Position.left())
96  .setDrag(dragBoundary, Draggable.top(), Draggable.left());
97 
98  EditHandle topRight = new EditHandle(physicalTag)
99  .setPosition(Position.top(), Position.right())
100  .setDrag(dragBoundary, Draggable.top(), Draggable.right());
101 
102  EditHandle bottomMiddle = new EditHandle(physicalTag)
103  .setPosition(Position.bottom(), Position.xMiddle())
104  .setDrag(dragBoundary, Draggable.bottom());
105 
106  EditHandle topMiddle = new EditHandle(physicalTag)
107  .setPosition(Position.top(), Position.xMiddle())
108  .setDrag(dragBoundary, Draggable.top());
109 
110  EditHandle rightMiddle = new EditHandle(physicalTag)
111  .setPosition(Position.right(), Position.yMiddle())
112  .setDrag(dragBoundary, Draggable.right());
113 
114  EditHandle leftMiddle = new EditHandle(physicalTag)
115  .setPosition(Position.left(), Position.yMiddle())
116  .setDrag(dragBoundary, Draggable.left());
117 
118  //The "logical" tag is the Group
119  this.getChildren().addAll(physicalTag, bottomLeft, bottomRight, topLeft,
120  topRight, bottomMiddle, topMiddle, rightMiddle, leftMiddle);
121 
122  Tooltip.install(this, new Tooltip(contentViewerTag.getContentTag()
123  .getName().getDisplayName()));
124 
125 // this.addEventHandler(ImageTagControls.NOT_FOCUSED, event -> ALL_CHILDREN.dispatchEvent(event));
126 // this.addEventHandler(ImageTagControls.FOCUSED, event -> ALL_CHILDREN.dispatchEvent(event));
127  }
128 
135  public void subscribeToEditEvents(PropertyChangeListener listener) {
136  pcs.addPropertyChangeListener(listener);
137  }
138 
139  public double getWidth() {
140  return physicalTag.getWidth();
141  }
142 
143  public double getHeight() {
144  return physicalTag.getHeight();
145  }
146 
153  return appTag;
154  }
155 
159  class PhysicalTag extends Rectangle {
160 
161  public PhysicalTag(ImageTagRegion details) {
162  this.setStroke(Color.RED);
163  this.setFill(Color.RED.deriveColor(0, 0, 0, 0));
164  this.setStrokeWidth(details.getStrokeThickness());
165 
166  setX(details.getX());
167  setY(details.getY());
168  setWidth(details.getWidth());
169  setHeight(details.getHeight());
170 
171  this.addEventHandler(ImageTagControls.NOT_FOCUSED, event -> this.setOpacity(1));
172  this.addEventHandler(ImageTagControls.FOCUSED, event -> this.setOpacity(0.5));
173  }
174 
180  public ImageTagRegion getState() {
181  return new ImageTagRegion()
182  .setX(this.getX())
183  .setY(this.getY())
184  .setWidth(this.getWidth())
185  .setHeight(this.getHeight())
186  .setStrokeThickness(this.getStrokeWidth());
187  }
188  }
189 
193  class EditHandle extends Circle {
194 
195  private final PhysicalTag parent;
196 
197  public EditHandle(PhysicalTag parent) {
198  this.setVisible(false);
199 
200  //Hide when the tag is not selected.
201  this.addEventHandler(ImageTagControls.NOT_FOCUSED, event -> this.setVisible(false));
202  this.addEventHandler(ImageTagControls.FOCUSED, event -> this.setVisible(true));
203 
204  this.setRadius(parent.getStrokeWidth());
205  this.setFill(parent.getStroke());
206 
207  this.setOnDragDetected(event -> {
208  this.getParent().setCursor(Cursor.CLOSED_HAND);
209  });
210 
211  this.setOnMouseReleased(event -> {
212  this.getParent().setCursor(Cursor.DEFAULT);
213  pcs.firePropertyChange(new PropertyChangeEvent(this, "Tag Edit", null, parent.getState()));
214  });
215 
216  this.parent = parent;
217  }
218 
225  public EditHandle setPosition(Position... vals) {
226  for (Position pos : vals) {
227  parent.widthProperty().addListener((obs, oldVal, newVal) -> pos.set(parent, this));
228  parent.heightProperty().addListener((obs, oldVal, newVal) -> pos.set(parent, this));
229  pos.set(parent, this);
230  }
231  return this;
232  }
233 
241  public EditHandle setDrag(Boundary bounds, Draggable... vals) {
242  this.setOnMouseDragged((event) -> {
243  for (Draggable drag : vals) {
244  drag.perform(parent, event, bounds);
245  }
246  });
247  return this;
248  }
249  }
250 
255  static interface Position {
256 
257  void set(PhysicalTag parent, Circle knob);
258 
259  static Position left() {
260  return (parent, knob) -> knob.centerXProperty().bind(parent.xProperty());
261  }
262 
263  static Position right() {
264  return (parent, knob) -> knob.centerXProperty().bind(parent.xProperty().add(parent.getWidth()));
265  }
266 
267  static Position top() {
268  return (parent, knob) -> knob.centerYProperty().bind(parent.yProperty());
269  }
270 
271  static Position bottom() {
272  return (parent, knob) -> knob.centerYProperty().bind(parent.yProperty().add(parent.getHeight()));
273  }
274 
275  static Position xMiddle() {
276  return (parent, knob) -> knob.centerXProperty().bind(parent.xProperty().add(parent.getWidth() / 2));
277  }
278 
279  static Position yMiddle() {
280  return (parent, knob) -> knob.centerYProperty().bind(parent.yProperty().add(parent.getHeight() / 2));
281  }
282  }
283 
287  @FunctionalInterface
288  static interface Boundary {
289 
290  boolean isPointInBounds(double x, double y);
291  }
292 
297  static interface Draggable {
298 
299  void perform(PhysicalTag parent, MouseEvent event, Boundary b);
300 
301  static Draggable bottom() {
302  return (parent, event, bounds) -> {
303  if (!bounds.isPointInBounds(event.getX(), event.getY())) {
304  return;
305  }
306 
307  double deltaY = event.getY() - parent.getY();
308  if (deltaY > 0) {
309  parent.setHeight(deltaY);
310  }
311  };
312  }
313 
314  static Draggable top() {
315  return (parent, event, bounds) -> {
316  if (!bounds.isPointInBounds(event.getX(), event.getY())) {
317  return;
318  }
319 
320  double deltaY = parent.getY() + parent.getHeight() - event.getY();
321  if (deltaY < parent.getY() + parent.getHeight() && deltaY > 0) {
322  parent.setHeight(deltaY);
323  parent.setY(event.getY());
324  }
325  };
326  }
327 
328  static Draggable left() {
329  return (parent, event, bounds) -> {
330  if (!bounds.isPointInBounds(event.getX(), event.getY())) {
331  return;
332  }
333 
334  double deltaX = parent.getX() + parent.getWidth() - event.getX();
335  if (deltaX < parent.getX() + parent.getWidth() && deltaX > 0) {
336  parent.setWidth(deltaX);
337  parent.setX(event.getX());
338  }
339  };
340  }
341 
342  static Draggable right() {
343  return (parent, event, bounds) -> {
344  if (!bounds.isPointInBounds(event.getX(), event.getY())) {
345  return;
346  }
347 
348  double deltaX = event.getX() - parent.getX();
349  if (deltaX > 0) {
350  parent.setWidth(deltaX);
351  }
352  };
353  }
354  }
355 }
ContentViewerTag< ImageTagRegion > getContentViewerTag()
Definition: ImageTag.java:152
final ContentViewerTag< ImageTagRegion > appTag
Definition: ImageTag.java:59
ImageTag(ContentViewerTag< ImageTagRegion > contentViewerTag, ImageView image)
Definition: ImageTag.java:61
void subscribeToEditEvents(PropertyChangeListener listener)
Definition: ImageTag.java:135

Copyright © 2012-2022 Basis Technology. Generated on: Tue Jun 27 2023
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.