Display options for plate
This commit is contained in:
		
							parent
							
								
									e6d80ab8a3
								
							
						
					
					
						commit
						418bf4a79e
					
				| 
						 | 
				
			
			@ -5,7 +5,7 @@ use eframe::egui::{self};
 | 
			
		|||
 | 
			
		||||
use crate::main_state::{construct_fake_mainstate, MainState};
 | 
			
		||||
use crate::modals::{self, ModalState};
 | 
			
		||||
use crate::plate::{add_plate, PlateUiState};
 | 
			
		||||
use crate::plate::{add_plate, PlateDisplayOptions, PlateUiState};
 | 
			
		||||
use crate::transfer_menu::{transfer_menu, CurrentTransferState, TransferMenuState};
 | 
			
		||||
use crate::tree::tree;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -13,12 +13,14 @@ use crate::tree::tree;
 | 
			
		|||
#[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(),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -101,9 +103,15 @@ impl eframe::App for PlateToolEframe {
 | 
			
		|||
                });
 | 
			
		||||
                ui.menu_button("Options", |ui| {
 | 
			
		||||
                    ui.menu_button("Styles", |ui| {
 | 
			
		||||
                        if ui.button("Toggle transfer hashes").clicked() {}
 | 
			
		||||
                        if ui.button("Toggle volume heatmap").clicked() {}
 | 
			
		||||
                        if ui.button("Toggle current coordinates view").clicked() {}
 | 
			
		||||
                        if ui.button("Toggle transfer hashes").clicked() {
 | 
			
		||||
                            self.main_window_state.plate_display_options.show_transfer_hashes ^= true;
 | 
			
		||||
                        }
 | 
			
		||||
                        if ui.button("Toggle volume heatmap").clicked() {
 | 
			
		||||
                            self.main_window_state.plate_display_options.show_volume_heatmap ^= true;
 | 
			
		||||
                        }
 | 
			
		||||
                        if ui.button("Toggle current coordinates view").clicked() {
 | 
			
		||||
                            self.main_window_state.plate_display_options.show_coordinates ^= true;
 | 
			
		||||
                        }
 | 
			
		||||
                    });
 | 
			
		||||
                    ui.menu_button("Exports", |ui| {
 | 
			
		||||
                        if ui.button("Change CSV export type").clicked() {}
 | 
			
		||||
| 
						 | 
				
			
			@ -169,6 +177,7 @@ impl eframe::App for PlateToolEframe {
 | 
			
		|||
                        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) =
 | 
			
		||||
| 
						 | 
				
			
			@ -184,6 +193,7 @@ impl eframe::App for PlateToolEframe {
 | 
			
		|||
                        Some(&self.current_transfer_state),
 | 
			
		||||
                        ui,
 | 
			
		||||
                        self.destination_plate_state.lock().unwrap().deref_mut(),
 | 
			
		||||
                        self.main_window_state.plate_display_options,
 | 
			
		||||
                    );
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,5 @@
 | 
			
		|||
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;
 | 
			
		||||
| 
						 | 
				
			
			@ -37,11 +38,34 @@ 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 }
 | 
			
		||||
        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,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -143,9 +167,9 @@ fn calculate_shading_for_wells(
 | 
			
		|||
            };
 | 
			
		||||
            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)
 | 
			
		||||
                {
 | 
			
		||||
                    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 {
 | 
			
		||||
| 
						 | 
				
			
			@ -173,6 +197,20 @@ 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,
 | 
			
		||||
| 
						 | 
				
			
			@ -184,6 +222,7 @@ 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());
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -288,10 +327,14 @@ 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: [255.0, 255.0, 255.0],
 | 
			
		||||
                        color,
 | 
			
		||||
                        volume: 1.0,
 | 
			
		||||
                        fill,
 | 
			
		||||
                        highlight: true,
 | 
			
		||||
                    })
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			@ -327,8 +370,13 @@ 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);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            //
 | 
			
		||||
            // Draw stroke on top
 | 
			
		||||
| 
						 | 
				
			
			@ -366,7 +414,19 @@ 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(255));
 | 
			
		||||
    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,
 | 
			
		||||
| 
						 | 
				
			
			@ -374,11 +434,18 @@ fn add_plate_sub(
 | 
			
		|||
            ),
 | 
			
		||||
            egui::Align2::CENTER_CENTER,
 | 
			
		||||
            (c_row + 1).to_string(),
 | 
			
		||||
            egui::FontId::monospace(f32::min(radius, 14.0)),
 | 
			
		||||
            egui::Color32::from_gray(128),
 | 
			
		||||
            default_font.clone(),
 | 
			
		||||
            text_color,
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
    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,
 | 
			
		||||
| 
						 | 
				
			
			@ -386,8 +453,8 @@ fn add_plate_sub(
 | 
			
		|||
            ),
 | 
			
		||||
            egui::Align2::CENTER_CENTER,
 | 
			
		||||
            plate_tool_lib::util::num_to_letters(c_column + 1).unwrap(),
 | 
			
		||||
            egui::FontId::monospace(f32::min(radius, 14.0)),
 | 
			
		||||
            egui::Color32::from_gray(128),
 | 
			
		||||
            default_font.clone(),
 | 
			
		||||
            text_color,
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -402,6 +469,7 @@ pub fn add_plate(
 | 
			
		|||
    current_transfer_state: Option<&CurrentTransferState>,
 | 
			
		||||
    ui: &mut egui::Ui,
 | 
			
		||||
    state: &mut PlateUiState,
 | 
			
		||||
    display_options: PlateDisplayOptions,
 | 
			
		||||
) {
 | 
			
		||||
    add_plate_sub(
 | 
			
		||||
        size,
 | 
			
		||||
| 
						 | 
				
			
			@ -414,5 +482,6 @@ pub fn add_plate(
 | 
			
		|||
        current_transfer_state,
 | 
			
		||||
        ui,
 | 
			
		||||
        state,
 | 
			
		||||
        display_options,
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue