feat(styles): green ✓ for current style + resolve it from DWG files

- The current-style marker is now a green ✓ in its own fixed-width column
  so names stay aligned; rendered as a separate coloured glyph rather than
  baked into the label string.
- Resolve the current text / dimension / multiline style from the handle
  the DWG header stores into the name the app reads (fix_current_style_names
  on load). DXF already provides these as names ($TEXTSTYLE / $DIMSTYLE /
  $CMLSTYLE); DWG only stores handles, so the marker previously always fell
  back to "Standard". Only overrides when the handle resolves.

Note: table and multileader current styles are not surfaced by the file
reader (no header name/handle exposed), so those markers still default to
the app's active selection until acadrust exposes them.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
Hakan SevenandClaude Opus 4.8 committed 2026-06-10 15:56:13 +03:00
1 parent 885bacd0f6
commit b3ba3a53d1
3 files changed
+56 -13

No files matched your search

+34
View File
@@ -99,6 +99,7 @@ pub fn load_file(path: &Path) -> Result<CadDocument, String> {
.read()
.map_err(|e| e.to_string())?;
fix_viewport_status_flags(&mut doc);
fix_current_style_names(&mut doc);
Ok(doc)
}
"dxf" => {
@@ -108,6 +109,7 @@ pub fn load_file(path: &Path) -> Result<CadDocument, String> {
.map_err(|e| e.to_string())?;
fix_dxf_dimension_rotations(&mut doc);
fix_viewport_status_flags(&mut doc);
fix_current_style_names(&mut doc);
Ok(doc)
}
_ => Err(format!("Unsupported file format: .{ext}")),
@@ -235,6 +237,38 @@ pub fn save(doc: &CadDocument, path: &Path) -> Result<(), String> {
// ── Post-load fixups ──────────────────────────────────────────────────────
// Resolve the current text / dimension / multiline style from the handle the
// DWG header stores into the *name* the app reads. DXF stores these as names
// directly ($TEXTSTYLE / $DIMSTYLE / $CMLSTYLE), but DWG only stores handles,
// so without this the current-style markers (and any code keyed on the name)
// fall back to "Standard". Only overrides when the handle resolves, leaving the
// DXF-provided names intact.
fn fix_current_style_names(doc: &mut CadDocument) {
use acadrust::objects::ObjectType;
let h = doc.header.current_text_style_handle;
if h.is_valid() {
if let Some(name) = doc.text_styles.iter().find(|s| s.handle == h).map(|s| s.name.clone()) {
doc.header.current_text_style_name = name;
}
}
let h = doc.header.current_dimstyle_handle;
if h.is_valid() {
if let Some(name) = doc.dim_styles.iter().find(|s| s.handle == h).map(|s| s.name.clone()) {
doc.header.current_dimstyle_name = name;
}
}
let h = doc.header.current_multiline_style_handle;
if h.is_valid() {
if let Some(name) = doc.objects.values().find_map(|o| match o {
ObjectType::MLineStyle(s) if s.handle == h => Some(s.name.clone()),
_ => None,
}) {
doc.header.multiline_style = name;
}
}
}
// ── Corrupt-entity guard ──────────────────────────────────────────────────
//
// acadrust's DWG parser occasionally desynchronises on certain files and
+20 -5
View File
@@ -9,7 +9,7 @@
//! carries both `on_press` (select) and `on_double_click` (rename) itself.
use crate::app::{Message, StyleKind};
use iced::widget::{container, mouse_area, text, text_input};
use iced::widget::{container, mouse_area, row, text, text_input};
use iced::{Background, Color, Element, Fill, Theme};
/// Shared id for the inline rename field, so the rename-start handler can focus
@@ -30,13 +30,19 @@ const ACTIVE: Color = Color {
b: 0.70,
a: 1.0,
};
const CURRENT_CHECK: Color = Color {
r: 0.30,
g: 0.82,
b: 0.36,
a: 1.0,
};
/// One row of the style list. Renders an editable `text_input` when `name` is
/// the style being renamed (`rename_active`), otherwise a selectable row whose
/// double click starts the rename.
/// double click starts the rename. The current style gets a green ✓.
pub fn item<'a>(
name: &str,
label: String,
is_current: bool,
is_selected: bool,
kind: StyleKind,
on_select: Message,
@@ -53,7 +59,16 @@ pub fn item<'a>(
.width(Fill)
.into()
} else {
let row = container(text(label).size(11).color(TEXT))
// Fixed-width ✓ column keeps every name left-aligned whether or not the
// row is current.
let check = if is_current {
text("✓").size(11).color(CURRENT_CHECK)
} else {
text("").size(11)
};
let label = row![check.width(14), text(name.to_string()).size(11).color(TEXT)]
.align_y(iced::Center);
let cell = container(label)
.padding([4, 8])
.width(Fill)
.style(move |_: &Theme| container::Style {
@@ -61,7 +76,7 @@ pub fn item<'a>(
text_color: Some(TEXT),
..Default::default()
});
mouse_area(row)
mouse_area(cell)
.on_press(on_select)
.on_double_click(Message::StyleRenameStart(kind, name.to_string()))
.into()
+2 -8
View File
@@ -114,16 +114,10 @@ pub fn view<'a, 'b>(s: Scaffold<'a, 'b>) -> Element<'a, Message> {
.iter()
.map(|name| {
let is_sel = name.as_str() == s.selected;
// Mark the current style with a leading ✓; pad the rest so names
// line up.
let label = if s.current == Some(name.as_str()) {
format!("✓ {name}")
} else {
format!(" {name}")
};
let is_current = s.current == Some(name.as_str());
crate::ui::style_list::item(
name,
label,
is_current,
is_sel,
s.kind,
(s.on_select)(name.clone()),