refactor(ui): finish dialog form helper adoption

This commit is contained in:
Karim Jerbi committed 2026-10-18 12:56:33 +01:00
1 parent c80a1d1703
commit b97e67b533
8 files changed
+110 -149

No files matched your search

+70
View File
@@ -0,0 +1,70 @@
use iced::widget::{text, text_input};
use iced::{Background, Theme};
/// Right-hand lane reserved for the scrollbar in editable command tables.
pub(crate) const EDITOR_TABLE_GUTTER: f32 = 16.0;
/// Text style for a value flagged as invalid in an editable command table.
pub(crate) fn danger_text_style(theme: &Theme) -> text::Style {
text::Style {
color: Some(theme.palette().danger.base.color),
}
}
/// Invalid-value field style shared by the Shortcuts and Aliases editors.
pub(crate) fn danger_input_style(theme: &Theme, status: text_input::Status) -> text_input::Style {
let danger = theme.palette().danger.base;
text_input::Style {
background: Background::Color(theme.palette().danger.weak.color),
border: iced::border::rounded(4).color(danger.color).width(
if matches!(status, text_input::Status::Focused { .. }) {
1.5
} else {
1.0
},
),
icon: danger.color,
placeholder: danger.color.scale_alpha(0.7),
value: danger.text,
selection: danger.color,
}
}
#[cfg(test)]
mod tests {
use super::{danger_input_style, danger_text_style, EDITOR_TABLE_GUTTER};
use iced::widget::text_input;
use iced::{Background, Theme};
#[test]
fn invalid_editor_styles_keep_danger_palette_and_focus_border() {
let theme = Theme::Dark;
let palette = theme.palette();
let text_style = danger_text_style(&theme);
assert_eq!(text_style.color, Some(palette.danger.base.color));
let active = danger_input_style(&theme, text_input::Status::Active);
assert_eq!(
active.background,
Background::Color(palette.danger.weak.color)
);
assert_eq!(active.border.color, palette.danger.base.color);
assert_eq!(active.border.width, 1.0);
assert_eq!(active.border.radius, 4.0.into());
assert_eq!(active.icon, palette.danger.base.color);
assert_eq!(
active.placeholder,
palette.danger.base.color.scale_alpha(0.7)
);
assert_eq!(active.value, palette.danger.base.text);
assert_eq!(active.selection, palette.danger.base.color);
let focused = danger_input_style(&theme, text_input::Status::Focused { is_hovered: false });
assert_eq!(focused.border.width, 1.5);
}
#[test]
fn editor_table_gutter_is_sixteen_pixels() {
assert_eq!(EDITOR_TABLE_GUTTER, 16.0);
}
}
+1
View File
@@ -1,6 +1,7 @@
pub mod anno_object_scale;
pub mod common;
pub mod dimstyle;
pub(crate) mod editor_table;
pub mod form;
pub mod fusion_theme;
pub mod mleaderstyle;
+2 -36
View File
@@ -9,6 +9,7 @@
use crate::app::Message;
use crate::t;
use crate::ui::style::common::muted_style;
use crate::ui::style::editor_table::{danger_input_style, danger_text_style, EDITOR_TABLE_GUTTER};
use iced::widget::{button, column, container, row, scrollable, text, text_input, Space};
use iced::{Background, Element, Length, Theme};
@@ -19,41 +20,6 @@ pub enum AliasField {
Command,
}
/// Right-hand lane reserved for the scrollbar so it never overlaps the ✕ column.
const GUTTER: f32 = 16.0;
fn danger_text_style(theme: &Theme) -> iced::widget::text::Style {
iced::widget::text::Style {
color: Some(theme.palette().danger.base.color),
}
}
/// Text-input variant flagging an invalid value: danger border and value
/// color on the theme's danger weak background.
fn danger_input_style(
theme: &Theme,
status: iced::widget::text_input::Status,
) -> iced::widget::text_input::Style {
let danger = theme.palette().danger.base;
iced::widget::text_input::Style {
background: Background::Color(theme.palette().danger.weak.color),
border: iced::border::rounded(4).color(danger.color).width(
if matches!(
status,
iced::widget::text_input::Status::Focused { is_hovered: _ }
) {
1.5
} else {
1.0
},
),
icon: danger.color,
placeholder: danger.color.scale_alpha(0.7),
value: danger.text,
selection: danger.color,
}
}
/// Build the alias editor content. `rows` is the live working buffer.
pub fn view_window<'a>(
rows: &'a [(String, String)],
@@ -78,7 +44,7 @@ pub fn view_window<'a>(
// scrollable rows so the columns stay aligned.
let gutter = iced::Padding {
top: 0.0,
right: GUTTER,
right: EDITOR_TABLE_GUTTER,
bottom: 0.0,
left: 0.0,
};
+12 -19
View File
@@ -42,16 +42,6 @@ fn muted(theme: &Theme) -> iced::widget::text::Style {
}
}
fn button_style(accent: bool) -> impl Fn(&Theme, button::Status) -> button::Style {
move |theme, status| {
if accent {
button::primary(theme, status)
} else {
button::secondary(theme, status)
}
}
}
fn list_style(selected: bool) -> impl Fn(&Theme, button::Status) -> button::Style {
move |theme, status| {
if selected {
@@ -196,7 +186,10 @@ pub fn view_window<'a>(
]
.spacing(8),
row![
text(t!("Current layer")).size(10).style(muted).width(LABEL_WIDTH),
text(t!("Current layer"))
.size(10)
.style(muted)
.width(LABEL_WIDTH),
text(if state.current_layer.is_empty() {
"—".to_string()
} else {
@@ -224,9 +217,9 @@ pub fn view_window<'a>(
let restore = if selected_state.is_some() {
button(text(t!("Restore")).size(11))
.on_press(Message::LayerStateManagerRestore)
.style(button_style(true))
.style(button::primary)
} else {
button(text(t!("Restore")).size(11)).style(button_style(true))
button(text(t!("Restore")).size(11)).style(button::primary)
};
let delete = if selected_state.is_some() {
button(text(t!("Delete")).size(11))
@@ -238,9 +231,9 @@ pub fn view_window<'a>(
let edit = if selected_state.is_some() {
button(text(t!("Edit")).size(11))
.on_press(Message::LayerStateManagerEdit)
.style(button_style(false))
.style(button::secondary)
} else {
button(text(t!("Edit")).size(11)).style(button_style(false))
button(text(t!("Edit")).size(11)).style(button::secondary)
};
let right = container(
@@ -248,7 +241,7 @@ pub fn view_window<'a>(
row![
button(text(t!("New")).size(11))
.on_press(Message::LayerStateManagerNew)
.style(button_style(false))
.style(button::secondary)
.padding([5, 12]),
edit.padding([5, 12]),
Space::new().width(sizing.width),
@@ -282,7 +275,7 @@ pub fn view_window<'a>(
})
.size(11))
.on_press(Message::LayerStateManagerSave)
.style(button_style(true))
.style(button::primary)
.padding([6, 14]),
]
.spacing(7)
@@ -614,11 +607,11 @@ pub fn view_editor<'a>(
Space::new().width(sizing.width),
button(text(t!("Cancel")).size(11))
.on_press(Message::LayerStateEditorCancel)
.style(button_style(false))
.style(button::secondary)
.padding([5, 12]),
button(text(t!("Save Changes")).size(11))
.on_press(Message::LayerStateEditorSave)
.style(button_style(true))
.style(button::primary)
.padding([5, 12]),
]
.spacing(7)
+6 -37
View File
@@ -4,6 +4,7 @@ use crate::app::Message;
use crate::t;
use crate::ui::properties::{lw_options, LinetypeItem, LwItem};
use crate::ui::style::common::muted_style;
use crate::ui::style::form::field_style_with_radius;
use crate::ui::style::row_button::{cell_button_style, header_button_style};
use crate::ui::ROW_H;
use codec::tables::layer::Layer as DocLayer;
@@ -53,29 +54,6 @@ const LINETYPE_MENU_W: f32 = 220.0;
/// scrolled into view after it is added (#271).
pub const LAYER_TABLE_SCROLL_ID: &str = "layer-manager-table-scroll";
fn table_input_style(
theme: &Theme,
status: iced::widget::text_input::Status,
) -> iced::widget::text_input::Style {
let palette = theme.palette();
let border = match status {
iced::widget::text_input::Status::Focused { .. } => palette.primary.base.color,
_ => palette.background.neutral.color,
};
iced::widget::text_input::Style {
background: Background::Color(palette.background.base.color),
border: Border {
color: border,
width: 1.0,
radius: 2.0.into(),
},
icon: palette.background.base.text,
placeholder: palette.background.base.text.scale_alpha(0.48),
value: palette.background.base.text,
selection: palette.primary.base.color.scale_alpha(0.5),
}
}
// ── Layer data ────────────────────────────────────────────────────────────
#[derive(Clone, Debug)]
@@ -401,7 +379,7 @@ impl LayerPanel {
.size(FONT_SZ)
.padding([3, 6])
.width(Length::Fixed(180.0))
.style(table_input_style),
.style(|theme, status| field_style_with_radius(theme, status, 2.0)),
]
.spacing(2)
.align_y(iced::Center),
@@ -816,7 +794,7 @@ fn layer_row<'a>(
left: 4.0,
right: 4.0,
})
.style(table_input_style)
.style(|theme, status| field_style_with_radius(theme, status, 2.0))
.width(Length::Fixed(name_col_w))
.into()
} else {
@@ -892,7 +870,7 @@ fn layer_row<'a>(
right: 4.0,
})
.width(Length::Fixed(COL_LT))
.input_style(combo_input_style),
.input_style(|theme, status| field_style_with_radius(theme, status, 2.0)),
LINETYPE_MENU_W,
)
} else {
@@ -920,7 +898,7 @@ fn layer_row<'a>(
right: 4.0,
})
.width(Length::Fixed(COL_LW))
.input_style(combo_input_style)
.input_style(|theme, status| field_style_with_radius(theme, status, 2.0))
.into()
} else {
text(cur_lw_item.to_string())
@@ -943,7 +921,7 @@ fn layer_row<'a>(
right: 4.0,
})
.style(|theme: &Theme, status| {
let mut style = table_input_style(theme, status);
let mut style = field_style_with_radius(theme, status, 2.0);
style.background = iced::Background::Color(Color::TRANSPARENT);
style
})
@@ -1021,15 +999,6 @@ fn layer_row<'a>(
.into()
}
// ── Combo style ────────────────────────────────────────────────────────────
fn combo_input_style(
theme: &Theme,
status: iced::widget::text_input::Status,
) -> iced::widget::text_input::Style {
table_input_style(theme, status)
}
// ── Display helpers ───────────────────────────────────────────────────────
pub fn iced_color_from_acad(c: &AcadColor) -> Color {
+5 -15
View File
@@ -4,16 +4,6 @@ use crate::ui::style::common::muted_style as muted;
use iced::widget::{button, checkbox, column, container, row, scrollable, text, Space};
use iced::{Background, Border, Element, Length, Theme};
fn button_style(primary: bool) -> impl Fn(&Theme, button::Status) -> button::Style {
move |theme, status| {
if primary {
button::primary(theme, status)
} else {
button::secondary(theme, status)
}
}
}
pub fn view_window<'a>(
layouts: &'a [(String, bool)],
printer: Option<&'a str>,
@@ -61,10 +51,10 @@ pub fn view_window<'a>(
};
let mut pdf = button(text(t!("PDF")).size(11))
.style(button_style(false))
.style(button::secondary)
.padding([5, 16]);
let mut print = button(text(t!("Print")).size(11))
.style(button_style(true))
.style(button::primary)
.padding([5, 18]);
if selected > 0 {
pdf = pdf.on_press(Message::PrintAllPdf);
@@ -94,11 +84,11 @@ pub fn view_window<'a>(
row![
button(text(t!("Select all")).size(11))
.on_press(Message::PrintAllSelectAll)
.style(button_style(false))
.style(button::secondary)
.padding([4, 10]),
button(text(t!("Select none")).size(11))
.on_press(Message::PrintAllSelectNone)
.style(button_style(false))
.style(button::secondary)
.padding([4, 10]),
Space::new().width(Length::Fill),
text(summary).size(11).style(muted),
@@ -113,7 +103,7 @@ pub fn view_window<'a>(
Space::new().width(Length::Fill),
button(text(t!("Options…")).size(11))
.on_press(Message::PrintAllOptions)
.style(button_style(false))
.style(button::secondary)
.padding([5, 12]),
pdf,
print,
+2 -35
View File
@@ -3,6 +3,7 @@
use crate::app::Message;
use crate::t;
use crate::ui::style::common::muted_style;
use crate::ui::style::editor_table::{danger_input_style, danger_text_style, EDITOR_TABLE_GUTTER};
use iced::widget::{button, column, container, row, scrollable, text, text_input, Space};
use iced::{Background, Element, Length, Theme};
@@ -12,40 +13,6 @@ pub enum ShortcutField {
Command,
}
const GUTTER: f32 = 16.0;
fn danger_text_style(theme: &Theme) -> iced::widget::text::Style {
iced::widget::text::Style {
color: Some(theme.palette().danger.base.color),
}
}
/// Text-input variant flagging an invalid value: danger border and value
/// color on the theme's danger weak background.
fn danger_input_style(
theme: &Theme,
status: iced::widget::text_input::Status,
) -> iced::widget::text_input::Style {
let danger = theme.palette().danger.base;
iced::widget::text_input::Style {
background: Background::Color(theme.palette().danger.weak.color),
border: iced::border::rounded(4).color(danger.color).width(
if matches!(
status,
iced::widget::text_input::Status::Focused { is_hovered: _ }
) {
1.5
} else {
1.0
},
),
icon: danger.color,
placeholder: danger.color.scale_alpha(0.7),
value: danger.text,
selection: danger.color,
}
}
pub fn view_window<'a>(
rows: &'a [(String, String)],
capture_row: Option<usize>,
@@ -65,7 +32,7 @@ pub fn view_window<'a>(
.style(muted_style);
let gutter = iced::Padding {
top: 0.0,
right: GUTTER,
right: EDITOR_TABLE_GUTTER,
bottom: 0.0,
left: 0.0,
};
+12 -7
View File
@@ -13,7 +13,7 @@ use crate::app::Message;
use crate::io::xref_model::Pathtype;
use crate::t;
use crate::ui::style::common::muted_style;
use crate::ui::style::form::{button_style, dialog_button, field_style, form_radio};
use crate::ui::style::form::{button_style, dialog_button, field_style, form_radio, LABEL_WIDTH};
use crate::ui::window::block_definition::{group, labeled_checkbox};
/// One edit in the dialog.
@@ -366,8 +366,12 @@ pub fn view_window<'a>(
group(
t!("Location").into_owned(),
column![
read_only_field(t!("Found in:").into_owned(), &state.found_in, 92.0),
read_only_field(t!("Saved path:").into_owned(), &state.saved_path, 92.0),
read_only_field(t!("Found in:").into_owned(), &state.found_in, LABEL_WIDTH,),
read_only_field(
t!("Saved path:").into_owned(),
&state.saved_path,
LABEL_WIDTH,
),
]
.spacing(5),
Length::Shrink,
@@ -383,10 +387,11 @@ pub fn view_window<'a>(
t!("Show Details")
};
let footer = row![
button(text(details_label).size(12))
.on_press(msg(XrefAttachMsg::Details(!state.details)))
.style(button::secondary)
.padding([6, 18]),
dialog_button(
details_label,
msg(XrefAttachMsg::Details(!state.details)),
false,
),
Space::new().width(Fill),
dialog_button(t!("OK"), msg(XrefAttachMsg::Apply), true),
dialog_button(t!("Cancel"), Message::CloseModal, false),