Эх сурвалжийг харах

wallet: move draw() methods into UIObject trait

darkfi 1 жил өмнө
parent
commit
00f936b316

+ 1 - 1
bin/darkwallet/gui/api.py

@@ -2,7 +2,7 @@ from collections import namedtuple
 from pydrk import Api, HostApi, PropertyType, PropertySubType, Property, serial
 import zmq
 
-api = Api(addr="192.168.1.20")
+api = Api()
 host = HostApi(api)
 print("Node status:", api.hello())
 

+ 6 - 3
bin/darkwallet/src/app/schema.rs

@@ -569,6 +569,7 @@ pub(super) async fn make(app: &App) {
     prop.set_f32(Role::App, 1, 0.).unwrap();
     prop.set_expr(Role::App, 2, shape::load_var("w")).unwrap();
     prop.set_expr(Role::App, 3, shape::load_var("h")).unwrap();
+    node.set_property_u32(Role::App, "z_index", 0).unwrap();
 
     let c = if LIGHTMODE { 1. } else { 0.05 };
     // Setup the pimpl
@@ -600,7 +601,7 @@ pub(super) async fn make(app: &App) {
     prop.set_f32(Role::App, 1, 0.).unwrap();
     prop.set_expr(Role::App, 2, shape::load_var("w")).unwrap();
     prop.set_f32(Role::App, 3, EDITCHAT_HEIGHT).unwrap();
-    node.set_property_u32(Role::App, "z_index", 0).unwrap();
+    node.set_property_u32(Role::App, "z_index", 1).unwrap();
     drop(sg);
     let mut shape = VectorShape::new();
     shape.add_outline(
@@ -630,6 +631,7 @@ pub(super) async fn make(app: &App) {
     prop.set_f32(Role::App, 1, 0.).unwrap();
     prop.set_expr(Role::App, 2, shape::load_var("w")).unwrap();
     prop.set_f32(Role::App, 3, EDITCHAT_HEIGHT).unwrap();
+    node.set_property_u32(Role::App, "z_index", 2).unwrap();
     node.set_property_f32(Role::App, "baseline", (EDITCHAT_HEIGHT + 20.) / 2.).unwrap();
     node.set_property_f32(Role::App, "font_size", FONTSIZE).unwrap();
     node.set_property_str(Role::App, "text", "random").unwrap();
@@ -760,7 +762,7 @@ pub(super) async fn make(app: &App) {
     prop.set_expr(Role::App, 1, code).unwrap();
     prop.set_expr(Role::App, 2, shape::load_var("w")).unwrap();
     prop.set_f32(Role::App, 3, EDITCHAT_HEIGHT).unwrap();
-    node.set_property_u32(Role::App, "z_index", 0).unwrap();
+    node.set_property_u32(Role::App, "z_index", 1).unwrap();
     drop(sg);
     let mut shape = VectorShape::new();
     shape.add_filled_box(
@@ -815,6 +817,7 @@ pub(super) async fn make(app: &App) {
     prop.set_f32(Role::App, 1, 1.).unwrap();
     prop.set_f32(Role::App, 2, 0.94).unwrap();
     prop.set_f32(Role::App, 3, 1.).unwrap();
+    node.set_property_u32(Role::App, "z_index", 2).unwrap();
 
     drop(sg);
     let pimpl = Text::new(
@@ -879,7 +882,7 @@ pub(super) async fn make(app: &App) {
     let prop = node.get_property("selected").unwrap();
     prop.set_null(Role::App, 0).unwrap();
     prop.set_null(Role::App, 1).unwrap();
-    node.set_property_u32(Role::App, "z_index", 1).unwrap();
+    node.set_property_u32(Role::App, "z_index", 2).unwrap();
     //node.set_property_bool(Role::App, "debug", true).unwrap();
 
     let editbox_text = PropertyStr::wrap(node, Role::App, "text", 0).unwrap();

+ 9 - 9
bin/darkwallet/src/ui/button.rs

@@ -31,7 +31,7 @@ use crate::{
     ExecutorPtr,
 };
 
-use super::{eval_rect, read_rect, UIObject};
+use super::{eval_rect, read_rect, DrawUpdate, UIObject};
 
 pub type ButtonPtr = Arc<Button>;
 
@@ -81,12 +81,6 @@ impl Button {
         };
         Some(rect)
     }
-
-    pub fn set_parent_rect(&self, parent_rect: &Rectangle) {
-        if let Err(err) = eval_rect(self.rect.clone(), parent_rect) {
-            panic!("Button bad rect property: {}", err);
-        }
-    }
 }
 
 #[async_trait]
@@ -95,6 +89,13 @@ impl UIObject for Button {
         self.z_index.get()
     }
 
+    async fn draw(&self, _: &SceneGraph, parent_rect: &Rectangle) -> Option<DrawUpdate> {
+        if let Err(err) = eval_rect(self.rect.clone(), parent_rect) {
+            panic!("Button bad rect property: {}", err);
+        }
+        None
+    }
+
     async fn handle_mouse_btn_down(
         &self,
         sg: &SceneGraph,
@@ -145,8 +146,7 @@ impl UIObject for Button {
         }
 
         debug!(target: "ui::button", "Mouse button clicked!");
-        let scene_graph = self.sg.lock().await;
-        let node = scene_graph.get_node(self.node_id).unwrap();
+        let node = sg.get_node(self.node_id).unwrap();
         node.trigger("click", vec![]).await.unwrap();
 
         true

+ 35 - 35
bin/darkwallet/src/ui/chatview/mod.rs

@@ -653,41 +653,6 @@ impl ChatView {
         (instrs, freed)
     }
 
-    pub async fn draw(&self, sg: &SceneGraph, parent_rect: &Rectangle) -> Option<DrawUpdate> {
-        debug!(target: "ui::chatview", "ChatView::draw()");
-
-        *self.parent_rect.lock().unwrap() = Some(parent_rect.clone());
-        let rect = eval_rect(self.rect.clone(), parent_rect).expect("bad rect property");
-
-        let mut msgbuf = self.msgbuf.lock().await;
-        msgbuf.adjust_width(rect.w);
-
-        let mut scroll = self.scroll.get();
-        if let Some(scroll) = self.adjust_scroll(&mut msgbuf, scroll, rect.h).await {
-            self.scroll.set(scroll);
-        }
-
-        // We may need to load more messages since the screen size has changed.
-        // Now we have updated all the values so it's safe to wake up here.
-        self.bgload_cv.notify();
-
-        let (mut mesh_instrs, freed) = self.get_meshes(&mut msgbuf, &rect).await;
-        drop(msgbuf);
-
-        let mut instrs = vec![GfxDrawInstruction::ApplyViewport(rect)];
-        instrs.append(&mut mesh_instrs);
-
-        Some(DrawUpdate {
-            key: self.dc_key,
-            draw_calls: vec![(
-                self.dc_key,
-                GfxDrawCall { instrs, dcs: vec![], z_index: self.z_index.get() },
-            )],
-            freed_textures: freed.textures,
-            freed_buffers: freed.buffers,
-        })
-    }
-
     async fn redraw_cached(&self, msgbuf: &mut MessageBuffer) {
         let rect = read_rect(self.rect.clone()).expect("bad rect property");
 
@@ -722,6 +687,41 @@ impl UIObject for ChatView {
         self.z_index.get()
     }
 
+    async fn draw(&self, sg: &SceneGraph, parent_rect: &Rectangle) -> Option<DrawUpdate> {
+        debug!(target: "ui::chatview", "ChatView::draw()");
+
+        *self.parent_rect.lock().unwrap() = Some(parent_rect.clone());
+        let rect = eval_rect(self.rect.clone(), parent_rect).expect("bad rect property");
+
+        let mut msgbuf = self.msgbuf.lock().await;
+        msgbuf.adjust_width(rect.w);
+
+        let mut scroll = self.scroll.get();
+        if let Some(scroll) = self.adjust_scroll(&mut msgbuf, scroll, rect.h).await {
+            self.scroll.set(scroll);
+        }
+
+        // We may need to load more messages since the screen size has changed.
+        // Now we have updated all the values so it's safe to wake up here.
+        self.bgload_cv.notify();
+
+        let (mut mesh_instrs, freed) = self.get_meshes(&mut msgbuf, &rect).await;
+        drop(msgbuf);
+
+        let mut instrs = vec![GfxDrawInstruction::ApplyViewport(rect)];
+        instrs.append(&mut mesh_instrs);
+
+        Some(DrawUpdate {
+            key: self.dc_key,
+            draw_calls: vec![(
+                self.dc_key,
+                GfxDrawCall { instrs, dcs: vec![], z_index: self.z_index.get() },
+            )],
+            freed_textures: freed.textures,
+            freed_buffers: freed.buffers,
+        })
+    }
+
     async fn handle_key_down(
         &self,
         sg: &SceneGraph,

+ 13 - 13
bin/darkwallet/src/ui/editbox.rs

@@ -1014,19 +1014,6 @@ impl EditBox {
         })
     }
 
-    pub fn draw(&self, sg: &SceneGraph, parent_rect: &Rectangle) -> Option<DrawUpdate> {
-        *self.parent_rect.lock().unwrap() = Some(parent_rect.clone());
-        //debug!(target: "ui::editbox", "EditBox::draw()");
-        // Only used for debug messages
-        let node = sg.get_node(self.node_id).unwrap();
-
-        if let Err(err) = eval_rect(self.rect.clone(), parent_rect) {
-            panic!("Node {:?} bad rect property: {}", node, err);
-        }
-
-        self.draw_cached()
-    }
-
     async fn send_event(&self) {
         let text = self.text.get();
         debug!(target: "ui::editbox", "sending text {}", text);
@@ -1067,6 +1054,19 @@ impl UIObject for EditBox {
         self.z_index.get()
     }
 
+    async fn draw(&self, sg: &SceneGraph, parent_rect: &Rectangle) -> Option<DrawUpdate> {
+        *self.parent_rect.lock().unwrap() = Some(parent_rect.clone());
+        //debug!(target: "ui::editbox", "EditBox::draw()");
+        // Only used for debug messages
+        let node = sg.get_node(self.node_id).unwrap();
+
+        if let Err(err) = eval_rect(self.rect.clone(), parent_rect) {
+            panic!("Node {:?} bad rect property: {}", node, err);
+        }
+
+        self.draw_cached()
+    }
+
     async fn handle_char(&self, sg: &SceneGraph, key: char, mods: KeyMods, repeat: bool) -> bool {
         // First filter for only single digit keys
         if DISALLOWED_CHARS.contains(&key) {

+ 27 - 25
bin/darkwallet/src/ui/image.rs

@@ -16,6 +16,7 @@
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  */
 
+use async_trait::async_trait;
 use image::ImageReader;
 use rand::{rngs::OsRng, Rng};
 use std::{
@@ -134,7 +135,7 @@ impl Image {
             return;
         };
 
-        let Some(draw_update) = self.draw(&sg, &parent_rect) else {
+        let Some(draw_update) = self.draw(&sg, &parent_rect).await else {
             error!(target: "ui::text", "Text {:?} failed to draw", node);
             return;
         };
@@ -150,8 +151,32 @@ impl Image {
         mesh.draw_box(&basic, COLOR_WHITE, &basic);
         mesh.alloc(&self.render_api)
     }
+}
+
+impl Drop for Image {
+    fn drop(&mut self) {
+        // TODO: Delete own draw call
+
+        // Free buffers
+        // Should this be in drop?
+        if let Some(mesh) = &*self.mesh.lock().unwrap() {
+            let vertex_buffer = mesh.vertex_buffer;
+            let index_buffer = mesh.index_buffer;
+            self.render_api.delete_buffer(vertex_buffer);
+            self.render_api.delete_buffer(index_buffer);
+        }
+        let texture_id = self.texture.lock().unwrap().unwrap();
+        self.render_api.delete_texture(texture_id);
+    }
+}
+
+#[async_trait]
+impl UIObject for Image {
+    fn z_index(&self) -> u32 {
+        self.z_index.get()
+    }
 
-    pub fn draw(&self, sg: &SceneGraph, parent_rect: &Rectangle) -> Option<DrawUpdate> {
+    async fn draw(&self, sg: &SceneGraph, parent_rect: &Rectangle) -> Option<DrawUpdate> {
         debug!(target: "ui::text", "Text::draw()");
         // Only used for debug messages
         let node = sg.get_node(self.node_id).unwrap();
@@ -212,26 +237,3 @@ impl Image {
         })
     }
 }
-
-impl Drop for Image {
-    fn drop(&mut self) {
-        // TODO: Delete own draw call
-
-        // Free buffers
-        // Should this be in drop?
-        if let Some(mesh) = &*self.mesh.lock().unwrap() {
-            let vertex_buffer = mesh.vertex_buffer;
-            let index_buffer = mesh.index_buffer;
-            self.render_api.delete_buffer(vertex_buffer);
-            self.render_api.delete_buffer(index_buffer);
-        }
-        let texture_id = self.texture.lock().unwrap().unwrap();
-        self.render_api.delete_texture(texture_id);
-    }
-}
-
-impl UIObject for Image {
-    fn z_index(&self) -> u32 {
-        self.z_index.get()
-    }
-}

+ 20 - 32
bin/darkwallet/src/ui/layer.rs

@@ -112,9 +112,20 @@ impl RenderLayer {
         self.render_api.replace_draw_calls(draw_update.draw_calls);
         debug!(target: "ui::layer", "replace draw calls done");
     }
+}
 
-    #[async_recursion]
-    pub async fn draw(&self, sg: &SceneGraph, parent_rect: &Rectangle) -> Option<DrawUpdate> {
+impl Stoppable for RenderLayer {
+    async fn stop(&self) {}
+}
+
+#[async_trait]
+impl UIObject for RenderLayer {
+    fn z_index(&self) -> u32 {
+        self.z_index.get()
+    }
+
+    //#[async_recursion]
+    async fn draw(&self, sg: &SceneGraph, parent_rect: &Rectangle) -> Option<DrawUpdate> {
         debug!(target: "ui::layer", "RenderLayer::draw()");
         let node = sg.get_node(self.node_id).unwrap();
 
@@ -153,26 +164,14 @@ impl RenderLayer {
         let mut freed_textures = vec![];
         let mut freed_buffers = vec![];
 
-        for child_inf in node.get_children2() {
-            let node = sg.get_node(child_inf.id).unwrap();
-
-            let dcs = match &node.pimpl {
-                Pimpl::RenderLayer(layer) => layer.draw(&sg, &rect).await,
-                Pimpl::VectorArt(svg) => svg.draw(&sg, &rect),
-                Pimpl::Text(txt) => txt.draw(&sg, &rect),
-                Pimpl::EditBox(editb) => editb.draw(&sg, &rect),
-                Pimpl::ChatView(chat) => chat.draw(&sg, &rect).await,
-                Pimpl::Image(img) => img.draw(&sg, &rect),
-                Pimpl::Button(btn) => {
-                    btn.set_parent_rect(&rect);
-                    continue
-                }
-                _ => {
-                    error!(target: "ui::layer", "unhandled pimpl type");
-                    continue
-                }
+        for child_id in get_child_nodes_ordered(&sg, self.node_id) {
+            let node = sg.get_node(child_id).unwrap();
+            let obj = get_ui_object(node);
+            let Some(mut draw_update) = obj.draw(sg, &rect).await else {
+                debug!(target: "ui::layer", "Skipped draw() of {node:?}");
+                continue
             };
-            let Some(mut draw_update) = dcs else { continue };
+
             draw_calls.append(&mut draw_update.draw_calls);
             child_calls.push(draw_update.key);
             freed_textures.append(&mut draw_update.freed_textures);
@@ -187,17 +186,6 @@ impl RenderLayer {
         draw_calls.push((self.dc_key, dc));
         Some(DrawUpdate { key: self.dc_key, draw_calls, freed_textures, freed_buffers })
     }
-}
-
-impl Stoppable for RenderLayer {
-    async fn stop(&self) {}
-}
-
-#[async_trait]
-impl UIObject for RenderLayer {
-    fn z_index(&self) -> u32 {
-        self.z_index.get()
-    }
 
     async fn handle_char(&self, sg: &SceneGraph, key: char, mods: KeyMods, repeat: bool) -> bool {
         for child_id in get_child_nodes_ordered(&sg, self.node_id) {

+ 4 - 0
bin/darkwallet/src/ui/mod.rs

@@ -57,6 +57,10 @@ pub trait Stoppable {
 pub trait UIObject: Sync {
     fn z_index(&self) -> u32;
 
+    async fn draw(&self, sg: &SceneGraph, parent_rect: &Rectangle) -> Option<DrawUpdate> {
+        None
+    }
+
     async fn handle_char(&self, sg: &SceneGraph, key: char, mods: KeyMods, repeat: bool) -> bool {
         false
     }

+ 26 - 24
bin/darkwallet/src/ui/text.rs

@@ -16,6 +16,7 @@
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  */
 
+use async_trait::async_trait;
 use rand::{rngs::OsRng, Rng};
 use std::sync::{Arc, Mutex as SyncMutex, Weak};
 
@@ -182,7 +183,7 @@ impl Text {
             return;
         };
 
-        let Some(draw_update) = self.draw(&sg, &parent_rect) else {
+        let Some(draw_update) = self.draw(&sg, &parent_rect).await else {
             error!(target: "ui::text", "Text {:?} failed to draw", node);
             return;
         };
@@ -194,8 +195,31 @@ impl Text {
         self.render_api.delete_buffer(old.mesh.index_buffer);
         self.render_api.delete_texture(old.texture_id);
     }
+}
+
+impl Stoppable for Text {
+    async fn stop(&self) {
+        // TODO: Delete own draw call
+
+        // Free buffers
+        // Should this be in drop?
+        let render_info = self.render_info.lock().unwrap().clone();
+        let vertex_buffer = render_info.mesh.vertex_buffer;
+        let index_buffer = render_info.mesh.index_buffer;
+        let texture_id = render_info.texture_id;
+        self.render_api.delete_buffer(vertex_buffer);
+        self.render_api.delete_buffer(index_buffer);
+        self.render_api.delete_texture(texture_id);
+    }
+}
+
+#[async_trait]
+impl UIObject for Text {
+    fn z_index(&self) -> u32 {
+        self.z_index.get()
+    }
 
-    pub fn draw(&self, sg: &SceneGraph, parent_rect: &Rectangle) -> Option<DrawUpdate> {
+    async fn draw(&self, sg: &SceneGraph, parent_rect: &Rectangle) -> Option<DrawUpdate> {
         debug!(target: "ui::text", "Text::draw()");
         // Only used for debug messages
         let node = sg.get_node(self.node_id).unwrap();
@@ -242,25 +266,3 @@ impl Text {
         })
     }
 }
-
-impl Stoppable for Text {
-    async fn stop(&self) {
-        // TODO: Delete own draw call
-
-        // Free buffers
-        // Should this be in drop?
-        let render_info = self.render_info.lock().unwrap().clone();
-        let vertex_buffer = render_info.mesh.vertex_buffer;
-        let index_buffer = render_info.mesh.index_buffer;
-        let texture_id = render_info.texture_id;
-        self.render_api.delete_buffer(vertex_buffer);
-        self.render_api.delete_buffer(index_buffer);
-        self.render_api.delete_texture(texture_id);
-    }
-}
-
-impl UIObject for Text {
-    fn z_index(&self) -> u32 {
-        self.z_index.get()
-    }
-}

+ 23 - 21
bin/darkwallet/src/ui/vector_art/mod.rs

@@ -16,6 +16,7 @@
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  */
 
+use async_trait::async_trait;
 use rand::{rngs::OsRng, Rng};
 use std::sync::{Arc, Mutex as SyncMutex, Weak};
 
@@ -98,15 +99,35 @@ impl VectorArt {
             return;
         };
 
-        let Some(draw_update) = self.draw(&sg, &parent_rect) else {
+        let Some(draw_update) = self.draw(&sg, &parent_rect).await else {
             error!(target: "ui::vector_art", "Mesh {:?} failed to draw", node);
             return;
         };
         self.render_api.replace_draw_calls(draw_update.draw_calls);
         debug!(target: "ui::vector_art", "replace draw calls done");
     }
+}
+
+impl Stoppable for VectorArt {
+    async fn stop(&self) {
+        // TODO: Delete own draw call
+
+        // Free buffers
+        // Should this be in drop?
+        if let Some(mesh) = &*self.buffers.lock().unwrap() {
+            self.render_api.delete_buffer(mesh.vertex_buffer);
+            self.render_api.delete_buffer(mesh.index_buffer);
+        }
+    }
+}
+
+#[async_trait]
+impl UIObject for VectorArt {
+    fn z_index(&self) -> u32 {
+        self.z_index.get()
+    }
 
-    pub fn draw(&self, sg: &SceneGraph, parent_rect: &Rectangle) -> Option<DrawUpdate> {
+    async fn draw(&self, sg: &SceneGraph, parent_rect: &Rectangle) -> Option<DrawUpdate> {
         debug!(target: "ui::vector_art", "VectorArt::draw()");
         // Only used for debug messages
         let node = sg.get_node(self.node_id).unwrap();
@@ -166,22 +187,3 @@ impl VectorArt {
         })
     }
 }
-
-impl Stoppable for VectorArt {
-    async fn stop(&self) {
-        // TODO: Delete own draw call
-
-        // Free buffers
-        // Should this be in drop?
-        if let Some(mesh) = &*self.buffers.lock().unwrap() {
-            self.render_api.delete_buffer(mesh.vertex_buffer);
-            self.render_api.delete_buffer(mesh.index_buffer);
-        }
-    }
-}
-
-impl UIObject for VectorArt {
-    fn z_index(&self) -> u32 {
-        self.z_index.get()
-    }
-}

+ 7 - 11
bin/darkwallet/src/ui/win.rs

@@ -402,18 +402,14 @@ impl Window {
         let mut freed_textures = vec![];
         let mut freed_buffers = vec![];
 
-        for child_inf in self_node.get_children2() {
-            let node = sg.get_node(child_inf.id).unwrap();
-            //debug!(target: "ui::win", "Window::draw() calling draw() for node '{}':{}", node.name, node.id);
-
-            let dcs = match &node.pimpl {
-                Pimpl::RenderLayer(layer) => layer.draw(sg, &parent_rect).await,
-                _ => {
-                    error!(target: "ui::win", "unhandled pimpl type");
-                    continue
-                }
+        for child_id in get_child_nodes_ordered(&sg, self.node_id) {
+            let node = sg.get_node(child_id).unwrap();
+            let obj = get_ui_object(node);
+            let Some(mut draw_update) = obj.draw(sg, &parent_rect).await else {
+                error!(target: "ui::layer", "draw() of {node:?} failed");
+                continue
             };
-            let Some(mut draw_update) = dcs else { continue };
+
             draw_calls.append(&mut draw_update.draw_calls);
             child_calls.push(draw_update.key);
             freed_textures.append(&mut draw_update.freed_textures);