forked from 1b-agent/opencadstudio-upstream
Share the colour editor, add an eyedropper, use library code
- ColorEditor: the HSB / RGB / field editor and hex box, now shared by the Select Color panel and the Options background swatches. Those swatches open the panel without tabs or index colours, which removes the iced_aw color_picker feature and the BgPicker messages. - Sliders are iced's built-in slider and vertical_slider over a gradient container; the custom GradientSlider widget is gone. - Nearest index colour comes from opencadcodec's aci_table::nearest_aci. - Eyedropper: a pipette at the right of the mode row hides the panel, captures the window with iced's screenshot task and shows an 11x11 magnifier beside a crosshair; a click picks the pixel, Esc backs out. Not offered on the web build. - The hex box applies six-digit values while typing. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_013rGmDUNr1hUf4zo1X3dak8
This commit is contained in:
16 files changed
+1125
-1053
No files matched your search
+18
-34
@@ -8256,39 +8256,6 @@ impl OpenCADStudio {
|
||||
Task::none()
|
||||
}
|
||||
|
||||
Message::BgPickerOpen(target) => {
|
||||
self.bg_picker = Some(target);
|
||||
Task::none()
|
||||
}
|
||||
|
||||
Message::BgPickerCancel => {
|
||||
self.bg_picker = None;
|
||||
Task::none()
|
||||
}
|
||||
|
||||
Message::BgPickerSubmit(color) => {
|
||||
// Hand the result to the same handler the typed hex field
|
||||
// uses, so the wheel and the field cannot drift apart on
|
||||
// validation, persistence or the MatchTheme fallback.
|
||||
let hex = crate::app::config::rgb_to_hex([
|
||||
(color.r * 255.0).round() as u8,
|
||||
(color.g * 255.0).round() as u8,
|
||||
(color.b * 255.0).round() as u8,
|
||||
]);
|
||||
match self.bg_picker.take() {
|
||||
Some(crate::app::BgTarget::Model) => {
|
||||
Task::done(Message::ModelSpaceBgChanged(hex))
|
||||
}
|
||||
Some(crate::app::BgTarget::Paper) => {
|
||||
Task::done(Message::PaperSpaceBgChanged(hex))
|
||||
}
|
||||
Some(crate::app::BgTarget::Desk) => {
|
||||
Task::done(Message::DeskSpaceBgChanged(hex))
|
||||
}
|
||||
None => Task::none(),
|
||||
}
|
||||
}
|
||||
|
||||
Message::ModelSpaceBgChanged(hex) => {
|
||||
self.model_bg_input = hex.clone();
|
||||
if hex.trim().is_empty() {
|
||||
@@ -11066,6 +11033,16 @@ impl OpenCADStudio {
|
||||
self.color_picker = None;
|
||||
Task::none()
|
||||
}
|
||||
Some(crate::ui::color_select::Outcome::Screenshot) => {
|
||||
use crate::ui::color_select::{eyedropper::EyedropperMsg, ColorPickerMsg};
|
||||
self.main_window.map_or_else(Task::none, |id| {
|
||||
iced::window::screenshot(id).map(|shot| {
|
||||
Message::ColorPicker(ColorPickerMsg::Eyedropper(
|
||||
EyedropperMsg::Shot(shot),
|
||||
))
|
||||
})
|
||||
})
|
||||
}
|
||||
None => Task::none(),
|
||||
}
|
||||
}
|
||||
@@ -11075,7 +11052,14 @@ impl OpenCADStudio {
|
||||
}
|
||||
|
||||
Message::ColorWindowPick(color) => {
|
||||
self.note_recent_color(color);
|
||||
// Interface colours are not drawing colours: keep them out of
|
||||
// the recent list.
|
||||
if !matches!(
|
||||
self.color_picker.as_ref().map(|picker| &picker.target),
|
||||
Some(crate::app::ColorPickTarget::Background(_))
|
||||
) {
|
||||
self.note_recent_color(color);
|
||||
}
|
||||
self.on_color_window_pick(color)
|
||||
}
|
||||
Message::DsSetHandle { field, value } => self.on_ds_set_handle(field, value),
|
||||
|
||||
+23
-1
@@ -1136,6 +1136,25 @@ impl OpenCADStudio {
|
||||
}
|
||||
|
||||
pub(super) fn on_color_window_pick(&mut self, color: codec::types::Color) -> Task<Message> {
|
||||
if let Some(crate::app::ColorPickTarget::Background(target)) = self
|
||||
.color_picker
|
||||
.as_ref()
|
||||
.map(|picker| picker.target.clone())
|
||||
{
|
||||
self.color_picker = None;
|
||||
let Some((r, g, b)) = crate::ui::color_select::math::color_rgb(color) else {
|
||||
return Task::none();
|
||||
};
|
||||
// Hand the result to the same handler the typed hex field uses, so
|
||||
// the picker and the field cannot drift apart on validation,
|
||||
// persistence or the MatchTheme fallback.
|
||||
let hex = crate::app::config::rgb_to_hex([r, g, b]);
|
||||
return Task::done(match target {
|
||||
crate::app::BgTarget::Model => Message::ModelSpaceBgChanged(hex),
|
||||
crate::app::BgTarget::Paper => Message::PaperSpaceBgChanged(hex),
|
||||
crate::app::BgTarget::Desk => Message::DeskSpaceBgChanged(hex),
|
||||
});
|
||||
}
|
||||
if matches!(
|
||||
self.color_picker.as_ref().map(|picker| &picker.target),
|
||||
Some(crate::app::ColorPickTarget::PlotStyle)
|
||||
@@ -1187,7 +1206,10 @@ impl OpenCADStudio {
|
||||
Some(crate::app::ColorPickTarget::LayerState(idx)) => {
|
||||
Some(Message::LayerStateEditorLayerColor(idx, color))
|
||||
}
|
||||
Some(crate::app::ColorPickTarget::PlotStyle) => None,
|
||||
// Handled before this match.
|
||||
Some(
|
||||
crate::app::ColorPickTarget::PlotStyle | crate::app::ColorPickTarget::Background(_),
|
||||
) => None,
|
||||
None => None,
|
||||
};
|
||||
if let Some(m) = edit {
|
||||
|
||||
Reference in new issue
Block a user