forked from 1b-agent/opencadstudio-upstream
feat(ui): migrate style editors + nested colour picker (Plan B)
Move Table Style, MLeader Style and Dimension Style editors off OS windows onto `active_modal` / `modal_content`, and turn the colour picker into a nested modal that stacks over whichever dialog requested it (`color_pick_target.is_some()` drives the overlay; CloseColorPicker dismisses it). OpenColorWindow/ColorWindowPick no longer open/close an OS window. All thirteen former pop-up windows now render as in-canvas modals on both native and web; only the native-only assoc/unsaved/save dialogs remain as OS windows. Native + web build; 75 tests pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
1 parent
7cd938443e
commit
28232f1247
3 files changed
+349
-383
No files matched your search
@@ -1321,6 +1321,8 @@ pub enum Message {
|
|||||||
DsColorMore(DsField),
|
DsColorMore(DsField),
|
||||||
/// Open the standalone palette window targeting the given field.
|
/// Open the standalone palette window targeting the given field.
|
||||||
OpenColorWindow(ColorPickTarget),
|
OpenColorWindow(ColorPickTarget),
|
||||||
|
/// Close the nested colour-picker modal without choosing (Plan B).
|
||||||
|
CloseColorPicker,
|
||||||
/// A colour was chosen in the standalone palette window.
|
/// A colour was chosen in the standalone palette window.
|
||||||
ColorWindowPick(acadrust::types::Color),
|
ColorWindowPick(acadrust::types::Color),
|
||||||
/// Set a block/linetype Handle field on the selected dim style from a
|
/// Set a block/linetype Handle field on the selected dim style from a
|
||||||
|
|||||||
+22
-56
@@ -6490,22 +6490,13 @@ impl OpenCADStudio {
|
|||||||
if let Some(id) = self.tablestyle_window {
|
if let Some(id) = self.tablestyle_window {
|
||||||
return window::gain_focus(id);
|
return window::gain_focus(id);
|
||||||
}
|
}
|
||||||
let (id, task) = window::open(window::Settings {
|
self.active_modal = Some(super::ModalKind::TableStyle);
|
||||||
size: iced::Size::new(620.0, 420.0),
|
|
||||||
resizable: true,
|
|
||||||
level: window::Level::AlwaysOnTop,
|
|
||||||
..Default::default()
|
|
||||||
});
|
|
||||||
self.tablestyle_window = Some(id);
|
|
||||||
self.style_stage_begin();
|
self.style_stage_begin();
|
||||||
task.map(|_| Message::Noop)
|
Task::none()
|
||||||
}
|
}
|
||||||
Message::TableStyleDialogClose => {
|
Message::TableStyleDialogClose => {
|
||||||
if let Some(id) = self.tablestyle_window.take() {
|
self.active_modal = None;
|
||||||
window::close(id)
|
Task::none()
|
||||||
} else {
|
|
||||||
Task::none()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Message::TableStyleDialogSelect(name) => {
|
Message::TableStyleDialogSelect(name) => {
|
||||||
self.tablestyle_selected = name;
|
self.tablestyle_selected = name;
|
||||||
@@ -6903,22 +6894,13 @@ impl OpenCADStudio {
|
|||||||
if let Some(id) = self.mleaderstyle_window {
|
if let Some(id) = self.mleaderstyle_window {
|
||||||
return window::gain_focus(id);
|
return window::gain_focus(id);
|
||||||
}
|
}
|
||||||
let (id, task) = window::open(window::Settings {
|
self.active_modal = Some(super::ModalKind::MLeaderStyle);
|
||||||
size: iced::Size::new(560.0, 560.0),
|
|
||||||
resizable: true,
|
|
||||||
level: window::Level::AlwaysOnTop,
|
|
||||||
..Default::default()
|
|
||||||
});
|
|
||||||
self.mleaderstyle_window = Some(id);
|
|
||||||
self.style_stage_begin();
|
self.style_stage_begin();
|
||||||
task.map(|_| Message::Noop)
|
Task::none()
|
||||||
}
|
}
|
||||||
Message::MLeaderStyleDialogClose => {
|
Message::MLeaderStyleDialogClose => {
|
||||||
if let Some(id) = self.mleaderstyle_window.take() {
|
self.active_modal = None;
|
||||||
window::close(id)
|
Task::none()
|
||||||
} else {
|
|
||||||
Task::none()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Message::MLeaderStyleDialogSelect(name) => {
|
Message::MLeaderStyleDialogSelect(name) => {
|
||||||
self.mleaderstyle_selected = name;
|
self.mleaderstyle_selected = name;
|
||||||
@@ -7260,22 +7242,13 @@ impl OpenCADStudio {
|
|||||||
if let Some(id) = self.dimstyle_window {
|
if let Some(id) = self.dimstyle_window {
|
||||||
return window::gain_focus(id);
|
return window::gain_focus(id);
|
||||||
}
|
}
|
||||||
let (id, task) = window::open(window::Settings {
|
self.active_modal = Some(super::ModalKind::DimStyle);
|
||||||
size: iced::Size::new(720.0, 560.0),
|
|
||||||
resizable: true,
|
|
||||||
level: window::Level::AlwaysOnTop,
|
|
||||||
..Default::default()
|
|
||||||
});
|
|
||||||
self.dimstyle_window = Some(id);
|
|
||||||
self.style_stage_begin();
|
self.style_stage_begin();
|
||||||
task.map(|_| Message::Noop)
|
Task::none()
|
||||||
}
|
}
|
||||||
Message::DimStyleDialogClose => {
|
Message::DimStyleDialogClose => {
|
||||||
if let Some(id) = self.dimstyle_window.take() {
|
self.active_modal = None;
|
||||||
window::close(id)
|
Task::none()
|
||||||
} else {
|
|
||||||
Task::none()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Message::DimStyleDialogApply => {
|
Message::DimStyleDialogApply => {
|
||||||
let i = self.active_tab;
|
let i = self.active_tab;
|
||||||
@@ -7343,17 +7316,13 @@ impl OpenCADStudio {
|
|||||||
let i = self.active_tab;
|
let i = self.active_tab;
|
||||||
self.tabs[i].properties.color_picker_open = false;
|
self.tabs[i].properties.color_picker_open = false;
|
||||||
self.tabs[i].layers.color_picker_row = None;
|
self.tabs[i].layers.color_picker_row = None;
|
||||||
if let Some(id) = self.color_pick_window {
|
// Shown as a nested modal over the active dialog (Plan B):
|
||||||
return window::gain_focus(id);
|
// `color_pick_target.is_some()` drives the overlay in view_main.
|
||||||
}
|
Task::none()
|
||||||
let (id, task) = window::open(window::Settings {
|
}
|
||||||
size: iced::Size::new(420.0, 470.0),
|
Message::CloseColorPicker => {
|
||||||
resizable: true,
|
self.color_pick_target = None;
|
||||||
level: window::Level::AlwaysOnTop,
|
Task::none()
|
||||||
..Default::default()
|
|
||||||
});
|
|
||||||
self.color_pick_window = Some(id);
|
|
||||||
task.map(|_| Message::Noop)
|
|
||||||
}
|
}
|
||||||
Message::ColorWindowPick(color) => {
|
Message::ColorWindowPick(color) => {
|
||||||
let s = crate::ui::color_select::color_to_aci_string(color);
|
let s = crate::ui::color_select::color_to_aci_string(color);
|
||||||
@@ -7384,14 +7353,11 @@ impl OpenCADStudio {
|
|||||||
}
|
}
|
||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
let mut tasks = Vec::new();
|
|
||||||
if let Some(m) = edit {
|
if let Some(m) = edit {
|
||||||
tasks.push(self.update(m));
|
self.update(m)
|
||||||
|
} else {
|
||||||
|
Task::none()
|
||||||
}
|
}
|
||||||
if let Some(id) = self.color_pick_window.take() {
|
|
||||||
tasks.push(window::close(id));
|
|
||||||
}
|
|
||||||
Task::batch(tasks)
|
|
||||||
}
|
}
|
||||||
Message::DsSetHandle { field, value } => {
|
Message::DsSetHandle { field, value } => {
|
||||||
let i = self.active_tab;
|
let i = self.active_tab;
|
||||||
|
|||||||
+325
-327
@@ -40,329 +40,6 @@ impl std::fmt::Display for RenderModeChoice {
|
|||||||
impl OpenCADStudio {
|
impl OpenCADStudio {
|
||||||
pub fn view(&self, window_id: window::Id) -> Element<'_, Message> {
|
pub fn view(&self, window_id: window::Id) -> Element<'_, Message> {
|
||||||
// ── Floating panel windows ─────────────────────────────────────────
|
// ── Floating panel windows ─────────────────────────────────────────
|
||||||
if Some(window_id) == self.tablestyle_window {
|
|
||||||
use acadrust::objects::ObjectType;
|
|
||||||
let tab = &self.tabs[self.active_tab];
|
|
||||||
let styles: Vec<String> = tab
|
|
||||||
.scene
|
|
||||||
.document
|
|
||||||
.objects
|
|
||||||
.values()
|
|
||||||
.filter_map(|o| {
|
|
||||||
if let ObjectType::TableStyle(s) = o {
|
|
||||||
Some(s.name.clone())
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
let selected_style = tab.scene.document.objects.values().find_map(|o| {
|
|
||||||
if let ObjectType::TableStyle(s) = o {
|
|
||||||
if s.name == self.tablestyle_selected {
|
|
||||||
Some(s)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return crate::ui::tablestyle::view_window(
|
|
||||||
styles,
|
|
||||||
&self.tablestyle_selected,
|
|
||||||
&self.ribbon.active_table_style,
|
|
||||||
selected_style,
|
|
||||||
&self.ts_hmargin,
|
|
||||||
&self.ts_vmargin,
|
|
||||||
&self.ts_description,
|
|
||||||
&self.ts_cell_textstyle,
|
|
||||||
&self.ts_cell_height,
|
|
||||||
&self.ts_cell_textcolor,
|
|
||||||
&self.ts_cell_fillcolor,
|
|
||||||
&self.ts_cell_datatype,
|
|
||||||
&self.ts_cell_unittype,
|
|
||||||
&self.ts_cell_format,
|
|
||||||
&self.ts_border_lw,
|
|
||||||
&self.ts_border_color,
|
|
||||||
&self.ts_border_spacing,
|
|
||||||
self.style_rename.as_deref(),
|
|
||||||
&self.style_rename_buf,
|
|
||||||
self.ts_color_open,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if Some(window_id) == self.mleaderstyle_window {
|
|
||||||
use acadrust::objects::ObjectType;
|
|
||||||
let tab = &self.tabs[self.active_tab];
|
|
||||||
let styles: Vec<String> = tab
|
|
||||||
.scene
|
|
||||||
.document
|
|
||||||
.objects
|
|
||||||
.values()
|
|
||||||
.filter_map(|o| {
|
|
||||||
if let ObjectType::MultiLeaderStyle(s) = o {
|
|
||||||
Some(s.name.clone())
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
let selected_style = tab.scene.document.objects.values().find_map(|o| {
|
|
||||||
if let ObjectType::MultiLeaderStyle(s) = o {
|
|
||||||
if s.name == self.mleaderstyle_selected {
|
|
||||||
Some(s)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
});
|
|
||||||
let doc = &tab.scene.document;
|
|
||||||
let mut block_opts: Vec<String> = vec!["None".to_string()];
|
|
||||||
block_opts.extend(doc.block_records.iter().map(|b| b.name.clone()));
|
|
||||||
let mut lt_opts: Vec<String> = vec!["None".to_string()];
|
|
||||||
lt_opts.extend(doc.line_types.iter().map(|lt| lt.name.clone()));
|
|
||||||
let mut textstyle_opts: Vec<String> = vec!["None".to_string()];
|
|
||||||
textstyle_opts.extend(doc.text_styles.iter().map(|t| t.name.clone()));
|
|
||||||
let opt_block = |h: Option<acadrust::types::Handle>| -> String {
|
|
||||||
match h {
|
|
||||||
Some(h) => doc
|
|
||||||
.block_records
|
|
||||||
.iter()
|
|
||||||
.find(|b| b.handle == h)
|
|
||||||
.map(|b| b.name.clone())
|
|
||||||
.unwrap_or_else(|| "None".to_string()),
|
|
||||||
None => "None".to_string(),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let opt_lt = |h: Option<acadrust::types::Handle>| -> String {
|
|
||||||
match h {
|
|
||||||
Some(h) => doc
|
|
||||||
.line_types
|
|
||||||
.iter()
|
|
||||||
.find(|lt| lt.handle == h)
|
|
||||||
.map(|lt| lt.name.clone())
|
|
||||||
.unwrap_or_else(|| "None".to_string()),
|
|
||||||
None => "None".to_string(),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let opt_ts = |h: Option<acadrust::types::Handle>| -> String {
|
|
||||||
match h {
|
|
||||||
Some(h) => doc
|
|
||||||
.text_styles
|
|
||||||
.iter()
|
|
||||||
.find(|t| t.handle == h)
|
|
||||||
.map(|t| t.name.clone())
|
|
||||||
.unwrap_or_else(|| "None".to_string()),
|
|
||||||
None => "None".to_string(),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let (line_type_name, arrowhead_name, text_style_name, block_content_name) =
|
|
||||||
match selected_style {
|
|
||||||
Some(s) => (
|
|
||||||
opt_lt(s.line_type_handle),
|
|
||||||
opt_block(s.arrowhead_handle),
|
|
||||||
opt_ts(s.text_style_handle),
|
|
||||||
opt_block(s.block_content_handle),
|
|
||||||
),
|
|
||||||
None => Default::default(),
|
|
||||||
};
|
|
||||||
return crate::ui::mleaderstyle::view_window(
|
|
||||||
crate::ui::mleaderstyle::MLeaderStyleView {
|
|
||||||
styles,
|
|
||||||
selected: &self.mleaderstyle_selected,
|
|
||||||
style: selected_style,
|
|
||||||
current: tab.active_mleader_style.clone(),
|
|
||||||
landing_distance: &self.mls_landing_distance,
|
|
||||||
landing_gap: &self.mls_landing_gap,
|
|
||||||
arrowhead_size: &self.mls_arrowhead_size,
|
|
||||||
text_height: &self.mls_text_height,
|
|
||||||
scale_factor: &self.mls_scale_factor,
|
|
||||||
break_gap: &self.mls_break_gap,
|
|
||||||
first_seg_angle: &self.mls_first_seg_angle,
|
|
||||||
second_seg_angle: &self.mls_second_seg_angle,
|
|
||||||
max_points: &self.mls_max_points,
|
|
||||||
default_text: &self.mls_default_text,
|
|
||||||
line_color: &self.mls_line_color,
|
|
||||||
text_color: &self.mls_text_color,
|
|
||||||
description: &self.mls_description,
|
|
||||||
line_weight: &self.mls_line_weight,
|
|
||||||
align_space: &self.mls_align_space,
|
|
||||||
block_color: &self.mls_block_color,
|
|
||||||
block_rotation: &self.mls_block_rotation,
|
|
||||||
block_scale_x: &self.mls_block_scale_x,
|
|
||||||
block_scale_y: &self.mls_block_scale_y,
|
|
||||||
block_scale_z: &self.mls_block_scale_z,
|
|
||||||
block_opts,
|
|
||||||
lt_opts,
|
|
||||||
textstyle_opts,
|
|
||||||
line_type_name,
|
|
||||||
arrowhead_name,
|
|
||||||
text_style_name,
|
|
||||||
block_content_name,
|
|
||||||
rename_active: self.style_rename.as_deref(),
|
|
||||||
rename_buf: &self.style_rename_buf,
|
|
||||||
color_open: self.mls_color_open,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if Some(window_id) == self.dimstyle_window {
|
|
||||||
let tab = &self.tabs[self.active_tab];
|
|
||||||
let styles: Vec<String> = tab
|
|
||||||
.scene
|
|
||||||
.document
|
|
||||||
.dim_styles
|
|
||||||
.iter()
|
|
||||||
.map(|s| s.name.clone())
|
|
||||||
.collect();
|
|
||||||
let doc = &tab.scene.document;
|
|
||||||
// Dropdown options (names must match the records exactly so the
|
|
||||||
// selection can be resolved back to a handle on the update side).
|
|
||||||
let mut block_opts: Vec<String> = vec!["Default".to_string()];
|
|
||||||
block_opts.extend(doc.block_records.iter().map(|b| b.name.clone()));
|
|
||||||
let mut lt_opts: Vec<String> = vec!["ByBlock".to_string()];
|
|
||||||
lt_opts.extend(doc.line_types.iter().map(|lt| lt.name.clone()));
|
|
||||||
let blk_name = |h: acadrust::types::Handle| -> String {
|
|
||||||
if h.is_null() {
|
|
||||||
"Default".to_string()
|
|
||||||
} else {
|
|
||||||
doc.block_records
|
|
||||||
.iter()
|
|
||||||
.find(|b| b.handle == h)
|
|
||||||
.map(|b| b.name.clone())
|
|
||||||
.unwrap_or_else(|| "Default".to_string())
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let lt_name = |h: acadrust::types::Handle| -> String {
|
|
||||||
if h.is_null() {
|
|
||||||
"ByBlock".to_string()
|
|
||||||
} else {
|
|
||||||
doc.line_types
|
|
||||||
.iter()
|
|
||||||
.find(|lt| lt.handle == h)
|
|
||||||
.map(|lt| lt.name.clone())
|
|
||||||
.unwrap_or_else(|| "ByBlock".to_string())
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let ds_sel = doc.dim_styles.get(&self.dimstyle_selected);
|
|
||||||
let (
|
|
||||||
dimblk_name,
|
|
||||||
dimblk1_name,
|
|
||||||
dimblk2_name,
|
|
||||||
dimldrblk_name,
|
|
||||||
dimltex_name,
|
|
||||||
dimltex1_name,
|
|
||||||
dimltex2_name,
|
|
||||||
) = match ds_sel {
|
|
||||||
Some(d) => (
|
|
||||||
blk_name(d.dimblk),
|
|
||||||
blk_name(d.dimblk1),
|
|
||||||
blk_name(d.dimblk2),
|
|
||||||
blk_name(d.dimldrblk),
|
|
||||||
lt_name(d.dimltex_handle),
|
|
||||||
lt_name(d.dimltex1_handle),
|
|
||||||
lt_name(d.dimltex2_handle),
|
|
||||||
),
|
|
||||||
None => Default::default(),
|
|
||||||
};
|
|
||||||
return crate::ui::dimstyle::view_window(
|
|
||||||
styles,
|
|
||||||
&self.dimstyle_selected,
|
|
||||||
&self.tabs[self.active_tab]
|
|
||||||
.scene
|
|
||||||
.document
|
|
||||||
.header
|
|
||||||
.current_dimstyle_name,
|
|
||||||
self.dimstyle_tab,
|
|
||||||
crate::ui::dimstyle::DimStyleValues {
|
|
||||||
dimdle: &self.ds_dimdle,
|
|
||||||
dimdli: &self.ds_dimdli,
|
|
||||||
dimgap: &self.ds_dimgap,
|
|
||||||
dimexe: &self.ds_dimexe,
|
|
||||||
dimexo: &self.ds_dimexo,
|
|
||||||
dimsd1: self.ds_dimsd1,
|
|
||||||
dimsd2: self.ds_dimsd2,
|
|
||||||
dimse1: self.ds_dimse1,
|
|
||||||
dimse2: self.ds_dimse2,
|
|
||||||
dimasz: &self.ds_dimasz,
|
|
||||||
dimcen: &self.ds_dimcen,
|
|
||||||
dimtsz: &self.ds_dimtsz,
|
|
||||||
dimtxt: &self.ds_dimtxt,
|
|
||||||
dimtxsty: &self.ds_dimtxsty,
|
|
||||||
dimtad: &self.ds_dimtad,
|
|
||||||
dimtih: self.ds_dimtih,
|
|
||||||
dimtoh: self.ds_dimtoh,
|
|
||||||
dimscale: &self.ds_dimscale,
|
|
||||||
dimlfac: &self.ds_dimlfac,
|
|
||||||
dimlunit: &self.ds_dimlunit,
|
|
||||||
dimdec: &self.ds_dimdec,
|
|
||||||
dimpost: &self.ds_dimpost,
|
|
||||||
dimtol: self.ds_dimtol,
|
|
||||||
dimlim: self.ds_dimlim,
|
|
||||||
dimtp: &self.ds_dimtp,
|
|
||||||
dimtm: &self.ds_dimtm,
|
|
||||||
dimtdec: &self.ds_dimtdec,
|
|
||||||
dimtfac: &self.ds_dimtfac,
|
|
||||||
annotative: self.ds_annotative,
|
|
||||||
dimclrd: &self.ds_dimclrd,
|
|
||||||
dimlwd: &self.ds_dimlwd,
|
|
||||||
dimclre: &self.ds_dimclre,
|
|
||||||
dimlwe: &self.ds_dimlwe,
|
|
||||||
dimfxl: &self.ds_dimfxl,
|
|
||||||
dimfxlon: self.ds_dimfxlon,
|
|
||||||
dimsah: self.ds_dimsah,
|
|
||||||
dimarcsym: &self.ds_dimarcsym,
|
|
||||||
dimjogang: &self.ds_dimjogang,
|
|
||||||
dimclrt: &self.ds_dimclrt,
|
|
||||||
dimjust: &self.ds_dimjust,
|
|
||||||
dimtvp: &self.ds_dimtvp,
|
|
||||||
dimtfill: &self.ds_dimtfill,
|
|
||||||
dimtfillclr: &self.ds_dimtfillclr,
|
|
||||||
dimtxtdirection: self.ds_dimtxtdirection,
|
|
||||||
dimatfit: &self.ds_dimatfit,
|
|
||||||
dimtix: self.ds_dimtix,
|
|
||||||
dimsoxd: self.ds_dimsoxd,
|
|
||||||
dimtmove: &self.ds_dimtmove,
|
|
||||||
dimupt: self.ds_dimupt,
|
|
||||||
dimtofl: self.ds_dimtofl,
|
|
||||||
dimfit: &self.ds_dimfit,
|
|
||||||
dimdsep: &self.ds_dimdsep,
|
|
||||||
dimrnd: &self.ds_dimrnd,
|
|
||||||
dimzin: &self.ds_dimzin,
|
|
||||||
dimfrac: &self.ds_dimfrac,
|
|
||||||
dimaunit: &self.ds_dimaunit,
|
|
||||||
dimadec: &self.ds_dimadec,
|
|
||||||
dimunit: &self.ds_dimunit,
|
|
||||||
dimazin: &self.ds_dimazin,
|
|
||||||
dimalt: self.ds_dimalt,
|
|
||||||
dimaltf: &self.ds_dimaltf,
|
|
||||||
dimaltd: &self.ds_dimaltd,
|
|
||||||
dimaltu: &self.ds_dimaltu,
|
|
||||||
dimalttd: &self.ds_dimalttd,
|
|
||||||
dimaltrnd: &self.ds_dimaltrnd,
|
|
||||||
dimapost: &self.ds_dimapost,
|
|
||||||
dimaltz: &self.ds_dimaltz,
|
|
||||||
dimalttz: &self.ds_dimalttz,
|
|
||||||
dimtolj: &self.ds_dimtolj,
|
|
||||||
dimtzin: &self.ds_dimtzin,
|
|
||||||
dimblk_name,
|
|
||||||
dimblk1_name,
|
|
||||||
dimblk2_name,
|
|
||||||
dimldrblk_name,
|
|
||||||
dimltex_name,
|
|
||||||
dimltex1_name,
|
|
||||||
dimltex2_name,
|
|
||||||
block_opts,
|
|
||||||
lt_opts,
|
|
||||||
color_open: self.ds_color_open.clone(),
|
|
||||||
},
|
|
||||||
self.style_rename.as_deref(),
|
|
||||||
&self.style_rename_buf,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if Some(window_id) == self.color_pick_window {
|
|
||||||
return crate::ui::color_select::color_grid_window(Message::ColorWindowPick);
|
|
||||||
}
|
|
||||||
if Some(window_id) == self.assoc_prompt_window {
|
if Some(window_id) == self.assoc_prompt_window {
|
||||||
return default_assoc_dialog_window();
|
return default_assoc_dialog_window();
|
||||||
}
|
}
|
||||||
@@ -1398,9 +1075,24 @@ impl OpenCADStudio {
|
|||||||
// ── In-canvas modal dialogs (Plan B) ───────────────────────────────
|
// ── In-canvas modal dialogs (Plan B) ───────────────────────────────
|
||||||
// Former pop-up windows render as overlays here, so they work on both
|
// Former pop-up windows render as overlays here, so they work on both
|
||||||
// the native (single main window) and web builds.
|
// the native (single main window) and web builds.
|
||||||
match self.modal_content() {
|
let base: Element<'_, Message> = match self.modal_content() {
|
||||||
Some(content) => crate::ui::modal::modal(composed, content, Message::CloseModal),
|
Some(content) => crate::ui::modal::modal(composed, content, Message::CloseModal),
|
||||||
None => composed.into(),
|
None => composed.into(),
|
||||||
|
};
|
||||||
|
// The colour picker is a nested modal: it stacks over whichever dialog
|
||||||
|
// (style editor, properties, …) requested it.
|
||||||
|
if self.color_pick_target.is_some() {
|
||||||
|
crate::ui::modal::modal(
|
||||||
|
base,
|
||||||
|
iced::widget::container(crate::ui::color_select::color_grid_window(
|
||||||
|
Message::ColorWindowPick,
|
||||||
|
))
|
||||||
|
.width(iced::Length::Fixed(420.0))
|
||||||
|
.height(iced::Length::Fixed(470.0)),
|
||||||
|
Message::CloseColorPicker,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
base
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1540,9 +1232,315 @@ impl OpenCADStudio {
|
|||||||
420,
|
420,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
super::ModalKind::TableStyle
|
super::ModalKind::TableStyle => {
|
||||||
| super::ModalKind::MLeaderStyle
|
use acadrust::objects::ObjectType;
|
||||||
| super::ModalKind::DimStyle => return None,
|
let tab = &self.tabs[self.active_tab];
|
||||||
|
let styles: Vec<String> = tab
|
||||||
|
.scene
|
||||||
|
.document
|
||||||
|
.objects
|
||||||
|
.values()
|
||||||
|
.filter_map(|o| match o {
|
||||||
|
ObjectType::TableStyle(s) => Some(s.name.clone()),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
let selected_style = tab.scene.document.objects.values().find_map(|o| match o {
|
||||||
|
ObjectType::TableStyle(s) if s.name == self.tablestyle_selected => Some(s),
|
||||||
|
_ => None,
|
||||||
|
});
|
||||||
|
sized(
|
||||||
|
crate::ui::tablestyle::view_window(
|
||||||
|
styles,
|
||||||
|
&self.tablestyle_selected,
|
||||||
|
&self.ribbon.active_table_style,
|
||||||
|
selected_style,
|
||||||
|
&self.ts_hmargin,
|
||||||
|
&self.ts_vmargin,
|
||||||
|
&self.ts_description,
|
||||||
|
&self.ts_cell_textstyle,
|
||||||
|
&self.ts_cell_height,
|
||||||
|
&self.ts_cell_textcolor,
|
||||||
|
&self.ts_cell_fillcolor,
|
||||||
|
&self.ts_cell_datatype,
|
||||||
|
&self.ts_cell_unittype,
|
||||||
|
&self.ts_cell_format,
|
||||||
|
&self.ts_border_lw,
|
||||||
|
&self.ts_border_color,
|
||||||
|
&self.ts_border_spacing,
|
||||||
|
self.style_rename.as_deref(),
|
||||||
|
&self.style_rename_buf,
|
||||||
|
self.ts_color_open,
|
||||||
|
),
|
||||||
|
620,
|
||||||
|
420,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
super::ModalKind::MLeaderStyle => {
|
||||||
|
use acadrust::objects::ObjectType;
|
||||||
|
let tab = &self.tabs[self.active_tab];
|
||||||
|
let styles: Vec<String> = tab
|
||||||
|
.scene
|
||||||
|
.document
|
||||||
|
.objects
|
||||||
|
.values()
|
||||||
|
.filter_map(|o| match o {
|
||||||
|
ObjectType::MultiLeaderStyle(s) => Some(s.name.clone()),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
let selected_style = tab.scene.document.objects.values().find_map(|o| match o {
|
||||||
|
ObjectType::MultiLeaderStyle(s) if s.name == self.mleaderstyle_selected => {
|
||||||
|
Some(s)
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
});
|
||||||
|
let doc = &tab.scene.document;
|
||||||
|
let mut block_opts: Vec<String> = vec!["None".to_string()];
|
||||||
|
block_opts.extend(doc.block_records.iter().map(|b| b.name.clone()));
|
||||||
|
let mut lt_opts: Vec<String> = vec!["None".to_string()];
|
||||||
|
lt_opts.extend(doc.line_types.iter().map(|lt| lt.name.clone()));
|
||||||
|
let mut textstyle_opts: Vec<String> = vec!["None".to_string()];
|
||||||
|
textstyle_opts.extend(doc.text_styles.iter().map(|t| t.name.clone()));
|
||||||
|
let opt_block = |h: Option<acadrust::types::Handle>| -> String {
|
||||||
|
match h {
|
||||||
|
Some(h) => doc
|
||||||
|
.block_records
|
||||||
|
.iter()
|
||||||
|
.find(|b| b.handle == h)
|
||||||
|
.map(|b| b.name.clone())
|
||||||
|
.unwrap_or_else(|| "None".to_string()),
|
||||||
|
None => "None".to_string(),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let opt_lt = |h: Option<acadrust::types::Handle>| -> String {
|
||||||
|
match h {
|
||||||
|
Some(h) => doc
|
||||||
|
.line_types
|
||||||
|
.iter()
|
||||||
|
.find(|lt| lt.handle == h)
|
||||||
|
.map(|lt| lt.name.clone())
|
||||||
|
.unwrap_or_else(|| "None".to_string()),
|
||||||
|
None => "None".to_string(),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let opt_ts = |h: Option<acadrust::types::Handle>| -> String {
|
||||||
|
match h {
|
||||||
|
Some(h) => doc
|
||||||
|
.text_styles
|
||||||
|
.iter()
|
||||||
|
.find(|t| t.handle == h)
|
||||||
|
.map(|t| t.name.clone())
|
||||||
|
.unwrap_or_else(|| "None".to_string()),
|
||||||
|
None => "None".to_string(),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let (line_type_name, arrowhead_name, text_style_name, block_content_name) =
|
||||||
|
match selected_style {
|
||||||
|
Some(s) => (
|
||||||
|
opt_lt(s.line_type_handle),
|
||||||
|
opt_block(s.arrowhead_handle),
|
||||||
|
opt_ts(s.text_style_handle),
|
||||||
|
opt_block(s.block_content_handle),
|
||||||
|
),
|
||||||
|
None => Default::default(),
|
||||||
|
};
|
||||||
|
sized(
|
||||||
|
crate::ui::mleaderstyle::view_window(crate::ui::mleaderstyle::MLeaderStyleView {
|
||||||
|
styles,
|
||||||
|
selected: &self.mleaderstyle_selected,
|
||||||
|
style: selected_style,
|
||||||
|
current: tab.active_mleader_style.clone(),
|
||||||
|
landing_distance: &self.mls_landing_distance,
|
||||||
|
landing_gap: &self.mls_landing_gap,
|
||||||
|
arrowhead_size: &self.mls_arrowhead_size,
|
||||||
|
text_height: &self.mls_text_height,
|
||||||
|
scale_factor: &self.mls_scale_factor,
|
||||||
|
break_gap: &self.mls_break_gap,
|
||||||
|
first_seg_angle: &self.mls_first_seg_angle,
|
||||||
|
second_seg_angle: &self.mls_second_seg_angle,
|
||||||
|
max_points: &self.mls_max_points,
|
||||||
|
default_text: &self.mls_default_text,
|
||||||
|
line_color: &self.mls_line_color,
|
||||||
|
text_color: &self.mls_text_color,
|
||||||
|
description: &self.mls_description,
|
||||||
|
line_weight: &self.mls_line_weight,
|
||||||
|
align_space: &self.mls_align_space,
|
||||||
|
block_color: &self.mls_block_color,
|
||||||
|
block_rotation: &self.mls_block_rotation,
|
||||||
|
block_scale_x: &self.mls_block_scale_x,
|
||||||
|
block_scale_y: &self.mls_block_scale_y,
|
||||||
|
block_scale_z: &self.mls_block_scale_z,
|
||||||
|
block_opts,
|
||||||
|
lt_opts,
|
||||||
|
textstyle_opts,
|
||||||
|
line_type_name,
|
||||||
|
arrowhead_name,
|
||||||
|
text_style_name,
|
||||||
|
block_content_name,
|
||||||
|
rename_active: self.style_rename.as_deref(),
|
||||||
|
rename_buf: &self.style_rename_buf,
|
||||||
|
color_open: self.mls_color_open,
|
||||||
|
}),
|
||||||
|
560,
|
||||||
|
560,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
super::ModalKind::DimStyle => {
|
||||||
|
|
||||||
|
let tab = &self.tabs[self.active_tab];
|
||||||
|
let styles: Vec<String> = tab
|
||||||
|
.scene
|
||||||
|
.document
|
||||||
|
.dim_styles
|
||||||
|
.iter()
|
||||||
|
.map(|s| s.name.clone())
|
||||||
|
.collect();
|
||||||
|
let doc = &tab.scene.document;
|
||||||
|
// Dropdown options (names must match the records exactly so the
|
||||||
|
// selection can be resolved back to a handle on the update side).
|
||||||
|
let mut block_opts: Vec<String> = vec!["Default".to_string()];
|
||||||
|
block_opts.extend(doc.block_records.iter().map(|b| b.name.clone()));
|
||||||
|
let mut lt_opts: Vec<String> = vec!["ByBlock".to_string()];
|
||||||
|
lt_opts.extend(doc.line_types.iter().map(|lt| lt.name.clone()));
|
||||||
|
let blk_name = |h: acadrust::types::Handle| -> String {
|
||||||
|
if h.is_null() {
|
||||||
|
"Default".to_string()
|
||||||
|
} else {
|
||||||
|
doc.block_records
|
||||||
|
.iter()
|
||||||
|
.find(|b| b.handle == h)
|
||||||
|
.map(|b| b.name.clone())
|
||||||
|
.unwrap_or_else(|| "Default".to_string())
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let lt_name = |h: acadrust::types::Handle| -> String {
|
||||||
|
if h.is_null() {
|
||||||
|
"ByBlock".to_string()
|
||||||
|
} else {
|
||||||
|
doc.line_types
|
||||||
|
.iter()
|
||||||
|
.find(|lt| lt.handle == h)
|
||||||
|
.map(|lt| lt.name.clone())
|
||||||
|
.unwrap_or_else(|| "ByBlock".to_string())
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let ds_sel = doc.dim_styles.get(&self.dimstyle_selected);
|
||||||
|
let (
|
||||||
|
dimblk_name,
|
||||||
|
dimblk1_name,
|
||||||
|
dimblk2_name,
|
||||||
|
dimldrblk_name,
|
||||||
|
dimltex_name,
|
||||||
|
dimltex1_name,
|
||||||
|
dimltex2_name,
|
||||||
|
) = match ds_sel {
|
||||||
|
Some(d) => (
|
||||||
|
blk_name(d.dimblk),
|
||||||
|
blk_name(d.dimblk1),
|
||||||
|
blk_name(d.dimblk2),
|
||||||
|
blk_name(d.dimldrblk),
|
||||||
|
lt_name(d.dimltex_handle),
|
||||||
|
lt_name(d.dimltex1_handle),
|
||||||
|
lt_name(d.dimltex2_handle),
|
||||||
|
),
|
||||||
|
None => Default::default(),
|
||||||
|
};
|
||||||
|
sized(crate::ui::dimstyle::view_window(
|
||||||
|
styles,
|
||||||
|
&self.dimstyle_selected,
|
||||||
|
&self.tabs[self.active_tab]
|
||||||
|
.scene
|
||||||
|
.document
|
||||||
|
.header
|
||||||
|
.current_dimstyle_name,
|
||||||
|
self.dimstyle_tab,
|
||||||
|
crate::ui::dimstyle::DimStyleValues {
|
||||||
|
dimdle: &self.ds_dimdle,
|
||||||
|
dimdli: &self.ds_dimdli,
|
||||||
|
dimgap: &self.ds_dimgap,
|
||||||
|
dimexe: &self.ds_dimexe,
|
||||||
|
dimexo: &self.ds_dimexo,
|
||||||
|
dimsd1: self.ds_dimsd1,
|
||||||
|
dimsd2: self.ds_dimsd2,
|
||||||
|
dimse1: self.ds_dimse1,
|
||||||
|
dimse2: self.ds_dimse2,
|
||||||
|
dimasz: &self.ds_dimasz,
|
||||||
|
dimcen: &self.ds_dimcen,
|
||||||
|
dimtsz: &self.ds_dimtsz,
|
||||||
|
dimtxt: &self.ds_dimtxt,
|
||||||
|
dimtxsty: &self.ds_dimtxsty,
|
||||||
|
dimtad: &self.ds_dimtad,
|
||||||
|
dimtih: self.ds_dimtih,
|
||||||
|
dimtoh: self.ds_dimtoh,
|
||||||
|
dimscale: &self.ds_dimscale,
|
||||||
|
dimlfac: &self.ds_dimlfac,
|
||||||
|
dimlunit: &self.ds_dimlunit,
|
||||||
|
dimdec: &self.ds_dimdec,
|
||||||
|
dimpost: &self.ds_dimpost,
|
||||||
|
dimtol: self.ds_dimtol,
|
||||||
|
dimlim: self.ds_dimlim,
|
||||||
|
dimtp: &self.ds_dimtp,
|
||||||
|
dimtm: &self.ds_dimtm,
|
||||||
|
dimtdec: &self.ds_dimtdec,
|
||||||
|
dimtfac: &self.ds_dimtfac,
|
||||||
|
annotative: self.ds_annotative,
|
||||||
|
dimclrd: &self.ds_dimclrd,
|
||||||
|
dimlwd: &self.ds_dimlwd,
|
||||||
|
dimclre: &self.ds_dimclre,
|
||||||
|
dimlwe: &self.ds_dimlwe,
|
||||||
|
dimfxl: &self.ds_dimfxl,
|
||||||
|
dimfxlon: self.ds_dimfxlon,
|
||||||
|
dimsah: self.ds_dimsah,
|
||||||
|
dimarcsym: &self.ds_dimarcsym,
|
||||||
|
dimjogang: &self.ds_dimjogang,
|
||||||
|
dimclrt: &self.ds_dimclrt,
|
||||||
|
dimjust: &self.ds_dimjust,
|
||||||
|
dimtvp: &self.ds_dimtvp,
|
||||||
|
dimtfill: &self.ds_dimtfill,
|
||||||
|
dimtfillclr: &self.ds_dimtfillclr,
|
||||||
|
dimtxtdirection: self.ds_dimtxtdirection,
|
||||||
|
dimatfit: &self.ds_dimatfit,
|
||||||
|
dimtix: self.ds_dimtix,
|
||||||
|
dimsoxd: self.ds_dimsoxd,
|
||||||
|
dimtmove: &self.ds_dimtmove,
|
||||||
|
dimupt: self.ds_dimupt,
|
||||||
|
dimtofl: self.ds_dimtofl,
|
||||||
|
dimfit: &self.ds_dimfit,
|
||||||
|
dimdsep: &self.ds_dimdsep,
|
||||||
|
dimrnd: &self.ds_dimrnd,
|
||||||
|
dimzin: &self.ds_dimzin,
|
||||||
|
dimfrac: &self.ds_dimfrac,
|
||||||
|
dimaunit: &self.ds_dimaunit,
|
||||||
|
dimadec: &self.ds_dimadec,
|
||||||
|
dimunit: &self.ds_dimunit,
|
||||||
|
dimazin: &self.ds_dimazin,
|
||||||
|
dimalt: self.ds_dimalt,
|
||||||
|
dimaltf: &self.ds_dimaltf,
|
||||||
|
dimaltd: &self.ds_dimaltd,
|
||||||
|
dimaltu: &self.ds_dimaltu,
|
||||||
|
dimalttd: &self.ds_dimalttd,
|
||||||
|
dimaltrnd: &self.ds_dimaltrnd,
|
||||||
|
dimapost: &self.ds_dimapost,
|
||||||
|
dimaltz: &self.ds_dimaltz,
|
||||||
|
dimalttz: &self.ds_dimalttz,
|
||||||
|
dimtolj: &self.ds_dimtolj,
|
||||||
|
dimtzin: &self.ds_dimtzin,
|
||||||
|
dimblk_name,
|
||||||
|
dimblk1_name,
|
||||||
|
dimblk2_name,
|
||||||
|
dimldrblk_name,
|
||||||
|
dimltex_name,
|
||||||
|
dimltex1_name,
|
||||||
|
dimltex2_name,
|
||||||
|
block_opts,
|
||||||
|
lt_opts,
|
||||||
|
color_open: self.ds_color_open.clone(),
|
||||||
|
},
|
||||||
|
self.style_rename.as_deref(),
|
||||||
|
&self.style_rename_buf,
|
||||||
|
), 720, 560)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user