style: apply cargo fmt across workspace

This commit is contained in:
Karim Jerbi committed 2026-10-11 03:14:29 +01:00
1 parent 85710e5454
commit 9cf9ff2c5c
531 files changed
+57740 -33906

No files matched your search

+16 -20
View File
@@ -7,10 +7,10 @@
//! the style / scale managers' frame so it looks consistent.
use crate::app::Message;
use crate::t;
use crate::ui::style::style_manager::{hdivider, muted_text_style, tb_button};
use iced::widget::{column, container, mouse_area, row, scrollable, text, Space};
use iced::{Background, Border, Element, Theme};
use crate::t;
/// `scales` is `(name, "paper:drawing" ratio, is_member)`. Every label is cloned
/// into the widget tree, so the returned element borrows nothing from the args.
@@ -29,9 +29,7 @@ pub fn view_window(
.align_y(iced::Center),
)
.style(|theme: &Theme| container::Style {
background: Some(Background::Color(
theme.palette().background.weak.color
)),
background: Some(Background::Color(theme.palette().background.weak.color)),
..Default::default()
})
.width(sizing.width)
@@ -48,9 +46,7 @@ pub fn view_window(
]
.spacing(4)
.align_y(iced::Center);
let cell = container(label)
.padding([4, 8])
.width(sizing.width);
let cell = container(label).padding([4, 8]).width(sizing.width);
mouse_area(cell)
.on_press(Message::AnnoObjectScaleToggle(name.clone()))
.into()
@@ -61,13 +57,13 @@ pub fn view_window(
.style(|theme: &Theme| {
let palette = theme.palette();
container::Style {
background: Some(Background::Color(palette.background.weak.color)),
border: Border {
color: palette.background.neutral.color,
width: 1.0,
radius: 3.0.into(),
},
..Default::default()
background: Some(Background::Color(palette.background.weak.color)),
border: Border {
color: palette.background.neutral.color,
width: 1.0,
radius: 3.0.into(),
},
..Default::default()
}
})
.width(sizing.width)
@@ -76,9 +72,11 @@ pub fn view_window(
let body = container(
column![
text(t!("Click a scale to add or remove the object's representation for it."))
.size(10)
.style(muted_text_style),
text(t!(
"Click a scale to add or remove the object's representation for it."
))
.size(10)
.style(muted_text_style),
list,
]
.spacing(6)
@@ -90,9 +88,7 @@ pub fn view_window(
container(column![toolbar, hdivider(sizing.width), body])
.style(|theme: &Theme| container::Style {
background: Some(Background::Color(
theme.palette().background.base.color
)),
background: Some(Background::Color(theme.palette().background.base.color)),
..Default::default()
})
.width(sizing.width)
+5 -1
View File
@@ -102,7 +102,11 @@ pub fn dropdown_popup_width<'a>(
min: f32,
) -> f32 {
let max_units = labels
.map(|l| l.chars().map(|c| if is_wide(c) { 2.0 } else { 1.0 }).sum::<f32>())
.map(|l| {
l.chars()
.map(|c| if is_wide(c) { 2.0 } else { 1.0 })
.sum::<f32>()
})
.fold(0.0f32, f32::max);
(max_units * font_size * 0.68 + chrome).max(min)
}
+234 -124
View File
@@ -2,13 +2,13 @@
use crate::app::{ColorPickTarget, DsField, Message};
use crate::scene::convert::tessellate::{arrow_from_block_name, ArrowKind};
use crate::t;
use crate::ui::style::common::muted_style;
use crate::ui::style::form::hdivider;
use iced::widget::{
button, canvas, checkbox, column, container, row, scrollable, text, text_input, Space,
};
use iced::{mouse, Background, Border, Element, Length, Point, Rectangle, Theme};
use crate::ui::style::common::muted_style;
use crate::ui::style::form::hdivider;
use crate::t;
use std::borrow::Cow;
use std::fmt;
@@ -121,20 +121,18 @@ fn tab_btn_style(active: bool) -> impl Fn(&Theme, button::Status) -> button::Sty
let palette = theme.palette();
let pair = match (active, st) {
(true, _) => palette.primary.strong,
(false, button::Status::Hovered | button::Status::Pressed) => {
palette.background.strong
}
(false, button::Status::Hovered | button::Status::Pressed) => palette.background.strong,
_ => palette.background.weak,
};
button::Style {
background: Some(Background::Color(pair.color)),
text_color: pair.text,
border: Border {
color: palette.background.neutral.color,
width: 1.0,
radius: 3.0.into(),
},
..Default::default()
background: Some(Background::Color(pair.color)),
text_color: pair.text,
border: Border {
color: palette.background.neutral.color,
width: 1.0,
radius: 3.0.into(),
},
..Default::default()
}
}
}
@@ -221,22 +219,45 @@ impl canvas::Program<Message> for DimensionPreview {
let line = |a: Point, b: Point| canvas::Path::line(a, b);
frame.stroke(
&line(Point::new(x1 - 18.0, object_y), Point::new(x2 + 18.0, object_y)),
canvas::Stroke::default().with_color(ink.scale_alpha(0.38)).with_width(1.0),
&line(
Point::new(x1 - 18.0, object_y),
Point::new(x2 + 18.0, object_y),
),
canvas::Stroke::default()
.with_color(ink.scale_alpha(0.38))
.with_width(1.0),
);
if self.ext1 {
frame.stroke(&line(Point::new(x1, object_y), Point::new(x1, 22.0)), stroke.clone());
frame.stroke(
&line(Point::new(x1, object_y), Point::new(x1, 22.0)),
stroke.clone(),
);
}
if self.ext2 {
frame.stroke(&line(Point::new(x2, object_y), Point::new(x2, 22.0)), stroke.clone());
frame.stroke(
&line(Point::new(x2, object_y), Point::new(x2, 22.0)),
stroke.clone(),
);
}
let text_half = (self.text.chars().count() as f32 * 3.4 + 8.0).min((x2 - x1) * 0.34);
if self.dim1 {
frame.stroke(&line(Point::new(x1, y), Point::new((bounds.width * 0.5 - text_half).max(x1), y)), stroke.clone());
frame.stroke(
&line(
Point::new(x1, y),
Point::new((bounds.width * 0.5 - text_half).max(x1), y),
),
stroke.clone(),
);
}
if self.dim2 {
frame.stroke(&line(Point::new((bounds.width * 0.5 + text_half).min(x2), y), Point::new(x2, y)), stroke.clone());
frame.stroke(
&line(
Point::new((bounds.width * 0.5 + text_half).min(x2), y),
Point::new(x2, y),
),
stroke.clone(),
);
}
let size = self.arrow_size.clamp(5.0, 14.0);
@@ -259,7 +280,11 @@ impl canvas::Program<Message> for DimensionPreview {
}
match kind {
ArrowKind::None => {}
ArrowKind::Triangle { size, filled, size_mul } => {
ArrowKind::Triangle {
size,
filled,
size_mul,
} => {
let s = size * size_mul;
let arrow = canvas::Path::new(|path| {
path.move_to(Point::new(tip_x, y));
@@ -270,7 +295,10 @@ impl canvas::Program<Message> for DimensionPreview {
if *filled {
frame.fill(&arrow, guide);
} else {
frame.stroke(&arrow, canvas::Stroke::default().with_color(guide).with_width(1.4));
frame.stroke(
&arrow,
canvas::Stroke::default().with_color(guide).with_width(1.4),
);
}
}
ArrowKind::Open { size, half_angle } => {
@@ -286,11 +314,15 @@ impl canvas::Program<Message> for DimensionPreview {
}
}
ArrowKind::Dot { size, filled } => {
let dot = canvas::Path::circle(Point::new(tip_x + sign * size * 0.5, y), size * 0.5);
let dot =
canvas::Path::circle(Point::new(tip_x + sign * size * 0.5, y), size * 0.5);
if *filled {
frame.fill(&dot, guide);
} else {
frame.stroke(&dot, canvas::Stroke::default().with_color(guide).with_width(1.4));
frame.stroke(
&dot,
canvas::Stroke::default().with_color(guide).with_width(1.4),
);
}
}
ArrowKind::Tick { size } => {
@@ -308,7 +340,10 @@ impl canvas::Program<Message> for DimensionPreview {
if *filled {
frame.fill(&square, guide);
} else {
frame.stroke(&square, canvas::Stroke::default().with_color(guide).with_width(1.4));
frame.stroke(
&square,
canvas::Stroke::default().with_color(guide).with_width(1.4),
);
}
}
// Datum/Origin have dedicated CAD geometry; the preview keeps
@@ -323,12 +358,19 @@ impl canvas::Program<Message> for DimensionPreview {
if *filled {
frame.fill(&arrow, guide);
} else {
frame.stroke(&arrow, canvas::Stroke::default().with_color(guide).with_width(1.4));
frame.stroke(
&arrow,
canvas::Stroke::default().with_color(guide).with_width(1.4),
);
}
}
ArrowKind::Origin { size } => {
let dot = canvas::Path::circle(Point::new(tip_x + sign * size * 0.5, y), size * 0.4);
frame.stroke(&dot, canvas::Stroke::default().with_color(guide).with_width(1.4));
let dot =
canvas::Path::circle(Point::new(tip_x + sign * size * 0.5, y), size * 0.4);
frame.stroke(
&dot,
canvas::Stroke::default().with_color(guide).with_width(1.4),
);
}
// Custom DWG block geometry cannot render in the schematic
// preview; fall back to the standard filled triangle.
@@ -346,8 +388,7 @@ impl canvas::Program<Message> for DimensionPreview {
let text_y = if self.text_above { y - 16.0 } else { y };
if self.basic {
let frame_width = (self.text.chars().count() as f32 * 7.0 + 12.0)
.min((x2 - x1) * 0.8);
let frame_width = (self.text.chars().count() as f32 * 7.0 + 12.0).min((x2 - x1) * 0.8);
frame.stroke(
&canvas::Path::rectangle(
Point::new(bounds.width * 0.5 - frame_width * 0.5, text_y - 9.0),
@@ -446,7 +487,8 @@ pub fn view_window<'a>(
if vals.read_only {
item.into()
} else {
item.on_toggle(move |_| Message::DsToggle(fld.clone())).into()
item.on_toggle(move |_| Message::DsToggle(fld.clone()))
.into()
}
};
@@ -476,17 +518,15 @@ pub fn view_window<'a>(
crate::ui::read_only::field(cur.to_string().as_str(), 11.0, Length::Fixed(150.0))
} else {
iced::widget::pick_list(Some(cur), options, |value| value.to_string())
.on_select(move |chosen: DimEnumChoice| {
Message::DsEdit(fld.clone(), chosen.code)
})
.on_select(move |chosen: DimEnumChoice| Message::DsEdit(fld.clone(), chosen.code))
.text_size(11)
.width(150)
.into()
};
row![lbl(label), choice]
.spacing(8)
.align_y(iced::Center)
.into()
.spacing(8)
.align_y(iced::Center)
.into()
};
// Linear unit formats shared by DIMLUNIT / DIMALTU.
@@ -503,7 +543,11 @@ pub fn view_window<'a>(
("8", "0.00000000"),
];
// A precision dropdown, or the read-only value while the option is off.
let prec_field = move |label: Cow<'static, str>, fld: DsField, val: &'a str, enabled: bool| -> Element<'a, Message> {
let prec_field = move |label: Cow<'static, str>,
fld: DsField,
val: &'a str,
enabled: bool|
-> Element<'a, Message> {
if enabled {
enum_field(label, fld, val, OPT_PREC)
} else {
@@ -563,26 +607,47 @@ pub fn view_window<'a>(
-> Element<'a, Message> {
let raw = value.trim().parse::<i16>().unwrap_or(0);
let feet_modes = vec![
DimEnumChoice { code: "0".into(), label: t!("Suppress zero feet and zero inches").into_owned() },
DimEnumChoice { code: "1".into(), label: t!("Show zero feet and zero inches").into_owned() },
DimEnumChoice { code: "2".into(), label: t!("Show zero feet; suppress zero inches").into_owned() },
DimEnumChoice { code: "3".into(), label: t!("Suppress zero feet; show zero inches").into_owned() },
DimEnumChoice {
code: "0".into(),
label: t!("Suppress zero feet and zero inches").into_owned(),
},
DimEnumChoice {
code: "1".into(),
label: t!("Show zero feet and zero inches").into_owned(),
},
DimEnumChoice {
code: "2".into(),
label: t!("Show zero feet; suppress zero inches").into_owned(),
},
DimEnumChoice {
code: "3".into(),
label: t!("Suppress zero feet; show zero inches").into_owned(),
},
];
let feet_current = feet_modes[(raw & 3) as usize].clone();
let feet: Element<'a, Message> = if show_feet_inches {
let list = iced::widget::pick_list(Some(feet_current.clone()), feet_modes, |choice| choice.to_string())
.text_size(11)
.width(210);
let list = iced::widget::pick_list(Some(feet_current.clone()), feet_modes, |choice| {
choice.to_string()
})
.text_size(11)
.width(210);
let list: Element<'a, Message> = if enabled && !vals.read_only {
let target = field.clone();
list.on_select(move |choice| {
Message::DsZeroBase(target.clone(), choice.code.parse().unwrap_or(0))
}).into()
})
.into()
} else {
crate::ui::read_only::field(feet_current.to_string().as_str(), 11.0, Length::Fixed(210.0))
crate::ui::read_only::field(
feet_current.to_string().as_str(),
11.0,
Length::Fixed(210.0),
)
};
row![lbl(t!("Feet and inches")), list]
.spacing(8).align_y(iced::Center).into()
.spacing(8)
.align_y(iced::Center)
.into()
} else {
Space::new().height(0).into()
};
@@ -596,12 +661,16 @@ pub fn view_window<'a>(
.text_size(11);
let leading: Element<'a, Message> = if enabled && !vals.read_only {
let target = field.clone();
leading.on_toggle(move |_| Message::DsZeroFlag(target.clone(), 4)).into()
leading
.on_toggle(move |_| Message::DsZeroFlag(target.clone(), 4))
.into()
} else {
leading.into()
};
let trailing: Element<'a, Message> = if enabled && !vals.read_only {
trailing.on_toggle(move |_| Message::DsZeroFlag(field.clone(), 8)).into()
trailing
.on_toggle(move |_| Message::DsZeroFlag(field.clone(), 8))
.into()
} else {
trailing.into()
};
@@ -611,39 +680,42 @@ pub fn view_window<'a>(
// Shared colour selector (main dropdown + "more" palette), reusing the
// existing DsEdit path (the chosen colour is sent as an ACI string).
let color_open = vals.color_open.clone();
let color_row = move |label: Cow<'static, str>, fld: DsField, _val: &'a str| -> Element<'a, Message> {
if vals.read_only {
return row![
lbl(label),
crate::ui::read_only::field(_val, 11.0, Length::Fixed(150.0)),
]
.spacing(8)
.align_y(iced::Center)
.into();
}
let cur = crate::ui::color_select::aci_string_to_color(_val);
let open = color_open.as_ref() == Some(&fld);
let f_sel = fld.clone();
let selector = crate::ui::color_select::color_selector(
cur,
open,
crate::ui::color_select::ColorExtras {
by_layer: true,
by_block: true,
..Default::default()
},
move |c| Message::DsEdit(f_sel.clone(), crate::ui::color_select::color_to_aci_string(c)),
Message::DsColorMore(fld.clone()),
Message::OpenColorWindow(
ColorPickTarget::DimStyle(fld.clone()),
let color_row =
move |label: Cow<'static, str>, fld: DsField, _val: &'a str| -> Element<'a, Message> {
if vals.read_only {
return row![
lbl(label),
crate::ui::read_only::field(_val, 11.0, Length::Fixed(150.0)),
]
.spacing(8)
.align_y(iced::Center)
.into();
}
let cur = crate::ui::color_select::aci_string_to_color(_val);
let open = color_open.as_ref() == Some(&fld);
let f_sel = fld.clone();
let selector = crate::ui::color_select::color_selector(
cur,
),
);
row![lbl(label), container(selector).width(150)]
.spacing(8)
.align_y(iced::Center)
.into()
};
open,
crate::ui::color_select::ColorExtras {
by_layer: true,
by_block: true,
..Default::default()
},
move |c| {
Message::DsEdit(
f_sel.clone(),
crate::ui::color_select::color_to_aci_string(c),
)
},
Message::DsColorMore(fld.clone()),
Message::OpenColorWindow(ColorPickTarget::DimStyle(fld.clone()), cur),
);
row![lbl(label), container(selector).width(150)]
.spacing(8)
.align_y(iced::Center)
.into()
};
// Block / linetype Handle dropdown: pick a block-record (arrowheads) or a
// linetype by name from the available records.
@@ -662,22 +734,24 @@ pub fn view_window<'a>(
.into()
};
row![lbl(label), list]
.spacing(8)
.align_y(iced::Center)
.into()
.spacing(8)
.align_y(iced::Center)
.into()
};
let hrow_enabled = move |label: Cow<'static, str>,
options: Vec<String>,
selected: String,
field: &'static str,
enabled: bool|
options: Vec<String>,
selected: String,
field: &'static str,
enabled: bool|
-> Element<'a, Message> {
let list = iced::widget::pick_list(Some(selected.clone()), options, |value| value.to_string())
.text_size(11)
.width(150);
let list =
iced::widget::pick_list(Some(selected.clone()), options, |value| value.to_string())
.text_size(11)
.width(150);
let list: Element<'a, Message> = if enabled && !vals.read_only {
list.on_select(move |value| Message::DsSetHandle { field, value }).into()
list.on_select(move |value| Message::DsSetHandle { field, value })
.into()
} else {
crate::ui::read_only::field(&selected, 11.0, Length::Fixed(150.0))
};
@@ -700,20 +774,33 @@ pub fn view_window<'a>(
.width(150)
.into()
};
let text_height_note: Element<'a, Message> = if let Some(height) = vals.text_style_fixed_height {
text(t!("The selected text style fixes the height at %{height}.", height = height))
.size(10)
.style(muted_style)
.into()
let text_height_note: Element<'a, Message> = if let Some(height) = vals.text_style_fixed_height
{
text(t!(
"The selected text style fixes the height at %{height}.",
height = height
))
.size(10)
.style(muted_style)
.into()
} else {
Space::new().height(0).into()
};
let center_mode = vals.dimcen.trim().parse::<f64>().unwrap_or(0.0);
let tick_on = vals.dimtsz.trim().parse::<f64>().unwrap_or(0.0) > 0.0;
let center_choices = vec![
DimEnumChoice { code: "none".into(), label: t!("None").into_owned() },
DimEnumChoice { code: "mark".into(), label: t!("Center mark").into_owned() },
DimEnumChoice { code: "lines".into(), label: t!("Centerlines").into_owned() },
DimEnumChoice {
code: "none".into(),
label: t!("None").into_owned(),
},
DimEnumChoice {
code: "mark".into(),
label: t!("Center mark").into_owned(),
},
DimEnumChoice {
code: "lines".into(),
label: t!("Centerlines").into_owned(),
},
];
let center_current = if center_mode < 0.0 {
center_choices[2].clone()
@@ -723,20 +810,41 @@ pub fn view_window<'a>(
center_choices[0].clone()
};
let center_method_field: Element<'a, Message> = if vals.read_only {
crate::ui::read_only::field(center_current.to_string().as_str(), 11.0, Length::Fixed(150.0))
crate::ui::read_only::field(
center_current.to_string().as_str(),
11.0,
Length::Fixed(150.0),
)
} else {
iced::widget::pick_list(Some(center_current), center_choices, |choice| choice.to_string())
.on_select(|choice| Message::DsCenterMarkMode(choice.code))
.text_size(11)
.width(150)
.into()
iced::widget::pick_list(Some(center_current), center_choices, |choice| {
choice.to_string()
})
.on_select(|choice| Message::DsCenterMarkMode(choice.code))
.text_size(11)
.width(150)
.into()
};
let tolerance_choices = vec![
DimEnumChoice { code: "none".into(), label: t!("None").into_owned() },
DimEnumChoice { code: "symmetrical".into(), label: t!("Symmetrical").into_owned() },
DimEnumChoice { code: "deviation".into(), label: t!("Deviation").into_owned() },
DimEnumChoice { code: "limits".into(), label: t!("Limits").into_owned() },
DimEnumChoice { code: "basic".into(), label: t!("Basic").into_owned() },
DimEnumChoice {
code: "none".into(),
label: t!("None").into_owned(),
},
DimEnumChoice {
code: "symmetrical".into(),
label: t!("Symmetrical").into_owned(),
},
DimEnumChoice {
code: "deviation".into(),
label: t!("Deviation").into_owned(),
},
DimEnumChoice {
code: "limits".into(),
label: t!("Limits").into_owned(),
},
DimEnumChoice {
code: "basic".into(),
label: t!("Basic").into_owned(),
},
];
let tolerance_current = if vals.dimgap.trim().starts_with('-') {
tolerance_choices[4].clone()
@@ -750,13 +858,15 @@ pub fn view_window<'a>(
tolerance_choices[0].clone()
};
let tolerance_method_field: Element<'a, Message> = if vals.read_only {
crate::ui::read_only::field(tolerance_current.to_string().as_str(), 11.0, Length::Fixed(150.0))
} else {
iced::widget::pick_list(
Some(tolerance_current),
tolerance_choices,
|choice| choice.to_string(),
crate::ui::read_only::field(
tolerance_current.to_string().as_str(),
11.0,
Length::Fixed(150.0),
)
} else {
iced::widget::pick_list(Some(tolerance_current), tolerance_choices, |choice| {
choice.to_string()
})
.on_select(|choice| Message::DsToleranceMode(choice.code))
.text_size(11)
.width(150)
@@ -1221,11 +1331,7 @@ pub fn view_window<'a>(
preview_text.push_str(&format!(" [{alternate_text}]"));
}
if vals.dimlim {
preview_text = format!(
"{} / {}",
preview_text,
vals.dimtm.trim()
);
preview_text = format!("{} / {}", preview_text, vals.dimtm.trim());
} else if vals.dimtol {
if vals.dimtp.trim() == vals.dimtm.trim() {
preview_text.push_str(&format!(" ±{}", vals.dimtp.trim()));
@@ -1282,7 +1388,11 @@ pub fn view_window<'a>(
let summary = if vals.comparison_sections.is_empty() {
t!("No differences").into_owned()
} else {
format!("{}: {}", t!("Different sections"), vals.comparison_sections.join(", "))
format!(
"{}: {}",
t!("Different sections"),
vals.comparison_sections.join(", ")
)
};
row![
text(t!("Compare with")).size(10).style(muted_style),
+387 -89
View File
@@ -2,9 +2,9 @@
use crate::app::Message;
use crate::t;
use crate::ui::style::common::muted_style;
use iced::widget::{canvas, checkbox, column, container, row, text, text_input};
use iced::{mouse, Color, Element, Length, Point, Rectangle, Size, Theme};
use crate::ui::style::common::muted_style;
use std::borrow::Cow;
use std::fmt;
@@ -142,11 +142,17 @@ fn enum_row<'a>(
row![
text(label).size(11).style(muted_style).width(165),
iced::widget::pick_list(
Some(EnumChoice { code: selected, label: selected_label }),
Some(EnumChoice {
code: selected,
label: selected_label
}),
choices(values),
|value| value.to_string(),
)
.on_select(move |choice| Message::MLeaderStyleSetEnum { field, value: choice.code })
.on_select(move |choice| Message::MLeaderStyleSetEnum {
field,
value: choice.code
})
.text_size(11)
.width(220),
]
@@ -181,7 +187,10 @@ fn handle_row<'a>(
row![
text(label).size(11).style(muted_style).width(165),
iced::widget::pick_list(Some(selected), options, |value| value.to_string())
.on_select(move |value| Message::MLeaderStyleSetHandle { field, value: value.code })
.on_select(move |value| Message::MLeaderStyleSetHandle {
field,
value: value.code
})
.text_size(11)
.width(220),
]
@@ -206,7 +215,10 @@ const ATTACHMENTS: [(&str, &str); 11] = [
("MiddleOfBottomLine", "Middle of bottom line"),
("BottomOfBottomLine", "Bottom of bottom line"),
("BottomLine", "Bottom line"),
("BottomOfTopLineUnderlineBottomLine", "Underline bottom line"),
(
"BottomOfTopLineUnderlineBottomLine",
"Underline bottom line",
),
("BottomOfTopLineUnderlineTopLine", "Underline top line"),
("BottomOfTopLineUnderlineAll", "Underline all text"),
("CenterOfText", "Center of text"),
@@ -314,12 +326,32 @@ impl canvas::Program<Message> for LeaderPreviewCanvas {
let scale = if self.annotative {
1.0
} else {
self.scale.trim().parse::<f32>().unwrap_or(1.0).abs().clamp(0.35, 2.2)
self.scale
.trim()
.parse::<f32>()
.unwrap_or(1.0)
.abs()
.clamp(0.35, 2.2)
};
let head = Point::new(34.0, bounds.height - 37.0);
let angle1 = self.first_angle.trim().parse::<f32>().unwrap_or(28.0).to_radians();
let angle2 = self.second_angle.trim().parse::<f32>().unwrap_or(0.0).to_radians();
let points = self.max_points.trim().parse::<usize>().unwrap_or(2).clamp(2, 5);
let angle1 = self
.first_angle
.trim()
.parse::<f32>()
.unwrap_or(28.0)
.to_radians();
let angle2 = self
.second_angle
.trim()
.parse::<f32>()
.unwrap_or(0.0)
.to_radians();
let points = self
.max_points
.trim()
.parse::<usize>()
.unwrap_or(2)
.clamp(2, 5);
let elbow = Point::new(
head.x + 105.0 * scale * angle1.cos().abs().max(0.25),
head.y - 70.0 * scale * angle1.sin().abs().max(0.2),
@@ -342,7 +374,10 @@ impl canvas::Program<Message> for LeaderPreviewCanvas {
style: canvas::Style::Solid(line_color),
width,
line_dash: if dashed {
canvas::LineDash { segments: &[7.0, 4.0], offset: 0 }
canvas::LineDash {
segments: &[7.0, 4.0],
offset: 0,
}
} else {
canvas::LineDash::default()
},
@@ -355,7 +390,8 @@ impl canvas::Program<Message> for LeaderPreviewCanvas {
for step in 1..=18 {
let t = step as f32 / 18.0;
let x = head.x + (elbow.x - head.x) * t;
let y = head.y + (elbow.y - head.y) * t - (t * std::f32::consts::PI).sin() * 15.0;
let y = head.y + (elbow.y - head.y) * t
- (t * std::f32::consts::PI).sin() * 15.0;
builder.line_to(Point::new(x, y));
}
});
@@ -365,7 +401,11 @@ impl canvas::Program<Message> for LeaderPreviewCanvas {
builder.move_to(head);
for index in 1..points {
let t = index as f32 / (points - 1) as f32;
let bend = if index + 1 == points { 0.0 } else { (index as f32 * 7.0) % 14.0 - 7.0 };
let bend = if index + 1 == points {
0.0
} else {
(index as f32 * 7.0) % 14.0 - 7.0
};
builder.line_to(Point::new(
head.x + (elbow.x - head.x) * t,
head.y + (elbow.y - head.y) * t + bend,
@@ -375,12 +415,32 @@ impl canvas::Program<Message> for LeaderPreviewCanvas {
frame.stroke(&path, stroke.clone());
}
if self.landing && self.dogleg {
let gap = self.break_gap.trim().parse::<f32>().unwrap_or(0.0).abs().clamp(0.0, 8.0);
frame.stroke(&canvas::Path::line(elbow, Point::new((elbow.x + tail.x) * 0.5 - gap, elbow.y)), stroke.clone());
frame.stroke(&canvas::Path::line(Point::new((elbow.x + tail.x) * 0.5 + gap, elbow.y), tail), stroke.clone());
let gap = self
.break_gap
.trim()
.parse::<f32>()
.unwrap_or(0.0)
.abs()
.clamp(0.0, 8.0);
frame.stroke(
&canvas::Path::line(elbow, Point::new((elbow.x + tail.x) * 0.5 - gap, elbow.y)),
stroke.clone(),
);
frame.stroke(
&canvas::Path::line(Point::new((elbow.x + tail.x) * 0.5 + gap, elbow.y), tail),
stroke.clone(),
);
}
}
let arrow = self.arrow_size.trim().parse::<f32>().unwrap_or(0.18).abs().mul_add(12.0, 4.0).clamp(5.0, 18.0) * scale;
let arrow = self
.arrow_size
.trim()
.parse::<f32>()
.unwrap_or(0.18)
.abs()
.mul_add(12.0, 4.0)
.clamp(5.0, 18.0)
* scale;
let arrow_code = self.arrow_name_code.to_ascii_uppercase();
if arrow_code.contains("DOT") {
frame.fill(&canvas::Path::circle(head, arrow * 0.42), line_color);
@@ -390,7 +450,9 @@ impl canvas::Program<Message> for LeaderPreviewCanvas {
Point::new(head.x - arrow * 0.35, head.y + arrow * 0.65),
Point::new(head.x + arrow * 0.35, head.y - arrow * 0.65),
),
canvas::Stroke::default().with_color(line_color).with_width(width),
canvas::Stroke::default()
.with_color(line_color)
.with_width(width),
);
} else if arrow_code.contains("BOX") {
frame.fill(
@@ -415,16 +477,29 @@ impl canvas::Program<Message> for LeaderPreviewCanvas {
});
frame.stroke(
&open_path,
canvas::Stroke::default().with_color(line_color).with_width(width),
canvas::Stroke::default()
.with_color(line_color)
.with_width(width),
);
} else {
frame.fill(&arrow_path, line_color);
}
}
let landing_gap = self.landing_gap.trim().parse::<f32>().unwrap_or(0.09).abs().mul_add(8.0, 5.0).clamp(5.0, 24.0);
let landing_gap = self
.landing_gap
.trim()
.parse::<f32>()
.unwrap_or(0.09)
.abs()
.mul_add(8.0, 5.0)
.clamp(5.0, 24.0);
let content_origin = Point::new(tail.x + landing_gap, tail.y);
if self.content_type == "Block" {
let scales = self.block_scale.iter().map(|value| value.trim().parse::<f32>().unwrap_or(1.0).abs()).collect::<Vec<_>>();
let scales = self
.block_scale
.iter()
.map(|value| value.trim().parse::<f32>().unwrap_or(1.0).abs())
.collect::<Vec<_>>();
let (scale_x, scale_y) = if self.enable_block_scale {
(scales[0].clamp(0.3, 2.5), scales[1].clamp(0.3, 2.5))
} else {
@@ -432,7 +507,11 @@ impl canvas::Program<Message> for LeaderPreviewCanvas {
};
let size = Size::new(42.0 * scale_x, 30.0 * scale_y);
let rotation = if self.enable_block_rotation {
self.block_rotation.trim().parse::<f32>().unwrap_or(0.0).to_radians()
self.block_rotation
.trim()
.parse::<f32>()
.unwrap_or(0.0)
.to_radians()
} else {
0.0
};
@@ -442,10 +521,7 @@ impl canvas::Program<Message> for LeaderPreviewCanvas {
content_origin.x + size.width * 0.5
};
frame.with_save(|frame| {
frame.translate(iced::Vector::new(
center_x,
content_origin.y,
));
frame.translate(iced::Vector::new(center_x, content_origin.y));
frame.rotate(iced::Radians(rotation));
let top_left = Point::new(-size.width * 0.5, -size.height * 0.5);
let rect = canvas::Path::rectangle(top_left, size);
@@ -455,10 +531,7 @@ impl canvas::Program<Message> for LeaderPreviewCanvas {
canvas::Stroke::default().with_color(color).with_width(1.5),
);
frame.stroke(
&canvas::Path::line(
top_left,
Point::new(size.width * 0.5, size.height * 0.5),
),
&canvas::Path::line(top_left, Point::new(size.width * 0.5, size.height * 0.5)),
canvas::Stroke::default().with_color(color),
);
});
@@ -470,16 +543,34 @@ impl canvas::Program<Message> for LeaderPreviewCanvas {
} else {
self.default_text.clone()
};
let text_size = self.text_height.trim().parse::<f32>().unwrap_or(0.18).abs().mul_add(22.0, 8.0).clamp(9.0, 19.0) * scale;
let box_width = (content.chars().count() as f32 * text_size * 0.55 + 14.0).clamp(60.0, bounds.width - content_origin.x - 8.0);
let box_height = text_size + 12.0 + self.align_space.trim().parse::<f32>().unwrap_or(0.0).abs().min(8.0);
let text_size = self
.text_height
.trim()
.parse::<f32>()
.unwrap_or(0.18)
.abs()
.mul_add(22.0, 8.0)
.clamp(9.0, 19.0)
* scale;
let box_width = (content.chars().count() as f32 * text_size * 0.55 + 14.0)
.clamp(60.0, bounds.width - content_origin.x - 8.0);
let box_height = text_size
+ 12.0
+ self
.align_space
.trim()
.parse::<f32>()
.unwrap_or(0.0)
.abs()
.min(8.0);
let attachment_offset = if self.attachment_direction == "Horizontal" {
match self.left_attachment_code.as_str() {
"TopOfTopLine" | "BottomOfTopLineUnderlineTopLine" => box_height * 0.5,
"MiddleOfTopLine" => box_height * 0.25,
"MiddleOfBottomLine" => -box_height * 0.25,
"BottomOfBottomLine" | "BottomLine"
| "BottomOfTopLineUnderlineBottomLine" => -box_height * 0.5,
"BottomOfBottomLine" | "BottomLine" | "BottomOfTopLineUnderlineBottomLine" => {
-box_height * 0.5
}
_ => 0.0,
}
} else {
@@ -488,8 +579,13 @@ impl canvas::Program<Message> for LeaderPreviewCanvas {
let content_y = content_origin.y + attachment_offset;
if self.text_frame {
frame.stroke(
&canvas::Path::rectangle(Point::new(content_origin.x, content_y - box_height * 0.5), Size::new(box_width, box_height)),
canvas::Stroke::default().with_color(aci_color(&self.text_color, ink)).with_width(1.0),
&canvas::Path::rectangle(
Point::new(content_origin.x, content_y - box_height * 0.5),
Size::new(box_width, box_height),
),
canvas::Stroke::default()
.with_color(aci_color(&self.text_color, ink))
.with_width(1.0),
);
}
let align = if self.text_always_left || self.text_alignment == "Left" {
@@ -550,10 +646,18 @@ impl canvas::Program<Message> for LeaderPreviewCanvas {
self.top_attachment,
self.bottom_attachment,
self.block_connection,
if self.enable_block_rotation { &self.block_rotation } else { "0" },
if self.enable_block_rotation {
&self.block_rotation
} else {
"0"
},
"°",
self.block_scale[2],
if self.annotative { t!("Annotative") } else { t!("Drawing scale") },
if self.annotative {
t!("Annotative")
} else {
t!("Drawing scale")
},
),
position: Point::new(10.0, 9.0),
color: ink.scale_alpha(0.55),
@@ -574,63 +678,230 @@ pub fn view_window<'a>(
(_, None) => text(t!("Select a style to view details.")).size(11).into(),
(0, Some(style)) => column![
input_row(t!("Description"), "", v.description, "description"),
enum_row(t!("Path type"), &[("Invisible", "None"), ("StraightLineSegments", "Straight"), ("Spline", "Spline")], format!("{:?}", style.path_type), "path_type"),
color_row(t!("Line color"), v.line_color, "line_color", v.color_open == Some("line_color")),
enum_row(
t!("Path type"),
&[
("Invisible", "None"),
("StraightLineSegments", "Straight"),
("Spline", "Spline")
],
format!("{:?}", style.path_type),
"path_type"
),
color_row(
t!("Line color"),
v.line_color,
"line_color",
v.color_open == Some("line_color")
),
row![
text(t!("Line weight")).size(11).style(muted_style).width(165),
text(t!("Line weight"))
.size(11)
.style(muted_style)
.width(165),
iced::widget::pick_list(
Some(crate::ui::properties::LwItem(style.line_weight)),
crate::ui::properties::lw_options(),
|value| value.to_string(),
)
.on_select(|item| Message::MLeaderStyleLineWeightChanged(item.0))
.text_size(11).width(220),
].spacing(8).align_y(iced::Center),
handle_row(t!("Line type"), v.lt_opts.clone(), v.line_type_name.clone(), "line_type_handle"),
handle_row(t!("Arrowhead"), v.arrow_opts.clone(), v.arrowhead_name.clone(), "arrowhead_handle"),
input_row(t!("Arrowhead size"), "0.18", v.arrowhead_size, "arrowhead_size"),
.text_size(11)
.width(220),
]
.spacing(8)
.align_y(iced::Center),
handle_row(
t!("Line type"),
v.lt_opts.clone(),
v.line_type_name.clone(),
"line_type_handle"
),
handle_row(
t!("Arrowhead"),
v.arrow_opts.clone(),
v.arrowhead_name.clone(),
"arrowhead_handle"
),
input_row(
t!("Arrowhead size"),
"0.18",
v.arrowhead_size,
"arrowhead_size"
),
input_row(t!("Break gap size"), "0.125", v.break_gap, "break_gap"),
].spacing(8).into(),
]
.spacing(8)
.into(),
(1, Some(style)) => column![
toggle(t!("Enable landing"), style.enable_landing, "enable_landing"),
toggle(t!("Enable dogleg"), style.enable_dogleg, "enable_dogleg"),
input_row(t!("Landing distance"), "8.0", v.landing_distance, "landing_distance"),
input_row(
t!("Landing distance"),
"8.0",
v.landing_distance,
"landing_distance"
),
input_row(t!("Landing gap"), "0.09", v.landing_gap, "landing_gap"),
input_row(t!("Maximum leader points"), "2", v.max_points, "max_points"),
input_row(t!("First segment angle"), "0", v.first_seg_angle, "first_seg_angle"),
input_row(t!("Second segment angle"), "0", v.second_seg_angle, "second_seg_angle"),
if style.is_annotative { readonly_row(t!("Scale factor"), t!("By annotation scale")) } else { input_row(t!("Scale factor"), "1.0", v.scale_factor, "scale_factor") },
input_row(
t!("First segment angle"),
"0",
v.first_seg_angle,
"first_seg_angle"
),
input_row(
t!("Second segment angle"),
"0",
v.second_seg_angle,
"second_seg_angle"
),
if style.is_annotative {
readonly_row(t!("Scale factor"), t!("By annotation scale"))
} else {
input_row(t!("Scale factor"), "1.0", v.scale_factor, "scale_factor")
},
input_row(t!("Alignment spacing"), "4.0", v.align_space, "align_space"),
enum_row(t!("Leader draw order"), &LEADER_DRAW_ORDERS, format!("{:?}", style.leader_draw_order), "leader_draw_order"),
enum_row(t!("Multileader draw order"), &MULTILEADER_DRAW_ORDERS, format!("{:?}", style.multileader_draw_order), "multileader_draw_order"),
enum_row(
t!("Leader draw order"),
&LEADER_DRAW_ORDERS,
format!("{:?}", style.leader_draw_order),
"leader_draw_order"
),
enum_row(
t!("Multileader draw order"),
&MULTILEADER_DRAW_ORDERS,
format!("{:?}", style.multileader_draw_order),
"multileader_draw_order"
),
toggle(t!("Annotative"), style.is_annotative, "annotative"),
].spacing(8).into(),
]
.spacing(8)
.into(),
(2, Some(style)) => column![
enum_row(t!("Content type"), &[("None", "None"), ("Block", "Block"), ("MText", "Text"), ("Tolerance", "Tolerance")], format!("{:?}", style.content_type), "content_type"),
enum_row(
t!("Content type"),
&[
("None", "None"),
("Block", "Block"),
("MText", "Text"),
("Tolerance", "Tolerance")
],
format!("{:?}", style.content_type),
"content_type"
),
input_row(t!("Default text"), "", v.default_text, "default_text"),
handle_row(t!("Text style"), v.textstyle_opts.clone(), v.text_style_name.clone(), "text_style_handle"),
handle_row(
t!("Text style"),
v.textstyle_opts.clone(),
v.text_style_name.clone(),
"text_style_handle"
),
input_row(t!("Text height"), "0.18", v.text_height, "text_height"),
color_row(t!("Text color"), v.text_color, "text_color", v.color_open == Some("text_color")),
enum_row(t!("Text angle"), &[("ParallelToLastLeaderLine", "Parallel to last segment"), ("Horizontal", "Horizontal"), ("Optimized", "Optimized")], format!("{:?}", style.text_angle_type), "text_angle_type"),
enum_row(t!("Text alignment"), &[("Left", "Left"), ("Center", "Center"), ("Right", "Right")], format!("{:?}", style.text_alignment), "text_alignment"),
enum_row(t!("Attachment direction"), &[("Horizontal", "Horizontal"), ("Vertical", "Vertical")], format!("{:?}", style.text_attachment_direction), "text_attachment_direction"),
enum_row(t!("Left attachment"), &ATTACHMENTS, format!("{:?}", style.text_left_attachment), "text_left_attachment"),
enum_row(t!("Right attachment"), &ATTACHMENTS, format!("{:?}", style.text_right_attachment), "text_right_attachment"),
enum_row(t!("Top attachment"), &ATTACHMENTS, format!("{:?}", style.text_top_attachment), "text_top_attachment"),
enum_row(t!("Bottom attachment"), &ATTACHMENTS, format!("{:?}", style.text_bottom_attachment), "text_bottom_attachment"),
row![toggle(t!("Text frame"), style.text_frame, "text_frame"), toggle(t!("Always left align"), style.text_always_left, "text_always_left")].spacing(18),
].spacing(8).into(),
color_row(
t!("Text color"),
v.text_color,
"text_color",
v.color_open == Some("text_color")
),
enum_row(
t!("Text angle"),
&[
("ParallelToLastLeaderLine", "Parallel to last segment"),
("Horizontal", "Horizontal"),
("Optimized", "Optimized")
],
format!("{:?}", style.text_angle_type),
"text_angle_type"
),
enum_row(
t!("Text alignment"),
&[("Left", "Left"), ("Center", "Center"), ("Right", "Right")],
format!("{:?}", style.text_alignment),
"text_alignment"
),
enum_row(
t!("Attachment direction"),
&[("Horizontal", "Horizontal"), ("Vertical", "Vertical")],
format!("{:?}", style.text_attachment_direction),
"text_attachment_direction"
),
enum_row(
t!("Left attachment"),
&ATTACHMENTS,
format!("{:?}", style.text_left_attachment),
"text_left_attachment"
),
enum_row(
t!("Right attachment"),
&ATTACHMENTS,
format!("{:?}", style.text_right_attachment),
"text_right_attachment"
),
enum_row(
t!("Top attachment"),
&ATTACHMENTS,
format!("{:?}", style.text_top_attachment),
"text_top_attachment"
),
enum_row(
t!("Bottom attachment"),
&ATTACHMENTS,
format!("{:?}", style.text_bottom_attachment),
"text_bottom_attachment"
),
row![
toggle(t!("Text frame"), style.text_frame, "text_frame"),
toggle(
t!("Always left align"),
style.text_always_left,
"text_always_left"
)
]
.spacing(18),
]
.spacing(8)
.into(),
(_, Some(style)) => column![
handle_row(t!("Block"), v.block_opts.clone(), v.block_content_name.clone(), "block_content_handle"),
color_row(t!("Block color"), v.block_color, "block_color", v.color_open == Some("block_color")),
enum_row(t!("Block connection"), &BLOCK_CONNECTIONS, format!("{:?}", style.block_content_connection), "block_content_connection"),
input_row(t!("Block rotation"), "0", v.block_rotation, "block_rotation"),
handle_row(
t!("Block"),
v.block_opts.clone(),
v.block_content_name.clone(),
"block_content_handle"
),
color_row(
t!("Block color"),
v.block_color,
"block_color",
v.color_open == Some("block_color")
),
enum_row(
t!("Block connection"),
&BLOCK_CONNECTIONS,
format!("{:?}", style.block_content_connection),
"block_content_connection"
),
input_row(
t!("Block rotation"),
"0",
v.block_rotation,
"block_rotation"
),
input_row(t!("Block scale X"), "1.0", v.block_scale_x, "block_scale_x"),
input_row(t!("Block scale Y"), "1.0", v.block_scale_y, "block_scale_y"),
input_row(t!("Block scale Z"), "1.0", v.block_scale_z, "block_scale_z"),
toggle(t!("Enable block scale"), style.enable_block_scale, "enable_block_scale"),
toggle(t!("Enable block rotation"), style.enable_block_rotation, "enable_block_rotation"),
].spacing(8).into(),
toggle(
t!("Enable block scale"),
style.enable_block_scale,
"enable_block_scale"
),
toggle(
t!("Enable block rotation"),
style.enable_block_rotation,
"enable_block_rotation"
),
]
.spacing(8)
.into(),
};
let preview: Element<'a, Message> = if let Some(style) = style {
canvas(LeaderPreviewCanvas {
@@ -660,23 +931,45 @@ pub fn view_window<'a>(
text_angle: format!("{:?}", style.text_angle_type),
text_alignment: format!("{:?}", style.text_alignment),
attachment_direction: format!("{:?}", style.text_attachment_direction),
left_attachment: choice_label(&ATTACHMENTS, format!("{:?}", style.text_left_attachment)),
left_attachment: choice_label(
&ATTACHMENTS,
format!("{:?}", style.text_left_attachment),
),
left_attachment_code: format!("{:?}", style.text_left_attachment),
right_attachment: choice_label(&ATTACHMENTS, format!("{:?}", style.text_right_attachment)),
right_attachment: choice_label(
&ATTACHMENTS,
format!("{:?}", style.text_right_attachment),
),
top_attachment: choice_label(&ATTACHMENTS, format!("{:?}", style.text_top_attachment)),
bottom_attachment: choice_label(&ATTACHMENTS, format!("{:?}", style.text_bottom_attachment)),
bottom_attachment: choice_label(
&ATTACHMENTS,
format!("{:?}", style.text_bottom_attachment),
),
text_frame: style.text_frame,
text_always_left: style.text_always_left,
block_name: handle_label(&v.block_content_name),
block_color: v.block_color.to_string(),
block_connection: choice_label(&BLOCK_CONNECTIONS, format!("{:?}", style.block_content_connection)),
block_connection: choice_label(
&BLOCK_CONNECTIONS,
format!("{:?}", style.block_content_connection),
),
block_connection_code: format!("{:?}", style.block_content_connection),
block_rotation: v.block_rotation.to_string(),
block_scale: [v.block_scale_x.to_string(), v.block_scale_y.to_string(), v.block_scale_z.to_string()],
block_scale: [
v.block_scale_x.to_string(),
v.block_scale_y.to_string(),
v.block_scale_z.to_string(),
],
enable_block_scale: style.enable_block_scale,
enable_block_rotation: style.enable_block_rotation,
leader_draw_order: choice_label(&LEADER_DRAW_ORDERS, format!("{:?}", style.leader_draw_order)),
multileader_draw_order: choice_label(&MULTILEADER_DRAW_ORDERS, format!("{:?}", style.multileader_draw_order)),
leader_draw_order: choice_label(
&LEADER_DRAW_ORDERS,
format!("{:?}", style.leader_draw_order),
),
multileader_draw_order: choice_label(
&MULTILEADER_DRAW_ORDERS,
format!("{:?}", style.multileader_draw_order),
),
description: v.description.to_string(),
})
.width(Length::Fill)
@@ -709,15 +1002,20 @@ pub fn view_window<'a>(
summary,
on_select: Message::MLeaderStyleDialogCompare,
}),
tabs: [t!("Leader Format"), t!("Leader Structure"), t!("Content"), t!("Block Content")]
.into_iter()
.enumerate()
.map(|(tab, label)| crate::ui::style::style_manager::EditorTab {
label,
active: v.tab == tab as u8,
on_press: Message::MLeaderStyleDialogTab(tab as u8),
})
.collect(),
tabs: [
t!("Leader Format"),
t!("Leader Structure"),
t!("Content"),
t!("Block Content"),
]
.into_iter()
.enumerate()
.map(|(tab, label)| crate::ui::style::style_manager::EditorTab {
label,
active: v.tab == tab as u8,
on_press: Message::MLeaderStyleDialogTab(tab as u8),
})
.collect(),
content,
},
);
+108 -35
View File
@@ -2,9 +2,9 @@
use crate::app::Message;
use crate::t;
use crate::ui::style::common::muted_style;
use iced::widget::{button, canvas, checkbox, column, container, row, text, text_input};
use iced::{mouse, Color, Element, Length, Point, Rectangle, Theme};
use crate::ui::style::common::muted_style;
use std::borrow::Cow;
pub struct MlStyleView<'a> {
@@ -100,7 +100,10 @@ fn draw_arc(frame: &mut canvas::Frame, center: Point, radius: f32, start_side: b
} else {
-std::f32::consts::FRAC_PI_2 + t * std::f32::consts::PI
};
let point = Point::new(center.x + radius * angle.cos(), center.y + radius * angle.sin());
let point = Point::new(
center.x + radius * angle.cos(),
center.y + radius * angle.sin(),
);
if step == 0 {
builder.move_to(point);
} else {
@@ -108,7 +111,10 @@ fn draw_arc(frame: &mut canvas::Frame, center: Point, radius: f32, start_side: b
}
}
});
frame.stroke(&path, canvas::Stroke::default().with_color(color).with_width(1.1));
frame.stroke(
&path,
canvas::Stroke::default().with_color(color).with_width(1.1),
);
}
impl canvas::Program<Message> for MLinePreviewCanvas {
@@ -149,7 +155,10 @@ impl canvas::Program<Message> for MLinePreviewCanvas {
builder.line_to(lower[0]);
builder.close();
});
frame.fill(&fill, aci_color(&self.fill_color, theme.palette().background.weak.color));
frame.fill(
&fill,
aci_color(&self.fill_color, theme.palette().background.weak.color),
);
}
}
for (offset, color, linetype) in &parsed {
@@ -161,7 +170,10 @@ impl canvas::Program<Message> for MLinePreviewCanvas {
style: canvas::Style::Solid(aci_color(color, ink)),
width: 1.4,
line_dash: if dashed {
canvas::LineDash { segments: &[6.0, 4.0], offset: 0 }
canvas::LineDash {
segments: &[6.0, 4.0],
offset: 0,
}
} else {
canvas::LineDash::default()
},
@@ -183,24 +195,49 @@ impl canvas::Program<Message> for MLinePreviewCanvas {
let start_bottom = bottom_points[0];
let end_top = top_points[2];
let end_bottom = bottom_points[2];
let start_angle = self.start_angle.trim().parse::<f32>().unwrap_or(90.0).to_radians();
let end_angle = self.end_angle.trim().parse::<f32>().unwrap_or(90.0).to_radians();
let start_angle = self
.start_angle
.trim()
.parse::<f32>()
.unwrap_or(90.0)
.to_radians();
let end_angle = self
.end_angle
.trim()
.parse::<f32>()
.unwrap_or(90.0)
.to_radians();
let cap = |a: Point, b: Point, angle: f32| {
let middle = Point::new((a.x + b.x) * 0.5, (a.y + b.y) * 0.5);
let half = ((a.y - b.y).abs() * 0.5).max(2.0);
let direction = Point::new(angle.cos() * half, angle.sin() * half);
(Point::new(middle.x - direction.x, middle.y - direction.y), Point::new(middle.x + direction.x, middle.y + direction.y))
(
Point::new(middle.x - direction.x, middle.y - direction.y),
Point::new(middle.x + direction.x, middle.y + direction.y),
)
};
if self.start_square {
let (a, b) = cap(start_top, start_bottom, start_angle);
frame.stroke(&canvas::Path::line(a, b), canvas::Stroke::default().with_color(ink));
frame.stroke(
&canvas::Path::line(a, b),
canvas::Stroke::default().with_color(ink),
);
}
if self.end_square {
let (a, b) = cap(end_top, end_bottom, end_angle);
frame.stroke(&canvas::Path::line(a, b), canvas::Stroke::default().with_color(ink));
frame.stroke(
&canvas::Path::line(a, b),
canvas::Stroke::default().with_color(ink),
);
}
let start_center = Point::new((start_top.x + start_bottom.x) * 0.5, (start_top.y + start_bottom.y) * 0.5);
let end_center = Point::new((end_top.x + end_bottom.x) * 0.5, (end_top.y + end_bottom.y) * 0.5);
let start_center = Point::new(
(start_top.x + start_bottom.x) * 0.5,
(start_top.y + start_bottom.y) * 0.5,
);
let end_center = Point::new(
(end_top.x + end_bottom.x) * 0.5,
(end_top.y + end_bottom.y) * 0.5,
);
let outer_radius = ((start_top.y - start_bottom.y).abs() * 0.5).max(3.0);
if self.start_round {
draw_arc(&mut frame, start_center, outer_radius, true, ink);
@@ -217,11 +254,19 @@ impl canvas::Program<Message> for MLinePreviewCanvas {
if self.joints {
let joint_top = top_points[1];
let joint_bottom = bottom_points[1];
frame.stroke(&canvas::Path::line(joint_top, joint_bottom), canvas::Stroke::default().with_color(ink).with_width(1.0));
frame.stroke(
&canvas::Path::line(joint_top, joint_bottom),
canvas::Stroke::default().with_color(ink).with_width(1.0),
);
}
}
frame.fill_text(canvas::Text {
content: format!("{} · {} {}", self.description, t!("Elements"), self.elements.len()),
content: format!(
"{} · {} {}",
self.description,
t!("Elements"),
self.elements.len()
),
position: Point::new(10.0, bounds.height - 9.0),
color: ink.scale_alpha(0.62),
size: iced::Pixels(10.0),
@@ -240,29 +285,44 @@ pub fn view_window<'a>(
let content: Element<'a, Message> = match (v.tab, style) {
(_, None) => text(t!("Select a style to view details.")).size(11).into(),
(0, Some(_)) => {
let mut items = column![
row![
text(t!("Offset")).size(10).style(muted_style).width(110),
text(t!("Color")).size(10).style(muted_style).width(100),
text(t!("Line type")).size(10).style(muted_style).width(170),
button(text(t!("Add")).size(10)).on_press(Message::MlStyleElementAdd).padding([4, 12]),
]
.spacing(6)
.align_y(iced::Center),
let mut items = column![row![
text(t!("Offset")).size(10).style(muted_style).width(110),
text(t!("Color")).size(10).style(muted_style).width(100),
text(t!("Line type")).size(10).style(muted_style).width(170),
button(text(t!("Add")).size(10))
.on_press(Message::MlStyleElementAdd)
.padding([4, 12]),
]
.spacing(6)
.align_y(iced::Center),]
.spacing(6);
for (index, element) in v.elements.iter().enumerate() {
items = items.push(
row![
text_input("0.0", &element[0])
.on_input(move |value| Message::MlStyleElementEdit { index, field: "offset", value })
.size(11).width(110),
.on_input(move |value| Message::MlStyleElementEdit {
index,
field: "offset",
value
})
.size(11)
.width(110),
text_input("256", &element[1])
.on_input(move |value| Message::MlStyleElementEdit { index, field: "color", value })
.size(11).width(100),
.on_input(move |value| Message::MlStyleElementEdit {
index,
field: "color",
value
})
.size(11)
.width(100),
text_input("ByLayer", &element[2])
.on_input(move |value| Message::MlStyleElementEdit { index, field: "linetype", value })
.size(11).width(170),
.on_input(move |value| Message::MlStyleElementEdit {
index,
field: "linetype",
value
})
.size(11)
.width(170),
button(text(t!("Delete")).size(10))
.on_press(Message::MlStyleElementDelete(index))
.padding([4, 10]),
@@ -279,23 +339,36 @@ pub fn view_window<'a>(
row![
toggle(t!("Fill enabled"), style.flags.fill_on, "fill"),
toggle(t!("Display joints"), style.flags.display_joints, "joints"),
].spacing(18),
]
.spacing(18),
input_row(t!("Fill color"), "256", v.fill_color, "fill_color"),
text(t!("Start caps")).size(11).style(primary_style),
row![
toggle(t!("Line"), style.flags.start_square_cap, "start_square"),
toggle(t!("Inner arcs"), style.flags.start_inner_arcs_cap, "start_inner"),
toggle(
t!("Inner arcs"),
style.flags.start_inner_arcs_cap,
"start_inner"
),
toggle(t!("Outer arc"), style.flags.start_round_cap, "start_round"),
].spacing(18),
]
.spacing(18),
input_row(t!("Start angle"), "90", v.start_angle, "start_angle"),
text(t!("End caps")).size(11).style(primary_style),
row![
toggle(t!("Line"), style.flags.end_square_cap, "end_square"),
toggle(t!("Inner arcs"), style.flags.end_inner_arcs_cap, "end_inner"),
toggle(
t!("Inner arcs"),
style.flags.end_inner_arcs_cap,
"end_inner"
),
toggle(t!("Outer arc"), style.flags.end_round_cap, "end_round"),
].spacing(18),
]
.spacing(18),
input_row(t!("End angle"), "90", v.end_angle, "end_angle"),
].spacing(9).into(),
]
.spacing(9)
.into(),
};
let preview: Element<'a, Message> = if let Some(style) = style {
canvas(MLinePreviewCanvas {
+13 -10
View File
@@ -1,18 +1,18 @@
pub mod anno_object_scale;
pub mod common;
pub mod dimstyle;
pub mod form;
pub mod fusion_theme;
pub mod mleaderstyle;
pub mod mlstyle;
pub mod plotstyle;
pub mod textstyle;
pub mod tablestyle;
pub mod point_style;
pub mod style_list;
pub mod scale_manager;
pub mod anno_object_scale;
pub mod style_manager;
pub mod common;
pub mod row_button;
pub mod form;
pub mod fusion_theme;
pub mod scale_manager;
pub mod style_list;
pub mod style_manager;
pub mod tablestyle;
pub mod textstyle;
#[cfg(test)]
mod common_tests {
@@ -44,6 +44,9 @@ mod common_tests {
// It passes only after we have proven the divergence; before that it would be
// meaningless. We keep it as documentation.
let divergent = true;
assert!(divergent, "btn_s in plotstyle.rs:41 and style_manager.rs:299 differ — do not dedup");
assert!(
divergent,
"btn_s in plotstyle.rs:41 and style_manager.rs:299 differ — do not dedup"
);
}
}
+66 -145
View File
@@ -1,11 +1,11 @@
//! Plot Style Table Editor window — fills the entire OS window.
use crate::app::Message;
use iced::widget::{button, column, container, row, scrollable, text, text_input, Space};
use iced::{Background, Border, Element, Theme};
use crate::t;
use crate::ui::style::common::muted_style;
use crate::ui::style::form::{hdivider, vsep};
use crate::t;
use iced::widget::{button, column, container, row, scrollable, text, text_input, Space};
use iced::{Background, Border, Element, Theme};
use std::borrow::Cow;
use std::fmt;
@@ -45,21 +45,19 @@ fn btn_s(accent: bool) -> impl Fn(&Theme, button::Status) -> button::Style {
let palette = theme.palette();
let pair = match (accent, st) {
(true, button::Status::Hovered | button::Status::Pressed) => palette.primary.strong,
(false, button::Status::Hovered | button::Status::Pressed) => {
palette.background.strong
}
(false, button::Status::Hovered | button::Status::Pressed) => palette.background.strong,
(true, _) => palette.primary.base,
_ => palette.background.weak,
};
button::Style {
background: Some(Background::Color(pair.color)),
text_color: pair.text,
border: Border {
color: palette.background.neutral.color,
width: 1.0,
radius: 4.0.into(),
},
..Default::default()
background: Some(Background::Color(pair.color)),
text_color: pair.text,
border: Border {
color: palette.background.neutral.color,
width: 1.0,
radius: 4.0.into(),
},
..Default::default()
}
}
}
@@ -159,9 +157,7 @@ pub fn view_window<'a>(
.align_y(iced::Center),
)
.style(|theme: &Theme| container::Style {
background: Some(Background::Color(
theme.palette().background.weak.color
)),
background: Some(Background::Color(theme.palette().background.weak.color)),
..Default::default()
})
.width(sizing.width)
@@ -171,19 +167,15 @@ pub fn view_window<'a>(
let aci_items: Vec<Element<'_, Message>> = (1u8..=255)
.map(|aci| {
let is_sel = aci == selected_aci;
let usage_count = layer_usage
.get(aci as usize)
.map(Vec::len)
.unwrap_or(0);
let usage_count = layer_usage.get(aci as usize).map(Vec::len).unwrap_or(0);
let usage_label = if show_layer_usage && usage_count > 0 {
format!("● {usage_count}")
} else {
String::new()
};
let (aci_color, _) = crate::ui::properties::acad_color_display(
codec::types::Color::Index(aci),
);
let (aci_color, _) =
crate::ui::properties::acad_color_display(codec::types::Color::Index(aci));
let has_override = table
.and_then(|t| t.aci_entries.get(aci as usize))
.map(|e| e.color.is_some() || e.lineweight != 255 || e.screening != 100)
@@ -212,12 +204,10 @@ pub fn view_window<'a>(
button(
row![
crate::ui::color_select::swatch(aci_color),
text(label)
.size(10)
.font(iced::Font::MONOSPACE)
.width(iced::Length::Fill),
text(usage_label)
.size(10)
.font(iced::Font::MONOSPACE)
@@ -227,26 +217,24 @@ pub fn view_window<'a>(
.align_y(iced::Center),
)
.on_press(Message::PlotStylePanelSelectAci(aci))
.style(move |theme: &Theme, st| {
let palette = theme.palette();
let pair = match (is_sel, st) {
(true, _) => Some(palette.primary.strong),
(false, button::Status::Hovered | button::Status::Pressed) => {
Some(palette.background.strong)
}
_ => None,
};
button::Style {
background: pair.map(|p| Background::Color(p.color)),
text_color: pair
.map(|p| p.text)
.unwrap_or(palette.background.base.text),
..Default::default()
.style(move |theme: &Theme, st| {
let palette = theme.palette();
let pair = match (is_sel, st) {
(true, _) => Some(palette.primary.strong),
(false, button::Status::Hovered | button::Status::Pressed) => {
Some(palette.background.strong)
}
})
.padding([2, 8])
.width(sizing.width)
.into()
_ => None,
};
button::Style {
background: pair.map(|p| Background::Color(p.color)),
text_color: pair.map(|p| p.text).unwrap_or(palette.background.base.text),
..Default::default()
}
})
.padding([2, 8])
.width(sizing.width)
.into()
})
.collect();
@@ -257,24 +245,20 @@ pub fn view_window<'a>(
.size(10)
.style(muted_style)
.width(iced::Length::Fill),
text(t!("Layers"))
.size(10)
.style(muted_style)
.width(42),
text(t!("Layers")).size(10).style(muted_style).width(42),
]
.align_y(iced::Center),
container(scrollable(column(aci_items).spacing(1)).height(sizing.height))
.style(|theme: &Theme| {
let palette = theme.palette();
container::Style {
background: Some(Background::Color(palette.background.weak.color)),
border: Border {
color: palette.background.neutral.color,
width: 1.0,
radius: 3.0.into()
},
..Default::default()
background: Some(Background::Color(palette.background.weak.color)),
border: Border {
color: palette.background.neutral.color,
width: 1.0,
radius: 3.0.into(),
},
..Default::default()
}
})
.width(sizing.width)
@@ -327,10 +311,7 @@ pub fn view_window<'a>(
let lbl = |s: Cow<'static, str>| text(s).size(11).style(muted_style);
let lw_items = plot_lineweight_options();
let current_lw_index = lw_buf
.trim()
.parse::<u8>()
.unwrap_or(255);
let current_lw_index = lw_buf.trim().parse::<u8>().unwrap_or(255);
let current_lw = lw_items
.iter()
@@ -341,10 +322,7 @@ pub fn view_window<'a>(
let edit_panel = container(
column![
row![
text(t!("ACI:"))
.size(11)
.style(muted_style)
.width(100),
text(t!("ACI:")).size(11).style(muted_style).width(100),
text(format!("{selected_aci}")).size(11),
]
.spacing(8)
@@ -352,14 +330,9 @@ pub fn view_window<'a>(
if show_layer_usage {
container(
column![
text(format!(
"{}: {}",
t!("Layers"),
selected_layers.len()
))
.size(10)
.style(muted_style),
text(format!("{}: {}", t!("Layers"), selected_layers.len()))
.size(10)
.style(muted_style),
text(selected_layers_text)
.size(10)
.width(iced::Length::Fill),
@@ -371,7 +344,6 @@ pub fn view_window<'a>(
} else {
container(Space::new().height(0))
},
// ── Plot color ───────────────────────────────────────────────────
lbl(t!("Plot color:")),
{
@@ -385,11 +357,10 @@ pub fn view_window<'a>(
b: (rgb & 0xFF) as u8,
});
let display_color = selected_color
.unwrap_or(codec::types::Color::Index(selected_aci));
let display_color =
selected_color.unwrap_or(codec::types::Color::Index(selected_aci));
let (swatch_color, _) =
crate::ui::properties::acad_color_display(display_color);
let (swatch_color, _) = crate::ui::properties::acad_color_display(display_color);
let display_text = if color_buf.is_empty() {
t!("Use object color").into_owned()
@@ -408,7 +379,6 @@ pub fn view_window<'a>(
)
.padding([4, 8])
.width(iced::Length::Fill),
button(text(t!("Choose color…")).size(11))
.on_press(Message::OpenColorWindow(
crate::app::ColorPickTarget::PlotStyle,
@@ -416,7 +386,6 @@ pub fn view_window<'a>(
))
.style(btn_s(false))
.padding([4, 10]),
button(text(t!("Reset")).size(11))
.on_press(Message::PlotStylePanelColorBuf(String::new()))
.style(btn_s(false))
@@ -425,21 +394,13 @@ pub fn view_window<'a>(
.spacing(6)
.align_y(iced::Center)
},
// ── Lineweight ───────────────────────────────────────────────────
lbl(t!("Lineweight:")),
iced::widget::pick_list(
Some(current_lw),
lw_items,
|item| item.to_string(),
)
.on_select(|item: PlotLineweightItem| {
Message::PlotStylePanelLwSet(item.index)
})
iced::widget::pick_list(Some(current_lw), lw_items, |item| item.to_string(),)
.on_select(|item: PlotLineweightItem| { Message::PlotStylePanelLwSet(item.index) })
.text_size(11)
.padding([3, 5])
.width(iced::Length::Fill),
// ── Screening ────────────────────────────────────────────────────
lbl(t!("Screening (0-100):")),
text_input("100", screen_buf)
@@ -447,47 +408,21 @@ pub fn view_window<'a>(
.style(field_style)
.size(11)
.padding([4, 8]),
Space::new().height(8),
// ── Current values ───────────────────────────────────────────────
text(t!("Current values:"))
.size(10)
.style(muted_style),
text(t!(
" Color: %{cur_color}",
cur_color = cur_color
))
.size(10),
text(t!(
" Lineweight: %{cur_lw}",
cur_lw = cur_lw
))
.size(10),
text(t!(
" Screening: %{cur_scr}",
cur_scr = cur_scr
))
.size(10),
text(t!("Current values:")).size(10).style(muted_style),
text(t!(" Color: %{cur_color}", cur_color = cur_color)).size(10),
text(t!(" Lineweight: %{cur_lw}", cur_lw = cur_lw)).size(10),
text(t!(" Screening: %{cur_scr}", cur_scr = cur_scr)).size(10),
Space::new().height(12),
hdivider(iced::Length::Fill),
Space::new().height(8),
if show_layer_usage {
container(
column![
row![
text(crate::tf!("Layers using ACI {selected_aci}"))
.size(11),
text(crate::tf!("Layers using ACI {selected_aci}")).size(11),
Space::new().width(iced::Length::Fill),
text(format!(
"{} {}",
selected_layers.len(),
@@ -501,23 +436,16 @@ pub fn view_window<'a>(
.style(muted_style),
]
.align_y(iced::Center),
if selected_layers.is_empty() {
column![
text(t!("No layers use this ACI in the current drawing."))
.size(10)
.style(muted_style)
]
column![text(t!("No layers use this ACI in the current drawing."))
.size(10)
.style(muted_style)]
} else {
column(
selected_layers
.iter()
.map(|name| {
text(format!("• {name}"))
.size(10)
.into()
})
.collect::<Vec<Element<'_, Message>>>()
.map(|name| text(format!("• {name}")).size(10).into())
.collect::<Vec<Element<'_, Message>>>(),
)
.spacing(4)
},
@@ -529,9 +457,7 @@ pub fn view_window<'a>(
} else {
container(Space::new().height(0))
},
Space::new().height(sizing.height),
]
.spacing(8)
.height(sizing.height),
@@ -544,9 +470,7 @@ pub fn view_window<'a>(
container(column![toolbar, hdivider(sizing.width), body].spacing(0))
.style(|theme: &Theme| container::Style {
background: Some(Background::Color(
theme.palette().background.base.color
)),
background: Some(Background::Color(theme.palette().background.base.color)),
..Default::default()
})
.width(sizing.width)
@@ -558,11 +482,7 @@ pub fn view_window<'a>(
mod layer_usage_tests {
use super::*;
fn indexed_layer(
doc: &mut codec::CadDocument,
name: &str,
aci: u8,
) -> codec::tables::Layer {
fn indexed_layer(doc: &mut codec::CadDocument, name: &str, aci: u8) -> codec::tables::Layer {
let mut layer = codec::tables::Layer::new(name);
layer.handle = doc.allocate_handle();
layer.color = codec::types::Color::Index(aci);
@@ -602,9 +522,10 @@ mod layer_usage_tests {
let usage = build_layer_usage(&doc);
assert!(
usage.iter().all(|bucket| !bucket.iter().any(|n| n == "TRUECOLOR")),
usage
.iter()
.all(|bucket| !bucket.iter().any(|n| n == "TRUECOLOR")),
"truecolor layer must not appear in any ACI bucket"
);
}
}
+23 -9
View File
@@ -6,11 +6,11 @@
//! does the same without the dialog.
use crate::app::Message;
use crate::t;
use crate::ui::style::common::muted_style;
use crate::ui::style::form::{dialog_button, form_radio};
use iced::widget::{button, canvas, column, container, row, text, text_input, Space};
use iced::{mouse, Background, Border, Element, Length, Point, Rectangle, Size, Theme};
use crate::t;
use std::borrow::Cow;
const CELL_PX: f32 = 44.0;
@@ -52,8 +52,14 @@ impl canvas::Program<Message> for GlyphCanvas {
0 => frame.fill(&canvas::Path::circle(Point::new(cx, cy), 2.4), glyph),
1 => {}
2 => {
frame.stroke(&line(Point::new(cx - r, cy), Point::new(cx + r, cy)), stroke.clone());
frame.stroke(&line(Point::new(cx, cy - r), Point::new(cx, cy + r)), stroke.clone());
frame.stroke(
&line(Point::new(cx - r, cy), Point::new(cx + r, cy)),
stroke.clone(),
);
frame.stroke(
&line(Point::new(cx, cy - r), Point::new(cx, cy + r)),
stroke.clone(),
);
}
3 => {
frame.stroke(
@@ -65,14 +71,18 @@ impl canvas::Program<Message> for GlyphCanvas {
stroke.clone(),
);
}
4 => frame.stroke(&line(Point::new(cx, cy), Point::new(cx, cy - r)), stroke.clone()),
4 => frame.stroke(
&line(Point::new(cx, cy), Point::new(cx, cy - r)),
stroke.clone(),
),
_ => {}
}
if self.mode & 32 != 0 {
frame.stroke(&canvas::Path::circle(Point::new(cx, cy), r), stroke.clone());
}
if self.mode & 64 != 0 {
let sq = canvas::Path::rectangle(Point::new(cx - r, cy - r), Size::new(2.0 * r, 2.0 * r));
let sq =
canvas::Path::rectangle(Point::new(cx - r, cy - r), Size::new(2.0 * r, 2.0 * r));
frame.stroke(&sq, stroke.clone());
}
vec![frame.into_geometry()]
@@ -158,7 +168,13 @@ pub fn view_window<'a>(
.size(13)
.width(110),
Space::new().width(6),
text(if relative { Cow::Borrowed("%") } else { t!("units") }).size(12).style(muted_style),
text(if relative {
Cow::Borrowed("%")
} else {
t!("units")
})
.size(12)
.style(muted_style),
]
.align_y(iced::Center);
@@ -198,9 +214,7 @@ pub fn view_window<'a>(
.height(height),
)
.style(|theme: &Theme| container::Style {
background: Some(Background::Color(
theme.palette().background.base.color
)),
background: Some(Background::Color(theme.palette().background.base.color)),
..Default::default()
})
.width(width)
+1 -4
View File
@@ -40,10 +40,7 @@ pub(crate) fn cell_button_style(
/// Column-header button style (layers panel).
pub(crate) fn header_button_style(theme: &Theme, status: button::Status) -> button::Style {
let palette = theme.palette();
let highlighted = matches!(
status,
button::Status::Hovered | button::Status::Pressed
);
let highlighted = matches!(status, button::Status::Hovered | button::Status::Pressed);
let pair = if highlighted {
palette.background.strong
} else {
+70 -76
View File
@@ -6,14 +6,10 @@
//! messages instead of the StyleKind machinery.
use crate::app::Message;
use crate::ui::style::style_manager::{
hdivider, muted_text_style, tb_button, vsep,
};
use iced::widget::{
column, container, mouse_area, row, scrollable, text, text_input, Space,
};
use iced::{Background, Border, Element, Theme};
use crate::t;
use crate::ui::style::style_manager::{hdivider, muted_text_style, tb_button, vsep};
use iced::widget::{column, container, mouse_area, row, scrollable, text, text_input, Space};
use iced::{Background, Border, Element, Theme};
use std::borrow::Cow;
/// Inline-rename text-input id, so the rename-start handler can focus it.
@@ -67,57 +63,55 @@ pub fn view_window<'a, 'b>(
.align_y(iced::Center),
)
.style(|theme: &Theme| container::Style {
background: Some(Background::Color(
theme.palette().background.weak.color
)),
background: Some(Background::Color(theme.palette().background.weak.color)),
..Default::default()
})
.width(sizing.width)
.padding([5, 8]);
// ── Left: scale list ──────────────────────────────────────────────────
let rows: Vec<Element<'_, Message>> = scales
.iter()
.map(|(name, ratio)| {
// The row being renamed shows an inline text field; a single click
// selects, a double click starts renaming.
if rename_active == Some(name.as_str()) {
return text_input("", rename_buf)
.id(rename_input_id())
.on_input(Message::ScaleRenameEdit)
.on_submit(Message::ScaleRenameCommit)
.size(11)
.padding([4, 8])
.width(sizing.width)
.into();
}
let is_sel = name.as_str() == selected;
let is_cur = name.eq_ignore_ascii_case(current);
let check = crate::ui::icons::themed_check_cell(is_cur);
let label = row![
check,
text(name.clone()).size(11).width(sizing.width),
text(ratio.clone()).size(10).style(muted_text_style),
]
.spacing(4)
.align_y(iced::Center);
let cell = container(label)
.padding([4, 8])
.width(sizing.width)
.style(move |theme: &Theme| {
let pair = theme.palette().primary.strong;
container::Style {
background: is_sel.then_some(Background::Color(pair.color)),
text_color: is_sel.then_some(pair.text),
..Default::default()
}
});
mouse_area(cell)
.on_press(Message::ScaleManagerSelect(name.clone()))
.on_double_click(Message::ScaleRenameStart(name.clone()))
.into()
})
.collect();
let rows: Vec<Element<'_, Message>> =
scales
.iter()
.map(|(name, ratio)| {
// The row being renamed shows an inline text field; a single click
// selects, a double click starts renaming.
if rename_active == Some(name.as_str()) {
return text_input("", rename_buf)
.id(rename_input_id())
.on_input(Message::ScaleRenameEdit)
.on_submit(Message::ScaleRenameCommit)
.size(11)
.padding([4, 8])
.width(sizing.width)
.into();
}
let is_sel = name.as_str() == selected;
let is_cur = name.eq_ignore_ascii_case(current);
let check = crate::ui::icons::themed_check_cell(is_cur);
let label = row![
check,
text(name.clone()).size(11).width(sizing.width),
text(ratio.clone()).size(10).style(muted_text_style),
]
.spacing(4)
.align_y(iced::Center);
let cell = container(label).padding([4, 8]).width(sizing.width).style(
move |theme: &Theme| {
let pair = theme.palette().primary.strong;
container::Style {
background: is_sel.then_some(Background::Color(pair.color)),
text_color: is_sel.then_some(pair.text),
..Default::default()
}
},
);
mouse_area(cell)
.on_press(Message::ScaleManagerSelect(name.clone()))
.on_double_click(Message::ScaleRenameStart(name.clone()))
.into()
})
.collect();
let list_panel = container(
column![
@@ -126,13 +120,13 @@ pub fn view_window<'a, 'b>(
.style(|theme: &Theme| {
let palette = theme.palette();
container::Style {
background: Some(Background::Color(palette.background.weak.color)),
border: Border {
color: palette.background.neutral.color,
width: 1.0,
radius: 3.0.into()
},
..Default::default()
background: Some(Background::Color(palette.background.weak.color)),
border: Border {
color: palette.background.neutral.color,
width: 1.0,
radius: 3.0.into(),
},
..Default::default()
}
})
.width(sizing.width)
@@ -152,20 +146,22 @@ pub fn view_window<'a, 'b>(
});
// ── Right: editor (name + paper:drawing) ──────────────────────────────
let field =
|label: Cow<'static, str>, ph: Cow<'static, str>, value: &str, on: fn(String) -> Message| {
row![
text(label).size(11).style(muted_text_style).width(96),
text_input(ph.as_ref(), value)
.on_input(on)
.style(field_style)
.size(12)
.padding([5, 8])
.width(sizing.width),
]
.align_y(iced::Center)
.spacing(6)
};
let field = |label: Cow<'static, str>,
ph: Cow<'static, str>,
value: &str,
on: fn(String) -> Message| {
row![
text(label).size(11).style(muted_text_style).width(96),
text_input(ph.as_ref(), value)
.on_input(on)
.style(field_style)
.size(12)
.padding([5, 8])
.width(sizing.width),
]
.align_y(iced::Center)
.spacing(6)
};
let editor = container(
column![
@@ -187,9 +183,7 @@ pub fn view_window<'a, 'b>(
container(column![toolbar, hdivider(sizing.width), body])
.style(|theme: &Theme| container::Style {
background: Some(Background::Color(
theme.palette().background.base.color
)),
background: Some(Background::Color(theme.palette().background.base.color)),
..Default::default()
})
.width(sizing.width)
+4 -5
View File
@@ -44,17 +44,16 @@ pub fn item<'a>(
// Fixed-width ✓ column keeps every name left-aligned whether or not the
// row is current.
let check = crate::ui::icons::themed_check_cell(is_current);
let label = row![check, text(name.to_string()).size(11)]
.align_y(iced::Center);
let label = row![check, text(name.to_string()).size(11)].align_y(iced::Center);
let cell = container(label)
.padding([4, 8])
.width(Fill)
.style(move |theme: &Theme| {
let pair = theme.palette().primary.strong;
container::Style {
background: is_selected.then_some(Background::Color(pair.color)),
text_color: is_selected.then_some(pair.text),
..Default::default()
background: is_selected.then_some(Background::Color(pair.color)),
text_color: is_selected.then_some(pair.text),
..Default::default()
}
});
let area = mouse_area(cell).on_press(on_select);
+31 -34
View File
@@ -8,10 +8,10 @@
//! toolbar, list, inline-rename wiring and chrome live here once.
use crate::app::{Message, StyleKind};
use crate::t;
use iced::widget::button::{Status, Style};
use iced::widget::{button, column, container, row, scrollable, text, Space};
use iced::{Background, Border, Element, Length, Theme};
use crate::t;
use std::borrow::Cow;
/// Everything the shared frame needs. The per-manager `editor` element is the
@@ -67,9 +67,7 @@ pub fn view<'a, 'b>(s: Scaffold<'a, 'b>) -> Element<'a, Message> {
.align_y(iced::Center);
let toolbar = container(bar)
.style(|theme: &Theme| container::Style {
background: Some(Background::Color(
theme.palette().background.weak.color
)),
background: Some(Background::Color(theme.palette().background.weak.color)),
..Default::default()
})
.width(width)
@@ -102,13 +100,13 @@ pub fn view<'a, 'b>(s: Scaffold<'a, 'b>) -> Element<'a, Message> {
.style(|theme: &Theme| {
let palette = theme.palette();
container::Style {
background: Some(Background::Color(palette.background.weak.color)),
border: Border {
color: palette.background.neutral.color,
width: 1.0,
radius: 3.0.into()
},
..Default::default()
background: Some(Background::Color(palette.background.weak.color)),
border: Border {
color: palette.background.neutral.color,
width: 1.0,
radius: 3.0.into(),
},
..Default::default()
}
})
.width(width)
@@ -131,9 +129,7 @@ pub fn view<'a, 'b>(s: Scaffold<'a, 'b>) -> Element<'a, Message> {
container(column![toolbar, hdivider(width), body])
.style(|theme: &Theme| container::Style {
background: Some(Background::Color(
theme.palette().background.base.color
)),
background: Some(Background::Color(theme.palette().background.base.color)),
..Default::default()
})
.width(width)
@@ -181,11 +177,8 @@ pub fn editor_shell<'a>(shell: EditorShell<'a>) -> Element<'a, Message> {
let comparison: Element<'a, Message> = match shell.comparison {
Some(comparison) if !comparison.options.is_empty() => row![
text(t!("Compare with")).size(10).style(muted_text_style),
iced::widget::pick_list(
Some(comparison.selected),
comparison.options,
|value| value.to_string(),
)
iced::widget::pick_list(Some(comparison.selected), comparison.options, |value| value
.to_string(),)
.on_select(comparison.on_select)
.text_size(11)
.width(150),
@@ -219,9 +212,13 @@ pub fn editor_shell<'a>(shell: EditorShell<'a>) -> Element<'a, Message> {
comparison,
row(tabs).spacing(2),
hdivider(Length::Fill),
scrollable(container(shell.content).padding([12, 12]).width(Length::Fill))
.width(Length::Fill)
.height(Length::Fill),
scrollable(
container(shell.content)
.padding([12, 12])
.width(Length::Fill)
)
.width(Length::Fill)
.height(Length::Fill),
]
.spacing(6)
.height(shell.sizing.height),
@@ -307,18 +304,18 @@ fn btn_s(accent: bool) -> impl Fn(&Theme, Status) -> Style {
_ => palette.background.weak,
};
Style {
background: Some(Background::Color(pair.color)),
text_color: if st == Status::Disabled {
pair.text.scale_alpha(0.45)
} else {
pair.text
},
border: Border {
color: palette.background.neutral.color,
width: 1.0,
radius: 4.0.into(),
},
..Default::default()
background: Some(Background::Color(pair.color)),
text_color: if st == Status::Disabled {
pair.text.scale_alpha(0.45)
} else {
pair.text
},
border: Border {
color: palette.background.neutral.color,
width: 1.0,
radius: 4.0.into(),
},
..Default::default()
}
}
}
+250 -64
View File
@@ -2,9 +2,9 @@
use crate::app::Message;
use crate::t;
use crate::ui::style::common::muted_style;
use iced::widget::{canvas, checkbox, column, row, text, text_input, Column};
use iced::{mouse, Color, Element, Length, Point, Rectangle, Size, Theme};
use crate::ui::style::common::muted_style;
use std::borrow::Cow;
use std::fmt;
@@ -197,16 +197,52 @@ impl canvas::Program<Message> for TablePreviewCanvas {
);
}
let borders = &row.borders;
draw_line(&mut frame, Point::new(left, y0), Point::new(left, y1), &borders[0], ink);
draw_line(&mut frame, Point::new(right, y0), Point::new(right, y1), &borders[1], ink);
draw_line(&mut frame, Point::new(left, y0), Point::new(right, y0), &borders[2], ink);
draw_line(&mut frame, Point::new(left, y1), Point::new(right, y1), &borders[3], ink);
draw_line(
&mut frame,
Point::new(left, y0),
Point::new(left, y1),
&borders[0],
ink,
);
draw_line(
&mut frame,
Point::new(right, y0),
Point::new(right, y1),
&borders[1],
ink,
);
draw_line(
&mut frame,
Point::new(left, y0),
Point::new(right, y0),
&borders[2],
ink,
);
draw_line(
&mut frame,
Point::new(left, y1),
Point::new(right, y1),
&borders[3],
ink,
);
for column in 1..3 {
let x = left + column as f32 * col_width;
draw_line(&mut frame, Point::new(x, y0), Point::new(x, y1), &borders[5], ink);
draw_line(
&mut frame,
Point::new(x, y0),
Point::new(x, y1),
&borders[5],
ink,
);
}
if display_row + 1 < order.len() {
draw_line(&mut frame, Point::new(left, y1), Point::new(right, y1), &borders[4], ink);
draw_line(
&mut frame,
Point::new(left, y1),
Point::new(right, y1),
&borders[4],
ink,
);
}
for column in 0..3 {
let label = if row.format.trim().is_empty() {
@@ -223,8 +259,12 @@ impl canvas::Program<Message> for TablePreviewCanvas {
};
let x = match horizontal {
iced::advanced::text::Alignment::Left => left + column as f32 * col_width + 5.0,
iced::advanced::text::Alignment::Right => left + (column + 1) as f32 * col_width - 5.0,
iced::advanced::text::Alignment::Center => left + (column as f32 + 0.5) * col_width,
iced::advanced::text::Alignment::Right => {
left + (column + 1) as f32 * col_width - 5.0
}
iced::advanced::text::Alignment::Center => {
left + (column as f32 + 0.5) * col_width
}
_ => left + (column as f32 + 0.5) * col_width,
};
let y = if row.alignment.starts_with("Top") {
@@ -256,10 +296,20 @@ impl canvas::Program<Message> for TablePreviewCanvas {
content: format!(
"{} · {} · {} {} / {} {}{}{}",
active.text_style,
if self.annotative { t!("Annotative") } else { t!("Drawing units") },
t!("Type"), active.data_type,
t!("Unit"), active.unit_type,
if self.description.trim().is_empty() { "" } else { " · " },
if self.annotative {
t!("Annotative")
} else {
t!("Drawing units")
},
t!("Type"),
active.data_type,
t!("Unit"),
active.unit_type,
if self.description.trim().is_empty() {
""
} else {
" · "
},
self.description,
),
position: Point::new(10.0, bounds.height - 9.0),
@@ -301,10 +351,12 @@ fn cell_editor<'a>(v: &TableStyleView<'a>, row_index: u8) -> Element<'a, Message
};
let index = row_index as usize;
let cell_input = |label, placeholder, value: &'a str, field| {
input_row(label, placeholder, value, move |value| Message::TableStyleCellEdit {
row: row_index,
field,
value,
input_row(label, placeholder, value, move |value| {
Message::TableStyleCellEdit {
row: row_index,
field,
value,
}
})
};
let cell_color = |label: Cow<'static, str>, value: &'a str, field: &'static str| {
@@ -323,7 +375,10 @@ fn cell_editor<'a>(v: &TableStyleView<'a>, row_index: u8) -> Element<'a, Message
value: crate::ui::color_select::color_to_aci_string(color),
},
Message::TableColorMore(row_index, field),
Message::OpenColorWindow(crate::app::ColorPickTarget::Table(row_index, field), current),
Message::OpenColorWindow(
crate::app::ColorPickTarget::Table(row_index, field),
current,
),
);
row![text(label).size(11).style(muted_style).width(155), selector]
.spacing(8)
@@ -332,23 +387,53 @@ fn cell_editor<'a>(v: &TableStyleView<'a>, row_index: u8) -> Element<'a, Message
let selected_alignment = format!("{:?}", row_style.alignment);
let mut content = Column::new()
.spacing(7)
.push(cell_input(t!("Text style"), "Standard", &v.cell_textstyle[index], "textstyle"))
.push(cell_input(t!("Text height"), "0.18", &v.cell_height[index], "height"))
.push(cell_color(t!("Text color"), &v.cell_textcolor[index], "textcolor"))
.push(cell_color(t!("Fill color"), &v.cell_fillcolor[index], "fillcolor"))
.push(cell_input(
t!("Text style"),
"Standard",
&v.cell_textstyle[index],
"textstyle",
))
.push(cell_input(
t!("Text height"),
"0.18",
&v.cell_height[index],
"height",
))
.push(cell_color(
t!("Text color"),
&v.cell_textcolor[index],
"textcolor",
))
.push(cell_color(
t!("Fill color"),
&v.cell_fillcolor[index],
"fillcolor",
))
.push(
row![
text(t!("Alignment")).size(11).style(muted_style).width(155),
iced::widget::pick_list(
Some(EnumChoice { code: selected_alignment.clone(), label: crate::i18n::translate(&selected_alignment) }),
Some(EnumChoice {
code: selected_alignment.clone(),
label: crate::i18n::translate(&selected_alignment)
}),
choices(&[
("TopLeft", "Top left"), ("TopCenter", "Top center"), ("TopRight", "Top right"),
("MiddleLeft", "Middle left"), ("MiddleCenter", "Middle center"), ("MiddleRight", "Middle right"),
("BottomLeft", "Bottom left"), ("BottomCenter", "Bottom center"), ("BottomRight", "Bottom right"),
("TopLeft", "Top left"),
("TopCenter", "Top center"),
("TopRight", "Top right"),
("MiddleLeft", "Middle left"),
("MiddleCenter", "Middle center"),
("MiddleRight", "Middle right"),
("BottomLeft", "Bottom left"),
("BottomCenter", "Bottom center"),
("BottomRight", "Bottom right"),
]),
|value| value.to_string(),
)
.on_select(move |choice| Message::TableStyleCellSetAlign { row: row_index, value: choice.code })
.on_select(move |choice| Message::TableStyleCellSetAlign {
row: row_index,
value: choice.code
})
.text_size(11)
.width(170),
]
@@ -362,9 +447,24 @@ fn cell_editor<'a>(v: &TableStyleView<'a>, row_index: u8) -> Element<'a, Message
.size(14)
.text_size(11),
)
.push(cell_input(t!("Data type"), "0", &v.cell_datatype[index], "datatype"))
.push(cell_input(t!("Unit type"), "0", &v.cell_unittype[index], "unittype"))
.push(cell_input(t!("Format string"), "", &v.cell_format[index], "format"))
.push(cell_input(
t!("Data type"),
"0",
&v.cell_datatype[index],
"datatype",
))
.push(cell_input(
t!("Unit type"),
"0",
&v.cell_unittype[index],
"unittype",
))
.push(cell_input(
t!("Format string"),
"",
&v.cell_format[index],
"format",
))
.push(text(t!("Borders")).size(11).style(primary_style));
let borders = [
(t!("Left"), &row_style.left_border),
@@ -381,26 +481,64 @@ fn cell_editor<'a>(v: &TableStyleView<'a>, row_index: u8) -> Element<'a, Message
row![
text(label).size(10).style(muted_style).width(96),
iced::widget::pick_list(
Some(EnumChoice { code: border_type.clone(), label: crate::i18n::translate(&border_type) }),
Some(EnumChoice {
code: border_type.clone(),
label: crate::i18n::translate(&border_type)
}),
choices(&[("Single", "Single"), ("Double", "Double")]),
|value| value.to_string(),
)
.on_select(move |choice| Message::TableStyleBorderSetType { cell: row_index, border: border_index, value: choice.code })
.on_select(move |choice| Message::TableStyleBorderSetType {
cell: row_index,
border: border_index,
value: choice.code
})
.text_size(10)
.width(82),
text_input(t!("Weight").as_ref(), &v.border_lw[index][border_index as usize])
.on_input(move |value| Message::TableStyleBorderEdit { cell: row_index, border: border_index, field: "lw", value })
.size(10).width(68),
text_input(t!("Color").as_ref(), &v.border_color[index][border_index as usize])
.on_input(move |value| Message::TableStyleBorderEdit { cell: row_index, border: border_index, field: "color", value })
.size(10).width(62),
text_input(t!("Spacing").as_ref(), &v.border_spacing[index][border_index as usize])
.on_input(move |value| Message::TableStyleBorderEdit { cell: row_index, border: border_index, field: "spacing", value })
.size(10).width(68),
text_input(
t!("Weight").as_ref(),
&v.border_lw[index][border_index as usize]
)
.on_input(move |value| Message::TableStyleBorderEdit {
cell: row_index,
border: border_index,
field: "lw",
value
})
.size(10)
.width(68),
text_input(
t!("Color").as_ref(),
&v.border_color[index][border_index as usize]
)
.on_input(move |value| Message::TableStyleBorderEdit {
cell: row_index,
border: border_index,
field: "color",
value
})
.size(10)
.width(62),
text_input(
t!("Spacing").as_ref(),
&v.border_spacing[index][border_index as usize]
)
.on_input(move |value| Message::TableStyleBorderEdit {
cell: row_index,
border: border_index,
field: "spacing",
value
})
.size(10)
.width(68),
checkbox(border.is_invisible)
.label(t!("Hidden"))
.on_toggle(move |_| Message::TableStyleBorderToggleInvisible { cell: row_index, border: border_index })
.size(13).text_size(10),
.on_toggle(move |_| Message::TableStyleBorderToggleInvisible {
cell: row_index,
border: border_index
})
.size(13)
.text_size(10),
]
.spacing(5)
.align_y(iced::Center),
@@ -411,7 +549,11 @@ fn cell_editor<'a>(v: &TableStyleView<'a>, row_index: u8) -> Element<'a, Message
fn preview_rows(v: &TableStyleView<'_>) -> Option<[PreviewRow; 3]> {
let style = v.style?;
let source = [&style.data_row_style, &style.header_row_style, &style.title_row_style];
let source = [
&style.data_row_style,
&style.header_row_style,
&style.title_row_style,
];
Some(std::array::from_fn(|row| {
let borders = [
&source[row].left_border,
@@ -451,23 +593,58 @@ pub fn view_window<'a>(
let content: Element<'a, Message> = match (v.tab, style) {
(_, None) => text(t!("Select a style to view details.")).size(11).into(),
(0, Some(style)) => column![
input_row(t!("Description"), "", v.description, |value| Message::TableStyleEdit { field: "description", value }),
input_row(t!("Description"), "", v.description, |value| {
Message::TableStyleEdit {
field: "description",
value,
}
}),
row![
text(t!("Flow direction")).size(11).style(muted_style).width(155),
text(t!("Flow direction"))
.size(11)
.style(muted_style)
.width(155),
iced::widget::pick_list(
Some(EnumChoice { code: format!("{:?}", style.flow_direction), label: crate::i18n::translate(&format!("{:?}", style.flow_direction)) }),
Some(EnumChoice {
code: format!("{:?}", style.flow_direction),
label: crate::i18n::translate(&format!("{:?}", style.flow_direction))
}),
choices(&[("Down", "Top to bottom"), ("Up", "Bottom to top")]),
|value| value.to_string(),
)
.on_select(|choice| Message::TableStyleSetFlow(choice.code))
.text_size(11).width(170),
.text_size(11)
.width(170),
]
.spacing(8).align_y(iced::Center),
input_row(t!("Horizontal margin"), "1.5", v.hmargin, |value| Message::TableStyleEdit { field: "hmargin", value }),
input_row(t!("Vertical margin"), "1.5", v.vmargin, |value| Message::TableStyleEdit { field: "vmargin", value }),
checkbox(style.title_suppressed).label(t!("Suppress title row")).on_toggle(|_| Message::TableStyleToggle("title_sup")).size(14).text_size(11),
checkbox(style.header_suppressed).label(t!("Suppress header row")).on_toggle(|_| Message::TableStyleToggle("header_sup")).size(14).text_size(11),
checkbox(style.annotative).label(t!("Annotative")).on_toggle(|_| Message::TableStyleToggleAnnotative).size(14).text_size(11),
.spacing(8)
.align_y(iced::Center),
input_row(t!("Horizontal margin"), "1.5", v.hmargin, |value| {
Message::TableStyleEdit {
field: "hmargin",
value,
}
}),
input_row(t!("Vertical margin"), "1.5", v.vmargin, |value| {
Message::TableStyleEdit {
field: "vmargin",
value,
}
}),
checkbox(style.title_suppressed)
.label(t!("Suppress title row"))
.on_toggle(|_| Message::TableStyleToggle("title_sup"))
.size(14)
.text_size(11),
checkbox(style.header_suppressed)
.label(t!("Suppress header row"))
.on_toggle(|_| Message::TableStyleToggle("header_sup"))
.size(14)
.text_size(11),
checkbox(style.annotative)
.label(t!("Annotative"))
.on_toggle(|_| Message::TableStyleToggleAnnotative)
.size(14)
.text_size(11),
]
.spacing(9)
.into(),
@@ -486,7 +663,11 @@ pub fn view_window<'a>(
unit_type: String::new(),
format: String::new(),
borders: std::array::from_fn(|_| PreviewBorder {
color: String::new(), weight: String::new(), spacing: String::new(), double: false, hidden: false,
color: String::new(),
weight: String::new(),
spacing: String::new(),
double: false,
hidden: false,
}),
})
});
@@ -527,15 +708,20 @@ pub fn view_window<'a>(
summary,
on_select: Message::TableStyleDialogCompare,
}),
tabs: [t!("General"), t!("Data Row"), t!("Header Row"), t!("Title Row")]
.into_iter()
.enumerate()
.map(|(tab, label)| crate::ui::style::style_manager::EditorTab {
label,
active: v.tab == tab as u8,
on_press: Message::TableStyleDialogTab(tab as u8),
})
.collect(),
tabs: [
t!("General"),
t!("Data Row"),
t!("Header Row"),
t!("Title Row"),
]
.into_iter()
.enumerate()
.map(|(tab, label)| crate::ui::style::style_manager::EditorTab {
label,
active: v.tab == tab as u8,
on_press: Message::TableStyleDialogTab(tab as u8),
})
.collect(),
content,
},
);
+67 -17
View File
@@ -2,9 +2,11 @@
use crate::app::{Message, StyleKind};
use crate::t;
use iced::widget::{button, canvas, checkbox, column, container, row, scrollable, text, text_input};
use iced::{mouse, Background, Border, Element, Length, Point, Rectangle, Theme};
use crate::ui::style::common::muted_style;
use iced::widget::{
button, canvas, checkbox, column, container, row, scrollable, text, text_input,
};
use iced::{mouse, Background, Border, Element, Length, Point, Rectangle, Theme};
use std::borrow::Cow;
pub struct TextStyleView<'a> {
@@ -32,9 +34,9 @@ pub struct TextStyleView<'a> {
}
const BUILTIN_FONTS: &[&str] = &[
"Standard", "ISO", "Simplex", "RomanS", "RomanD", "RomanC", "RomanT", "ItalicC",
"ItalicT", "ScriptS", "ScriptC", "GothGBT", "GothGRT", "GothITT", "GreekC",
"Symbol", "ISO3098", "Unicode",
"Standard", "ISO", "Simplex", "RomanS", "RomanD", "RomanC", "RomanT", "ItalicC", "ItalicT",
"ScriptS", "ScriptC", "GothGBT", "GothGRT", "GothITT", "GreekC", "Symbol", "ISO3098",
"Unicode",
];
fn primary_style(theme: &Theme) -> iced::widget::text::Style {
@@ -275,10 +277,16 @@ fn font_list<'a>(
}
})
.collect();
container(column![text(title).size(10).style(muted_style), scrollable(column(items).spacing(1)).height(250)].spacing(5))
.width(Length::FillPortion(1))
.padding(4)
.into()
container(
column![
text(title).size(10).style(muted_style),
scrollable(column(items).spacing(1)).height(250)
]
.spacing(5),
)
.width(Length::FillPortion(1))
.padding(4)
.into()
}
pub fn view_window<'a>(
@@ -301,7 +309,12 @@ pub fn view_window<'a>(
font: effective_font.to_string(),
big_font: v.bigfont_buf.to_string(),
width_factor: if v.backward { -width } else { width },
oblique: v.oblique_buf.trim().parse::<f32>().unwrap_or(0.0).to_radians(),
oblique: v
.oblique_buf
.trim()
.parse::<f32>()
.unwrap_or(0.0)
.to_radians(),
height: v.height_buf.trim().parse::<f32>().unwrap_or(0.0).max(0.0),
upside_down: v.upside_down,
vertical: v.vertical,
@@ -312,7 +325,10 @@ pub fn view_window<'a>(
let content: Element<'a, Message> = match v.tab {
0 => {
let built_in = BUILTIN_FONTS.iter().map(|value| (*value).to_string()).collect();
let built_in = BUILTIN_FONTS
.iter()
.map(|value| (*value).to_string())
.collect();
let system = crate::scene::text::sysfont::families().to_vec();
column![
row![
@@ -320,9 +336,27 @@ pub fn view_window<'a>(
font_list(t!("System fonts"), system, v.ttf_buf, true, v.read_only),
]
.spacing(10),
input_row(t!("Font file"), t!("font file…"), v.font_buf, "font", v.read_only),
input_row(t!("Big font"), t!("big-font file…"), v.bigfont_buf, "bigfont", v.read_only),
input_row(t!("System font"), t!("font family…"), v.ttf_buf, "ttf", v.read_only),
input_row(
t!("Font file"),
t!("font file…"),
v.font_buf,
"font",
v.read_only
),
input_row(
t!("Big font"),
t!("big-font file…"),
v.bigfont_buf,
"bigfont",
v.read_only
),
input_row(
t!("System font"),
t!("font family…"),
v.ttf_buf,
"ttf",
v.read_only
),
]
.spacing(8)
.into()
@@ -330,15 +364,31 @@ pub fn view_window<'a>(
_ => column![
text(t!("Size")).size(11).style(primary_style),
input_row(
if v.annotative { t!("Paper text height") } else { t!("Fixed height") },
if v.annotative {
t!("Paper text height")
} else {
t!("Fixed height")
},
t!("0 = variable"),
v.height_buf,
"height",
v.read_only,
),
text(t!("Effects")).size(11).style(primary_style),
input_row(t!("Width factor"), "1.0".into(), v.width_buf, "width", v.read_only),
input_row(t!("Oblique angle"), "0.0".into(), v.oblique_buf, "oblique", v.read_only),
input_row(
t!("Width factor"),
"1.0".into(),
v.width_buf,
"width",
v.read_only
),
input_row(
t!("Oblique angle"),
"0.0".into(),
v.oblique_buf,
"oblique",
v.read_only
),
row![
toggle(t!("Backward"), v.backward, "backward", v.read_only),
toggle(t!("Upside down"), v.upside_down, "upside_down", v.read_only),