diff --git a/src/ui/panes/valve_control.rs b/src/ui/panes/valve_control.rs index e42c2012c02f7c8f0a72677cf7f37697c0cf1911..91cf456b7b82d0f36b8561b6d2bdb627a168e6f7 100644 --- a/src/ui/panes/valve_control.rs +++ b/src/ui/panes/valve_control.rs @@ -5,8 +5,8 @@ mod valves; use std::time::{Duration, Instant}; use egui::{ - Color32, DragValue, Frame, Grid, Label, Layout, Rect, RichText, Sense, Stroke, Ui, UiBuilder, - Vec2, Widget, vec2, + Color32, DragValue, FontId, Frame, Grid, Label, Layout, Rect, Response, RichText, Sense, + Stroke, Ui, UiBuilder, Vec2, Widget, vec2, }; use egui_extras::{Size, StripBuilder}; use itertools::Itertools; @@ -145,14 +145,14 @@ impl PaneBehavior for ValveControlPane { impl ValveControlPane { fn pane_ui(&mut self) -> impl FnOnce(&mut Ui) { |ui| { - let valve_chunks = Valve::iter().chunks(3); + let valve_chunks = Valve::iter().enumerate().chunks(3); Grid::new("valves_grid") .num_columns(3) .spacing(Vec2::splat(5.)) .show(ui, |ui| { for chunk in &valve_chunks { - for valve in chunk { - ui.scope(self.valve_frame_ui(valve)); + for (i, valve) in chunk { + ui.scope(self.valve_frame_ui(valve, i as u8)); } ui.end_row(); } @@ -198,7 +198,7 @@ impl ValveControlPane { } } - fn valve_frame_ui(&self, valve: Valve) -> impl FnOnce(&mut Ui) { + fn valve_frame_ui(&self, valve: Valve, number: u8) -> impl FnOnce(&mut Ui) { move |ui| { let valve_str = valve.to_string(); let timing = self.valves_state.get_timing_for(valve); @@ -222,45 +222,89 @@ impl ValveControlPane { format!("ERROR: {}", err_id) } }; + let text_color = ui.visuals().text_color(); + + let valve_title_ui = |ui: &mut Ui| { + Label::new( + RichText::new(valve_str.to_ascii_uppercase()) + .color(text_color) + .size(16.0), + ) + .selectable(false) + .ui(ui); + }; - let inside_frame = |ui: &mut Ui| { - let text_color = ui.visuals().text_color(); - let icon_size = Vec2::splat(17.); + fn big_number_ui( + response: &Response, + number: u8, + text_color: Color32, + ) -> impl Fn(&mut Ui) { + move |ui: &mut Ui| { + let visuals = ui.style().interact(response); + let number = RichText::new(number.to_string()) + .color(text_color) + .font(FontId::monospace(25.)); + + let fill_color = if response.hovered() { + visuals.bg_fill.gamma_multiply(0.8).to_opaque() + } else { + visuals.bg_fill + }; + + Frame::canvas(ui.style()) + .fill(fill_color) + .stroke(Stroke::NONE) + .inner_margin(ui.spacing().menu_margin) + .corner_radius(visuals.corner_radius) + .show(ui, |ui| { + Label::new(number).selectable(false).ui(ui); + }); + } + } - StripBuilder::new(ui) - .sizes(Size::exact(20.), 2) - .vertical(|mut strip| { - strip.cell(|ui| { - Label::new( - RichText::new(valve_str.to_ascii_uppercase()) - .color(text_color) - .size(16.0), - ) + let labels_ui = |ui: &mut Ui| { + let icon_size = Vec2::splat(17.); + ui.vertical(|ui| { + ui.horizontal(|ui| { + let rect = Rect::from_min_size(ui.cursor().min, icon_size); + Icon::Timing.paint(ui, rect); + ui.allocate_rect(rect, Sense::hover()); + Label::new(format!("Timing: {}", timing_str)) .selectable(false) .ui(ui); - }); - strip.cell(|ui| { - ui.vertical(|ui| { - ui.horizontal(|ui| { - let rect = Rect::from_min_size(ui.cursor().min, icon_size); - Icon::Timing.paint(ui, rect); - ui.allocate_rect(rect, Sense::hover()); - Label::new(format!("Timing: {}", timing_str)) - .selectable(false) - .ui(ui); - }); + }); + ui.horizontal(|ui| { + let rect = Rect::from_min_size(ui.cursor().min, icon_size); + Icon::Aperture.paint(ui, rect); + ui.allocate_rect(rect, Sense::hover()); + Label::new(format!("Aperture: {}", aperture_str)) + .selectable(false) + .ui(ui); + }); + }); + }; + + fn inside_frame( + response: &Response, + valve_title_ui: impl Fn(&mut Ui), + number: &u8, + text_color: &Color32, + labels_ui: &impl Fn(&mut Ui), + ) -> impl FnOnce(&mut Ui) { + |ui: &mut Ui| { + StripBuilder::new(ui) + .sizes(Size::exact(20.), 2) + .vertical(|mut strip| { + strip.cell(valve_title_ui); + strip.cell(|ui| { ui.horizontal(|ui| { - let rect = Rect::from_min_size(ui.cursor().min, icon_size); - Icon::Aperture.paint(ui, rect); - ui.allocate_rect(rect, Sense::hover()); - Label::new(format!("Aperture: {}", aperture_str)) - .selectable(false) - .ui(ui); + big_number_ui(response, *number, *text_color)(ui); + labels_ui(ui); }); }); }); - }); - }; + } + } ui.scope_builder( UiBuilder::new() @@ -283,7 +327,16 @@ impl ValveControlPane { .stroke(Stroke::NONE) .inner_margin(ui.spacing().menu_margin) .corner_radius(visuals.corner_radius) - .show(ui, inside_frame); + .show( + ui, + inside_frame( + &response, + &valve_title_ui, + &number, + &text_color, + &labels_ui, + ), + ); if response.clicked() { info!("Clicked!");