forked from 1b-agent/opencadstudio-upstream
Merge pull request #1613 from ramox81/codex/sheet-set-manager
Sheet Set Manager, NEWSHEETSET / OPENSHEETSET and sheet set fields, with review fixes. # Conflicts: # Cargo.lock # src/app/control/actions.rs # src/app/mod.rs # src/app/settings.rs # src/app/update/dialog.rs # src/app/update/file.rs # src/app/update/mod.rs # src/app/view/mod.rs # src/ui/dock.rs # src/ui/ribbon/mod.rs # src/ui/window/field_dialog.rs # src/ui/window/mod.rs
This commit is contained in:
commit
fbe55bab37
52 files changed
+9088
-69
No files matched your search
@@ -50,6 +50,8 @@ pub enum PanelId {
|
||||
PointCloudManager,
|
||||
/// Block counts (COUNTLIST).
|
||||
Count,
|
||||
/// The open sheet sets: subsets and sheets.
|
||||
SheetSetManager,
|
||||
}
|
||||
|
||||
impl PanelId {
|
||||
@@ -63,6 +65,7 @@ impl PanelId {
|
||||
PanelId::NodeGraph => "Node Graph",
|
||||
PanelId::PointCloudManager => "Point Cloud Manager",
|
||||
PanelId::Count => "Count",
|
||||
PanelId::SheetSetManager => "Sheet Set Manager",
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,6 +79,7 @@ impl PanelId {
|
||||
PanelId::NodeGraph => 220.0,
|
||||
PanelId::PointCloudManager => 280.0,
|
||||
PanelId::Count => 280.0,
|
||||
PanelId::SheetSetManager => 280.0,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,6 +171,7 @@ impl DockState {
|
||||
PanelId::NodeGraph,
|
||||
PanelId::PointCloudManager,
|
||||
PanelId::Count,
|
||||
PanelId::SheetSetManager,
|
||||
] {
|
||||
self.panels.entry(id).or_insert_with(|| DockPanel::for_id(id));
|
||||
}
|
||||
|
||||
@@ -59,6 +59,8 @@ static LAY_ULK: &[u8] = include_bytes!("../../assets/icons/layers/layulk.svg");
|
||||
pub static CHECK: &[u8] = include_bytes!("../../assets/icons/ui/check.svg");
|
||||
pub static CLOSE: &[u8] = include_bytes!("../../assets/icons/ui/close.svg");
|
||||
pub static PLUS: &[u8] = include_bytes!("../../assets/icons/ui/plus.svg");
|
||||
pub static REFRESH: &[u8] = include_bytes!("../../assets/icons/ui/refresh.svg");
|
||||
pub static SWAP: &[u8] = include_bytes!("../../assets/icons/ui/swap.svg");
|
||||
pub static MINUS: &[u8] = include_bytes!("../../assets/icons/ui/minus.svg");
|
||||
pub static TRASH: &[u8] = include_bytes!("../../assets/icons/ui/trash.svg");
|
||||
pub static NODE_GRAPH: &[u8] = include_bytes!("../../assets/icons/ui/node_graph.svg");
|
||||
|
||||
@@ -60,6 +60,8 @@ pub struct Ribbon {
|
||||
pub show_properties: bool,
|
||||
/// The Count palette is open (View › Palettes › Count).
|
||||
pub show_count_palette: bool,
|
||||
/// Sheet Set Manager palette shown (SSMSTATE).
|
||||
pub show_sheet_set: bool,
|
||||
/// File tabs (FILETAB) visibility — drives the File Tabs button highlight.
|
||||
pub show_file_tabs: bool,
|
||||
/// Layout tabs (LAYOUTTAB) visibility — drives the Layout Tabs button highlight.
|
||||
@@ -177,6 +179,7 @@ impl Ribbon {
|
||||
show_ucs_icon: true,
|
||||
show_properties: true,
|
||||
show_count_palette: false,
|
||||
show_sheet_set: false,
|
||||
show_file_tabs: true,
|
||||
show_layout_tabs: true,
|
||||
open_dropdown: None,
|
||||
@@ -341,6 +344,9 @@ impl Ribbon {
|
||||
pub fn set_count_palette(&mut self, on: bool) {
|
||||
self.show_count_palette = on;
|
||||
}
|
||||
pub fn set_sheet_set(&mut self, on: bool) {
|
||||
self.show_sheet_set = on;
|
||||
}
|
||||
pub fn set_file_tabs(&mut self, on: bool) {
|
||||
self.show_file_tabs = on;
|
||||
}
|
||||
@@ -360,6 +366,7 @@ impl Ribbon {
|
||||
show_properties: self.show_properties,
|
||||
show_count_palette: self.show_count_palette,
|
||||
show_block_palette,
|
||||
show_sheet_set: self.show_sheet_set,
|
||||
show_file_tabs: self.show_file_tabs,
|
||||
show_layout_tabs: self.show_layout_tabs,
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ pub(super) struct ToggleState {
|
||||
pub show_properties: bool,
|
||||
pub show_count_palette: bool,
|
||||
pub show_block_palette: bool,
|
||||
pub show_sheet_set: bool,
|
||||
pub show_file_tabs: bool,
|
||||
pub show_layout_tabs: bool,
|
||||
}
|
||||
@@ -382,6 +383,7 @@ pub(super) fn is_active_tool(
|
||||
"PROPERTIES" => state.show_properties,
|
||||
"COUNTLIST" => state.show_count_palette,
|
||||
"BLOCKPALETTE" => state.show_block_palette,
|
||||
"SHEETSET" => state.show_sheet_set,
|
||||
"FILETAB" => state.show_file_tabs,
|
||||
"LAYOUTTAB" => state.show_layout_tabs,
|
||||
id => active_tool.as_deref() == Some(id),
|
||||
|
||||
@@ -378,6 +378,11 @@ impl<'a> Program<Message> for BlockPreviewCanvas<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
/// A block preview (the palette's canvas) for other dialogs.
|
||||
pub(crate) fn preview_canvas<'a>(wires: &'a [WireModel], height: f32) -> Element<'a, Message> {
|
||||
canvas(BlockPreviewCanvas { wires }).width(Fill).height(Length::Fixed(height)).into()
|
||||
}
|
||||
|
||||
fn pm(m: BlockPaletteMsg) -> Message {
|
||||
Message::BlockPalette(m)
|
||||
}
|
||||
|
||||
@@ -38,8 +38,234 @@ pub const CATEGORIES: &[(&str, &[&str])] = &[
|
||||
"Plot",
|
||||
&["DeviceName", "Login", "PageSetupName", "PaperSize", "PlotDate", "PlotOrientation", "PlotScale", "PlotStyleTable"],
|
||||
),
|
||||
("SheetSet", SHEET_SET_FIELDS),
|
||||
];
|
||||
|
||||
/// The SheetSet category, in the reference's order.
|
||||
pub const SHEET_SET_FIELDS: &[&str] = &[
|
||||
"CurrentSheetCategory",
|
||||
"CurrentSheetCustom",
|
||||
"CurrentSheetDescription",
|
||||
"CurrentSheetIssuePurpose",
|
||||
"CurrentSheetNumber",
|
||||
"CurrentSheetNumberAndTitle",
|
||||
"CurrentSheetRevisionDate",
|
||||
"CurrentSheetRevisionNumber",
|
||||
"CurrentSheetSet",
|
||||
"CurrentSheetSetCustom",
|
||||
"CurrentSheetSetDescription",
|
||||
"CurrentSheetSetProjectMilestone",
|
||||
"CurrentSheetSetProjectName",
|
||||
"CurrentSheetSetProjectNumber",
|
||||
"CurrentSheetSetProjectPhase",
|
||||
"CurrentSheetSubSet",
|
||||
"CurrentSheetTitle",
|
||||
"SheetSet",
|
||||
"SheetSetPlaceholder",
|
||||
"SheetView",
|
||||
];
|
||||
|
||||
/// A sheet set field's code without format: `\AcSm[.16.2] Component.Property`.
|
||||
fn sheet_set_code(name: &str, custom: &str) -> String {
|
||||
let (version, target) = match name {
|
||||
"CurrentSheetCategory" => (".16.2", "Sheet.Category".to_string()),
|
||||
"CurrentSheetCustom" => ("", format!("Sheet.{custom}")),
|
||||
"CurrentSheetDescription" => ("", "Sheet.Description".into()),
|
||||
"CurrentSheetIssuePurpose" => (".16.2", "Sheet.IssuePurpose".into()),
|
||||
"CurrentSheetNumber" => ("", "Sheet.Number".into()),
|
||||
"CurrentSheetNumberAndTitle" => ("", "Sheet.NumberAndTitle".into()),
|
||||
"CurrentSheetRevisionDate" => (".16.2", "Sheet.RevisionDate".into()),
|
||||
"CurrentSheetRevisionNumber" => (".16.2", "Sheet.RevisionNumber".into()),
|
||||
"CurrentSheetSet" => ("", "SheetSet.Name".into()),
|
||||
"CurrentSheetSetCustom" => ("", format!("SheetSet.{custom}")),
|
||||
"CurrentSheetSetDescription" => ("", "SheetSet.Description".into()),
|
||||
"CurrentSheetSetProjectMilestone" => (".16.2", "SheetSet.ProjectMilestone".into()),
|
||||
"CurrentSheetSetProjectName" => (".16.2", "SheetSet.ProjectName".into()),
|
||||
"CurrentSheetSetProjectNumber" => (".16.2", "SheetSet.ProjectNumber".into()),
|
||||
"CurrentSheetSetProjectPhase" => (".16.2", "SheetSet.ProjectPhase".into()),
|
||||
"CurrentSheetSubSet" => ("", "Subset.Name".into()),
|
||||
"CurrentSheetTitle" => ("", "Sheet.Title".into()),
|
||||
_ => return "\\AcSm".into(),
|
||||
};
|
||||
format!("\\AcSm{version} {target}")
|
||||
}
|
||||
|
||||
/// The navigation tree of a SheetSet (set, subsets, sheets) or SheetView
|
||||
/// (set, view categories) field: depth, component id, label, is a sheet.
|
||||
pub fn nav_nodes(db: &codec::sheet_set::SheetSetDatabase, views: bool) -> Vec<(u16, String, String, bool)> {
|
||||
use codec::sheet_set::{number_and_title, ComponentKind, Element as SsElement};
|
||||
let set = db.sheet_set();
|
||||
let mut out = vec![(0, set.id().to_string(), db.name().to_string(), false)];
|
||||
if views {
|
||||
// Views of the unnamed (default) category sit under the set, then each
|
||||
// named category with its views.
|
||||
let all: Vec<&SsElement> = db.sheets().into_iter().flat_map(|s| db.sheet_views(s)).collect();
|
||||
let named: Vec<&SsElement> = db.view_categories();
|
||||
let in_named = |v: &SsElement| {
|
||||
codec::sheet_set::SheetSetDatabase::view_category_of(v).is_some_and(|c| named.iter().any(|n| n.id() == c))
|
||||
};
|
||||
for v in all.iter().filter(|v| !in_named(v)) {
|
||||
out.push((1, v.id().to_string(), number_and_title(v), true));
|
||||
}
|
||||
for c in &named {
|
||||
out.push((1, c.id().to_string(), c.prop("Name").unwrap_or("").to_string(), false));
|
||||
for v in all.iter().filter(|v| codec::sheet_set::SheetSetDatabase::view_category_of(v) == Some(c.id())) {
|
||||
out.push((2, v.id().to_string(), number_and_title(v), true));
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
fn go(el: &SsElement, depth: u16, out: &mut Vec<(u16, String, String, bool)>) {
|
||||
for c in &el.children {
|
||||
match ComponentKind::of(c) {
|
||||
Some(ComponentKind::Subset) => {
|
||||
out.push((depth, c.id().to_string(), c.prop("Name").unwrap_or("").to_string(), false));
|
||||
go(c, depth + 1, out);
|
||||
}
|
||||
Some(ComponentKind::Sheet) => out.push((depth, c.id().to_string(), number_and_title(c), true)),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
go(set, 1, &mut out);
|
||||
out
|
||||
}
|
||||
|
||||
/// The properties a navigation node offers: list label, code property, version.
|
||||
pub fn nav_props(db: &codec::sheet_set::SheetSetDatabase, id: &str) -> Vec<(String, String, &'static str)> {
|
||||
use codec::sheet_set::{custom_properties, ComponentKind, CUSTOM_SHEET_PROP, CUSTOM_SHEET_SET_PROP};
|
||||
let Some(el) = db.find(id) else { return Vec::new() };
|
||||
let fixed = |list: &[(&str, &str, &'static str)]| -> Vec<(String, String, &'static str)> {
|
||||
list.iter().map(|(l, p, v)| (l.to_string(), p.to_string(), *v)).collect()
|
||||
};
|
||||
let custom = |flag: i32| -> Vec<(String, String, &'static str)> {
|
||||
custom_properties(db.sheet_set()).into_iter().filter(|(_, _, f)| f & flag != 0).map(|(n, _, _)| (n.clone(), n, "")).collect()
|
||||
};
|
||||
match ComponentKind::of(el) {
|
||||
Some(ComponentKind::SheetSet) => {
|
||||
let mut v = fixed(&[
|
||||
("SheetSetName", "Name", ""),
|
||||
("SheetSetDescription", "Description", ""),
|
||||
("ProjectNumber", "ProjectNumber", ".16.2"),
|
||||
("ProjectName", "ProjectName", ".16.2"),
|
||||
("ProjectPhase", "ProjectPhase", ".16.2"),
|
||||
("ProjectMilestone", "ProjectMilestone", ".16.2"),
|
||||
]);
|
||||
v.extend(custom(CUSTOM_SHEET_SET_PROP));
|
||||
v
|
||||
}
|
||||
Some(ComponentKind::Subset) => fixed(&[("SheetSubsetName", "Name", "")]),
|
||||
Some(ComponentKind::Sheet) => {
|
||||
let mut v = fixed(&[
|
||||
("SheetNumberAndTitle", "NumberAndTitle", ""),
|
||||
("SheetTitle", "Title", ""),
|
||||
("SheetNumber", "Number", ""),
|
||||
("SheetDescription", "Description", ""),
|
||||
("RevisionNumber", "RevisionNumber", ".16.2"),
|
||||
("RevisionDate", "RevisionDate", ".16.2"),
|
||||
("IssuePurpose", "IssuePurpose", ".16.2"),
|
||||
("Category", "Category", ".16.2"),
|
||||
]);
|
||||
v.extend(custom(CUSTOM_SHEET_PROP));
|
||||
v
|
||||
}
|
||||
None if el.name == "AcSmSheetView" => fixed(&[
|
||||
("ViewNumberAndTitle", "NumberAndTitle", ""),
|
||||
("ViewTitle", "Title", ""),
|
||||
("ViewNumber", "Number", ""),
|
||||
("ViewportScale", "ViewportScale", ".16.2"),
|
||||
]),
|
||||
None => fixed(&[("ViewCategoryName", "Name", "")]),
|
||||
}
|
||||
}
|
||||
|
||||
/// The sheet drawing, named view and layout a sheet or sheet view node links to.
|
||||
pub fn nav_link(db: &codec::sheet_set::SheetSetDatabase, id: &str) -> Option<(String, String, String)> {
|
||||
let el = db.find(id)?;
|
||||
let (sheet, view) = if el.name == "AcSmSheetView" {
|
||||
let views = db.parent_of(id)?;
|
||||
let sheet = db.parent_of(views.id())?;
|
||||
(sheet.id().to_string(), el.named("NamedView").and_then(|v| v.prop("Name")).unwrap_or("").to_string())
|
||||
} else if codec::sheet_set::ComponentKind::of(el) == Some(codec::sheet_set::ComponentKind::Sheet) {
|
||||
(id.to_string(), String::new())
|
||||
} else {
|
||||
return None;
|
||||
};
|
||||
let r = db.layout_reference(&sheet, "Layout")?;
|
||||
Some((r.file_name, view, r.name))
|
||||
}
|
||||
|
||||
impl FieldDialogState {
|
||||
/// `\AcSm Database("…").SheetSet("…")[.Component("…")].Property` of the
|
||||
/// picked node, with the text case and, on a sheet, the hyperlink to it.
|
||||
fn navigation_code(&self) -> String {
|
||||
let Some(db) = self.ss_sets.get(self.ss_set) else { return "\\AcSm".into() };
|
||||
let Some((_, prop, version)) = nav_props(db, &self.ss_node).into_iter().find(|(l, _, _)| *l == self.ss_prop) else {
|
||||
return "\\AcSm".into();
|
||||
};
|
||||
let set = db.sheet_set().id().to_string();
|
||||
let path = codec::sheet_set::native_path(db.path.as_deref().unwrap_or(""));
|
||||
// ViewportScale takes a scale format (and its version), not a text case.
|
||||
let scale = prop == "ViewportScale";
|
||||
let version = if scale {
|
||||
codec::fields::PLOT_SCALE_FORMATS
|
||||
.get(self.ss_scale_format)
|
||||
.map_or("", |(_, c)| if c.starts_with("\\AcVar.16.2") { ".16.2" } else { "" })
|
||||
} else {
|
||||
version
|
||||
};
|
||||
let mut code = format!("\\AcSm{version} Database(\"{path}\").SheetSet(\"{set}\")");
|
||||
if self.ss_node != set {
|
||||
code.push_str(&format!(".Component(\"{}\")", self.ss_node));
|
||||
}
|
||||
code.push('.');
|
||||
code.push_str(&prop);
|
||||
if scale {
|
||||
let f = viewport_scale_picture(self.ss_scale_format);
|
||||
if !f.is_empty() {
|
||||
code.push(' ');
|
||||
code.push_str(&f);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
if self.text_case != 0 {
|
||||
code.push_str(&format!(" \\f \"%tc{}\"", self.text_case));
|
||||
}
|
||||
// A sheet links to its layout, a view to its named view on the sheet.
|
||||
if self.ss_href {
|
||||
if let Some((file, view, layout)) = nav_link(db, &self.ss_node) {
|
||||
code.push_str(&format!(" \\href \"{file}#{view},{layout}##1\""));
|
||||
}
|
||||
}
|
||||
code
|
||||
}
|
||||
}
|
||||
|
||||
/// SheetSetPlaceholder types: list label, the `?` target, field version.
|
||||
pub const PLACEHOLDER_TYPES: &[(&str, &str, &str)] = &[
|
||||
("SheetNumberAndTitle", "?Sheet.NumberAndTitle", ""),
|
||||
("SheetTitle", "?Sheet.Title", ""),
|
||||
("SheetNumber", "?Sheet.Number", ""),
|
||||
("SheetDescription", "?Sheet.Description", ""),
|
||||
("RevisionNumber", "?Sheet.RevisionNumber", ".16.2"),
|
||||
("RevisionDate", "?Sheet.RevisionDate", ".16.2"),
|
||||
("IssuePurpose", "?Sheet.IssuePurpose", ".16.2"),
|
||||
("Category", "?Sheet.Category", ".16.2"),
|
||||
("Custom", "?Sheet.", ""),
|
||||
("ViewNumberAndTitle", "?View.NumberAndTitle", ""),
|
||||
("ViewTitle", "?View.Title", ""),
|
||||
("ViewNumber", "?View.Number", ""),
|
||||
("ViewportScale", "?View.ViewportScale", ".16.2"),
|
||||
];
|
||||
|
||||
/// ViewportScale placeholder formats: the PlotScale pictures.
|
||||
pub fn viewport_scale_picture(k: usize) -> String {
|
||||
codec::fields::PLOT_SCALE_FORMATS
|
||||
.get(k)
|
||||
.and_then(|(_, code)| code.find("\\f ").map(|p| code[p..].to_string()))
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
/// The fields of a category; "All" lists every field once, sorted.
|
||||
pub fn fields_of(category: usize) -> Vec<&'static str> {
|
||||
if category == 0 {
|
||||
@@ -79,6 +305,13 @@ pub enum FieldKind {
|
||||
PlotScale,
|
||||
/// Count / CountInArea: a JSON expression.
|
||||
Count,
|
||||
/// A CurrentSheet* / CurrentSheetSet* field (text case).
|
||||
SheetSet,
|
||||
/// CurrentSheetCustom / CurrentSheetSetCustom (text case + property).
|
||||
SheetSetCustom,
|
||||
SheetSetPlaceholder,
|
||||
/// SheetSet / SheetView: a component picked in a sheet set.
|
||||
SheetSetNavigation,
|
||||
BlockPlaceholder,
|
||||
}
|
||||
|
||||
@@ -99,6 +332,10 @@ pub fn kind_of(name: &str) -> FieldKind {
|
||||
"Hyperlink" => FieldKind::Hyperlink,
|
||||
"PlotScale" => FieldKind::PlotScale,
|
||||
"Count" | "CountInArea" => FieldKind::Count,
|
||||
"CurrentSheetCustom" | "CurrentSheetSetCustom" => FieldKind::SheetSetCustom,
|
||||
"SheetSetPlaceholder" => FieldKind::SheetSetPlaceholder,
|
||||
"SheetSet" | "SheetView" => FieldKind::SheetSetNavigation,
|
||||
n if SHEET_SET_FIELDS.contains(&n) => FieldKind::SheetSet,
|
||||
"BlockPlaceholder" => FieldKind::BlockPlaceholder,
|
||||
_ => FieldKind::Text,
|
||||
}
|
||||
@@ -141,6 +378,23 @@ pub struct FieldDialogState {
|
||||
/// Index into codec BLOCK_PLACEHOLDER_PROPERTIES.
|
||||
pub placeholder_property: usize,
|
||||
pub preview: String,
|
||||
/// Sheet set fields: the open set's sheet (flags 2) and set (flags 1)
|
||||
/// custom property names, the chosen one, the placeholder type and the
|
||||
/// ViewportScale format.
|
||||
pub ss_sheet_custom: Vec<String>,
|
||||
pub ss_set_custom: Vec<String>,
|
||||
pub ss_custom: String,
|
||||
pub ss_placeholder: usize,
|
||||
pub ss_scale_format: usize,
|
||||
/// The open sheet set's name (SheetSet / SheetView fields).
|
||||
pub ss_set_name: String,
|
||||
/// SheetSet / SheetView: the sets offered (open ones and any picked with
|
||||
/// "..."), the one shown, the node and property picked, associate hyperlink.
|
||||
pub ss_sets: Vec<codec::sheet_set::SheetSetDatabase>,
|
||||
pub ss_set: usize,
|
||||
pub ss_node: String,
|
||||
pub ss_prop: String,
|
||||
pub ss_href: bool,
|
||||
/// Today in each of DATE_FORMATS, for the Examples list.
|
||||
pub examples: Vec<String>,
|
||||
}
|
||||
@@ -174,6 +428,17 @@ impl FieldDialogState {
|
||||
placeholder_block: None,
|
||||
placeholder_property: 7,
|
||||
preview: String::new(),
|
||||
ss_sheet_custom: Vec::new(),
|
||||
ss_set_custom: Vec::new(),
|
||||
ss_custom: String::new(),
|
||||
ss_placeholder: 0,
|
||||
ss_scale_format: 6,
|
||||
ss_set_name: String::new(),
|
||||
ss_sets: Vec::new(),
|
||||
ss_set: 0,
|
||||
ss_node: String::new(),
|
||||
ss_prop: String::new(),
|
||||
ss_href: true,
|
||||
examples: Vec::new(),
|
||||
}
|
||||
}
|
||||
@@ -234,6 +499,25 @@ impl FieldDialogState {
|
||||
json => (format!("\\{evaluator} {json}"), vec![]),
|
||||
}
|
||||
}
|
||||
FieldKind::SheetSet | FieldKind::SheetSetCustom => (case(sheet_set_code(self.name, &self.ss_custom)), vec![]),
|
||||
FieldKind::SheetSetNavigation => (self.navigation_code(), vec![]),
|
||||
FieldKind::SheetSetPlaceholder => {
|
||||
let (label, target, version) = PLACEHOLDER_TYPES[self.ss_placeholder.min(PLACEHOLDER_TYPES.len() - 1)];
|
||||
let target = if label == "Custom" { format!("{target}{}", self.ss_custom) } else { target.to_string() };
|
||||
if label == "ViewportScale" {
|
||||
// The version follows the format, as for PlotScale.
|
||||
let version = codec::fields::PLOT_SCALE_FORMATS
|
||||
.get(self.ss_scale_format)
|
||||
.map_or("", |(_, code)| if code.starts_with("\\AcVar.16.2") { ".16.2" } else { "" });
|
||||
let base = format!("\\AcSm{version} {target}");
|
||||
match viewport_scale_picture(self.ss_scale_format) {
|
||||
f if f.is_empty() => (base, vec![]),
|
||||
f => (format!("{base} {f}"), vec![]),
|
||||
}
|
||||
} else {
|
||||
(case(format!("\\AcSm{version} {target}")), vec![])
|
||||
}
|
||||
}
|
||||
FieldKind::BlockPlaceholder => {
|
||||
let (_, property, format) = codec::fields::BLOCK_PLACEHOLDER_PROPERTIES[self.placeholder_property];
|
||||
// Text properties take the chosen case; the others keep their own format.
|
||||
@@ -345,6 +629,15 @@ pub enum FieldDialogMsg {
|
||||
PlotScale(usize),
|
||||
CountExpression(String),
|
||||
ShowCountInstances,
|
||||
SsCustom(String),
|
||||
SsPlaceholder(usize),
|
||||
SsScaleFormat(usize),
|
||||
SsSet(usize),
|
||||
SsNode(String),
|
||||
SsProp(String),
|
||||
SsHref(bool),
|
||||
SsBrowse,
|
||||
SsPicked(Option<std::path::PathBuf>),
|
||||
Help,
|
||||
Ok,
|
||||
}
|
||||
@@ -648,6 +941,123 @@ fn format_panel<'a>(state: &'a FieldDialogState) -> Element<'a, Message> {
|
||||
.spacing(8)
|
||||
.into(),
|
||||
FieldKind::Count => column![].into(),
|
||||
FieldKind::SheetSet => column![text(t!("Format")).size(12), case_list(state)].spacing(8).into(),
|
||||
FieldKind::SheetSetCustom => {
|
||||
let names = if state.name == "CurrentSheetCustom" { &state.ss_sheet_custom } else { &state.ss_set_custom };
|
||||
column![
|
||||
text(t!("Format")).size(12),
|
||||
case_list(state),
|
||||
text(t!("Custom property name")).size(12),
|
||||
pick_list(
|
||||
(!state.ss_custom.is_empty()).then(|| state.ss_custom.clone()),
|
||||
names.clone(),
|
||||
|s: &String| s.clone(),
|
||||
)
|
||||
.on_select(|s| msg(FieldDialogMsg::SsCustom(s)))
|
||||
.text_size(12)
|
||||
.padding([5, 8])
|
||||
.width(Fill),
|
||||
]
|
||||
.spacing(8)
|
||||
.into()
|
||||
}
|
||||
FieldKind::SheetSetPlaceholder => {
|
||||
let kind = PLACEHOLDER_TYPES[state.ss_placeholder.min(PLACEHOLDER_TYPES.len() - 1)].0;
|
||||
let types = list(
|
||||
PLACEHOLDER_TYPES
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, (n, _, _))| (n.to_string(), state.ss_placeholder == i, FieldDialogMsg::SsPlaceholder(i)))
|
||||
.collect(),
|
||||
200.0,
|
||||
);
|
||||
let format: Element<'a, Message> = if kind == "ViewportScale" {
|
||||
list(
|
||||
codec::fields::PLOT_SCALE_FORMATS
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, (n, _))| (t!(*n).into_owned(), state.ss_scale_format == i, FieldDialogMsg::SsScaleFormat(i)))
|
||||
.collect(),
|
||||
170.0,
|
||||
)
|
||||
} else {
|
||||
case_list(state)
|
||||
};
|
||||
let mut col = column![text(t!("Placeholder type")).size(12), types, text(t!("Format")).size(12), format].spacing(8);
|
||||
if kind == "Custom" {
|
||||
col = col.push(text(t!("Custom property name")).size(12)).push(
|
||||
pick_list(
|
||||
(!state.ss_custom.is_empty()).then(|| state.ss_custom.clone()),
|
||||
state.ss_sheet_custom.clone(),
|
||||
|s: &String| s.clone(),
|
||||
)
|
||||
.on_select(|s| msg(FieldDialogMsg::SsCustom(s)))
|
||||
.text_size(12)
|
||||
.padding([5, 8])
|
||||
.width(Fill),
|
||||
);
|
||||
}
|
||||
col.into()
|
||||
}
|
||||
FieldKind::SheetSetNavigation => {
|
||||
let picks: Vec<Pick> = state.ss_sets.iter().enumerate().map(|(i, d)| Pick(i, d.name().to_string())).collect();
|
||||
let current = picks.get(state.ss_set).cloned();
|
||||
let set_row = row![
|
||||
pick_list(current, picks, |p: &Pick| p.1.clone())
|
||||
.on_select(|p: Pick| msg(FieldDialogMsg::SsSet(p.0)))
|
||||
.text_size(12)
|
||||
.padding([5, 8])
|
||||
.width(Fill),
|
||||
button(text("...").size(12)).on_press(msg(FieldDialogMsg::SsBrowse)).style(button_style(false)).padding([5, 10]),
|
||||
]
|
||||
.spacing(6);
|
||||
let db = state.ss_sets.get(state.ss_set);
|
||||
let nodes = db.map(|d| nav_nodes(d, state.name == "SheetView")).unwrap_or_default();
|
||||
let tree = list(
|
||||
nodes
|
||||
.iter()
|
||||
.map(|(depth, id, label, _)| {
|
||||
(format!("{}{label}", " ".repeat(usize::from(*depth))), *id == state.ss_node, FieldDialogMsg::SsNode(id.clone()))
|
||||
})
|
||||
.collect(),
|
||||
118.0,
|
||||
);
|
||||
let props = db.map(|d| nav_props(d, &state.ss_node)).unwrap_or_default();
|
||||
let prop_list = list(
|
||||
props.iter().map(|(l, _, _)| (l.clone(), *l == state.ss_prop, FieldDialogMsg::SsProp(l.clone()))).collect(),
|
||||
92.0,
|
||||
);
|
||||
let linkable = db.is_some_and(|d| nav_link(d, &state.ss_node).is_some()) && state.ss_prop != "ViewportScale";
|
||||
let mut href = checkbox(state.ss_href && linkable).label(t!("Associate hyperlink").into_owned()).text_size(12).size(14);
|
||||
if linkable {
|
||||
href = href.on_toggle(|v| msg(FieldDialogMsg::SsHref(v)));
|
||||
}
|
||||
let format: Element<'a, Message> = if state.ss_prop == "ViewportScale" {
|
||||
list(
|
||||
codec::fields::PLOT_SCALE_FORMATS
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, (n, _))| (t!(*n).into_owned(), state.ss_scale_format == i, FieldDialogMsg::SsScaleFormat(i)))
|
||||
.collect(),
|
||||
120.0,
|
||||
)
|
||||
} else {
|
||||
case_list(state)
|
||||
};
|
||||
column![
|
||||
text(t!("Sheet set")).size(12),
|
||||
set_row,
|
||||
text(t!("Sheet navigation tree")).size(12),
|
||||
tree,
|
||||
text(t!("Property")).size(12),
|
||||
prop_list,
|
||||
text(t!("Format")).size(12),
|
||||
format,
|
||||
href,
|
||||
]
|
||||
.spacing(8)
|
||||
.into()
|
||||
}
|
||||
FieldKind::Object => column![
|
||||
row![
|
||||
text(t!("Object type")).size(12).width(Length::Fixed(96.0)),
|
||||
@@ -771,6 +1181,7 @@ pub fn view<'a>(
|
||||
]
|
||||
.spacing(10),
|
||||
FieldKind::BlockPlaceholder => column![card(t!("Block placeholder").into_owned(), format_panel(state)), preview].spacing(10),
|
||||
FieldKind::SheetSetNavigation => column![card(t!("Sheet set").into_owned(), format_panel(state)), preview].spacing(10),
|
||||
_ => column![card(t!("Format").into_owned(), format_panel(state)), preview].spacing(10),
|
||||
};
|
||||
let (code, _) = state.code();
|
||||
|
||||
@@ -28,6 +28,7 @@ pub mod find_replace;
|
||||
pub mod named_parameters;
|
||||
pub mod pc_manager;
|
||||
pub mod count_palette;
|
||||
pub mod sheet_set;
|
||||
pub mod pdf_dialogs;
|
||||
pub mod xref_attach;
|
||||
pub mod xref_help;
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user