use crate::widget::Widget;
use image::RgbaImage;
use std::any::Any;
pub struct Column {
pub children: Vec<Box<dyn Widget>>,
pub spacing: i32,
pub position: (i32, i32),
}
impl Column {
pub fn new() -> Self {
Self {
children: Vec::new(),
spacing: 10,
position: (0, 0),
}
}
pub fn at(mut self, x: i32, y: i32) -> Self {
self.position = (x, y);
self
}
pub fn with_spacing(mut self, spacing: i32) -> Self {
self.spacing = spacing;
self
}
pub fn add(mut self, widget: impl Widget + 'static) -> Self {
self.children.push(Box::new(widget));
self
}
}
impl Widget for Column {
fn set_position(&mut self, x: i32, y: i32) {
self.position = (x, y);
}
fn draw(&mut self, framebuffer: &mut RgbaImage) {
let mut current_y = self.position.1;
for child in &mut self.children {
child.set_position(self.position.0, current_y);
child.draw(framebuffer);
current_y += child.size().1 + self.spacing;
}
}
fn handle_click(&mut self, x: i32, y: i32) -> Option<String> {
for child in &mut self.children {
if let Some(clicked_id) = child.handle_click(x, y) {
return Some(clicked_id);
}
}
None
}
fn size(&self) -> (i32, i32) {
let mut width = 0;
let mut height = 0;
for child in &self.children {
let (w, h) = child.size();
if w > width {
width = w;
}
height += h + self.spacing;
}
if !self.children.is_empty() {
height -= self.spacing;
}
(width, height)
}
fn id(&self) -> Option<&str> {
None
}
fn as_any_mut(&mut self) -> &mut dyn Any {
self
}
fn find_child_mut(&mut self, id: &str) -> Option<&mut dyn Widget> {
for child in &mut self.children {
if child.id() == Some(id) {
return Some(child.as_mut());
}
if let Some(found) = child.find_child_mut(id) {
return Some(found);
}
}
None
}
}
pub struct Row {
pub children: Vec<Box<dyn Widget>>,
pub spacing: i32,
pub position: (i32, i32),
}
impl Row {
pub fn new() -> Self {
Self {
children: Vec::new(),
spacing: 10,
position: (0, 0),
}
}
pub fn at(mut self, x: i32, y: i32) -> Self {
self.position = (x, y);
self
}
pub fn with_spacing(mut self, spacing: i32) -> Self {
self.spacing = spacing;
self
}
pub fn add(mut self, widget: impl Widget + 'static) -> Self {
self.children.push(Box::new(widget));
self
}
}
impl Widget for Row {
fn set_position(&mut self, x: i32, y: i32) {
self.position = (x, y);
}
fn draw(&mut self, framebuffer: &mut RgbaImage) {
let mut current_x = self.position.0;
for child in &mut self.children {
child.set_position(current_x, self.position.1);
child.draw(framebuffer);
current_x += child.size().0 + self.spacing;
}
}
fn handle_click(&mut self, x: i32, y: i32) -> Option<String> {
for child in &mut self.children {
if let Some(clicked_id) = child.handle_click(x, y) {
return Some(clicked_id);
}
}
None
}
fn size(&self) -> (i32, i32) {
let mut width = 0;
let mut height = 0;
for child in &self.children {
let (w, h) = child.size();
if h > height {
height = h;
}
width += w + self.spacing;
}
if !self.children.is_empty() {
width -= self.spacing;
}
(width, height)
}
fn id(&self) -> Option<&str> {
None
}
fn as_any_mut(&mut self) -> &mut dyn Any {
self
}
fn find_child_mut(&mut self, id: &str) -> Option<&mut dyn Widget> {
for child in &mut self.children {
if child.id() == Some(id) {
return Some(child.as_mut());
}
if let Some(found) = child.find_child_mut(id) {
return Some(found);
}
}
None
}
}