1
0
Fork 0
This repository has been archived on 2023-11-15. You can view files and clone it, but you cannot make any changes to it's state, such as pushing and creating new issues, pull requests or comments.
comicinfo-editor/src/main.rs
2023-09-29 00:21:42 +02:00

447 lines
16 KiB
Rust

use std::any::Any;
use std::iter::Enumerate;
use egui::{widgets, TextStyle};
use crate::metadata::{AgeRating, LanguageISO, Metadata};
use eframe::egui;
use strum::IntoEnumIterator;
use crate::parsers::{MetadataSource, Parser};
mod metadata;
mod parsers;
const TEXT_SIZE_SMALL: f32 = 1.0;
const TEXT_SIZE_MEDIUM: f32 = 1.2;
const TEXT_SIZE_LARGE: f32 = 1.4;
fn main() -> Result<(), eframe::Error> {
env_logger::init();
let options = eframe::NativeOptions {
initial_window_size: Some(egui::vec2(1280.0, 720.0)),
..Default::default()
};
eframe::run_native(
"Metadata Generator",
options,
Box::new(|cc| {
cc.egui_ctx.set_pixels_per_point(TEXT_SIZE_MEDIUM);
Box::<Generator>::default()
}),
)
}
struct Generator<'a> {
show_all: bool,
metadata: Vec<Metadata<'a>>,
selected_parser: Box<dyn Parser>,
meta_path: Option<String>,
bundle: bool,
bundle_source: Option<String>,
bundle_path: Option<String>,
footer_height: f32,
}
impl Default for Generator<'_> {
fn default() -> Self {
Self {
show_all: false,
metadata: vec![Metadata::default()],
selected_parser: Box::new(parsers::file::File::new()),
meta_path: None,
bundle: false,
bundle_source: None,
bundle_path: None,
footer_height: 0.0,
}
}
}
impl eframe::App for Generator<'_> {
fn update(&mut self, ctx: &egui::Context, frame: &mut eframe::Frame) {
let ParserList: Vec<Box<dyn Parser>> = vec![
Box::new(parsers::fakku::Fakku::new()),
Box::new(parsers::file::File::new()),
Box::new(parsers::irodori::Irodori::new()),
Box::new(parsers::jnovel::JNovel::new()),
];
// Non-Metadata Options
egui::SidePanel::right("Options")
.resizable(false)
.min_width(ctx.screen_rect().width() / 3.0)
.max_width(ctx.screen_rect().width() / 3.0)
.show(ctx, |panel| {
panel.heading("Options");
panel.horizontal(|row| {
row.label("Parser: ");
egui::containers::ComboBox::from_label("")
.selected_text(self.selected_parser.get_display_string())
.show_ui(row, |ui| {
for parser in ParserList {
let text = parser.get_display_string().clone();
if ui.selectable_value(&mut self.selected_parser.get_display_string(), parser.get_display_string(), text).clicked() {
self.selected_parser = parser;
};
}
});
});
let file_label;
if self.selected_parser.source_is_file() {
file_label = "File Path";
} else {
file_label = "URL";
}
text_input_option(panel, &mut self.meta_path, file_label, self.selected_parser.source_is_file());
// TODO this feels wrong, there must be a better way
panel.add_space(self.footer_height * 0.1);
panel.separator();
panel.add_space(self.footer_height * 0.1);
panel.horizontal(|row| {
row.label("Perform Bundle: ");
row.add(widgets::Checkbox::new(&mut self.bundle, ""));
});
if self.bundle {
text_input_option(panel, &mut self.bundle_source, "Images Folder", true);
text_input_option(panel, &mut self.bundle_path, "Output Path", true);
}
panel.add_space(self.footer_height * 2.0);
panel.horizontal(|elem| {
elem.vertical_centered(|centered| {
if centered.button("Generate Metadata").clicked() {
// Run Metadata Generation
// DO NOT SAVE RESULTS YET ONLY POPULATE DATA
println!("Ran Generation (not yet)");
}
})
});
panel.add_space(panel.available_height() - self.footer_height);
self.footer_height = panel
.horizontal(|row| {
let ppp = ctx.pixels_per_point();
row.label("Text Size:");
if row
.add(widgets::RadioButton::new(ppp == TEXT_SIZE_SMALL, "Small"))
.clicked()
{
ctx.set_pixels_per_point(TEXT_SIZE_SMALL);
}
if row
.add(widgets::RadioButton::new(ppp == TEXT_SIZE_MEDIUM, "Medium"))
.clicked()
{
ctx.set_pixels_per_point(TEXT_SIZE_MEDIUM);
}
if row
.add(widgets::RadioButton::new(ppp == TEXT_SIZE_LARGE, "Large"))
.clicked()
{
ctx.set_pixels_per_point(TEXT_SIZE_LARGE);
}
})
.response
.rect
.height();
});
// Metadata Options
egui::CentralPanel::default().show(ctx, |ui| {
ui.heading("Metadata");
// Title & Series
text_input(ui, &mut self.metadata[0].series, "Series", false);
text_input(ui, &mut self.metadata[0].title, "Title", false);
// Volume and Chapter Info
ui.horizontal(|row| {
row.label("Volume:");
if row.button("-").clicked() {
self.metadata[0].volume -= 1;
}
row.label(format!("{}", self.metadata[0].volume));
if row.button("+").clicked() {
self.metadata[0].volume += 1;
}
row.label("Chapter:");
if row.button("-").clicked() {
self.metadata[0].number -= 1;
}
row.label(format!("{}", self.metadata[0].number));
if row.button("+").clicked() {
self.metadata[0].number += 1;
}
});
ui.horizontal(|row| {
row.label("Series Chapter Count:");
if row.button("-").clicked() {
self.metadata[0].count -= 1;
}
row.label(format!("{}", self.metadata[0].count));
if row.button("+").clicked() {
self.metadata[0].count += 1;
}
});
ui.label("Summary Edit:");
let mut summary = self.metadata[0].summary.clone().unwrap_or("".to_string());
if ui.add(egui::TextEdit::multiline(&mut summary)).changed() {
self.metadata[0].summary = Some(summary);
};
// Date Inputs
let glyph_width = ctx
.fonts(|f| -> f32 { f.glyph_width(&TextStyle::Body.resolve(ui.style()), '0') });
let mut year_text = self.metadata[0].year.to_string();
ui.horizontal(|row| {
row.label("Release Date:");
if row
.add(
widgets::text_edit::TextEdit::singleline(&mut year_text)
.desired_width(5.0 * glyph_width),
)
.changed()
{
let trimmed = year_text.trim();
if trimmed == "0" {
self.metadata[0].year = -1;
self.metadata[0].month = -1;
self.metadata[0].day = -1;
} else {
self.metadata[0].year =
trimmed.parse::<i16>().unwrap_or(self.metadata[0].year);
}
};
if self.metadata[0].year >= 1970 {
let mut month_text = self.metadata[0].month.to_string();
if row
.add(
widgets::text_edit::TextEdit::singleline(&mut month_text)
.desired_width(3.0 * glyph_width),
)
.changed()
{
let trimmed = month_text.trim();
if trimmed == "0" {
self.metadata[0].month = -1;
self.metadata[0].day = -1;
} else {
self.metadata[0].month = month_text
.trim()
.parse::<i8>()
.unwrap_or(self.metadata[0].month);
}
};
if self.metadata[0].month >= 0 {
let mut day_text = self.metadata[0].day.to_string();
if row
.add(
widgets::text_edit::TextEdit::singleline(&mut day_text)
.desired_width(3.0 * glyph_width),
)
.changed()
{
let trimmed = day_text.trim();
if trimmed == "0" {
self.metadata[0].day = -1;
} else {
self.metadata[0].day = day_text
.trim()
.parse::<i8>()
.unwrap_or(self.metadata[0].day);
}
};
}
}
});
// People involved
text_input_option(ui, &mut self.metadata[0].writer, "Author", false);
text_input_option(ui, &mut self.metadata[0].letterer, "Typesetter", false);
text_input_option(ui, &mut self.metadata[0].editor, "Editor", false);
text_input_option(ui, &mut self.metadata[0].translator, "Translator", false);
text_input_option(ui, &mut self.metadata[0].publisher, "Publisher", false);
/*
tags: Vec<String>,
characters: Vec<String>,
*/
// TODO tag list (List of bordered labels with plus that opens a new text edit)
ui.horizontal(|row| {
row.label("Tags:");
for mut tag in &mut self.metadata[0].tags {
text_input(row, &mut tag, "", false);
}
if row.button("+").clicked() {
&self.metadata[0].tags.push("".to_string());
};
});
text_input(ui, &mut self.metadata[0].genre, "Genre", false);
ui.horizontal(|row| {
row.label("Page Count:");
if row.button("-").clicked() {
self.metadata[0].page_count -= 1;
}
row.label(format!("{}", self.metadata[0].page_count));
if row.button("+").clicked() {
self.metadata[0].page_count += 1;
}
});
//text_input(ui, &mut self.metadata[0].page_count, "Page Count", false);
// Lang Drop Down
ui.horizontal(|row| {
row.label("Language: ");
egui::containers::ComboBox::from_label("a")
.selected_text(self.metadata[0].language.to_string())
.show_ui(row, |ui| {
for language in LanguageISO::iter() {
let text = language.to_string().clone();
ui.selectable_value(&mut self.metadata[0].language, language, text);
}
});
});
// TODO same as with Tags but for characters
// Age Rating Drop Down
ui.horizontal(|row| {
row.label("Age Rating: ");
egui::containers::ComboBox::from_label("b")
.selected_text(self.metadata[0].age_rating.to_string())
.show_ui(row, |ui| {
for rating in AgeRating::iter() {
let text = rating.to_string().clone();
ui.selectable_value(&mut self.metadata[0].age_rating, rating, text);
}
});
});
ui.horizontal(|elem| {
elem.vertical_centered(|centered| {
if centered.button("Save Metadata").clicked() {
// Run Metadata Generation
// DO NOT SAVE RESULTS YET ONLY POPULATE DATA
self.metadata[0].save_to_xml("/home/neshura/Repositories/comicinfo-editor/ComicInfo.xml")
}
})
});
if self.show_all {
ui.label(format!("Not Implemented yet."));
}
});
}
}
pub(crate) fn text_input_option(
ui: &mut egui::Ui,
option: &mut Option<String>,
label: &str,
file_picker: bool,
) -> egui::InnerResponse<()> {
let zero_width =
2.0 * ui.fonts(|f| -> f32 { f.glyph_width(&TextStyle::Body.resolve(ui.style()), '0') });
ui.horizontal(|row| {
row.label(format!("{}:", label));
if let Some(ref mut text) = option {
let dynamic_width = zero_width
+ text
.chars()
.map(|c| {
row.fonts(|f| -> f32 {
f.glyph_width(&TextStyle::Body.resolve(row.style()), c)
})
})
.sum::<f32>();
row.add(
widgets::text_edit::TextEdit::singleline(text).desired_width(
if dynamic_width >= zero_width * 3.0 {
dynamic_width
} else {
zero_width * 3.0
},
),
);
if text == "" {
*option = None;
}
} else {
let mut init = "".to_string();
row.add(
widgets::text_edit::TextEdit::singleline(&mut init).desired_width(zero_width * 3.0),
);
if init != "" {
*option = Some(init);
}
}
if file_picker {
if row.button("...").clicked() {
if let Some(path) = rfd::FileDialog::new().pick_file() {
*option = Some(path.display().to_string());
}
}
}
})
}
pub(crate) fn text_input(
ui: &mut egui::Ui,
option: &mut String,
label: &str,
file_picker: bool,
) -> egui::InnerResponse<()> {
let zero_width =
2.0 * ui.fonts(|f| -> f32 { f.glyph_width(&TextStyle::Body.resolve(ui.style()), '0') });
ui.horizontal(|row| {
row.label(format!("{}:", label));
let dynamic_width = zero_width
+ option
.chars()
.map(|c| {
row.fonts(|f| -> f32 {
f.glyph_width(&TextStyle::Body.resolve(row.style()), c)
})
})
.sum::<f32>();
row.add(
widgets::text_edit::TextEdit::singleline(option).desired_width(
if dynamic_width >= zero_width * 3.0 {
dynamic_width
} else {
zero_width * 3.0
},
),
);
if file_picker {
if row.button("...").clicked() {
if let Some(path) = rfd::FileDialog::new().pick_file() {
*option = path.display().to_string();
}
}
}
})
}