Compare commits
No commits in common. "5e70a17a00a6a47e052e86cb8925dbd04167f4cb" and "fcbfa6e544ef6a8eae93e08db69f70c81ea7328c" have entirely different histories.
5e70a17a00
...
fcbfa6e544
|
@ -3,24 +3,24 @@ use std::sync::Mutex;
|
|||
|
||||
use eframe::egui::{self};
|
||||
|
||||
use plate_tool_lib::plate::PlateFormat;
|
||||
|
||||
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::plate::{add_plate, PlateUiState};
|
||||
use crate::transfer_menu::{self, 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(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -57,13 +57,10 @@ 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;
|
||||
return eframe::get_value(storage, eframe::APP_KEY).unwrap_or_default();
|
||||
} else {
|
||||
let pte: PlateToolEframe = Default::default();
|
||||
pte.main_state
|
||||
.transfer_region_cache
|
||||
pte.main_state.transfer_region_cache
|
||||
.generate_cache(&pte.main_state.transfers);
|
||||
|
||||
pte
|
||||
|
@ -79,13 +76,11 @@ impl eframe::App for PlateToolEframe {
|
|||
}
|
||||
|
||||
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);
|
||||
crate::modals::open_new_plate_modal(ctx, &mut self.modal_state);
|
||||
}
|
||||
ui.menu_button("Export", |ui| {
|
||||
if ui.button("Export as CSV").clicked() {}
|
||||
|
@ -95,37 +90,13 @@ impl eframe::App for PlateToolEframe {
|
|||
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);
|
||||
}
|
||||
if ui.button("Reset All").clicked() {}
|
||||
});
|
||||
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",
|
||||
);
|
||||
if ui.button("Toggle transfer hashes").clicked() {}
|
||||
if ui.button("Toggle volume heatmap").clicked() {}
|
||||
if ui.button("Toggle current coordinates view").clicked() {}
|
||||
});
|
||||
ui.menu_button("Exports", |ui| {
|
||||
if ui.button("Change CSV export type").clicked() {}
|
||||
|
@ -143,12 +114,7 @@ impl eframe::App for PlateToolEframe {
|
|||
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,
|
||||
);
|
||||
tree(ui, &mut self.main_state, &self.current_transfer_state);
|
||||
ui.separator();
|
||||
transfer_menu(
|
||||
ui,
|
||||
|
@ -184,30 +150,26 @@ impl eframe::App for PlateToolEframe {
|
|||
add_plate(
|
||||
half_height,
|
||||
source_pi.plate.plate_format,
|
||||
self.main_state.get_current_source_transfers(),
|
||||
self.main_state.get_current_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()
|
||||
{
|
||||
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(),
|
||||
self.main_state.get_current_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,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
@ -215,47 +177,19 @@ impl eframe::App for PlateToolEframe {
|
|||
|
||||
// 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;
|
||||
if let modals::ModalState::NewPlateComplete(modals::NewPlateModalComplete(Some(pi))) =
|
||||
&self.modal_state
|
||||
{
|
||||
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());
|
||||
},
|
||||
}
|
||||
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;
|
||||
}
|
||||
_ => (),
|
||||
self.modal_state = modals::ModalState::None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,5 +4,4 @@ mod tree;
|
|||
mod transfer_menu;
|
||||
mod main_state;
|
||||
mod modals;
|
||||
mod styling;
|
||||
pub use app::PlateToolEframe;
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
use core::fmt;
|
||||
|
||||
use plate_tool_lib::plate::PlateFormat;
|
||||
use plate_tool_lib::plate_instances::{self, PlateInstance};
|
||||
use plate_tool_lib::plate_instances;
|
||||
use plate_tool_lib::transfer_region_cache::TransferRegionCache;
|
||||
|
||||
#[derive(Default, serde::Serialize, serde::Deserialize)]
|
||||
#[derive(Default, Debug, serde::Serialize, serde::Deserialize)]
|
||||
pub struct MainState {
|
||||
/// Stores all plates and transfers
|
||||
///
|
||||
|
@ -57,28 +55,14 @@ impl MainState {
|
|||
None
|
||||
}
|
||||
}
|
||||
pub fn get_current_source_transfers(&self) -> Option<Vec<&plate_tool_lib::transfer::Transfer>> {
|
||||
pub fn get_current_transfers(&self) -> Option<Vec<&plate_tool_lib::transfer::Transfer>> {
|
||||
let source_uuid = self.get_current_source_uuid();
|
||||
if let Some(source_uuid) = source_uuid {
|
||||
Some(
|
||||
self.transfers
|
||||
.iter()
|
||||
.filter(|tr| tr.source_id == source_uuid)
|
||||
.collect(),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
pub fn get_current_destination_transfers(&self) -> Option<Vec<&plate_tool_lib::transfer::Transfer>> {
|
||||
let destination_uuid = self.get_current_destination_uuid();
|
||||
if let Some(destination_uuid) = destination_uuid {
|
||||
Some(
|
||||
self.transfers
|
||||
.iter()
|
||||
.filter(|tr| tr.dest_id == destination_uuid)
|
||||
.collect(),
|
||||
)
|
||||
if let (Some(source_uuid), Some(destination_uuid)) = (source_uuid, destination_uuid) {
|
||||
Some(self.transfers
|
||||
.iter()
|
||||
.filter(|tr| tr.source_id == source_uuid && tr.dest_id == destination_uuid)
|
||||
.collect())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
@ -133,12 +117,6 @@ impl MainState {
|
|||
.find(|x| *x == id)
|
||||
.is_some()
|
||||
}
|
||||
pub fn get_source_by_uuid(&self, id: plate_tool_lib::uuid::Uuid) -> Option<&PlateInstance> {
|
||||
self.source_plates
|
||||
.iter()
|
||||
.find(|x| x.get_uuid() == id)
|
||||
}
|
||||
|
||||
fn check_destination_exists(&self, id: plate_tool_lib::uuid::Uuid) -> bool {
|
||||
self.destination_plates
|
||||
.iter()
|
||||
|
@ -146,45 +124,6 @@ impl MainState {
|
|||
.find(|x| *x == id)
|
||||
.is_some()
|
||||
}
|
||||
pub fn get_destination_by_uuid(&self, id: plate_tool_lib::uuid::Uuid) -> Option<&PlateInstance> {
|
||||
self.destination_plates
|
||||
.iter()
|
||||
.find(|x| x.get_uuid() == id)
|
||||
}
|
||||
}
|
||||
impl fmt::Debug for MainState {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
||||
#[derive(Debug)]
|
||||
#[allow(dead_code)]
|
||||
struct SelectedFields<'a> {
|
||||
pub source_plates: &'a Vec<plate_tool_lib::plate_instances::PlateInstance>,
|
||||
pub destination_plates: &'a Vec<plate_tool_lib::plate_instances::PlateInstance>,
|
||||
pub transfers: &'a Vec<plate_tool_lib::transfer::Transfer>,
|
||||
current_source: &'a Option<plate_tool_lib::uuid::Uuid>,
|
||||
current_destination: &'a Option<plate_tool_lib::uuid::Uuid>,
|
||||
current_transfer: &'a Option<plate_tool_lib::uuid::Uuid>,
|
||||
}
|
||||
let Self {
|
||||
source_plates,
|
||||
destination_plates,
|
||||
transfers,
|
||||
current_source,
|
||||
current_destination,
|
||||
current_transfer,
|
||||
transfer_region_cache: _,
|
||||
} = self;
|
||||
fmt::Debug::fmt(
|
||||
&SelectedFields {
|
||||
source_plates,
|
||||
destination_plates,
|
||||
transfers,
|
||||
current_source,
|
||||
current_destination,
|
||||
current_transfer,
|
||||
},
|
||||
f,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn construct_fake_mainstate() -> MainState {
|
||||
|
|
|
@ -5,8 +5,6 @@ use eframe::egui;
|
|||
pub enum ModalState {
|
||||
NewPlate(NewPlateModalState),
|
||||
NewPlateComplete(NewPlateModalComplete),
|
||||
EditPlate(EditPlateModalState),
|
||||
EditPlateComplete(EditPlateModalStateComplete),
|
||||
None,
|
||||
}
|
||||
impl Default for ModalState {
|
||||
|
@ -16,22 +14,11 @@ impl Default for ModalState {
|
|||
}
|
||||
|
||||
#[non_exhaustive]
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Default)]
|
||||
pub struct NewPlateModalState {
|
||||
pub name: String,
|
||||
pub plate_type: plate_tool_lib::plate::PlateType,
|
||||
pub plate_format: plate_tool_lib::plate::PlateFormat,
|
||||
window_open: bool,
|
||||
}
|
||||
impl Default for NewPlateModalState {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
name: String::default(),
|
||||
plate_type: plate_tool_lib::plate::PlateType::default(),
|
||||
plate_format: plate_tool_lib::plate::PlateFormat::default(),
|
||||
window_open: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[non_exhaustive]
|
||||
|
@ -41,7 +28,6 @@ pub struct NewPlateModalComplete(pub Option<plate_tool_lib::plate_instances::Pla
|
|||
pub fn show_modal_if_open(ctx: &egui::Context, modal_state: &mut ModalState) {
|
||||
match modal_state {
|
||||
ModalState::NewPlate(_) => show_new_plate_modal(ctx, modal_state),
|
||||
ModalState::EditPlate(_) => show_edit_plate_modal(ctx, modal_state),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
@ -64,7 +50,6 @@ fn show_new_plate_modal(ctx: &egui::Context, modal_state: &mut ModalState) {
|
|||
.order(egui::Order::Foreground)
|
||||
.collapsible(false)
|
||||
.resizable(false)
|
||||
.open(&mut state.window_open)
|
||||
.show(ctx, |ui| {
|
||||
ui.vertical(|ui| {
|
||||
ui.add(egui::TextEdit::singleline(&mut state.name).hint_text("Plate Name"));
|
||||
|
@ -102,134 +87,21 @@ fn show_new_plate_modal(ctx: &egui::Context, modal_state: &mut ModalState) {
|
|||
);
|
||||
});
|
||||
if ui.button("Add").clicked() {
|
||||
output = Some(plate_tool_lib::plate_instances::PlateInstance::new(
|
||||
state.plate_type,
|
||||
state.plate_format,
|
||||
state.name.clone(),
|
||||
));
|
||||
output = Some(plate_tool_lib::plate_instances::PlateInstance::new(state.plate_type, state.plate_format, state.name.clone()));
|
||||
}
|
||||
});
|
||||
});
|
||||
if state.window_open == false {
|
||||
*modal_state = ModalState::NewPlateComplete(NewPlateModalComplete(None));
|
||||
return;
|
||||
}
|
||||
if output.is_some() {
|
||||
*modal_state = ModalState::NewPlateComplete(NewPlateModalComplete(output));
|
||||
}
|
||||
}
|
||||
pub fn open_new_plate_modal(modal_state: &mut ModalState) {
|
||||
|
||||
pub fn open_new_plate_modal(
|
||||
ctx: &egui::Context,
|
||||
modal_state: &mut ModalState,
|
||||
) {
|
||||
// Do not close another modal
|
||||
if matches!(modal_state, ModalState::None) {
|
||||
*modal_state = ModalState::NewPlate(NewPlateModalState::default());
|
||||
}
|
||||
}
|
||||
|
||||
#[non_exhaustive]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct EditPlateModalState {
|
||||
pub name: String,
|
||||
pub plate_type: plate_tool_lib::plate::PlateType,
|
||||
pub plate_format: plate_tool_lib::plate::PlateFormat,
|
||||
pub id: plate_tool_lib::uuid::Uuid,
|
||||
window_open: bool,
|
||||
}
|
||||
impl EditPlateModalState {
|
||||
fn new(
|
||||
name: &str,
|
||||
plate_type: plate_tool_lib::plate::PlateType,
|
||||
plate_format: plate_tool_lib::plate::PlateFormat,
|
||||
id: plate_tool_lib::uuid::Uuid,
|
||||
) -> Self {
|
||||
Self {
|
||||
name: name.to_owned(),
|
||||
plate_type,
|
||||
plate_format,
|
||||
id,
|
||||
window_open: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
#[non_exhaustive]
|
||||
#[derive(Debug)]
|
||||
pub struct EditPlateModalStateComplete(pub Option<EditPlateModalState>);
|
||||
|
||||
fn show_edit_plate_modal(ctx: &egui::Context, modal_state: &mut ModalState) {
|
||||
let state: &mut EditPlateModalState = {
|
||||
if let ModalState::EditPlate(x) = modal_state {
|
||||
x
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let mut should_complete: bool = false;
|
||||
egui::Window::new("Edit Plate")
|
||||
.order(egui::Order::Foreground)
|
||||
.collapsible(false)
|
||||
.resizable(false)
|
||||
.open(&mut state.window_open)
|
||||
.show(ctx, |ui| {
|
||||
ui.vertical(|ui| {
|
||||
ui.add(egui::TextEdit::singleline(&mut state.name).hint_text("Plate Name"));
|
||||
egui::ComboBox::from_label("Plate Format")
|
||||
.selected_text(format!("{:?}", state.plate_format))
|
||||
.show_ui(ui, |ui| {
|
||||
ui.selectable_value(
|
||||
&mut state.plate_format,
|
||||
plate_tool_lib::plate::PlateFormat::W96,
|
||||
"96W",
|
||||
);
|
||||
ui.selectable_value(
|
||||
&mut state.plate_format,
|
||||
plate_tool_lib::plate::PlateFormat::W384,
|
||||
"384W",
|
||||
);
|
||||
ui.selectable_value(
|
||||
&mut state.plate_format,
|
||||
plate_tool_lib::plate::PlateFormat::W1536,
|
||||
"1536W",
|
||||
);
|
||||
});
|
||||
if ui.button("Save").clicked() {
|
||||
should_complete = true;
|
||||
}
|
||||
});
|
||||
});
|
||||
if state.window_open == false {
|
||||
*modal_state = ModalState::EditPlateComplete(EditPlateModalStateComplete(None));
|
||||
return;
|
||||
}
|
||||
if should_complete {
|
||||
*modal_state =
|
||||
ModalState::EditPlateComplete(EditPlateModalStateComplete(Some(state.to_owned())));
|
||||
return;
|
||||
}
|
||||
}
|
||||
pub fn open_edit_plate_modal(
|
||||
modal_state: &mut ModalState,
|
||||
name: &str,
|
||||
plate_type: plate_tool_lib::plate::PlateType,
|
||||
plate_format: plate_tool_lib::plate::PlateFormat,
|
||||
id: plate_tool_lib::uuid::Uuid,
|
||||
) {
|
||||
// Do not close another modal
|
||||
if matches!(modal_state, ModalState::None) {
|
||||
*modal_state =
|
||||
ModalState::EditPlate(EditPlateModalState::new(name, plate_type, plate_format, id))
|
||||
}
|
||||
}
|
||||
pub fn open_edit_plate_modal_plateinstance(
|
||||
modal_state: &mut ModalState,
|
||||
plate_instance: &plate_tool_lib::plate_instances::PlateInstance,
|
||||
) {
|
||||
// Do not close another modal
|
||||
if matches!(modal_state, ModalState::None) {
|
||||
*modal_state = ModalState::EditPlate(EditPlateModalState::new(
|
||||
&plate_instance.name,
|
||||
plate_instance.plate.plate_type,
|
||||
plate_instance.plate.plate_format,
|
||||
plate_instance.get_uuid(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
use eframe::egui::{self, pos2, Color32, Rounding};
|
||||
use eframe::glow::OFFSET;
|
||||
use plate_tool_lib::plate::PlateFormat;
|
||||
use plate_tool_lib::transfer_region::Region;
|
||||
use plate_tool_lib::uuid::Uuid;
|
||||
|
@ -13,13 +12,13 @@ const PALETTE: plate_tool_lib::util::ColorPalette = plate_tool_lib::util::Palett
|
|||
|
||||
// Stroke types
|
||||
static STROKE_DEFAULT: LazyLock<egui::Stroke> =
|
||||
LazyLock::new(|| egui::Stroke::new(2.0, egui::Color32::from_gray(80)));
|
||||
LazyLock::new(|| egui::Stroke::new(2.0, egui::Color32::from_gray(128)));
|
||||
static STROKE_CURRENT: LazyLock<egui::Stroke> =
|
||||
LazyLock::new(|| egui::Stroke::new(2.0, egui::Color32::from_gray(30)));
|
||||
LazyLock::new(|| egui::Stroke::new(2.0, egui::Color32::from_gray(200)));
|
||||
static STROKE_SELECT: LazyLock<egui::Stroke> =
|
||||
LazyLock::new(|| egui::Stroke::new(3.0, egui::Color32::from_gray(30)));
|
||||
LazyLock::new(|| egui::Stroke::new(3.0, egui::Color32::from_gray(200)));
|
||||
static STROKE_HOVER: LazyLock<egui::Stroke> =
|
||||
LazyLock::new(|| egui::Stroke::new(3.0, egui::Color32::from_gray(0)));
|
||||
LazyLock::new(|| egui::Stroke::new(3.0, egui::Color32::from_gray(255)));
|
||||
|
||||
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
|
||||
pub struct PlateUiState {
|
||||
|
@ -38,34 +37,11 @@ impl Default for PlateUiState {
|
|||
struct WellInfo {
|
||||
volume: f32,
|
||||
color: [f64; 3],
|
||||
highlight: bool,
|
||||
fill: bool,
|
||||
}
|
||||
|
||||
impl WellInfo {
|
||||
fn new(volume: f32, color: [f64; 3]) -> Self {
|
||||
WellInfo {
|
||||
volume,
|
||||
color,
|
||||
highlight: false,
|
||||
fill: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, serde::Serialize, serde::Deserialize)]
|
||||
pub struct PlateDisplayOptions {
|
||||
pub show_transfer_hashes: bool,
|
||||
pub show_volume_heatmap: bool,
|
||||
pub show_coordinates: bool,
|
||||
}
|
||||
impl Default for PlateDisplayOptions {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
show_transfer_hashes: true,
|
||||
show_volume_heatmap: false,
|
||||
show_coordinates: true,
|
||||
}
|
||||
WellInfo { volume, color }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -153,66 +129,39 @@ fn calculate_shading_for_wells(
|
|||
plate_type: plate_tool_lib::plate::PlateType,
|
||||
ordered_ids: &[Uuid],
|
||||
cache: &plate_tool_lib::transfer_region_cache::TransferRegionCache,
|
||||
display_options: PlateDisplayOptions,
|
||||
) -> Box<[Option<WellInfo>]> {
|
||||
let box_size: usize = rows as usize * columns as usize;
|
||||
let mut well_infos: Box<[Option<WellInfo>]> = vec![None; box_size].into_boxed_slice();
|
||||
|
||||
if let Some(transfers) = transfers {
|
||||
// Needed for palette
|
||||
let max_volume: f32 = transfers
|
||||
.iter()
|
||||
.flat_map(|v| match v.volume {
|
||||
plate_tool_lib::transfer_volume::TransferVolume::Single(x) => Some(x),
|
||||
_ => None,
|
||||
})
|
||||
.fold(f32::MIN, f32::max)
|
||||
.max(1.0f32); // Otherwise f32::MIN is return value
|
||||
|
||||
for transfer in transfers {
|
||||
let cache_result = match plate_type {
|
||||
plate_tool_lib::plate::PlateType::Source => cache.get_or_calculate_source(transfer),
|
||||
plate_tool_lib::plate::PlateType::Destination => {
|
||||
cache.get_or_calculate_destination(transfer)
|
||||
}
|
||||
};
|
||||
let volume = if let plate_tool_lib::transfer_volume::TransferVolume::Single(x) =
|
||||
transfer.volume
|
||||
{
|
||||
x
|
||||
} else {
|
||||
0.0
|
||||
};
|
||||
if let Some(wells) = cache_result {
|
||||
for well in wells.iter().filter(|x| x.row <= rows && x.col <= columns) {
|
||||
if let Some(Some(mut x)) = well_infos.get_mut(
|
||||
for transfer in transfers {
|
||||
let cache_result = match plate_type {
|
||||
plate_tool_lib::plate::PlateType::Source => cache.get_or_calculate_source(transfer),
|
||||
plate_tool_lib::plate::PlateType::Destination => {
|
||||
cache.get_or_calculate_destination(transfer)
|
||||
}
|
||||
};
|
||||
if let Some(wells) = cache_result {
|
||||
for well in wells.iter().filter(|x| x.row <= rows && x.col <= columns) {
|
||||
if let Some(Some(mut x)) = well_infos
|
||||
.get_mut((well.row - 1) as usize * columns as usize + (well.col - 1) as usize)
|
||||
{
|
||||
x.volume += 5.0;
|
||||
x.color = PALETTE.get_ordered(transfer.id, ordered_ids);
|
||||
} else {
|
||||
if let Some(mut wi) = well_infos.get_mut(
|
||||
(well.row - 1) as usize * columns as usize + (well.col - 1) as usize,
|
||||
) {
|
||||
x.volume += volume;
|
||||
|
||||
x.color = if display_options.show_volume_heatmap {
|
||||
PALETTE.get_linear(volume.into(), max_volume.into())
|
||||
} else {
|
||||
PALETTE.get_ordered(transfer.id, ordered_ids)
|
||||
};
|
||||
} else {
|
||||
if let Some(mut wi) = well_infos.get_mut(
|
||||
(well.row - 1) as usize * columns as usize + (well.col - 1) as usize,
|
||||
) {
|
||||
*wi = Some(WellInfo::new(
|
||||
volume,
|
||||
if display_options.show_volume_heatmap {
|
||||
PALETTE.get_linear(volume.into(), max_volume.into())
|
||||
} else {
|
||||
PALETTE.get_ordered(transfer.id, ordered_ids)
|
||||
},
|
||||
));
|
||||
}
|
||||
*wi = Some(WellInfo::new(
|
||||
5.0,
|
||||
PALETTE.get_ordered(transfer.id, ordered_ids),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
well_infos
|
||||
}
|
||||
|
@ -224,20 +173,6 @@ fn f64_to_color32(x: [f64; 3]) -> Color32 {
|
|||
Color32::from_rgb(r, g, b)
|
||||
}
|
||||
|
||||
fn draw_cross(painter: &egui::Painter, center: egui::Pos2, radius: f32, stroke: egui::Stroke) {
|
||||
// Generate points on circle
|
||||
const OFFSET_ARRAY_X: [f32; 4] = [0.71, -0.71, -0.71, 0.71]; // == sin(2pi/8) == cos(2pi/8)
|
||||
const OFFSET_ARRAY_Y: [f32; 4] = [0.71, 0.71, -0.71, -0.71];
|
||||
let radius_adjusted_array_x: [f32; 4] = core::array::from_fn(|x| OFFSET_ARRAY_X[x] * radius);
|
||||
let radius_adjusted_array_y: [f32; 4] = core::array::from_fn(|y| OFFSET_ARRAY_Y[y] * radius);
|
||||
let xs: [f32; 4] = core::array::from_fn(|x| radius_adjusted_array_x[x] + center.x);
|
||||
let ys: [f32; 4] = core::array::from_fn(|y| radius_adjusted_array_y[y] + center.y);
|
||||
let pts: [egui::Pos2; 4] = core::array::from_fn(|i| egui::Pos2::new(xs[i], ys[i]));
|
||||
|
||||
painter.line_segment([pts[0], pts[2]], stroke);
|
||||
painter.line_segment([pts[1], pts[3]], stroke);
|
||||
}
|
||||
|
||||
fn add_plate_sub(
|
||||
size: egui::Vec2,
|
||||
rows: u8,
|
||||
|
@ -249,7 +184,6 @@ fn add_plate_sub(
|
|||
current_transfer_state: Option<&CurrentTransferState>,
|
||||
ui: &mut egui::Ui,
|
||||
state: &mut PlateUiState,
|
||||
display_options: PlateDisplayOptions,
|
||||
) {
|
||||
let (response, painter) = ui.allocate_painter(size, egui::Sense::click_and_drag());
|
||||
|
||||
|
@ -326,7 +260,7 @@ fn add_plate_sub(
|
|||
let well_infos = {
|
||||
// Get non-active transfer info
|
||||
let mut well_infos =
|
||||
calculate_shading_for_wells(rows, columns, transfers, plate_type, ordered_ids, cache, display_options);
|
||||
calculate_shading_for_wells(rows, columns, transfers, plate_type, ordered_ids, cache);
|
||||
|
||||
// Get wells in the current transfer to tack on to well_infos separately
|
||||
let current_transfer_wells: Option<Box<[(usize, usize)]>> = {
|
||||
|
@ -354,14 +288,10 @@ fn add_plate_sub(
|
|||
.and_then(|x| x.lock().ok())
|
||||
.map(|x| x.volume)
|
||||
.unwrap_or(0.0);
|
||||
let color = well_info.map(|x| x.color).unwrap_or([255.0, 255.0, 255.0]);
|
||||
let fill = well_info.map(|x| x.color).is_some();
|
||||
|
||||
*well_info = Some(WellInfo {
|
||||
color,
|
||||
color: [255.0, 255.0, 255.0],
|
||||
volume: 1.0,
|
||||
fill,
|
||||
highlight: true,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -397,12 +327,7 @@ fn add_plate_sub(
|
|||
if let Some(well_info) =
|
||||
well_infos[(c_row - 1) as usize * columns as usize + (c_column - 1) as usize]
|
||||
{
|
||||
if well_info.fill {
|
||||
painter.circle_filled(center, radius * 0.80, f64_to_color32(well_info.color));
|
||||
}
|
||||
if well_info.highlight && display_options.show_transfer_hashes {
|
||||
draw_cross(&painter, center, radius * 0.80, *STROKE_CURRENT);
|
||||
}
|
||||
painter.circle_filled(center, radius * 0.80, f64_to_color32(well_info.color));
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -441,19 +366,7 @@ fn add_plate_sub(
|
|||
}
|
||||
|
||||
// Draw row/column labels
|
||||
let default_font = egui::FontId::monospace(f32::min(radius, 14.0));
|
||||
static DEFAULT_TEXT_COLOR: LazyLock<egui::Color32> =
|
||||
LazyLock::new(|| egui::Color32::from_gray(128));
|
||||
static HIGHLIGHT_TEXT_COLOR: LazyLock<egui::Color32> =
|
||||
LazyLock::new(|| egui::Color32::from_gray(0));
|
||||
for c_row in 0..rows {
|
||||
let text_color = {
|
||||
if display_options.show_coordinates && hovered_well.is_some_and(|x| x.0 == c_row + 1) {
|
||||
*HIGHLIGHT_TEXT_COLOR
|
||||
} else {
|
||||
*DEFAULT_TEXT_COLOR
|
||||
}
|
||||
};
|
||||
painter.text(
|
||||
egui::pos2(
|
||||
start_x - 10.0,
|
||||
|
@ -461,19 +374,11 @@ fn add_plate_sub(
|
|||
),
|
||||
egui::Align2::CENTER_CENTER,
|
||||
(c_row + 1).to_string(),
|
||||
default_font.clone(),
|
||||
text_color,
|
||||
egui::FontId::monospace(f32::min(radius, 14.0)),
|
||||
egui::Color32::from_gray(128),
|
||||
);
|
||||
}
|
||||
for c_column in 0..columns {
|
||||
let text_color = {
|
||||
if display_options.show_coordinates && hovered_well.is_some_and(|x| x.1 == c_column + 1)
|
||||
{
|
||||
*HIGHLIGHT_TEXT_COLOR
|
||||
} else {
|
||||
*DEFAULT_TEXT_COLOR
|
||||
}
|
||||
};
|
||||
painter.text(
|
||||
egui::pos2(
|
||||
start_x + radius + 2.0 * radius * c_column as f32,
|
||||
|
@ -481,8 +386,8 @@ fn add_plate_sub(
|
|||
),
|
||||
egui::Align2::CENTER_CENTER,
|
||||
plate_tool_lib::util::num_to_letters(c_column + 1).unwrap(),
|
||||
default_font.clone(),
|
||||
text_color,
|
||||
egui::FontId::monospace(f32::min(radius, 14.0)),
|
||||
egui::Color32::from_gray(128),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -497,7 +402,6 @@ pub fn add_plate(
|
|||
current_transfer_state: Option<&CurrentTransferState>,
|
||||
ui: &mut egui::Ui,
|
||||
state: &mut PlateUiState,
|
||||
display_options: PlateDisplayOptions,
|
||||
) {
|
||||
add_plate_sub(
|
||||
size,
|
||||
|
@ -510,6 +414,5 @@ pub fn add_plate(
|
|||
current_transfer_state,
|
||||
ui,
|
||||
state,
|
||||
display_options,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,135 +0,0 @@
|
|||
use std::sync::LazyLock;
|
||||
|
||||
use eframe::egui::{
|
||||
self,
|
||||
style::{Selection, Visuals, WidgetVisuals, Widgets},
|
||||
Color32, Stroke,
|
||||
};
|
||||
|
||||
pub fn set_visuals(ctx: &egui::Context) {
|
||||
let current = ctx.style().visuals.clone();
|
||||
let visuals = Visuals {
|
||||
override_text_color: Some(STANDARD_THEME.text),
|
||||
faint_bg_color: STANDARD_THEME.surface0,
|
||||
extreme_bg_color: STANDARD_THEME.surface0,
|
||||
window_fill: STANDARD_THEME.base,
|
||||
panel_fill: STANDARD_THEME.base,
|
||||
window_stroke: Stroke {
|
||||
color: STANDARD_THEME.overlay1,
|
||||
..current.window_stroke
|
||||
},
|
||||
widgets: Widgets {
|
||||
noninteractive: make_widget_visual(
|
||||
current.widgets.noninteractive,
|
||||
STANDARD_THEME.base,
|
||||
&STANDARD_THEME,
|
||||
),
|
||||
inactive: make_widget_visual(
|
||||
current.widgets.inactive,
|
||||
STANDARD_THEME.surface0,
|
||||
&STANDARD_THEME,
|
||||
),
|
||||
hovered: make_widget_visual(
|
||||
current.widgets.hovered,
|
||||
STANDARD_THEME.light_purple,
|
||||
&STANDARD_THEME,
|
||||
),
|
||||
active: make_widget_visual(
|
||||
current.widgets.active,
|
||||
STANDARD_THEME.surface1,
|
||||
&STANDARD_THEME,
|
||||
),
|
||||
open: make_widget_visual(
|
||||
current.widgets.open,
|
||||
STANDARD_THEME.surface0,
|
||||
&STANDARD_THEME,
|
||||
),
|
||||
},
|
||||
selection: Selection {
|
||||
bg_fill: STANDARD_THEME.purple,
|
||||
stroke: Stroke {
|
||||
color: STANDARD_THEME.overlay1,
|
||||
..current.selection.stroke
|
||||
},
|
||||
},
|
||||
..current
|
||||
};
|
||||
ctx.set_visuals(visuals);
|
||||
}
|
||||
fn make_widget_visual(current: WidgetVisuals, bg: Color32, theme: &Theme) -> WidgetVisuals {
|
||||
WidgetVisuals {
|
||||
bg_fill: bg,
|
||||
weak_bg_fill: bg,
|
||||
bg_stroke: Stroke {
|
||||
color: theme.overlay1,
|
||||
..current.bg_stroke
|
||||
},
|
||||
fg_stroke: Stroke {
|
||||
color: theme.text,
|
||||
..current.fg_stroke
|
||||
},
|
||||
..current
|
||||
}
|
||||
}
|
||||
|
||||
pub static STANDARD_THEME: LazyLock<Theme> = LazyLock::new(|| {
|
||||
Theme::standard()
|
||||
});
|
||||
#[derive(Debug)]
|
||||
pub struct Theme {
|
||||
pub base: Color32,
|
||||
pub surface0: Color32,
|
||||
pub surface1: Color32,
|
||||
pub surface2: Color32,
|
||||
pub overlay0: Color32,
|
||||
pub overlay1: Color32,
|
||||
pub overlay2: Color32,
|
||||
pub text: Color32,
|
||||
pub purple: Color32,
|
||||
pub light_purple: Color32,
|
||||
}
|
||||
impl Theme {
|
||||
fn standard() -> Self {
|
||||
const BASE_HUE: f32 = 45.0;
|
||||
const BASE_SATURATION: f32 = 40.0;
|
||||
Self {
|
||||
base: hsl_to_color32(BASE_HUE, BASE_SATURATION, 88.0),
|
||||
surface0: hsl_to_color32(BASE_HUE, BASE_SATURATION, 80.0),
|
||||
surface1: hsl_to_color32(BASE_HUE, BASE_SATURATION, 75.0),
|
||||
surface2: hsl_to_color32(BASE_HUE, BASE_SATURATION, 65.0),
|
||||
overlay0: hsl_to_color32(BASE_HUE, BASE_SATURATION, 60.0),
|
||||
overlay1: hsl_to_color32(BASE_HUE, BASE_SATURATION, 55.0),
|
||||
overlay2: hsl_to_color32(BASE_HUE, BASE_SATURATION, 50.0),
|
||||
text: hsl_to_color32(BASE_HUE, BASE_SATURATION, 25.0),
|
||||
purple: hsl_to_color32(270.0, 80.0, 80.0),
|
||||
light_purple: hsl_to_color32(270.0, 70.0, 90.0),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn hsl_to_rgb(h: f32, s: f32, l: f32) -> (u8, u8, u8) {
|
||||
let s = s / 100.0;
|
||||
let l = l / 100.0;
|
||||
let chroma = (1.0 - f32::abs(2.0 * l - 1.0)) * s;
|
||||
let h_prime = h / 60.0;
|
||||
let x = chroma * (1.0 - f32::abs((h_prime % 2.0) - 1.0));
|
||||
|
||||
let (r1, g1, b1) = match h_prime {
|
||||
_ if h_prime < 1.0 => (chroma, x, 0.0),
|
||||
_ if h_prime >= 1.0 && h_prime < 2.0 => (x, chroma, 0.0),
|
||||
_ if h_prime >= 2.0 && h_prime < 3.0 => (0.0, chroma, x),
|
||||
_ if h_prime >= 3.0 && h_prime < 4.0 => (0.0, x, chroma),
|
||||
_ if h_prime >= 4.0 && h_prime < 5.0 => (x, 0.0, chroma),
|
||||
_ if h_prime >= 5.0 && h_prime < 6.0 => (chroma, 0.0, x),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
let m = l - (chroma/2.0);
|
||||
let (r,g,b) = ((r1 + m) * 255.0, (g1 + m) * 255.0, (b1 + m) * 255.0);
|
||||
(r as u8, g as u8, b as u8)
|
||||
}
|
||||
|
||||
fn hsl_to_color32(h: f32, s: f32, l: f32) -> Color32 {
|
||||
let (r, g, b) = hsl_to_rgb(h, s, l);
|
||||
Color32::from_rgb(r, g, b)
|
||||
}
|
|
@ -116,7 +116,7 @@ impl CurrentTransferStateInterior {
|
|||
let volume: f32 = match transfer.volume {
|
||||
plate_tool_lib::transfer_volume::TransferVolume::Single(x) => x,
|
||||
plate_tool_lib::transfer_volume::TransferVolume::WellMap(_) => {
|
||||
log::warn!("COOL BUG: I genuinely don't know when this variant is used and honestly assume that it just never is constructed! Anyway, here's main state:\n{:?}", ms);
|
||||
log::debug!("COOL BUG: I genuinely don't know when this variant is used and honestly assume that it just never is constructed! Anyway, here's main state:\n{:?}", ms);
|
||||
unreachable!("It better not!");
|
||||
}
|
||||
_ => unreachable!(),
|
||||
|
@ -188,7 +188,6 @@ pub fn transfer_menu(
|
|||
main_state: &mut MainState,
|
||||
) {
|
||||
// Can we reduce the length of this lock pls
|
||||
let cts = state;
|
||||
let mut state = state.lock().unwrap();
|
||||
|
||||
ui.horizontal(|ui| {
|
||||
|
@ -290,10 +289,7 @@ pub fn transfer_menu(
|
|||
transfer.name = state.transfer_name.clone();
|
||||
main_state.transfer_region_cache.invalidate(&transfer);
|
||||
}
|
||||
} else { // Need to make a new transfer
|
||||
if state.transfer_name.is_empty() {
|
||||
state.transfer_name = "New Transfer".to_string();
|
||||
}
|
||||
} else {
|
||||
let new_transfer = state.convert_to_transfer(main_state);
|
||||
log::info!("{:?}", new_transfer);
|
||||
if let Some(new_transfer) = new_transfer {
|
||||
|
@ -301,23 +297,12 @@ pub fn transfer_menu(
|
|||
let new_transfer = main_state.transfers.last()
|
||||
.expect("Cannot be empty, just added a transfer");
|
||||
main_state.transfer_region_cache.add_overwrite(new_transfer);
|
||||
main_state.set_current_transfer(new_transfer.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ui.button("New").clicked() {
|
||||
*state = CurrentTransferStateInterior::default();
|
||||
set_plates(main_state, &mut state);
|
||||
main_state.set_no_current_transfer();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn set_plates(ms: &MainState, cts: &mut CurrentTransferStateInterior) {
|
||||
if let Some(source_plate) = ms.get_current_source_plateinstance() {
|
||||
cts.source_plate = source_plate.plate;
|
||||
}
|
||||
if let Some(destination_plate) = ms.get_current_destination_plateinstance() {
|
||||
cts.destination_plate = destination_plate.plate;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,95 +1,41 @@
|
|||
use eframe::egui::{self, text_selection::visuals, NumExt};
|
||||
use eframe::egui;
|
||||
|
||||
use crate::{
|
||||
main_state::MainState,
|
||||
modals::ModalState,
|
||||
transfer_menu::{CurrentTransferState, CurrentTransferStateInterior},
|
||||
};
|
||||
use crate::{main_state::MainState, transfer_menu::{CurrentTransferState, CurrentTransferStateInterior}};
|
||||
|
||||
use std::sync::LazyLock;
|
||||
|
||||
fn tree_label(
|
||||
ui: &mut egui::Ui,
|
||||
ms: &MainState,
|
||||
modal_state: &mut ModalState,
|
||||
name: &str,
|
||||
uuid: plate_tool_lib::uuid::Uuid,
|
||||
selected: bool,
|
||||
) -> (Option<plate_tool_lib::uuid::Uuid>, bool) {
|
||||
let button_padding = ui.spacing().button_padding;
|
||||
let total_extra = button_padding + button_padding;
|
||||
let wrap_width = ui.available_width() - total_extra.x;
|
||||
let galley =
|
||||
egui::WidgetText::from(name).into_galley(ui, None, wrap_width, egui::TextStyle::Button);
|
||||
let desired_size = {
|
||||
let mut desired_size = total_extra + galley.size();
|
||||
desired_size.y = desired_size.y.at_least(ui.spacing().interact_size.y);
|
||||
desired_size
|
||||
};
|
||||
let (rect, response) = ui.allocate_at_least(desired_size, egui::Sense::click());
|
||||
let text_pos = ui
|
||||
.layout()
|
||||
.align_size_within_rect(galley.size(), rect.shrink2(button_padding))
|
||||
.min;
|
||||
let visuals = ui.style().interact_selectable(&response, selected);
|
||||
if selected || response.hovered() {
|
||||
let rect = rect.expand(visuals.expansion);
|
||||
ui.painter().rect(
|
||||
rect,
|
||||
visuals.rounding,
|
||||
visuals.weak_bg_fill,
|
||||
visuals.bg_stroke,
|
||||
);
|
||||
}
|
||||
ui.painter().galley(text_pos, galley, visuals.text_color());
|
||||
static SELECT_COLOR: LazyLock<egui::Color32> =
|
||||
LazyLock::new(|| egui::Color32::from_hex("#aa0000").unwrap());
|
||||
|
||||
if response.clicked() {
|
||||
return (Some(uuid), false);
|
||||
}
|
||||
if response.double_clicked() {
|
||||
return (None, true);
|
||||
}
|
||||
(None, false)
|
||||
}
|
||||
|
||||
pub fn tree(
|
||||
ui: &mut egui::Ui,
|
||||
ms: &mut MainState,
|
||||
cts: &CurrentTransferState,
|
||||
modal_state: &mut ModalState,
|
||||
) {
|
||||
pub fn tree(ui: &mut egui::Ui, ms: &mut MainState, cts: &CurrentTransferState) {
|
||||
// Add all source plates
|
||||
ui.vertical(|ui| {
|
||||
ui.heading("Source Plates");
|
||||
let mut new_uuid: Option<plate_tool_lib::uuid::Uuid> = None;
|
||||
for (name, uuid) in ms.source_plates.iter().map(|x| (&x.name, x.get_uuid())) {
|
||||
let (potential_new_uuid, dbl_clicked) = tree_label(
|
||||
ui,
|
||||
ms,
|
||||
modal_state,
|
||||
name,
|
||||
uuid,
|
||||
ms.get_current_source_uuid().is_some_and(|x| x == uuid),
|
||||
);
|
||||
if potential_new_uuid.is_some() {
|
||||
new_uuid = potential_new_uuid;
|
||||
}
|
||||
if dbl_clicked {
|
||||
let pi = ms.get_source_by_uuid(uuid);
|
||||
if let Some(pi) = pi {
|
||||
crate::modals::open_edit_plate_modal_plateinstance(modal_state, &pi);
|
||||
let f = {
|
||||
let mut f = egui::Frame::none();
|
||||
if ms.get_current_source_uuid().is_some_and(|x| x == uuid) {
|
||||
f = f.fill(*SELECT_COLOR);
|
||||
}
|
||||
}
|
||||
f
|
||||
};
|
||||
f.show(ui, |ui| {
|
||||
let r = ui.add(
|
||||
egui::Label::new(name)
|
||||
.sense(egui::Sense::click())
|
||||
.selectable(false),
|
||||
);
|
||||
if r.clicked() {
|
||||
new_uuid = Some(uuid);
|
||||
}
|
||||
});
|
||||
}
|
||||
if let Some(uuid) = new_uuid {
|
||||
let current_source_uuid = ms.get_current_source_uuid();
|
||||
if current_source_uuid.is_some_and(|x| x != uuid) || current_source_uuid.is_none() {
|
||||
ms.set_current_source(uuid);
|
||||
ms.set_no_current_transfer();
|
||||
if let Some(mut cts) = cts.lock().ok() {
|
||||
*cts = CurrentTransferStateInterior::default();
|
||||
}
|
||||
set_plates(ms, cts);
|
||||
ms.set_current_source(uuid);
|
||||
ms.set_no_current_transfer();
|
||||
if let Some(mut cts) = cts.lock().ok() {
|
||||
*cts = CurrentTransferStateInterior::default();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -103,44 +49,29 @@ pub fn tree(
|
|||
.iter()
|
||||
.map(|x| (&x.name, x.get_uuid()))
|
||||
{
|
||||
let (potential_new_uuid, dbl_clicked) = tree_label(
|
||||
ui,
|
||||
ms,
|
||||
modal_state,
|
||||
name,
|
||||
uuid,
|
||||
ms.get_current_destination_uuid().is_some_and(|x| x == uuid),
|
||||
);
|
||||
if potential_new_uuid.is_some() {
|
||||
new_uuid = potential_new_uuid;
|
||||
}
|
||||
if dbl_clicked {
|
||||
let pi = ms.get_destination_by_uuid(uuid);
|
||||
if let Some(pi) = pi {
|
||||
crate::modals::open_edit_plate_modal_plateinstance(modal_state, &pi);
|
||||
let f = {
|
||||
let mut f = egui::Frame::none();
|
||||
if ms.get_current_destination_uuid().is_some_and(|x| x == uuid) {
|
||||
f = f.fill(*SELECT_COLOR);
|
||||
}
|
||||
}
|
||||
f
|
||||
};
|
||||
f.show(ui, |ui| {
|
||||
let r = ui.add(
|
||||
egui::Label::new(name)
|
||||
.sense(egui::Sense::click())
|
||||
.selectable(false),
|
||||
);
|
||||
if r.clicked() {
|
||||
new_uuid = Some(uuid);
|
||||
}
|
||||
});
|
||||
}
|
||||
if let Some(uuid) = new_uuid {
|
||||
let current_destination_uuid = ms.get_current_destination_uuid();
|
||||
if current_destination_uuid.is_some_and(|x| x != uuid)
|
||||
|| current_destination_uuid.is_none()
|
||||
{
|
||||
ms.set_current_destination(uuid);
|
||||
ms.set_no_current_transfer();
|
||||
if let Some(mut cts) = cts.lock().ok() {
|
||||
*cts = CurrentTransferStateInterior::default();
|
||||
cts.destination_plate = ms
|
||||
.get_current_destination_plateinstance()
|
||||
.expect("Just set destination")
|
||||
.plate;
|
||||
}
|
||||
set_plates(ms, cts);
|
||||
log::warn!(
|
||||
"{:?}\n{:?}",
|
||||
cts,
|
||||
ms.get_current_destination_plateinstance()
|
||||
);
|
||||
ms.set_current_destination(uuid);
|
||||
ms.set_no_current_transfer();
|
||||
if let Some(mut cts) = cts.lock().ok() {
|
||||
*cts = CurrentTransferStateInterior::default();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -149,37 +80,30 @@ pub fn tree(
|
|||
ui.heading("Transfers");
|
||||
let mut new_uuid: Option<plate_tool_lib::uuid::Uuid> = None;
|
||||
for (name, uuid) in ms.transfers.iter().map(|x| (&x.name, x.get_uuid())) {
|
||||
let (potential_new_uuid, _) = tree_label(
|
||||
ui,
|
||||
ms,
|
||||
modal_state,
|
||||
name,
|
||||
uuid,
|
||||
ms.get_current_transfer_uuid().is_some_and(|x| x == uuid),
|
||||
);
|
||||
if potential_new_uuid.is_some() {
|
||||
new_uuid = potential_new_uuid;
|
||||
}
|
||||
let f = {
|
||||
let mut f = egui::Frame::none();
|
||||
if ms.get_current_transfer_uuid().is_some_and(|x| x == uuid) {
|
||||
f = f.fill(*SELECT_COLOR);
|
||||
}
|
||||
f
|
||||
};
|
||||
f.show(ui, |ui| {
|
||||
let r = ui.add(
|
||||
egui::Label::new(name)
|
||||
.sense(egui::Sense::click())
|
||||
.selectable(false),
|
||||
);
|
||||
if r.clicked() {
|
||||
new_uuid = Some(uuid);
|
||||
log::info!("{:?}", uuid);
|
||||
}
|
||||
});
|
||||
}
|
||||
if let Some(uuid) = new_uuid {
|
||||
ms.set_current_transfer(uuid);
|
||||
if let Some(new_cts) =
|
||||
CurrentTransferStateInterior::try_new_from_main_state_transfer(ms)
|
||||
{
|
||||
if let Some(new_cts) = CurrentTransferStateInterior::try_new_from_main_state_transfer(ms) {
|
||||
*cts.lock().unwrap() = new_cts;
|
||||
}
|
||||
set_plates(ms, cts);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn set_plates(ms: &MainState, cts: &CurrentTransferState) {
|
||||
if let Some(mut cts) = cts.lock().ok() {
|
||||
if let Some(source_plate) = ms.get_current_source_plateinstance() {
|
||||
cts.source_plate = source_plate.plate;
|
||||
}
|
||||
if let Some(destination_plate) = ms.get_current_destination_plateinstance() {
|
||||
cts.destination_plate = destination_plate.plate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -101,7 +101,7 @@ impl Region {
|
|||
|
||||
log::info!("{:?}", input);
|
||||
if let Some(captures) = RECT_REGEX.captures(input) {
|
||||
if let (Some(col1), Some(row1), Some(col2), Some(row2)) = (
|
||||
if let (Some(row1), Some(col1), Some(row2), Some(col2)) = (
|
||||
crate::util::letters_to_num(&captures[1]),
|
||||
captures[2].parse::<u8>().ok(),
|
||||
crate::util::letters_to_num(&captures[3]),
|
||||
|
@ -121,7 +121,7 @@ impl Region {
|
|||
return None;
|
||||
}
|
||||
} else if let Some(captures) = POINT_REGEX.captures(input) {
|
||||
if let (Some(col), Some(row)) = (
|
||||
if let (Some(row), Some(col)) = (
|
||||
crate::util::letters_to_num(&captures[1]),
|
||||
captures[2].parse::<u8>().ok(),
|
||||
) {
|
||||
|
@ -457,10 +457,11 @@ impl TransferRegion {
|
|||
}
|
||||
// Sufficient to check if the corners are in-bounds
|
||||
let source_max = self.source_plate.size();
|
||||
if (s1.row > source_max.0 || s2.row > source_max.0) && il_dest.0 != 0 {
|
||||
if s1.row > source_max.0 || s2.row > source_max.0 {
|
||||
return Err("Source region is out-of-bounds! (Too tall)");
|
||||
}
|
||||
if (s1.col > source_max.1 || s2.col > source_max.1) && il_dest.1 != 0 {
|
||||
if s1.col > source_max.1 || s2.col > source_max.1 {
|
||||
// log::debug!("s1.1: {}, max.1: {}", s1.1, source_max.1);
|
||||
return Err("Source region is out-of-bounds! (Too wide)");
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue