#include <inspector_overlay.hpp>
Classes | |
| struct | ReparentSourceEdit |
| Structural reparent → lock-to-source. More... | |
| struct | KnobApplyEdit |
| struct | AgentRequestEdit |
| Send-to-agent → free-text request. More... | |
| struct | KnobHit |
| One knob control's on-screen hit-rect from the last paint. More... | |
| struct | PassAttribution |
| Aggregated attribution data for a single render pass type, computed over the rolling frame history. More... | |
| struct | ReconcileRow |
| One classified tweak row in the reconciliation report. More... | |
| struct | ReconcileReport |
| Aggregate reconciliation report over every tweak in the attached TweakStore, classified against the current live view tree. More... | |
Public Types | |
| enum class | Tool : std::uint8_t { select , text } |
| enum class | CursorAffordance : std::uint8_t { none , move , resize_nw_se , resize_ne_sw , resize_ns , resize_ew } |
| enum class | SelectionMode : std::uint8_t { follows_focus , follows_mouse } |
| How the selected node is chosen as the pointer moves. More... | |
| enum class | ReconcileStatus : std::uint8_t { locked_to_source , drifted , unresolvable } |
| Reconciliation state of a single stored tweak. More... | |
Public Member Functions | |
| InspectorOverlay (View &root) | |
| ~InspectorOverlay () | |
| View & | inspected_root () const |
| bool | is_active () const |
| void | set_active (bool active) |
| void | toggle () |
| Tool | tool () const |
| void | set_tool (Tool t) |
| void | toggle_tool () |
| bool | handle_key_event (const KeyEvent &event) |
| bool | handle_mouse_event (const MouseEvent &event) |
| bool | handle_text_input (const TextInputEvent &event) |
| void | paint (Canvas &canvas) |
| void | set_render_pass_manager (render::RenderPassManager *rpm) |
| void | set_atlas_inventory (const render::AtlasInventory *inv) |
| Attach the render layer's texture-atlas inventory so the atlas viewer tab (A hotkey) can report per-atlas dimensions, page count, and occupancy. | |
| const render::AtlasInventory * | atlas_inventory () const |
| void | set_tweak_store (TweakStore *store) |
| Connect the inspector overlay to the in-process TweakStore so gesture detectors can persist direct-manipulation edits without round-tripping through the TCP protocol. | |
| TweakStore * | tweak_store () const |
| void | set_edit_history (pulp::state::EditHistory *h) |
| Attach an EditHistory so every committed manipulation gesture (drag-to-move, corner-resize, tweak-panel delete) becomes ONE undoable unit. | |
| pulp::state::EditHistory * | edit_history () const |
| void | set_reparent_source_sink (std::function< void(const ReparentSourceEdit &)> sink) |
| bool | has_reparent_source_sink () const |
| void | set_knob_schema (pulp::design::KnobSchema schema) |
| Semantic knobs → apply-to-artifact. | |
| const pulp::design::KnobSchema & | knob_schema () const |
| void | set_knob_apply_sink (std::function< void(const KnobApplyEdit &)> sink) |
| bool | has_knob_apply_sink () const |
| std::string | knob_selection (std::string_view knob_id) const |
| The knob's currently-selected value (empty when never set). | |
| void | set_agent_request_sink (std::function< void(const AgentRequestEdit &)> sink) |
| bool | has_agent_request_sink () const |
| const std::vector< KnobHit > & | knob_hits () const |
| Rect | agent_field_bounds () const |
| Rect | agent_send_bounds () const |
| const std::string & | agent_text_buffer () const |
| bool | agent_field_active () const |
| void | clear_edit_history () |
| Clear the attached EditHistory. | |
| bool | emit_tweak_for_selection (std::string_view property_path, choc::value::Value value, std::string_view source="inspector-gesture") |
| Emit a tweak for the currently-selected view's anchor. | |
| void | set_dragging_enabled (bool enabled) |
| Toggle drag-handles mode. | |
| bool | dragging_enabled () const |
| void | toggle_dragging () |
| void | set_manipulate_only (bool on) |
| bool | manipulate_only () const |
| void | set_selected_view (View *v) |
| Set the selected view directly (used by the floating Inspector window so the two surfaces share one selection). | |
| bool | select_parent () |
| CursorAffordance | cursor_affordance_at (Point pos) const |
| bool | drop_indicator_active () const |
| Whether a drop indicator (the blue insertion line / container highlight) would paint right now. | |
| int | drop_index () const |
| Test-visible accessors for the resolved reflow drop. | |
| bool | drop_indicator_is_line () const |
| Rect | drop_indicator_rect () const |
| const View * | drop_target () const |
| int | cursor_style_for (Point pos) const |
| Map a CursorAffordance to a View::CursorStyle; returns the int cast the cursor hook reports to the host (or -1 for none/no override). | |
| bool | capture_pass_frame () |
| Sample the attached RenderPassManager's current-frame pass stats into the rolling history. | |
| std::vector< PassAttribution > | pass_attribution () const |
| Per-pass attribution computed over the current rolling history, ordered by RenderPassType (background → post_effects). | |
| int | budget_overrun_count () const |
| Count of frames in history where the manager reported the frame exceeded its time budget (RenderPassManager::over_budget()). | |
| std::uint64_t | pass_frames_captured () const |
| Total frames sampled into the rolling history since construction (saturates conceptually — only the last kPassHistoryFrames worth of per-pass detail is retained, but this counter keeps growing). | |
| void | set_pass_viewer_enabled (bool enabled) |
| Toggle the per-pass attribution panel section. | |
| bool | pass_viewer_enabled () const |
| void | toggle_pass_viewer () |
| void | set_eyedropper_active (bool active) |
| Toggle eyedropper mode. | |
| bool | eyedropper_active () const |
| void | toggle_eyedropper () |
| Color | eyedropper_sample () const |
| Last color sampled by the eyedropper (updated on every mouse-move while eyedropper mode is active). | |
| bool | eyedropper_has_sample () const |
| Whether eyedropper_sample_ reflects a real sample yet (false until the first mouse-move inside the canvas while active). | |
| const std::string & | eyedropper_target () const |
| The dotted color property the eyedropper writes to on click. | |
| void | set_eyedropper_target (std::string path) |
| bool | sample_color_at (Point pos, Canvas *canvas, Color &out) const |
| Sample the color under pos (root coords) WITHOUT applying it. | |
| bool | apply_eyedropper_pick () |
| Apply the last sampled color as a tweak to the current selection's eyedropper_target_ property, encoded as a "#rrggbb" / "#rrggbbaa" hex string, with source "inspector-eyedropper". | |
| View * | selected_view () const |
| View * | hovered_view () const |
| SelectionMode | selection_mode () const |
| Current selection mode. | |
| void | set_selection_mode (SelectionMode mode) |
| void | toggle_selection_mode () |
| Flip between follows_focus and follows_mouse. | |
| void | set_config (InspectorConfig config) |
| The editor-URL config used to format source-jump URLs. | |
| const InspectorConfig & | config () const |
| SourceJumpResult | jump_to_selection_source (bool dry_run=true) |
| Resolve the selected view's authored source location and (unless dry_run) open the user's editor at that file:line. | |
| const std::string & | editing_field () const |
| const std::string & | edit_buffer () const |
| std::size_t | edit_caret_pos () const |
| bool | is_editing () const |
| bool | begin_field_edit (std::string field_path, float initial_value) |
| Begin editing the named property on the current selection. | |
| bool | commit_field_edit () |
| Commit the current edit buffer as a tweak, then exit edit mode. | |
| void | cancel_field_edit () |
| Cancel the current edit without writing a tweak. | |
| bool | text_editing () const |
| const std::string & | text_edit_buffer () const |
| View * | text_edit_target () const |
| bool | selection_shows_resize_handles () const |
| bool | selection_uses_subtle_edit_outline () const |
| True when the selected element should render the subtle thin-blue text-edit outline instead of the orange Select-tool box. | |
| bool | begin_text_edit (View *v) |
| Begin an inline text edit of v's copy, seeding the buffer with the current text. | |
| bool | commit_text_edit () |
| Commit the inline text edit: keep the live View text, emit a text content tweak (path == text_tweak_path()), and — when an EditHistory is wired — push ONE undoable unit whose undo restores the prior text on BOTH the live View and the TweakStore. | |
| void | cancel_text_edit () |
| Cancel the inline text edit, restoring the View's original text. | |
| std::size_t | text_caret () const |
| Caret byte-offset into the edit buffer (UTF-8 boundary-aligned). | |
| std::pair< std::size_t, std::size_t > | text_selection () const |
| Selection range as [start, end) byte offsets (start == end → none). | |
| bool | text_has_selection () const |
| void | text_move_caret (int delta, bool extend) |
| Move the caret by delta UTF-8 codepoints (negative = left). | |
| void | text_move_word (int direction, bool extend) |
| Move the caret one word in direction (-1 left / +1 right), skipping the run of non-word then word bytes (Option/Alt+Arrow). | |
| void | text_move_home (bool extend) |
| Move the caret to the buffer start / end (Cmd+Left / Cmd+Right / Home / End — single-line). | |
| void | text_move_end (bool extend) |
| void | text_select_all () |
| Select the entire buffer (Cmd+A). | |
| bool | text_copy () |
| Clipboard: copy / cut / paste the selection (Cmd+C / X / V). | |
| bool | text_cut () |
| bool | text_paste () |
| void | text_insert (const std::string &utf8) |
| Insert UTF-8 text at the caret, replacing any selection. | |
| void | text_delete_backward () |
| Delete the selection if any; otherwise the codepoint before the caret (Backspace) or after it (Delete / forward-delete). | |
| void | text_delete_forward () |
| const std::string & | text_tweak_path () const |
| Dotted property path the Text tool writes the edited copy to. | |
| void | set_text_tweak_path (std::string path) |
| void | set_tweaks_panel_visible (bool visible) |
| bool | tweaks_panel_visible () const |
| void | toggle_tweaks_panel () |
| std::size_t | tweak_row_count () const |
| Number of tweak rows currently laid out in the management panel (populated by the most recent paint() while the panel is visible). | |
| void | refresh_drift () |
| Recompute the drift list by diffing the attached TweakStore against the current live view tree's anchor set. | |
| std::size_t | drift_count () const |
| Number of drifted/orphaned tweaks from the last refresh_drift(). | |
| bool | drift_drawer_open () const |
| Whether the drift drawer is currently expanded. | |
| void | set_drift_drawer_open (bool open) |
| void | toggle_drift_drawer () |
| const std::vector< TweakStore::DriftedTweak > & | drifted () const |
| Read-only access to the last computed drift list — for tests and host-side badges. | |
| ReconcileReport | reconcile_report () const |
| Recompute the reconciliation report by classifying every stored tweak against the live view tree's anchor + lock state. | |
| void | set_reconcile_tab_visible (bool visible) |
| Toggle the reconciliation tab. | |
| bool | reconcile_tab_visible () const |
| void | toggle_reconcile_tab () |
| std::size_t | reconcile_row_count () const |
| Number of tweak rows the reconciliation tab laid out on the most recent paint() while it was visible. | |
| void | set_atlas_viewer_visible (bool visible) |
| Toggle the texture-atlas viewer tab. | |
| bool | atlas_viewer_visible () const |
| void | toggle_atlas_viewer () |
| std::size_t | atlas_row_count () const |
| Number of atlas rows the viewer laid out on the most recent paint() while it was visible. | |
| bool | zoom_active () const |
| void | set_zoom_active (bool active) |
| void | toggle_zoom () |
| int | zoom_factor () const |
| Magnification factor — how many panel pixels per source pixel. | |
| void | set_zoom_factor (int factor) |
| Point | zoom_sample_center () const |
| Last cursor position the loupe sampled around, in root (window) coordinates. | |
| Color | zoom_center_color () const |
| Resolved color of the center (sample) pixel — what the loupe readout reports as a hex string. | |
Static Public Member Functions | |
| static bool | view_has_editable_text (const View *v) |
| True if v exposes editable text the Text tool can edit (today a Label or a TextEditor). | |
| static std::string | editable_text_of (const View *v) |
| Read the current text of a text-bearing View (empty if v is null or carries no editable text). | |
| static void | set_editable_text_of (View *v, const std::string &text) |
| Write text to a text-bearing View's copy, marking layout dirty so the new text reflows + repaints. | |
| static const char * | reconcile_status_str (ReconcileStatus status) |
| Stringify a ReconcileStatus for the panel + tests. | |
Static Public Attributes | |
| static constexpr std::size_t | kPassHistoryFrames = 60 |
| Number of frames the rolling per-pass history retains. | |
|
strong |
|
strong |
|
strong |
How the selected node is chosen as the pointer moves.
| Enumerator | |
|---|---|
| follows_focus | |
| follows_mouse | |
|
strong |
|
explicit |
| pulp::inspect::InspectorOverlay::~InspectorOverlay | ( | ) |
|
inline |
|
inline |
|
inline |
|
inline |
| bool pulp::inspect::InspectorOverlay::apply_eyedropper_pick | ( | ) |
Apply the last sampled color as a tweak to the current selection's eyedropper_target_ property, encoded as a "#rrggbb" / "#rrggbbaa" hex string, with source "inspector-eyedropper".
Returns false if there's no sample yet or emit_tweak_for_selection reports no-op (no selection / anchor / store). On success the eyedropper auto-disables so a pick is a single, deliberate action.
|
inline |
|
inline |
Number of atlas rows the viewer laid out on the most recent paint() while it was visible.
Visible for tests so they can assert the tab rendered the expected rows without scraping pixels. Zero when the tab is hidden or no inventory is wired.
|
inline |
| bool pulp::inspect::InspectorOverlay::begin_field_edit | ( | std::string | field_path, |
| float | initial_value ) |
Begin editing the named property on the current selection.
The initial_value is what shows in the buffer at edit start and is restored on Esc-cancel. Returns false if there's no selection (nothing to edit) or field_path is empty. Visible for tests; production code enters edit mode via the panel-click path in handle_mouse_event().
| bool pulp::inspect::InspectorOverlay::begin_text_edit | ( | View * | v | ) |
Begin an inline text edit of v's copy, seeding the buffer with the current text.
Returns false when v is null or exposes no editable text. Visible for tests; production enters via the Text-tool click path in handle_mouse_event(). Selects v so the selection box + the props panel track the edit target.
|
inline |
Count of frames in history where the manager reported the frame exceeded its time budget (RenderPassManager::over_budget()).
Surfaced as the panel's "overruns" figure.
| void pulp::inspect::InspectorOverlay::cancel_field_edit | ( | ) |
Cancel the current edit without writing a tweak.
Restores the original value to the underlying View when changes were applied optimistically (none today; edits commit only on Enter).
| void pulp::inspect::InspectorOverlay::cancel_text_edit | ( | ) |
Cancel the inline text edit, restoring the View's original text.
| bool pulp::inspect::InspectorOverlay::capture_pass_frame | ( | ) |
Sample the attached RenderPassManager's current-frame pass stats into the rolling history.
Safe to call when no RPM is attached (no-op). Called automatically at the start of every paint() so the viewer always reflects fresh data; also callable directly from tests to drive deterministic history without a real frame loop. Returns true if a frame was actually captured.
|
inline |
Clear the attached EditHistory.
The undo/redo closures recorded for each gesture capture the live View* they mutate (e.g. View* tgt = selected_;). If the inspected view tree is rebuilt or re-imported (the design re-imported, a live React subtree rebuilt) BEFORE the user hits undo, those captured pointers dangle and undo would deref freed memory. The minimal, guaranteed-safe mitigation is to drop the entire history whenever the inspected root is replaced: nothing recorded against the OLD tree can be undone against the NEW tree anyway. Hosts that own the EditHistory must call this at their root-replacement seam (e.g. right after re-import, before the new tree is wired up).
The longer-term undo model can resolve each target by stable anchor-id at undo time instead of capturing a raw View*, allowing legitimate cross-import undo to survive. Until that model is wired, clearing is the conservative guard.
| bool pulp::inspect::InspectorOverlay::commit_field_edit | ( | ) |
Commit the current edit buffer as a tweak, then exit edit mode.
Returns true if a tweak was emitted (selection has an anchor + a TweakStore is wired); returns false if commit is a no-op (selection missing anchor, no store, no field being edited). Regardless of return value, edit mode is exited.
| bool pulp::inspect::InspectorOverlay::commit_text_edit | ( | ) |
Commit the inline text edit: keep the live View text, emit a text content tweak (path == text_tweak_path()), and — when an EditHistory is wired — push ONE undoable unit whose undo restores the prior text on BOTH the live View and the TweakStore.
Returns true if a tweak was emitted (target has an anchor + a store is wired). Exits edit mode regardless.
|
inline |
| CursorAffordance pulp::inspect::InspectorOverlay::cursor_affordance_at | ( | Point | pos | ) | const |
| int pulp::inspect::InspectorOverlay::cursor_style_for | ( | Point | pos | ) | const |
Map a CursorAffordance to a View::CursorStyle; returns the int cast the cursor hook reports to the host (or -1 for none/no override).
|
inline |
|
inline |
Number of drifted/orphaned tweaks from the last refresh_drift().
|
inline |
Whether the drift drawer is currently expanded.
|
inline |
Read-only access to the last computed drift list — for tests and host-side badges.
|
inline |
Test-visible accessors for the resolved reflow drop.
drop_index() is the insertion slot among the target container's visible children (0 == before first, count == after last); drop_indicator_is_line() distinguishes the Figma-style between-sibling insertion LINE from the empty-container drop-inside HIGHLIGHT; drop_indicator_rect() is the indicator geometry in root coords; drop_target() is the container the cursor resolved into (or null).
|
inline |
Whether a drop indicator (the blue insertion line / container highlight) would paint right now.
True ONLY during an active reflow (non-float) move with a resolved drop target — it is always false at rest (no drag), so a selected-but-idle element shows exactly one (orange) selection affordance, never a drop indicator. Visible for tests so they can assert "no drop indicator when idle" without scraping pixels.
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
|
static |
Read the current text of a text-bearing View (empty if v is null or carries no editable text).
|
inline |
| bool pulp::inspect::InspectorOverlay::emit_tweak_for_selection | ( | std::string_view | property_path, |
| choc::value::Value | value, | ||
| std::string_view | source = "inspector-gesture" ) |
Emit a tweak for the currently-selected view's anchor.
Returns false if there's no selection, the selection has no anchor_id, or no TweakStore is attached. Used by gesture-detection code in the overlay (drag-handles, color-picker, field-edit).
|
inline |
|
inline |
Whether eyedropper_sample_ reflects a real sample yet (false until the first mouse-move inside the canvas while active).
|
inline |
Last color sampled by the eyedropper (updated on every mouse-move while eyedropper mode is active).
Read by tests and by the cursor-swatch paint. Defaults to transparent black until the first sample lands.
|
inline |
The dotted color property the eyedropper writes to on click.
Defaults to "style.background_color"; a host could retarget it to "style.color" / "style.border_color" before a pick. The setter ignores empty strings.
| bool pulp::inspect::InspectorOverlay::handle_key_event | ( | const KeyEvent & | event | ) |
| bool pulp::inspect::InspectorOverlay::handle_mouse_event | ( | const MouseEvent & | event | ) |
| bool pulp::inspect::InspectorOverlay::handle_text_input | ( | const TextInputEvent & | event | ) |
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
| SourceJumpResult pulp::inspect::InspectorOverlay::jump_to_selection_source | ( | bool | dry_run = true | ) |
Resolve the selected view's authored source location and (unless dry_run) open the user's editor at that file:line.
Defaults to dry-run so tests and protocol callers must opt into launching. Returns the full result so callers / tests can inspect the formatted URL. A graceful no-op (ok == false) when there is no selection or the selected view carries no source provenance — the inspector never throws or spawns a process for a non-imported view.
|
inline |
|
inline |
| std::string pulp::inspect::InspectorOverlay::knob_selection | ( | std::string_view | knob_id | ) | const |
The knob's currently-selected value (empty when never set).
The overlay tracks selection only for display; the host owns the authoritative state.
|
inline |
| void pulp::inspect::InspectorOverlay::paint | ( | Canvas & | canvas | ) |
| std::vector< PassAttribution > pulp::inspect::InspectorOverlay::pass_attribution | ( | ) | const |
Per-pass attribution computed over the current rolling history, ordered by RenderPassType (background → post_effects).
Entries with present == false had no frames in history and are skipped by the panel; tests can still inspect the full ordered set.
|
inline |
Total frames sampled into the rolling history since construction (saturates conceptually — only the last kPassHistoryFrames worth of per-pass detail is retained, but this counter keeps growing).
|
inline |
| ReconcileReport pulp::inspect::InspectorOverlay::reconcile_report | ( | ) | const |
Recompute the reconciliation report by classifying every stored tweak against the live view tree's anchor + lock state.
A no-op returning an empty report when no TweakStore is wired. Pure computation — safe for tests, never spawns a process, never throws. Called automatically on first paint while the tab is open; callers may invoke it directly after a re-import.
|
inline |
Number of tweak rows the reconciliation tab laid out on the most recent paint() while it was visible.
Visible for tests so they can assert the tab rendered the expected rows without scraping pixels. Zero when the tab is hidden or no TweakStore is wired.
|
static |
Stringify a ReconcileStatus for the panel + tests.
|
inline |
| void pulp::inspect::InspectorOverlay::refresh_drift | ( | ) |
Recompute the drift list by diffing the attached TweakStore against the current live view tree's anchor set.
A no-op (and clears the list) when no TweakStore is wired. Called automatically on first paint after set_active(true); call it explicitly after a re-import to refresh the drawer.
| bool pulp::inspect::InspectorOverlay::sample_color_at | ( | Point | pos, |
| Canvas * | canvas, | ||
| Color & | out ) const |
Sample the color under pos (root coords) WITHOUT applying it.
Visible for tests + used internally by the mouse-move handler. Returns true if a color was found (always true for the resolved-style fallback once a view is under the cursor).
| bool pulp::inspect::InspectorOverlay::select_parent | ( | ) |
|
inline |
|
inline |
Current selection mode.
Defaults to follows_focus (click-to- select), so existing hosts and tests are unaffected until the user opts in via the M hotkey.
|
inline |
|
inline |
True when the selected element should render the subtle thin-blue text-edit outline instead of the orange Select-tool box.
Gated purely on "is a text edit active for the selected view".
| void pulp::inspect::InspectorOverlay::set_active | ( | bool | active | ) |
|
inline |
|
inline |
Attach the render layer's texture-atlas inventory so the atlas viewer tab (A hotkey) can report per-atlas dimensions, page count, and occupancy.
The inventory is a value-snapshot collection owned by the render/host layer; the overlay only reads it. Passing nullptr (the default) makes the atlas tab render its "GPU atlas unavailable" empty state — the inspector never crashes when no GPU atlas is wired.
|
inline |
Toggle the texture-atlas viewer tab.
Off by default so the inspector panel layout is unchanged until the user opts in (A key in handle_key_event). When on, the tab replaces the property section, mirroring the pass attribution viewer.
|
inline |
The editor-URL config used to format source-jump URLs.
The host sets this once (mirroring the DomainHandler's config); the J hotkey and jump_to_selection_source() read it. Defaults to the built-in VS Code template — see pulp/inspect/editor_url.hpp.
|
inline |
Toggle drag-handles mode.
When enabled AND a view is selected AND has an anchor_id, eight 8×8 handles paint at the selected view's corners + edges; mouse-down on a handle starts a resize gesture that mutates flex inputs (preferred_width / preferred_height) so Yoga picks up the new size, then emits "layout.width" / "layout.height" tweaks on mouse-up. Default OFF for safety — without it, normal click-to-select is unchanged.
|
inline |
|
inline |
Attach an EditHistory so every committed manipulation gesture (drag-to-move, corner-resize, tweak-panel delete) becomes ONE undoable unit.
Each gesture's commit pushes a single entry whose undo restores BOTH the live View layout inputs AND the TweakStore to the exact pre-gesture state — nothing is ever lost. Cmd+Z / Cmd+Shift+Z (or Cmd+Y) in handle_key_event() drive undo / redo and repaint. When null (the default), gestures behave exactly as before (no undo) — the EditHistory is a strictly additive safety net.
NOTE: EditHistory coalesces by default (merges consecutive entries with the same description), which would fuse two separate moves into one undo step. Callers that want one-undo-per-gesture should set_coalesce(false) on the history before wiring it here.
|
static |
Write text to a text-bearing View's copy, marking layout dirty so the new text reflows + repaints.
No-op for non-text views.
| void pulp::inspect::InspectorOverlay::set_eyedropper_active | ( | bool | active | ) |
Toggle eyedropper mode.
When enabled, mouse-move samples the color under the cursor and a swatch + hex readout follows the pointer; the next click captures that color and emits it as a tweak on the selected view's color property (default "style.background_color"). Toggled via the E key (no modifier) while the inspector is active — mirrors how D toggles drag handles. Default OFF: without it, normal click-to-select is unchanged.
Sampling strategy: if the live Canvas exposes pixel readback (Canvas::read_pixels — Skia raster surfaces only), the eyedropper reads the exact framebuffer pixel under the cursor. Otherwise it falls back to the resolved-style color of the top-most View under the cursor — walking up the tree to the nearest ancestor with an explicit background color. The v1 fallback is documented as a known simplification.
|
inline |
|
inline |
|
inline |
Semantic knobs → apply-to-artifact.
A knob is one expressive control (a "minimalism" slider, a theme flip, a layout-variant switch) whose value drives a bundle of parameter writes at once (see pulp::design::design_knobs). The overlay renders the schema set here in the tweaks panel and, when a value is chosen, emits the knob id + selected value through this sink. Like the reparent sink, the overlay never touches files: the host owns the design artifact + manifest and applies the change (pulp::design::apply_knob — persist the local writes into the artifact's EDITMODE block, apply the token writes at the theme layer, re-import), so the model stays testable without a filesystem.
|
inline |
|
inline |
Toggle the per-pass attribution panel section.
Off by default so the inspector panel layout is unchanged until the user opts in (P-key in handle_key_event). When on, the section replaces the lower portion of the property panel.
|
inline |
Toggle the reconciliation tab.
Off by default so the inspector panel layout is unchanged until the user opts in (R key in handle_key_event). When on, the tab replaces the property section, mirroring the pass attribution viewer.
|
inline |
|
inline |
|
inline |
Set the selected view directly (used by the floating Inspector window so the two surfaces share one selection).
Safe to pass nullptr to clear. Does not require the overlay to be active.
|
inline |
|
inline |
| void pulp::inspect::InspectorOverlay::set_tool | ( | Tool | t | ) |
|
inline |
Connect the inspector overlay to the in-process TweakStore so gesture detectors can persist direct-manipulation edits without round-tripping through the TCP protocol.
The protocol path (Inspector.applyTweak) still works independently; this is the FAST in-process path for overlay-driven gestures. Setting nullptr disables the in-process emission (e.g. when no TweakStore is wired into the host).
|
inline |
| void pulp::inspect::InspectorOverlay::set_zoom_active | ( | bool | active | ) |
| void pulp::inspect::InspectorOverlay::set_zoom_factor | ( | int | factor | ) |
|
inline |
Caret byte-offset into the edit buffer (UTF-8 boundary-aligned).
| bool pulp::inspect::InspectorOverlay::text_copy | ( | ) |
Clipboard: copy / cut / paste the selection (Cmd+C / X / V).
Copy returns false when there is no selection; cut/paste mutate the buffer + live View text. Paste replaces the selection (or inserts at the caret when none).
| bool pulp::inspect::InspectorOverlay::text_cut | ( | ) |
| void pulp::inspect::InspectorOverlay::text_delete_backward | ( | ) |
Delete the selection if any; otherwise the codepoint before the caret (Backspace) or after it (Delete / forward-delete).
| void pulp::inspect::InspectorOverlay::text_delete_forward | ( | ) |
|
inline |
|
inline |
|
inline |
|
inline |
| void pulp::inspect::InspectorOverlay::text_insert | ( | const std::string & | utf8 | ) |
Insert UTF-8 text at the caret, replacing any selection.
The shared insertion path for typed characters (handle_text_input) and paste.
| void pulp::inspect::InspectorOverlay::text_move_caret | ( | int | delta, |
| bool | extend ) |
Move the caret by delta UTF-8 codepoints (negative = left).
When extend is true the selection anchor stays put (shift-select); otherwise the selection collapses to the new caret.
| void pulp::inspect::InspectorOverlay::text_move_end | ( | bool | extend | ) |
| void pulp::inspect::InspectorOverlay::text_move_home | ( | bool | extend | ) |
Move the caret to the buffer start / end (Cmd+Left / Cmd+Right / Home / End — single-line).
extend = shift-select.
| void pulp::inspect::InspectorOverlay::text_move_word | ( | int | direction, |
| bool | extend ) |
Move the caret one word in direction (-1 left / +1 right), skipping the run of non-word then word bytes (Option/Alt+Arrow).
extend = shift-select.
| bool pulp::inspect::InspectorOverlay::text_paste | ( | ) |
| void pulp::inspect::InspectorOverlay::text_select_all | ( | ) |
Select the entire buffer (Cmd+A).
| std::pair< std::size_t, std::size_t > pulp::inspect::InspectorOverlay::text_selection | ( | ) | const |
Selection range as [start, end) byte offsets (start == end → none).
|
inline |
Dotted property path the Text tool writes the edited copy to.
Defaults to "text" (the JSX text-node content). A host could retarget it; the setter ignores empty strings.
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
Flip between follows_focus and follows_mouse.
Bound to the M ("mode") hotkey in handle_key_event() — D/E/P/T/J/Z/R/A are all taken, so M is the natural free letter for "selection mode".
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
Number of tweak rows currently laid out in the management panel (populated by the most recent paint() while the panel is visible).
Visible for tests so they can assert the panel rendered the expected number of rows without scraping pixels.
|
inline |
|
inline |
|
static |
True if v exposes editable text the Text tool can edit (today a Label or a TextEditor).
Used by the Text-tool click path + tests.
|
inline |
|
inline |
Resolved color of the center (sample) pixel — what the loupe readout reports as a hex string.
Comes from read_pixels() when available, else the fallback resolved-view-color path.
|
inline |
Magnification factor — how many panel pixels per source pixel.
Defaults to 20×; clamped to [4, 40] so the grid neither degenerates into a single cell nor overflows the panel.
|
inline |
Last cursor position the loupe sampled around, in root (window) coordinates.
The loupe centers its grid on this pixel.
|
staticconstexpr |
Number of frames the rolling per-pass history retains.
60 keeps one second of 60fps history without unbounded growth.