style: rustfmt the tree so the CI lint check passes

This commit is contained in:
Karim Jerbi committed 2026-10-15 04:10:06 +01:00
1 parent 1317a7b4fd
commit 6025d8be44
128 files changed
+4097 -1676

No files matched your search

+5 -1
View File
@@ -553,7 +553,11 @@ impl CommandLine {
let fade = self.fade_secs();
let now = Instant::now();
for entry in &mut self.history {
if since.saturating_duration_since(entry.created_at).as_secs_f32() < fade {
if since
.saturating_duration_since(entry.created_at)
.as_secs_f32()
< fade
{
entry.created_at = now;
}
}
+3 -1
View File
@@ -156,7 +156,9 @@ impl PanelId {
pub fn icon(self) -> &'static [u8] {
match self {
PanelId::Properties => include_bytes!("../../assets/icons/properties.svg"),
PanelId::GraphicAttributes => include_bytes!("../../assets/icons/graphic_attributes.svg"),
PanelId::GraphicAttributes => {
include_bytes!("../../assets/icons/graphic_attributes.svg")
}
PanelId::BlockPalette => include_bytes!("../../assets/icons/blocks/insert.svg"),
PanelId::ExternalReferences => crate::ui::icons::FOLDER_OPEN,
PanelId::Browser => include_bytes!("../../assets/icons/content_browser.svg"),
+1 -1
View File
@@ -6,9 +6,9 @@ pub mod color_select;
pub mod command_line;
pub mod dock;
pub mod icons;
pub mod menu_bar;
pub mod modal;
pub mod node_graph;
pub mod menu_bar;
pub mod overlay;
pub mod popup;
pub mod properties;
+2 -1
View File
@@ -1798,7 +1798,8 @@ impl canvas::Program<Message> for SelectionCanvas {
},
..canvas::Stroke::default().with_color(marker).with_width(1.0)
};
let tip = Point::new(sp.x + dx / len * 18.0, sp.y + dy / len * 18.0);
let tip =
Point::new(sp.x + dx / len * 18.0, sp.y + dy / len * 18.0);
// `base` is a projected entity endpoint: clip before
// stroking (see `clip_seg`).
if let Some((a, b)) = clip_seg(base, tip, bounds) {
+5 -1
View File
@@ -270,7 +270,11 @@ pub(super) fn keytip_items(id: &str) -> Vec<(&'static str, &'static str, bool)>
.tools
.iter()
.filter(|tool| tool.command == id)
.flat_map(|tool| tool.options.iter().map(|(cmd, _)| (tool.command, *cmd, false)))
.flat_map(|tool| {
tool.options
.iter()
.map(|(cmd, _)| (tool.command, *cmd, false))
})
.collect()
}
+67 -13
View File
@@ -29,7 +29,9 @@ pub enum KeyTipInput {
AltTap,
/// Show the tab level; `refocus` returns the focus to the command line
/// when the tips close.
Open { refocus: bool },
Open {
refocus: bool,
},
/// One typed character (upper case).
Char(String),
/// Settle a code that also starts a longer one.
@@ -104,7 +106,10 @@ pub fn active() -> bool {
}
/// Record `el`'s bounds under `id` while key tips show.
pub(super) fn anchor<'a>(id: &'static str, el: impl Into<Element<'a, Message>>) -> Element<'a, Message> {
pub(super) fn anchor<'a>(
id: &'static str,
el: impl Into<Element<'a, Message>>,
) -> Element<'a, Message> {
if active() {
PosReport::new(id, el).into()
} else {
@@ -166,7 +171,11 @@ pub(super) fn collapsed_anchor(title: &str) -> String {
/// Keyboard listener hook for a key press. `Some` while key tips own the
/// keyboard (the inner value is the message to send, if any).
pub fn key_pressed(key: &Key, modifiers: keyboard::Modifiers, repeat: bool) -> Option<Option<Message>> {
pub fn key_pressed(
key: &Key,
modifiers: keyboard::Modifiers,
repeat: bool,
) -> Option<Option<Message>> {
let alt = matches!(key, Key::Named(Named::Alt));
if !repeat {
ALT_ALONE.store(
@@ -607,7 +616,8 @@ impl Ribbon {
.filter(|tip| tip.code.as_deref() == Some(typed))
.min_by_key(|tip| rank(tip))
};
let longer = |typed: &str| codes().any(|code| code.len() > typed.len() && code.starts_with(typed));
let longer =
|typed: &str| codes().any(|code| code.len() > typed.len() && code.starts_with(typed));
let typed = ch.map(|ch| format!("{}{ch}", state.typed));
let chosen = match typed {
Some(typed) if codes().any(|code| code.starts_with(&typed)) => {
@@ -791,7 +801,9 @@ impl Ribbon {
.map(|(position, (dropdown_id, cmd, submenu))| Tip {
anchor: item_anchor(dropdown_id, cmd),
target: cmd,
code: Some(code(open, cmd).map_or_else(|| (position + 1).to_string(), str::to_string)),
code: Some(
code(open, cmd).map_or_else(|| (position + 1).to_string(), str::to_string),
),
action: if submenu {
Action::Open(Message::ToggleRibbonDropdown(cmd.to_string()))
} else {
@@ -1103,7 +1115,9 @@ impl overlay::Overlay<Message, Theme, Renderer> for KeyTipOverlay<'_> {
let free = |rect: &Rectangle, blocked: &[Rectangle]| {
// Touching edges do not count.
!blocked.iter().any(|other| {
other.intersection(rect).is_some_and(|r| r.width > 1.0 && r.height > 1.0)
other
.intersection(rect)
.is_some_and(|r| r.width > 1.0 && r.height > 1.0)
})
};
let mut pills: Vec<(&String, &String, Rectangle)> = Vec::new();
@@ -1125,7 +1139,11 @@ impl overlay::Overlay<Message, Theme, Renderer> for KeyTipOverlay<'_> {
let Some(&first) = rects.first() else {
continue;
};
let pill = rects.iter().copied().find(|rect| free(rect, &blocked)).unwrap_or(first);
let pill = rects
.iter()
.copied()
.find(|rect| free(rect, &blocked))
.unwrap_or(first);
blocked.push(pill);
pills.push((anchor, code, pill));
}
@@ -1161,9 +1179,27 @@ impl overlay::Overlay<Message, Theme, Renderer> for KeyTipOverlay<'_> {
..pill
};
if !done.is_empty() {
draw_text(renderer, done, Point::new(left, pill.center_y() - 0.5), PILL_TEXT, font, ink.scale_alpha(0.45), false, clip);
draw_text(
renderer,
done,
Point::new(left, pill.center_y() - 0.5),
PILL_TEXT,
font,
ink.scale_alpha(0.45),
false,
clip,
);
}
draw_text(renderer, rest, Point::new(left + done_w, pill.center_y() - 0.5), PILL_TEXT, font, ink, false, clip);
draw_text(
renderer,
rest,
Point::new(left + done_w, pill.center_y() - 0.5),
PILL_TEXT,
font,
ink,
false,
clip,
);
shown.push(anchor.clone());
}
});
@@ -1210,7 +1246,16 @@ fn draw_bar(renderer: &mut Renderer, theme: &Theme, parts: &[String; 3]) {
1 => (regular, ink),
_ => (regular, ink.scale_alpha(0.6)),
};
draw_text(renderer, part, Point::new(x, y), BAR_TEXT, part_font, color, false, bar);
draw_text(
renderer,
part,
Point::new(x, y),
BAR_TEXT,
part_font,
color,
false,
bar,
);
x += text_width(part, BAR_TEXT, part_font) + 18.0;
}
}
@@ -1239,13 +1284,19 @@ fn pill_candidates(
let left_corner = |x: f32, y: f32| Point::new(x - width / 2.0, y + PILL_H / 2.0);
let label = fresh_bounds(&label_id(anchor));
if anchor.starts_with("tab:") {
return vec![Point::new(b.center_x(), b.y + b.height - 4.0 + PILL_H / 2.0)];
return vec![Point::new(
b.center_x(),
b.y + b.height - 4.0 + PILL_H / 2.0,
)];
}
if anchor.starts_with("qa:")
|| anchor == super::widgets::UNDO_HISTORY_ID
|| anchor == super::widgets::REDO_HISTORY_ID
{
return vec![corner(b.x + 14.0, b.center_y()), Point::new(b.x + 14.0, b.center_y())];
return vec![
corner(b.x + 14.0, b.center_y()),
Point::new(b.x + 14.0, b.center_y()),
];
}
if anchor == XREF_LAUNCHER {
return vec![
@@ -1291,7 +1342,10 @@ fn pill_candidates(
let mut spots = Vec::new();
if dropdown {
// The arrow strip lies under the label.
spots.push(Point::new(b.center_x(), b.y + b.height - super::widgets::LARGE_ARR / 2.0));
spots.push(Point::new(
b.center_x(),
b.y + b.height - super::widgets::LARGE_ARR / 2.0,
));
}
spots.extend([
Point::new(b.center_x(), label.y + label.height + 1.0 + PILL_H / 2.0),
+9 -6
View File
@@ -30,17 +30,17 @@ pub use context_tools::{pdf_underlay_tools, point_cloud_tools, xref_tools, Under
use widgets::{StyleContext, *};
pub(crate) use widgets::{REDO_HISTORY_ID, UNDO_HISTORY_ID};
mod collapse;
mod locate;
mod keytips;
mod locate;
use crate::t;
use crate::ui::wrap_bar::{PosReport, WrapBar, WrapFlow};
pub use collapse::CollapseMode;
use collapse::{CollapsePanels, Panel};
pub use keytips::{
active as keytips_active, key_pressed as keytip_key_pressed,
key_released as keytip_key_released, pointer_pressed as keytip_pointer_pressed, KeyTipInput,
KeyTipStep,
};
use crate::t;
use crate::ui::wrap_bar::{PosReport, WrapBar, WrapFlow};
pub use collapse::CollapseMode;
use collapse::{CollapsePanels, Panel};
pub(crate) fn tooltip_content(text: String) -> Element<'static, Message> {
widgets::make_tip(text)
@@ -337,7 +337,10 @@ impl Ribbon {
/// Show the Block Editor tab while a block is being edited, and return to
/// the previous tab when the editing ends.
pub fn set_block_editing(&mut self, editing: bool) {
let Some(index) = self.modules.iter().position(|module| module.id() == "block_editor")
let Some(index) = self
.modules
.iter()
.position(|module| module.id() == "block_editor")
else {
return;
};
+4 -4
View File
@@ -1103,8 +1103,8 @@ pub(super) fn render_large<'a>(item: &RibbonItem, ctx: &RenderCtx<'_>) -> Elemen
|| super::keytips::label_id(LAYER_COMBO_ID),
text(active_layer_label).size(11),
))
.width(name_w)
.clip(true),
.width(name_w)
.clip(true),
icons::themed_arrow_down(9.0),
]
.spacing(4)
@@ -1253,8 +1253,8 @@ pub(super) fn render_large<'a>(item: &RibbonItem, ctx: &RenderCtx<'_>) -> Elemen
|| super::keytips::label_id(combo_id),
text(active.clone()).size(11),
))
.width(Fill)
.clip(true),
.width(Fill)
.clip(true),
if is_open {
icons::themed_arrow_up(9.0)
} else {
+35 -20
View File
@@ -72,24 +72,30 @@ pub fn refedit_header(name: &str, count: usize) -> Element<'static, Message> {
..Default::default()
}
});
let tip = container(text(name.to_string()).size(11)).padding([2, 6]).style(|theme: &Theme| {
let palette = theme.palette();
container::Style {
background: Some(Background::Color(palette.background.strong.color)),
border: Border {
color: palette.background.neutral.color,
width: 1.0,
radius: 3.0.into(),
},
text_color: Some(palette.background.strong.text),
..Default::default()
}
});
let tip = container(text(name.to_string()).size(11))
.padding([2, 6])
.style(|theme: &Theme| {
let palette = theme.palette();
container::Style {
background: Some(Background::Color(palette.background.strong.color)),
border: Border {
color: palette.background.neutral.color,
width: 1.0,
radius: 3.0.into(),
},
text_color: Some(palette.background.strong.text),
..Default::default()
}
});
column![
tooltip(pill, tip, tooltip::Position::Left).gap(6),
text(format!("{} {}", count, crate::tr!("ref-edit", "toolbar-objects")))
.size(9)
.style(crate::ui::style::common::muted_style),
text(format!(
"{} {}",
count,
crate::tr!("ref-edit", "toolbar-objects")
))
.size(9)
.style(crate::ui::style::common::muted_style),
]
.spacing(2)
.align_x(iced::Center)
@@ -126,9 +132,16 @@ pub fn view_sections(
if let Some(header) = header {
col = col.push(header);
}
let tools = groups.iter().filter(|g| !g.is_empty()).enumerate().flat_map(|(group, tools)| {
tools.iter().enumerate().map(move |(k, t)| (group > 0 && k == 0, t))
});
let tools = groups
.iter()
.filter(|g| !g.is_empty())
.enumerate()
.flat_map(|(group, tools)| {
tools
.iter()
.enumerate()
.map(move |(k, t)| (group > 0 && k == 0, t))
});
for (starts_group, t) in tools {
if starts_group {
col = col.push(
@@ -136,7 +149,9 @@ pub fn view_sections(
.width(Length::Fixed(BTN_SIZE - 4.0))
.height(Length::Fixed(1.0))
.style(|theme: &Theme| container::Style {
background: Some(Background::Color(theme.palette().background.neutral.color)),
background: Some(Background::Color(
theme.palette().background.neutral.color,
)),
..Default::default()
}),
);
+9 -10
View File
@@ -221,10 +221,14 @@ pub fn view_window<'a>(
.style(button::secondary)]
.spacing(8)
.align_y(iced::Center),
row![add, button(text(t!("Import PGP…")).size(12))
.on_press_maybe((!pending_add).then_some(Message::AliasEditorImport))
.padding([4, 10])
.style(button::secondary)].spacing(8),
row![
add,
button(text(t!("Import PGP…")).size(12))
.on_press_maybe((!pending_add).then_some(Message::AliasEditorImport))
.padding([4, 10])
.style(button::secondary)
]
.spacing(8),
)
};
// Apply — primary action; commits the rows to ocad.pgp and stays open.
@@ -276,12 +280,7 @@ pub fn view_window<'a>(
Space::new().height(6),
scrollable(conflict_banner).height(Length::Fit.max(72)),
Space::new().height(4),
row![
add_area,
reset_area,
]
.spacing(8)
.align_y(iced::Center),
row![add_area, reset_area,].spacing(8).align_y(iced::Center),
row![stats, Space::new().width(Length::Fill), apply_area]
.spacing(8)
.align_y(iced::Center),
+8 -3
View File
@@ -904,9 +904,14 @@ pub fn data_extraction_view(
#[cfg(target_arch = "wasm32")]
let add_folder = iced::widget::tooltip(
add_folder,
container(text(t!("Adding folders is not available in the browser. Add drawing files instead.")).size(11))
.padding([3, 6])
.style(container::bordered_box),
container(
text(t!(
"Adding folders is not available in the browser. Add drawing files instead."
))
.size(11),
)
.padding([3, 6])
.style(container::bordered_box),
iced::widget::tooltip::Position::Top,
)
.gap(4);
+5 -1
View File
@@ -664,7 +664,11 @@ pub fn view_window<'a>(
.align_x(iced::alignment::Horizontal::Center),
Space::new().height(16),
row![
dialog_button(t!("Redefine"), Message::BlockDefConfirmRedefine(true), false),
dialog_button(
t!("Redefine"),
Message::BlockDefConfirmRedefine(true),
false
),
// Default / safe focus on "No"
dialog_button(t!("No"), Message::BlockDefConfirmRedefine(false), true),
]
+32 -24
View File
@@ -31,7 +31,16 @@ pub struct GradientEditorState {
preview: std::cell::RefCell<Option<(PreviewKey, Option<iced::widget::image::Handle>)>>,
}
type PreviewKey = (GradientColorMode, AcadColor, AcadColor, u32, GradientKind, bool, String, bool);
type PreviewKey = (
GradientColorMode,
AcadColor,
AcadColor,
u32,
GradientKind,
bool,
String,
bool,
);
#[derive(Debug, Clone)]
pub enum GradientMsg {
@@ -54,10 +63,7 @@ fn msg(message: GradientMsg) -> Message {
}
impl GradientEditorState {
pub fn from_hatch(
handles: Vec<codec::Handle>,
hatch: &codec::entities::Hatch,
) -> Self {
pub fn from_hatch(handles: Vec<codec::Handle>, hatch: &codec::entities::Hatch) -> Self {
let color = |index: usize| {
hatch
.gradient_color
@@ -124,9 +130,7 @@ impl GradientEditorState {
fn rgb(color: &AcadColor) -> Color {
let (r, g, b) = match color {
AcadColor::Rgb { r, g, b } => (*r, *g, *b),
AcadColor::Index(i) => {
codec::types::aci_table::aci_to_rgb(*i).unwrap_or((128, 128, 128))
}
AcadColor::Index(i) => codec::types::aci_table::aci_to_rgb(*i).unwrap_or((128, 128, 128)),
_ => (255, 255, 255),
};
Color::from_rgb8(r, g, b)
@@ -192,7 +196,9 @@ fn preview_sized(
});
}
}
Some(iced::widget::image::Handle::from_rgba(width, height, pixels))
Some(iced::widget::image::Handle::from_rgba(
width, height, pixels,
))
}
fn preview(state: &GradientEditorState) -> Element<'static, Message> {
@@ -219,7 +225,9 @@ pub(crate) fn compact_preview(
preview_sized(&GradientEditorState::from_hatch(Vec::new(), hatch), 256, 26)
}
pub(crate) fn preview_image(handle: Option<iced::widget::image::Handle>) -> Element<'static, Message> {
pub(crate) fn preview_image(
handle: Option<iced::widget::image::Handle>,
) -> Element<'static, Message> {
match handle {
Some(handle) => image(handle)
.width(Fill)
@@ -357,20 +365,20 @@ pub fn view(state: &GradientEditorState, dimmed: bool) -> Element<'_, Message> {
));
}
let invert_selected = state.inverted && state.kind != GradientKind::Linear;
let invert = button(column![text("⇄").size(18), text(crate::t!("Invert")).size(9)].align_x(iced::Center))
.on_press_maybe(
(state.kind != GradientKind::Linear).then(|| msg(GradientMsg::InvertToggled)),
)
.width(42)
.height(48)
.style(move |theme: &Theme, status| {
let mut style = button::secondary(theme, status);
if invert_selected {
style.border.color = theme.palette().primary.base.color;
style.border.width = 1.0;
}
style
});
let invert = button(
column![text("⇄").size(18), text(crate::t!("Invert")).size(9)].align_x(iced::Center),
)
.on_press_maybe((state.kind != GradientKind::Linear).then(|| msg(GradientMsg::InvertToggled)))
.width(42)
.height(48)
.style(move |theme: &Theme, status| {
let mut style = button::secondary(theme, status);
if invert_selected {
style.border.color = theme.palette().primary.base.color;
style.border.width = 1.0;
}
style
});
let separator =
container(Space::new().width(1).height(36)).style(|theme: &Theme| container::Style {
background: Some(Background::Color(theme.palette().background.neutral.color)),
+106 -37
View File
@@ -10,8 +10,7 @@ use codec::entities::{EntityCommon, Hatch, HatchGradientPattern};
use codec::types::{Color as AcadColor, LineWeight, Transparency};
use codec::{CadDocument, EntityType, Handle};
use iced::widget::{
button, image, column, combo_box, container, row, slider, text, text_input, tooltip,
Space,
button, column, combo_box, container, image, row, slider, text, text_input, tooltip, Space,
};
use iced::{Background, Border, Element, Fill, Length, Padding, Theme};
use rustc_hash::{FxHashMap, FxHashSet};
@@ -171,7 +170,11 @@ impl GraphicAttributesState {
/// The fills and fill kind of `selected`, from an index of associative
/// fills that is rebuilt only when the scene's geometry changes.
pub(crate) fn fills(&self, scene: &Scene, selected: &[Handle]) -> (Vec<Handle>, GraphicAttribute) {
pub(crate) fn fills(
&self,
scene: &Scene,
selected: &[Handle],
) -> (Vec<Handle>, GraphicAttribute) {
// Geometry epochs are unique across all scenes, so the epoch alone
// identifies both the tab and the state of its drawing.
let key = scene.geometry_epoch;
@@ -213,13 +216,25 @@ impl GraphicAttributesState {
let same = |handles: &[Handle]| {
handles.len() == selected.len() && selected.iter().all(|h| handles.contains(h))
};
if self.gradient_editor.as_ref().is_some_and(|e| !same(&e.handles)) {
if self
.gradient_editor
.as_ref()
.is_some_and(|e| !same(&e.handles))
{
self.gradient_editor = None;
}
if self.hatch_editor.as_ref().is_some_and(|e| !same(&e.handles)) {
if self
.hatch_editor
.as_ref()
.is_some_and(|e| !same(&e.handles))
{
self.hatch_editor = None;
}
if self.pending_fill_close.as_ref().is_some_and(|p| !same(&p.selection)) {
if self
.pending_fill_close
.as_ref()
.is_some_and(|p| !same(&p.selection))
{
self.pending_fill_close = None;
}
}
@@ -227,8 +242,10 @@ impl GraphicAttributesState {
pub fn fill_close_prompt(&self) -> Option<String> {
let count = self.pending_fill_close.as_ref()?.open_boundaries.len();
Some(if count == 1 {
crate::t!("The selected object is open. Close it before creating the fill? [Yes / No] <Yes>")
.into_owned()
crate::t!(
"The selected object is open. Close it before creating the fill? [Yes / No] <Yes>"
)
.into_owned()
} else {
crate::tf!(
"{count} selected objects are open. Close them before creating the fill? [Yes / No] <Yes>"
@@ -367,7 +384,9 @@ fn shared_value<'a, T: PartialEq>(
draw_depth: &DrawDepth,
value: impl Fn(&EntityCommon) -> T,
) -> Option<(&'a EntityCommon, T, bool)> {
let top = document.get_entity(top_handle(handles, draw_depth)?)?.common();
let top = document
.get_entity(top_handle(handles, draw_depth)?)?
.common();
let shared = value(top);
let varies = handles.iter().any(|handle| {
document
@@ -469,10 +488,13 @@ impl TransparencyInfo {
}
}
fn color_info(document: &CadDocument, handles: &[Handle], draw_depth: &DrawDepth) -> Option<ColorInfo> {
fn color_info(
document: &CadDocument,
handles: &[Handle],
draw_depth: &DrawDepth,
) -> Option<ColorInfo> {
let (top, color, varies) = shared_value(document, handles, draw_depth, |c| c.color)?;
let rgba =
crate::scene::view::render::render_style_for_common_viewport(document, top, None).0;
let rgba = crate::scene::view::render::render_style_for_common_viewport(document, top, None).0;
Some(ColorInfo {
color,
display: iced::Color::from_rgba(rgba[0], rgba[1], rgba[2], 1.0),
@@ -576,8 +598,8 @@ fn linetype_preview_art(document: &CadDocument, linetype: &str) -> String {
.filter(|character| matches!(character, '_' | '.' | '-' | '/' | '\\' | '|' | '~'))
.count()
>= 2)
.then(|| art.find(part))
.flatten()
.then(|| art.find(part))
.flatten()
});
let pattern = pattern_start.map_or(art.as_str(), |start| &art[start..]);
if pattern.is_empty() {
@@ -746,7 +768,10 @@ fn color_control<'a>(
vec![
("ByLayer".into(), msg(changed(AcadColor::ByLayer))),
("ByBlock".into(), msg(changed(AcadColor::ByBlock))),
(crate::t!("Custom…"), Message::OpenColorWindow(target, info.color)),
(
crate::t!("Custom…"),
Message::OpenColorWindow(target, info.color),
),
],
);
row![swatch, more].spacing(4).align_y(iced::Center).into()
@@ -791,7 +816,11 @@ fn transparency_control<'a>(
row![control, more].spacing(4).align_y(iced::Center).into()
}
fn header_menu(side: DockSide, open: bool, fill_on_current_layer: bool) -> Element<'static, Message> {
fn header_menu(
side: DockSide,
open: bool,
fill_on_current_layer: bool,
) -> Element<'static, Message> {
let menu_button = button(crate::ui::icons::themed_secondary(
crate::ui::icons::MENU,
12.0,
@@ -817,10 +846,22 @@ fn header_menu(side: DockSide, open: bool, fill_on_current_layer: bool) -> Eleme
.padding([4, 8])
};
let popup = container(column![
item("Set all attributes ByLayer", GraphicAttributesMsg::SetAllByLayer),
item("Set all attributes ByBlock", GraphicAttributesMsg::SetAllByBlock),
item("Remove ByLayer / ByBlock", GraphicAttributesMsg::RemoveReferences),
item("Create Layer with active settings", GraphicAttributesMsg::CreateLayer),
item(
"Set all attributes ByLayer",
GraphicAttributesMsg::SetAllByLayer
),
item(
"Set all attributes ByBlock",
GraphicAttributesMsg::SetAllByBlock
),
item(
"Remove ByLayer / ByBlock",
GraphicAttributesMsg::RemoveReferences
),
item(
"Create Layer with active settings",
GraphicAttributesMsg::CreateLayer
),
container(iced::widget::rule::horizontal(1)).padding([2, 4]),
container(
iced::widget::checkbox(fill_on_current_layer)
@@ -944,7 +985,11 @@ fn preview_row<'a>(
})
.height(COMPACT_BUTTON_HEIGHT)
.padding([1, 3]);
let edit = tooltip(edit, text(tooltip_label).size(10), tooltip::Position::Bottom);
let edit = tooltip(
edit,
text(tooltip_label).size(10),
tooltip::Position::Bottom,
);
let edit: Element<'a, Message> = match flyout {
Some((popup, width, height)) => {
let mut drop_down = iced_aw::DropDown::new(edit, popup, true)
@@ -1011,8 +1056,14 @@ fn linetype_row<'a>(
open_menu,
COMPACT_BUTTON_HEIGHT,
vec![
("ByLayer".into(), msg(GraphicAttributesMsg::LineLinetype("ByLayer".into()))),
("ByBlock".into(), msg(GraphicAttributesMsg::LineLinetype("ByBlock".into()))),
(
"ByLayer".into(),
msg(GraphicAttributesMsg::LineLinetype("ByLayer".into())),
),
(
"ByBlock".into(),
msg(GraphicAttributesMsg::LineLinetype("ByBlock".into())),
),
],
);
row![crate::ui::wide_menu::wide_menu(combo, 220.0), more]
@@ -1108,8 +1159,14 @@ fn lineweight_field<'a>(
open_menu,
COMPACT_BUTTON_HEIGHT,
vec![
("ByLayer".into(), msg(GraphicAttributesMsg::LineLineweight(LineWeight::ByLayer))),
("ByBlock".into(), msg(GraphicAttributesMsg::LineLineweight(LineWeight::ByBlock))),
(
"ByLayer".into(),
msg(GraphicAttributesMsg::LineLineweight(LineWeight::ByLayer)),
),
(
"ByBlock".into(),
msg(GraphicAttributesMsg::LineLineweight(LineWeight::ByBlock)),
),
],
);
row![
@@ -1142,15 +1199,22 @@ fn line_section<'a>(
}
let layer = top_layer(document, handles, draw_depth).to_string();
let header = &document.header;
let (linetype, linetype_varies) = shared_value(document, handles, draw_depth, |c| {
c.linetype.clone()
})
.map_or_else(
|| (current_linetype_name(document).to_string(), false),
|(_, value, varies)| (if value.is_empty() { "ByLayer".into() } else { value }, varies),
);
let (scale, scale_varies) =
shared_value(document, handles, draw_depth, |c| c.linetype_scale).map_or(
let (linetype, linetype_varies) =
shared_value(document, handles, draw_depth, |c| c.linetype.clone()).map_or_else(
|| (current_linetype_name(document).to_string(), false),
|(_, value, varies)| {
(
if value.is_empty() {
"ByLayer".into()
} else {
value
},
varies,
)
},
);
let (scale, scale_varies) = shared_value(document, handles, draw_depth, |c| c.linetype_scale)
.map_or(
(header.current_entity_linetype_scale, false),
|(_, value, varies)| (value, varies),
);
@@ -1159,10 +1223,15 @@ fn line_section<'a>(
(LineWeight::from_value(header.current_line_weight), false),
|(_, value, varies)| (value, varies),
);
let color = color_info(document, handles, draw_depth)
.unwrap_or_else(|| current_color_info(document));
let color =
color_info(document, handles, draw_depth).unwrap_or_else(|| current_color_info(document));
let transparency = transparency_info(document, handles, draw_depth).unwrap_or_else(|| {
TransparencyInfo::new(document, &layer, document.current_entity_transparency(), false)
TransparencyInfo::new(
document,
&layer,
document.current_entity_transparency(),
false,
)
});
let continuous =
!linetype_varies && is_continuous(effective_linetype(document, &layer, &linetype));
-1
View File
@@ -737,7 +737,6 @@ fn name_tip<'a>(name: &'a str) -> Element<'a, Message> {
.into()
}
/// The layer-name field while a rename is open; a click that moves focus
/// elsewhere commits the typed name.
pub fn rename_input_id() -> iced::widget::Id {
+1 -1
View File
@@ -6,8 +6,8 @@ pub mod attribute_editor;
pub mod auto_constrain_settings;
pub mod block_definition;
pub mod block_edit_picker;
pub mod block_save_as;
pub mod block_palette;
pub mod block_save_as;
pub mod browser;
pub mod count_palette;
pub mod drafting_settings;
+3 -5
View File
@@ -1810,11 +1810,9 @@ pub fn view_window<'a>(
let files = column![
text(crate::t!("Files")).size(15),
Space::new().height(6),
text(crate::t!(
"Where the application keeps its own files."
))
.size(11)
.width(sizing.width),
text(crate::t!("Where the application keeps its own files."))
.size(11)
.width(sizing.width),
Space::new().height(16),
folder_row(crate::t!("Configuration"), folders.config.clone(), None),
Space::new().height(12),
+212 -87
View File
@@ -312,7 +312,10 @@ pub(crate) fn well_style(theme: &Theme) -> container::Style {
}
/// A titled card.
pub(crate) fn card<'a>(title: String, content: impl Into<Element<'a, Message>>) -> Element<'a, Message> {
pub(crate) fn card<'a>(
title: String,
content: impl Into<Element<'a, Message>>,
) -> Element<'a, Message> {
container(
column![
text(title.to_uppercase()).size(10).style(accent_text),
@@ -2212,12 +2215,27 @@ pub struct BgPreview {
pub fn bg_preview(path: &str) -> Option<BgPreview> {
let decoded = ::image::open(path.trim()).ok()?;
let size = [decoded.width(), decoded.height()];
let small = if size[0].max(size[1]) > 512 { decoded.thumbnail(512, 512) } else { decoded }.to_rgba8();
let handle = |pixels: ::image::RgbaImage| image::Handle::from_rgba(pixels.width(), pixels.height(), pixels.into_raw());
let small = if size[0].max(size[1]) > 512 {
decoded.thumbnail(512, 512)
} else {
decoded
}
.to_rgba8();
let handle = |pixels: ::image::RgbaImage| {
image::Handle::from_rgba(pixels.width(), pixels.height(), pixels.into_raw())
};
let flip_x = ::image::imageops::flip_horizontal(&small);
let flip_y = ::image::imageops::flip_vertical(&small);
let flip_xy = ::image::imageops::flip_vertical(&flip_x);
Some(BgPreview { size, handles: [handle(small), handle(flip_x), handle(flip_y), handle(flip_xy)] })
Some(BgPreview {
size,
handles: [
handle(small),
handle(flip_x),
handle(flip_y),
handle(flip_xy),
],
})
}
/// Image offsets the reference's Adjust Image sliders reach, in pixels.
@@ -2325,7 +2343,11 @@ pub fn view_background<'a>(
if state.position == BgPosition::Stretch {
// Filling the view; keeping the aspect ratio it covers
// the view and the overflow is cut off.
let fit = if state.aspect { iced::ContentFit::Cover } else { iced::ContentFit::Fill };
let fit = if state.aspect {
iced::ContentFit::Cover
} else {
iced::ContentFit::Fill
};
let handle = state.preview.as_ref().map_or_else(
|| image::Handle::from_path(state.image.trim()),
|preview| preview.handles[0].clone(),
@@ -2338,13 +2360,26 @@ pub fn view_background<'a>(
} else {
// The image at its size times its scale, moved by its
// offset, in a view of the drawing viewport's shape.
let parse = |v: &String, d: f64| v.trim().parse::<f64>().ok().filter(|v| v.is_finite()).unwrap_or(d);
let parse = |v: &String, d: f64| {
v.trim()
.parse::<f64>()
.ok()
.filter(|v| v.is_finite())
.unwrap_or(d)
};
let offset = [parse(&state.offset[0], 0.0), parse(&state.offset[1], 0.0)];
let scale = [0, 1].map(|k| {
let v = parse(&state.scale[k], state.scale_base[k]);
if v.abs() < 1e-9 { state.scale_base[k] } else { v }
if v.abs() < 1e-9 {
state.scale_base[k]
} else {
v
}
});
let [iw, ih] = state.preview.as_ref().map_or([1, 1], |preview| preview.size);
let [iw, ih] = state
.preview
.as_ref()
.map_or([1, 1], |preview| preview.size);
// A negative scale mirrors the image.
let mirrored = usize::from(scale[0] < 0.0) | usize::from(scale[1] < 0.0) << 1;
let handle = state.preview.as_ref().map_or_else(
@@ -2363,7 +2398,10 @@ pub fn view_background<'a>(
let x = size.width / 2.0 + offset[0] as f32 * factor - w / 2.0;
let y = size.height / 2.0 + offset[1] as f32 * factor - h / 2.0;
let (cols, rows) = if tile {
((size.width / w).ceil() as i32 + 1, (size.height / h).ceil() as i32 + 1)
(
(size.width / w).ceil() as i32 + 1,
(size.height / h).ceil() as i32 + 1,
)
} else {
(0, 0)
};
@@ -2375,7 +2413,10 @@ pub fn view_background<'a>(
let y0 = if tile { y - (y / h).ceil() * h } else { y };
for row_index in 0..=rows.min(60) {
for col_index in 0..=cols.min(60) {
let at = iced::Point::new(x0 + col_index as f32 * w, y0 + row_index as f32 * h);
let at = iced::Point::new(
x0 + col_index as f32 * w,
y0 + row_index as f32 * h,
);
layers = layers.push(
iced::widget::pin(
image(handle.clone())
@@ -2398,7 +2439,9 @@ pub fn view_background<'a>(
} else {
container(note(crate::tr!("view-background", "no-image")))
.center(Fill)
.style(fill(Background::Color(iced::Color::from_rgb8(0x1a, 0x1a, 0x1a))))
.style(fill(Background::Color(iced::Color::from_rgb8(
0x1a, 0x1a, 0x1a,
))))
.into()
}
}
@@ -2421,26 +2464,27 @@ pub fn view_background<'a>(
})
.width(Length::Fixed(92.0))
};
let color_row = |name: String, slot: u8, color: [u8; 3], enabled: bool| -> Element<'a, Message> {
let mut pick = button(text(crate::tr!("view-background", "select")).size(11))
.style(button_style(false))
.padding([4, 10]);
if enabled {
pick = pick.on_press(msg(PdfDialogMsg::BgPickColor(slot)));
}
row![
label(name, enabled),
swatch(color, 64.0, 22.0),
text(format!("{},{},{}", color[0], color[1], color[2]))
.size(11)
.style(muted_style),
Space::new().width(Fill),
pick,
]
.spacing(8)
.align_y(iced::Center)
.into()
};
let color_row =
|name: String, slot: u8, color: [u8; 3], enabled: bool| -> Element<'a, Message> {
let mut pick = button(text(crate::tr!("view-background", "select")).size(11))
.style(button_style(false))
.padding([4, 10]);
if enabled {
pick = pick.on_press(msg(PdfDialogMsg::BgPickColor(slot)));
}
row![
label(name, enabled),
swatch(color, 64.0, 22.0),
text(format!("{},{},{}", color[0], color[1], color[2]))
.size(11)
.style(muted_style),
Space::new().width(Fill),
pick,
]
.spacing(8)
.align_y(iced::Center)
.into()
};
let options: Element<'a, Message> = match state.kind {
BgKind::None => card(
crate::tr!("view-background", "info"),
@@ -2473,8 +2517,18 @@ pub fn view_background<'a>(
.spacing(8)
.align_y(iced::Center),
color_row(crate::tr!("view-background", "top"), 1, state.top, true),
color_row(crate::tr!("view-background", "middle"), 2, state.middle, state.three),
color_row(crate::tr!("view-background", "bottom"), 3, state.bottom, true),
color_row(
crate::tr!("view-background", "middle"),
2,
state.middle,
state.three
),
color_row(
crate::tr!("view-background", "bottom"),
3,
state.bottom,
true
),
]
.spacing(8),
),
@@ -2497,9 +2551,11 @@ pub fn view_background<'a>(
.align_y(iced::Center),
row![
label(crate::tr!("view-background", "position"), true),
pick_list(Some(state.position), BgPosition::ALL.to_vec(), |p: &BgPosition| {
p.to_string()
})
pick_list(
Some(state.position),
BgPosition::ALL.to_vec(),
|p: &BgPosition| { p.to_string() }
)
.on_select(|p| msg(PdfDialogMsg::BgPosition(p)))
.text_size(12)
.padding([4, 8])
@@ -2545,11 +2601,17 @@ fn adjust_card<'a>(state: &'a ViewBackgroundState) -> Element<'a, Message> {
if enabled {
muted_style(theme)
} else {
text::Style { color: Some(theme.palette().background.strong.color) }
text::Style {
color: Some(theme.palette().background.strong.color),
}
}
};
let spin = |field: u8| -> Element<'a, Message> {
let value = if field < 2 { &state.offset[field as usize] } else { &state.scale[field as usize - 2] };
let value = if field < 2 {
&state.offset[field as usize]
} else {
&state.scale[field as usize - 2]
};
let mut input = text_input("", value)
.size(11)
.padding([4, 8])
@@ -2583,7 +2645,10 @@ fn adjust_card<'a>(state: &'a ViewBackgroundState) -> Element<'a, Message> {
}
b
};
row![input, column![arrow(true), arrow(false)].spacing(1)].spacing(2).align_y(iced::Center).into()
row![input, column![arrow(true), arrow(false)].spacing(1)]
.spacing(2)
.align_y(iced::Center)
.into()
};
let axis = |name: &'static str| text(name).size(11).style(dim);
let line = |label: String, a: u8, b: u8, unit: bool| -> Element<'a, Message> {
@@ -2597,7 +2662,11 @@ fn adjust_card<'a>(state: &'a ViewBackgroundState) -> Element<'a, Message> {
.spacing(6)
.align_y(iced::Center);
if unit {
r = r.push(text(crate::tr!("view-background", "pixels")).size(11).style(dim));
r = r.push(
text(crate::tr!("view-background", "pixels"))
.size(11)
.style(dim),
);
}
r.into()
};
@@ -2610,9 +2679,15 @@ fn adjust_card<'a>(state: &'a ViewBackgroundState) -> Element<'a, Message> {
container(
column![
row![
text(crate::tr!("view-background", "adjust").to_uppercase()).size(10).style(move |theme: &Theme| {
if enabled { accent_text(theme) } else { dim(theme) }
}),
text(crate::tr!("view-background", "adjust").to_uppercase())
.size(10)
.style(move |theme: &Theme| {
if enabled {
accent_text(theme)
} else {
dim(theme)
}
}),
Space::new().width(Fill),
reset,
]
@@ -2653,11 +2728,16 @@ pub const IMAGE_ADJUST_DEFAULTS: [u8; 3] = [50, 50, 0];
impl ImageAdjustState {
pub fn new(handles: Vec<codec::Handle>, path: &str, values: [u8; 3], canvas: [u8; 3]) -> Self {
let name = std::path::Path::new(path.trim())
.file_name()
.map_or_else(|| path.trim().to_string(), |n| n.to_string_lossy().into_owned());
let name = std::path::Path::new(path.trim()).file_name().map_or_else(
|| path.trim().to_string(),
|n| n.to_string_lossy().into_owned(),
);
let source = crate::scene::model::image_model::resolve_image(path).and_then(|decoded| {
let full = ::image::RgbaImage::from_raw(decoded.width, decoded.height, decoded.pixels.to_vec())?;
let full = ::image::RgbaImage::from_raw(
decoded.width,
decoded.height,
decoded.pixels.to_vec(),
)?;
let small = if full.width().max(full.height()) > 512 {
::image::imageops::thumbnail(&full, 512, 512)
} else {
@@ -2690,7 +2770,10 @@ impl ImageAdjustState {
self.preview = self.source.as_ref().map(|(w, h, pixels)| {
// As the drawing shows it: brightness then contrast per channel,
// fade as the image's opacity over the drawing area.
let lut = crate::scene::model::image_model::brightness_contrast_lut(self.values[0], self.values[1]);
let lut = crate::scene::model::image_model::brightness_contrast_lut(
self.values[0],
self.values[1],
);
let opacity = 1.0 - f32::from(self.values[2]) / 100.0;
let mut out = Vec::with_capacity(pixels.len());
for (k, px) in pixels.chunks_exact(4).enumerate() {
@@ -2741,16 +2824,20 @@ pub fn image_adjust<'a>(
.width(Fill)
.height(Fill)
.into(),
None => container(text(crate::tr!("image-adjust", "no-preview")).size(11).style(muted_style))
.center(Fill)
.into(),
None => container(
text(crate::tr!("image-adjust", "no-preview"))
.size(11)
.style(muted_style),
)
.center(Fill)
.into(),
};
let divider = container(
container(Space::new().width(2.0).height(Fill)).style(|theme: &Theme| container::Style {
let divider = container(container(Space::new().width(2.0).height(Fill)).style(
|theme: &Theme| container::Style {
background: Some(Background::Color(theme.palette().primary.base.color)),
..Default::default()
}),
)
},
))
.center_x(Fill)
.height(Fill);
let badges = row![
@@ -2759,7 +2846,10 @@ pub fn image_adjust<'a>(
badge(crate::tr!("image-adjust", "after"), true),
]
.padding(8);
let mut layers = iced::widget::Stack::new().width(Fill).height(Fill).push(picture);
let mut layers = iced::widget::Stack::new()
.width(Fill)
.height(Fill)
.push(picture);
if state.preview.is_some() {
layers = layers.push(divider).push(badges);
}
@@ -2771,15 +2861,24 @@ pub fn image_adjust<'a>(
.clip(true)
.style(move |_: &Theme| container::Style {
background: Some(Background::Color(canvas)),
border: Border { radius: 5.0.into(), ..Default::default() },
border: Border {
radius: 5.0.into(),
..Default::default()
},
..Default::default()
}),
);
let ramp = |row: u8| -> Background {
let (from, to) = match row {
// Contrast: grey, the flat image its zero gives.
1 => (iced::Color::from_rgb8(0x77, 0x77, 0x77), iced::Color::from_rgb8(0x77, 0x77, 0x77)),
_ => (iced::Color::from_rgb8(0x22, 0x22, 0x22), iced::Color::from_rgb8(0xee, 0xee, 0xee)),
1 => (
iced::Color::from_rgb8(0x77, 0x77, 0x77),
iced::Color::from_rgb8(0x77, 0x77, 0x77),
),
_ => (
iced::Color::from_rgb8(0x22, 0x22, 0x22),
iced::Color::from_rgb8(0xee, 0xee, 0xee),
),
};
Background::Gradient(iced::Gradient::Linear(
iced::gradient::Linear::new(iced::Radians(std::f32::consts::FRAC_PI_2))
@@ -2789,30 +2888,41 @@ pub fn image_adjust<'a>(
};
let line = |row: u8, label: String| -> Element<'a, Message> {
let k = row as usize;
let bar = container(container(Space::new()).width(Fill).height(8.0).style(move |_: &Theme| {
container::Style {
let bar = container(container(Space::new()).width(Fill).height(8.0).style(
move |_: &Theme| container::Style {
background: Some(ramp(row)),
border: Border { radius: 4.0.into(), ..Default::default() },
border: Border {
radius: 4.0.into(),
..Default::default()
},
..Default::default()
}
}))
},
))
.center_y(16.0)
.width(Fill);
let slide = iced::widget::slider(0..=100u8, state.values[k], move |v| msg(PdfDialogMsg::IaValue(row, v)))
.height(16.0)
.style(|theme: &Theme, _| iced::widget::slider::Style {
rail: iced::widget::slider::Rail {
backgrounds: (iced::Color::TRANSPARENT.into(), iced::Color::TRANSPARENT.into()),
width: 0.0,
border: Border::default(),
let slide = iced::widget::slider(0..=100u8, state.values[k], move |v| {
msg(PdfDialogMsg::IaValue(row, v))
})
.height(16.0)
.style(|theme: &Theme, _| iced::widget::slider::Style {
rail: iced::widget::slider::Rail {
backgrounds: (
iced::Color::TRANSPARENT.into(),
iced::Color::TRANSPARENT.into(),
),
width: 0.0,
border: Border::default(),
},
handle: iced::widget::slider::Handle {
shape: iced::widget::slider::HandleShape::Rectangle {
width: 4,
border_radius: 2.0.into(),
},
handle: iced::widget::slider::Handle {
shape: iced::widget::slider::HandleShape::Rectangle { width: 4, border_radius: 2.0.into() },
background: theme.palette().primary.base.color.into(),
border_width: 0.0,
border_color: iced::Color::TRANSPARENT,
},
});
background: theme.palette().primary.base.color.into(),
border_width: 0.0,
border_color: iced::Color::TRANSPARENT,
},
});
let step = |dir: i8| {
button(text(if dir < 0 { "\u{2212}" } else { "+" }).size(12))
.on_press(msg(PdfDialogMsg::IaStep(row, dir)))
@@ -2829,9 +2939,13 @@ pub fn image_adjust<'a>(
row![
text(label).size(11).width(Length::Fixed(72.0)),
iced::widget::Stack::new().width(Fill).push(bar).push(slide),
container(row![step(-1), value, step(1)].spacing(2).align_y(iced::Center))
.padding(2)
.style(well_style),
container(
row![step(-1), value, step(1)]
.spacing(2)
.align_y(iced::Center)
)
.padding(2)
.style(well_style),
]
.spacing(10)
.align_y(iced::Center)
@@ -2843,18 +2957,29 @@ pub fn image_adjust<'a>(
line(0, crate::tr!("image-adjust", "brightness")),
line(1, crate::tr!("image-adjust", "contrast")),
line(2, crate::tr!("image-adjust", "fade")),
text(crate::tr!("image-adjust", "hint")).size(10).style(muted_style),
text(crate::tr!("image-adjust", "hint"))
.size(10)
.style(muted_style),
]
.spacing(10),
);
let reset = button(text(crate::tr!("image-adjust", "reset")).size(11).style(accent_text))
.on_press(msg(PdfDialogMsg::IaReset))
.style(button::text)
.padding([5, 4]);
let reset = button(
text(crate::tr!("image-adjust", "reset"))
.size(11)
.style(accent_text),
)
.on_press(msg(PdfDialogMsg::IaReset))
.style(button::text)
.padding([5, 4]);
column![
preview,
adjust,
footer("imageadjust", Some(reset.into()), crate::tr!("image-adjust", "apply").into(), PdfDialogMsg::IaApply),
footer(
"imageadjust",
Some(reset.into()),
crate::tr!("image-adjust", "apply").into(),
PdfDialogMsg::IaApply
),
]
.spacing(10)
.padding([10, 12])
+21 -9
View File
@@ -153,25 +153,37 @@ pub fn view<'a>(
const MAX: usize = 64;
let count = path.chars().count();
let shown = if count > MAX {
format!("…{}", path.chars().skip(count - (MAX - 1)).collect::<String>())
format!(
"…{}",
path.chars().skip(count - (MAX - 1)).collect::<String>()
)
} else {
path.to_string()
};
about = about.push(
text(format!("{} {}", crate::tr!("ref-edit", "dialog-path"), shown))
.size(11)
.style(muted_style),
text(format!(
"{} {}",
crate::tr!("ref-edit", "dialog-path"),
shown
))
.size(11)
.style(muted_style),
);
}
let reference = card(
crate::tr!("ref-edit", "dialog-reference"),
row![
preview,
column![iced::widget::scrollable(chips).direction(
iced::widget::scrollable::Direction::Horizontal(
iced::widget::scrollable::Scrollbar::new().width(4).scroller_width(4)
)
), about]
column![
iced::widget::scrollable(chips).direction(
iced::widget::scrollable::Direction::Horizontal(
iced::widget::scrollable::Scrollbar::new()
.width(4)
.scroller_width(4)
)
),
about
]
.spacing(8)
.width(Fill)
]
+4 -2
View File
@@ -1070,8 +1070,10 @@ impl<'a> Widget<Message, Theme, Renderer> for PosReport<'a> {
viewport: &Rectangle,
) {
DD_BOUNDS.with(|m| {
m.borrow_mut()
.insert(self.id.to_string(), (layout.bounds(), FRAME.with(Cell::get)));
m.borrow_mut().insert(
self.id.to_string(),
(layout.bounds(), FRAME.with(Cell::get)),
);
});
self.child.as_widget().draw(
&tree.children[0],