forked from 1b-agent/opencadstudio-upstream
refactor(ui): use pin for anchored overlays
This commit is contained in:
1 parent
b9de8940bc
commit
ce1091cea5
5 files changed
+51
-98
No files matched your search
+33
-64
@@ -742,18 +742,12 @@ impl OpenCADStudio {
|
||||
])
|
||||
.report_width0(self.render_bar_w.clone())
|
||||
.into();
|
||||
// Position the bar at the active model tile's top-left corner so it
|
||||
// follows the active panel in a tiled layout (full canvas when a
|
||||
// single tile fills the window). Leading Spaces offset it.
|
||||
let bar_layer = column![
|
||||
Space::new().height(iced::Length::Fixed(rect.y.max(0.0))),
|
||||
row![
|
||||
Space::new().width(iced::Length::Fixed(rect.x.max(0.0))),
|
||||
container(adaptive).width(iced::Length::Fixed(rect.width.max(1.0))),
|
||||
],
|
||||
]
|
||||
.width(Fill)
|
||||
.height(Fill);
|
||||
// Pin the bar to the active model tile's top-left corner so it
|
||||
// follows the active panel in a tiled layout.
|
||||
let bar_layer = crate::ui::pin_at(
|
||||
iced::Point::new(rect.x, rect.y),
|
||||
container(adaptive).width(iced::Length::Fixed(rect.width.max(1.0))),
|
||||
);
|
||||
viewport_stack = viewport_stack.push(bar_layer);
|
||||
}
|
||||
|
||||
@@ -802,12 +796,7 @@ impl OpenCADStudio {
|
||||
},
|
||||
..Default::default()
|
||||
});
|
||||
let border_layer = column![
|
||||
Space::new().height(iced::Length::Fixed(y)),
|
||||
row![Space::new().width(iced::Length::Fixed(x)), border_frame,],
|
||||
]
|
||||
.width(Fill)
|
||||
.height(Fill);
|
||||
let border_layer = crate::ui::pin_at(iced::Point::new(x, y), border_frame);
|
||||
viewport_stack = viewport_stack.push(border_layer);
|
||||
|
||||
let vp_mode = tab
|
||||
@@ -833,15 +822,10 @@ impl OpenCADStudio {
|
||||
])
|
||||
.report_width0(self.render_bar_w.clone())
|
||||
.into();
|
||||
let picker_layer = column![
|
||||
Space::new().height(iced::Length::Fixed(y + 4.0)),
|
||||
row![
|
||||
Space::new().width(iced::Length::Fixed(x + 4.0)),
|
||||
container(adaptive).width(iced::Length::Fixed(rect.width.max(1.0))),
|
||||
],
|
||||
]
|
||||
.width(Fill)
|
||||
.height(Fill);
|
||||
let picker_layer = crate::ui::pin_at(
|
||||
iced::Point::new(x + 4.0, y + 4.0),
|
||||
container(adaptive).width(iced::Length::Fixed(rect.width.max(1.0))),
|
||||
);
|
||||
viewport_stack = viewport_stack.push(picker_layer);
|
||||
|
||||
// Hide the ViewCube first — before the render bar — when they collide.
|
||||
@@ -849,15 +833,10 @@ impl OpenCADStudio {
|
||||
let cube_x = (rect.x + rect.width - VIEWCUBE_HIT_SIZE - VIEWCUBE_PAD).max(0.0);
|
||||
let cube_y = (rect.y + VIEWCUBE_PAD).max(0.0);
|
||||
|
||||
let controls = column![
|
||||
Space::new().height(iced::Length::Fixed(cube_y)),
|
||||
row![
|
||||
Space::new().width(iced::Length::Fixed(cube_x)),
|
||||
viewcube_nav_controls(),
|
||||
],
|
||||
]
|
||||
.width(Fill)
|
||||
.height(Fill);
|
||||
let controls = crate::ui::pin_at(
|
||||
iced::Point::new(cube_x, cube_y),
|
||||
viewcube_nav_controls(),
|
||||
);
|
||||
viewport_stack = viewport_stack.push(controls);
|
||||
|
||||
let ucs_current = tab
|
||||
@@ -873,16 +852,13 @@ impl OpenCADStudio {
|
||||
.map(|u| u.name.clone())
|
||||
.filter(|n| !n.is_empty())
|
||||
.collect();
|
||||
let picker = column![
|
||||
Space::new().height(iced::Length::Fixed(cube_y + VIEWCUBE_HIT_SIZE + 6.0)),
|
||||
row![
|
||||
Space::new()
|
||||
.width(iced::Length::Fixed(cube_x + VIEWCUBE_HIT_SIZE * 0.5 - UCS_PICKER_W * 0.5)),
|
||||
iced::widget::opaque(viewcube_ucs_picker(ucs_current, ucs_names)),
|
||||
],
|
||||
]
|
||||
.width(Fill)
|
||||
.height(Fill);
|
||||
let picker = crate::ui::pin_at(
|
||||
iced::Point::new(
|
||||
cube_x + VIEWCUBE_HIT_SIZE * 0.5 - UCS_PICKER_W * 0.5,
|
||||
cube_y + VIEWCUBE_HIT_SIZE + 6.0,
|
||||
),
|
||||
iced::widget::opaque(viewcube_ucs_picker(ucs_current, ucs_names)),
|
||||
);
|
||||
viewport_stack = viewport_stack.push(picker);
|
||||
}
|
||||
}
|
||||
@@ -897,15 +873,10 @@ impl OpenCADStudio {
|
||||
let cube_y = (rect.y + VIEWCUBE_PAD).max(0.0);
|
||||
|
||||
// Cube hit area + nav controls (home / roll / nudge) as one layer.
|
||||
let controls = column![
|
||||
Space::new().height(iced::Length::Fixed(cube_y)),
|
||||
row![
|
||||
Space::new().width(iced::Length::Fixed(cube_x)),
|
||||
viewcube_nav_controls(),
|
||||
],
|
||||
]
|
||||
.width(Fill)
|
||||
.height(Fill);
|
||||
let controls = crate::ui::pin_at(
|
||||
iced::Point::new(cube_x, cube_y),
|
||||
viewcube_nav_controls(),
|
||||
);
|
||||
viewport_stack = viewport_stack.push(controls);
|
||||
|
||||
// WCS / named-UCS selector under the cube.
|
||||
@@ -922,15 +893,13 @@ impl OpenCADStudio {
|
||||
.map(|u| u.name.clone())
|
||||
.filter(|n| !n.is_empty())
|
||||
.collect();
|
||||
let picker = column![
|
||||
Space::new().height(iced::Length::Fixed(cube_y + VIEWCUBE_HIT_SIZE + 6.0)),
|
||||
row![
|
||||
Space::new().width(iced::Length::Fixed(cube_x + VIEWCUBE_HIT_SIZE * 0.5 - UCS_PICKER_W * 0.5)),
|
||||
iced::widget::opaque(viewcube_ucs_picker(ucs_current, ucs_names)),
|
||||
],
|
||||
]
|
||||
.width(Fill)
|
||||
.height(Fill);
|
||||
let picker = crate::ui::pin_at(
|
||||
iced::Point::new(
|
||||
cube_x + VIEWCUBE_HIT_SIZE * 0.5 - UCS_PICKER_W * 0.5,
|
||||
cube_y + VIEWCUBE_HIT_SIZE + 6.0,
|
||||
),
|
||||
iced::widget::opaque(viewcube_ucs_picker(ucs_current, ucs_names)),
|
||||
);
|
||||
viewport_stack = viewport_stack.push(picker);
|
||||
}
|
||||
|
||||
|
||||
+1
-12
@@ -9,18 +9,7 @@ pub(super) fn position_canvas_overlay<'a>(
|
||||
anchor: iced::Point,
|
||||
panel: Element<'a, Message>,
|
||||
) -> Element<'a, Message> {
|
||||
let ax = anchor.x.max(0.0);
|
||||
let ay = anchor.y.max(0.0);
|
||||
column![
|
||||
Space::new().height(iced::Length::Fixed(ay)),
|
||||
row![
|
||||
Space::new().width(iced::Length::Fixed(ax)),
|
||||
iced::widget::opaque(panel),
|
||||
],
|
||||
]
|
||||
.width(Fill)
|
||||
.height(Fill)
|
||||
.into()
|
||||
crate::ui::pin_at(anchor, iced::widget::opaque(panel))
|
||||
}
|
||||
|
||||
// ── In-place MText editor overlay ───────────────────────────────────────────
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
use super::super::Message;
|
||||
use crate::scene::{VIEWCUBE_PX, VIEWCUBE_REGION_PX};
|
||||
use iced::widget::{
|
||||
button, column, container, mouse_area, pick_list, row, stack,
|
||||
Space,
|
||||
button, container, mouse_area, pick_list, stack, Space,
|
||||
};
|
||||
use iced::{Background, Border, Color, Element, Fill, Theme};
|
||||
use iced::{Background, Border, Color, Element, Theme};
|
||||
|
||||
// ── Render-mode picker ──────────────────────────────────────────────────────
|
||||
|
||||
@@ -15,15 +14,9 @@ use iced::{Background, Border, Color, Element, Fill, Theme};
|
||||
/// state and emit `ToggleGrid` / `ToggleGridSnap`.
|
||||
// ── ViewCube navigation controls (home / roll / nudge / UCS) ───────────────
|
||||
|
||||
/// Place `el` at pixel offset (x, y) inside a Fill layer (top-left origin).
|
||||
/// Place `el` at pixel offset (x, y) inside a fill layer (top-left origin).
|
||||
fn vc_place<'a>(x: f32, y: f32, el: Element<'a, Message>) -> Element<'a, Message> {
|
||||
column![
|
||||
Space::new().height(iced::Length::Fixed(y.max(0.0))),
|
||||
row![Space::new().width(iced::Length::Fixed(x.max(0.0))), el],
|
||||
]
|
||||
.width(Fill)
|
||||
.height(Fill)
|
||||
.into()
|
||||
crate::ui::pin_at(iced::Point::new(x, y), el)
|
||||
}
|
||||
|
||||
/// Borderless square icon button used by the ViewCube nav controls.
|
||||
@@ -198,4 +191,3 @@ pub(super) fn viewcube_ucs_picker<'a>(current: String, names: Vec<String>) -> El
|
||||
})
|
||||
.into()
|
||||
}
|
||||
|
||||
@@ -2,6 +2,17 @@
|
||||
/// Change this to scale the ribbon, layer manager rows, and property panel rows uniformly.
|
||||
pub const ROW_H: f32 = 26.0;
|
||||
|
||||
/// Place `content` at fixed top-left coordinates inside a fill-sized layer.
|
||||
/// Negative coordinates clamp to the layer edge.
|
||||
pub fn pin_at<'a, Message: 'a>(
|
||||
position: iced::Point,
|
||||
content: impl Into<iced::Element<'a, Message>>,
|
||||
) -> iced::Element<'a, Message> {
|
||||
iced::widget::pin(content)
|
||||
.position(iced::Point::new(position.x.max(0.0), position.y.max(0.0)))
|
||||
.into()
|
||||
}
|
||||
|
||||
pub mod color_select;
|
||||
pub mod command_line;
|
||||
pub mod icons;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
//! two or more overlapping objects. Each row names a candidate; clicking it
|
||||
//! adds that object to the current selection. Clicking outside dismisses it.
|
||||
|
||||
use iced::widget::{button, column, container, mouse_area, opaque, row, text, Space};
|
||||
use iced::widget::{button, column, container, mouse_area, opaque, text};
|
||||
use iced::{Background, Border, Color, Element, Fill, Length, Theme};
|
||||
|
||||
use crate::app::Message;
|
||||
@@ -30,15 +30,7 @@ pub fn cycle_popup_overlay(
|
||||
})
|
||||
.width(Length::Fixed(150.0));
|
||||
|
||||
let positioned = column![
|
||||
Space::new().height(Length::Fixed(anchor.y.max(0.0))),
|
||||
row![
|
||||
Space::new().width(Length::Fixed(anchor.x.max(0.0))),
|
||||
opaque(panel),
|
||||
],
|
||||
]
|
||||
.width(Fill)
|
||||
.height(Fill);
|
||||
let positioned = crate::ui::pin_at(anchor, opaque(panel));
|
||||
|
||||
mouse_area(positioned).on_press(Message::CycleCancel).into()
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user