feat(gui): add images tab

This commit is contained in:
InioX 2025-03-23 16:53:49 +01:00
parent 25617214af
commit c708abab2f
3 changed files with 151 additions and 10 deletions

60
Cargo.lock generated
View file

@ -1336,6 +1336,20 @@ dependencies = [
"winit",
]
[[package]]
name = "egui_extras"
version = "0.29.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf3c1f5cd8dfe2ade470a218696c66cf556fcfd701e7830fa2e9f4428292a2a1"
dependencies = [
"ahash",
"egui",
"enum-map",
"image",
"log",
"mime_guess2",
]
[[package]]
name = "egui_file"
version = "0.19.0"
@ -1407,6 +1421,27 @@ dependencies = [
"thiserror",
]
[[package]]
name = "enum-map"
version = "2.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6866f3bfdf8207509a033af1a75a7b08abda06bbaaeae6669323fd5a097df2e9"
dependencies = [
"enum-map-derive",
"serde",
]
[[package]]
name = "enum-map-derive"
version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f282cfdfe92516eb26c2af8589c274c7c17681f5ecc03c18255fe741c6aa64eb"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.75",
]
[[package]]
name = "enumflags2"
version = "0.7.10"
@ -2512,6 +2547,7 @@ dependencies = [
"directories",
"eframe",
"egui",
"egui_extras",
"egui_file",
"enquote",
"execute",
@ -2588,6 +2624,16 @@ version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
[[package]]
name = "mime_guess2"
version = "2.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25a3333bb1609500601edc766a39b4c1772874a4ce26022f4d866854dc020c41"
dependencies = [
"mime",
"unicase",
]
[[package]]
name = "minimal-lexical"
version = "0.2.1"
@ -3293,18 +3339,18 @@ dependencies = [
[[package]]
name = "profiling"
version = "1.0.15"
version = "1.0.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43d84d1d7a6ac92673717f9f6d1518374ef257669c24ebc5ac25d5033828be58"
checksum = "afbdc74edc00b6f6a218ca6a5364d6226a259d4b8ea1af4a0ea063f27e179f4d"
dependencies = [
"profiling-procmacros",
]
[[package]]
name = "profiling-procmacros"
version = "1.0.15"
version = "1.0.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8021cf59c8ec9c432cfc2526ac6b8aa508ecaf29cd415f271b8406c1b851c3fd"
checksum = "a65f2e60fbf1063868558d69c6beacf412dc755f9fc020f514b7955fc914fe30"
dependencies = [
"quote",
"syn 2.0.75",
@ -4468,6 +4514,12 @@ dependencies = [
"winapi",
]
[[package]]
name = "unicase"
version = "2.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539"
[[package]]
name = "unicode-bidi"
version = "0.3.15"

View file

@ -28,6 +28,7 @@ ui = [
"dep:indexmap",
"dep:egui_file",
"dep:rfd",
"dep:egui_extras",
]
[dev-dependencies]
@ -79,6 +80,7 @@ reqwest = { version = "0.12.5", default-features = false, features = [
# gui feature
egui = { version = "0.29.1", optional = true }
egui_extras = { version = "0.29.1", optional = true, features = ["image", "file"] }
eframe = { version = "0.29.1", optional = true }
indexmap = { version = "2.7.0", optional = true }
egui_file = { version = "0.19.0", optional = true }

View file

@ -1,4 +1,4 @@
use std::path::PathBuf;
use std::{ffi::OsStr, path::PathBuf};
#[cfg(feature = "ui")]
use indexmap::IndexMap;
@ -20,6 +20,7 @@ use crate::{template::TemplateFile, util::arguments::Cli, State};
#[cfg(feature = "ui")]
#[derive(PartialEq)]
pub enum Tabs {
Images,
Settings,
Colors,
}
@ -33,6 +34,8 @@ pub struct MyApp {
colors: ColorsMap,
selected_tab: Tabs,
app: State,
images_vec: Vec<PathBuf>,
images_folder: Option<PathBuf>,
}
#[cfg(feature = "ui")]
@ -41,6 +44,25 @@ pub struct ColorsMap {
pub dark: Option<IndexMap<String, Color32>>,
}
fn get_images_in_folder(folder_path: &PathBuf) -> Vec<PathBuf> {
let valid_extensions = ["jpg", "jpeg", "png", "gif", "bmp", "tiff", "webp"];
std::fs::read_dir(folder_path)
.ok()
.into_iter()
.flatten()
.flatten()
.map(|entry| entry.path())
.filter(|path| path.is_file())
.filter(|path| {
path.extension()
.and_then(|ext| ext.to_str())
.map(|ext| valid_extensions.contains(&ext.to_lowercase().as_str()))
.unwrap_or(false)
})
.collect()
}
// FIXME: Cleanup code, reorganize stuff into its own functions
#[cfg(feature = "ui")]
@ -55,12 +77,15 @@ impl MyApp {
dark: None,
},
selected_tab: Tabs::Settings,
images_vec: vec![],
images_folder: None,
}
}
fn body(&mut self, ui: &mut Ui) {
match self.selected_tab {
Tabs::Settings => self.settings(ui),
Tabs::Colors => self.colors(ui),
Tabs::Images => self.images(ui),
}
}
@ -73,7 +98,7 @@ impl MyApp {
));
});
ui.label("Scheme type");
egui::ComboBox::from_label("Select one!")
egui::ComboBox::from_label("")
.selected_text(format!("{:?}", self.app.args.r#type.unwrap()))
.show_ui(ui, |ui| {
ui.selectable_value(
@ -172,20 +197,80 @@ impl MyApp {
});
}
fn images(&mut self, ui: &mut Ui) {
if self.images_vec.is_empty() {
ui.label("No image folder selected or no images to show.");
} else {
ui.with_layout(
egui::Layout::left_to_right(egui::Align::Max).with_cross_justify(true),
|ui| {
self.show_images(ui);
},
);
}
}
fn show_images(&mut self, ui: &mut Ui) {
egui::ScrollArea::vertical().show(ui, |ui| {
egui::Grid::new("image_grid")
.num_columns(3) // Set number of columns
.spacing([10.0, 10.0]) // Spacing between items
.show(ui, |ui| {
for (i, path) in self.images_vec.clone().iter().enumerate() {
let img_widget = egui::Image::from_uri(format!(
"file://{}",
path.clone().into_os_string().into_string().unwrap()
))
.max_height(300.0)
.max_width(300.0)
.maintain_aspect_ratio(true)
.fit_to_original_size(1.0);
if ui.add(img_widget.sense(egui::Sense::click())).clicked() {
self.selected_file = Some(path.to_path_buf());
self.run();
}
if (i + 1) % 3 == 0 {
ui.end_row();
}
}
});
});
}
fn update_images_tab(&mut self, ui: &mut Ui, image_folder: Option<PathBuf>) {
if image_folder == Some("".into()) || image_folder.is_none() {
return;
}
let images = get_images_in_folder(&image_folder.as_ref().unwrap());
self.images_vec = images;
}
fn top_buttons(&mut self, ui: &mut Ui) {
if ui.button("Image Folder").clicked() {
if let Some(path) = rfd::FileDialog::new().pick_folder() {
self.update_images_tab(ui, Some(path))
}
}
if ui.button("Select image").clicked() {
if let Some(path) = rfd::FileDialog::new().pick_file() {
self.selected_file = Some(path);
}
}
if ui.button("Run").clicked() {
if self.selected_file != Some("".into()) || self.selected_file.is_some() {
self.update_colors_tab();
self.generate_tempalates();
};
self.run()
}
}
fn run(&mut self) {
if self.selected_file == Some("".into()) || self.selected_file.is_none() {
return;
};
self.generate_tempalates();
self.update_colors_tab();
}
fn generate_tempalates(&mut self) {
let mut engine = self.app.init_engine();
let mut render_data = self.app.init_render_data().unwrap();
@ -225,9 +310,11 @@ fn argb_to_color32(color: &Argb) -> Color32 {
#[cfg(feature = "ui")]
impl eframe::App for MyApp {
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
egui_extras::install_image_loaders(ctx);
egui::TopBottomPanel::top("my_panel").show(ctx, |ui| {
ui.horizontal(|ui| {
ui.horizontal(|ui| {
ui.selectable_value(&mut self.selected_tab, Tabs::Images, "Images");
ui.selectable_value(&mut self.selected_tab, Tabs::Settings, "Settings");
ui.selectable_value(&mut self.selected_tab, Tabs::Colors, "Colors");
});