From e13e93966bcc65b0b6a6a8f8b18844cc0876386e Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 14 Oct 2026 17:46:45 +0000 Subject: [PATCH] Select Color: search boxes, readable icon buttons, cleaner Document and Color books layout - Info line shows a colour-book colour as "BOOK - NAME". - Document tab: a search box (by name) replaces the "Colors in this drawing" heading; grid swatches no longer carry text; larger grid/list icons, dark on the accent colour when active, like the OK button. - Color books tab: no "Color book"/"Find" labels; the book list is as wide as the colour bars, and the search box (magnifier, gray "Search") and load button sit over the page strip and RGB values, all 28 px high; the load button and page arrows use the button's dark text colour. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_013rGmDUNr1hUf4zo1X3dak8 --- assets/icons/ui/search.svg | 1 + locales/ar-SA/opencadstudio.ftl | 1 - locales/bg-BG/opencadstudio.ftl | 1 - locales/cs-CZ/opencadstudio.ftl | 1 - locales/de-DE/opencadstudio.ftl | 1 - locales/el-GR/opencadstudio.ftl | 1 - locales/en-US/opencadstudio.ftl | 1 - locales/es-ES/opencadstudio.ftl | 1 - locales/fi-FI/opencadstudio.ftl | 1 - locales/fr-FR/opencadstudio.ftl | 1 - locales/hi-IN/opencadstudio.ftl | 1 - locales/hu-HU/opencadstudio.ftl | 1 - locales/it-IT/opencadstudio.ftl | 1 - locales/ja-JP/opencadstudio.ftl | 1 - locales/ko-KR/opencadstudio.ftl | 1 - locales/lo-LA/opencadstudio.ftl | 1 - locales/nl-NL/opencadstudio.ftl | 1 - locales/pl-PL/opencadstudio.ftl | 1 - locales/pt-BR/opencadstudio.ftl | 1 - locales/ru-RU/opencadstudio.ftl | 1 - locales/tr-TR/opencadstudio.ftl | 1 - locales/zh-CN/opencadstudio.ftl | 1 - locales/zh-TW/opencadstudio.ftl | 1 - src/locale_catalog.rs | 1 - src/ui/color_select/document.rs | 16 +-- src/ui/color_select/picker.rs | 203 ++++++++++++++++++++------------ src/ui/icons.rs | 1 + 27 files changed, 134 insertions(+), 110 deletions(-) create mode 100644 assets/icons/ui/search.svg diff --git a/assets/icons/ui/search.svg b/assets/icons/ui/search.svg new file mode 100644 index 000000000..aa0347716 --- /dev/null +++ b/assets/icons/ui/search.svg @@ -0,0 +1 @@ + diff --git a/locales/ar-SA/opencadstudio.ftl b/locales/ar-SA/opencadstudio.ftl index 31895c7a5..643e7dab9 100644 --- a/locales/ar-SA/opencadstudio.ftl +++ b/locales/ar-SA/opencadstudio.ftl @@ -1361,7 +1361,6 @@ common = .color-number = رقم اللون .color-name-az = الاسم أ–ي .color-name-za = الاسم ي–أ - .color-in-drawing = الألوان في هذا الرسم .color-sort = فرز .color-no-drawing-colors = لا توجد ألوان في هذا الرسم بعد .color-books = كتب الألوان diff --git a/locales/bg-BG/opencadstudio.ftl b/locales/bg-BG/opencadstudio.ftl index 43e184ba9..8bc2bce14 100644 --- a/locales/bg-BG/opencadstudio.ftl +++ b/locales/bg-BG/opencadstudio.ftl @@ -1348,7 +1348,6 @@ common = .color-number = Номер на цвят .color-name-az = Име А–Я .color-name-za = Име Я–А - .color-in-drawing = Цветове в този чертеж .color-sort = Сортиране .color-no-drawing-colors = Все още няма цветове в този чертеж .color-books = Цветови каталози diff --git a/locales/cs-CZ/opencadstudio.ftl b/locales/cs-CZ/opencadstudio.ftl index a16245e9e..a10b59019 100644 --- a/locales/cs-CZ/opencadstudio.ftl +++ b/locales/cs-CZ/opencadstudio.ftl @@ -1348,7 +1348,6 @@ common = .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 .color-books = Barevné vzorníky diff --git a/locales/de-DE/opencadstudio.ftl b/locales/de-DE/opencadstudio.ftl index 8e2199112..7ec27fa3c 100644 --- a/locales/de-DE/opencadstudio.ftl +++ b/locales/de-DE/opencadstudio.ftl @@ -1349,7 +1349,6 @@ common = .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 .color-books = Farbbücher diff --git a/locales/el-GR/opencadstudio.ftl b/locales/el-GR/opencadstudio.ftl index cf52e3306..2d739abfd 100644 --- a/locales/el-GR/opencadstudio.ftl +++ b/locales/el-GR/opencadstudio.ftl @@ -1350,7 +1350,6 @@ common = .color-number = Αριθμός χρώματος .color-name-az = Όνομα Α–Ω .color-name-za = Όνομα Ω–Α - .color-in-drawing = Χρώματα σε αυτό το σχέδιο .color-sort = Ταξινόμηση .color-no-drawing-colors = Δεν υπάρχουν ακόμη χρώματα σε αυτό το σχέδιο .color-books = Βιβλία χρωμάτων diff --git a/locales/en-US/opencadstudio.ftl b/locales/en-US/opencadstudio.ftl index 39c221c99..de4a4cd78 100644 --- a/locales/en-US/opencadstudio.ftl +++ b/locales/en-US/opencadstudio.ftl @@ -1349,7 +1349,6 @@ common = .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 .color-books = Color Books diff --git a/locales/es-ES/opencadstudio.ftl b/locales/es-ES/opencadstudio.ftl index 1459af092..6ccf8988e 100644 --- a/locales/es-ES/opencadstudio.ftl +++ b/locales/es-ES/opencadstudio.ftl @@ -1349,7 +1349,6 @@ common = .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 .color-books = Libros de colores diff --git a/locales/fi-FI/opencadstudio.ftl b/locales/fi-FI/opencadstudio.ftl index 24e76f90a..7dff34f02 100644 --- a/locales/fi-FI/opencadstudio.ftl +++ b/locales/fi-FI/opencadstudio.ftl @@ -1348,7 +1348,6 @@ common = .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ä .color-books = Värikirjat diff --git a/locales/fr-FR/opencadstudio.ftl b/locales/fr-FR/opencadstudio.ftl index b13f28875..6e514a155 100644 --- a/locales/fr-FR/opencadstudio.ftl +++ b/locales/fr-FR/opencadstudio.ftl @@ -1349,7 +1349,6 @@ common = .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 .color-books = Carnets de couleurs diff --git a/locales/hi-IN/opencadstudio.ftl b/locales/hi-IN/opencadstudio.ftl index 03b09327c..d5d58eb92 100644 --- a/locales/hi-IN/opencadstudio.ftl +++ b/locales/hi-IN/opencadstudio.ftl @@ -1337,7 +1337,6 @@ common = .color-number = रंग संख्या .color-name-az = नाम A–Z .color-name-za = नाम Z–A - .color-in-drawing = इस ड्रॉइंग के रंग .color-sort = क्रमबद्ध करें .color-no-drawing-colors = इस ड्रॉइंग में अभी तक कोई रंग नहीं है .color-books = रंग पुस्तकें diff --git a/locales/hu-HU/opencadstudio.ftl b/locales/hu-HU/opencadstudio.ftl index 95533f1eb..ae28ca775 100644 --- a/locales/hu-HU/opencadstudio.ftl +++ b/locales/hu-HU/opencadstudio.ftl @@ -1348,7 +1348,6 @@ common = .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 .color-books = Színkönyvek diff --git a/locales/it-IT/opencadstudio.ftl b/locales/it-IT/opencadstudio.ftl index d20cd6253..d19c64fd4 100644 --- a/locales/it-IT/opencadstudio.ftl +++ b/locales/it-IT/opencadstudio.ftl @@ -1348,7 +1348,6 @@ common = .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 .color-books = Album colori diff --git a/locales/ja-JP/opencadstudio.ftl b/locales/ja-JP/opencadstudio.ftl index 341ca7b0c..1d3cc642d 100644 --- a/locales/ja-JP/opencadstudio.ftl +++ b/locales/ja-JP/opencadstudio.ftl @@ -1339,7 +1339,6 @@ common = .color-number = 色番号 .color-name-az = 名前 (昇順) .color-name-za = 名前 (降順) - .color-in-drawing = この図面の色 .color-sort = 並べ替え .color-no-drawing-colors = この図面にはまだ色がありません .color-books = カラー ブック diff --git a/locales/ko-KR/opencadstudio.ftl b/locales/ko-KR/opencadstudio.ftl index 8feda62e0..81b836734 100644 --- a/locales/ko-KR/opencadstudio.ftl +++ b/locales/ko-KR/opencadstudio.ftl @@ -1348,7 +1348,6 @@ common = .color-number = 색상 번호 .color-name-az = 이름 오름차순 .color-name-za = 이름 내림차순 - .color-in-drawing = 이 도면의 색상 .color-sort = 정렬 .color-no-drawing-colors = 이 도면에는 아직 색상이 없습니다 .color-books = 색상표 diff --git a/locales/lo-LA/opencadstudio.ftl b/locales/lo-LA/opencadstudio.ftl index 69971103d..e0a414a24 100644 --- a/locales/lo-LA/opencadstudio.ftl +++ b/locales/lo-LA/opencadstudio.ftl @@ -1354,7 +1354,6 @@ common = .color-number = ເລກສີ .color-name-az = ຊື່ A–Z .color-name-za = ຊື່ Z–A - .color-in-drawing = ສີໃນແບບແຕ້ມນີ້ .color-sort = ຈັດລຽງ .color-no-drawing-colors = ຍັງບໍ່ມີສີໃນແບບແຕ້ມນີ້ .color-books = ປຶ້ມສີ diff --git a/locales/nl-NL/opencadstudio.ftl b/locales/nl-NL/opencadstudio.ftl index 8be90e920..2da6d4c6d 100644 --- a/locales/nl-NL/opencadstudio.ftl +++ b/locales/nl-NL/opencadstudio.ftl @@ -1347,7 +1347,6 @@ common = .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 .color-books = Kleurboeken diff --git a/locales/pl-PL/opencadstudio.ftl b/locales/pl-PL/opencadstudio.ftl index b7408ba68..1874e7b4e 100644 --- a/locales/pl-PL/opencadstudio.ftl +++ b/locales/pl-PL/opencadstudio.ftl @@ -1348,7 +1348,6 @@ common = .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 .color-books = Wzorniki kolorów diff --git a/locales/pt-BR/opencadstudio.ftl b/locales/pt-BR/opencadstudio.ftl index 1eb42528f..a879ecaac 100644 --- a/locales/pt-BR/opencadstudio.ftl +++ b/locales/pt-BR/opencadstudio.ftl @@ -1349,7 +1349,6 @@ common = .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 .color-books = Catálogos de cores diff --git a/locales/ru-RU/opencadstudio.ftl b/locales/ru-RU/opencadstudio.ftl index 98ae70a65..bd1b67d28 100644 --- a/locales/ru-RU/opencadstudio.ftl +++ b/locales/ru-RU/opencadstudio.ftl @@ -1352,7 +1352,6 @@ common = .color-number = Номер цвета .color-name-az = Имя А–Я .color-name-za = Имя Я–А - .color-in-drawing = Цвета в этом чертеже .color-sort = Сортировка .color-no-drawing-colors = В этом чертеже пока нет цветов .color-books = Альбомы цветов diff --git a/locales/tr-TR/opencadstudio.ftl b/locales/tr-TR/opencadstudio.ftl index ce888b89b..6f8efd839 100644 --- a/locales/tr-TR/opencadstudio.ftl +++ b/locales/tr-TR/opencadstudio.ftl @@ -1335,7 +1335,6 @@ common = .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 .color-books = Renk kitapları diff --git a/locales/zh-CN/opencadstudio.ftl b/locales/zh-CN/opencadstudio.ftl index a0c09867c..797197fdd 100644 --- a/locales/zh-CN/opencadstudio.ftl +++ b/locales/zh-CN/opencadstudio.ftl @@ -1336,7 +1336,6 @@ common = .color-number = 颜色编号 .color-name-az = 名称 A–Z .color-name-za = 名称 Z–A - .color-in-drawing = 此图形中的颜色 .color-sort = 排序 .color-no-drawing-colors = 此图形中还没有颜色 .color-books = 配色系统 diff --git a/locales/zh-TW/opencadstudio.ftl b/locales/zh-TW/opencadstudio.ftl index fc5989507..b08b84662 100644 --- a/locales/zh-TW/opencadstudio.ftl +++ b/locales/zh-TW/opencadstudio.ftl @@ -1348,7 +1348,6 @@ common = .color-number = 顏色編號 .color-name-az = 名稱 A–Z .color-name-za = 名稱 Z–A - .color-in-drawing = 此圖面中的顏色 .color-sort = 排序 .color-no-drawing-colors = 此圖面中還沒有顏色 .color-books = 配色系統 diff --git a/src/locale_catalog.rs b/src/locale_catalog.rs index 80b1bf903..3403cd85c 100644 --- a/src/locale_catalog.rs +++ b/src/locale_catalog.rs @@ -4725,7 +4725,6 @@ pub(super) fn message_attribute(source: &str) -> Option<(&'static str, &'static "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")), "Color Books" => Some(("common", "color-books")), diff --git a/src/ui/color_select/document.rs b/src/ui/color_select/document.rs index bbd1d0a88..c257f9c1b 100644 --- a/src/ui/color_select/document.rs +++ b/src/ui/color_select/document.rs @@ -21,16 +21,6 @@ pub struct DocColor { } impl DocColor { - /// 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(_), _) => 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 { @@ -225,9 +215,9 @@ 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 5015"); - assert_eq!(colors[0].tag(), "1"); - assert_eq!(colors[1].tag(), "RGB"); + assert_eq!(colors[2].label(), "RAL 5015"); + assert_eq!(colors[0].label(), "ACI 1"); + assert_eq!(colors[1].label(), "#39BFFC"); } #[test] diff --git a/src/ui/color_select/picker.rs b/src/ui/color_select/picker.rs index cf4090223..f02057a44 100644 --- a/src/ui/color_select/picker.rs +++ b/src/ui/color_select/picker.rs @@ -29,6 +29,10 @@ const BODY_HEIGHT: f32 = 368.0; const DOC_COLUMNS: usize = 8; /// Search matches shown at once in the Color books tab. const PAGE_BARS: usize = 7; +/// Height of the search boxes, dropdowns and icon buttons. +const CONTROL_HEIGHT: f32 = 28.0; +/// Width of the page strip, the RGB values and the gap between them. +const SIDE_WIDTH: f32 = 26.0 + 10.0 + 104.0; #[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] pub enum ColorPickerTab { @@ -55,6 +59,8 @@ pub enum ColorPickerMsg { PickDocument(usize), DocSort(DocSort), DocView(DocView), + /// Filter the Document tab by name. + DocQuery(String), /// Show another loaded colour book. Book(usize), BookPage(usize), @@ -96,6 +102,7 @@ pub struct ColorPicker { doc: Vec, doc_sort: DocSort, doc_view: DocView, + doc_query: String, /// This drawing's colours picked this session, newest first. recent: Vec, books: Arc>, @@ -123,6 +130,7 @@ impl ColorPicker { doc: Vec::new(), doc_sort: DocSort::default(), doc_view: DocView::default(), + doc_query: String::new(), recent: Vec::new(), books: Arc::default(), book: 0, @@ -295,6 +303,7 @@ impl ColorPicker { } } ColorPickerMsg::DocView(view) => self.doc_view = view, + ColorPickerMsg::DocQuery(query) => self.doc_query = query, ColorPickerMsg::DocSort(by) => { self.doc_sort = by; document::sort(&mut self.doc, by, &self.recent); @@ -386,7 +395,7 @@ impl ColorPicker { (Some(status), _) => status.clone(), (None, Some(name)) => { let (r, g, b) = math::color_rgb(self.pending).unwrap_or_default(); - format!("{name} · RGB {r}, {g}, {b}") + format!("{} · RGB {r}, {g}, {b}", name.replacen('$', " - ", 1)) } (None, None) => math::describe(self.pending), }; @@ -586,16 +595,11 @@ impl ColorPicker { fn document_tab(&self) -> Element<'_, Message> { let header = row![ - text(t!("Colors in this drawing")).size(11), - text(format!("· {}", self.doc.len())) - .size(11) - .style(muted_text), - Space::new().width(Length::Fill), - text(t!("Sort")).size(11).style(muted_text), + search_box(&self.doc_query, |query| ColorPickerMsg::DocQuery(query)), pick_list(Some(self.doc_sort), &DocSort::ALL[..], DocSort::to_string) .on_select(|by| picker_msg(ColorPickerMsg::DocSort(by))) .text_size(12) - .padding([3, 6]), + .padding([6, 8]), row![ self.view_button(crate::ui::icons::GRID, DocView::Grid), self.view_button(crate::ui::icons::LIST, DocView::List), @@ -612,11 +616,23 @@ impl ColorPicker { .spacing(10) .into(); } + // Indices stay those of `doc`, which the pick messages refer to. + let query = self.doc_query.trim().to_lowercase(); + let shown: Vec<(usize, &DocColor)> = self + .doc + .iter() + .enumerate() + .filter(|(_, entry)| query.is_empty() || entry.label().to_lowercase().contains(&query)) + .collect(); + if shown.is_empty() { + return column![header, empty_note(t!("No colors match").into_owned())] + .spacing(10) + .into(); + } let list: Element<'_, Message> = if self.doc_view == DocView::List { - self.doc + shown .iter() - .enumerate() - .fold(column![].spacing(2), |list, (i, entry)| { + .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; @@ -632,7 +648,7 @@ impl ColorPicker { }) .into() } else { - self.doc_grid() + self.doc_grid(&shown) }; column![ header, @@ -646,30 +662,47 @@ impl ColorPicker { .into() } - /// Grid or list toggle for the Document tab. + /// Grid or list toggle for the Document tab: dark on the accent colour + /// when active, like the OK button. 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), + container( + svg(crate::ui::icons::themed_handle(icon)) + .width(18) + .height(18) + .style(move |theme: &Theme, _status| svg::Style { + color: Some(if active { + theme.palette().primary.base.text + } else { + theme.palette().background.base.text + }), + }), + ) + .center(Length::Fill), ) .on_press(picker_msg(ColorPickerMsg::DocView(view))) - .padding(5) - .style(move |theme: &Theme, status| toggle_style(theme, active, status)) + .width(CONTROL_HEIGHT) + .height(CONTROL_HEIGHT) + .padding(0) + .style(move |theme: &Theme, status| { + if active { + button::primary(theme, status) + } else { + toggle_style(theme, false, status) + } + }) .into() } - fn doc_grid(&self) -> Element<'_, Message> { - self.doc + fn doc_grid<'a>(&self, shown: &[(usize, &'a DocColor)]) -> Element<'a, Message> { + shown .chunks(DOC_COLUMNS) - .enumerate() - .fold(column![].spacing(4), |grid, (r, chunk)| { + .fold(column![].spacing(4), |grid, chunk| { let line = chunk .iter() - .enumerate() - .fold(row![].spacing(4), |line, (c, entry)| { - line.push(self.doc_swatch(r * DOC_COLUMNS + c, entry)) + .fold(row![].spacing(4), |line, &(i, entry)| { + line.push(self.doc_swatch(i, entry)) }); let line = (chunk.len()..DOC_COLUMNS) .fold(line, |line, _| line.push(Space::new().width(Length::Fill))); @@ -681,19 +714,8 @@ impl ColorPicker { fn doc_swatch<'a>(&self, i: usize, entry: &'a DocColor) -> Element<'a, Message> { 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; - button( - container( - text(entry.tag()) - .size(10) - .font(iced::Font::MONOSPACE) - .color(ink(fill)), - ) - .align_y(iced::Bottom) - .padding([1, 4]) - .height(Length::Fill) - .clip(true), - ) - .on_press(picker_msg(ColorPickerMsg::PickDocument(i))) + button(Space::new()) + .on_press(picker_msg(ColorPickerMsg::PickDocument(i))) .padding(0) .width(Length::Fill) .height(30) @@ -720,45 +742,39 @@ impl ColorPicker { .center(Length::Fill) .into(); }; - let label = |label: std::borrow::Cow<'static, str>| text(label).size(11).style(muted_text); + // The book list as wide as the colour bars; the search box and the + // load button over the page strip and the RGB values. let books = Arc::clone(&self.books); let top = row![ - column![ - label(t!("Color book")), - pick_list( - Some(self.book), - (0..self.books.len()).collect::>(), - move |&i| books[i].name.clone(), - ) - .on_select(|i| picker_msg(ColorPickerMsg::Book(i))) - .text_size(12) - .padding([4, 6]) - .width(Length::Fill), - ] - .spacing(4) - .width(Length::Fill), - column![ - label(t!("Find")), - text_input("", &self.book_query) - .on_input(|query| picker_msg(ColorPickerMsg::BookQuery(query))) - .size(12) - .padding([5, 8]) - .font(iced::Font::MONOSPACE) - .width(116), - ] - .spacing(4), - load_button( - svg(crate::ui::icons::themed_handle( - crate::ui::icons::FOLDER_OPEN - )) - .width(15) - .height(15) - .into() + pick_list( + Some(self.book), + (0..self.books.len()).collect::>(), + move |&i| books[i].name.clone(), ) - .padding([6, 7]), + .on_select(|i| picker_msg(ColorPickerMsg::Book(i))) + .text_size(12) + .padding([6, 8]) + .width(Length::Fill), + row![ + search_box(&self.book_query, |query| ColorPickerMsg::BookQuery(query)), + load_button( + container(secondary_icon(crate::ui::icons::themed_handle( + crate::ui::icons::FOLDER_OPEN + )) + .width(16) + .height(16)) + .center(Length::Fill) + .into() + ) + .width(CONTROL_HEIGHT) + .height(CONTROL_HEIGHT) + .padding(0), + ] + .spacing(6) + .width(SIDE_WIDTH), ] - .spacing(8) - .align_y(iced::Bottom); + .spacing(10) + .align_y(iced::Center); // The page's colours, or the first matches while searching. let selected = self.book_selection(); @@ -829,7 +845,7 @@ impl ColorPicker { .width(9) .height(5) .style(|theme: &Theme, _status| svg::Style { - color: Some(theme.palette().background.base.text), + color: Some(theme.palette().secondary.base.text), }), ) .on_press(picker_msg(ColorPickerMsg::BookPage(page))) @@ -1082,6 +1098,45 @@ fn color_bar<'a>( .style(move |theme: &Theme, status| swatch_button_style(theme, status, fill, selected)) } +/// A search field with a magnifier and a gray "Search" placeholder. +fn search_box<'a>( + value: &str, + on_input: impl Fn(String) -> ColorPickerMsg + 'a, +) -> Element<'a, Message> { + iced::widget::stack![ + text_input(&t!("Search"), value) + .on_input(move |query| picker_msg(on_input(query))) + .size(12) + .padding(iced::Padding { + top: 6.0, + right: 8.0, + bottom: 6.0, + left: 28.0, + }) + .width(Length::Fill), + container( + svg(crate::ui::icons::themed_handle(crate::ui::icons::SEARCH)) + .width(14) + .height(14) + .style(|theme: &Theme, _status| svg::Style { + color: Some(theme.palette().background.base.text.scale_alpha(0.5)), + }), + ) + .padding([0, 8]) + .height(Length::Fill) + .center_y(Length::Fill), + ] + .width(Length::Fill) + .into() +} + +/// An icon in the text colour of a secondary button, so it reads on it. +fn secondary_icon<'a>(handle: svg::Handle) -> svg::Svg<'a> { + svg(handle).style(|theme: &Theme, _status| svg::Style { + color: Some(theme.palette().secondary.base.text), + }) +} + /// A short gray note in the middle of the free space. fn empty_note<'a>(note: String) -> Element<'a, Message> { container(text(note).size(12).style(muted_text)) diff --git a/src/ui/icons.rs b/src/ui/icons.rs index a37c7ccdd..9897fd9e3 100644 --- a/src/ui/icons.rs +++ b/src/ui/icons.rs @@ -82,6 +82,7 @@ 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 SEARCH: &[u8] = include_bytes!("../../assets/icons/ui/search.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");