mirror of
https://github.com/InioX/matugen.git
synced 2025-05-12 21:10:36 +01:00
feat(gui): add images tab
This commit is contained in:
parent
25617214af
commit
c708abab2f
3 changed files with 151 additions and 10 deletions
60
Cargo.lock
generated
60
Cargo.lock
generated
|
@ -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"
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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");
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue