19 package org.sleuthkit.autopsy.contentviewers.imagetagging;
21 import com.sun.javafx.event.EventDispatchChainImpl;
22 import java.beans.PropertyChangeEvent;
23 import java.beans.PropertyChangeListener;
24 import java.beans.PropertyChangeSupport;
25 import javafx.collections.ListChangeListener;
26 import javafx.scene.Cursor;
27 import javafx.scene.Group;
28 import javafx.scene.Node;
29 import javafx.scene.control.Tooltip;
30 import javafx.scene.image.ImageView;
31 import javafx.scene.input.MouseEvent;
32 import javafx.scene.paint.Color;
33 import javafx.scene.shape.Circle;
34 import javafx.scene.shape.Rectangle;
54 private final PropertyChangeSupport
pcs =
new PropertyChangeSupport(
this);
60 ALL_CHILDREN =
new EventDispatchChainImpl();
61 this.appTag = contentViewerTag;
63 this.getChildren().addListener((ListChangeListener<Node>) change -> {
65 change.getAddedSubList().forEach((node) -> ALL_CHILDREN.append(node.getEventDispatcher()));
69 physicalTag =
new PhysicalTag(details);
72 Boundary dragBoundary = (x, y) -> {
73 double boundingX = image.getX();
74 double boundingY = image.getY();
75 double width = image.getImage().getWidth();
76 double height = image.getImage().getHeight();
84 EditHandle bottomLeft =
new EditHandle(physicalTag)
85 .setPosition(Position.bottom(), Position.left())
86 .setDrag(dragBoundary, Draggable.bottom(), Draggable.left());
88 EditHandle bottomRight =
new EditHandle(physicalTag)
89 .setPosition(Position.bottom(), Position.right())
90 .setDrag(dragBoundary, Draggable.bottom(), Draggable.right());
92 EditHandle topLeft =
new EditHandle(physicalTag)
93 .setPosition(Position.top(), Position.left())
94 .setDrag(dragBoundary, Draggable.top(), Draggable.left());
96 EditHandle topRight =
new EditHandle(physicalTag)
97 .setPosition(Position.top(), Position.right())
98 .setDrag(dragBoundary, Draggable.top(), Draggable.right());
100 EditHandle bottomMiddle =
new EditHandle(physicalTag)
101 .setPosition(Position.bottom(), Position.xMiddle())
102 .setDrag(dragBoundary, Draggable.bottom());
104 EditHandle topMiddle =
new EditHandle(physicalTag)
105 .setPosition(Position.top(), Position.xMiddle())
106 .setDrag(dragBoundary, Draggable.top());
108 EditHandle rightMiddle =
new EditHandle(physicalTag)
109 .setPosition(Position.right(), Position.yMiddle())
110 .setDrag(dragBoundary, Draggable.right());
112 EditHandle leftMiddle =
new EditHandle(physicalTag)
113 .setPosition(Position.left(), Position.yMiddle())
114 .setDrag(dragBoundary, Draggable.left());
117 this.getChildren().addAll(physicalTag, bottomLeft, bottomRight, topLeft,
118 topRight, bottomMiddle, topMiddle, rightMiddle, leftMiddle);
120 Tooltip.install(
this,
new Tooltip(contentViewerTag.
getContentTag()
121 .getName().getDisplayName()));
134 pcs.addPropertyChangeListener(listener);
138 return physicalTag.getWidth();
142 return physicalTag.getHeight();
157 class PhysicalTag
extends Rectangle {
160 this.setStroke(Color.RED);
161 this.setFill(Color.RED.deriveColor(0, 0, 0, 0));
164 setX(details.
getX());
165 setY(details.
getY());
191 class EditHandle
extends Circle {
193 private final PhysicalTag parent;
195 public EditHandle(PhysicalTag parent) {
196 this.setVisible(
false);
199 this.addEventHandler(ImageTagControls.NOT_FOCUSED, event ->
this.setVisible(
false));
200 this.addEventHandler(ImageTagControls.FOCUSED, event ->
this.setVisible(
true));
202 this.setRadius(parent.getStrokeWidth());
203 this.setFill(parent.getStroke());
205 this.setOnDragDetected(event -> {
206 this.getParent().setCursor(Cursor.CLOSED_HAND);
209 this.setOnMouseReleased(event -> {
210 this.getParent().setCursor(Cursor.DEFAULT);
211 pcs.firePropertyChange(
new PropertyChangeEvent(
this,
"Tag Edit", null, parent.getState()));
214 this.parent = parent;
223 public EditHandle setPosition(Position... vals) {
224 for (Position pos : vals) {
225 parent.widthProperty().addListener((obs, oldVal, newVal) -> pos.set(parent,
this));
226 parent.heightProperty().addListener((obs, oldVal, newVal) -> pos.set(parent,
this));
227 pos.set(parent,
this);
239 public EditHandle setDrag(Boundary bounds, Draggable... vals) {
240 this.setOnMouseDragged((event) -> {
241 for (Draggable drag : vals) {
242 drag.perform(parent, event, bounds);
253 static interface Position {
255 void set(PhysicalTag parent, Circle knob);
257 static Position left() {
258 return (parent, knob) -> knob.centerXProperty().bind(parent.xProperty());
261 static Position right() {
262 return (parent, knob) -> knob.centerXProperty().bind(parent.xProperty().add(parent.getWidth()));
265 static Position top() {
266 return (parent, knob) -> knob.centerYProperty().bind(parent.yProperty());
269 static Position bottom() {
270 return (parent, knob) -> knob.centerYProperty().bind(parent.yProperty().add(parent.getHeight()));
273 static Position xMiddle() {
274 return (parent, knob) -> knob.centerXProperty().bind(parent.xProperty().add(parent.getWidth() / 2));
277 static Position yMiddle() {
278 return (parent, knob) -> knob.centerYProperty().bind(parent.yProperty().add(parent.getHeight() / 2));
286 static interface Boundary {
288 boolean isPointInBounds(
double x,
double y);
295 static interface Draggable {
297 void perform(PhysicalTag parent, MouseEvent event, Boundary b);
299 static Draggable bottom() {
300 return (parent, event, bounds) -> {
301 if (!bounds.isPointInBounds(event.getX(),
event.getY())) {
305 double deltaY =
event.getY() - parent.getY();
307 parent.setHeight(deltaY);
312 static Draggable top() {
313 return (parent, event, bounds) -> {
314 if (!bounds.isPointInBounds(event.getX(),
event.getY())) {
318 double deltaY = parent.getY() + parent.getHeight() -
event.getY();
319 if (deltaY < parent.getY() + parent.getHeight() && deltaY > 0) {
320 parent.setHeight(deltaY);
321 parent.setY(event.getY());
326 static Draggable left() {
327 return (parent, event, bounds) -> {
328 if (!bounds.isPointInBounds(event.getX(),
event.getY())) {
332 double deltaX = parent.getX() + parent.getWidth() -
event.getX();
333 if (deltaX < parent.getX() + parent.getWidth() && deltaX > 0) {
334 parent.setWidth(deltaX);
335 parent.setX(event.getX());
340 static Draggable right() {
341 return (parent, event, bounds) -> {
342 if (!bounds.isPointInBounds(event.getX(),
event.getY())) {
346 double deltaX =
event.getX() - parent.getX();
348 parent.setWidth(deltaX);
final PropertyChangeSupport pcs
ImageTagRegion setHeight(double height)
ImageTagRegion setStrokeThickness(double thickness)
ImageTagRegion setY(double y)
static final EventType< Event > FOCUSED
ImageTagRegion setWidth(double width)
ContentViewerTag< ImageTagRegion > getContentViewerTag()
static final EventType< Event > NOT_FOCUSED
double getStrokeThickness()
ContentTag getContentTag()
final ContentViewerTag< ImageTagRegion > appTag
ImageTag(ContentViewerTag< ImageTagRegion > contentViewerTag, ImageView image)
ImageTagRegion setX(double x)
final PhysicalTag physicalTag
void subscribeToEditEvents(PropertyChangeListener listener)
final EventDispatchChainImpl ALL_CHILDREN