style: apply cargo fmt across workspace

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

No files matched your search

+12 -12
View File
@@ -346,26 +346,26 @@ pub(super) fn dyn_component_value(
) && relative
&& !comma_cartesian;
match f.component {
DynComponent::X if relative => crate::entities::common::format_length(if wh { dx.abs() } else { dx }),
DynComponent::Y if relative => crate::entities::common::format_length(if wh { dy.abs() } else { dy }),
DynComponent::X if relative => {
crate::entities::common::format_length(if wh { dx.abs() } else { dx })
}
DynComponent::Y if relative => {
crate::entities::common::format_length(if wh { dy.abs() } else { dy })
}
DynComponent::Z if relative => crate::entities::common::format_length(0.0),
DynComponent::X => crate::entities::common::format_length(p.x),
DynComponent::Y => crate::entities::common::format_length(p.y),
DynComponent::Z => crate::entities::common::format_length(p.z),
// Scaled by the role so a diameter box reads twice the radius.
DynComponent::Distance => {
crate::entities::common::format_length(
(dx * dx + dy * dy).sqrt() * f.role.value_scale() as f64,
)
}
DynComponent::Distance => crate::entities::common::format_length(
(dx * dx + dy * dy).sqrt() * f.role.value_scale() as f64,
),
// Shared rule: unsigned magnitude of the short angle, so CW (below the
// reference axis) reads positive (e.g. 30°, not -30°/330°). The
// committed value stays signed (see dyn_resolve_point).
DynComponent::Angle => {
crate::entities::common::format_angle(
(crate::command::dyn_display_angle_deg(dy.atan2(dx) as f32) as f64).to_radians(),
)
}
DynComponent::Angle => crate::entities::common::format_angle(
(crate::command::dyn_display_angle_deg(dy.atan2(dx) as f32) as f64).to_radians(),
),
// Typed-only scalar — no geometric value to track when empty.
DynComponent::Scalar => String::new(),
}
+51 -45
View File
@@ -625,7 +625,10 @@ bg={bg_ms:.1}ms n={view_count}"
let control_polygon = tab.selected_handle.and_then(|handle| {
let spline = match tab.scene.document.get_entity(handle) {
Some(codec::EntityType::Spline(spline))
if crate::entities::spline::shows_control_vertices(spline) => spline,
if crate::entities::spline::shows_control_vertices(spline) =>
{
spline
}
_ => return None,
};
if tab
@@ -797,7 +800,7 @@ bg={bg_ms:.1}ms n={view_count}"
&& b.y.is_finite()
&& a.x.is_finite()
&& a.y.is_finite())
.then_some((b, a))
.then_some((b, a))
})
.collect()
}
@@ -1131,8 +1134,12 @@ bg={bg_ms:.1}ms n={view_count}"
(None, _) if rectangle_values.is_some() => {
let (width, height) = rectangle_values.unwrap();
match f.role {
crate::command::DynRole::Width => crate::entities::common::format_length(width),
crate::command::DynRole::Height => crate::entities::common::format_length(height),
crate::command::DynRole::Width => {
crate::entities::common::format_length(width)
}
crate::command::DynRole::Height => {
crate::entities::common::format_length(height)
}
_ => String::new(),
}
}
@@ -1673,8 +1680,10 @@ bg={bg_ms:.1}ms n={view_count}"
// Count mode: a blue frame round the drawing and the count toolbar.
if let (Some(mode), false) = (tab.count.as_ref(), tab.is_start) {
viewport_stack = viewport_stack.push(crate::ui::window::count_palette::border());
viewport_stack = viewport_stack
.push(crate::ui::window::count_palette::toolbar(mode, &tab.scene.document));
viewport_stack = viewport_stack.push(crate::ui::window::count_palette::toolbar(
mode,
&tab.scene.document,
));
}
// Reserve the overlaid command line when placing cursor-anchored panels.
@@ -1887,9 +1896,7 @@ bg={bg_ms:.1}ms n={view_count}"
// hovered or unpinned panel expands to the full column height on top.
// Single source of truth with dock_visible_len (#57): one new panel
// updated in only one place used to break drag math vs rendering.
let visible_panel = |id: crate::ui::dock::PanelId| -> bool {
self.dock_panel_visible(id)
};
let visible_panel = |id: crate::ui::dock::PanelId| -> bool { self.dock_panel_visible(id) };
let edge_stack = |side: crate::app::config::DockSide| -> Option<Element<'_, Message>> {
let ids: Vec<crate::ui::dock::PanelId> = match side {
crate::app::config::DockSide::Left => self.dock.left.clone(),
@@ -1915,8 +1922,7 @@ bg={bg_ms:.1}ms n={view_count}"
// value is numeric input, not the prefix of a new command (for example,
// `3` must not open the 3DALIGN / 3DARRAY suggestions).
let allow_autocomplete = self.grip_pending.is_none()
&& (tab.active_cmd.is_none()
|| self.command_line.has_contextual_suggestions());
&& (tab.active_cmd.is_none() || self.command_line.has_contextual_suggestions());
// Dynamic input captures keystrokes when its fields are showing,
// so the command-line field must release focus / its on_input.
// The MText preview also captures keystrokes (typing edits it), so the
@@ -2323,18 +2329,18 @@ bg={bg_ms:.1}ms n={view_count}"
// otherwise an empty slice short-circuits the overlay gate
// (`dropdown_overlay` returns `None` for empty labels anyway).
let open_dropdown = self.ribbon.open_dropdown.as_deref();
let undo_labels: Vec<String> =
if open_dropdown == Some(crate::ui::ribbon::UNDO_HISTORY_ID) {
history_dropdown_labels(&self.tabs[self.active_tab].history.undo_stack)
} else {
Vec::new()
};
let redo_labels: Vec<String> =
if open_dropdown == Some(crate::ui::ribbon::REDO_HISTORY_ID) {
history_dropdown_labels(&self.tabs[self.active_tab].history.redo_stack)
} else {
Vec::new()
};
let undo_labels: Vec<String> = if open_dropdown == Some(crate::ui::ribbon::UNDO_HISTORY_ID)
{
history_dropdown_labels(&self.tabs[self.active_tab].history.undo_stack)
} else {
Vec::new()
};
let redo_labels: Vec<String> = if open_dropdown == Some(crate::ui::ribbon::REDO_HISTORY_ID)
{
history_dropdown_labels(&self.tabs[self.active_tab].history.redo_stack)
} else {
Vec::new()
};
let gallery_open = open_dropdown == Some(crate::modules::insert::insert_block::GALLERY_ID)
&& !self.tabs[self.active_tab].is_start;
let dropdown_layer: Element<'_, Message> = if gallery_open {
@@ -2345,16 +2351,15 @@ bg={bg_ms:.1}ms n={view_count}"
self.win_size.0,
)
} else {
self
.ribbon
.dropdown_overlay(
&undo_labels,
&redo_labels,
self.win_size,
self.tabs[self.active_tab].is_start,
&self.recent_colors,
)
.unwrap_or_else(|| iced::widget::Space::new().width(0).height(0).into())
self.ribbon
.dropdown_overlay(
&undo_labels,
&redo_labels,
self.win_size,
self.tabs[self.active_tab].is_start,
&self.recent_colors,
)
.unwrap_or_else(|| iced::widget::Space::new().width(0).height(0).into())
};
let snap_override_layer: Element<'_, Message> = if let Some(pos) = self.snap_override_popup
@@ -2719,10 +2724,9 @@ impl OpenCADStudio {
&& modifiers.alt()
&& !modifiers.control()
&& !modifiers.logo();
let shortcut_modifier = (modifiers.control()
|| modifiers.alt()
|| modifiers.logo())
&& !(types_glyph && (altgr || mac_option));
let shortcut_modifier =
(modifiers.control() || modifiers.alt() || modifiers.logo())
&& !(types_glyph && (altgr || mac_option));
// Any key that produces a printable glyph types it,
// even when its logical key resolves to navigation
// (NumLock-on Numpad8 / Numpad2 arrive as
@@ -2832,7 +2836,9 @@ impl OpenCADStudio {
} else {
Subscription::none()
},
self.spacemouse.subscription().map(|_| Message::SpaceMouseWake),
self.spacemouse
.subscription()
.map(|_| Message::SpaceMouseWake),
crate::input::trackpad::subscription().map(Message::TrackpadPinch),
event::listen_with(|event, _, id| match event {
iced::Event::Window(window::Event::Focused) => {
@@ -3023,15 +3029,15 @@ impl OpenCADStudio {
crate::ui::dock::PanelId::BlockPalette => {
crate::ui::window::block_palette::view(&self.block_palette, width, auto_collapse)
}
crate::ui::dock::PanelId::ExternalReferences => self.xref_manager.view(
width,
auto_collapse,
tab.xref_missing,
&tab.scene.document,
),
crate::ui::dock::PanelId::ExternalReferences => {
self.xref_manager
.view(width, auto_collapse, tab.xref_missing, &tab.scene.document)
}
crate::ui::dock::PanelId::Browser => crate::ui::window::browser::view(
&tab.scene.document,
tab.sketch_session.as_ref().map(|session| session.name.as_str()),
tab.sketch_session
.as_ref()
.map(|session| session.name.as_str()),
width,
auto_collapse,
),
+783 -793
View File
File diff suppressed because it is too large. Load diff
+189 -216
View File
@@ -1,4 +1,8 @@
use super::super::Message;
use crate::t;
use crate::ui::popup::context_menu::{
ContextMenu, MenuIcon, MenuItem, MenuRow, MENU_PAD_TOP, MENU_ROW_H,
};
use iced::advanced::layout;
use iced::advanced::mouse;
use iced::advanced::overlay;
@@ -9,9 +13,9 @@ use iced::widget::{
button, checkbox, column, container, mouse_area, row, scrollable, stack, text, text_input,
Space,
};
use iced::{Background, Border, Color, Element, Event, Fill, Length, Rectangle, Size, Theme, Vector};
use crate::t;
use crate::ui::popup::context_menu::{ContextMenu, MenuIcon, MenuItem, MenuRow, MENU_PAD_TOP, MENU_ROW_H};
use iced::{
Background, Border, Color, Element, Event, Fill, Length, Rectangle, Size, Theme, Vector,
};
pub(super) fn position_canvas_overlay<'a>(
anchor: iced::Point,
@@ -48,13 +52,13 @@ pub(super) fn text_inline_overlay(
.style(move |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: 5.0.into(),
},
..Default::default()
background: Some(Background::Color(palette.background.weak.color)),
border: Border {
color: palette.background.neutral.color,
width: 1.0,
radius: 5.0.into(),
},
..Default::default()
}
})
.padding(4);
@@ -246,10 +250,7 @@ impl iced::widget::canvas::Program<Message> for MTextPreview {
iced::Point::new(p0.x.min(p1.x), p0.y.min(p1.y)),
iced::Size::new((p1.x - p0.x).abs(), (p1.y - p0.y).abs()),
);
frame.fill(
&rect,
theme.palette().primary.base.color.scale_alpha(0.45),
);
frame.fill(&rect, theme.palette().primary.base.color.scale_alpha(0.45));
}
}
}
@@ -380,12 +381,8 @@ pub(super) fn mtext_editor_overlay<'a>(
writing_area_px,
(writing_area_px * 0.5).max(1.0),
);
let content = crate::ui::modal::intrinsic(
measurement,
content,
iced::Size::INFINITE,
modal_resize,
);
let content =
crate::ui::modal::intrinsic(measurement, content, iced::Size::INFINITE, modal_resize);
crate::ui::modal::modal(
iced::widget::Space::new().width(Fill).height(Fill),
@@ -421,15 +418,15 @@ fn mtext_editor_content<'a>(
_ => 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(),
},
shadow: iced::Shadow::default(),
snap: false,
background: Some(Background::Color(pair.color)),
text_color: pair.text,
border: Border {
color: palette.background.neutral.color,
width: 1.0,
radius: 3.0.into(),
},
shadow: iced::Shadow::default(),
snap: false,
}
};
let icon_btn = move |bytes: &'static [u8], msg: Message| -> Element<'static, Message> {
@@ -459,14 +456,12 @@ fn mtext_editor_content<'a>(
} else {
styles.to_vec()
};
let style_pl = iced::widget::pick_list(
Some(ed.style.clone()),
style_opts,
|value| value.to_string(),
)
.on_select(Message::MTextStyle)
.text_size(11)
.width(iced::Length::Fixed(96.0));
let style_pl = iced::widget::pick_list(Some(ed.style.clone()), style_opts, |value| {
value.to_string()
})
.on_select(Message::MTextStyle)
.text_size(11)
.width(iced::Length::Fixed(96.0));
let annotative = checkbox(ed.annotative)
.on_toggle(Message::MTextAnnotative)
.size(14);
@@ -749,11 +744,14 @@ fn mtext_editor_content<'a>(
let preview_scale = ed.preview_scale();
let slider_min = 1e-6_f64;
let slider_max =
f64::from(writing_area_px / preview_scale).max(slider_min * 2.0);
let slider_max = f64::from(writing_area_px / preview_scale).max(slider_min * 2.0);
let width_slider = column![
row![
text(t!("Width: %{value}", value = format!("{:.3}", ed.rect_width))).size(11),
text(t!(
"Width: %{value}",
value = format!("{:.3}", ed.rect_width)
))
.size(11),
Space::new().width(width),
text(format!("{:.0}%", ed.rect_width / slider_max * 100.0)).size(11),
]
@@ -785,13 +783,13 @@ fn mtext_editor_content<'a>(
.style(move |theme: &Theme| {
let palette = theme.palette();
container::Style {
background: Some(Background::Color(palette.background.base.color)),
border: Border {
color: palette.background.neutral.color,
width: 1.0,
radius: 3.0.into(),
},
..Default::default()
background: Some(Background::Color(palette.background.base.color)),
border: Border {
color: palette.background.neutral.color,
width: 1.0,
radius: 3.0.into(),
},
..Default::default()
}
})
.padding(2)
@@ -827,9 +825,7 @@ fn mtext_editor_content<'a>(
// can be wider than the editor; size the canvas to the real content
// width and let the scroll area pan horizontally to reach later columns.
let content_w = if maxx >= minx {
((maxx - minx).max(ed.rect_width as f32) * scale
+ 2.0 * MTEXT_PREVIEW_PAD)
.max(40.0)
((maxx - minx).max(ed.rect_width as f32) * scale + 2.0 * MTEXT_PREVIEW_PAD).max(40.0)
} else {
ed.rect_width as f32 * scale + 2.0 * MTEXT_PREVIEW_PAD
};
@@ -861,9 +857,9 @@ fn mtext_editor_content<'a>(
.width(width)
.height(preview_height),
)
.style(move |theme: &Theme| {
let palette = theme.palette();
container::Style {
.style(move |theme: &Theme| {
let palette = theme.palette();
container::Style {
background: Some(Background::Color(palette.background.base.color)),
border: Border {
color: palette.background.neutral.color,
@@ -871,12 +867,12 @@ fn mtext_editor_content<'a>(
radius: 3.0.into(),
},
..Default::default()
}
})
.padding(2)
.width(width)
.height(preview_height)
.into()
}
})
.padding(2)
.width(width)
.height(preview_height)
.into()
};
// ── Top action bar: Apply keeps editing; Close saves and exits. Escape
@@ -885,14 +881,16 @@ fn mtext_editor_content<'a>(
row![
iced::widget::Space::new().width(width),
crate::ui::style::style_manager::tb_button(t!("Apply"), Message::MTextApply, true),
crate::ui::style::style_manager::tb_button(t!("Close Text Editor"), Message::MTextOk, true),
crate::ui::style::style_manager::tb_button(
t!("Close Text Editor"),
Message::MTextOk,
true
),
]
.align_y(iced::Alignment::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(width)
@@ -1145,7 +1143,10 @@ fn context_menu_gutter(icon: Option<MenuIcon>, enabled: bool) -> Element<'static
Some(MenuIcon::Chrome(bytes)) => chrome(bytes),
Some(MenuIcon::Tool(bytes)) if enabled => icons::semantic(bytes, MENU_ICON_SIZE),
Some(MenuIcon::Tool(bytes)) => icons::semantic_disabled(bytes, MENU_ICON_SIZE),
None => iced::widget::Space::new().width(MENU_ICON_SIZE).height(MENU_ICON_SIZE).into(),
None => iced::widget::Space::new()
.width(MENU_ICON_SIZE)
.height(MENU_ICON_SIZE)
.into(),
};
container(cell)
.width(Length::Fixed(MENU_GUTTER_W))
@@ -1168,9 +1169,7 @@ pub(super) fn viewport_context_menu_overlay(
let sep = || -> Element<'static, Message> {
container(iced::widget::Space::new().width(Fill).height(1))
.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(Fill)
@@ -1225,7 +1224,9 @@ pub(super) fn viewport_context_menu_overlay(
})
.width(Fill)
.height(Length::Fixed(MENU_ROW_H))
.style(move |theme: &Theme, status| context_menu_row_style(theme, status, is_hl));
.style(move |theme: &Theme, status| {
context_menu_row_style(theme, status, is_hl)
});
if enabled {
btn = btn.on_press(Message::ContextMenuSubmenuToggle(*id));
}
@@ -1243,13 +1244,12 @@ pub(super) fn viewport_context_menu_overlay(
}
let menu_col = column(items).spacing(0).width(Length::Fixed(menu.width));
let menu_col = scrollable(menu_col)
.height(Length::Shrink)
.direction(scrollable::Direction::Vertical(
scrollable::Scrollbar::new()
.width(8)
.scroller_width(6),
));
let menu_col =
scrollable(menu_col)
.height(Length::Shrink)
.direction(scrollable::Direction::Vertical(
scrollable::Scrollbar::new().width(8).scroller_width(6),
));
let panel = container(menu_col)
.style(container::bordered_box)
@@ -1285,23 +1285,19 @@ fn context_menu_row(item: &MenuItem, indent: f32, highlighted: bool) -> Element<
.spacing(4)
.align_y(iced::Center);
if let Some(hint) = item.hint.as_ref() {
content = content
.push(iced::widget::Space::new().width(Fill))
.push(
text(hint.clone())
.size(11)
.style(move |theme: &Theme| {
let palette = theme.palette();
let base = if highlighted {
palette.primary.strong.text
} else {
palette.background.base.text
};
iced::widget::text::Style {
color: Some(base.scale_alpha(if enabled { 0.6 } else { 0.35 })),
}
}),
);
content = content.push(iced::widget::Space::new().width(Fill)).push(
text(hint.clone()).size(11).style(move |theme: &Theme| {
let palette = theme.palette();
let base = if highlighted {
palette.primary.strong.text
} else {
palette.background.base.text
};
iced::widget::text::Style {
color: Some(base.scale_alpha(if enabled { 0.6 } else { 0.35 })),
}
}),
);
}
let mut btn = button(content)
.padding(iced::Padding {
@@ -1321,7 +1317,11 @@ fn context_menu_row(item: &MenuItem, indent: f32, highlighted: bool) -> Element<
/// Row colours: keyboard highlight uses the accent (as the grip popup does),
/// hover the subtle background tint, disabled rows faded text.
fn context_menu_row_style(theme: &Theme, status: button::Status, highlighted: bool) -> button::Style {
fn context_menu_row_style(
theme: &Theme,
status: button::Status,
highlighted: bool,
) -> button::Style {
let palette = theme.palette();
let (background, text_color) = if highlighted {
(
@@ -1357,54 +1357,49 @@ fn context_menu_row_style(theme: &Theme, status: button::Status, highlighted: bo
pub(super) fn snap_override_overlay(pos: iced::Point) -> Element<'static, Message> {
const COLS: usize = 4;
let cell_icon = |icon: &'static [u8], label: String, msg: Message| -> Element<'static, Message> {
let icon = container(crate::ui::icons::themed::<Message>(icon, 16.0))
.width(26)
.height(26)
.align_x(iced::Center)
.align_y(iced::Center);
let btn = button(icon)
.on_press(msg)
.style(|theme: &Theme, status| button::Style {
background: matches!(
status,
button::Status::Hovered | button::Status::Pressed
)
.then_some(Background::Color(
theme.palette().primary.weak.color
)),
border: Border::default(),
text_color: theme.palette().background.base.text,
..Default::default()
})
.padding(2);
iced::widget::tooltip(
btn,
container(text(label).size(11))
.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: 2.0.into(),
},
text_color: Some(palette.background.strong.text),
let cell_icon =
|icon: &'static [u8], label: String, msg: Message| -> Element<'static, Message> {
let icon = container(crate::ui::icons::themed::<Message>(icon, 16.0))
.width(26)
.height(26)
.align_x(iced::Center)
.align_y(iced::Center);
let btn = button(icon)
.on_press(msg)
.style(|theme: &Theme, status| button::Style {
background: matches!(status, button::Status::Hovered | button::Status::Pressed)
.then_some(Background::Color(theme.palette().primary.weak.color)),
border: Border::default(),
text_color: theme.palette().background.base.text,
..Default::default()
}
})
.padding([2, 6]),
iced::widget::tooltip::Position::Bottom,
)
.into()
};
.padding(2);
iced::widget::tooltip(
btn,
container(text(label).size(11))
.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: 2.0.into(),
},
text_color: Some(palette.background.strong.text),
..Default::default()
}
})
.padding([2, 6]),
iced::widget::tooltip::Position::Bottom,
)
.into()
};
// MTP (`_M2P`) goes last, after Parallel: two picks, so not a
// `SnapType`, but same icon-only cell with hover tooltip.
let mut cells: Vec<Element<'static, Message>> = Vec::with_capacity(
crate::snap::ALL_SNAP_MODES.len() + 1,
);
let mut cells: Vec<Element<'static, Message>> =
Vec::with_capacity(crate::snap::ALL_SNAP_MODES.len() + 1);
for &(snap_type, _glyph, label) in crate::snap::ALL_SNAP_MODES {
cells.push(cell_icon(
crate::ui::icons::osnap(snap_type),
@@ -1431,13 +1426,13 @@ pub(super) fn snap_override_overlay(pos: iced::Point) -> Element<'static, Messag
.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: 4.0.into(),
},
..Default::default()
background: Some(Background::Color(palette.background.weak.color)),
border: Border {
color: palette.background.neutral.color,
width: 1.0,
radius: 4.0.into(),
},
..Default::default()
}
})
.padding(4);
@@ -1484,12 +1479,8 @@ pub(super) fn qselect_overlay<'a>(
candidate_count,
crate::ui::modal::ModalSizing::FILL,
);
let content = crate::ui::modal::intrinsic(
measurement,
content,
iced::Size::INFINITE,
modal_resize,
);
let content =
crate::ui::modal::intrinsic(measurement, content, iced::Size::INFINITE, modal_resize);
crate::ui::modal::modal(
Space::new().width(Fill).height(Fill),
@@ -1508,8 +1499,8 @@ fn qselect_content<'a>(
candidate_count: usize,
sizing: crate::ui::modal::ModalSizing,
) -> Element<'a, Message> {
use iced::widget::{checkbox, rule};
use crate::ui::style::form::{dialog_button, dialog_button_styled_opt, form_radio};
use iced::widget::{checkbox, rule};
let mut type_options: Vec<String> = vec![QSELECT_ANY_TYPE.to_string()];
type_options.extend(types.iter().cloned());
@@ -1521,13 +1512,12 @@ fn qselect_content<'a>(
}];
prop_options.extend(properties.iter().cloned());
let number_property = state.property.as_ref().is_some_and(|property| {
matches!(property.editor, crate::app::QSelectValueEditor::Number)
});
let mut op_options: Vec<crate::app::QSelectOp> = vec![
crate::app::QSelectOp::Eq,
crate::app::QSelectOp::Neq,
];
let number_property = state
.property
.as_ref()
.is_some_and(|property| matches!(property.editor, crate::app::QSelectValueEditor::Number));
let mut op_options: Vec<crate::app::QSelectOp> =
vec![crate::app::QSelectOp::Eq, crate::app::QSelectOp::Neq];
if number_property {
op_options.push(crate::app::QSelectOp::Gt);
op_options.push(crate::app::QSelectOp::Lt);
@@ -1560,35 +1550,30 @@ fn qselect_content<'a>(
iced::Length::Shrink
};
let label = |s: std::borrow::Cow<'static, str>| {
text(s)
.size(12)
.width(iced::Length::Fixed(112.0))
};
let label =
|s: std::borrow::Cow<'static, str>| text(s).size(12).width(iced::Length::Fixed(112.0));
let section_label = |s: std::borrow::Cow<'static, str>| {
text(s).size(11).style(|theme: &Theme| iced::widget::text::Style {
color: Some(theme.palette().background.base.text.scale_alpha(0.65)),
})
text(s)
.size(11)
.style(|theme: &Theme| iced::widget::text::Style {
color: Some(theme.palette().background.base.text.scale_alpha(0.65)),
})
};
let value_editor: Element<'a, Message> = match state.property.as_ref() {
Some(property) => match &property.editor {
crate::app::QSelectValueEditor::Choice(options) => {
let selected = (!state.value.is_empty()).then(|| state.value.clone());
let picker = iced::widget::pick_list(
selected,
options.clone(),
|value| value.to_string(),
)
.width(field_width);
let picker =
iced::widget::pick_list(selected, options.clone(), |value| value.to_string())
.width(field_width);
if value_enabled {
picker.on_select(Message::QSelectSetValue).into()
} else {
picker.into()
}
}
crate::app::QSelectValueEditor::Text
| crate::app::QSelectValueEditor::Number => {
crate::app::QSelectValueEditor::Text | crate::app::QSelectValueEditor::Number => {
let mut input = text_input("", &state.value).size(12).width(field_width);
if value_enabled {
input = input.on_input(Message::QSelectSetValue);
@@ -1601,7 +1586,8 @@ fn qselect_content<'a>(
let derived_error = if candidate_count == 0 {
Some(crate::t!("No objects are available in this scope.").into_owned())
} else if value_enabled && number_property
} else if value_enabled
&& number_property
&& crate::entities::common::parse_f64(&state.value).is_none()
{
Some(crate::t!("Enter a valid number.").into_owned())
@@ -1612,8 +1598,10 @@ fn qselect_content<'a>(
&& state.value.is_empty()
{
Some(crate::t!("Choose a value.").into_owned())
} else if matches!(state.operator, crate::app::QSelectOp::Gt | crate::app::QSelectOp::Lt)
&& !number_property
} else if matches!(
state.operator,
crate::app::QSelectOp::Gt | crate::app::QSelectOp::Lt
) && !number_property
{
Some(crate::t!("This operator requires a numeric property.").into_owned())
} else {
@@ -1625,13 +1613,10 @@ fn qselect_content<'a>(
crate::app::QSelectScope::CurrentSpace,
crate::app::QSelectScope::CurrentSelection,
];
let scope_picker = iced::widget::pick_list(
Some(state.scope),
scope_options,
|value| value.to_string(),
)
.on_select(Message::QSelectSetScope)
.width(field_width);
let scope_picker =
iced::widget::pick_list(Some(state.scope), scope_options, |value| value.to_string())
.on_select(Message::QSelectSetScope)
.width(field_width);
let mut append = checkbox(state.append).size(14);
if matches!(state.scope, crate::app::QSelectScope::CurrentSpace) {
@@ -1665,19 +1650,15 @@ fn qselect_content<'a>(
Space::new().height(5),
row![
label(t!("Object type:")),
iced::widget::pick_list(
Some(type_sel),
type_options,
|value| t!(value).into_owned(),
)
.on_select(|s: String| {
if s == QSELECT_ANY_TYPE {
Message::QSelectSetType(None)
} else {
Message::QSelectSetType(Some(s))
}
})
.width(field_width),
iced::widget::pick_list(Some(type_sel), type_options, |value| t!(value).into_owned(),)
.on_select(|s: String| {
if s == QSELECT_ANY_TYPE {
Message::QSelectSetType(None)
} else {
Message::QSelectSetType(Some(s))
}
})
.width(field_width),
]
.align_y(iced::Alignment::Center)
.spacing(8)
@@ -1685,19 +1666,15 @@ fn qselect_content<'a>(
Space::new().height(6),
row![
label(t!("Property:")),
iced::widget::pick_list(
Some(prop_sel),
prop_options,
|value| value.to_string(),
)
.on_select(|p: crate::app::QSelectPropertyChoice| {
if p.field.is_empty() {
Message::QSelectSetProperty(None)
} else {
Message::QSelectSetProperty(Some(p))
}
})
.width(field_width),
iced::widget::pick_list(Some(prop_sel), prop_options, |value| value.to_string(),)
.on_select(|p: crate::app::QSelectPropertyChoice| {
if p.field.is_empty() {
Message::QSelectSetProperty(None)
} else {
Message::QSelectSetProperty(Some(p))
}
})
.width(field_width),
]
.align_y(iced::Alignment::Center)
.spacing(8)
@@ -1705,13 +1682,9 @@ fn qselect_content<'a>(
Space::new().height(6),
row![
label(t!("Operator:")),
iced::widget::pick_list(
Some(state.operator),
op_options,
|value| value.to_string(),
)
.on_select(Message::QSelectSetOperator)
.width(field_width),
iced::widget::pick_list(Some(state.operator), op_options, |value| value.to_string(),)
.on_select(Message::QSelectSetOperator)
.width(field_width),
]
.align_y(iced::Alignment::Center)
.spacing(8)
+23 -21
View File
@@ -1,8 +1,6 @@
use super::super::Message;
use crate::scene::{VIEWCUBE_PX, VIEWCUBE_REGION_PX};
use iced::widget::{
button, container, mouse_area, stack, Space,
};
use iced::widget::{button, container, mouse_area, stack, Space};
use iced::{Background, Border, Element, Theme};
// ── Render-mode picker ──────────────────────────────────────────────────────
@@ -37,9 +35,7 @@ fn vc_btn<'a>(content: Element<'a, Message>, size: f32, msg: Message) -> Element
status,
iced::widget::button::Status::Hovered | iced::widget::button::Status::Pressed
)
.then_some(Background::Color(
theme.palette().primary.weak.color
)),
.then_some(Background::Color(theme.palette().primary.weak.color)),
border: Border {
radius: 3.0.into(),
..Default::default()
@@ -52,9 +48,7 @@ fn vc_btn<'a>(content: Element<'a, Message>, size: f32, msg: Message) -> Element
/// Overlay of home / roll / nudge controls sized to the whole nav region, so
/// the caller can position it exactly like the cube hit area.
pub(super) fn viewcube_nav_controls<'a>(
viewport: Option<codec::Handle>,
) -> Element<'a, Message> {
pub(super) fn viewcube_nav_controls<'a>(viewport: Option<codec::Handle>) -> Element<'a, Message> {
use crate::scene::NudgeDir;
use crate::ui::icons;
let r = VIEWCUBE_REGION_PX;
@@ -96,12 +90,20 @@ pub(super) fn viewcube_nav_controls<'a>(
vc_place(
rax,
ray,
vc_btn(icons::themed_undo(12.0, true), BTN, Message::ViewCubeRoll(false))
vc_btn(
icons::themed_undo(12.0, true),
BTN,
Message::ViewCubeRoll(false)
)
),
vc_place(
rbx,
rby,
vc_btn(icons::themed_redo(12.0, true), BTN, Message::ViewCubeRoll(true))
vc_btn(
icons::themed_redo(12.0, true),
BTN,
Message::ViewCubeRoll(true)
)
),
vc_place(
tux,
@@ -174,16 +176,16 @@ pub(super) fn viewcube_ucs_picker<'a>(
.style(move |theme: &Theme, _| {
let palette = theme.palette();
iced::widget::pick_list::Style {
background: Background::Color(palette.background.weak.color),
border: Border {
radius: 3.0.into(),
color: palette.background.neutral.color,
width: 1.0,
..Default::default()
},
text_color: palette.background.base.text,
placeholder_color: palette.background.base.text.scale_alpha(0.68),
handle_color: palette.background.base.text,
background: Background::Color(palette.background.weak.color),
border: Border {
radius: 3.0.into(),
color: palette.background.neutral.color,
width: 1.0,
..Default::default()
},
text_color: palette.background.base.text,
placeholder_color: palette.background.base.text.scale_alpha(0.68),
handle_color: palette.background.base.text,
}
})
.into()