refactor(ui): adopt iced color picker
Remove local Pin/PickList wrappers and the ACI grid.\nBlock viewport input behind the picker and load iced_aw glyphs.
This commit is contained in:
parent
3ab8dc3ca5
commit
c9c3d3b1bf
25 changed files with 289 additions and 255 deletions
|
|
@ -79,11 +79,12 @@ pub(super) fn viewport_controls<'a>(
|
|||
};
|
||||
|
||||
// Render-mode picker, restyled borderless so the outer chip frames it.
|
||||
let picker = crate::ui::pick_list(
|
||||
render_modes,
|
||||
let picker = iced::widget::pick_list(
|
||||
Some(RenderModeChoice(render_mode)),
|
||||
|c| Message::SetRenderMode(c.0),
|
||||
render_modes,
|
||||
|value| value.to_string(),
|
||||
)
|
||||
.on_select(|c| Message::SetRenderMode(c.0))
|
||||
.text_size(11)
|
||||
.padding([4, 6])
|
||||
.style(move |theme: &Theme, _| {
|
||||
|
|
|
|||
|
|
@ -788,10 +788,10 @@ impl OpenCADStudio {
|
|||
.into();
|
||||
// Pin the bar to the active model tile's top-left corner so it
|
||||
// follows the active panel in a tiled layout.
|
||||
let bar_layer = crate::ui::pin_at(
|
||||
iced::Point::new(rect.x, rect.y),
|
||||
let bar_layer = iced::widget::pin(
|
||||
container(adaptive).width(iced::Length::Fixed(rect.width.max(1.0))),
|
||||
);
|
||||
)
|
||||
.position(iced::Point::new(rect.x.max(0.0), rect.y.max(0.0)));
|
||||
viewport_stack = viewport_stack.push(bar_layer);
|
||||
}
|
||||
|
||||
|
|
@ -840,7 +840,8 @@ impl OpenCADStudio {
|
|||
},
|
||||
..Default::default()
|
||||
});
|
||||
let border_layer = crate::ui::pin_at(iced::Point::new(x, y), border_frame);
|
||||
let border_layer =
|
||||
iced::widget::pin(border_frame).position(iced::Point::new(x, y));
|
||||
viewport_stack = viewport_stack.push(border_layer);
|
||||
|
||||
let vp_mode = tab
|
||||
|
|
@ -866,10 +867,10 @@ impl OpenCADStudio {
|
|||
])
|
||||
.report_width0(self.render_bar_w.clone())
|
||||
.into();
|
||||
let picker_layer = crate::ui::pin_at(
|
||||
iced::Point::new(x + 4.0, y + 4.0),
|
||||
let picker_layer = iced::widget::pin(
|
||||
container(adaptive).width(iced::Length::Fixed(rect.width.max(1.0))),
|
||||
);
|
||||
)
|
||||
.position(iced::Point::new(x + 4.0, y + 4.0));
|
||||
viewport_stack = viewport_stack.push(picker_layer);
|
||||
|
||||
// Hide the ViewCube first — before the render bar — when they collide.
|
||||
|
|
@ -877,10 +878,8 @@ impl OpenCADStudio {
|
|||
let cube_x = (rect.x + rect.width - VIEWCUBE_HIT_SIZE - VIEWCUBE_PAD).max(0.0);
|
||||
let cube_y = (rect.y + VIEWCUBE_PAD).max(0.0);
|
||||
|
||||
let controls = crate::ui::pin_at(
|
||||
iced::Point::new(cube_x, cube_y),
|
||||
viewcube_nav_controls(),
|
||||
);
|
||||
let controls = iced::widget::pin(viewcube_nav_controls())
|
||||
.position(iced::Point::new(cube_x, cube_y));
|
||||
viewport_stack = viewport_stack.push(controls);
|
||||
|
||||
let ucs_current = tab
|
||||
|
|
@ -896,13 +895,14 @@ impl OpenCADStudio {
|
|||
.map(|u| u.name.clone())
|
||||
.filter(|n| !n.is_empty())
|
||||
.collect();
|
||||
let picker = crate::ui::pin_at(
|
||||
iced::Point::new(
|
||||
let picker = iced::widget::pin(iced::widget::opaque(viewcube_ucs_picker(
|
||||
ucs_current,
|
||||
ucs_names,
|
||||
)))
|
||||
.position(iced::Point::new(
|
||||
cube_x + VIEWCUBE_HIT_SIZE * 0.5 - UCS_PICKER_W * 0.5,
|
||||
cube_y + VIEWCUBE_HIT_SIZE + 6.0,
|
||||
),
|
||||
iced::widget::opaque(viewcube_ucs_picker(ucs_current, ucs_names)),
|
||||
);
|
||||
));
|
||||
viewport_stack = viewport_stack.push(picker);
|
||||
}
|
||||
}
|
||||
|
|
@ -917,10 +917,8 @@ impl OpenCADStudio {
|
|||
let cube_y = (rect.y + VIEWCUBE_PAD).max(0.0);
|
||||
|
||||
// Cube hit area + nav controls (home / roll / nudge) as one layer.
|
||||
let controls = crate::ui::pin_at(
|
||||
iced::Point::new(cube_x, cube_y),
|
||||
viewcube_nav_controls(),
|
||||
);
|
||||
let controls = iced::widget::pin(viewcube_nav_controls())
|
||||
.position(iced::Point::new(cube_x, cube_y));
|
||||
viewport_stack = viewport_stack.push(controls);
|
||||
|
||||
// WCS / named-UCS selector under the cube.
|
||||
|
|
@ -937,13 +935,14 @@ impl OpenCADStudio {
|
|||
.map(|u| u.name.clone())
|
||||
.filter(|n| !n.is_empty())
|
||||
.collect();
|
||||
let picker = crate::ui::pin_at(
|
||||
iced::Point::new(
|
||||
let picker = iced::widget::pin(iced::widget::opaque(viewcube_ucs_picker(
|
||||
ucs_current,
|
||||
ucs_names,
|
||||
)))
|
||||
.position(iced::Point::new(
|
||||
cube_x + VIEWCUBE_HIT_SIZE * 0.5 - UCS_PICKER_W * 0.5,
|
||||
cube_y + VIEWCUBE_HIT_SIZE + 6.0,
|
||||
),
|
||||
iced::widget::opaque(viewcube_ucs_picker(ucs_current, ucs_names)),
|
||||
);
|
||||
));
|
||||
viewport_stack = viewport_stack.push(picker);
|
||||
}
|
||||
|
||||
|
|
@ -1554,21 +1553,24 @@ impl OpenCADStudio {
|
|||
}
|
||||
None => composed.into(),
|
||||
};
|
||||
// The colour picker is a nested modal: it stacks over whichever dialog
|
||||
// (style editor, properties, …) requested it.
|
||||
if self.color_pick_target.is_some() {
|
||||
crate::ui::modal::modal(
|
||||
base,
|
||||
"Select Color",
|
||||
iced::widget::container(crate::ui::color_select::color_grid_window(
|
||||
Message::ColorWindowPick,
|
||||
))
|
||||
.width(iced::Length::Fit.max(420.0))
|
||||
.height(iced::Length::Fit.max(470.0)),
|
||||
// iced_aw owns the colour-picker overlay and keeps it above whichever
|
||||
// application modal requested it.
|
||||
if let Some((_, current)) = self.color_pick_target.as_ref() {
|
||||
let initial = crate::ui::properties::acad_color_display(*current).0;
|
||||
let modal_base =
|
||||
crate::ui::modal::backdrop(base, Message::CloseColorPicker);
|
||||
iced_aw::ColorPicker::new(
|
||||
true,
|
||||
initial,
|
||||
modal_base,
|
||||
Message::CloseColorPicker,
|
||||
iced::Vector::ZERO,
|
||||
crate::ui::modal::ModalOptions::MOVABLE_FIXED,
|
||||
|color| {
|
||||
Message::ColorWindowPick(
|
||||
crate::ui::color_select::iced_to_acad_color(color),
|
||||
)
|
||||
},
|
||||
)
|
||||
.into()
|
||||
} else {
|
||||
base
|
||||
}
|
||||
|
|
|
|||
|
|
@ -982,9 +982,12 @@ fn save_as_dialog_window<'a>(filename: &'a str, format: &'a str) -> Element<'a,
|
|||
items.push(
|
||||
row![
|
||||
label("Format:").width(70),
|
||||
crate::ui::pick_list(crate::io::SAVE_FORMAT_OPTIONS, sel_fmt, |s: &str| {
|
||||
Message::SaveDialogFormatChanged(s.to_string())
|
||||
})
|
||||
iced::widget::pick_list(
|
||||
sel_fmt,
|
||||
crate::io::SAVE_FORMAT_OPTIONS,
|
||||
|value| value.to_string(),
|
||||
)
|
||||
.on_select(|s: &str| Message::SaveDialogFormatChanged(s.to_string()))
|
||||
.width(Fit),
|
||||
]
|
||||
.align_y(iced::Alignment::Center)
|
||||
|
|
|
|||
|
|
@ -9,7 +9,9 @@ pub(super) fn position_canvas_overlay<'a>(
|
|||
anchor: iced::Point,
|
||||
panel: Element<'a, Message>,
|
||||
) -> Element<'a, Message> {
|
||||
crate::ui::pin_at(anchor, iced::widget::opaque(panel))
|
||||
iced::widget::pin(iced::widget::opaque(panel))
|
||||
.position(iced::Point::new(anchor.x.max(0.0), anchor.y.max(0.0)))
|
||||
.into()
|
||||
}
|
||||
|
||||
// ── In-place MText editor overlay ───────────────────────────────────────────
|
||||
|
|
@ -369,7 +371,12 @@ pub(super) fn mtext_editor_overlay<'a>(
|
|||
} else {
|
||||
styles
|
||||
};
|
||||
let style_pl = crate::ui::pick_list(style_opts, Some(ed.style.clone()), Message::MTextStyle)
|
||||
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 font_sel = if ed.font.trim().is_empty() {
|
||||
|
|
@ -377,14 +384,15 @@ pub(super) fn mtext_editor_overlay<'a>(
|
|||
} else {
|
||||
ed.font.clone()
|
||||
};
|
||||
let font_pl = crate::ui::pick_list(
|
||||
let font_pl = iced::widget::pick_list(
|
||||
Some(font_sel),
|
||||
MTEXT_FONTS
|
||||
.iter()
|
||||
.map(|s| s.to_string())
|
||||
.collect::<Vec<_>>(),
|
||||
Some(font_sel),
|
||||
Message::MTextFont,
|
||||
|value| value.to_string(),
|
||||
)
|
||||
.on_select(Message::MTextFont)
|
||||
.text_size(11)
|
||||
.width(iced::Length::Fixed(120.0));
|
||||
// Same colour picker as the Properties panel (named swatches + "More…" full
|
||||
|
|
@ -398,7 +406,10 @@ pub(super) fn mtext_editor_overlay<'a>(
|
|||
},
|
||||
Message::MTextColorChanged,
|
||||
Message::MTextColorPickerToggle,
|
||||
Message::OpenColorWindow(crate::app::ColorPickTarget::MText),
|
||||
Message::OpenColorWindow(
|
||||
crate::app::ColorPickTarget::MText,
|
||||
acadrust::types::Color::from_index(ed.color_aci as i16),
|
||||
),
|
||||
))
|
||||
.width(iced::Length::Fixed(150.0));
|
||||
|
||||
|
|
@ -443,11 +454,12 @@ pub(super) fn mtext_editor_overlay<'a>(
|
|||
.width(width);
|
||||
|
||||
// ── Row 2: oblique / width / char-spacing · align · line spacing · OK ─
|
||||
let justify = crate::ui::pick_list(
|
||||
JustifyChoice::ALL,
|
||||
let justify = iced::widget::pick_list(
|
||||
Some(JustifyChoice(ed.attachment)),
|
||||
|c| Message::MTextJustify(c.0),
|
||||
JustifyChoice::ALL,
|
||||
|value| value.to_string(),
|
||||
)
|
||||
.on_select(|c| Message::MTextJustify(c.0))
|
||||
.text_size(11)
|
||||
.width(iced::Length::Fixed(112.0));
|
||||
let row2 = row![
|
||||
|
|
@ -1008,7 +1020,12 @@ pub(super) fn qselect_overlay<'a>(
|
|||
Space::new().height(10),
|
||||
row![
|
||||
label("Object type:"),
|
||||
crate::ui::pick_list(type_options, Some(type_sel), |s: String| {
|
||||
iced::widget::pick_list(
|
||||
Some(type_sel),
|
||||
type_options,
|
||||
|value| value.to_string(),
|
||||
)
|
||||
.on_select(|s: String| {
|
||||
if s == QSELECT_ANY_TYPE {
|
||||
Message::QSelectSetType(None)
|
||||
} else {
|
||||
|
|
@ -1022,17 +1039,18 @@ pub(super) fn qselect_overlay<'a>(
|
|||
Space::new().height(6),
|
||||
row![
|
||||
label("Property:"),
|
||||
crate::ui::pick_list(
|
||||
prop_options,
|
||||
iced::widget::pick_list(
|
||||
Some(prop_sel),
|
||||
|p: crate::app::QSelectPropertyChoice| {
|
||||
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(Fill),
|
||||
]
|
||||
.align_y(iced::Alignment::Center)
|
||||
|
|
@ -1040,11 +1058,12 @@ pub(super) fn qselect_overlay<'a>(
|
|||
Space::new().height(6),
|
||||
row![
|
||||
label("Operator:"),
|
||||
crate::ui::pick_list(
|
||||
op_options,
|
||||
iced::widget::pick_list(
|
||||
Some(state.operator),
|
||||
Message::QSelectSetOperator
|
||||
op_options,
|
||||
|value| value.to_string(),
|
||||
)
|
||||
.on_select(Message::QSelectSetOperator)
|
||||
.width(Fill),
|
||||
]
|
||||
.align_y(iced::Alignment::Center)
|
||||
|
|
|
|||
|
|
@ -16,7 +16,9 @@ use iced::{Background, Border, Element, Theme};
|
|||
|
||||
/// Place `el` at pixel offset (x, y) inside a fill layer (top-left origin).
|
||||
fn vc_place<'a>(x: f32, y: f32, el: Element<'a, Message>) -> Element<'a, Message> {
|
||||
crate::ui::pin_at(iced::Point::new(x, y), el)
|
||||
iced::widget::pin(el)
|
||||
.position(iced::Point::new(x.max(0.0), y.max(0.0)))
|
||||
.into()
|
||||
}
|
||||
|
||||
/// Borderless square icon button used by the ViewCube nav controls.
|
||||
|
|
@ -155,7 +157,8 @@ pub(super) fn viewcube_ucs_picker<'a>(current: String, names: Vec<String>) -> El
|
|||
} else {
|
||||
current
|
||||
};
|
||||
crate::ui::pick_list(options, Some(selected), Message::SetViewcubeUcs)
|
||||
iced::widget::pick_list(Some(selected), options, |value| value.to_string())
|
||||
.on_select(Message::SetViewcubeUcs)
|
||||
.text_size(11)
|
||||
.padding([2, 6])
|
||||
// Fixed width so the caller can centre it under the cube centre with a
|
||||
|
|
|
|||
Loading…
Reference in a new issue