feat: did some stuff that could possible make create widget work

This commit is contained in:
Byson94
2025-08-18 11:14:32 +05:30
parent 88fd6297e2
commit 654bb95f90
4 changed files with 90 additions and 49 deletions

View File

@@ -330,7 +330,7 @@ impl<B: DisplayBackend> App<B> {
root_widget.style_context().add_class(window_name);
let monitor = get_gdk_monitor(initiator.monitor.clone())?;
let mut ewwii_window = initialize_window::<B>(&initiator, monitor, root_widget)?;
let mut ewwii_window = initialize_window::<B>(&initiator, monitor, root_widget.clone())?;
ewwii_window.gtk_window.style_context().add_class(window_name);
// listening/polling
@@ -345,7 +345,7 @@ impl<B: DisplayBackend> App<B> {
match generate_new_widgetnode(&vars, &config_path).await {
Ok(new_widget) => {
let _ = widget_reg_store.update_widget_tree(new_widget);
let _ = widget_reg_store.update_widget_tree(new_widget, root_widget.clone());
}
Err(e) => {
log::error!("Failed to generate new widgetnode: {:#}", e);

View File

@@ -63,7 +63,7 @@ pub struct WidgetRegistry {
}
pub enum PatchGtkWidget {
Create(WidgetNode),
Create(WidgetNode, u64),
Update(u64, Map),
Remove(u64),
}
@@ -73,15 +73,13 @@ impl WidgetRegistry {
Self { widgets: HashMap::new(), stored_widget_node: wn.cloned() }
}
pub fn update_widget_tree(&mut self, new_tree: WidgetNode) -> Result<(), anyhow::Error> {
pub fn update_widget_tree(&mut self, new_tree: WidgetNode, root_widget: gtk::Widget) -> Result<()> {
let old_tree = self.stored_widget_node.take();
let patch = Self::diff_trees(old_tree.as_ref(), &new_tree);
let patch = Self::diff_trees(old_tree.as_ref(), &new_tree, root_widget);
for op in patch {
match op {
PatchGtkWidget::Create(w_node) => {
build_gtk_widget(WidgetInput::Node(w_node), self)?;
}
PatchGtkWidget::Create(w_node, parent_id) => self.create_widget(w_node, parent_id).expect("failed to create new gtk widget"),
PatchGtkWidget::Update(widget_id, new_props) => {
self.update_props(widget_id, new_props);
}
@@ -93,26 +91,25 @@ impl WidgetRegistry {
Ok(())
}
pub fn diff_trees(old: Option<&WidgetNode>, new: &WidgetNode) -> Vec<PatchGtkWidget> {
pub fn diff_trees(old: Option<&WidgetNode>, new: &WidgetNode, root_widget: gtk::Widget) -> Vec<PatchGtkWidget> {
let mut patch = Vec::new();
let mut old_map = HashMap::new();
if let Some(old_node) = old {
let _ = get_id_to_widget_info(old_node, &mut old_map);
let _ = get_id_to_widget_info(old_node, &mut old_map, None);
}
let mut new_map = HashMap::new();
let _ = get_id_to_widget_info(new, &mut new_map);
let _ = get_id_to_widget_info(new, &mut new_map, None);
// Updates and creations
for (id, new_info) in &new_map {
match old_map.get(id) {
Some(old_info) if props_differ(&old_info.props, &new_info.props) => {
log::debug!("Widget {} props changed: {:?}", id, new_info.props);
patch.push(PatchGtkWidget::Update(*id, new_info.props.clone()));
}
None => {
patch.push(PatchGtkWidget::Create(new_info.node.clone()));
patch.push(PatchGtkWidget::Create(new_info.node.clone(), new_info.parent_id.expect("Parent ID must exist")));
}
_ => {}
}
@@ -128,6 +125,20 @@ impl WidgetRegistry {
patch
}
pub fn create_widget(&mut self, widget_node: WidgetNode, parent_id: u64) -> Result<()> {
if let Some(parent) = self.widgets.get(&parent_id) {
let parent_widget = parent.widget.clone();
let gtk_widget = build_gtk_widget(WidgetInput::Node(widget_node.clone()), self)?;
if let Some(container) = parent_widget.dynamic_cast::<gtk::Container>().ok() {
container.add(&gtk_widget);
}
}
Ok(())
}
pub fn update_props(&self, widget_id: u64, new_props: Map) {
if let Some(entry) = self.widgets.get(&widget_id) {
(entry.update_fn)(&new_props);

View File

@@ -45,105 +45,131 @@ pub struct WidgetInfo {
pub props: Map,
pub widget_type: String,
pub children: Vec<WidgetNode>,
pub parent_id: Option<u64>
}
pub fn get_id_to_widget_info(node: &WidgetNode, id_to_props: &mut HashMap<u64, WidgetInfo>) -> Result<()> {
pub fn get_id_to_widget_info(
node: &WidgetNode,
id_to_props: &mut HashMap<u64, WidgetInfo>,
parent_id: Option<u64>,
) -> Result<()> {
match node {
WidgetNode::Box { props, children } => {
insert_wdgt_info(node, props, "Box", children.clone(), id_to_props)?;
let id = hash_props_and_type(props, "Box");
insert_wdgt_info(node, props, "Box", children.clone(), parent_id, id_to_props)?;
for child in children {
get_id_to_widget_info(child, id_to_props)?;
get_id_to_widget_info(child, id_to_props, Some(id))?;
}
}
WidgetNode::CenterBox { props, children } => {
insert_wdgt_info(node, props, "CenterBox", children.clone(), id_to_props)?;
let id = hash_props_and_type(props, "CenterBox");
insert_wdgt_info(node, props, "CenterBox", children.clone(), parent_id, id_to_props)?;
for child in children {
get_id_to_widget_info(child, id_to_props)?;
get_id_to_widget_info(child, id_to_props, Some(id))?;
}
}
WidgetNode::EventBox { props, children } => {
insert_wdgt_info(node, props, "EventBox", children.clone(), id_to_props)?;
let id = hash_props_and_type(props, "EventBox");
insert_wdgt_info(node, props, "EventBox", children.clone(), parent_id, id_to_props)?;
for child in children {
get_id_to_widget_info(child, id_to_props)?;
get_id_to_widget_info(child, id_to_props, Some(id))?;
}
}
WidgetNode::CircularProgress { props } => {
insert_wdgt_info(node, props, "CircularProgress", vec![], id_to_props)?;
let id = hash_props_and_type(props, "CircularProgress");
insert_wdgt_info(node, props, "CircularProgress", vec![], parent_id, id_to_props)?;
}
WidgetNode::Graph { props } => {
insert_wdgt_info(node, props, "Graph", vec![], id_to_props)?;
let id = hash_props_and_type(props, "Graph");
insert_wdgt_info(node, props, "Graph", vec![], parent_id, id_to_props)?;
}
WidgetNode::Transform { props } => {
insert_wdgt_info(node, props, "Transform", vec![], id_to_props)?;
let id = hash_props_and_type(props, "Transform");
insert_wdgt_info(node, props, "Transform", vec![], parent_id, id_to_props)?;
}
WidgetNode::Slider { props } => {
insert_wdgt_info(node, props, "Slider", vec![], id_to_props)?;
let id = hash_props_and_type(props, "Slider");
insert_wdgt_info(node, props, "Slider", vec![], parent_id, id_to_props)?;
}
WidgetNode::Progress { props } => {
insert_wdgt_info(node, props, "Progress", vec![], id_to_props)?;
let id = hash_props_and_type(props, "Progress");
insert_wdgt_info(node, props, "Progress", vec![], parent_id, id_to_props)?;
}
WidgetNode::Image { props } => {
insert_wdgt_info(node, props, "Image", vec![], id_to_props)?;
let id = hash_props_and_type(props, "Image");
insert_wdgt_info(node, props, "Image", vec![], parent_id, id_to_props)?;
}
WidgetNode::Button { props } => {
insert_wdgt_info(node, props, "Button", vec![], id_to_props)?;
let id = hash_props_and_type(props, "Button");
insert_wdgt_info(node, props, "Button", vec![], parent_id, id_to_props)?;
}
WidgetNode::Label { props } => {
insert_wdgt_info(node, props, "Label", vec![], id_to_props)?;
let id = hash_props_and_type(props, "Label");
insert_wdgt_info(node, props, "Label", vec![], parent_id, id_to_props)?;
}
WidgetNode::Input { props } => {
insert_wdgt_info(node, props, "Input", vec![], id_to_props)?;
let id = hash_props_and_type(props, "Input");
insert_wdgt_info(node, props, "Input", vec![], parent_id, id_to_props)?;
}
WidgetNode::Calendar { props } => {
insert_wdgt_info(node, props, "Calendar", vec![], id_to_props)?;
let id = hash_props_and_type(props, "Calendar");
insert_wdgt_info(node, props, "Calendar", vec![], parent_id, id_to_props)?;
}
WidgetNode::ColorButton { props } => {
insert_wdgt_info(node, props, "ColorButton", vec![], id_to_props)?;
let id = hash_props_and_type(props, "ColorButton");
insert_wdgt_info(node, props, "ColorButton", vec![], parent_id, id_to_props)?;
}
WidgetNode::Expander { props, children } => {
insert_wdgt_info(node, props, "Expander", children.clone(), id_to_props)?;
let id = hash_props_and_type(props, "Expander");
insert_wdgt_info(node, props, "Expander", children.clone(), parent_id, id_to_props)?;
for child in children {
get_id_to_widget_info(child, id_to_props)?;
get_id_to_widget_info(child, id_to_props, Some(id))?;
}
}
WidgetNode::ToolTip { children } => {
for child in children {
get_id_to_widget_info(child, id_to_props)?;
get_id_to_widget_info(child, id_to_props, parent_id)?;
}
}
WidgetNode::ColorChooser { props } => {
insert_wdgt_info(node, props, "ColorChooser", vec![], id_to_props)?;
let id = hash_props_and_type(props, "ColorChooser");
insert_wdgt_info(node, props, "ColorChooser", vec![], parent_id, id_to_props)?;
}
WidgetNode::ComboBoxText { props } => {
insert_wdgt_info(node, props, "ComboBoxText", vec![], id_to_props)?;
let id = hash_props_and_type(props, "ComboBoxText");
insert_wdgt_info(node, props, "ComboBoxText", vec![], parent_id, id_to_props)?;
}
WidgetNode::Checkbox { props } => {
insert_wdgt_info(node, props, "Checkbox", vec![], id_to_props)?;
let id = hash_props_and_type(props, "Checkbox");
insert_wdgt_info(node, props, "Checkbox", vec![], parent_id, id_to_props)?;
}
WidgetNode::Revealer { props, children } => {
insert_wdgt_info(node, props, "Revealer", children.clone(), id_to_props)?;
let id = hash_props_and_type(props, "Revealer");
insert_wdgt_info(node, props, "Revealer", children.clone(), parent_id, id_to_props)?;
for child in children {
get_id_to_widget_info(child, id_to_props)?;
get_id_to_widget_info(child, id_to_props, Some(id))?;
}
}
WidgetNode::Scroll { props, children } => {
insert_wdgt_info(node, props, "Scroll", children.clone(), id_to_props)?;
let id = hash_props_and_type(props, "Scroll");
insert_wdgt_info(node, props, "Scroll", children.clone(), parent_id, id_to_props)?;
for child in children {
get_id_to_widget_info(child, id_to_props)?;
get_id_to_widget_info(child, id_to_props, Some(id))?;
}
}
WidgetNode::OverLay { children } => {
for child in children {
get_id_to_widget_info(child, id_to_props)?;
get_id_to_widget_info(child, id_to_props, parent_id)?;
}
}
WidgetNode::Stack { props, children } => {
insert_wdgt_info(node, props, "Stack", children.clone(), id_to_props)?;
let id = hash_props_and_type(props, "Stack");
insert_wdgt_info(node, props, "Stack", children.clone(), parent_id, id_to_props)?;
for child in children {
get_id_to_widget_info(child, id_to_props)?;
get_id_to_widget_info(child, id_to_props, Some(id))?;
}
}
_ => { /* do nothinnng */ }
_ => { /* do nothing */ }
}
Ok(())
@@ -154,10 +180,17 @@ fn insert_wdgt_info(
props: &Map,
widget_type: &str,
children: Vec<WidgetNode>,
parent_id: Option<u64>,
id_to_info: &mut HashMap<u64, WidgetInfo>,
) -> Result<()> {
let id = hash_props_and_type(props, widget_type);
let info = WidgetInfo { node: node.clone(), props: props.clone(), widget_type: widget_type.to_string(), children };
let info = WidgetInfo {
node: node.clone(),
props: props.clone(),
widget_type: widget_type.to_string(),
children,
parent_id,
};
id_to_info.insert(id, info);
Ok(())
}

View File

@@ -16,9 +16,6 @@ let object = #{
// Widget: a single animal button
fn animalButton(emoji, selected) {
print!(selected);
print!(emoji);
let class = "animal";
if selected == emoji {