From 7cd938443e10d239fe46f51585abe572830628f2 Mon Sep 17 00:00:00 2001 From: Hakan Seven Date: Tue, 16 Jun 2026 23:29:50 +0300 Subject: [PATCH] feat(ui): migrate Text Style and Multiline Style to modals (Plan B) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the Text Style and Multiline Style editors off OS windows onto the shared `active_modal` / `modal_content` path. Their open handlers set `active_modal` (keeping the existing buffer/stage setup); construction moves from the daemon `view` dispatch into `modal_content`. The remaining style editors (Table, MLeader, Dimension) still use OS windows for now — they carry a nested colour picker that needs its own handling. Native + web build; 75 tests pass. Co-Authored-By: Claude Opus 4.8 --- src/app/mod.rs | 5 ++ src/app/update.rs | 40 +++---------- src/app/view.rs | 139 +++++++++++++++++++++++----------------------- 3 files changed, 83 insertions(+), 101 deletions(-) diff --git a/src/app/mod.rs b/src/app/mod.rs index 0a611403f..8b11aced0 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -601,6 +601,11 @@ pub enum ModalKind { PageSetup, LayoutManager, Plotstyle, + TextStyle, + TableStyle, + MlStyle, + MLeaderStyle, + DimStyle, } /// Identifies a DimStyle field that can be edited in the dialog. diff --git a/src/app/update.rs b/src/app/update.rs index b37a36370..d64687b9e 100644 --- a/src/app/update.rs +++ b/src/app/update.rs @@ -6349,25 +6349,13 @@ impl OpenCADStudio { .unwrap_or_else(|| "Standard".to_string()) }; self.load_textstyle_bufs(i); - if let Some(id) = self.textstyle_window { - return window::gain_focus(id); - } - let (id, task) = window::open(window::Settings { - size: iced::Size::new(620.0, 460.0), - resizable: true, - level: window::Level::AlwaysOnTop, - ..Default::default() - }); - self.textstyle_window = Some(id); + self.active_modal = Some(super::ModalKind::TextStyle); self.style_stage_begin(); - task.map(|_| Message::Noop) + Task::none() } Message::TextStyleDialogClose => { - if let Some(id) = self.textstyle_window.take() { - window::close(id) - } else { - Task::none() - } + self.active_modal = None; + Task::none() } Message::TextStyleDialogSelect(name) => { let i = self.active_tab; @@ -6830,25 +6818,13 @@ impl OpenCADStudio { }) .unwrap_or_else(|| "Standard".to_string()) }; - if let Some(id) = self.mlstyle_window { - return window::gain_focus(id); - } - let (id, task) = window::open(window::Settings { - size: iced::Size::new(620.0, 420.0), - resizable: true, - level: window::Level::AlwaysOnTop, - ..Default::default() - }); - self.mlstyle_window = Some(id); + self.active_modal = Some(super::ModalKind::MlStyle); self.style_stage_begin(); - task.map(|_| Message::Noop) + Task::none() } Message::MlStyleDialogClose => { - if let Some(id) = self.mlstyle_window.take() { - window::close(id) - } else { - Task::none() - } + self.active_modal = None; + Task::none() } Message::MlStyleDialogSelect(name) => { self.mlstyle_selected = name; diff --git a/src/app/view.rs b/src/app/view.rs index d8ae4420c..62f9df6e5 100644 --- a/src/app/view.rs +++ b/src/app/view.rs @@ -40,39 +40,6 @@ impl std::fmt::Display for RenderModeChoice { impl OpenCADStudio { pub fn view(&self, window_id: window::Id) -> Element<'_, Message> { // ── Floating panel windows ───────────────────────────────────────── - if Some(window_id) == self.textstyle_window { - let tab = &self.tabs[self.active_tab]; - let styles: Vec = tab - .scene - .document - .text_styles - .iter() - .map(|s| s.name.clone()) - .collect(); - let (backward, upside_down, annotative) = tab - .scene - .document - .text_styles - .get(&self.textstyle_selected) - .map(|s| (s.flags.backward, s.flags.upside_down, s.annotative)) - .unwrap_or((false, false, false)); - return crate::ui::textstyle::view_window(crate::ui::textstyle::TextStyleView { - styles, - selected: &self.textstyle_selected, - current: &tab.scene.document.header.current_text_style_name, - font_buf: &self.textstyle_font, - width_buf: &self.textstyle_width, - oblique_buf: &self.textstyle_oblique, - height_buf: &self.textstyle_height, - bigfont_buf: &self.textstyle_bigfont, - ttf_buf: &self.textstyle_ttf, - backward, - upside_down, - annotative, - rename_active: self.style_rename.as_deref(), - rename_buf: &self.style_rename_buf, - }); - } if Some(window_id) == self.tablestyle_window { use acadrust::objects::ObjectType; let tab = &self.tabs[self.active_tab]; @@ -123,42 +90,6 @@ impl OpenCADStudio { self.ts_color_open, ); } - if Some(window_id) == self.mlstyle_window { - use acadrust::objects::ObjectType; - let tab = &self.tabs[self.active_tab]; - let styles: Vec = tab - .scene - .document - .objects - .values() - .filter_map(|o| { - if let ObjectType::MLineStyle(s) = o { - Some(s.name.clone()) - } else { - None - } - }) - .collect(); - let selected_style = tab.scene.document.objects.values().find_map(|o| { - if let ObjectType::MLineStyle(s) = o { - if s.name == self.mlstyle_selected { - Some(s) - } else { - None - } - } else { - None - } - }); - return crate::ui::mlstyle::view_window( - styles, - &self.mlstyle_selected, - selected_style, - tab.scene.document.header.multiline_style.clone(), - self.style_rename.as_deref(), - &self.style_rename_buf, - ); - } if Some(window_id) == self.mleaderstyle_window { use acadrust::objects::ObjectType; let tab = &self.tabs[self.active_tab]; @@ -1542,6 +1473,76 @@ impl OpenCADStudio { 780, 540, ), + super::ModalKind::TextStyle => { + let tab = &self.tabs[self.active_tab]; + let styles: Vec = tab + .scene + .document + .text_styles + .iter() + .map(|s| s.name.clone()) + .collect(); + let (backward, upside_down, annotative) = tab + .scene + .document + .text_styles + .get(&self.textstyle_selected) + .map(|s| (s.flags.backward, s.flags.upside_down, s.annotative)) + .unwrap_or((false, false, false)); + sized( + crate::ui::textstyle::view_window(crate::ui::textstyle::TextStyleView { + styles, + selected: &self.textstyle_selected, + current: &tab.scene.document.header.current_text_style_name, + font_buf: &self.textstyle_font, + width_buf: &self.textstyle_width, + oblique_buf: &self.textstyle_oblique, + height_buf: &self.textstyle_height, + bigfont_buf: &self.textstyle_bigfont, + ttf_buf: &self.textstyle_ttf, + backward, + upside_down, + annotative, + rename_active: self.style_rename.as_deref(), + rename_buf: &self.style_rename_buf, + }), + 620, + 460, + ) + } + super::ModalKind::MlStyle => { + use acadrust::objects::ObjectType; + let tab = &self.tabs[self.active_tab]; + let styles: Vec = tab + .scene + .document + .objects + .values() + .filter_map(|o| match o { + ObjectType::MLineStyle(s) => Some(s.name.clone()), + _ => None, + }) + .collect(); + let selected_style = tab.scene.document.objects.values().find_map(|o| match o { + ObjectType::MLineStyle(s) if s.name == self.mlstyle_selected => Some(s), + _ => None, + }); + sized( + crate::ui::mlstyle::view_window( + styles, + &self.mlstyle_selected, + selected_style, + tab.scene.document.header.multiline_style.clone(), + self.style_rename.as_deref(), + &self.style_rename_buf, + ), + 620, + 420, + ) + } + super::ModalKind::TableStyle + | super::ModalKind::MLeaderStyle + | super::ModalKind::DimStyle => return None, }) }