forked from 1b-agent/opencadstudio-upstream
Select Color: one fixed colour book folder instead of a folder list setting
The color_book_dirs setting is gone. Colour books live in color_books in the config folder (book::folder()), like the other fixed locations; Options > Files shows it through Folders::color_books. read_all() and load_from_dialog() use that folder directly. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013rGmDUNr1hUf4zo1X3dak8
This commit is contained in:
7 files changed
+47
-72
No files matched your search
+2
-4
@@ -1067,10 +1067,9 @@ pub(super) struct OpenCADStudio {
|
|||||||
// ── Floating panel windows ────────────────────────────────────────────
|
// ── Floating panel windows ────────────────────────────────────────────
|
||||||
/// The open Select Color panel, if any.
|
/// The open Select Color panel, if any.
|
||||||
color_picker: Option<crate::ui::color_select::ColorPicker>,
|
color_picker: Option<crate::ui::color_select::ColorPicker>,
|
||||||
/// The built-in colour books and those in `color_book_dirs`, read
|
/// The built-in colour book and those in the colour book folder, read
|
||||||
/// lazily when the Select Color panel opens.
|
/// lazily when the Select Color panel first opens.
|
||||||
color_books: std::sync::Arc<Vec<crate::ui::color_select::book::ColorBook>>,
|
color_books: std::sync::Arc<Vec<crate::ui::color_select::book::ColorBook>>,
|
||||||
color_book_dirs: Vec<String>,
|
|
||||||
color_books_read: bool,
|
color_books_read: bool,
|
||||||
/// Recently committed real colours, newest first.
|
/// Recently committed real colours, newest first.
|
||||||
/// ACI and True Color remain semantically distinct even when their RGB matches.
|
/// ACI and True Color remain semantically distinct even when their RGB matches.
|
||||||
@@ -4793,7 +4792,6 @@ impl OpenCADStudio {
|
|||||||
web_autosave_clear_after: Vec::new(),
|
web_autosave_clear_after: Vec::new(),
|
||||||
color_picker: None,
|
color_picker: None,
|
||||||
color_books: Default::default(),
|
color_books: Default::default(),
|
||||||
color_book_dirs: Vec::new(),
|
|
||||||
color_books_read: false,
|
color_books_read: false,
|
||||||
active_modal: None,
|
active_modal: None,
|
||||||
hyperlink_editor_handles: Vec::new(),
|
hyperlink_editor_handles: Vec::new(),
|
||||||
|
|||||||
@@ -636,10 +636,6 @@ pub struct UserSettings {
|
|||||||
/// Blocks palette: library folders or drawings, last used first.
|
/// Blocks palette: library folders or drawings, last used first.
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub block_libraries: Vec<String>,
|
pub block_libraries: 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,
|
/// Blocks palette view: 0 extra large, 1 large, 2 medium, 3 small icons,
|
||||||
/// 4 details, 5 list.
|
/// 4 details, 5 list.
|
||||||
#[serde(default = "default_block_view")]
|
#[serde(default = "default_block_view")]
|
||||||
@@ -801,15 +797,6 @@ fn default_grid_major() -> u32 {
|
|||||||
5
|
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 {
|
fn default_true() -> bool {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
@@ -973,7 +960,6 @@ impl Default for UserSettings {
|
|||||||
block_recent: Vec::new(),
|
block_recent: Vec::new(),
|
||||||
block_favorites: Vec::new(),
|
block_favorites: Vec::new(),
|
||||||
block_libraries: Vec::new(),
|
block_libraries: Vec::new(),
|
||||||
color_book_dirs: default_color_book_dirs(),
|
|
||||||
block_palette_view: 1,
|
block_palette_view: 1,
|
||||||
block_insert: BlockInsertOptions::default(),
|
block_insert: BlockInsertOptions::default(),
|
||||||
block_mru_list: 50,
|
block_mru_list: 50,
|
||||||
|
|||||||
@@ -868,7 +868,6 @@ impl OpenCADStudio {
|
|||||||
block_recent: self.block_palette.recent.clone(),
|
block_recent: self.block_palette.recent.clone(),
|
||||||
block_favorites: self.block_palette.favorites.clone(),
|
block_favorites: self.block_palette.favorites.clone(),
|
||||||
block_libraries: self.block_palette.libraries.clone(),
|
block_libraries: self.block_palette.libraries.clone(),
|
||||||
color_book_dirs: self.color_book_dirs.clone(),
|
|
||||||
block_palette_view: self.block_palette.view as u8,
|
block_palette_view: self.block_palette.view as u8,
|
||||||
block_insert: self.block_palette.options.clone(),
|
block_insert: self.block_palette.options.clone(),
|
||||||
block_mru_list: self.block_mru_list,
|
block_mru_list: self.block_mru_list,
|
||||||
@@ -1047,10 +1046,6 @@ impl OpenCADStudio {
|
|||||||
self.block_palette.recent = s.block_recent.clone();
|
self.block_palette.recent = s.block_recent.clone();
|
||||||
self.block_palette.favorites = s.block_favorites.clone();
|
self.block_palette.favorites = s.block_favorites.clone();
|
||||||
self.block_palette.libraries = s.block_libraries.clone();
|
self.block_palette.libraries = s.block_libraries.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 =
|
self.block_palette.view =
|
||||||
crate::ui::window::block_palette::ViewMode::from_u8(s.block_palette_view);
|
crate::ui::window::block_palette::ViewMode::from_u8(s.block_palette_view);
|
||||||
self.block_palette.set_options(s.block_insert.clone());
|
self.block_palette.set_options(s.block_insert.clone());
|
||||||
|
|||||||
@@ -11935,9 +11935,7 @@ impl OpenCADStudio {
|
|||||||
self.update(Message::ColorWindowPick(color, name))
|
self.update(Message::ColorWindowPick(color, name))
|
||||||
}
|
}
|
||||||
Some(crate::ui::color_select::Outcome::LoadBook) => Task::perform(
|
Some(crate::ui::color_select::Outcome::LoadBook) => Task::perform(
|
||||||
crate::ui::color_select::book::load_from_dialog(
|
crate::ui::color_select::book::load_from_dialog(),
|
||||||
self.color_book_dirs.first().cloned(),
|
|
||||||
),
|
|
||||||
Message::ColorBookLoaded,
|
Message::ColorBookLoaded,
|
||||||
),
|
),
|
||||||
Some(crate::ui::color_select::Outcome::Cancel) => {
|
Some(crate::ui::color_select::Outcome::Cancel) => {
|
||||||
@@ -12070,16 +12068,14 @@ impl OpenCADStudio {
|
|||||||
document.layers.get(layer).map(|layer| layer.color)
|
document.layers.get(layer).map(|layer| layer.color)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read the built-in colour books and every `.acb` in the colour book
|
/// Read the built-in colour book and every `.acb` in the colour book
|
||||||
/// folders, once until the folders change. A book in a folder replaces a
|
/// folder, once per session. A book in the folder replaces a built-in
|
||||||
/// built-in one of the same name.
|
/// one of the same name.
|
||||||
fn read_color_books(&mut self) {
|
fn read_color_books(&mut self) {
|
||||||
if std::mem::replace(&mut self.color_books_read, true) {
|
if std::mem::replace(&mut self.color_books_read, true) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
self.color_books = std::sync::Arc::new(crate::ui::color_select::book::read_all(
|
self.color_books = std::sync::Arc::new(crate::ui::color_select::book::read_all());
|
||||||
&self.color_book_dirs,
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Colour the selected objects (or set the current colour when nothing
|
/// Colour the selected objects (or set the current colour when nothing
|
||||||
|
|||||||
@@ -373,6 +373,8 @@ impl OpenCADStudio {
|
|||||||
.map(|_| std::env::temp_dir().display().to_string()),
|
.map(|_| std::env::temp_dir().display().to_string()),
|
||||||
fonts: crate::io::font_repo::fonts_dir()
|
fonts: crate::io::font_repo::fonts_dir()
|
||||||
.map(|p| p.display().to_string()),
|
.map(|p| p.display().to_string()),
|
||||||
|
color_books: crate::ui::color_select::book::folder()
|
||||||
|
.map(|p| p.display().to_string()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
@@ -381,7 +383,6 @@ impl OpenCADStudio {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
&self.qnew_template,
|
&self.qnew_template,
|
||||||
&self.color_book_dirs,
|
|
||||||
self.double_click_block_refedit,
|
self.double_click_block_refedit,
|
||||||
self.double_click_block_attedit,
|
self.double_click_block_attedit,
|
||||||
self.cursor_type,
|
self.cursor_type,
|
||||||
|
|||||||
+31
-31
@@ -77,42 +77,45 @@ pub fn builtin() -> impl Iterator<Item = ColorBook> {
|
|||||||
parse(include_str!("../../../assets/color_books/ral-classic.acb")).into_iter()
|
parse(include_str!("../../../assets/color_books/ral-classic.acb")).into_iter()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The built-in book plus every `.acb` file in `dirs`, folder by folder in
|
/// Where colour books are kept: `color_books` in the config folder. The
|
||||||
|
/// web has no folders.
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
pub fn folder() -> Option<std::path::PathBuf> {
|
||||||
|
crate::config::config_dir().map(|dir| dir.join("color_books"))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The built-in book plus every `.acb` file in the colour book folder, in
|
||||||
/// file-name order. A book replaces an earlier one of the same name.
|
/// file-name order. A book replaces an earlier one of the same name.
|
||||||
pub fn read_all(dirs: &[String]) -> Vec<ColorBook> {
|
pub fn read_all() -> Vec<ColorBook> {
|
||||||
#[cfg_attr(target_arch = "wasm32", allow(unused_mut))]
|
#[cfg_attr(target_arch = "wasm32", allow(unused_mut))]
|
||||||
let mut books: Vec<_> = builtin().collect();
|
let mut books: Vec<_> = builtin().collect();
|
||||||
// Browsers have no folders.
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
|
||||||
let _ = dirs;
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
for book in dirs
|
if let Some(dir) = folder() {
|
||||||
.iter()
|
let mut files: Vec<_> = std::fs::read_dir(dir)
|
||||||
.flat_map(|dir| {
|
.into_iter()
|
||||||
let mut files: Vec<_> = std::fs::read_dir(dir)
|
.flatten()
|
||||||
.into_iter()
|
.filter_map(|entry| entry.ok().map(|entry| entry.path()))
|
||||||
.flatten()
|
.filter(|path| {
|
||||||
.filter_map(|entry| entry.ok().map(|entry| entry.path()))
|
path.extension()
|
||||||
.filter(|path| {
|
.is_some_and(|ext| ext.eq_ignore_ascii_case("acb"))
|
||||||
path.extension()
|
})
|
||||||
.is_some_and(|ext| ext.eq_ignore_ascii_case("acb"))
|
.collect();
|
||||||
})
|
files.sort();
|
||||||
.collect();
|
for book in files
|
||||||
files.sort();
|
.into_iter()
|
||||||
files
|
.filter_map(|path| std::fs::read_to_string(path).ok())
|
||||||
})
|
.filter_map(|text| parse(&text).ok())
|
||||||
.filter_map(|path| std::fs::read_to_string(path).ok())
|
{
|
||||||
.filter_map(|text| parse(&text).ok())
|
add_or_replace(&mut books, book);
|
||||||
{
|
}
|
||||||
add_or_replace(&mut books, book);
|
|
||||||
}
|
}
|
||||||
books
|
books
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Ask for an `.acb` file and read it. On desktop the file is copied into
|
/// Ask for an `.acb` file and read it. On desktop the file is copied into
|
||||||
/// `folder`, the first colour book folder, so it stays when the original
|
/// the colour book folder, so it stays when the original moves; the web
|
||||||
/// moves; the web keeps the book for the session only.
|
/// keeps the book for the session only.
|
||||||
pub async fn load_from_dialog(folder: Option<String>) -> Result<ColorBook, String> {
|
pub async fn load_from_dialog() -> Result<ColorBook, String> {
|
||||||
let file = crate::sys::file_dialog()
|
let file = crate::sys::file_dialog()
|
||||||
.add_filter(crate::t!("Color book").as_ref(), &["acb", "ACB"])
|
.add_filter(crate::t!("Color book").as_ref(), &["acb", "ACB"])
|
||||||
.pick_file()
|
.pick_file()
|
||||||
@@ -121,14 +124,11 @@ pub async fn load_from_dialog(folder: Option<String>) -> Result<ColorBook, Strin
|
|||||||
let bytes = file.read().await;
|
let bytes = file.read().await;
|
||||||
let book = parse(&String::from_utf8_lossy(&bytes))?;
|
let book = parse(&String::from_utf8_lossy(&bytes))?;
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
if let Some(folder) = folder {
|
if let Some(folder) = folder() {
|
||||||
let folder = std::path::PathBuf::from(folder);
|
|
||||||
std::fs::create_dir_all(&folder)
|
std::fs::create_dir_all(&folder)
|
||||||
.and_then(|()| std::fs::write(folder.join(file.file_name()), &bytes))
|
.and_then(|()| std::fs::write(folder.join(file.file_name()), &bytes))
|
||||||
.map_err(|e| e.to_string())?;
|
.map_err(|e| e.to_string())?;
|
||||||
}
|
}
|
||||||
#[cfg(target_arch = "wasm32")]
|
|
||||||
let _ = folder;
|
|
||||||
Ok(book)
|
Ok(book)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -108,6 +108,8 @@ pub struct Folders {
|
|||||||
/// Where `.shx` / `.ttf` fonts dropped in by the user (or downloaded for
|
/// Where `.shx` / `.ttf` fonts dropped in by the user (or downloaded for
|
||||||
/// a drawing) are found.
|
/// a drawing) are found.
|
||||||
pub fonts: Option<String>,
|
pub fonts: Option<String>,
|
||||||
|
/// Where `.acb` colour books are kept and loaded ones copied to.
|
||||||
|
pub color_books: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Values read from the current drawing's header rather than from preferences.
|
/// Values read from the current drawing's header rather than from preferences.
|
||||||
@@ -212,7 +214,6 @@ pub fn view_window<'a>(
|
|||||||
drawing_prefs: DrawingPrefs,
|
drawing_prefs: DrawingPrefs,
|
||||||
folders: Folders,
|
folders: Folders,
|
||||||
qnew_template: &'a str,
|
qnew_template: &'a str,
|
||||||
color_book_dirs: &'a [String],
|
|
||||||
double_click_block_refedit: bool,
|
double_click_block_refedit: bool,
|
||||||
double_click_block_attedit: bool,
|
double_click_block_attedit: bool,
|
||||||
cursor_type: CursorType,
|
cursor_type: CursorType,
|
||||||
@@ -1791,13 +1792,11 @@ pub fn view_window<'a>(
|
|||||||
folder_row(crate::t!("Autosave files"), folders.autosave.clone()),
|
folder_row(crate::t!("Autosave files"), folders.autosave.clone()),
|
||||||
Space::new().height(12),
|
Space::new().height(12),
|
||||||
folder_row(crate::t!("Fonts"), folders.fonts.clone()),
|
folder_row(crate::t!("Fonts"), folders.fonts.clone()),
|
||||||
// Where `.acb` colour books are found (none on the web).
|
Space::new().height(12),
|
||||||
color_book_dirs.iter().fold(column![], |rows, dir| rows
|
folder_row(
|
||||||
.push(Space::new().height(12))
|
crate::t!("Color book locations"),
|
||||||
.push(folder_row(
|
folders.color_books.clone()
|
||||||
crate::t!("Color book locations"),
|
),
|
||||||
Some(dir.clone())
|
|
||||||
))),
|
|
||||||
Space::new().height(16),
|
Space::new().height(16),
|
||||||
text(crate::t!("Default template for new drawings")).size(12),
|
text(crate::t!("Default template for new drawings")).size(12),
|
||||||
Space::new().height(4),
|
Space::new().height(4),
|
||||||
|
|||||||
Reference in new issue
Block a user