pretty
This commit is contained in:
parent
7295115506
commit
5e70a17a00
|
@ -79,6 +79,8 @@ impl eframe::App for PlateToolEframe {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update(&mut self, ctx: &eframe::egui::Context, _frame: &mut eframe::Frame) {
|
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::TopBottomPanel::top("top_panel").show(ctx, |ui| {
|
||||||
egui::menu::bar(ui, |ui| {
|
egui::menu::bar(ui, |ui| {
|
||||||
ui.menu_button("File", |ui| {
|
ui.menu_button("File", |ui| {
|
||||||
|
|
|
@ -4,4 +4,5 @@ mod tree;
|
||||||
mod transfer_menu;
|
mod transfer_menu;
|
||||||
mod main_state;
|
mod main_state;
|
||||||
mod modals;
|
mod modals;
|
||||||
|
mod styling;
|
||||||
pub use app::PlateToolEframe;
|
pub use app::PlateToolEframe;
|
||||||
|
|
|
@ -13,13 +13,13 @@ const PALETTE: plate_tool_lib::util::ColorPalette = plate_tool_lib::util::Palett
|
||||||
|
|
||||||
// Stroke types
|
// Stroke types
|
||||||
static STROKE_DEFAULT: LazyLock<egui::Stroke> =
|
static STROKE_DEFAULT: LazyLock<egui::Stroke> =
|
||||||
LazyLock::new(|| egui::Stroke::new(2.0, egui::Color32::from_gray(128)));
|
LazyLock::new(|| egui::Stroke::new(2.0, egui::Color32::from_gray(80)));
|
||||||
static STROKE_CURRENT: LazyLock<egui::Stroke> =
|
static STROKE_CURRENT: LazyLock<egui::Stroke> =
|
||||||
LazyLock::new(|| egui::Stroke::new(2.0, egui::Color32::from_gray(200)));
|
LazyLock::new(|| egui::Stroke::new(2.0, egui::Color32::from_gray(30)));
|
||||||
static STROKE_SELECT: LazyLock<egui::Stroke> =
|
static STROKE_SELECT: LazyLock<egui::Stroke> =
|
||||||
LazyLock::new(|| egui::Stroke::new(3.0, egui::Color32::from_gray(200)));
|
LazyLock::new(|| egui::Stroke::new(3.0, egui::Color32::from_gray(30)));
|
||||||
static STROKE_HOVER: LazyLock<egui::Stroke> =
|
static STROKE_HOVER: LazyLock<egui::Stroke> =
|
||||||
LazyLock::new(|| egui::Stroke::new(3.0, egui::Color32::from_gray(255)));
|
LazyLock::new(|| egui::Stroke::new(3.0, egui::Color32::from_gray(0)));
|
||||||
|
|
||||||
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
|
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
|
||||||
pub struct PlateUiState {
|
pub struct PlateUiState {
|
||||||
|
@ -445,7 +445,7 @@ fn add_plate_sub(
|
||||||
static DEFAULT_TEXT_COLOR: LazyLock<egui::Color32> =
|
static DEFAULT_TEXT_COLOR: LazyLock<egui::Color32> =
|
||||||
LazyLock::new(|| egui::Color32::from_gray(128));
|
LazyLock::new(|| egui::Color32::from_gray(128));
|
||||||
static HIGHLIGHT_TEXT_COLOR: LazyLock<egui::Color32> =
|
static HIGHLIGHT_TEXT_COLOR: LazyLock<egui::Color32> =
|
||||||
LazyLock::new(|| egui::Color32::from_gray(255));
|
LazyLock::new(|| egui::Color32::from_gray(0));
|
||||||
for c_row in 0..rows {
|
for c_row in 0..rows {
|
||||||
let text_color = {
|
let text_color = {
|
||||||
if display_options.show_coordinates && hovered_well.is_some_and(|x| x.0 == c_row + 1) {
|
if display_options.show_coordinates && hovered_well.is_some_and(|x| x.0 == c_row + 1) {
|
||||||
|
|
|
@ -0,0 +1,135 @@
|
||||||
|
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)
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
use eframe::egui;
|
use eframe::egui::{self, text_selection::visuals, NumExt};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
main_state::MainState,
|
main_state::MainState,
|
||||||
|
@ -8,8 +8,49 @@ use crate::{
|
||||||
|
|
||||||
use std::sync::LazyLock;
|
use std::sync::LazyLock;
|
||||||
|
|
||||||
static SELECT_COLOR: LazyLock<egui::Color32> =
|
fn tree_label(
|
||||||
LazyLock::new(|| egui::Color32::from_hex("#aa0000").unwrap());
|
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());
|
||||||
|
|
||||||
|
if response.clicked() {
|
||||||
|
return (Some(uuid), false);
|
||||||
|
}
|
||||||
|
if response.double_clicked() {
|
||||||
|
return (None, true);
|
||||||
|
}
|
||||||
|
(None, false)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn tree(
|
pub fn tree(
|
||||||
ui: &mut egui::Ui,
|
ui: &mut egui::Ui,
|
||||||
|
@ -22,29 +63,23 @@ pub fn tree(
|
||||||
ui.heading("Source Plates");
|
ui.heading("Source Plates");
|
||||||
let mut new_uuid: Option<plate_tool_lib::uuid::Uuid> = None;
|
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())) {
|
for (name, uuid) in ms.source_plates.iter().map(|x| (&x.name, x.get_uuid())) {
|
||||||
let f = {
|
let (potential_new_uuid, dbl_clicked) = tree_label(
|
||||||
let mut f = egui::Frame::none();
|
ui,
|
||||||
if ms.get_current_source_uuid().is_some_and(|x| x == uuid) {
|
ms,
|
||||||
f = f.fill(*SELECT_COLOR);
|
modal_state,
|
||||||
}
|
name,
|
||||||
f
|
uuid,
|
||||||
};
|
ms.get_current_source_uuid().is_some_and(|x| x == uuid),
|
||||||
f.show(ui, |ui| {
|
|
||||||
let r = ui.add(
|
|
||||||
egui::Label::new(name)
|
|
||||||
.sense(egui::Sense::click())
|
|
||||||
.selectable(false),
|
|
||||||
);
|
);
|
||||||
if r.clicked() {
|
if potential_new_uuid.is_some() {
|
||||||
new_uuid = Some(uuid);
|
new_uuid = potential_new_uuid;
|
||||||
}
|
}
|
||||||
if r.double_clicked() {
|
if dbl_clicked {
|
||||||
let pi = ms.get_source_by_uuid(uuid);
|
let pi = ms.get_source_by_uuid(uuid);
|
||||||
if let Some(pi) = pi {
|
if let Some(pi) = pi {
|
||||||
crate::modals::open_edit_plate_modal_plateinstance(modal_state, &pi);
|
crate::modals::open_edit_plate_modal_plateinstance(modal_state, &pi);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
}
|
||||||
if let Some(uuid) = new_uuid {
|
if let Some(uuid) = new_uuid {
|
||||||
let current_source_uuid = ms.get_current_source_uuid();
|
let current_source_uuid = ms.get_current_source_uuid();
|
||||||
|
@ -68,29 +103,23 @@ pub fn tree(
|
||||||
.iter()
|
.iter()
|
||||||
.map(|x| (&x.name, x.get_uuid()))
|
.map(|x| (&x.name, x.get_uuid()))
|
||||||
{
|
{
|
||||||
let f = {
|
let (potential_new_uuid, dbl_clicked) = tree_label(
|
||||||
let mut f = egui::Frame::none();
|
ui,
|
||||||
if ms.get_current_destination_uuid().is_some_and(|x| x == uuid) {
|
ms,
|
||||||
f = f.fill(*SELECT_COLOR);
|
modal_state,
|
||||||
}
|
name,
|
||||||
f
|
uuid,
|
||||||
};
|
ms.get_current_destination_uuid().is_some_and(|x| x == uuid),
|
||||||
f.show(ui, |ui| {
|
|
||||||
let r = ui.add(
|
|
||||||
egui::Label::new(name)
|
|
||||||
.sense(egui::Sense::click())
|
|
||||||
.selectable(false),
|
|
||||||
);
|
);
|
||||||
if r.clicked() {
|
if potential_new_uuid.is_some() {
|
||||||
new_uuid = Some(uuid);
|
new_uuid = potential_new_uuid;
|
||||||
}
|
}
|
||||||
if r.double_clicked() {
|
if dbl_clicked {
|
||||||
let pi = ms.get_destination_by_uuid(uuid);
|
let pi = ms.get_destination_by_uuid(uuid);
|
||||||
if let Some(pi) = pi {
|
if let Some(pi) = pi {
|
||||||
crate::modals::open_edit_plate_modal_plateinstance(modal_state, &pi);
|
crate::modals::open_edit_plate_modal_plateinstance(modal_state, &pi);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
}
|
||||||
if let Some(uuid) = new_uuid {
|
if let Some(uuid) = new_uuid {
|
||||||
let current_destination_uuid = ms.get_current_destination_uuid();
|
let current_destination_uuid = ms.get_current_destination_uuid();
|
||||||
|
@ -120,24 +149,17 @@ pub fn tree(
|
||||||
ui.heading("Transfers");
|
ui.heading("Transfers");
|
||||||
let mut new_uuid: Option<plate_tool_lib::uuid::Uuid> = None;
|
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())) {
|
for (name, uuid) in ms.transfers.iter().map(|x| (&x.name, x.get_uuid())) {
|
||||||
let f = {
|
let (potential_new_uuid, _) = tree_label(
|
||||||
let mut f = egui::Frame::none();
|
ui,
|
||||||
if ms.get_current_transfer_uuid().is_some_and(|x| x == uuid) {
|
ms,
|
||||||
f = f.fill(*SELECT_COLOR);
|
modal_state,
|
||||||
}
|
name,
|
||||||
f
|
uuid,
|
||||||
};
|
ms.get_current_transfer_uuid().is_some_and(|x| x == uuid),
|
||||||
f.show(ui, |ui| {
|
|
||||||
let r = ui.add(
|
|
||||||
egui::Label::new(name)
|
|
||||||
.sense(egui::Sense::click())
|
|
||||||
.selectable(false),
|
|
||||||
);
|
);
|
||||||
if r.clicked() {
|
if potential_new_uuid.is_some() {
|
||||||
new_uuid = Some(uuid);
|
new_uuid = potential_new_uuid;
|
||||||
log::info!("{:?}", uuid);
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
}
|
||||||
if let Some(uuid) = new_uuid {
|
if let Some(uuid) = new_uuid {
|
||||||
ms.set_current_transfer(uuid);
|
ms.set_current_transfer(uuid);
|
||||||
|
|
Loading…
Reference in New Issue