use cacao::{
button::Button,
image::ImageView,
input::TextField,
layout::{LayoutAnchorDimension, LayoutAnchorX, LayoutAnchorY, LayoutConstraint},
text::Label,
view::View,
};
use crate::{
element::{Element, ElementType},
input::InputDelegate,
};
pub enum Widget {
Container {
view: View,
children: Vec<Widget>,
constraints: Vec<LayoutConstraint>,
},
Button {
control: Button,
handler_id: Option<usize>,
},
Label(Label),
Input(TextField<InputDelegate>),
ImageView {
view: ImageView,
version: u64,
},
}
pub struct Anchors {
pub top: LayoutAnchorY,
pub bottom: LayoutAnchorY,
pub leading: LayoutAnchorX,
pub trailing: LayoutAnchorX,
pub width: LayoutAnchorDimension,
pub height: LayoutAnchorDimension,
}
impl Widget {
pub fn anchors(&self) -> Anchors {
match self {
Widget::Container { view, .. } => Anchors {
top: view.top.clone(),
bottom: view.bottom.clone(),
leading: view.leading.clone(),
trailing: view.trailing.clone(),
width: view.width.clone(),
height: view.height.clone(),
},
Widget::Button { control, .. } => Anchors {
top: control.top.clone(),
bottom: control.bottom.clone(),
leading: control.leading.clone(),
trailing: control.trailing.clone(),
width: control.width.clone(),
height: control.height.clone(),
},
Widget::Label(label) => Anchors {
top: label.top.clone(),
bottom: label.bottom.clone(),
leading: label.leading.clone(),
trailing: label.trailing.clone(),
width: label.width.clone(),
height: label.height.clone(),
},
Widget::Input(field) => Anchors {
top: field.top.clone(),
bottom: field.bottom.clone(),
leading: field.leading.clone(),
trailing: field.trailing.clone(),
width: field.width.clone(),
height: field.height.clone(),
},
Widget::ImageView { view, .. } => Anchors {
top: view.top.clone(),
bottom: view.bottom.clone(),
leading: view.leading.clone(),
trailing: view.trailing.clone(),
width: view.width.clone(),
height: view.height.clone(),
},
}
}
}
const FLEX_PROPS: &[&str] = &["direction", "gap", "padding", "width", "height", "grow"];
pub fn flex_changed(old: &Element, new: &Element) -> bool {
FLEX_PROPS
.iter()
.any(|key| old.props.get(*key) != new.props.get(*key))
}
pub fn compatible(widget: &Widget, new_el: &Element) -> bool {
matches!(
(widget, &new_el.element_type),
(
Widget::Container { .. },
ElementType::Window | ElementType::Div
) | (Widget::Button { .. }, ElementType::Button)
| (Widget::Label(_), ElementType::Text(_))
| (Widget::Input(_), ElementType::Input)
| (Widget::ImageView { .. }, ElementType::Image)
)
}