Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 54 additions & 15 deletions connector/src/main/java/devtoolsfx/connector/BoundsPane.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package devtoolsfx.connector;

import devtoolsfx.util.SceneUtils;
import java.lang.System.Logger;
import java.lang.System.Logger.Level;
import javafx.geometry.BoundingBox;
import javafx.geometry.Bounds;
import javafx.geometry.Point2D;
Expand All @@ -9,13 +11,13 @@
import javafx.scene.paint.Color;
import javafx.scene.shape.Line;
import javafx.scene.shape.Rectangle;
import javafx.scene.shape.Shape;
import javafx.scene.shape.StrokeLineCap;
import javafx.scene.shape.StrokeLineJoin;
import javafx.scene.shape.StrokeType;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;

import static java.lang.System.Logger;
import static java.lang.System.Logger.Level;

/**
* Contains the logic to implement highlighting of arbitrary nodes within the given parent node.
* See {@link #attach(Parent)}. There are three types of nodes: a colored rectangle to
Expand All @@ -33,7 +35,7 @@ final class BoundsPane {
private @Nullable Parent parent;

public BoundsPane() {
// pass
updateHighlight(Highlight.defaults());
}

/**
Expand Down Expand Up @@ -180,6 +182,18 @@ public void toggleBaselineDisplay(@Nullable Node target) {
}
}

/**
* Applies the given {@link Highlight} to the visual elements, updating
* the layout bounds, bounds-in-parent, and baseline highlights accordingly.
*
* @param highlight the {@link Highlight} object containing the visual parameters to apply
*/
public void updateHighlight(Highlight highlight) {
updateBoundsHighlight(highlight.getLayoutBounds(), layoutBoundsRect);
updateBoundsHighlight(highlight.getBoundsInParent(), boundsInParentRect);
updateBaselineHighlight(highlight.getBaseline(), baselineStroke);
}

///////////////////////////////////////////////////////////////////////////

/**
Expand All @@ -189,12 +203,6 @@ public void toggleBaselineDisplay(@Nullable Node target) {
private Rectangle createBoundsInParentRect() {
var r = new Rectangle();
r.setId(ConnectorOptions.AUX_NODE_ID_PREFIX + "layoutBoundsRect");
r.setFill(null);
r.setStroke(Color.GREEN);
r.setStrokeType(StrokeType.INSIDE);
r.setOpacity(0.8);
r.getStrokeDashArray().addAll(3.0, 3.0);
r.setStrokeWidth(1);
r.setManaged(false);
r.setMouseTransparent(true);
return r;
Expand All @@ -207,8 +215,6 @@ private Rectangle createBoundsInParentRect() {
private Rectangle createLayoutBoundsRect() {
var r = new Rectangle();
r.setId(ConnectorOptions.AUX_NODE_ID_PREFIX + "boundsInParentRect");
r.setFill(Color.YELLOW);
r.setOpacity(0.5);
r.setManaged(false);
r.setMouseTransparent(true);
return r;
Expand All @@ -221,13 +227,46 @@ private Rectangle createLayoutBoundsRect() {
private Line createBaselineStroke() {
var l = new Line();
l.setId(ConnectorOptions.AUX_NODE_ID_PREFIX + "baselineLine");
l.setStroke(Color.RED);
l.setOpacity(.75);
l.setStrokeWidth(1);
l.setManaged(false);
return l;
}

private void updateBoundsHighlight(Highlight.BoundsHighlight h, Rectangle rect) {
if (h.getFill() != null) {
rect.setFill(Color.web(h.getFill()));
} else {
rect.setFill(null);
}

if (h.getStroke() != null) {
rect.setStroke(Color.web(h.getStroke()));
} else {
rect.setStroke(null);
}
updateShapeHighlight(h, rect);
}

private void updateBaselineHighlight(Highlight.BaselineHighlight h, Line line) {
line.setStroke(Color.web(h.getStroke()));
updateShapeHighlight(h, line);
}

private void updateShapeHighlight(Highlight.AbstractHighlight h, Shape shape) {
shape.setStrokeType(StrokeType.valueOf(h.getStrokeType()));

shape.getStrokeDashArray().clear();
for (var d : h.getStrokeDashArray()) {
shape.getStrokeDashArray().add(d);
}
shape.setStrokeDashOffset(h.getStrokeDashOffset());
shape.setStrokeLineCap(StrokeLineCap.valueOf(h.getStrokeLineCap()));
shape.setStrokeLineJoin(StrokeLineJoin.valueOf(h.getStrokeLineJoin()));
shape.setStrokeMiterLimit(h.getStrokeMiterLimit());

shape.setStrokeWidth(h.getStrokeWidth());
shape.setOpacity(h.getOpacity());
}

/**
* Hides the given line.
*/
Expand Down
12 changes: 9 additions & 3 deletions connector/src/main/java/devtoolsfx/connector/Connector.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,15 @@
import devtoolsfx.scenegraph.Element;
import devtoolsfx.scenegraph.WindowProperties;
import devtoolsfx.scenegraph.attributes.AttributeCategory;
import java.util.List;
import java.util.Map;
import javafx.application.Application;
import javafx.beans.property.ReadOnlyBooleanProperty;
import javafx.scene.Parent;
import javafx.scene.control.Control;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;

import java.util.List;
import java.util.Map;

/**
* The connector serves as the main entry point for application monitoring. It accepts
* the target app's primary stage and tracks and reports its state and changes via the
Expand Down Expand Up @@ -72,6 +71,13 @@ public interface Connector {
*/
void selectNode(int uid, Element element, @Nullable HighlightOptions opts);

/**
* Selects and starts monitoring the node attributes and visual highlights of the
* specified element's bounds, if possible. This method is mutually exclusive with
* {@link #selectWindow(int)}.
*/
void selectNode(int uid, Element element, @Nullable HighlightOptions opts, @Nullable Highlight highlight);

/**
* The opposite of {@link #selectNode(int, Element, HighlightOptions)}.
*
Expand Down
Loading