use egui::{Id, Pos2, Rect, Sense, Ui, UiBuilder};
use crate::tokens::shadcn;
pub const DATA_SPLIT_DEFAULT: f32 = 0.5;
const FRAC_MIN: f32 = 0.15;
const FRAC_MAX: f32 = 0.85;
const HANDLE: f32 = 6.0;
pub fn clamp_frac(f: f32) -> f32 {
f.clamp(FRAC_MIN, FRAC_MAX)
}
#[allow(clippy::too_many_arguments)]
pub fn quad(
ui: &mut Ui,
id: Id,
row_frac: f32,
col_frac: f32,
on_row: impl FnOnce(f32),
on_col: impl FnOnce(f32),
top_left: impl FnOnce(&mut Ui),
top_right: impl FnOnce(&mut Ui),
bottom_left: impl FnOnce(&mut Ui),
bottom_right: impl FnOnce(&mut Ui),
) {
let total = ui.available_rect_before_wrap();
if total.width() <= 0.0 || total.height() <= 0.0 {
return; }
let row = clamp_frac(row_frac);
let col = clamp_frac(col_frac);
ui.allocate_rect(total, Sense::hover());
let half = HANDLE * 0.5;
let y = total.top() + total.height() * row;
let x = total.left() + total.width() * col;
let quads = [
Rect::from_min_max(total.left_top(), Pos2::new(x - half, y - half)),
Rect::from_min_max(
Pos2::new(x + half, total.top()),
Pos2::new(total.right(), y - half),
),
Rect::from_min_max(
Pos2::new(total.left(), y + half),
Pos2::new(x - half, total.bottom()),
),
Rect::from_min_max(Pos2::new(x + half, y + half), total.right_bottom()),
];
ui.scope_builder(UiBuilder::new().max_rect(quads[0]), top_left);
ui.scope_builder(UiBuilder::new().max_rect(quads[1]), top_right);
ui.scope_builder(UiBuilder::new().max_rect(quads[2]), bottom_left);
ui.scope_builder(UiBuilder::new().max_rect(quads[3]), bottom_right);
let p = ui.painter();
let h_band = Rect::from_min_max(
Pos2::new(total.left(), y - half),
Pos2::new(total.right(), y + half),
);
let v_band = Rect::from_min_max(
Pos2::new(x - half, total.top()),
Pos2::new(x + half, total.bottom()),
);
p.rect_filled(h_band, 0.0, shadcn::BG1);
p.rect_filled(v_band, 0.0, shadcn::BG1);
let h_resp = ui.interact(h_band, id.with("handle_h"), Sense::drag());
let v_resp = ui.interact(v_band, id.with("handle_v"), Sense::drag());
let mut h_color = shadcn::BORDER;
let mut v_color = shadcn::BORDER;
if h_resp.dragged() {
h_color = shadcn::ACCENT4;
if total.height() > 1.0 {
let moved = clamp_frac(row + h_resp.drag_delta().y / total.height());
if moved != row {
on_row(moved);
}
}
} else if h_resp.hovered() {
h_color = shadcn::ACCENT4;
}
if v_resp.dragged() {
v_color = shadcn::ACCENT4;
if total.width() > 1.0 {
let moved = clamp_frac(col + v_resp.drag_delta().x / total.width());
if moved != col {
on_col(moved);
}
}
} else if v_resp.hovered() {
v_color = shadcn::ACCENT4;
}
p.line_segment(
[Pos2::new(total.left(), y), Pos2::new(total.right(), y)],
egui::Stroke::new(1.0, h_color),
);
p.line_segment(
[Pos2::new(x, total.top()), Pos2::new(x, total.bottom())],
egui::Stroke::new(1.0, v_color),
);
}