diff --git a/src/app/update/mod.rs b/src/app/update/mod.rs index 1e4b217b2..01630caea 100644 --- a/src/app/update/mod.rs +++ b/src/app/update/mod.rs @@ -11563,12 +11563,14 @@ impl OpenCADStudio { let mut picker = crate::ui::color_select::ColorPicker::new(target, current, varies); if !matches!(picker.target, crate::app::ColorPickTarget::Interface(_)) { self.read_color_books(); + let by_layer = self.color_picker_layer_color(&picker.target); let tab = &self.tabs[self.active_tab]; picker = picker.with_drawing( crate::ui::color_select::document::collect(&tab.scene.document), &tab.recent_colors, std::sync::Arc::clone(&self.color_books), name, + by_layer, ); } self.color_picker = Some(picker); @@ -11734,6 +11736,29 @@ impl OpenCADStudio { (newest, true, name_of(newest_handle)) } + /// The colour ByLayer stands for in the Select Color panel: the layer of + /// the newest selected object, or the current layer for new objects. + fn color_picker_layer_color( + &self, + target: &crate::app::ColorPickTarget, + ) -> Option { + let i = self.active_tab; + let document = &self.tabs[i].scene.document; + let layer = match target { + crate::app::ColorPickTarget::Properties => self + .property_target_handles(i) + .into_iter() + .max() + .and_then(|handle| document.get_entity(handle)) + .map_or(self.tabs[i].active_layer.as_str(), |entity| { + entity.as_entity().layer() + }), + crate::app::ColorPickTarget::Ribbon => self.tabs[i].active_layer.as_str(), + _ => return None, + }; + document.layers.get(layer).map(|layer| layer.color) + } + /// Read the built-in colour books and the ones remembered in the /// settings, once per session. A loaded book replaces a built-in one of /// the same name. diff --git a/src/ui/color_select/picker.rs b/src/ui/color_select/picker.rs index c6cefccc3..cf4090223 100644 --- a/src/ui/color_select/picker.rs +++ b/src/ui/color_select/picker.rs @@ -104,6 +104,8 @@ pub struct ColorPicker { book_query: String, /// Why the last colour book did not load. status: Option, + /// What ByLayer looks like here: the layer's colour. + by_layer: Option, } impl ColorPicker { @@ -127,18 +129,23 @@ impl ColorPicker { book_page: 0, book_query: String::new(), status: None, + by_layer: None, } } /// Fill the Document and Color books tabs. `current_name` is the /// `BOOK$NAME` of the current colour; the Color books tab shows its page. + /// `by_layer` is the colour of the layer the colour is for, so ByLayer + /// shows that colour instead of gray. pub fn with_drawing( mut self, mut doc: Vec, recent: &[AcadColor], books: Arc>, current_name: Option, + by_layer: Option, ) -> Self { + self.by_layer = by_layer; document::sort(&mut doc, self.doc_sort, recent); self.doc = doc; self.recent = recent.to_vec(); @@ -330,6 +337,14 @@ impl ColorPicker { None } + /// How a colour looks; ByLayer takes the layer's colour when known. + fn shown(&self, color: AcadColor) -> Color { + match (color, self.by_layer) { + (AcadColor::ByLayer, Some(layer)) => acad_color_display(layer).0, + _ => acad_color_display(color).0, + } + } + fn pick_book(&mut self, index: usize) { let books = Arc::clone(&self.books); let Some(book) = books.get(self.book) else { @@ -366,8 +381,7 @@ impl ColorPicker { if self.tab == ColorPickerTab::Index { body = body.push(Space::new().height(Length::Fill)); } - let fill = - math::color_rgb(self.pending).map_or(Color::from_rgb8(128, 128, 128), rgb_color); + let fill = self.shown(self.pending); let info = match (&self.status, &self.pending_name) { (Some(status), _) => status.clone(), (None, Some(name)) => { @@ -469,8 +483,8 @@ impl ColorPicker { .width(Length::Fill) .height(Length::Fill) }; - let (current_bg, _) = acad_color_display(self.current); - let (new_bg, _) = acad_color_display(self.pending); + let current_bg = self.shown(self.current); + let new_bg = self.shown(self.pending); // A colour-book colour shows its own name, without the book. let name = |color: AcadColor, identity: &Option| match identity { Some(identity) => identity @@ -1336,7 +1350,7 @@ mod tests { #[test] fn book_colours_keep_their_name_until_edited() { - let mut p = picker(AcadColor::Index(30)).with_drawing(Vec::new(), &[], ral(), None); + let mut p = picker(AcadColor::Index(30)).with_drawing(Vec::new(), &[], ral(), None, None); p.update(ColorPickerMsg::PickBook(2)); assert_eq!(p.book_page, 1, "turns to the colour's page"); assert_eq!( @@ -1367,7 +1381,13 @@ mod tests { g: 113, b: 179, }) - .with_drawing(Vec::new(), &[], ral(), Some("RAL CLASSIC$RAL 5015".into())); + .with_drawing( + Vec::new(), + &[], + ral(), + Some("RAL CLASSIC$RAL 5015".into()), + None, + ); assert_eq!(p.book_selection(), Some(2)); assert_eq!(p.book_page, 1); } @@ -1377,7 +1397,7 @@ mod tests { // A new drawing's layer 0 is white. let doc = document::collect(&codec::CadDocument::new()); assert!(doc.iter().any(|c| c.color == AcadColor::Index(7))); - let mut p = picker(AcadColor::Index(30)).with_drawing(doc, &[], Arc::default(), None); + let mut p = picker(AcadColor::Index(30)).with_drawing(doc, &[], Arc::default(), None, None); p.update(ColorPickerMsg::Tab(ColorPickerTab::Document)); p.update(ColorPickerMsg::Arrow(ArrowKey::Right)); assert_eq!( @@ -1587,6 +1607,7 @@ mod tests { &[], books, None, + None, ); p.update(ColorPickerMsg::Tab(tab)); if name == "books" { diff --git a/src/ui/ribbon/color_dropdown.rs b/src/ui/ribbon/color_dropdown.rs index 7d070a186..2584310cb 100644 --- a/src/ui/ribbon/color_dropdown.rs +++ b/src/ui/ribbon/color_dropdown.rs @@ -157,12 +157,14 @@ fn divider<'a>() -> Element<'a, Message> { .into() } +/// `shown` overrides the swatch, so ByLayer can show the layer's colour. fn logical_row<'a>( color: AcadColor, cur_color: AcadColor, label: &'static str, + shown: Option, ) -> Element<'a, Message> { - let (bg, _) = acad_color_display(color); + let bg = shown.unwrap_or_else(|| acad_color_display(color).0); let selected = color == cur_color; let swatch = container( @@ -212,13 +214,15 @@ fn more_colors_row<'a>(active_color: AcadColor) -> Element<'a, Message> { } /// Builds the complete 5-section color dropdown panel element. +/// `layer_color` is the current layer's colour, shown on the ByLayer row. pub fn color_dropdown_panel<'a>( active_color: AcadColor, recent_colors: &[AcadColor], + layer_color: Option, ) -> Element<'a, Message> { // 1. ByLayer and ByBlock - let by_layer = logical_row(AcadColor::ByLayer, active_color, "ByLayer"); - let by_block = logical_row(AcadColor::ByBlock, active_color, "ByBlock"); + let by_layer = logical_row(AcadColor::ByLayer, active_color, "ByLayer", layer_color); + let by_block = logical_row(AcadColor::ByBlock, active_color, "ByBlock", None); let section1 = column![by_layer, by_block].spacing(2); // 2. 45-swatch Quick Pick Grid (5 rows × 9 columns) diff --git a/src/ui/ribbon/mod.rs b/src/ui/ribbon/mod.rs index 0d3777e2d..c67e39bdd 100644 --- a/src/ui/ribbon/mod.rs +++ b/src/ui/ribbon/mod.rs @@ -174,6 +174,14 @@ fn position_ribbon_dropdown<'a>( } impl Ribbon { + /// The current layer's colour: what ByLayer looks like for new objects. + pub fn active_layer_color(&self) -> Option { + self.layer_infos + .iter() + .find(|layer| layer.name == self.active_layer) + .map(|layer| layer.color) + } + /// The colour-book identity of the active colour, while the active colour /// is still the one picked from the book. pub fn active_color_name(&self) -> Option { @@ -1232,7 +1240,11 @@ impl Ribbon { win: (f32, f32), recent_colors: &[AcadColor], ) -> Option> { - let panel = color_dropdown::color_dropdown_panel(self.active_color, recent_colors); + let panel = color_dropdown::color_dropdown_panel( + self.active_color, + recent_colors, + self.active_layer_color(), + ); let (align_right, h_pad, top) = self.dd_anchor(PROP_COLOR_ID, color_dropdown::PANEL_W, win.0); diff --git a/src/ui/ribbon/widgets.rs b/src/ui/ribbon/widgets.rs index 989ea879b..fdd53ee38 100644 --- a/src/ui/ribbon/widgets.rs +++ b/src/ui/ribbon/widgets.rs @@ -1167,7 +1167,12 @@ pub(super) fn render_large<'a>(item: &RibbonItem, ctx: &RenderCtx<'_>) -> Elemen .width(Length::Fixed(PROP_W)) }; - let (color_swatch, _) = acad_color_display(active_color); + // ByLayer shows the current layer's colour. + let color_swatch = layer_infos + .iter() + .find(|layer| layer.name == active_layer) + .filter(|_| active_color == AcadColor::ByLayer) + .map_or_else(|| acad_color_display(active_color).0, |layer| layer.color); let color_row = prop_row( crate::ui::color_select::color_display_name(active_color), PROP_COLOR_ID,