diff --git a/crates/openpencil-shell-native/src/widget_host/input.rs b/crates/openpencil-shell-native/src/widget_host/input.rs index 142749bd2..322e93f7b 100644 --- a/crates/openpencil-shell-native/src/widget_host/input.rs +++ b/crates/openpencil-shell-native/src/widget_host/input.rs @@ -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 { diff --git a/crates/openpencil-shell-native/src/widget_host/paint.rs b/crates/openpencil-shell-native/src/widget_host/paint.rs index 7d5c88540..a804dd548 100644 --- a/crates/openpencil-shell-native/src/widget_host/paint.rs +++ b/crates/openpencil-shell-native/src/widget_host/paint.rs @@ -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) =