diff --git a/src/app/mod.rs b/src/app/mod.rs index eea872c8c..7fefa5a65 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -574,6 +574,12 @@ pub enum ColorPickTarget { DimStyle(DsField), MLeader(&'static str), Table(u8, &'static str), + /// Selected entities' colour (left properties panel). + Properties, + /// Current creation colour (ribbon). + Ribbon, + /// A layer's colour, by panel row index. + Layer(usize), } /// Identifies a DimStyle field that can be edited in the dialog. diff --git a/src/app/update.rs b/src/app/update.rs index c3d026f15..1a0ab4f57 100644 --- a/src/app/update.rs +++ b/src/app/update.rs @@ -7330,6 +7330,10 @@ impl OpenCADStudio { 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; if let Some(id) = self.color_pick_window { return window::gain_focus(id); } @@ -7356,6 +7360,19 @@ impl OpenCADStudio { value: s, }) } + Some(crate::app::ColorPickTarget::Properties) => { + Some(Message::PropColorChanged(color)) + } + Some(crate::app::ColorPickTarget::Ribbon) => { + Some(Message::RibbonColorChanged(color)) + } + Some(crate::app::ColorPickTarget::Layer(idx)) => { + self.tabs[self.active_tab].layers.selected = Some(idx); + match color { + acadrust::types::Color::Index(i) => Some(Message::LayerColorSet(i)), + _ => None, + } + } None => None, }; let mut tasks = Vec::new(); diff --git a/src/ui/color_select.rs b/src/ui/color_select.rs index ae1a1390b..081ed15c2 100644 --- a/src/ui/color_select.rs +++ b/src/ui/color_select.rs @@ -111,13 +111,41 @@ pub fn color_selector<'a>( ) .on_press(on_toggle) .padding([3, 6]) - .width(170); + .width(Length::Fill); if !open { return head.into(); } - // One named-colour row (swatch + name), selectable. + let popup = container(color_list(extras, on_select, on_more)) + .style(|_: &Theme| container::Style { + background: Some(Background::Color(PICKER_BG)), + border: Border { + color: BORDER, + width: 1.0, + radius: 2.0.into(), + }, + ..Default::default() + }) + .padding(5) + .width(220); + + // The popup is shown as a floating overlay (anchored below the button) so + // it doesn't push the surrounding form down. + Element::new(Floating { + base: head.into(), + popup: popup.into(), + }) +} + +/// The colour list shown inside a picker popup: named ACI colours (with +/// swatches) plus a "More…" entry that opens the full palette window. Shared by +/// `color_selector` and the ribbon's colour overlay. +pub fn color_list<'a>( + extras: ColorExtras, + on_select: impl Fn(AcadColor) -> Message + 'a, + on_more: Message, +) -> Element<'a, Message> { let named_row = |color: AcadColor| -> Element<'a, Message> { let (bg, name) = acad_color_display(color); button( @@ -151,7 +179,6 @@ pub fn color_selector<'a>( for i in 1u8..=9 { list = list.push(named_row(AcadColor::Index(i))); } - // "More…" opens the full ACI palette in a separate window. list = list.push( button(text("More…").size(11).color(TEXT)) .on_press(on_more) @@ -168,26 +195,7 @@ pub fn color_selector<'a>( .padding([2, 4]) .width(Length::Fill), ); - - let popup = container(list) - .style(|_: &Theme| container::Style { - background: Some(Background::Color(PICKER_BG)), - border: Border { - color: BORDER, - width: 1.0, - radius: 2.0.into(), - }, - ..Default::default() - }) - .padding(5) - .width(220); - - // The popup is shown as a floating overlay (anchored below the button) so - // it doesn't push the surrounding form down. - Element::new(Floating { - base: head.into(), - popup: popup.into(), - }) + list.into() } /// Full ACI palette as a standalone window body: ByLayer / ByBlock plus the diff --git a/src/ui/layers.rs b/src/ui/layers.rs index 81ef88a29..06edb6568 100644 --- a/src/ui/layers.rs +++ b/src/ui/layers.rs @@ -1,7 +1,7 @@ //! Layer Manager — floating window. use crate::app::Message; -use crate::ui::properties::{color_picker_dropdown, lw_options, LinetypeItem, LwItem}; +use crate::ui::properties::{lw_options, LinetypeItem, LwItem}; use crate::ui::ROW_H; use acadrust::tables::layer::Layer as DocLayer; use acadrust::tables::Table; @@ -271,10 +271,6 @@ impl LayerPanel { &self.vp_cols, )); - // Insert color picker dropdown below this row when open. - if color_open { - rows_col = rows_col.push(color_picker_palette(self.color_full_palette)); - } } let table = scrollable(rows_col).height(Fill); @@ -559,77 +555,23 @@ fn layer_row<'a>( // Color cell — looks like a combo_box input; click opens swatch dropdown below row. let aci = iced_to_aci(layer.color); let cur_color_name = color_label_aci(aci).to_string(); - let layer_color = layer.color; - - let swatch = container(text("")) - .style(move |_: &Theme| container::Style { - background: Some(Background::Color(layer_color)), - border: Border { - color: Color { - r: 0.0, - g: 0.0, - b: 0.0, - a: 0.5, - }, - width: 1.0, - radius: 1.0.into(), - }, - ..Default::default() - }) - .width(12) - .height(12); - - let color_cell: Element<'_, Message> = button( - row![ - swatch, - text(cur_color_name).size(FONT_SZ).color(ROW_TEXT), - iced::widget::Space::new().width(Fill), - text(if color_picker_open { "▲" } else { "▼" }) - .size(FONT_SZ * 0.75) - .color(DIM), - ] - .spacing(4) - .align_y(iced::Center), - ) - .on_press(Message::LayerColorPickerToggle(index)) - .style(move |_: &Theme, status| button::Style { - background: Some(Background::Color(match status { - button::Status::Hovered => Color { - r: 0.20, - g: 0.20, - b: 0.20, - a: 1.0, - }, - _ => Color { - r: 0.13, - g: 0.13, - b: 0.13, - a: 1.0, - }, - })), - border: Border { - radius: 2.0.into(), - width: 1.0, - color: if color_picker_open { - Color { - r: 0.45, - g: 0.65, - b: 0.90, - a: 1.0, - } - } else { - BORDER_COLOR - }, + let _ = cur_color_name; + // Shared colour selector. Layers carry a concrete colour (no ByLayer / + // ByBlock); the chosen index is applied to this row. + let color_cell: Element<'_, Message> = container(crate::ui::color_select::color_selector( + acadrust::types::Color::Index(aci), + color_picker_open, + crate::ui::color_select::ColorExtras { + by_layer: false, + by_block: false, }, - ..Default::default() - }) - .padding(Padding { - top: COMBO_PAD_V, - bottom: COMBO_PAD_V, - left: 4.0, - right: 4.0, - }) - .height(Length::Fixed(ROW_H)) + |c| match c { + acadrust::types::Color::Index(i) => Message::LayerColorSet(i), + _ => Message::LayerColorSet(7), + }, + Message::LayerColorPickerToggle(index), + Message::OpenColorWindow(crate::app::ColorPickTarget::Layer(index)), + )) .width(Length::Fixed(COL_COLOR)) .into(); @@ -815,21 +757,6 @@ fn combo_input_style( } } -// ── Color picker palette (shown below row) ──────────────────────────────── - -fn color_picker_palette<'a>(full: bool) -> Element<'a, Message> { - // Horizontal offset to align dropdown under the Color column. - const LEFT_OFFSET: f32 = - 20.0 + 4.0 + COL_NAME + 4.0 + COL_ICON + 4.0 + COL_ICON + 4.0 + COL_ICON + 4.0 + 8.0; - - // Use the shared color_picker_dropdown from properties — no ByLayer/ByBlock for layers. - let dropdown = color_picker_dropdown(full, Message::LayerColorMorePalette, None, None, |aci| { - Message::LayerColorSet(aci) - }); - - row![iced::widget::Space::new().width(LEFT_OFFSET), dropdown,].into() -} - // ── Display helpers ─────────────────────────────────────────────────────── #[allow(dead_code)] diff --git a/src/ui/properties.rs b/src/ui/properties.rs index 04efa1808..b4436dfc9 100644 --- a/src/ui/properties.rs +++ b/src/ui/properties.rs @@ -377,53 +377,18 @@ impl PropertiesPanel { // ── Color row (custom picker) ───────────────────────────────────────── fn render_color_row<'a>(&'a self, label: &'a str, color: AcadColor) -> Element<'a, Message> { - let (swatch_bg, color_label) = acad_color_display(color); - - // The button that shows current color + opens picker - let color_btn = button( - row![ - container(text("").width(SWATCH_SZ).height(SWATCH_SZ)) - .style(move |_: &Theme| container::Style { - background: Some(Background::Color(swatch_bg)), - border: Border { - color: Color { - r: 0.0, - g: 0.0, - b: 0.0, - a: 0.5 - }, - width: 1.0, - radius: 2.0.into() - }, - ..Default::default() - }) - .width(SWATCH_SZ) - .height(SWATCH_SZ), - text(color_label).size(FONT_SZ).color(VALUE_COLOR), - ] - .spacing(4) - .align_y(iced::Center), - ) - .on_press(Message::PropColorPickerToggle) - .style(combo_btn_style) - .padding(Padding { - top: COMBO_PAD_V, - bottom: COMBO_PAD_V, - left: 6.0, - right: 6.0, - }) - .width(Length::Fill); - - let color_row = prop_row_widget(label, color_btn.into()); - - // Color picker dropdown (inline) - if self.color_picker_open { - column![color_row, self.render_color_picker()] - .spacing(0) - .into() - } else { - color_row - } + let selector = crate::ui::color_select::color_selector( + color, + self.color_picker_open, + crate::ui::color_select::ColorExtras { + by_layer: true, + by_block: true, + }, + Message::PropColorChanged, + Message::PropColorPickerToggle, + Message::OpenColorWindow(crate::app::ColorPickTarget::Properties), + ); + prop_row_widget(label, selector) } fn render_color_varies_row<'a>(&'a self, label: &'a str) -> Element<'a, Message> { diff --git a/src/ui/ribbon/mod.rs b/src/ui/ribbon/mod.rs index 58a6dad81..f8e8465f4 100644 --- a/src/ui/ribbon/mod.rs +++ b/src/ui/ribbon/mod.rs @@ -15,7 +15,7 @@ use iced::{Background, Border, Color, Element, Fill, Length, Padding, Theme}; use crate::app::Message; use crate::modules::{CadModule, IconKind, RibbonItem}; use crate::plugin::all_ribbon_modules; -use crate::ui::properties::{color_picker_dropdown, lw_options, LinetypeItem}; +use crate::ui::properties::{lw_options, LinetypeItem}; mod widgets; use widgets::{StyleContext, *}; @@ -817,12 +817,13 @@ impl Ribbon { } fn prop_color_overlay(&self) -> Option> { - let picker = color_picker_dropdown( - self.prop_color_palette_open, - Message::RibbonColorPaletteToggle, - Some(Message::RibbonColorChanged(AcadColor::ByLayer)), - Some(Message::RibbonColorChanged(AcadColor::ByBlock)), - |aci| Message::RibbonColorChanged(AcadColor::Index(aci)), + let picker = crate::ui::color_select::color_list( + crate::ui::color_select::ColorExtras { + by_layer: true, + by_block: true, + }, + Message::RibbonColorChanged, + Message::OpenColorWindow(crate::app::ColorPickTarget::Ribbon), ); let panel = container(picker)