plate-tool/plate-tool-eframe/src/app.rs

262 lines
10 KiB
Rust

use std::ops::DerefMut;
use std::sync::Mutex;
use eframe::egui::{self};
use crate::main_state::{construct_fake_mainstate, MainState};
use crate::modals::{self, ModalState};
use crate::plate::{add_plate, PlateDisplayOptions, PlateUiState};
use crate::transfer_menu::{transfer_menu, CurrentTransferState, TransferMenuState};
use crate::tree::tree;
#[non_exhaustive]
#[derive(Debug, serde::Serialize, serde::Deserialize)]
struct MainWindowState {
show_side_panel: bool,
plate_display_options: PlateDisplayOptions,
}
impl Default for MainWindowState {
fn default() -> Self {
Self {
show_side_panel: true,
plate_display_options: PlateDisplayOptions::default(),
}
}
}
#[non_exhaustive]
#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub struct PlateToolEframe {
source_plate_state: Mutex<PlateUiState>,
destination_plate_state: Mutex<PlateUiState>,
main_window_state: MainWindowState,
current_transfer_state: CurrentTransferState,
#[serde(skip)]
modal_state: ModalState,
#[serde(skip)]
transfer_menu_state: TransferMenuState,
main_state: MainState,
}
impl Default for PlateToolEframe {
fn default() -> Self {
Self {
source_plate_state: Mutex::new(PlateUiState::default()),
destination_plate_state: Mutex::new(PlateUiState::default()),
main_window_state: MainWindowState::default(),
current_transfer_state: CurrentTransferState::default(),
modal_state: ModalState::default(),
transfer_menu_state: TransferMenuState::default(),
main_state: construct_fake_mainstate(),
}
}
}
impl PlateToolEframe {
pub fn new(cc: &eframe::CreationContext<'_>) -> Self {
// Would load state here
if let Some(storage) = cc.storage {
let out: PlateToolEframe =
eframe::get_value(storage, eframe::APP_KEY).unwrap_or_default();
return out;
} else {
let pte: PlateToolEframe = Default::default();
pte.main_state
.transfer_region_cache
.generate_cache(&pte.main_state.transfers);
pte
}
}
}
impl eframe::App for PlateToolEframe {
// State storage
fn save(&mut self, storage: &mut dyn eframe::Storage) {
log::info!("Saving state");
eframe::set_value(storage, eframe::APP_KEY, self);
}
fn update(&mut self, ctx: &eframe::egui::Context, _frame: &mut eframe::Frame) {
crate::styling::set_visuals(&ctx);
egui::TopBottomPanel::top("top_panel").show(ctx, |ui| {
egui::menu::bar(ui, |ui| {
ui.menu_button("File", |ui| {
if ui.button("New Plate").clicked() {
crate::modals::open_new_plate_modal(&mut self.modal_state);
}
ui.menu_button("Export", |ui| {
if ui.button("Export as CSV").clicked() {}
if ui.button("Export as JSON").clicked() {}
});
ui.menu_button("Import", |ui| {
if ui.button("Import from JSON").clicked() {}
if ui.button("Import transfer from CSV").clicked() {}
});
if ui.button("Reset All").clicked() {
self.main_state = MainState::default();
self.current_transfer_state = CurrentTransferState::default();
}
if ui.button("Dump State").clicked() {
log::warn!("{:?}\n{:?}", self.main_state, self.current_transfer_state);
}
});
ui.menu_button("Options", |ui| {
ui.menu_button("Styles", |ui| {
ui.toggle_value(
&mut self
.main_window_state
.plate_display_options
.show_transfer_hashes,
"Toggle transfer hashes",
);
ui.toggle_value(
&mut self
.main_window_state
.plate_display_options
.show_volume_heatmap,
"Toggle volume heatmap",
);
ui.toggle_value(
&mut self
.main_window_state
.plate_display_options
.show_coordinates,
"Toggle coordinate highlighting",
);
});
ui.menu_button("Exports", |ui| {
if ui.button("Change CSV export type").clicked() {}
});
ui.menu_button("Windows", |ui| {
ui.toggle_value(
&mut self.main_window_state.show_side_panel,
"Toggle side panel",
);
});
});
});
});
if self.main_window_state.show_side_panel {
egui::SidePanel::left("side_menus").show(ctx, |ui| {
ui.vertical(|ui| {
tree(
ui,
&mut self.main_state,
&self.current_transfer_state,
&mut self.modal_state,
);
ui.separator();
transfer_menu(
ui,
&self.current_transfer_state,
&mut self.transfer_menu_state,
&mut self.main_state,
);
});
});
}
// This MUST happen after the menu calls as they can mutate main state
let ordered_ids: Vec<plate_tool_lib::uuid::Uuid> = {
let mut ids: Vec<plate_tool_lib::uuid::Uuid> = self
.main_state
.transfers
.clone()
.iter()
.map(|x| x.id)
.collect();
ids.sort_unstable();
ids
};
egui::CentralPanel::default().show(ctx, |ui| {
ui.vertical(|ui| {
let available_size = ui.available_size();
let half_height = {
let mut x = available_size;
x.y /= 2.0;
x
};
if let Some(source_pi) = self.main_state.get_current_source_plateinstance() {
add_plate(
half_height,
source_pi.plate.plate_format,
self.main_state.get_current_source_transfers(),
plate_tool_lib::plate::PlateType::Source,
&ordered_ids,
&self.main_state.transfer_region_cache,
Some(&self.current_transfer_state),
ui,
self.source_plate_state.lock().unwrap().deref_mut(),
self.main_window_state.plate_display_options,
);
}
if let Some(destination_pi) =
self.main_state.get_current_destination_plateinstance()
{
add_plate(
half_height,
destination_pi.plate.plate_format,
self.main_state.get_current_destination_transfers(),
plate_tool_lib::plate::PlateType::Destination,
&ordered_ids,
&self.main_state.transfer_region_cache,
Some(&self.current_transfer_state),
ui,
self.destination_plate_state.lock().unwrap().deref_mut(),
self.main_window_state.plate_display_options,
);
}
});
});
// Modal processing
modals::show_modal_if_open(ctx, &mut self.modal_state);
match &self.modal_state {
modals::ModalState::NewPlateComplete(modals::NewPlateModalComplete(Some(pi))) => {
let plate_type = pi.plate.plate_type;
match plate_type {
plate_tool_lib::plate::PlateType::Source => {
self.main_state.source_plates.push(pi.clone());
}
plate_tool_lib::plate::PlateType::Destination => {
self.main_state.destination_plates.push(pi.clone());
}
}
self.modal_state = modals::ModalState::None;
}
modals::ModalState::EditPlateComplete(modals::EditPlateModalStateComplete(Some(x))) => {
let pi = {
match x.plate_type {
plate_tool_lib::plate::PlateType::Source => self
.main_state
.source_plates
.iter_mut()
.find(|y| y.get_uuid() == x.id),
plate_tool_lib::plate::PlateType::Destination => self
.main_state
.destination_plates
.iter_mut()
.find(|y| y.get_uuid() == x.id),
}
};
if let Some(pi) = pi {
pi.name = x.name.to_owned();
pi.change_format(&x.plate_format);
}
self.modal_state = modals::ModalState::None;
}
ModalState::NewPlateComplete(modals::NewPlateModalComplete(None)) => {
self.modal_state = modals::ModalState::None;
}
ModalState::EditPlateComplete(modals::EditPlateModalStateComplete(None)) => {
self.modal_state = modals::ModalState::None;
}
_ => (),
}
}
}