Select Color: colour book folders, app-style view toggles, load button by the book list

- Colour books now come from folders, like AutoCAD's Color Book
  Locations: Options > Files lists them (add, open, remove); by default
  one color_books folder in the config directory. The Color Books tab
  shows the built-in books plus every .acb in those folders; Load copies
  the chosen file into the first folder. Web: session only, as before.
- Grid/list buttons use the app's toggle style (light accent, its text
  colour for the icon, same corners as inactive).
- Color Books: the load button sits right of the book list; the search
  box keeps its start over the page strip and runs to the end.
- Translations for the two new Options strings in all 22 locales.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_013rGmDUNr1hUf4zo1X3dak8
This commit is contained in:
Claude committed 2026-10-14 18:51:02 +00:00
1 parent 322c1906f9
commit 666234f69e
30 files changed
+222 -61

No files matched your search

+2
View File
@@ -1372,6 +1372,8 @@ common =
.color-not-a-book = ليس كتاب ألوان
.color-book-encrypted = كتاب الألوان هذا مشفر ولا يمكن قراءته
.color-book-empty = لا يحتوي كتاب الألوان على ألوان
.color-book-locations = مواقع كتب الألوان
.color-book-locations-hint = المجلدات التي يُبحث فيها عن كتب الألوان ‎.acb. يُنسخ الكتاب الذي يُحمَّل في اختيار اللون إلى المجلد الأول.
.cad-color-index-aci-10-249 = فهرس ألوان ACI 10–249
.grayscale-250-255 = { common.grayscale } 250–255
.isometric-drafting = الرسم متساوي القياس
+2
View File
@@ -1359,6 +1359,8 @@ common =
.color-not-a-book = Не е цветови каталог
.color-book-encrypted = Този цветови каталог е шифрован и не може да бъде прочетен
.color-book-empty = Цветовият каталог няма цветове
.color-book-locations = Местоположения на цветови каталози
.color-book-locations-hint = Папки, в които се търсят цветови каталози .acb. Каталог, зареден в „Избор на цвят“, се копира в първата папка.
.cad-color-index-aci-10-249 = ACI Цветови индекс 10–249
.grayscale-250-255 = { common.grayscale } 250–255
.isometric-drafting = Изометрично чертане
+2
View File
@@ -1359,6 +1359,8 @@ common =
.color-not-a-book = Nejde o barevný vzorník
.color-book-encrypted = Tento barevný vzorník je zašifrovaný a nelze jej přečíst
.color-book-empty = Barevný vzorník neobsahuje žádné barvy
.color-book-locations = Umístění barevných vzorníků
.color-book-locations-hint = Složky, ve kterých se hledají barevné vzorníky .acb. Vzorník načtený ve Výběru barvy se zkopíruje do první složky.
.cad-color-index-aci-10-249 = Barevný index ACI 10–249
.grayscale-250-255 = { common.grayscale } 250–255
.isometric-drafting = Izometrické kreslení
+2
View File
@@ -1360,6 +1360,8 @@ common =
.color-not-a-book = Kein Farbbuch
.color-book-encrypted = Dieses Farbbuch ist verschlüsselt und kann nicht gelesen werden
.color-book-empty = Das Farbbuch enthält keine Farben
.color-book-locations = Speicherorte für Farbbücher
.color-book-locations-hint = Ordner, in denen nach .acb-Farbbüchern gesucht wird. Ein in „Farbe wählen“ geladenes Farbbuch wird in den ersten Ordner kopiert.
.cad-color-index-aci-10-249 = ACI Farbindex 10–249
.grayscale-250-255 = { common.grayscale } 250–255
.isometric-drafting = Isometrisches Zeichnen
+2
View File
@@ -1361,6 +1361,8 @@ common =
.color-not-a-book = Δεν είναι βιβλίο χρωμάτων
.color-book-encrypted = Αυτό το βιβλίο χρωμάτων είναι κρυπτογραφημένο και δεν μπορεί να διαβαστεί
.color-book-empty = Το βιβλίο χρωμάτων δεν έχει χρώματα
.color-book-locations = Θέσεις βιβλίων χρωμάτων
.color-book-locations-hint = Φάκελοι στους οποίους αναζητούνται βιβλία χρωμάτων .acb. Ένα βιβλίο που φορτώνεται στην Επιλογή χρώματος αντιγράφεται στον πρώτο φάκελο.
.cad-color-index-aci-10-249 = Δείκτης χρώματος ACI 10–249
.grayscale-250-255 = { common.grayscale } 250–255
.isometric-drafting = Ισομετρική σχεδίαση
+2
View File
@@ -1360,6 +1360,8 @@ common =
.color-not-a-book = Not a color book
.color-book-encrypted = This color book is encrypted and cannot be read
.color-book-empty = The color book has no colors
.color-book-locations = Color book locations
.color-book-locations-hint = Folders searched for .acb color books. A book loaded in Select Color is copied into the first folder.
.cad-color-index-aci-10-249 = CAD Color Index (ACI) 10–249
.grayscale-250-255 = Grayscale 250–255
.isometric-drafting = Isometric drafting
+2
View File
@@ -1360,6 +1360,8 @@ common =
.color-not-a-book = No es un libro de colores
.color-book-encrypted = Este libro de colores está cifrado y no se puede leer
.color-book-empty = El libro de colores no tiene colores
.color-book-locations = Ubicaciones de libros de colores
.color-book-locations-hint = Carpetas en las que se buscan libros de colores .acb. Un libro cargado en Seleccionar color se copia en la primera carpeta.
.cad-color-index-aci-10-249 = Índice de color ACI 10–249
.grayscale-250-255 = { common.grayscale } 250–255
.isometric-drafting = Dibujo isométrico
+2
View File
@@ -1359,6 +1359,8 @@ common =
.color-not-a-book = Ei värikirja
.color-book-encrypted = Tämä värikirja on salattu eikä sitä voi lukea
.color-book-empty = Värikirjassa ei ole värejä
.color-book-locations = Värikirjojen sijainnit
.color-book-locations-hint = Kansiot, joista etsitään .acb-värikirjoja. Värin valinnassa ladattu värikirja kopioidaan ensimmäiseen kansioon.
.cad-color-index-aci-10-249 = ACI väriindeksi 10–249
.grayscale-250-255 = { common.grayscale } 250–255
.isometric-drafting = Isometrinen piirtäminen
+2
View File
@@ -1360,6 +1360,8 @@ common =
.color-not-a-book = Ce n'est pas un carnet de couleurs
.color-book-encrypted = Ce carnet de couleurs est chiffré et ne peut pas être lu
.color-book-empty = Le carnet de couleurs ne contient aucune couleur
.color-book-locations = Emplacements des carnets de couleurs
.color-book-locations-hint = Dossiers où rechercher les carnets de couleurs .acb. Un carnet chargé dans Sélectionner une couleur est copié dans le premier dossier.
.cad-color-index-aci-10-249 = ACI Indice de couleur 10–249
.grayscale-250-255 = { common.grayscale } 250–255
.isometric-drafting = Dessin isométrique
+2
View File
@@ -1348,6 +1348,8 @@ common =
.color-not-a-book = यह रंग पुस्तक नहीं है
.color-book-encrypted = यह रंग पुस्तक एन्क्रिप्टेड है और पढ़ी नहीं जा सकती
.color-book-empty = रंग पुस्तक में कोई रंग नहीं है
.color-book-locations = रंग पुस्तकों के स्थान
.color-book-locations-hint = वे फ़ोल्डर जिनमें .acb रंग पुस्तकें खोजी जाती हैं। रंग चुनें में लोड की गई पुस्तक पहले फ़ोल्डर में कॉपी की जाती है।
.cad-color-index-aci-10-249 = ACI रंग सूचकांक 10–249
.grayscale-250-255 = { common.grayscale } 250–255
.isometric-drafting = सममितीय आरेखन
+2
View File
@@ -1359,6 +1359,8 @@ common =
.color-not-a-book = Nem színkönyv
.color-book-encrypted = Ez a színkönyv titkosított, és nem olvasható
.color-book-empty = A színkönyv nem tartalmaz színeket
.color-book-locations = Színkönyvek helye
.color-book-locations-hint = Mappák, amelyekben a program .acb színkönyveket keres. A Szín kiválasztása ablakban betöltött színkönyv az első mappába másolódik.
.cad-color-index-aci-10-249 = ACI színindex 10–249
.grayscale-250-255 = { common.grayscale } 250–255
.isometric-drafting = Izometrikus rajzolás
+2
View File
@@ -1359,6 +1359,8 @@ common =
.color-not-a-book = Non è un album colori
.color-book-encrypted = Questo album colori è crittografato e non può essere letto
.color-book-empty = L'album colori non contiene colori
.color-book-locations = Percorsi degli album colori
.color-book-locations-hint = Cartelle in cui cercare gli album colori .acb. Un album caricato in Seleziona colore viene copiato nella prima cartella.
.cad-color-index-aci-10-249 = ACI Indice colori 10–249
.grayscale-250-255 = { common.grayscale } 250–255
.isometric-drafting = Disegno isometrico
+2
View File
@@ -1350,6 +1350,8 @@ common =
.color-not-a-book = カラー ブックではありません
.color-book-encrypted = このカラー ブックは暗号化されているため読み込めません
.color-book-empty = カラー ブックに色がありません
.color-book-locations = カラー ブックの場所
.color-book-locations-hint = .acb カラー ブックを検索するフォルダです。[色を選択] で読み込んだブックは最初のフォルダにコピーされます。
.cad-color-index-aci-10-249 = ACI カラーインデックス 10–249
.grayscale-250-255 = { common.grayscale } 250–255
.isometric-drafting = アイソメ図作成
+2
View File
@@ -1359,6 +1359,8 @@ common =
.color-not-a-book = 색상표가 아닙니다
.color-book-encrypted = 이 색상표는 암호화되어 있어 읽을 수 없습니다
.color-book-empty = 색상표에 색상이 없습니다
.color-book-locations = 색상표 위치
.color-book-locations-hint = .acb 색상표를 찾는 폴더입니다. 색상 선택에서 로드한 색상표는 첫 번째 폴더에 복사됩니다.
.cad-color-index-aci-10-249 = ACI 컬러 인덱스 10–249
.grayscale-250-255 = { common.grayscale } 250–255
.isometric-drafting = 등각 제도
+2
View File
@@ -1365,6 +1365,8 @@ common =
.color-not-a-book = ບໍ່ແມ່ນປຶ້ມສີ
.color-book-encrypted = ປຶ້ມສີນີ້ຖືກເຂົ້າລະຫັດ ແລະອ່ານບໍ່ໄດ້
.color-book-empty = ປຶ້ມສີບໍ່ມີສີ
.color-book-locations = ທີ່ຕັ້ງປຶ້ມສີ
.color-book-locations-hint = ໂຟນເດີທີ່ໃຊ້ຊອກຫາປຶ້ມສີ .acb. ປຶ້ມທີ່ໂຫຼດໃນເລືອກສີຈະຖືກສຳເນົາໄປໃສ່ໂຟນເດີທຳອິດ.
.cad-color-index-aci-10-249 = CAD Color Index (ACI) 10–249
.grayscale-250-255 = ລະດັບສີເທົາ 250–255
.isometric-drafting = ການຂຽນແບບໄອໂຊເມຕຣິກ
+2
View File
@@ -1358,6 +1358,8 @@ common =
.color-not-a-book = Geen kleurboek
.color-book-encrypted = Dit kleurboek is versleuteld en kan niet worden gelezen
.color-book-empty = Het kleurboek bevat geen kleuren
.color-book-locations = Locaties van kleurboeken
.color-book-locations-hint = Mappen waarin naar .acb-kleurboeken wordt gezocht. Een kleurboek dat in Kleur selecteren wordt geladen, wordt naar de eerste map gekopieerd.
.cad-color-index-aci-10-249 = ACI Kleurindex 10–249
.grayscale-250-255 = { common.grayscale } 250–255
.isometric-drafting = Isometrisch tekenen
+2
View File
@@ -1359,6 +1359,8 @@ common =
.color-not-a-book = To nie jest wzornik kolorów
.color-book-encrypted = Ten wzornik kolorów jest zaszyfrowany i nie można go odczytać
.color-book-empty = Wzornik kolorów nie zawiera kolorów
.color-book-locations = Lokalizacje wzorników kolorów
.color-book-locations-hint = Foldery przeszukiwane w poszukiwaniu wzorników kolorów .acb. Wzornik wczytany w oknie Wybierz kolor jest kopiowany do pierwszego folderu.
.cad-color-index-aci-10-249 = Indeks kolorów ACI 10–249
.grayscale-250-255 = { common.grayscale } 250–255
.isometric-drafting = Rysowanie izometryczne
+2
View File
@@ -1360,6 +1360,8 @@ common =
.color-not-a-book = Não é um catálogo de cores
.color-book-encrypted = Este catálogo de cores é criptografado e não pode ser lido
.color-book-empty = O catálogo de cores não tem cores
.color-book-locations = Locais dos catálogos de cores
.color-book-locations-hint = Pastas pesquisadas em busca de catálogos de cores .acb. Um catálogo carregado em Selecionar cor é copiado para a primeira pasta.
.cad-color-index-aci-10-249 = Índice de cor ACI 10–249
.grayscale-250-255 = { common.grayscale } 250–255
.isometric-drafting = Desenho isométrico
+2
View File
@@ -1363,6 +1363,8 @@ common =
.color-not-a-book = Это не альбом цветов
.color-book-encrypted = Этот альбом цветов зашифрован и не может быть прочитан
.color-book-empty = В альбоме цветов нет цветов
.color-book-locations = Расположение альбомов цветов
.color-book-locations-hint = Папки, в которых ищутся альбомы цветов .acb. Альбом, загруженный в окне «Выбор цвета», копируется в первую папку.
.cad-color-index-aci-10-249 = Индекс цвета ACI 10–249
.grayscale-250-255 = { common.grayscale } 250–255
.isometric-drafting = Изометрическое черчение
+2
View File
@@ -1346,6 +1346,8 @@ common =
.color-not-a-book = Bir renk kitabı değil
.color-book-encrypted = Bu renk kitabı şifreli ve okunamıyor
.color-book-empty = Renk kitabında renk yok
.color-book-locations = Renk kitabı konumları
.color-book-locations-hint = Bu klasörlerde .acb renk kitapları aranır. Renk Seç'te yüklenen bir kitap ilk klasöre kopyalanır.
.cad-color-index-aci-10-249 = ACI renk dizini 10–249
.grayscale-250-255 = { common.grayscale } 250–255
.isometric-drafting = İzometrik çizim
+2
View File
@@ -1347,6 +1347,8 @@ common =
.color-not-a-book = 不是配色系统
.color-book-encrypted = 此配色系统已加密,无法读取
.color-book-empty = 配色系统中没有颜色
.color-book-locations = 配色系统位置
.color-book-locations-hint = 搜索 .acb 配色系统的文件夹。在“选择颜色”中加载的配色系统会复制到第一个文件夹。
.cad-color-index-aci-10-249 = ACI 颜色索引 10–249
.grayscale-250-255 = { common.grayscale } 250–255
.isometric-drafting = 等轴测绘图
+2
View File
@@ -1359,6 +1359,8 @@ common =
.color-not-a-book = 不是配色系統
.color-book-encrypted = 此配色系統已加密,無法讀取
.color-book-empty = 配色系統中沒有顏色
.color-book-locations = 配色系統位置
.color-book-locations-hint = 搜尋 .acb 配色系統的資料夾。在「選取顏色」中載入的配色系統會複製到第一個資料夾。
.cad-color-index-aci-10-249 = ACI 顏色索引 10–249
.grayscale-250-255 = { common.grayscale } 250–255
.isometric-drafting = 等角製圖
+11 -5
View File
@@ -965,9 +965,10 @@ pub(super) struct OpenCADStudio {
// ── Floating panel windows ────────────────────────────────────────────
/// The open Select Color panel, if any.
color_picker: Option<crate::ui::color_select::ColorPicker>,
/// Colour books loaded this session, read lazily from `color_book_paths`.
/// The built-in colour books and those in `color_book_dirs`, read
/// lazily when the Select Color panel opens.
color_books: std::sync::Arc<Vec<crate::ui::color_select::book::ColorBook>>,
color_book_paths: Vec<String>,
color_book_dirs: Vec<String>,
color_books_read: bool,
/// Recently committed real colours, newest first.
/// ACI and True Color remain semantically distinct even when their RGB matches.
@@ -4174,8 +4175,13 @@ pub enum Message {
/// Commit the colour chosen in the shared picker, with its `BOOK$NAME`
/// when it comes from a colour book.
ColorWindowPick(codec::types::Color, Option<String>),
/// An `.acb` file was read: the book and, on desktop, where it lives.
ColorBookLoaded(Result<(crate::ui::color_select::book::ColorBook, Option<String>), String>),
/// An `.acb` file was read (and, on desktop, copied into the first
/// colour book folder).
ColorBookLoaded(Result<crate::ui::color_select::book::ColorBook, String>),
/// Options › Files: pick a folder to search for colour books.
ColorBookDirBrowse,
ColorBookDirAdd(String),
ColorBookDirRemove(usize),
/// Set a block/linetype Handle field on the selected dim style from a
/// dropdown of available block-records / linetypes (by name).
DsSetHandle {
@@ -4608,7 +4614,7 @@ impl OpenCADStudio {
web_autosave_clear_after: Vec::new(),
color_picker: None,
color_books: Default::default(),
color_book_paths: Vec::new(),
color_book_dirs: Vec::new(),
color_books_read: false,
active_modal: None,
hyperlink_editor_handles: Vec::new(),
+14 -4
View File
@@ -619,9 +619,10 @@ pub struct UserSettings {
/// Blocks palette: library folders or drawings, last used first.
#[serde(default)]
pub block_libraries: Vec<String>,
/// Colour book (.acb) files loaded in the Select Color panel.
#[serde(default)]
pub color_books: Vec<String>,
/// Folders searched for `.acb` colour books. Books loaded in the Select
/// Color panel are copied into the first one.
#[serde(default = "default_color_book_dirs")]
pub color_book_dirs: Vec<String>,
/// Blocks palette view: 0 extra large, 1 large, 2 medium, 3 small icons,
/// 4 details, 5 list.
#[serde(default = "default_block_view")]
@@ -749,6 +750,15 @@ fn default_grid_major() -> u32 {
5
}
/// One folder in the config directory; none on the web, which has no folders.
fn default_color_book_dirs() -> Vec<String> {
#[cfg(not(target_arch = "wasm32"))]
if let Some(dir) = crate::config::config_dir() {
return vec![dir.join("color_books").display().to_string()];
}
Vec::new()
}
fn default_true() -> bool {
true
}
@@ -904,7 +914,7 @@ impl Default for UserSettings {
block_recent: Vec::new(),
block_favorites: Vec::new(),
block_libraries: Vec::new(),
color_books: Vec::new(),
color_book_dirs: default_color_book_dirs(),
block_palette_view: 1,
block_insert: BlockInsertOptions::default(),
block_mru_list: 50,
+5 -2
View File
@@ -860,7 +860,7 @@ impl OpenCADStudio {
block_recent: self.block_palette.recent.clone(),
block_favorites: self.block_palette.favorites.clone(),
block_libraries: self.block_palette.libraries.clone(),
color_books: self.color_book_paths.clone(),
color_book_dirs: self.color_book_dirs.clone(),
block_palette_view: self.block_palette.view as u8,
block_insert: self.block_palette.options.clone(),
block_mru_list: self.block_mru_list,
@@ -1026,7 +1026,10 @@ impl OpenCADStudio {
self.block_palette.recent = s.block_recent.clone();
self.block_palette.favorites = s.block_favorites.clone();
self.block_palette.libraries = s.block_libraries.clone();
self.color_book_paths = s.color_books.clone();
if self.color_book_dirs != s.color_book_dirs {
self.color_book_dirs = s.color_book_dirs.clone();
self.color_books_read = false;
}
self.block_palette.view =
crate::ui::window::block_palette::ViewMode::from_u8(s.block_palette_view);
self.block_palette.set_options(s.block_insert.clone());
+79 -28
View File
@@ -11596,25 +11596,38 @@ impl OpenCADStudio {
Some(crate::ui::color_select::Outcome::Commit(color, name)) => {
self.update(Message::ColorWindowPick(color, name))
}
Some(crate::ui::color_select::Outcome::LoadBook) => Task::perform(
async {
let file = crate::sys::file_dialog()
.add_filter(crate::t!("Color book").as_ref(), &["acb", "ACB"])
.pick_file()
.await
.ok_or_else(|| "Cancelled".to_string())?;
let book = crate::ui::color_select::book::parse(
&String::from_utf8_lossy(&file.read().await),
)?;
// The web build has no paths to read again later.
#[cfg(not(target_arch = "wasm32"))]
let path = Some(crate::sys::handle_path(&file).display().to_string());
#[cfg(target_arch = "wasm32")]
let path = None;
Ok((book, path))
},
Message::ColorBookLoaded,
),
Some(crate::ui::color_select::Outcome::LoadBook) => {
// Copied into the first colour book folder so it stays
// when the original moves; the web keeps it for the
// session only.
let folder = self.color_book_dirs.first().cloned();
Task::perform(
async move {
let file = crate::sys::file_dialog()
.add_filter(crate::t!("Color book").as_ref(), &["acb", "ACB"])
.pick_file()
.await
.ok_or_else(|| "Cancelled".to_string())?;
let bytes = file.read().await;
let book = crate::ui::color_select::book::parse(
&String::from_utf8_lossy(&bytes),
)?;
#[cfg(not(target_arch = "wasm32"))]
if let Some(folder) = folder {
let folder = std::path::PathBuf::from(folder);
std::fs::create_dir_all(&folder)
.and_then(|()| {
std::fs::write(folder.join(file.file_name()), &bytes)
})
.map_err(|e| e.to_string())?;
}
#[cfg(target_arch = "wasm32")]
let _ = folder;
Ok(book)
},
Message::ColorBookLoaded,
)
}
Some(crate::ui::color_select::Outcome::Cancel) => {
self.color_picker = None;
Task::none()
@@ -11651,7 +11664,7 @@ impl OpenCADStudio {
}
self.on_color_window_pick(color, name)
}
Message::ColorBookLoaded(Ok((book, path))) => {
Message::ColorBookLoaded(Ok(book)) => {
// A book loaded again replaces the earlier copy.
let books = std::sync::Arc::make_mut(&mut self.color_books);
let index = match books.iter().position(|b| b.name == book.name) {
@@ -11664,10 +11677,6 @@ impl OpenCADStudio {
books.len() - 1
}
};
if let Some(path) = path.filter(|path| !self.color_book_paths.contains(path)) {
self.color_book_paths.push(path);
self.save_config();
}
if let Some(picker) = self.color_picker.as_mut() {
picker.show_book(std::sync::Arc::clone(&self.color_books), index);
}
@@ -11679,6 +11688,35 @@ impl OpenCADStudio {
}
Task::none()
}
#[cfg(not(target_arch = "wasm32"))]
Message::ColorBookDirBrowse => Task::perform(
async {
crate::sys::file_dialog()
.pick_folder()
.await
.map(|handle| crate::sys::handle_path(&handle).display().to_string())
},
|dir| dir.map_or(Message::Noop, Message::ColorBookDirAdd),
),
// Browsers expose no folder picker.
#[cfg(target_arch = "wasm32")]
Message::ColorBookDirBrowse => Task::none(),
Message::ColorBookDirAdd(dir) => {
if !self.color_book_dirs.contains(&dir) {
self.color_book_dirs.push(dir);
self.color_books_read = false;
self.persist_settings_if_changed();
}
Task::none()
}
Message::ColorBookDirRemove(i) => {
if i < self.color_book_dirs.len() {
self.color_book_dirs.remove(i);
self.color_books_read = false;
self.persist_settings_if_changed();
}
Task::none()
}
Message::DsSetHandle { field, value } => self.on_ds_set_handle(field, value),
}
}
@@ -11759,9 +11797,9 @@ impl OpenCADStudio {
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.
/// Read the built-in colour books and every `.acb` in the colour book
/// folders, once until the folders change. A book in a folder replaces a
/// built-in one of the same name.
fn read_color_books(&mut self) {
if std::mem::replace(&mut self.color_books_read, true) {
return;
@@ -11771,8 +11809,21 @@ impl OpenCADStudio {
let mut books: Vec<_> = book::builtin().collect();
#[cfg(not(target_arch = "wasm32"))]
for loaded in self
.color_book_paths
.color_book_dirs
.iter()
.flat_map(|dir| {
let mut files: Vec<_> = std::fs::read_dir(dir)
.into_iter()
.flatten()
.filter_map(|entry| entry.ok().map(|entry| entry.path()))
.filter(|path| {
path.extension()
.is_some_and(|ext| ext.eq_ignore_ascii_case("acb"))
})
.collect();
files.sort();
files
})
.filter_map(|path| std::fs::read_to_string(path).ok())
.filter_map(|text| book::parse(&text).ok())
{
+1
View File
@@ -367,6 +367,7 @@ impl OpenCADStudio {
}
},
&self.qnew_template,
&self.color_book_dirs,
self.double_click_block_refedit,
self.double_click_block_attedit,
self.cursor_type,
+2
View File
@@ -4736,6 +4736,8 @@ pub(super) fn message_attribute(source: &str) -> Option<(&'static str, &'static
"Not a color book" => Some(("common", "color-not-a-book")),
"This color book is encrypted and cannot be read" => Some(("common", "color-book-encrypted")),
"The color book has no colors" => Some(("common", "color-book-empty")),
"Color book locations" => Some(("common", "color-book-locations")),
"Folders searched for .acb color books. A book loaded in Select Color is copied into the first folder." => Some(("common", "color-book-locations-hint")),
"CAD Color Index (ACI) 10–249" => Some(("common", "cad-color-index-aci-10-249")),
"Grayscale 250–255" => Some(("common", "grayscale-250-255")),
"Isometric drafting" => Some(("common", "isometric-drafting")),
+21 -22
View File
@@ -672,8 +672,9 @@ impl ColorPicker {
.into()
}
/// Grid or list toggle for the Document tab: dark on the accent colour
/// when active, like the OK button.
/// Grid or list toggle for the Document tab, styled like the app's other
/// toggles: light accent when active, its icon in that accent's text
/// colour.
fn view_button(&self, icon: &'static [u8], view: DocView) -> Element<'_, Message> {
let active = self.doc_view == view;
button(
@@ -683,7 +684,7 @@ impl ColorPicker {
.height(18)
.style(move |theme: &Theme, _status| svg::Style {
color: Some(if active {
theme.palette().primary.base.text
theme.palette().primary.weak.text
} else {
theme.palette().background.base.text
}),
@@ -695,13 +696,7 @@ impl ColorPicker {
.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)
}
})
.style(move |theme: &Theme, status| toggle_style(theme, active, status))
.into()
}
@@ -750,21 +745,20 @@ impl ColorPicker {
.center(Length::Fill)
.into();
};
// The book list as wide as the colour bars; the search box and the
// load button over the page strip and the RGB values.
// The book list and its load button over the colour bars; the
// search box over the page strip and the RGB values, to the end.
let books = Arc::clone(&self.books);
let top = row![
pick_list(
Some(self.book),
(0..self.books.len()).collect::<Vec<_>>(),
move |&i| books[i].name.clone(),
)
.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)),
pick_list(
Some(self.book),
(0..self.books.len()).collect::<Vec<_>>(),
move |&i| books[i].name.clone(),
)
.on_select(|i| picker_msg(ColorPickerMsg::Book(i)))
.text_size(12)
.padding([6, 8])
.width(Length::Fill),
load_button(
container(
secondary_icon(crate::ui::icons::themed_handle(
@@ -781,6 +775,11 @@ impl ColorPicker {
.padding(0),
]
.spacing(6)
.align_y(iced::Center)
.width(Length::Fill),
container(search_box(&self.book_query, |query| {
ColorPickerMsg::BookQuery(query)
}))
.width(SIDE_WIDTH),
]
.spacing(10)
+45
View File
@@ -204,6 +204,7 @@ pub fn view_window<'a>(
drawing_prefs: DrawingPrefs,
folders: Folders,
qnew_template: &'a str,
color_book_dirs: &'a [String],
double_click_block_refedit: bool,
double_click_block_attedit: bool,
cursor_type: CursorType,
@@ -1697,6 +1698,49 @@ pub fn view_window<'a>(
.align_y(iced::Center)
};
// Searched for `.acb` colour books; editable, unlike the folders above.
// Browsers have no folders, so the web build leaves it out.
let color_book_locations = |dirs: &'a [String]| -> Element<'a, Message> {
if cfg!(target_arch = "wasm32") {
return Space::new().into();
}
let list = dirs
.iter()
.enumerate()
.fold(column![].spacing(6), |list, (i, dir)| {
list.push(
row![
text(dir.as_str()).size(11).width(Fill),
button(text(crate::t!("Open folder")).size(11))
.padding([4, 10])
.style(button::secondary)
.on_press(Message::OpenFolder(dir.clone())),
button(text(crate::t!("Remove")).size(11))
.padding([4, 10])
.style(button::secondary)
.on_press(Message::ColorBookDirRemove(i)),
]
.spacing(10)
.align_y(iced::Center),
)
});
column![
text(crate::t!("Color book locations")).size(12),
text(crate::t!(
"Folders searched for .acb color books. A book loaded in Select Color is copied into the first folder."
))
.size(11),
list,
button(text(crate::t!("Add folder…")).size(11))
.padding([4, 10])
.style(button::secondary)
.on_press(Message::ColorBookDirBrowse),
Space::new().height(16),
]
.spacing(6)
.into()
};
let files = column![
text(crate::t!("Files")).size(15),
Space::new().height(6),
@@ -1716,6 +1760,7 @@ pub fn view_window<'a>(
Space::new().height(12),
folder_row(crate::t!("Fonts"), folders.fonts.clone()),
Space::new().height(16),
color_book_locations(color_book_dirs),
text(crate::t!("Default template for new drawings")).size(12),
Space::new().height(4),
row![