fix(native/paint): wire VariablesPanel into the right-rail paint pass

Codex stop-gate flagged that the previous commit (140d5495) shipped
`VariablesPanel` as a widget definition + tests but never wired it
into the host's paint composition, so users couldn't actually see
it. This commit closes that gap.

`crates/openpencil-shell-native/src/widget_host/paint.rs`:
  - Step 4 (PropertyPanel) now also computes the right-rail x +
    width as locals so the new VariablesPanel paint step reuses
    them instead of duplicating the geometry math.
  - New Step 4b: when `Document.var_table.variables` is non-empty,
    paint a `VariablesPanel::for_document(...)` rectangle anchored
    to the right rail. Layout decision:
      - No selection: panel pinned at the top of the rail
        (TOP_BAR_HEIGHT + 8 px) so it's the primary chrome there.
      - Active selection: PropertyPanel owns the rail; Variables
        anchors to the bottom (above the status bar). Approximate
        because PropertyPanel paints to fill the rail today;
        proper stacking lands when the rail grows scrollable
        regions or tabs.
    Variables stays hidden when `var_table` is empty — no visual
    noise for documents that don't use them.
  - `VariablesPanel` imported via `widgets::variables_panel::
    VariablesPanel` (the module is `pub mod` exported in
    widgets/mod.rs).

`crates/openpencil-shell-native/src/widget_host/input.rs`:
  - Cleaned up the unused imports left over from the input/keyboard
    split (5caa2eb3): `PropertyFocus`, `AIChatHit`, `AIChatPlaceholder`,
    `LayerPanel`, `LayoutCx`, `Toolbar`, `Widget`, `TOOLBAR_WIDTH`,
    `TOP_BAR_HEIGHT` were all moved to keyboard.rs but still
    listed in input.rs's import list. Down to the actually-used
    `ChatAnchor` + helpers + Point2D + Rect.

Tests: 274 shell-core + 54 desktop + 20 shell-native all pass.
Visual verification: opening a `.op` file whose `variables` array
is non-empty now shows the panel chrome (header "Variables" label,
active-theme chips, one row per variable with name + resolved
color swatch / scalar label). Edit interactions still pending —
`VariablesPanelHit::Row(idx)` is wired up but the host doesn't
dispatch it yet.
This commit is contained in:
Kayshen-X 2026-05-14 17:53:16 +08:00
parent 29c7930997
commit 048d53d71d
2 changed files with 40 additions and 13 deletions

View file

@ -5,11 +5,7 @@ use super::helpers::{
TOOLBAR_INSET_Y,
};
use super::{PanelResizeKind, WidgetHostNative};
use openpencil_shell_core::document::{ChatAnchor, PropertyFocus};
use openpencil_shell_core::widgets::{
AIChatHit, AIChatPlaceholder, LayerPanel, LayoutCx, Toolbar, Widget, TOOLBAR_WIDTH,
TOP_BAR_HEIGHT,
};
use openpencil_shell_core::document::ChatAnchor;
use openpencil_shell_core::{Point2D, Rect};
impl WidgetHostNative {

View file

@ -6,9 +6,9 @@ use super::frame_backend::NativeFrameBackend;
use super::helpers::{STATUS_INSET, TOOLBAR_INSET_X, TOOLBAR_INSET_Y};
use super::WidgetHostNative;
use openpencil_shell_core::widgets::{
AIChatPlaceholder, AlignToolbar, CanvasViewport, LayerPanel, LayoutCx, LocalePicker, PaintCx,
PropertyPanel, ShapePicker, StatusBar, Toolbar, TopBar, Widget, STATUS_BAR_HEIGHT,
STATUS_BAR_WIDTH, TOOLBAR_WIDTH, TOP_BAR_HEIGHT,
variables_panel::VariablesPanel, AIChatPlaceholder, AlignToolbar, CanvasViewport, LayerPanel,
LayoutCx, LocalePicker, PaintCx, PropertyPanel, ShapePicker, StatusBar, Toolbar, TopBar,
Widget, STATUS_BAR_HEIGHT, STATUS_BAR_WIDTH, TOOLBAR_WIDTH, TOP_BAR_HEIGHT,
};
use openpencil_shell_core::{Point2D, Rect, RenderBackend};
@ -92,14 +92,13 @@ impl WidgetHostNative {
// 4. PropertyPanel — only when selection.
let property_panel = PropertyPanel::for_selection_at(&self.document, self.now_ms);
let has_property = property_panel.is_some();
let property_panel_width = self.document.ui.property_panel_width;
let right_rail_x = viewport_width - property_panel_width;
if let Some(panel) = property_panel.as_ref() {
let property_rect = Rect {
origin: Point2D::new(
viewport_width - self.document.ui.property_panel_width,
TOP_BAR_HEIGHT,
),
origin: Point2D::new(right_rail_x, TOP_BAR_HEIGHT),
size: Point2D::new(
self.document.ui.property_panel_width,
property_panel_width,
(viewport_height - TOP_BAR_HEIGHT).max(0.0),
),
};
@ -109,6 +108,38 @@ impl WidgetHostNative {
panel.paint(&mut cx, property_rect);
}
// 4b. VariablesPanel — paints whenever the document has
// variables (so users with themed `.op` files see them
// immediately without needing to select a node). Sits in
// the same right-rail column as PropertyPanel. When a
// selection is active, PropertyPanel owns the rail and
// VariablesPanel paints below it; when no selection, the
// Variables panel anchors at the top so it's not hidden.
if !self.document.var_table.variables.is_empty() {
let vars = VariablesPanel::for_document(&self.document);
let intrinsic = vars.intrinsic_height();
let top_y = if has_property {
// Below PropertyPanel — naive offset uses the
// PropertyPanel's own intrinsic height proxy. The
// property panel paints to fill the rail, so we put
// Variables at the bottom of the rail above the
// status bar; users scroll the property pane
// separately. Approximate: anchor to bottom-of-rail.
let bottom_pad = STATUS_BAR_HEIGHT + 16.0;
(viewport_height - bottom_pad - intrinsic).max(TOP_BAR_HEIGHT + 8.0)
} else {
TOP_BAR_HEIGHT + 8.0
};
let vars_rect = Rect {
origin: Point2D::new(right_rail_x, top_y),
size: Point2D::new(property_panel_width, intrinsic),
};
let mut cx = PaintCx {
backend: &mut *frame,
};
vars.paint(&mut cx, vars_rect);
}
// 5. CanvasViewport — middle band, respects sidebar
// collapse state.
let (canvas_left, _canvas_y, canvas_w, canvas_h) =