feat(polar): angle picker dropdown on the POLAR pill (#264)

The polar-tracking pill only right-click-cycled 15→30→45→90. Add an
AutoCAD-style angle picker opened from a caret on the pill: presets
90/45/30/22.5/18/15/10/5/1 plus a free-text field for any custom angle,
mirroring the existing units / scale status-bar popups. The chosen angle
persists like the other user settings.

Factor the shared chrome into one `split_pill(main, caret_msg, active,
open)` helper (+ `pill_text_color`) so the OSNAP and POLAR pills stop
hand-rolling the same outer border, background, caret and sizing — each
pill now only supplies its own main region. The caret is sized and
aligned to sit inside the single pill border on both.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
Hakan SevenandClaude Opus 4.8 committed 2026-07-09 21:35:47 +03:00
1 parent 39c0a84c3c
commit 363ff614ec
6 files changed
+289 -137

No files matched your search

+15 -1
View File
@@ -252,6 +252,10 @@ pub(super) struct OpenCADStudio {
snapper: Snapper,
snap_popup_open: bool,
scale_popup_open: bool,
/// True while the polar-tracking angle picker is open.
polar_popup_open: bool,
/// Live text of the polar picker's custom-angle field.
polar_custom_input: String,
/// True while the status-bar customization menu is open.
statusbar_menu_open: bool,
/// True while the leftmost hamburger's Model/layout list dropdown is open.
@@ -1404,8 +1408,16 @@ pub enum Message {
ToggleLineweightDisplay,
/// Toggle polar-angle constraint — F10 / POLAR status-bar button.
TogglePolar,
/// Set polar tracking angle increment (right-click POLAR button).
/// Set polar tracking angle increment (POLAR picker / right-click cycle).
SetPolarAngle(f32),
/// Open/close the polar-tracking angle picker (POLAR pill caret).
TogglePolarPopup,
/// Close the polar-tracking angle picker.
ClosePolarPopup,
/// Live text edit of the polar picker's custom-angle field.
PolarCustomInput(String),
/// Apply the typed custom polar angle (Enter in the picker's field).
SubmitPolarCustom,
/// Set the model-space annotation scale (CANNOSCALE equivalent).
SetAnnotationScale(f32),
/// Set the active viewport's custom_scale (paper space).
@@ -2045,6 +2057,8 @@ impl OpenCADStudio {
snapper: Snapper::default(),
snap_popup_open: false,
scale_popup_open: false,
polar_popup_open: false,
polar_custom_input: String::new(),
statusbar_menu_open: false,
layout_list_open: false,
units_popup_open: false,
+31
View File
@@ -1561,6 +1561,37 @@ impl OpenCADStudio {
self.polar_increment_deg = deg;
self.polar_mode = true;
self.ortho_mode = false;
self.polar_popup_open = false;
Task::none()
}
Message::TogglePolarPopup => {
self.polar_popup_open ^= true;
if self.polar_popup_open {
// Start the custom field empty each time; picking a preset or
// typing a value is what actually enables polar tracking.
self.polar_custom_input.clear();
}
Task::none()
}
Message::ClosePolarPopup => {
self.polar_popup_open = false;
Task::none()
}
Message::PolarCustomInput(s) => {
self.polar_custom_input = s;
Task::none()
}
Message::SubmitPolarCustom => {
// Accept any positive angle up to a full turn; ignore garbage.
if let Ok(v) = self.polar_custom_input.trim().parse::<f32>() {
if v > 0.0 && v <= 360.0 {
self.polar_increment_deg = v;
self.polar_mode = true;
self.ortho_mode = false;
}
}
self.polar_custom_input.clear();
self.polar_popup_open = false;
Task::none()
}
Message::SetAnnotationScale(scale) => {
+13
View File
@@ -1253,6 +1253,7 @@ impl OpenCADStudio {
self.ortho_mode,
self.polar_mode,
self.polar_increment_deg,
self.polar_popup_open,
self.dyn_input,
self.snapper.otrack_enabled,
tab.scene.layout_names(),
@@ -1320,6 +1321,17 @@ impl OpenCADStudio {
iced::widget::Space::new().width(0).height(0).into()
};
let polar_layer: Element<'_, Message> = if self.polar_popup_open {
crate::ui::popup::polar_popup::polar_popup_overlay(
self.polar_increment_deg,
&self.polar_custom_input,
sb_pill(crate::ui::statusbar::SB_POLAR_ID),
win,
)
} else {
iced::widget::Space::new().width(0).height(0).into()
};
let statusbar_menu_layer: Element<'_, Message> = if self.statusbar_menu_open {
crate::ui::statusbar::statusbar_menu::statusbar_menu_overlay(
&self.statusbar_config,
@@ -1412,6 +1424,7 @@ impl OpenCADStudio {
main_ui,
snap_layer,
scale_layer,
polar_layer,
statusbar_menu_layer,
layout_list_layer,
units_layer,