feat: did some stuff that could possible make create widget work
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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(>k_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);
|
||||
|
||||
@@ -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(())
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user