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
+12
-12
@@ -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
@@ -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
File diff suppressed because it is too large.
Load diff
+189
-216
@@ -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
@@ -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()
|
||||
|
||||
Reference in new issue
Block a user