forked from 1b-agent/opencadstudio-upstream
style: apply cargo fmt across workspace
This commit is contained in:
1 parent
85710e5454
commit
9cf9ff2c5c
531 files changed
+57740
-33906
No files matched your search
@@ -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)
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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"
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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
@@ -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),
|
||||
|
||||
Reference in new issue
Block a user