use std::rc::Rc;
use glib::Cast;
use grx_macros::gtk_component;
use gtk::prelude::ObjectExt;
use gtk::traits::GridExt;
use gtk::{glib, traits::WidgetExt};
use crate::{new_gc, props, Component, ComponentExt};
use super::gtk_props::apply;
#[props]
#[derive(Default, Debug)]
pub struct Props {
pub col_spacing: u32,
pub row_spacing: u32,
pub row_homogeneous: bool,
pub col_homogeneous: bool,
}
pub fn grid(mut props: Props) -> Rc<Grid> {
let grid = gtk::Grid::builder().build();
let s = props.col_spacing;
grid.set_column_spacing(s);
let s = props.row_spacing;
grid.set_row_spacing(s);
let b = props.col_homogeneous;
grid.set_column_homogeneous(b);
let b = props.row_homogeneous;
grid.set_row_homogeneous(b);
let comp = new_gc!(Grid { grid, props });
for c in comp.children().iter() {
let c: &Component = c;
if let Some(row) = c.annotations().get("row").and_then(|v| v.as_i64()) {
if let Some(col) = c.annotations().get("col").and_then(|v| v.as_i64()) {
let w = c
.annotations()
.get("width")
.and_then(|v| v.as_i64().map(|i| i as i32));
let h = c
.annotations()
.get("height")
.and_then(|v| v.as_i64().map(|i| i as i32));
comp.append_internal(c, col as i32, row as i32, w.unwrap_or(1), h.unwrap_or(1));
}
}
}
apply(comp.clone());
comp
}
#[gtk_component(gtk::Grid)]
#[derive(Debug)]
pub struct Grid {}
impl Grid {
pub fn append(
self: &Rc<Self>,
child: &crate::grx::Component,
x: i32,
y: i32,
width: i32,
height: i32,
) {
let c = child.clone();
c.annotations_mut().insert("row".into(), y.into());
c.annotations_mut().insert("col".into(), x.into());
self.append_internal(&c, x, y, width, height);
self.children.borrow_mut().push(c);
}
pub fn get(self: &Rc<Self>, x: i32, y: i32) -> Option<crate::grx::Component> {
for child in self.children.borrow().iter() {
if let Some(row) = child.annotations().get("row").and_then(|r| r.as_i64()) {
if let Some(col) = child.annotations().get("col").and_then(|c| c.as_i64()) {
if row == y as i64 && col == x as i64 {
return Some(child.clone());
}
}
}
}
None
}
pub fn append_internal(
self: &Rc<Self>,
child: &crate::grx::Component,
x: i32,
y: i32,
width: i32,
height: i32,
) {
let inner = child.clone().inner();
let w: >k::Widget = inner.downcast_ref().unwrap();
self.widget.attach(w, x, y, width, height);
}
pub fn remove_row(self: &Rc<Self>, row: i32) {
self.widget.remove_row(row);
self.children_mut().retain_mut(|c| {
let annotations = c.annotations();
let value = annotations
.get("row")
.and_then(|v| v.as_i64().map(|v| v as i32));
drop(annotations);
if let Some(r) = value {
#[allow(clippy::comparison_chain)]
if r == row {
false
} else if r < row {
true
} else {
c.annotations_mut().insert("row".into(), (r - 1).into());
true
}
} else {
true
}
})
}
pub fn clear(self: &Rc<Self>) {
let mut c = self.widget.first_child();
while let Some(child) = c {
self.widget.remove(&child);
c = child.next_sibling();
}
}
pub fn remove_child(self: &Rc<Self>, child: &Rc<dyn ComponentExt>) {
let w = child.inner();
if let Ok(child_widget) = w.downcast::<gtk::Widget>() {
if child_widget.parent().is_some() {
self.widget.remove(child_widget.as_ref());
} else {
unsafe {
child_widget.run_dispose();
}
}
}
}
}