use crate::{DrawCtx, Rect};
use super::editor::{EditorKind, NumberAttrs};
use super::value::RowValue;
mod color;
mod default_row;
mod matrix;
mod slider;
mod string_read_only;
mod toggle;
pub fn paint_row(
ctx: &mut dyn DrawCtx,
area: Rect,
label: &str,
value: RowValue,
editor: &EditorKind,
scale: f64,
) {
if label.is_empty() {
dispatch_editor(ctx, area, value, editor, scale);
return;
}
let (label_rect, editor_rect) = split_label_editor(area, scale);
paint_label(ctx, label_rect, label, scale);
dispatch_editor(ctx, editor_rect, value, editor, scale);
}
pub fn paint_editor_only(
ctx: &mut dyn DrawCtx,
area: Rect,
value: RowValue,
editor: &EditorKind,
scale: f64,
) {
dispatch_editor(ctx, area, value, editor, scale);
}
fn dispatch_editor(
ctx: &mut dyn DrawCtx,
editor_area: Rect,
value: RowValue,
editor: &EditorKind,
scale: f64,
) {
match editor {
EditorKind::Slider(attrs) => slider::paint_editor(ctx, editor_area, value, attrs, scale),
EditorKind::NumberDrag(attrs) => {
slider::paint_editor_drag(ctx, editor_area, value, attrs, scale)
}
EditorKind::Toggle => toggle::paint_editor(ctx, editor_area, value, scale),
EditorKind::ColorPicker => color::paint_editor(ctx, editor_area, value, scale),
EditorKind::Matrix => matrix::paint_editor(ctx, editor_area, value, scale),
EditorKind::StringReadOnly => {
string_read_only::paint_editor(ctx, editor_area, value, scale)
}
_ => default_row::paint_editor(ctx, editor_area, value, scale),
}
}
pub(crate) fn split_label_editor(area: Rect, scale: f64) -> (Rect, Rect) {
let split = area.x + area.width * 0.45;
let pad = 8.0 * scale;
let label = Rect::new(
area.x + pad,
area.y,
(split - area.x - pad).max(0.0),
area.height,
);
let editor = Rect::new(
split,
area.y,
(area.width - (split - area.x) - pad).max(0.0),
area.height,
);
(label, editor)
}
pub(crate) fn paint_label(ctx: &mut dyn DrawCtx, area: Rect, label: &str, scale: f64) {
if label.is_empty() {
return;
}
let visuals = ctx.visuals().clone();
ctx.set_fill_color(visuals.text_color);
ctx.set_font_size(11.0 * scale);
let y = area.y + area.height * 0.5 - 4.0 * scale;
ctx.fill_text(label, area.x, y);
}
pub(crate) fn paint_pill_bg(ctx: &mut dyn DrawCtx, area: Rect, scale: f64) {
let visuals = ctx.visuals().clone();
ctx.set_fill_color(visuals.window_fill);
ctx.begin_path();
ctx.rounded_rect(area.x, area.y, area.width, area.height, 3.0 * scale);
ctx.fill();
ctx.set_stroke_color(visuals.window_stroke);
ctx.set_line_width(1.0);
ctx.begin_path();
ctx.rounded_rect(area.x, area.y, area.width, area.height, 3.0 * scale);
ctx.stroke();
}
pub(crate) fn editor_pill_rect(editor_area: Rect, scale: f64) -> Rect {
let pill_h = (editor_area.height - 4.0 * scale).max(12.0 * scale);
let pill_y = editor_area.y + (editor_area.height - pill_h) * 0.5;
Rect::new(editor_area.x, pill_y, editor_area.width, pill_h)
}
pub(crate) fn format_number(n: f64, attrs: Option<&NumberAttrs>) -> String {
let dp = attrs.and_then(|a| a.max_decimal_places);
let integer = attrs.map(|a| a.integer).unwrap_or(false);
if integer || n.fract().abs() < 1e-6 {
format!("{}", n as i64)
} else if let Some(places) = dp {
format!("{:.*}", places as usize, n)
} else {
format!("{:.3}", n)
}
}