use std::fmt::Debug;
use iced::widget::{Column, Row, container, row, text};
use iced::{Element, Length, alignment};
use truce_gui::layout::{GridLayout, WidgetKind};
use truce_params::Params;
use crate::param_cache::ParamCache;
use crate::param_message::Message;
use crate::theme;
use crate::widgets;
#[allow(clippy::cast_precision_loss)]
#[must_use]
pub fn auto_view<'a, M: Clone + Debug + 'static, P: Params>(
layout: &GridLayout,
params: &'a ParamCache<P>,
) -> Element<'a, Message<M>> {
let max_row = layout
.widgets
.iter()
.map(|w| w.row + w.row_span)
.max()
.unwrap_or(0);
let mut main_col: Column<'a, Message<M>> = Column::new().spacing(8).padding(15);
if !layout.titles.is_empty() {
let mut header_row = row![].spacing(8).align_y(alignment::Vertical::Center);
if let Some(t) = layout.titles.title {
header_row = header_row.push(text(t).size(16));
}
if let Some(s) = layout.titles.subtitle {
header_row = header_row.push(text(s).size(10).color(theme::TEXT_DIM));
}
let header = container(header_row)
.padding(8)
.style(|_theme: &iced::Theme| container::Style {
background: Some(theme::HEADER_BG.into()),
..Default::default()
})
.width(Length::Fill);
main_col = main_col.push(header);
}
for r in 0..max_row {
if let Some((_, label)) = layout.sections.iter().find(|(row, _)| *row == r) {
main_col = main_col.push(
text(*label)
.size(11)
.color(theme::TEXT_DIM)
.width(Length::Fill)
.align_x(alignment::Horizontal::Center),
);
}
let mut row_widgets: Vec<_> = layout.widgets.iter().filter(|w| w.row == r).collect();
row_widgets.sort_by_key(|w| w.col);
if row_widgets.is_empty() {
continue;
}
let mut row_elem: Row<'a, Message<M>> =
Row::new().spacing(10).align_y(alignment::Vertical::Top);
for widget in &row_widgets {
let kind = widget.widget.unwrap_or(WidgetKind::Knob);
let elem: Element<'a, Message<M>> = match kind {
WidgetKind::Knob => widgets::knob(widget.param_id, params)
.label(widget.label)
.size(layout.cell_size)
.into(),
WidgetKind::Slider => widgets::param_slider(widget.param_id, params)
.label(widget.label)
.width(layout.cell_size)
.into(),
WidgetKind::Toggle => widgets::param_toggle(widget.param_id, params)
.label(widget.label)
.into(),
WidgetKind::Selector | WidgetKind::Dropdown => {
widgets::param_dropdown(widget.param_id, params)
.label(widget.label)
.into()
}
WidgetKind::Meter => {
let fallback = [widget.param_id];
let ids = widget.meter_ids.as_deref().unwrap_or(&fallback);
widgets::meter(ids, params)
.label(widget.label)
.size(
layout.cell_size * widget.col_span as f32,
layout.cell_size * widget.row_span as f32,
)
.into()
}
WidgetKind::XYPad => {
let y_id = widget.param_id_y.unwrap_or(widget.param_id);
widgets::xy_pad(widget.param_id, y_id, params)
.label(widget.label)
.size(layout.cell_size * widget.col_span as f32)
.into()
}
};
row_elem = row_elem.push(elem);
}
main_col = main_col.push(row_elem);
}
main_col.into()
}