use bladvak::eframe::egui::{self, Color32, TextFormat, text::LayoutJob};
use bladvak::errors::ErrorManager;
use bladvak::utils::is_web;
use image::ImageFormat;
use std::io::Cursor;
use std::path::Path;
use crate::document::Document;
use crate::{TarsierApp, edit_mode::EditMode};
impl TarsierApp {
pub(crate) fn app_menu_file(&mut self, ui: &mut egui::Ui, error_manager: &mut ErrorManager) {
if ui.button("New").clicked() {
self.settings.new_image.is_open = true;
ui.close();
}
self.menu_clipboard(ui, error_manager);
if self.documents.is_some() {
ui.menu_button("Save", |ui| {
if ui.button("PNG").clicked() {
ui.close();
self.save_image_with_format(
ImageFormat::Png.extensions_str()[0],
ImageFormat::Png,
error_manager,
);
}
if ui.button("JPEG").clicked() {
ui.close();
self.save_image_with_format(
ImageFormat::Jpeg.extensions_str()[0],
ImageFormat::Jpeg,
error_manager,
);
}
if ui.button("BMP").clicked() {
ui.close();
self.save_image_with_format(
ImageFormat::Bmp.extensions_str()[0],
ImageFormat::Bmp,
error_manager,
);
}
if ui.button("GIF").clicked() {
ui.close();
self.save_image_with_format(
ImageFormat::Gif.extensions_str()[0],
ImageFormat::Gif,
error_manager,
);
}
});
}
}
pub fn menu_clipboard(&mut self, ui: &mut egui::Ui, error_manager: &mut ErrorManager) {
let is_document = self.documents.is_some();
#[cfg(target_arch = "wasm32")]
if !is_document {
return;
}
ui.menu_button("Clipboard", |ui| {
let show_copy = if is_web() { true } else { is_document };
if show_copy
&& ui.button("Copy").clicked()
&& let Some(document) = self.documents.get_current_doc_mut()
&& let Err(e) = bladvak::utils::set_image_in_clipboard(
ui.ctx(),
document.img.width() as usize,
document.img.height() as usize,
document.img.to_rgba8().as_flat_samples().as_slice(),
)
{
error_manager.add_error(e);
}
#[cfg(not(target_arch = "wasm32"))]
if ui.button("Paste").clicked() {
match bladvak::utils::get_image_from_clipboard() {
Ok((width, height, rgba_data)) => {
#[allow(clippy::cast_possible_truncation)]
if let Some(buffer) = image::ImageBuffer::from_raw(
width as u32,
height as u32,
rgba_data.clone(),
) {
use std::path::PathBuf;
let img = image::DynamicImage::ImageRgba8(buffer);
self.new_file(PathBuf::from("pasted.png"), img, None);
} else {
error_manager
.add_error("Invalid image data from clipboard".to_string());
}
}
Err(e) => {
error_manager.add_error(e);
}
}
}
});
}
pub(crate) fn save_image_with_format(
&mut self,
extension: &str,
image_format: ImageFormat,
error_manager: &mut ErrorManager,
) {
let Some(document) = self.documents.get_current_doc_mut() else {
error_manager.add_error("No document to save");
return;
};
let current_save_path =
if document.filename.extension().and_then(|e| e.to_str()) == Some(extension) {
document.filename.clone()
} else {
document.filename.with_extension(extension)
};
let save_path = bladvak::utils::get_save_path(Some(¤t_save_path));
match save_path {
Ok(save_p) => {
if let Some(path_to_save) = save_p {
document.filename.clone_from(&path_to_save);
if let Err(err) = document.save_image(image_format, &path_to_save) {
error_manager.add_error(err);
}
}
}
Err(e) => {
error_manager.add_error(e);
}
}
}
pub(crate) fn app_top_panel(&mut self, ui: &mut egui::Ui, _error_manager: &mut ErrorManager) {
let Some(document) = self.documents.get_current_doc_mut() else {
return;
};
ui.separator();
let (default_color, background_color) = if ui.visuals().dark_mode {
(Color32::LIGHT_GRAY, Color32::DARK_BLUE)
} else {
(Color32::DARK_GRAY, Color32::LIGHT_BLUE)
};
let mut job = LayoutJob::default();
job.append(
"Mode ",
0.0,
TextFormat {
color: default_color,
..Default::default()
},
);
job.append(
&format!("{}", self.mode.current),
0.0,
TextFormat {
color: default_color,
background: background_color,
..Default::default()
},
);
ui.menu_button(job, |ui| {
let previous_state = self.mode.current;
ui.selectable_value(&mut self.mode.current, EditMode::Cursor, "Cursor");
ui.selectable_value(&mut self.mode.current, EditMode::Selection, "Selection");
ui.selectable_value(&mut self.mode.current, EditMode::Drawing, "Drawing");
if self.mode.current != previous_state {
ui.close();
if self.mode.current != EditMode::Selection {
document.selection.rectangle = None;
}
}
});
ui.separator();
self.documents.show_file_list(ui);
}
}
impl Document {
fn save_image(&mut self, format: ImageFormat, path_file: &Path) -> Result<(), String> {
let mut bytes: Vec<u8> = Vec::new();
self.img
.write_to(&mut Cursor::new(&mut bytes), format)
.map_err(|e| format!("Cannot write image: {e}"))?;
bladvak::utils::save_file(&bytes, path_file)
}
}