Add volume and scroll wheel functionality for numeric values

This commit is contained in:
Emilia Allison 2025-11-23 20:22:55 -05:00
parent fb095d644d
commit 5aa29ff836
Signed by: emilia
GPG Key ID: FEC1CE6360EEC9A8
3 changed files with 103 additions and 30 deletions

View File

@ -0,0 +1,37 @@
use eframe::egui;
pub fn drag_value_with_scroll<T>(
ui: &mut egui::Ui,
value: &mut T,
range: std::ops::RangeInclusive<T>,
speed_drag: f64,
speed_scroll: f64,
) -> egui::Response
where
T: egui::emath::Numeric + std::ops::Add<Output = T> + std::fmt::Debug
{
let drag = egui::DragValue::new(value)
.speed(speed_drag)
.range(range.clone());
let response = ui.add(drag);
if response.hovered() {
let scroll_diff = ui.input(|i| i.smooth_scroll_delta.y);
const THRESHOLD: f32 = 10.0;
if scroll_diff > THRESHOLD {
*value = clamp_partial(*value + T::from_f64(speed_scroll), *range.start(), *range.end());
} else if scroll_diff < -THRESHOLD {
*value = clamp_partial(*value + T::from_f64(-speed_scroll), *range.start(), *range.end());
}
}
response
}
fn clamp_partial<T: PartialOrd + Copy + std::fmt::Debug>(val: T, min: T, max: T) -> T {
if val < min { min }
else if val > max { max }
else { val }
}

View File

@ -7,4 +7,5 @@ mod modals;
mod styling; mod styling;
mod file_handling; mod file_handling;
mod upper_menu; mod upper_menu;
mod extra_widgets;
pub use app::PlateToolEframe; pub use app::PlateToolEframe;

View File

@ -3,6 +3,7 @@ use plate_tool_lib::transfer_region::{self, Region, TransferRegion};
use std::hash::{DefaultHasher, Hash, Hasher}; use std::hash::{DefaultHasher, Hash, Hasher};
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use crate::extra_widgets;
use crate::main_state::{self, MainState}; use crate::main_state::{self, MainState};
pub type CurrentTransferState = Arc<Mutex<CurrentTransferStateInterior>>; pub type CurrentTransferState = Arc<Mutex<CurrentTransferStateInterior>>;
@ -140,18 +141,30 @@ impl CurrentTransferStateInterior {
None None
} }
pub fn convert_to_transfer(&self, ms: &MainState) -> Option<plate_tool_lib::transfer::Transfer> { pub fn convert_to_transfer(
&self,
ms: &MainState,
) -> Option<plate_tool_lib::transfer::Transfer> {
let source_plate_uuid = ms.get_current_source_uuid()?; let source_plate_uuid = ms.get_current_source_uuid()?;
let destination_plate_uuid = ms.get_current_destination_uuid()?; let destination_plate_uuid = ms.get_current_destination_uuid()?;
let source_plate_instance = ms.source_plates.iter().find(|x| x.get_uuid() == source_plate_uuid)?; let source_plate_instance = ms
let destination_plate_instance = ms.destination_plates.iter().find(|x| x.get_uuid() == destination_plate_uuid)?; .source_plates
.iter()
.find(|x| x.get_uuid() == source_plate_uuid)?;
let destination_plate_instance = ms
.destination_plates
.iter()
.find(|x| x.get_uuid() == destination_plate_uuid)?;
let transfer = Some(plate_tool_lib::transfer::Transfer::new( let transfer = Some(plate_tool_lib::transfer::Transfer::new(
source_plate_instance.clone(), source_plate_instance.clone(),
destination_plate_instance.clone(), destination_plate_instance.clone(),
self.generate_transfer_region(), self.generate_transfer_region(),
self.transfer_name.clone(), self.transfer_name.clone(),
)); ));
transfer.map(|mut x| {x.volume = plate_tool_lib::transfer_volume::TransferVolume::Single(self.volume); x}) transfer.map(|mut x| {
x.volume = plate_tool_lib::transfer_volume::TransferVolume::Single(self.volume);
x
})
} }
} }
@ -170,7 +183,7 @@ impl Default for TransferMenuState {
} }
} }
impl TransferMenuState { impl TransferMenuState {
fn new_from_cts(cts: &CurrentTransferState) -> Self { fn _new_from_cts(cts: &CurrentTransferState) -> Self {
let cts = cts.lock().unwrap(); let cts = cts.lock().unwrap();
let source_region_string = cts.source_region.to_string(); let source_region_string = cts.source_region.to_string();
let destination_region_string = cts.destination_region.to_string(); let destination_region_string = cts.destination_region.to_string();
@ -188,7 +201,7 @@ pub fn transfer_menu(
main_state: &mut MainState, main_state: &mut MainState,
) { ) {
// Can we reduce the length of this lock pls // Can we reduce the length of this lock pls
let cts = state; let _cts = state;
let mut state = state.lock().unwrap(); let mut state = state.lock().unwrap();
ui.horizontal(|ui| { ui.horizontal(|ui| {
@ -200,6 +213,17 @@ pub fn transfer_menu(
); );
}); });
ui.horizontal(|ui| {
ui.add(egui::Label::new("Volume"));
extra_widgets::drag_value_with_scroll(
ui,
&mut state.volume,
0.0..=f32::INFINITY,
0.5,
1.0,
);
});
ui.horizontal(|ui| { ui.horizontal(|ui| {
ui.add(egui::Label::new("Source Region")); ui.add(egui::Label::new("Source Region"));
let resp = ui.add( let resp = ui.add(
@ -245,18 +269,20 @@ pub fn transfer_menu(
ui.label("Source Interleave"); ui.label("Source Interleave");
ui.horizontal(|ui| { ui.horizontal(|ui| {
ui.label("Row: "); ui.label("Row: ");
ui.add( extra_widgets::drag_value_with_scroll(
egui::DragValue::new(&mut state.source_row_interleave) ui,
.fixed_decimals(0) &mut state.source_row_interleave,
.range(1..=30) 0..=30,
.speed(0.1), 0.1,
1.0,
); );
ui.label("Col: "); ui.label("Col: ");
ui.add( extra_widgets::drag_value_with_scroll(
egui::DragValue::new(&mut state.source_column_interleave) ui,
.fixed_decimals(0) &mut state.source_column_interleave,
.range(1..=30) 0..=30,
.speed(0.1), 0.1,
1.0,
); );
}); });
}); });
@ -265,18 +291,20 @@ pub fn transfer_menu(
ui.label("Destination Interleave"); ui.label("Destination Interleave");
ui.horizontal(|ui| { ui.horizontal(|ui| {
ui.label("Row: "); ui.label("Row: ");
ui.add( extra_widgets::drag_value_with_scroll(
egui::DragValue::new(&mut state.destination_row_interleave) ui,
.fixed_decimals(0) &mut state.destination_row_interleave,
.range(0..=30) 0..=30,
.speed(0.1), 0.1,
1.0,
); );
ui.label("Col: "); ui.label("Col: ");
ui.add( extra_widgets::drag_value_with_scroll(
egui::DragValue::new(&mut state.destination_column_interleave) ui,
.fixed_decimals(0) &mut state.destination_column_interleave,
.range(0..=30) 0..=30,
.speed(0.1), 0.1,
1.0,
); );
}); });
}); });
@ -285,12 +313,17 @@ pub fn transfer_menu(
if ui.button("Save").clicked() { if ui.button("Save").clicked() {
if let Some(transfer_uuid) = main_state.get_current_transfer_uuid() { if let Some(transfer_uuid) = main_state.get_current_transfer_uuid() {
log::info!("should change transfer"); log::info!("should change transfer");
if let Some(mut transfer) = main_state.transfers.iter_mut().find(|x| x.id == transfer_uuid) { if let Some(transfer) = main_state
.transfers
.iter_mut()
.find(|x| x.id == transfer_uuid)
{
transfer.transfer_region = state.generate_transfer_region(); transfer.transfer_region = state.generate_transfer_region();
transfer.name = state.transfer_name.clone(); transfer.name = state.transfer_name.clone();
main_state.transfer_region_cache.invalidate(&transfer); main_state.transfer_region_cache.invalidate(&transfer);
} }
} else { // Need to make a new transfer } else {
// Need to make a new transfer
if state.transfer_name.is_empty() { if state.transfer_name.is_empty() {
state.transfer_name = "New Transfer".to_string(); state.transfer_name = "New Transfer".to_string();
} }
@ -298,8 +331,10 @@ pub fn transfer_menu(
log::info!("{:?}", new_transfer); log::info!("{:?}", new_transfer);
if let Some(new_transfer) = new_transfer { if let Some(new_transfer) = new_transfer {
main_state.transfers.push(new_transfer); main_state.transfers.push(new_transfer);
let new_transfer = main_state.transfers.last() let new_transfer = main_state
.expect("Cannot be empty, just added a transfer"); .transfers
.last()
.expect("Cannot be empty, just added a transfer");
main_state.transfer_region_cache.add_overwrite(new_transfer); main_state.transfer_region_cache.add_overwrite(new_transfer);
main_state.set_current_transfer(new_transfer.id); main_state.set_current_transfer(new_transfer.id);
} }