forked from 1b-agent/opencadstudio-upstream
feat(color): add CAD indexed color picker
This commit is contained in:
1 parent
60f5bca0d4
commit
4697e8cc33
4 files changed
+293
-21
No files matched your search
+20
-3
@@ -599,6 +599,11 @@ pub(super) struct OpenCADStudio {
|
||||
// ── Floating panel windows ────────────────────────────────────────────
|
||||
/// Active `iced_aw` colour picker: destination plus its initial colour.
|
||||
color_pick_target: Option<(ColorPickTarget, AcadColor)>,
|
||||
/// Visible page in the shared CAD colour picker.
|
||||
color_picker_tab: ColorPickerTab,
|
||||
/// Recently committed real colours, newest first.
|
||||
/// ACI and True Color remain semantically distinct even when their RGB matches.
|
||||
recent_colors: Vec<AcadColor>,
|
||||
/// The open in-canvas modal dialog, if any (Plan B: shared overlay instead
|
||||
/// of OS windows).
|
||||
active_modal: Option<ModalKind>,
|
||||
@@ -1162,7 +1167,13 @@ pub struct SaveOutcome {
|
||||
refreshed_preview: Option<Option<acadrust::Preview>>,
|
||||
result: Result<(), crate::io::SaveFailure>,
|
||||
}
|
||||
|
||||
/// Active page in the shared CAD colour picker.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
|
||||
pub enum ColorPickerTab {
|
||||
#[default]
|
||||
Index,
|
||||
TrueColor,
|
||||
}
|
||||
/// Where a colour chosen in the standalone palette window should be applied.
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum ColorPickTarget {
|
||||
@@ -2904,11 +2915,15 @@ pub enum Message {
|
||||
DsCenterMarkMode(String),
|
||||
/// Toggle the expanded colour palette for a DimStyle colour field.
|
||||
DsColorMore(DsField),
|
||||
/// Open the `iced_aw` colour picker for a field and its current colour.
|
||||
/// Open the shared CAD colour picker for a field and its current colour.
|
||||
OpenColorWindow(ColorPickTarget, AcadColor),
|
||||
/// Switch between Index Color and True Color.
|
||||
ColorPickerTabChanged(ColorPickerTab),
|
||||
/// Change the pending colour without committing it yet.
|
||||
ColorPickerColorChanged(AcadColor),
|
||||
/// Close the colour picker without choosing.
|
||||
CloseColorPicker,
|
||||
/// A colour was chosen in the `iced_aw` picker.
|
||||
/// Commit the colour chosen in the shared picker.
|
||||
ColorWindowPick(acadrust::types::Color),
|
||||
/// Set a block/linetype Handle field on the selected dim style from a
|
||||
/// dropdown of available block-records / linetypes (by name).
|
||||
@@ -3127,6 +3142,8 @@ impl OpenCADStudio {
|
||||
last_point: None,
|
||||
main_window: None,
|
||||
color_pick_target: None,
|
||||
color_picker_tab: ColorPickerTab::Index,
|
||||
recent_colors: Vec::new(),
|
||||
active_modal: None,
|
||||
find_replace: FindReplaceState::default(),
|
||||
aec_drop_acknowledged: false,
|
||||
|
||||
+37
-2
@@ -7321,21 +7321,56 @@ impl OpenCADStudio {
|
||||
}
|
||||
Message::OpenColorWindow(target, color) => {
|
||||
self.color_pick_target = Some((target, color));
|
||||
|
||||
// Always open the shared CAD colour picker on the indexed ACI page.
|
||||
self.color_picker_tab = crate::app::ColorPickerTab::Index;
|
||||
self.modal_offset = iced::Vector::ZERO;
|
||||
self.ds_color_open = None;
|
||||
self.mls_color_open = None;
|
||||
self.ts_color_open = None;
|
||||
self.ribbon.close_dropdown();
|
||||
|
||||
let i = self.active_tab;
|
||||
self.tabs[i].properties.color_picker_open = false;
|
||||
self.tabs[i].layers.color_picker_row = None;
|
||||
// `color_pick_target.is_some()` drives the iced_aw overlay.
|
||||
|
||||
Task::none()
|
||||
}
|
||||
|
||||
Message::ColorPickerTabChanged(tab) => {
|
||||
self.color_picker_tab = tab;
|
||||
Task::none()
|
||||
}
|
||||
Message::ColorPickerColorChanged(color) => {
|
||||
if let Some((_, current)) = self.color_pick_target.as_mut() {
|
||||
*current = color;
|
||||
}
|
||||
Task::none()
|
||||
}
|
||||
Message::CloseColorPicker => {
|
||||
self.color_pick_target = None;
|
||||
Task::none()
|
||||
}
|
||||
Message::ColorWindowPick(color) => self.on_color_window_pick(color),
|
||||
|
||||
Message::ColorWindowPick(color) => {
|
||||
// Keep only real colours in the recent list. ByLayer / ByBlock / None
|
||||
// are logical CAD states rather than reusable colours.
|
||||
if matches!(
|
||||
&color,
|
||||
acadrust::types::Color::Index(_)
|
||||
| acadrust::types::Color::Rgb { .. }
|
||||
) {
|
||||
// No duplicates: selecting an existing colour moves it to the front.
|
||||
if let Some(pos) = self.recent_colors.iter().position(|c| c == &color) {
|
||||
self.recent_colors.remove(pos);
|
||||
}
|
||||
|
||||
self.recent_colors.insert(0, color.clone());
|
||||
self.recent_colors.truncate(12);
|
||||
}
|
||||
|
||||
self.on_color_window_pick(color)
|
||||
}
|
||||
Message::DsSetHandle { field, value } => self.on_ds_set_handle(field, value),
|
||||
}
|
||||
}
|
||||
|
||||
+41
-16
@@ -1850,24 +1850,49 @@ impl OpenCADStudio {
|
||||
}
|
||||
None => composed.into(),
|
||||
};
|
||||
// iced_aw owns the colour-picker overlay and keeps it above whichever
|
||||
// application modal requested it.
|
||||
// Shared CAD colour picker. Indexed ACI colours use OpenCADStudio's own
|
||||
// dialog; True Color keeps the existing iced_aw gradient picker.
|
||||
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,
|
||||
|color| {
|
||||
Message::ColorWindowPick(
|
||||
crate::ui::color_select::iced_to_acad_color(color),
|
||||
match self.color_picker_tab {
|
||||
super::ColorPickerTab::Index => {
|
||||
let content = crate::ui::color_select::index_color_page(
|
||||
*current,
|
||||
&self.recent_colors,
|
||||
);
|
||||
|
||||
crate::ui::modal::modal(
|
||||
base,
|
||||
"Select Color",
|
||||
content,
|
||||
Message::CloseColorPicker,
|
||||
self.modal_offset,
|
||||
crate::ui::modal::ModalOptions::NOTICE,
|
||||
)
|
||||
},
|
||||
)
|
||||
.into()
|
||||
}
|
||||
|
||||
super::ColorPickerTab::TrueColor => {
|
||||
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,
|
||||
|
||||
// Cancel inside True Color returns to the indexed page instead
|
||||
// of closing the whole CAD colour picker.
|
||||
Message::ColorPickerTabChanged(super::ColorPickerTab::Index),
|
||||
|
||||
|color| {
|
||||
Message::ColorWindowPick(
|
||||
crate::ui::color_select::iced_to_acad_color(color),
|
||||
)
|
||||
},
|
||||
)
|
||||
.into()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
base
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user