forked from 1b-agent/opencadstudio-upstream
Add persistent cursor sizing, pick aperture, color, pointer mode, isometric drafting planes, and SNAPANG-aligned grid behavior.\n\nRefs #413
126 lines
3.8 KiB
Rust
126 lines
3.8 KiB
Rust
//! OpenCADStudio-style OSNAP status menu.
|
|
|
|
use iced::widget::{button, checkbox, column, container, row, text};
|
|
use iced::{Background, Element, Fill, Length, Theme};
|
|
|
|
use crate::app::Message;
|
|
use crate::app::settings::IsoPlane;
|
|
use crate::snap::{SnapType, Snapper, ALL_SNAP_MODES};
|
|
use crate::ui::statusbar::status_menu::Entry;
|
|
use crate::t;
|
|
|
|
pub fn menu_entries<'a>(
|
|
snapper: &'a Snapper,
|
|
isometric: bool,
|
|
iso_plane: IsoPlane,
|
|
) -> Vec<Entry<'a>> {
|
|
let all_on = snapper.all_on();
|
|
let none_on = snapper.none_on();
|
|
|
|
let header = row![
|
|
header_btn("Select All", Message::SnapSelectAll, !all_on),
|
|
header_btn("Clear All", Message::SnapClearAll, !none_on),
|
|
]
|
|
.spacing(1)
|
|
.padding([4u16, 8]);
|
|
|
|
// Divider
|
|
let divider = container(iced::widget::Space::new().height(1))
|
|
.style(|theme: &Theme| container::Style {
|
|
background: Some(Background::Color(
|
|
theme.palette().background.weak.color,
|
|
)),
|
|
..Default::default()
|
|
})
|
|
.width(Fill)
|
|
.padding([0, 4]);
|
|
|
|
let mut iso_planes = row![].spacing(3);
|
|
for plane in IsoPlane::ALL {
|
|
iso_planes = iso_planes.push(
|
|
button(text(t!(plane.label())).size(10))
|
|
.on_press(Message::SetIsoPlane(plane))
|
|
.style(if isometric && iso_plane == plane {
|
|
button::primary
|
|
} else {
|
|
button::secondary
|
|
})
|
|
.padding([3, 8]),
|
|
);
|
|
}
|
|
let drafting = column![
|
|
row![
|
|
checkbox(isometric)
|
|
.on_toggle(|_| Message::ToggleIsometricDrafting)
|
|
.size(14),
|
|
text(t!("Isometric drafting")).size(11),
|
|
]
|
|
.spacing(6)
|
|
.align_y(iced::Center),
|
|
iso_planes,
|
|
text(t!("F5 cycles the active plane.")).size(10),
|
|
]
|
|
.spacing(5)
|
|
.padding([5, 8]);
|
|
let drafting_divider = container(iced::widget::Space::new().height(1))
|
|
.style(|theme: &Theme| container::Style {
|
|
background: Some(Background::Color(
|
|
theme.palette().background.weak.color,
|
|
)),
|
|
..Default::default()
|
|
})
|
|
.width(Fill)
|
|
.padding([0, 4]);
|
|
|
|
let mut entries = vec![
|
|
Entry::stay(header),
|
|
Entry::stay(divider),
|
|
Entry::stay(drafting),
|
|
Entry::stay(drafting_divider),
|
|
];
|
|
for &(snap_type, _glyph, label) in ALL_SNAP_MODES {
|
|
entries.push(Entry::stay(snap_row(
|
|
snap_type,
|
|
label,
|
|
snapper.is_on(snap_type),
|
|
)));
|
|
}
|
|
entries
|
|
}
|
|
|
|
// ── Individual snap row ───────────────────────────────────────────────────
|
|
|
|
fn snap_row<'a>(snap_type: SnapType, label: &'a str, active: bool) -> Element<'a, Message> {
|
|
let checkmark = crate::ui::icons::themed_check_cell(active);
|
|
|
|
// SVG marker (not a Unicode glyph) so the symbols render on the web build,
|
|
// whose bundled font lacks them and showed tofu boxes. (#138)
|
|
let icon_el = container(crate::ui::icons::themed_success::<Message>(
|
|
crate::ui::icons::osnap(snap_type),
|
|
13.0,
|
|
))
|
|
.width(Length::Fixed(16.0))
|
|
.align_x(iced::Center);
|
|
|
|
let label_el = text(t!(label)).size(11);
|
|
|
|
let content = row![checkmark, icon_el, label_el]
|
|
.spacing(4)
|
|
.align_y(iced::Center);
|
|
|
|
button(content)
|
|
.on_press(Message::ToggleSnap(snap_type))
|
|
.style(button::subtle)
|
|
.width(Fill)
|
|
.padding([3, 8])
|
|
.into()
|
|
}
|
|
|
|
fn header_btn(label: &str, msg: Message, enabled: bool) -> Element<'_, Message> {
|
|
let b = button(text(t!(label)).size(10));
|
|
let b = if enabled { b.on_press(msg) } else { b };
|
|
b.style(button::secondary)
|
|
.padding([3, 8])
|
|
.into()
|
|
}
|