diff --git a/assets/icons/ui/list.svg b/assets/icons/ui/list.svg new file mode 100644 index 000000000..ebfaa1599 --- /dev/null +++ b/assets/icons/ui/list.svg @@ -0,0 +1 @@ + diff --git a/locales/ar-SA/opencadstudio.ftl b/locales/ar-SA/opencadstudio.ftl index 8f492e2b9..31895c7a5 100644 --- a/locales/ar-SA/opencadstudio.ftl +++ b/locales/ar-SA/opencadstudio.ftl @@ -1359,6 +1359,8 @@ common = .color-recently-used = المستخدمة مؤخرًا .color-most-used = الأكثر استخدامًا .color-number = رقم اللون + .color-name-az = الاسم أ–ي + .color-name-za = الاسم ي–أ .color-in-drawing = الألوان في هذا الرسم .color-sort = فرز .color-no-drawing-colors = لا توجد ألوان في هذا الرسم بعد diff --git a/locales/bg-BG/opencadstudio.ftl b/locales/bg-BG/opencadstudio.ftl index 89a531b0b..43e184ba9 100644 --- a/locales/bg-BG/opencadstudio.ftl +++ b/locales/bg-BG/opencadstudio.ftl @@ -1346,6 +1346,8 @@ common = .color-recently-used = Наскоро използвани .color-most-used = Най-често използвани .color-number = Номер на цвят + .color-name-az = Име А–Я + .color-name-za = Име Я–А .color-in-drawing = Цветове в този чертеж .color-sort = Сортиране .color-no-drawing-colors = Все още няма цветове в този чертеж diff --git a/locales/cs-CZ/opencadstudio.ftl b/locales/cs-CZ/opencadstudio.ftl index 36bc5f400..a16245e9e 100644 --- a/locales/cs-CZ/opencadstudio.ftl +++ b/locales/cs-CZ/opencadstudio.ftl @@ -1346,6 +1346,8 @@ common = .color-recently-used = Naposledy použité .color-most-used = Nejpoužívanější .color-number = Číslo barvy + .color-name-az = Název A–Z + .color-name-za = Název Z–A .color-in-drawing = Barvy v tomto výkresu .color-sort = Řadit .color-no-drawing-colors = V tomto výkresu zatím nejsou žádné barvy diff --git a/locales/de-DE/opencadstudio.ftl b/locales/de-DE/opencadstudio.ftl index 518150aa6..8e2199112 100644 --- a/locales/de-DE/opencadstudio.ftl +++ b/locales/de-DE/opencadstudio.ftl @@ -1347,6 +1347,8 @@ common = .color-recently-used = Zuletzt verwendet .color-most-used = Am häufigsten verwendet .color-number = Farbnummer + .color-name-az = Name A–Z + .color-name-za = Name Z–A .color-in-drawing = Farben in dieser Zeichnung .color-sort = Sortieren .color-no-drawing-colors = Noch keine Farben in dieser Zeichnung diff --git a/locales/el-GR/opencadstudio.ftl b/locales/el-GR/opencadstudio.ftl index 9eb330ec7..cf52e3306 100644 --- a/locales/el-GR/opencadstudio.ftl +++ b/locales/el-GR/opencadstudio.ftl @@ -1348,6 +1348,8 @@ common = .color-recently-used = Πρόσφατα χρησιμοποιημένα .color-most-used = Πιο συχνά χρησιμοποιημένα .color-number = Αριθμός χρώματος + .color-name-az = Όνομα Α–Ω + .color-name-za = Όνομα Ω–Α .color-in-drawing = Χρώματα σε αυτό το σχέδιο .color-sort = Ταξινόμηση .color-no-drawing-colors = Δεν υπάρχουν ακόμη χρώματα σε αυτό το σχέδιο diff --git a/locales/en-US/opencadstudio.ftl b/locales/en-US/opencadstudio.ftl index 9c743dcdd..39c221c99 100644 --- a/locales/en-US/opencadstudio.ftl +++ b/locales/en-US/opencadstudio.ftl @@ -1347,6 +1347,8 @@ common = .color-recently-used = Recently used .color-most-used = Most used .color-number = Color number + .color-name-az = Name A–Z + .color-name-za = Name Z–A .color-in-drawing = Colors in this drawing .color-sort = Sort .color-no-drawing-colors = No colors in this drawing yet diff --git a/locales/es-ES/opencadstudio.ftl b/locales/es-ES/opencadstudio.ftl index a07925a3f..1459af092 100644 --- a/locales/es-ES/opencadstudio.ftl +++ b/locales/es-ES/opencadstudio.ftl @@ -1347,6 +1347,8 @@ common = .color-recently-used = Usados recientemente .color-most-used = Más usados .color-number = Número de color + .color-name-az = Nombre A–Z + .color-name-za = Nombre Z–A .color-in-drawing = Colores de este dibujo .color-sort = Ordenar .color-no-drawing-colors = Aún no hay colores en este dibujo diff --git a/locales/fi-FI/opencadstudio.ftl b/locales/fi-FI/opencadstudio.ftl index 59b67a113..24e76f90a 100644 --- a/locales/fi-FI/opencadstudio.ftl +++ b/locales/fi-FI/opencadstudio.ftl @@ -1346,6 +1346,8 @@ common = .color-recently-used = Viimeksi käytetyt .color-most-used = Eniten käytetyt .color-number = Värin numero + .color-name-az = Nimi A–Ö + .color-name-za = Nimi Ö–A .color-in-drawing = Tämän piirustuksen värit .color-sort = Lajittele .color-no-drawing-colors = Tässä piirustuksessa ei ole vielä värejä diff --git a/locales/fr-FR/opencadstudio.ftl b/locales/fr-FR/opencadstudio.ftl index 0068f6c15..b13f28875 100644 --- a/locales/fr-FR/opencadstudio.ftl +++ b/locales/fr-FR/opencadstudio.ftl @@ -1347,6 +1347,8 @@ common = .color-recently-used = Utilisées récemment .color-most-used = Les plus utilisées .color-number = Numéro de couleur + .color-name-az = Nom A–Z + .color-name-za = Nom Z–A .color-in-drawing = Couleurs de ce dessin .color-sort = Trier .color-no-drawing-colors = Aucune couleur dans ce dessin pour l'instant diff --git a/locales/hi-IN/opencadstudio.ftl b/locales/hi-IN/opencadstudio.ftl index 05aa07fd8..03b09327c 100644 --- a/locales/hi-IN/opencadstudio.ftl +++ b/locales/hi-IN/opencadstudio.ftl @@ -1335,6 +1335,8 @@ common = .color-recently-used = हाल ही में उपयोग किए गए .color-most-used = सबसे अधिक उपयोग किए गए .color-number = रंग संख्या + .color-name-az = नाम A–Z + .color-name-za = नाम Z–A .color-in-drawing = इस ड्रॉइंग के रंग .color-sort = क्रमबद्ध करें .color-no-drawing-colors = इस ड्रॉइंग में अभी तक कोई रंग नहीं है diff --git a/locales/hu-HU/opencadstudio.ftl b/locales/hu-HU/opencadstudio.ftl index 1e75ed541..95533f1eb 100644 --- a/locales/hu-HU/opencadstudio.ftl +++ b/locales/hu-HU/opencadstudio.ftl @@ -1346,6 +1346,8 @@ common = .color-recently-used = Legutóbb használt .color-most-used = Leggyakrabban használt .color-number = Színszám + .color-name-az = Név A–Z + .color-name-za = Név Z–A .color-in-drawing = Színek ebben a rajzban .color-sort = Rendezés .color-no-drawing-colors = Ebben a rajzban még nincsenek színek diff --git a/locales/it-IT/opencadstudio.ftl b/locales/it-IT/opencadstudio.ftl index 241c4f721..d20cd6253 100644 --- a/locales/it-IT/opencadstudio.ftl +++ b/locales/it-IT/opencadstudio.ftl @@ -1346,6 +1346,8 @@ common = .color-recently-used = Usati di recente .color-most-used = Più usati .color-number = Numero colore + .color-name-az = Nome A–Z + .color-name-za = Nome Z–A .color-in-drawing = Colori in questo disegno .color-sort = Ordina .color-no-drawing-colors = Ancora nessun colore in questo disegno diff --git a/locales/ja-JP/opencadstudio.ftl b/locales/ja-JP/opencadstudio.ftl index 3e3d9709d..341ca7b0c 100644 --- a/locales/ja-JP/opencadstudio.ftl +++ b/locales/ja-JP/opencadstudio.ftl @@ -1337,6 +1337,8 @@ common = .color-recently-used = 最近使用した色 .color-most-used = 使用頻度の高い色 .color-number = 色番号 + .color-name-az = 名前 (昇順) + .color-name-za = 名前 (降順) .color-in-drawing = この図面の色 .color-sort = 並べ替え .color-no-drawing-colors = この図面にはまだ色がありません diff --git a/locales/ko-KR/opencadstudio.ftl b/locales/ko-KR/opencadstudio.ftl index 0c6364171..8feda62e0 100644 --- a/locales/ko-KR/opencadstudio.ftl +++ b/locales/ko-KR/opencadstudio.ftl @@ -1346,6 +1346,8 @@ common = .color-recently-used = 최근 사용 .color-most-used = 가장 많이 사용 .color-number = 색상 번호 + .color-name-az = 이름 오름차순 + .color-name-za = 이름 내림차순 .color-in-drawing = 이 도면의 색상 .color-sort = 정렬 .color-no-drawing-colors = 이 도면에는 아직 색상이 없습니다 diff --git a/locales/lo-LA/opencadstudio.ftl b/locales/lo-LA/opencadstudio.ftl index 859458ff0..69971103d 100644 --- a/locales/lo-LA/opencadstudio.ftl +++ b/locales/lo-LA/opencadstudio.ftl @@ -1352,6 +1352,8 @@ common = .color-recently-used = ໃຊ້ຫຼ້າສຸດ .color-most-used = ໃຊ້ຫຼາຍທີ່ສຸດ .color-number = ເລກສີ + .color-name-az = ຊື່ A–Z + .color-name-za = ຊື່ Z–A .color-in-drawing = ສີໃນແບບແຕ້ມນີ້ .color-sort = ຈັດລຽງ .color-no-drawing-colors = ຍັງບໍ່ມີສີໃນແບບແຕ້ມນີ້ diff --git a/locales/nl-NL/opencadstudio.ftl b/locales/nl-NL/opencadstudio.ftl index f7d735880..8be90e920 100644 --- a/locales/nl-NL/opencadstudio.ftl +++ b/locales/nl-NL/opencadstudio.ftl @@ -1345,6 +1345,8 @@ common = .color-recently-used = Recent gebruikt .color-most-used = Meest gebruikt .color-number = Kleurnummer + .color-name-az = Naam A–Z + .color-name-za = Naam Z–A .color-in-drawing = Kleuren in deze tekening .color-sort = Sorteren .color-no-drawing-colors = Nog geen kleuren in deze tekening diff --git a/locales/pl-PL/opencadstudio.ftl b/locales/pl-PL/opencadstudio.ftl index 0852391c9..b7408ba68 100644 --- a/locales/pl-PL/opencadstudio.ftl +++ b/locales/pl-PL/opencadstudio.ftl @@ -1346,6 +1346,8 @@ common = .color-recently-used = Ostatnio używane .color-most-used = Najczęściej używane .color-number = Numer koloru + .color-name-az = Nazwa A–Z + .color-name-za = Nazwa Z–A .color-in-drawing = Kolory w tym rysunku .color-sort = Sortuj .color-no-drawing-colors = Brak kolorów w tym rysunku diff --git a/locales/pt-BR/opencadstudio.ftl b/locales/pt-BR/opencadstudio.ftl index 33fa9e2e8..1eb42528f 100644 --- a/locales/pt-BR/opencadstudio.ftl +++ b/locales/pt-BR/opencadstudio.ftl @@ -1347,6 +1347,8 @@ common = .color-recently-used = Usadas recentemente .color-most-used = Mais usadas .color-number = Número da cor + .color-name-az = Nome A–Z + .color-name-za = Nome Z–A .color-in-drawing = Cores neste desenho .color-sort = Ordenar .color-no-drawing-colors = Ainda não há cores neste desenho diff --git a/locales/ru-RU/opencadstudio.ftl b/locales/ru-RU/opencadstudio.ftl index 4778249cf..98ae70a65 100644 --- a/locales/ru-RU/opencadstudio.ftl +++ b/locales/ru-RU/opencadstudio.ftl @@ -1350,6 +1350,8 @@ common = .color-recently-used = Недавно использованные .color-most-used = Чаще всего используемые .color-number = Номер цвета + .color-name-az = Имя А–Я + .color-name-za = Имя Я–А .color-in-drawing = Цвета в этом чертеже .color-sort = Сортировка .color-no-drawing-colors = В этом чертеже пока нет цветов diff --git a/locales/tr-TR/opencadstudio.ftl b/locales/tr-TR/opencadstudio.ftl index c94918f97..ce888b89b 100644 --- a/locales/tr-TR/opencadstudio.ftl +++ b/locales/tr-TR/opencadstudio.ftl @@ -1333,6 +1333,8 @@ common = .color-recently-used = Son kullanılanlar .color-most-used = En çok kullanılanlar .color-number = Renk numarası + .color-name-az = Ad A–Z + .color-name-za = Ad Z–A .color-in-drawing = Bu çizimdeki renkler .color-sort = Sırala .color-no-drawing-colors = Bu çizimde henüz renk yok diff --git a/locales/zh-CN/opencadstudio.ftl b/locales/zh-CN/opencadstudio.ftl index d14c18f2c..a0c09867c 100644 --- a/locales/zh-CN/opencadstudio.ftl +++ b/locales/zh-CN/opencadstudio.ftl @@ -1334,6 +1334,8 @@ common = .color-recently-used = 最近使用 .color-most-used = 最常使用 .color-number = 颜色编号 + .color-name-az = 名称 A–Z + .color-name-za = 名称 Z–A .color-in-drawing = 此图形中的颜色 .color-sort = 排序 .color-no-drawing-colors = 此图形中还没有颜色 diff --git a/locales/zh-TW/opencadstudio.ftl b/locales/zh-TW/opencadstudio.ftl index fec601b75..fc5989507 100644 --- a/locales/zh-TW/opencadstudio.ftl +++ b/locales/zh-TW/opencadstudio.ftl @@ -1346,6 +1346,8 @@ common = .color-recently-used = 最近使用 .color-most-used = 最常使用 .color-number = 顏色編號 + .color-name-az = 名稱 A–Z + .color-name-za = 名稱 Z–A .color-in-drawing = 此圖面中的顏色 .color-sort = 排序 .color-no-drawing-colors = 此圖面中還沒有顏色 diff --git a/src/app/command_driver/entity_commit.rs b/src/app/command_driver/entity_commit.rs index 85c3dfc19..3416e9015 100644 --- a/src/app/command_driver/entity_commit.rs +++ b/src/app/command_driver/entity_commit.rs @@ -358,7 +358,11 @@ impl OpenCADStudio { if layer != "0" || entity.as_entity().layer().is_empty() { entity.as_entity_mut().set_layer(layer); } - crate::scene::view::dispatch::apply_color(&mut entity, self.ribbon.active_color); + crate::scene::view::dispatch::apply_named_color( + &mut entity, + self.ribbon.active_color, + self.ribbon.active_color_name(), + ); crate::scene::view::dispatch::apply_common_prop( &mut entity, "linetype", @@ -476,7 +480,11 @@ impl OpenCADStudio { if layer != "0" || entity.as_entity().layer().is_empty() { entity.as_entity_mut().set_layer(layer); } - crate::scene::view::dispatch::apply_color(&mut entity, self.ribbon.active_color); + crate::scene::view::dispatch::apply_named_color( + &mut entity, + self.ribbon.active_color, + self.ribbon.active_color_name(), + ); crate::scene::view::dispatch::apply_common_prop( &mut entity, "linetype", diff --git a/src/app/properties.rs b/src/app/properties.rs index c4b2ff463..4d82fcc7b 100644 --- a/src/app/properties.rs +++ b/src/app/properties.rs @@ -3149,7 +3149,11 @@ handles={handles_ms:.1} panel={:.1} ribbon={ribbon_ms:.1} tail={:.1} selected={} } if !preserve_entity_style { - crate::scene::view::dispatch::apply_color(&mut entity, self.ribbon.active_color); + crate::scene::view::dispatch::apply_named_color( + &mut entity, + self.ribbon.active_color, + self.ribbon.active_color_name(), + ); crate::scene::view::dispatch::apply_common_prop( &mut entity, "linetype", diff --git a/src/app/update/mod.rs b/src/app/update/mod.rs index 1211eff5b..1e4b217b2 100644 --- a/src/app/update/mod.rs +++ b/src/app/update/mod.rs @@ -11699,6 +11699,9 @@ impl OpenCADStudio { }; match target { crate::app::ColorPickTarget::Properties => {} + crate::app::ColorPickTarget::Ribbon => { + return (color, false, self.ribbon.active_color_name()); + } crate::app::ColorPickTarget::Layer(layer) => { let name = document.layers.get(layer).and_then(|layer| { match (&layer.book_name, &layer.color_name) { @@ -11767,6 +11770,7 @@ impl OpenCADStudio { let handles = self.property_target_handles(i); if handles.is_empty() { let task = self.on_ribbon_color_changed(color); + self.ribbon.active_color_book = name.map(|name| (color, name)); self.refresh_properties(); return task; } diff --git a/src/app/update/style.rs b/src/app/update/style.rs index fc0db8af7..dfd15aff9 100644 --- a/src/app/update/style.rs +++ b/src/app/update/style.rs @@ -1215,7 +1215,11 @@ impl OpenCADStudio { Some(Message::PropColorFieldChanged { field, color }) } Some(crate::app::ColorPickTarget::MText) => Some(Message::MTextColorChanged(color)), - Some(crate::app::ColorPickTarget::Ribbon) => Some(Message::RibbonColorChanged(color)), + Some(crate::app::ColorPickTarget::Ribbon) => { + let task = self.update(Message::RibbonColorChanged(color)); + self.ribbon.active_color_book = name.map(|name| (color, name)); + return task; + } Some(crate::app::ColorPickTarget::Layer(layer)) => { let i = self.active_tab; match self.layer_panel_index(i, &layer) { diff --git a/src/locale_catalog.rs b/src/locale_catalog.rs index 18ecb5ed0..80b1bf903 100644 --- a/src/locale_catalog.rs +++ b/src/locale_catalog.rs @@ -4723,6 +4723,8 @@ pub(super) fn message_attribute(source: &str) -> Option<(&'static str, &'static "Recently used" => Some(("common", "color-recently-used")), "Most used" => Some(("common", "color-most-used")), "Color number" => Some(("common", "color-number")), + "Name A–Z" => Some(("common", "color-name-az")), + "Name Z–A" => Some(("common", "color-name-za")), "Colors in this drawing" => Some(("common", "color-in-drawing")), "Sort" => Some(("common", "color-sort")), "No colors in this drawing yet" => Some(("common", "color-no-drawing-colors")), diff --git a/src/ui/color_select/document.rs b/src/ui/color_select/document.rs index 9f976b66d..bbd1d0a88 100644 --- a/src/ui/color_select/document.rs +++ b/src/ui/color_select/document.rs @@ -21,21 +21,35 @@ pub struct DocColor { } impl DocColor { - /// The few characters drawn on the swatch: the index number, `RGB`, or - /// the first word of the colour book. + /// The text drawn on the swatch: the index number, `RGB`, or the + /// colour-book colour's own name. pub fn tag(&self) -> String { match (&self.name, self.color) { - (Some(name), _) => name - .split(['$', ' ']) - .next() - .unwrap_or_default() - .chars() - .take(5) - .collect(), + (Some(_), _) => self.label(), (None, AcadColor::Index(i)) => i.to_string(), _ => "RGB".to_string(), } } + + /// The name in the list view: the colour-book colour's own name (without + /// the book), `ACI n` or `#RRGGBB`. + pub fn label(&self) -> String { + match &self.name { + Some(name) => name + .split_once('$') + .map_or(name.as_str(), |(_, name)| name) + .to_string(), + None => math::short_name(self.color), + } + } +} + +/// Swatches or a list of named bars. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] +pub enum DocView { + #[default] + Grid, + List, } #[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] @@ -45,14 +59,18 @@ pub enum DocSort { Usage, Hue, Number, + NameAsc, + NameDesc, } impl DocSort { - pub const ALL: [DocSort; 4] = [ + pub const ALL: [DocSort; 6] = [ DocSort::Recent, DocSort::Usage, DocSort::Hue, DocSort::Number, + DocSort::NameAsc, + DocSort::NameDesc, ]; } @@ -63,6 +81,8 @@ impl std::fmt::Display for DocSort { DocSort::Usage => crate::t!("Most used"), DocSort::Hue => crate::t!("Color"), DocSort::Number => crate::t!("Color number"), + DocSort::NameAsc => crate::t!("Name A–Z"), + DocSort::NameDesc => crate::t!("Name Z–A"), }) } } @@ -163,6 +183,10 @@ pub fn sort(colors: &mut [DocColor], by: DocSort, recent: &[AcadColor]) { .then_with(|| a.name.cmp(&b.name)) .then_with(|| key(a.color).cmp(&key(b.color))) }), + DocSort::NameAsc => colors.sort_by_cached_key(|c| c.label().to_lowercase()), + DocSort::NameDesc => { + colors.sort_by_cached_key(|c| std::cmp::Reverse(c.label().to_lowercase())) + } } } @@ -201,7 +225,7 @@ mod tests { assert_eq!(colors[0].uses, 3); assert_eq!(colors[0].newest, Handle::new(3)); assert_eq!(colors[3].name, None, "an empty name is no name"); - assert_eq!(colors[2].tag(), "RAL"); + assert_eq!(colors[2].tag(), "RAL 5015"); assert_eq!(colors[0].tag(), "1"); assert_eq!(colors[1].tag(), "RGB"); } diff --git a/src/ui/color_select/editor.rs b/src/ui/color_select/editor.rs index 47970c9ab..4249e4c0f 100644 --- a/src/ui/color_select/editor.rs +++ b/src/ui/color_select/editor.rs @@ -15,15 +15,15 @@ use iced::{Background, Border, Color, Element, Gradient, Length, Radians, Theme} const ROW_HEIGHT: f32 = 26.0; const TRACK: f32 = 18.0; const STRIP_WIDTH: f32 = 22.0; -const ROW_GAP: f32 = 8.0; +const ROW_GAP: f32 = 6.0; const FIELD_HEIGHT: f32 = 96.0; const MODE_WIDTH: f32 = 48.0; const MODE_HEIGHT: f32 = 24.0; #[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] pub enum EditorMode { - Rgb, #[default] + Rgb, Hsb, Cmyk, } @@ -151,19 +151,19 @@ impl ColorEditor { /// `mode_end` sits at the far right of the mode buttons (the pipette); /// `hex_end` at the far right of the hex row (the nearest index colour). + /// With `fill` the field and hex row sit at the bottom of the space, so + /// they stay put when CMYK adds a fourth slider. pub fn view<'a>( &'a self, mode_end: Option>, hex_end: Option>, + fill: bool, ) -> Element<'a, Message> { - column![ - self.mode_row(mode_end), - self.slider_rows(), - self.field(), - self.hex_row(hex_end), - ] - .spacing(12) - .into() + let mut view = column![self.mode_row(mode_end), self.slider_rows()].spacing(12); + if fill { + view = view.push(Space::new().height(Length::Fill)); + } + view.push(self.field()).push(self.hex_row(hex_end)).into() } /// RGB, HSB and CMYK, with `end` at the far right. diff --git a/src/ui/color_select/picker.rs b/src/ui/color_select/picker.rs index c02c3723d..c6cefccc3 100644 --- a/src/ui/color_select/picker.rs +++ b/src/ui/color_select/picker.rs @@ -6,7 +6,7 @@ //! colour editor: no tabs, no index colours. use super::book::ColorBook; -use super::document::{self, DocColor, DocSort}; +use super::document::{self, DocColor, DocSort, DocView}; use super::editor::{rgb_color, ColorEditor, EditorMsg}; use super::eyedropper::{Eyedropper, EyedropperMsg}; use super::math; @@ -54,6 +54,7 @@ pub enum ColorPickerMsg { /// A colour of the Document tab, by its place in the list. PickDocument(usize), DocSort(DocSort), + DocView(DocView), /// Show another loaded colour book. Book(usize), BookPage(usize), @@ -94,6 +95,7 @@ pub struct ColorPicker { eyedropper: Option, doc: Vec, doc_sort: DocSort, + doc_view: DocView, /// This drawing's colours picked this session, newest first. recent: Vec, books: Arc>, @@ -118,6 +120,7 @@ impl ColorPicker { eyedropper: None, doc: Vec::new(), doc_sort: DocSort::default(), + doc_view: DocView::default(), recent: Vec::new(), books: Arc::default(), book: 0, @@ -284,6 +287,7 @@ impl ColorPicker { self.pending_name = name; } } + ColorPickerMsg::DocView(view) => self.doc_view = view, ColorPickerMsg::DocSort(by) => { self.doc_sort = by; document::sort(&mut self.doc, by, &self.recent); @@ -358,8 +362,8 @@ impl ColorPicker { // height across its tabs, with the info line at the bottom. let mut body = column![body].spacing(8); if !editor_only { - // Document and Color books fill the height themselves. - if matches!(self.tab, ColorPickerTab::Index | ColorPickerTab::TrueColor) { + // The other tabs fill the height themselves. + if self.tab == ColorPickerTab::Index { body = body.push(Space::new().height(Length::Fill)); } let fill = @@ -578,6 +582,11 @@ impl ColorPicker { .on_select(|by| picker_msg(ColorPickerMsg::DocSort(by))) .text_size(12) .padding([3, 6]), + row![ + self.view_button(crate::ui::icons::GRID, DocView::Grid), + self.view_button(crate::ui::icons::LIST, DocView::List), + ] + .spacing(2), ] .spacing(6) .align_y(iced::Center); @@ -589,9 +598,59 @@ impl ColorPicker { .spacing(10) .into(); } - let grid = self.doc.chunks(DOC_COLUMNS).enumerate().fold( - column![].spacing(4), - |grid, (r, chunk)| { + let list: Element<'_, Message> = if self.doc_view == DocView::List { + self.doc + .iter() + .enumerate() + .fold(column![].spacing(2), |list, (i, entry)| { + let fill = math::color_rgb(entry.color) + .map_or(Color::from_rgb8(128, 128, 128), rgb_color); + let selected = self.pending == entry.color && self.pending_name == entry.name; + list.push( + color_bar( + entry.label(), + fill, + selected, + ColorPickerMsg::PickDocument(i), + ) + .height(26), + ) + }) + .into() + } else { + self.doc_grid() + }; + column![ + header, + scrollable(list).height(Length::Fill).spacing(4).direction( + scrollable::Direction::Vertical( + scrollable::Scrollbar::new().width(4).scroller_width(4) + ) + ), + ] + .spacing(10) + .into() + } + + /// Grid or list toggle for the Document tab. + fn view_button(&self, icon: &'static [u8], view: DocView) -> Element<'_, Message> { + let active = self.doc_view == view; + button( + svg(crate::ui::icons::themed_handle(icon)) + .width(14) + .height(14), + ) + .on_press(picker_msg(ColorPickerMsg::DocView(view))) + .padding(5) + .style(move |theme: &Theme, status| toggle_style(theme, active, status)) + .into() + } + + fn doc_grid(&self) -> Element<'_, Message> { + self.doc + .chunks(DOC_COLUMNS) + .enumerate() + .fold(column![].spacing(4), |grid, (r, chunk)| { let line = chunk .iter() .enumerate() @@ -601,18 +660,8 @@ impl ColorPicker { let line = (chunk.len()..DOC_COLUMNS) .fold(line, |line, _| line.push(Space::new().width(Length::Fill))); grid.push(line) - }, - ); - column![ - header, - scrollable(grid).height(Length::Fill).spacing(4).direction( - scrollable::Direction::Vertical( - scrollable::Scrollbar::new().width(4).scroller_width(4) - ) - ), - ] - .spacing(10) - .into() + }) + .into() } fn doc_swatch<'a>(&self, i: usize, entry: &'a DocColor) -> Element<'a, Message> { @@ -627,7 +676,8 @@ impl ColorPicker { ) .align_y(iced::Bottom) .padding([1, 4]) - .height(Length::Fill), + .height(Length::Fill) + .clip(true), ) .on_press(picker_msg(ColorPickerMsg::PickDocument(i))) .padding(0) @@ -863,7 +913,7 @@ impl ColorPicker { ) }; let nearest = (!self.editor_only()).then(|| self.nearest_button()); - self.editor.view(pipette, nearest) + self.editor.view(pipette, nearest, !self.editor_only()) } fn nearest_button(&self) -> Element<'_, Message> { @@ -985,24 +1035,37 @@ fn book_bar( color: &super::book::BookColor, selected: Option, ) -> Element<'_, Message> { - let fill = rgb_color(color.rgb); + color_bar( + &color.name, + rgb_color(color.rgb), + selected == Some(i), + ColorPickerMsg::PickBook(i), + ) + .height(Length::Fill) + .into() +} + +/// A full-width colour bar with a name: the Color books pages and the +/// Document tab's list. +fn color_bar<'a>( + name: impl text::IntoFragment<'a>, + fill: Color, + selected: bool, + on_press: ColorPickerMsg, +) -> button::Button<'a, Message> { button( container( - text(&color.name) + text(name) .size(12) .font(iced::Font::MONOSPACE) .color(ink(fill)), ) .center(Length::Fill), ) - .on_press(picker_msg(ColorPickerMsg::PickBook(i))) + .on_press(picker_msg(on_press)) .padding(0) .width(Length::Fill) - .height(Length::Fill) - .style(move |theme: &Theme, status| { - swatch_button_style(theme, status, fill, selected == Some(i)) - }) - .into() + .style(move |theme: &Theme, status| swatch_button_style(theme, status, fill, selected)) } /// A short gray note in the middle of the free space. diff --git a/src/ui/icons.rs b/src/ui/icons.rs index 35caaca19..a37c7ccdd 100644 --- a/src/ui/icons.rs +++ b/src/ui/icons.rs @@ -81,6 +81,7 @@ pub static PIN_ACTIVE: &[u8] = include_bytes!("../../assets/icons/ui/pin_active. pub static SPLIT_V: &[u8] = include_bytes!("../../assets/icons/ui/split_v.svg"); pub static SPLIT_H: &[u8] = include_bytes!("../../assets/icons/ui/split_h.svg"); pub static GRID: &[u8] = include_bytes!("../../assets/icons/ui/grid.svg"); +pub static LIST: &[u8] = include_bytes!("../../assets/icons/ui/list.svg"); pub static SNAP: &[u8] = include_bytes!("../../assets/icons/ui/snap.svg"); pub static DOC_NEW: &[u8] = include_bytes!("../../assets/icons/ui/doc_new.svg"); pub static DOC: &[u8] = include_bytes!("../../assets/icons/ui/doc.svg"); diff --git a/src/ui/ribbon/mod.rs b/src/ui/ribbon/mod.rs index 149f4e9a1..0d3777e2d 100644 --- a/src/ui/ribbon/mod.rs +++ b/src/ui/ribbon/mod.rs @@ -82,6 +82,9 @@ pub struct Ribbon { pub layer_filter: String, /// Active object color — ACI / ByLayer / ByBlock. pub active_color: AcadColor, + /// Colour-book identity (`BOOK$NAME`) of a colour picked from a colour + /// book, with the colour it was picked as; see `active_color_name`. + pub active_color_book: Option<(AcadColor, String)>, /// Active linetype override ("ByLayer", "Continuous", …). pub active_linetype: String, /// Active lineweight. @@ -171,6 +174,15 @@ fn position_ribbon_dropdown<'a>( } impl Ribbon { + /// 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 { + self.active_color_book + .as_ref() + .filter(|(color, _)| *color == self.active_color) + .map(|(_, name)| name.clone()) + } + pub fn new() -> Self { Self { modules: all_ribbon_modules(), @@ -195,6 +207,7 @@ impl Ribbon { layer_infos: vec![], layer_filter: String::new(), active_color: AcadColor::ByLayer, + active_color_book: None, active_linetype: "ByLayer".to_string(), active_lineweight: LineWeight::ByLayer, available_linetypes: vec![LinetypeItem {