|
@@ -1,7 +1,9 @@
|
|
|
+use kahlo::math::PixelSideOffsets;
|
|
|
+
|
|
|
use crate::{
|
|
|
component::Component,
|
|
|
input::InputState,
|
|
|
- layout::{ChildArrangement, LayoutNode, LayoutNodeAccess, LayoutNodeContainer, SizePolicy},
|
|
|
+ layout::{ChildArrangement, LayoutNode, LayoutNodeAccess, LayoutNodeContainer, SizePolicy, TableCell, HorizontalAlignment},
|
|
|
theme::Theme,
|
|
|
ui::UIHandle,
|
|
|
widget::Widget,
|
|
@@ -87,48 +89,99 @@ impl<C: Component> Widget<C> for PlainGroup<C> {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-use super::Label;
|
|
|
+use super::{Label, WidgetExt};
|
|
|
|
|
|
pub struct FormGroup<C: Component> {
|
|
|
+ label_margin: PixelSideOffsets,
|
|
|
lnode: LayoutNode,
|
|
|
- labelnode: LayoutNode,
|
|
|
- widgetnode: LayoutNode,
|
|
|
labels: Vec<Label<C>>,
|
|
|
widgets: Vec<Box<dyn Widget<C>>>,
|
|
|
}
|
|
|
|
|
|
-struct LabelContainer<'l, C: Component>(&'l FormGroup<C>);
|
|
|
-struct WidgetContainer<'l, C: Component>(&'l FormGroup<C>);
|
|
|
+impl<C: Component> FormGroup<C> {
|
|
|
+ pub fn new(uih: &UIHandle) -> Self {
|
|
|
+ let mut lnode = uih.new_layout_node();
|
|
|
+ lnode.set_arrangement(ChildArrangement::Table);
|
|
|
+ Self {
|
|
|
+ label_margin: PixelSideOffsets::new(1, 5, 1, 5),
|
|
|
+ lnode,
|
|
|
+ labels: vec![],
|
|
|
+ widgets: vec![],
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ pub fn label_margin(&self) -> PixelSideOffsets {
|
|
|
+ self.label_margin
|
|
|
+ }
|
|
|
+
|
|
|
+ pub fn set_label_margin(&mut self, margin: PixelSideOffsets) {
|
|
|
+ for lbl in self.labels.iter_mut() {
|
|
|
+ lbl.set_margins(margin);
|
|
|
+ }
|
|
|
+ self.label_margin = margin;
|
|
|
+ }
|
|
|
+
|
|
|
+ pub fn add_widget(&mut self, label: &str, mut widget: Box<dyn Widget<C>>) {
|
|
|
+ widget.set_table_cell(TableCell::new(1, self.labels.len()));
|
|
|
+ self.widgets.push(widget);
|
|
|
+ self.labels.push(
|
|
|
+ Label::new_with_node_and_text(self.lnode.make_new_node(), label)
|
|
|
+ .with_table_cell(TableCell::new(0, self.labels.len()))
|
|
|
+ .with_margins(self.label_margin)
|
|
|
+ .with_halign(HorizontalAlignment::Right)
|
|
|
+ );
|
|
|
+ }
|
|
|
+}
|
|
|
|
|
|
impl<C: Component> LayoutNodeContainer for FormGroup<C> {
|
|
|
fn layout_node(&self) -> &LayoutNode {
|
|
|
&self.lnode
|
|
|
}
|
|
|
fn layout_child(&self, ndx: usize) -> Option<LayoutNodeAccess<'_>> {
|
|
|
- match ndx {
|
|
|
- 0 => todo!(), // Some(LayoutNodeAccess::new(LabelContainer(self))),
|
|
|
- 1 => todo!(),
|
|
|
- _ => None,
|
|
|
+ if ndx < self.labels.len() {
|
|
|
+ Some(self.labels[ndx].layout_node())
|
|
|
+ } else if ndx < (self.labels.len() + self.widgets.len()) {
|
|
|
+ Some(self.widgets[ndx-self.labels.len()].layout_node())
|
|
|
+ } else {
|
|
|
+ None
|
|
|
}
|
|
|
}
|
|
|
fn layout_child_count(&self) -> usize {
|
|
|
- 2
|
|
|
+ self.labels.len() + self.widgets.len()
|
|
|
}
|
|
|
}
|
|
|
|
|
|
impl<C: Component> Widget<C> for FormGroup<C> {
|
|
|
fn layout_node(&self) -> LayoutNodeAccess {
|
|
|
- todo!()
|
|
|
+ LayoutNodeAccess::new(self)
|
|
|
}
|
|
|
+
|
|
|
fn layout_node_mut(&mut self) -> &mut LayoutNode {
|
|
|
- todo!()
|
|
|
+ &mut self.lnode
|
|
|
}
|
|
|
+
|
|
|
fn poll(
|
|
|
&mut self,
|
|
|
uih: &mut UIHandle,
|
|
|
input_state: Option<&InputState>,
|
|
|
) -> Vec<<C as Component>::Msg> {
|
|
|
- todo!()
|
|
|
+ let mut res = vec![];
|
|
|
+ for lbl in self.labels.iter_mut() {
|
|
|
+ res.append(&mut lbl.poll(uih, input_state));
|
|
|
+ }
|
|
|
+ for widget in self.widgets.iter_mut() {
|
|
|
+ res.append(&mut widget.poll(uih, input_state));
|
|
|
+ }
|
|
|
+
|
|
|
+ res
|
|
|
+ }
|
|
|
+
|
|
|
+ fn render(&self, theme: &Theme, target: &mut kahlo::BitmapMut<RenderFormat>) {
|
|
|
+ for lbl in self.labels.iter() {
|
|
|
+ lbl.render(theme, target);
|
|
|
+ }
|
|
|
+ for widget in self.widgets.iter() {
|
|
|
+ widget.render(theme, target);
|
|
|
+ }
|
|
|
}
|
|
|
- fn render(&self, theme: &Theme, target: &mut kahlo::BitmapMut<RenderFormat>) {}
|
|
|
}
|