Jelajahi Sumber

wallet: properly handle app cleanup (accidental cargo fmt so just check main.rs)

darkfi 2 tahun lalu
induk
melakukan
a3db035ffa

+ 58 - 108
bin/darkwallet/src/chatapp.rs

@@ -1,29 +1,27 @@
 use darkfi_serial::{Decodable, Encodable, SerialDecodable, SerialEncodable};
 use std::sync::mpsc;
 
-use crate::{expr::Op,
-error::Result,
-gfx::Rectangle,
+use crate::{
+    error::Result,
+    expr::Op,
+    gfx::Rectangle,
     prop::{Property, PropertySubType, PropertyType},
     res::{ResourceId, ResourceManager},
     scene::{
-        MethodResponseFn, SceneGraph, SceneGraphPtr, SceneNode, SceneNodeId, SceneNodeInfo,
-        SceneNodeType, Pimpl
-    }};
+        MethodResponseFn, Pimpl, SceneGraph, SceneGraphPtr, SceneNode, SceneNodeId, SceneNodeInfo,
+        SceneNodeType,
+    },
+};
 
 struct Buffer {
     verts: Vec<u8>,
     faces: Vec<u8>,
-    verts_len: u32
+    verts_len: u32,
 }
 
 impl Buffer {
     pub fn new() -> Self {
-        Self {
-            verts: vec![],
-            faces: vec![],
-            verts_len: 0
-        }
+        Self { verts: vec![], faces: vec![], verts_len: 0 }
     }
 
     fn vertex(&mut self, x: f32, y: f32, r: f32, g: f32, b: f32, a: f32, u: f32, v: f32) {
@@ -58,18 +56,25 @@ impl Buffer {
         let b = color[2];
         let a = color[3];
 
-        self.vertex(x,     y,     r, g, b, a, 0., 0.);
-        self.vertex(x + w, y,     r, g, b, a, 1., 0.);
-        self.vertex(x,     y + h, r, g, b, a, 0., 1.);
+        self.vertex(x, y, r, g, b, a, 0., 0.);
+        self.vertex(x + w, y, r, g, b, a, 1., 0.);
+        self.vertex(x, y + h, r, g, b, a, 0., 1.);
         self.vertex(x + w, y + h, r, g, b, a, 1., 1.);
 
         self.face(k, k + 2, k + 1);
         self.face(k + 1, k + 2, k + 3);
     }
 
-    pub fn draw_outline(&mut self, rect: Rectangle<f32>, color: [f32; 4], pad: f32, layer_w: f32, layer_h: f32) {
-        let pad_x = pad/layer_w;
-        let pad_y = pad/layer_h;
+    pub fn draw_outline(
+        &mut self,
+        rect: Rectangle<f32>,
+        color: [f32; 4],
+        pad: f32,
+        layer_w: f32,
+        layer_h: f32,
+    ) {
+        let pad_x = pad / layer_w;
+        let pad_y = pad / layer_h;
 
         let x = rect.x;
         let y = rect.y;
@@ -77,23 +82,15 @@ impl Buffer {
         let h = rect.h;
 
         // left
-        self.draw_box(Rectangle {
-            x, y, w: pad_x, h
-        }, color);
+        self.draw_box(Rectangle { x, y, w: pad_x, h }, color);
         // top
-        self.draw_box(Rectangle {
-            x, y, w, h: pad_y
-        }, color);
+        self.draw_box(Rectangle { x, y, w, h: pad_y }, color);
         // right
         let rhs = x + w;
-        self.draw_box(Rectangle {
-            x: rhs - pad_x, y, w: pad_x, h
-        }, color);
+        self.draw_box(Rectangle { x: rhs - pad_x, y, w: pad_x, h }, color);
         // bottom
         let bhs = y + h;
-        self.draw_box(Rectangle {
-            x, y: bhs - pad_y, w, h: pad_y
-        }, color);
+        self.draw_box(Rectangle { x, y: bhs - pad_y, w, h: pad_y }, color);
     }
 }
 
@@ -259,15 +256,9 @@ pub fn setup(sg: &mut SceneGraph) {
     let prop = node.get_property("rect").unwrap();
     prop.set_u32(0, 0).unwrap();
     prop.set_u32(1, 0).unwrap();
-    let code = vec![Op::Float32ToUint32((
-            Box::new(Op::LoadVar("sw".to_string()))
-            ))
-        ];
+    let code = vec![Op::Float32ToUint32((Box::new(Op::LoadVar("sw".to_string()))))];
     prop.set_expr(2, code).unwrap();
-    let code = vec![Op::Float32ToUint32((
-            Box::new(Op::LoadVar("sh".to_string()))
-            ))
-        ];
+    let code = vec![Op::Float32ToUint32((Box::new(Op::LoadVar("sh".to_string()))))];
     prop.set_expr(3, code).unwrap();
 
     // Make the black background
@@ -278,13 +269,9 @@ pub fn setup(sg: &mut SceneGraph) {
     let prop = node.get_property("rect").unwrap();
     prop.set_f32(0, 0.).unwrap();
     prop.set_f32(1, 0.).unwrap();
-    let code = vec![
-            Op::LoadVar("lw".to_string())
-        ];
+    let code = vec![Op::LoadVar("lw".to_string())];
     prop.set_expr(2, code).unwrap();
-    let code = vec![
-            Op::LoadVar("lh".to_string())
-        ];
+    let code = vec![Op::LoadVar("lh".to_string())];
     prop.set_expr(3, code).unwrap();
 
     let prop = node.get_property("data").unwrap();
@@ -301,23 +288,11 @@ pub fn setup(sg: &mut SceneGraph) {
 
     let prop = node.get_property("rect").unwrap();
     prop.set_f32(0, 140.).unwrap();
-    let code = vec![
-        Op::Sub((
-            Box::new(Op::LoadVar("lh".to_string())),
-            Box::new(
-                Op::ConstFloat32(60.)
-            )
-        ))
-    ];
+    let code =
+        vec![Op::Sub((Box::new(Op::LoadVar("lh".to_string())), Box::new(Op::ConstFloat32(60.))))];
     prop.set_expr(1, code).unwrap();
-    let code = vec![
-        Op::Sub((
-            Box::new(Op::LoadVar("lw".to_string())),
-            Box::new(
-                Op::ConstFloat32(140.)
-            )
-        ))
-    ];
+    let code =
+        vec![Op::Sub((Box::new(Op::LoadVar("lw".to_string())), Box::new(Op::ConstFloat32(140.))))];
     prop.set_expr(2, code).unwrap();
     prop.set_f32(3, 60.).unwrap();
 
@@ -328,8 +303,12 @@ pub fn setup(sg: &mut SceneGraph) {
     // FIXME: layer dim is passed here manually!
     // we should just use separate objs
     buff.draw_outline(
-        Rectangle { x: 0., y: 0., w: 1., h: 1. }, [0.22, 0.22, 0.22, 1.],
-        1., 1000., 50.);
+        Rectangle { x: 0., y: 0., w: 1., h: 1. },
+        [0.22, 0.22, 0.22, 1.],
+        1.,
+        1000.,
+        50.,
+    );
     prop.set_buf(0, buff.verts).unwrap();
     prop.set_buf(1, buff.faces).unwrap();
 
@@ -338,14 +317,8 @@ pub fn setup(sg: &mut SceneGraph) {
     let node = sg.get_node(node_id).unwrap();
     let prop = node.get_property("rect").unwrap();
     prop.set_f32(0, 0.).unwrap();
-    let code = vec![
-        Op::Sub((
-            Box::new(Op::LoadVar("lh".to_string())),
-            Box::new(
-                Op::ConstFloat32(60.)
-            )
-        ))
-    ];
+    let code =
+        vec![Op::Sub((Box::new(Op::LoadVar("lh".to_string())), Box::new(Op::ConstFloat32(60.))))];
     prop.set_expr(1, code).unwrap();
     prop.set_f32(2, 130.).unwrap();
     prop.set_f32(3, 60.).unwrap();
@@ -356,8 +329,12 @@ pub fn setup(sg: &mut SceneGraph) {
     // FIXME: layer dim is passed here manually!
     // we should just use separate objs
     buff.draw_outline(
-        Rectangle { x: 0., y: 0., w: 1., h: 1. }, [0., 0.13, 0.08, 1.],
-        1., 1000., 50.);
+        Rectangle { x: 0., y: 0., w: 1., h: 1. },
+        [0., 0.13, 0.08, 1.],
+        1.,
+        1000.,
+        50.,
+    );
     prop.set_buf(0, buff.verts).unwrap();
     prop.set_buf(1, buff.faces).unwrap();
 
@@ -366,14 +343,8 @@ pub fn setup(sg: &mut SceneGraph) {
     let node = sg.get_node(node_id).unwrap();
     let prop = node.get_property("rect").unwrap();
     prop.set_f32(0, 20.).unwrap();
-    let code = vec![
-        Op::Sub((
-            Box::new(Op::LoadVar("lh".to_string())),
-            Box::new(
-                Op::ConstFloat32(60.)
-            )
-        ))
-    ];
+    let code =
+        vec![Op::Sub((Box::new(Op::LoadVar("lh".to_string())), Box::new(Op::ConstFloat32(60.))))];
     prop.set_expr(1, code).unwrap();
     prop.set_f32(2, 120.).unwrap();
     prop.set_f32(3, 60.).unwrap();
@@ -393,23 +364,11 @@ pub fn setup(sg: &mut SceneGraph) {
     node.set_property_bool("is_active", true).unwrap();
     let prop = node.get_property("rect").unwrap();
     prop.set_f32(0, 150.).unwrap();
-    let code = vec![
-        Op::Sub((
-            Box::new(Op::LoadVar("lh".to_string())),
-            Box::new(
-                Op::ConstFloat32(60.)
-            )
-        ))
-    ];
+    let code =
+        vec![Op::Sub((Box::new(Op::LoadVar("lh".to_string())), Box::new(Op::ConstFloat32(60.))))];
     prop.set_expr(1, code).unwrap();
-    let code = vec![
-        Op::Sub((
-            Box::new(Op::LoadVar("lw".to_string())),
-            Box::new(
-                Op::ConstFloat32(120.)
-            )
-        ))
-    ];
+    let code =
+        vec![Op::Sub((Box::new(Op::LoadVar("lw".to_string())), Box::new(Op::ConstFloat32(120.))))];
     prop.set_expr(2, code).unwrap();
     prop.set_f32(3, 60.).unwrap();
     node.set_property_f32("baseline", 40.).unwrap();
@@ -453,18 +412,10 @@ pub fn setup(sg: &mut SceneGraph) {
     let prop = node.get_property("rect").unwrap();
     prop.set_f32(0, 0.).unwrap();
     prop.set_f32(1, 0.).unwrap();
-    let code = vec![
-        Op::LoadVar("lw".to_string())
-    ];
+    let code = vec![Op::LoadVar("lw".to_string())];
     prop.set_expr(2, code).unwrap();
-    let code = vec![
-        Op::Sub((
-            Box::new(Op::LoadVar("lh".to_string())),
-            Box::new(
-                Op::ConstFloat32(50.)
-            )
-        ))
-    ];
+    let code =
+        vec![Op::Sub((Box::new(Op::LoadVar("lh".to_string())), Box::new(Op::ConstFloat32(50.))))];
     prop.set_expr(3, code).unwrap();
     node.set_property_u32("z_index", 1).unwrap();
 
@@ -475,4 +426,3 @@ pub fn setup(sg: &mut SceneGraph) {
     let layer_node = sg.get_node(layer_node_id).unwrap();
     layer_node.set_property_bool("is_visible", true).unwrap();
 }
-

+ 75 - 50
bin/darkwallet/src/chatview.rs

@@ -1,19 +1,35 @@
 use atomic_float::AtomicF32;
-use miniquad::{KeyMods, UniformType, MouseButton, window, TextureId};
+use darkfi_serial::Decodable;
 use log::debug;
+use miniquad::{window, KeyMods, MouseButton, TextureId, UniformType};
 use std::{
     collections::HashMap,
-    path::Path,
     fs::File,
-    io::{BufRead, BufReader, Cursor}, sync::{Arc, atomic::{AtomicBool, Ordering}, Mutex}, time::{Instant, Duration}};
-use darkfi_serial::Decodable;
-
-use crate::{error::{Error, Result}, prop::{
-    PropertyBool, PropertyFloat32, PropertyUint32, PropertyStr, PropertyColor,
-    Property}, scene::{SceneGraph, SceneNode, SceneNodeId, Pimpl, Slot}, gfx::{Rectangle, RenderContext, COLOR_WHITE, COLOR_BLUE, COLOR_RED, COLOR_GREEN, FreetypeFace, COLOR_DARKGREY, Point}, text::{Glyph, TextShaper}, keysym::{MouseButtonAsU8, KeyCodeAsU16}};
+    io::{BufRead, BufReader, Cursor},
+    path::Path,
+    sync::{
+        atomic::{AtomicBool, Ordering},
+        Arc, Mutex,
+    },
+    time::{Duration, Instant},
+};
+
+use crate::{
+    error::{Error, Result},
+    gfx::{
+        FreetypeFace, Point, Rectangle, RenderContext, COLOR_BLUE, COLOR_DARKGREY, COLOR_GREEN,
+        COLOR_RED, COLOR_WHITE,
+    },
+    keysym::{KeyCodeAsU16, MouseButtonAsU8},
+    prop::{Property, PropertyBool, PropertyColor, PropertyFloat32, PropertyStr, PropertyUint32},
+    scene::{Pimpl, SceneGraph, SceneNode, SceneNodeId, Slot},
+    text::{Glyph, TextShaper},
+};
 
 fn read_lines<P>(filename: P) -> Vec<String>
-where P: AsRef<Path>, {
+where
+    P: AsRef<Path>,
+{
     //let file = File::open(filename).unwrap();
     //BufReader::new(file).lines().map(|l| l.unwrap()).collect()
     // Just so we can package for android easily
@@ -38,20 +54,22 @@ pub struct ChatView {
 }
 
 impl ChatView {
-    pub fn new(scene_graph: &mut SceneGraph, node_id: SceneNodeId, font_faces: Vec<FreetypeFace>) -> Result<Pimpl> {
+    pub fn new(
+        scene_graph: &mut SceneGraph,
+        node_id: SceneNodeId,
+        font_faces: Vec<FreetypeFace>,
+    ) -> Result<Pimpl> {
         let node = scene_graph.get_node(node_id).unwrap();
         let node_name = node.name.clone();
         let debug = PropertyBool::wrap(node, "debug", 0)?;
 
-        let text_shaper = TextShaper {
-            font_faces
-        };
-        
+        let text_shaper = TextShaper { font_faces };
+
         let lines = read_lines("chat.txt");
         let mut glyph_lines = vec![];
         glyph_lines.resize(lines.len(), vec![]);
 
-        let self_ = Arc::new(Self{
+        let self_ = Arc::new(Self {
             node_name: node_name.clone(),
             debug,
             world_rect: Mutex::new(Rectangle { x: 0., y: 0., w: 0., h: 0. }),
@@ -97,10 +115,8 @@ impl ChatView {
         };
         */
 
-        let mouse_node = 
-            scene_graph
-            .lookup_node_mut("/window/input/mouse")
-            .expect("no mouse attached!");
+        let mouse_node =
+            scene_graph.lookup_node_mut("/window/input/mouse").expect("no mouse attached!");
         //mouse_node.register("wheel", slot_wheel);
         //mouse_node.register("move", slot_move);
 
@@ -108,7 +124,12 @@ impl ChatView {
         Ok(Pimpl::ChatView(self_))
     }
 
-    pub fn render<'a>(&self, render: &mut RenderContext<'a>, node_id: SceneNodeId, layer_rect: &Rectangle<f32>) -> Result<()> {
+    pub fn render<'a>(
+        &self,
+        render: &mut RenderContext<'a>,
+        node_id: SceneNodeId,
+        layer_rect: &Rectangle<f32>,
+    ) -> Result<()> {
         let debug = self.debug.get();
 
         let node = render.scene_graph.get_node(node_id).unwrap();
@@ -140,19 +161,11 @@ impl ChatView {
         render.ctx.apply_uniforms_from_bytes(uniforms_data.as_ptr(), uniforms_data.len());
 
         // Used for scaling the font size
-        let window = render
-            .scene_graph
-            .lookup_node("/window")
-            .expect("no window attached!");
+        let window = render.scene_graph.lookup_node("/window").expect("no window attached!");
         let window_scale = window.get_property_f32("scale")?;
         let font_size = window_scale * 20.;
 
-        let bound = Rectangle {
-            x: 0.,
-            y: 0.,
-            w: rect.w,
-            h: rect.h,
-        };
+        let bound = Rectangle { x: 0., y: 0., w: rect.w, h: rect.h };
 
         let glyph_lines = &mut self.glyph_lines.lock().unwrap();
         let atlas = &mut self.atlas.lock().unwrap();
@@ -176,7 +189,7 @@ impl ChatView {
                 continue
             };
 
-            let linespacing = window_scale*30.;
+            let linespacing = window_scale * 30.;
             let off_y = linespacing * i as f32 + scroll;
             if off_y + linespacing < 0. || off_y - linespacing > rect.h {
                 continue;
@@ -187,7 +200,8 @@ impl ChatView {
             }
 
             let times_color = [0.4, 0.4, 0.4, 1.];
-            let times_color_u8 = [(255. * 0.4) as u8, (255. * 0.4) as u8, (255. * 0.4) as u8, (255. * 1.) as u8];
+            let times_color_u8 =
+                [(255. * 0.4) as u8, (255. * 0.4) as u8, (255. * 0.4) as u8, (255. * 1.) as u8];
             let glyphs_time = self.text_shaper.shape(time.to_string(), font_size, times_color);
             let mut rhs = 0.;
             for glyph in glyphs_time {
@@ -195,12 +209,16 @@ impl ChatView {
                 pos.y += off_y;
                 rhs = pos.x + pos.w;
 
-                assert_eq!(glyph.bmp.len() as u16, glyph.bmp_width*glyph.bmp_height*4);
+                assert_eq!(glyph.bmp.len() as u16, glyph.bmp_width * glyph.bmp_height * 4);
                 //debug!("gly {} {}", glyph.substr, glyph.bmp.len());
                 let texture = if atlas.contains_key(&(glyph.id, times_color_u8.clone())) {
                     *atlas.get(&(glyph.id, times_color_u8.clone())).unwrap()
                 } else {
-                    let texture = render.ctx.new_texture_from_rgba8(glyph.bmp_width, glyph.bmp_height, &glyph.bmp);
+                    let texture = render.ctx.new_texture_from_rgba8(
+                        glyph.bmp_width,
+                        glyph.bmp_height,
+                        &glyph.bmp,
+                    );
                     atlas.insert((glyph.id, times_color_u8.clone()), texture);
                     texture
                 };
@@ -218,38 +236,42 @@ impl ChatView {
                 [0.84, 0.48, 1.00, 1.],
                 [1.00, 0.61, 0.94, 1.],
                 [1.00, 0.36, 0.48, 1.],
-                [1.00, 0.30, 0.00, 1.]
+                [1.00, 0.30, 0.00, 1.],
             ];
             let nick_colors_u8 = [
                 [(255. * 0.00) as u8, (255. * 0.94) as u8, (255. * 1.00) as u8, (255. * 1.) as u8],
                 [(255. * 0.36) as u8, (255. * 1.00) as u8, (255. * 0.69) as u8, (255. * 1.) as u8],
-                [(255. * 0.29) as u8, (255. * 1.00) as u8, (255. * 0.45) as u8, (255. * 1. ) as u8],
-                [(255. * 0.00) as u8, (255. * 0.73) as u8, (255. * 0.38) as u8, (255. * 1. ) as u8],
-                [(255. * 0.21) as u8, (255. * 0.67) as u8, (255. * 0.67) as u8, (255. * 1. ) as u8],
-                [(255. * 0.56) as u8, (255. * 0.61) as u8, (255. * 1.00) as u8, (255. * 1. ) as u8],
-                [(255. * 0.84) as u8, (255. * 0.48) as u8, (255. * 1.00) as u8, (255. * 1. ) as u8],
-                [(255. * 1.00) as u8, (255. * 0.61) as u8, (255. * 0.94) as u8, (255. * 1. ) as u8],
-                [(255. * 1.00) as u8, (255. * 0.36) as u8, (255. * 0.48) as u8, (255. * 1. ) as u8],
-                [(255. * 1.00) as u8, (255. * 0.30) as u8, (255. * 0.00) as u8, (255. * 1. ) as u8]
+                [(255. * 0.29) as u8, (255. * 1.00) as u8, (255. * 0.45) as u8, (255. * 1.) as u8],
+                [(255. * 0.00) as u8, (255. * 0.73) as u8, (255. * 0.38) as u8, (255. * 1.) as u8],
+                [(255. * 0.21) as u8, (255. * 0.67) as u8, (255. * 0.67) as u8, (255. * 1.) as u8],
+                [(255. * 0.56) as u8, (255. * 0.61) as u8, (255. * 1.00) as u8, (255. * 1.) as u8],
+                [(255. * 0.84) as u8, (255. * 0.48) as u8, (255. * 1.00) as u8, (255. * 1.) as u8],
+                [(255. * 1.00) as u8, (255. * 0.61) as u8, (255. * 0.94) as u8, (255. * 1.) as u8],
+                [(255. * 1.00) as u8, (255. * 0.36) as u8, (255. * 0.48) as u8, (255. * 1.) as u8],
+                [(255. * 1.00) as u8, (255. * 0.30) as u8, (255. * 0.00) as u8, (255. * 1.) as u8],
             ];
 
             let nick_color = nick_colors[nick.len() % nick_colors.len()];
             let nick_color_u8 = nick_colors_u8[nick.len() % nick_colors.len()];
             let glyphs_nick = self.text_shaper.shape(nick.to_string(), font_size, nick_color);
-            let off_x = rhs + window_scale*20.;
+            let off_x = rhs + window_scale * 20.;
             for glyph in glyphs_nick {
                 let mut pos = glyph.pos.clone();
                 pos.x += off_x;
                 pos.y += off_y;
                 rhs = pos.x + pos.w;
 
-                assert_eq!(glyph.bmp.len() as u16, glyph.bmp_width*glyph.bmp_height*4);
+                assert_eq!(glyph.bmp.len() as u16, glyph.bmp_width * glyph.bmp_height * 4);
                 //debug!("gly {} {}", glyph.substr, glyph.bmp.len());
                 //let texture = render.ctx.new_texture_from_rgba8(glyph.bmp_width, glyph.bmp_height, &glyph.bmp);
                 let texture = if atlas.contains_key(&(glyph.id, nick_color_u8.clone())) {
                     *atlas.get(&(glyph.id, nick_color_u8.clone())).unwrap()
                 } else {
-                    let texture = render.ctx.new_texture_from_rgba8(glyph.bmp_width, glyph.bmp_height, &glyph.bmp);
+                    let texture = render.ctx.new_texture_from_rgba8(
+                        glyph.bmp_width,
+                        glyph.bmp_height,
+                        &glyph.bmp,
+                    );
                     atlas.insert((glyph.id, nick_color_u8.clone()), texture);
                     texture
                 };
@@ -257,19 +279,23 @@ impl ChatView {
                 //render.ctx.delete_texture(texture);
             }
 
-            let off_x = rhs + window_scale*20.;
+            let off_x = rhs + window_scale * 20.;
             for glyph in glyph_line {
                 let mut pos = glyph.pos.clone();
                 pos.x += off_x;
                 pos.y += off_y;
 
-                assert_eq!(glyph.bmp.len() as u16, glyph.bmp_width*glyph.bmp_height*4);
+                assert_eq!(glyph.bmp.len() as u16, glyph.bmp_width * glyph.bmp_height * 4);
                 //debug!("gly {} {}", glyph.substr, glyph.bmp.len());
                 //let texture = render.ctx.new_texture_from_rgba8(glyph.bmp_width, glyph.bmp_height, &glyph.bmp);
                 let texture = if atlas.contains_key(&(glyph.id, [255, 255, 255, 255])) {
                     *atlas.get(&(glyph.id, [255, 255, 255, 255])).unwrap()
                 } else {
-                    let texture = render.ctx.new_texture_from_rgba8(glyph.bmp_width, glyph.bmp_height, &glyph.bmp);
+                    let texture = render.ctx.new_texture_from_rgba8(
+                        glyph.bmp_width,
+                        glyph.bmp_height,
+                        &glyph.bmp,
+                    );
                     atlas.insert((glyph.id, [255, 255, 255, 255]), texture);
                     texture
                 };
@@ -298,4 +324,3 @@ impl ChatView {
         //println!("{}", y);
     }
 }
-

+ 82 - 74
bin/darkwallet/src/editbox.rs

@@ -1,14 +1,28 @@
-use miniquad::{KeyMods, UniformType, MouseButton, window, TextureId};
+use darkfi_serial::Decodable;
+use freetype as ft;
 use log::{debug, info};
+use miniquad::{window, KeyMods, MouseButton, TextureId, UniformType};
 use std::{
     collections::HashMap,
-    io::Cursor, sync::{Arc, atomic::{AtomicBool, Ordering}, Mutex}, time::{Instant, Duration}};
-use darkfi_serial::Decodable;
-use freetype as ft;
-
-use crate::{error::{Error, Result}, prop::{
-    PropertyBool, PropertyFloat32, PropertyUint32, PropertyStr, PropertyColor,
-    Property}, scene::{SceneGraph, SceneNode, SceneNodeId, Pimpl, Slot}, gfx::{Rectangle, RenderContext, COLOR_WHITE, COLOR_BLUE, COLOR_RED, COLOR_GREEN, FreetypeFace, COLOR_DARKGREY, Point}, text::{Glyph, TextShaper}, keysym::{MouseButtonAsU8, KeyCodeAsU16}};
+    io::Cursor,
+    sync::{
+        atomic::{AtomicBool, Ordering},
+        Arc, Mutex,
+    },
+    time::{Duration, Instant},
+};
+
+use crate::{
+    error::{Error, Result},
+    gfx::{
+        FreetypeFace, Point, Rectangle, RenderContext, COLOR_BLUE, COLOR_DARKGREY, COLOR_GREEN,
+        COLOR_RED, COLOR_WHITE,
+    },
+    keysym::{KeyCodeAsU16, MouseButtonAsU8},
+    prop::{Property, PropertyBool, PropertyColor, PropertyFloat32, PropertyStr, PropertyUint32},
+    scene::{Pimpl, SceneGraph, SceneNode, SceneNodeId, Slot},
+    text::{Glyph, TextShaper},
+};
 
 const CURSOR_WIDTH: f32 = 4.;
 
@@ -24,11 +38,7 @@ struct PressedKeysSmoothRepeat {
 
 impl PressedKeysSmoothRepeat {
     fn new(start_delay: u32, step_time: u32) -> Self {
-        Self {
-            pressed_keys: HashMap::new(),
-            start_delay,
-            step_time
-        }
+        Self { pressed_keys: HashMap::new(), start_delay, step_time }
     }
 
     fn key_down(&mut self, key: &str, repeat: bool) -> u32 {
@@ -57,10 +67,7 @@ struct RepeatingKeyTimer {
 
 impl RepeatingKeyTimer {
     fn new() -> Self {
-        Self {
-            start: Instant::now(),
-            actions: 0
-        }
+        Self { start: Instant::now(), actions: 0 }
     }
 
     fn update(&mut self, start_delay: u32, step_time: u32) -> u32 {
@@ -102,7 +109,11 @@ pub struct EditBox {
 }
 
 impl EditBox {
-    pub fn new(scene_graph: &mut SceneGraph, node_id: SceneNodeId, font_faces: Vec<FreetypeFace>) -> Result<Pimpl> {
+    pub fn new(
+        scene_graph: &mut SceneGraph,
+        node_id: SceneNodeId,
+        font_faces: Vec<FreetypeFace>,
+    ) -> Result<Pimpl> {
         let node = scene_graph.get_node(node_id).unwrap();
         let node_name = node.name.clone();
         let is_active = PropertyBool::wrap(node, "is_active", 0)?;
@@ -117,20 +128,15 @@ impl EditBox {
         let cursor_color = PropertyColor::wrap(node, "cursor_color")?;
         let hi_bg_color = PropertyColor::wrap(node, "hi_bg_color")?;
 
-        let text_shaper = TextShaper {
-            font_faces
-        };
+        let text_shaper = TextShaper { font_faces };
 
         // TODO: catch window resize event and regen glyphs
         // Used for scaling the font size
-        let window_node = 
-            scene_graph
-            .lookup_node("/window")
-            .expect("no window attached!");
+        let window_node = scene_graph.lookup_node("/window").expect("no window attached!");
         let window_scale = window_node.get_property_f32("scale")?;
         let screen_size = window_node.get_property("screen_size").ok_or(Error::PropertyNotFound)?;
 
-        let self_ = Arc::new(Self{
+        let self_ = Arc::new(Self {
             node_name: node_name.clone(),
             is_active,
             debug,
@@ -195,7 +201,7 @@ impl EditBox {
             }),
         };
 
-        let keyb_node = 
+        let keyb_node =
             scene_graph
             .lookup_node_mut("/window/input/keyboard")
             .expect("no keyboard attached!");
@@ -249,7 +255,7 @@ impl EditBox {
             }),
         };
 
-        let mouse_node = 
+        let mouse_node =
             scene_graph
             .lookup_node_mut("/window/input/mouse")
             .expect("no mouse attached!");
@@ -273,17 +279,19 @@ impl EditBox {
         };
         */
 
-        let window_node = 
-            scene_graph
-            .lookup_node_mut("/window")
-            .expect("no window attached!");
+        let window_node = scene_graph.lookup_node_mut("/window").expect("no window attached!");
         //window_node.register("resize", slot_resize).unwrap();
 
         // Save any properties we use
         Ok(Pimpl::EditBox(self_))
     }
 
-    pub fn render<'a>(&self, render: &mut RenderContext<'a>, node_id: SceneNodeId, layer_rect: &Rectangle<f32>) -> Result<()> {
+    pub fn render<'a>(
+        &self,
+        render: &mut RenderContext<'a>,
+        node_id: SceneNodeId,
+        layer_rect: &Rectangle<f32>,
+    ) -> Result<()> {
         let node = render.scene_graph.get_node(node_id).unwrap();
 
         let rect = RenderContext::get_dim(node, layer_rect)?;
@@ -335,12 +343,7 @@ impl EditBox {
             self.render_selected(render, &rect, glyphs)?;
         }
 
-        let bound = Rectangle {
-            x: 0.,
-            y: 0.,
-            w: rect.w,
-            h: rect.h,
-        };
+        let bound = Rectangle { x: 0., y: 0., w: rect.w, h: rect.h };
 
         let mut rhs = 0.;
         for (glyph_idx, glyph) in glyphs.iter().enumerate() {
@@ -349,13 +352,17 @@ impl EditBox {
             let x2 = x1 + glyph.pos.w;
             let y2 = y1 + glyph.pos.h;
 
-                let texture = if atlas.contains_key(&glyph.id) {
-                    *atlas.get(&glyph.id).unwrap()
-                } else {
-                    let texture = render.ctx.new_texture_from_rgba8(glyph.bmp_width, glyph.bmp_height, &glyph.bmp);
-                    atlas.insert(glyph.id, texture);
-                    texture
-                };
+            let texture = if atlas.contains_key(&glyph.id) {
+                *atlas.get(&glyph.id).unwrap()
+            } else {
+                let texture = render.ctx.new_texture_from_rgba8(
+                    glyph.bmp_width,
+                    glyph.bmp_height,
+                    &glyph.bmp,
+                );
+                atlas.insert(glyph.id, texture);
+                texture
+            };
             //let texture = render.ctx.new_texture_from_rgba8(glyph.bmp_width, glyph.bmp_height, &glyph.bmp);
             render.render_clipped_box_with_texture(&bound, x1, y1, x2, y2, COLOR_WHITE, texture);
             //render.render_box_with_texture(x1, y1, x2, y2, COLOR_WHITE, texture);
@@ -380,11 +387,7 @@ impl EditBox {
         }
 
         if debug {
-            let outline_color = if self.is_active.get() {
-                COLOR_GREEN
-            } else {
-                COLOR_DARKGREY
-            };
+            let outline_color = if self.is_active.get() { COLOR_GREEN } else { COLOR_DARKGREY };
             // Baseline
             //render.hline(0., rhs, 0., COLOR_RED, 1.);
             render.outline(0., 0., rect.w, rect.h, outline_color, 1.);
@@ -393,7 +396,12 @@ impl EditBox {
         Ok(())
     }
 
-    pub fn render_selected<'a>(&self, render: &mut RenderContext<'a>, rect: &Rectangle<f32>, glyphs: &Vec<Glyph>) -> Result<()> {
+    pub fn render_selected<'a>(
+        &self,
+        render: &mut RenderContext<'a>,
+        rect: &Rectangle<f32>,
+        glyphs: &Vec<Glyph>,
+    ) -> Result<()> {
         let start = self.selected.get_u32(0)? as usize;
         let end = self.selected.get_u32(1)? as usize;
 
@@ -457,8 +465,10 @@ impl EditBox {
             }
             text.push_str(&substr);
         }
-        debug!("EditBox(\"{}\")::delete_highlighted() text=\"{}\", cursor_pos={}",
-               self.node_name, text, sel_start);
+        debug!(
+            "EditBox(\"{}\")::delete_highlighted() text=\"{}\", cursor_pos={}",
+            self.node_name, text, sel_start
+        );
         self.text.set(text);
 
         self.selected.set_null(0).unwrap();
@@ -500,8 +510,7 @@ impl EditBox {
         let font_size = self.window_scale * self.font_size.get();
 
         debug!("shape start");
-        let glyphs = self.text_shaper.shape(self.text.get(), font_size,
-                self.text_color.get());
+        let glyphs = self.text_shaper.shape(self.text.get(), font_size, self.text_color.get());
         debug!("shape end");
         if self.cursor_pos.get() > glyphs.len() as u32 {
             self.cursor_pos.set(glyphs.len() as u32);
@@ -539,8 +548,10 @@ impl EditBox {
 
                 if cursor_pos > 0 {
                     cursor_pos -= 1;
-                    debug!("EditBox(\"{}\")::key_down(Left) cursor_pos={}",
-                           self.node_name, cursor_pos);
+                    debug!(
+                        "EditBox(\"{}\")::key_down(Left) cursor_pos={}",
+                        self.node_name, cursor_pos
+                    );
                     self.cursor_pos.set(cursor_pos);
                 }
 
@@ -564,8 +575,10 @@ impl EditBox {
                 let glyphs_len = self.glyphs.lock().unwrap().len() as u32;
                 if cursor_pos < glyphs_len {
                     cursor_pos += 1;
-                    debug!("EditBox(\"{}\")::key_down(Right) cursor_pos={}",
-                           self.node_name, cursor_pos);
+                    debug!(
+                        "EditBox(\"{}\")::key_down(Right) cursor_pos={}",
+                        self.node_name, cursor_pos
+                    );
                     self.cursor_pos.set(cursor_pos);
                 }
 
@@ -651,10 +664,11 @@ impl EditBox {
 
     fn insert_char(&self, key: &str, mods: &KeyMods) {
         // First filter for only single digit keys
-        let allowed_keys =
-        ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
-         " ", ":", ";", "'", "-", ".", "/", "=", "(", "\\", ")", "`",
-         "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ];
+        let allowed_keys = [
+            "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q",
+            "R", "S", "T", "U", "V", "W", "X", "Y", "Z", " ", ":", ";", "'", "-", ".", "/", "=",
+            "(", "\\", ")", "`", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
+        ];
         if !allowed_keys.contains(&key) {
             return
         }
@@ -663,11 +677,7 @@ impl EditBox {
         //let ch = key.chars().next().unwrap();
         // if !self.allowed_chars.chars().any(|c| c == ch) { return }
 
-        let key = if mods.shift {
-            key.to_string()
-        } else {
-            key.to_lowercase()
-        };
+        let key = if mods.shift { key.to_string() } else { key.to_lowercase() };
 
         self.insert_text(key);
     }
@@ -739,7 +749,7 @@ impl EditBox {
 
             let cpos = match self.find_closest_glyph_idx(x) {
                 MouseClickGlyph::Pos(cpos) => cpos,
-                _ => panic!("shouldn't be possible to reach here!")
+                _ => panic!("shouldn't be possible to reach here!"),
             };
 
             // set cursor pos
@@ -832,13 +842,11 @@ impl EditBox {
         MouseClickGlyph::Pos(cpos)
     }
 
-    fn window_resize(self: Arc<Self>, w: f32, h: f32) {
-    }
+    fn window_resize(self: Arc<Self>, w: f32, h: f32) {}
 }
 
 enum MouseClickGlyph {
     Lhs,
     Pos(u32),
-    Rhs(u32)
+    Rhs(u32),
 }
-

+ 55 - 55
bin/darkwallet/src/gfx.rs

@@ -17,16 +17,15 @@ use std::{
 };
 
 use crate::{
+    chatview, editbox,
     error::{Error, Result},
-    chatview,
-    editbox,
     expr::{SExprMachine, SExprVal},
     keysym::{KeyCodeAsStr, MouseButtonAsU8},
     prop::{Property, PropertySubType, PropertyType},
     res::{ResourceId, ResourceManager},
     scene::{
-        MethodResponseFn, SceneGraph, SceneGraphPtr, SceneNode, SceneNodeId, SceneNodeInfo,
-        SceneNodeType, Pimpl
+        MethodResponseFn, Pimpl, SceneGraph, SceneGraphPtr, SceneNode, SceneNodeId, SceneNodeInfo,
+        SceneNodeType,
     },
     shader,
 };
@@ -72,14 +71,23 @@ pub struct Point<T> {
 }
 
 #[derive(Debug, Clone)]
-pub struct Rectangle<T: Copy + std::ops::Add<Output=T> + std::ops::Sub<Output=T> + std::cmp::PartialOrd> {
+pub struct Rectangle<
+    T: Copy + std::ops::Add<Output = T> + std::ops::Sub<Output = T> + std::cmp::PartialOrd,
+> {
     pub x: T,
     pub y: T,
     pub w: T,
     pub h: T,
 }
 
-impl<T: Copy + std::ops::Add<Output=T> + std::ops::Sub<Output=T> + std::ops::AddAssign + std::cmp::PartialOrd> Rectangle<T> {
+impl<
+        T: Copy
+            + std::ops::Add<Output = T>
+            + std::ops::Sub<Output = T>
+            + std::ops::AddAssign
+            + std::cmp::PartialOrd,
+    > Rectangle<T>
+{
     fn from_array(arr: [T; 4]) -> Self {
         let mut iter = IntoIter::new(arr);
         Self {
@@ -118,8 +126,10 @@ impl<T: Copy + std::ops::Add<Output=T> + std::ops::Sub<Output=T> + std::ops::Add
     }
 
     pub fn contains(&self, point: &Point<T>) -> bool {
-        self.x < point.x && point.x < self.x + self.w &&
-            self.y < point.y && point.y < self.y + self.h
+        self.x < point.x &&
+            point.x < self.x + self.w &&
+            self.y < point.y &&
+            point.y < self.y + self.h
     }
 }
 
@@ -219,7 +229,7 @@ impl Stage {
             method_recvr,
             method_sender,
             last_draw_time: None,
-            atlas: Mutex::new(HashMap::new())
+            atlas: Mutex::new(HashMap::new()),
         };
         stage.setup_scene_graph_window();
 
@@ -421,11 +431,7 @@ impl Stage {
         Ok(vec![])
     }
 
-    fn method_create_chatview(
-        &mut self,
-        _: SceneNodeId,
-        arg_data: Vec<u8>,
-    ) -> Result<Vec<u8>> {
+    fn method_create_chatview(&mut self, _: SceneNodeId, arg_data: Vec<u8>) -> Result<Vec<u8>> {
         debug!("gfx::create_chatview()");
         let mut cur = Cursor::new(&arg_data);
         let node_id = SceneNodeId::decode(&mut cur).unwrap();
@@ -440,11 +446,7 @@ impl Stage {
         Ok(reply)
     }
 
-    fn method_create_editbox(
-        &mut self,
-        _: SceneNodeId,
-        arg_data: Vec<u8>,
-    ) -> Result<Vec<u8>> {
+    fn method_create_editbox(&mut self, _: SceneNodeId, arg_data: Vec<u8>) -> Result<Vec<u8>> {
         debug!("gfx::create_editbox()");
         let mut cur = Cursor::new(&arg_data);
         let node_id = SceneNodeId::decode(&mut cur).unwrap();
@@ -543,10 +545,7 @@ impl<'a> RenderContext<'a> {
         self.ctx.apply_viewport(view.x, view.y, view.w, view.h);
         self.ctx.apply_scissor_rect(view.x, view.y, view.w, view.h);
 
-        let window = self
-            .scene_graph
-            .lookup_node("/window")
-            .expect("no window attached!");
+        let window = self.scene_graph.lookup_node("/window").expect("no window attached!");
         let window_scale = window.get_property_f32("scale")?;
 
         let rect = Rectangle {
@@ -556,8 +555,12 @@ impl<'a> RenderContext<'a> {
             h: (rect.h as f32) / window_scale,
         };
 
-        let layer_children =
-            layer.get_children(&[SceneNodeType::RenderMesh, SceneNodeType::RenderText, SceneNodeType::EditBox, SceneNodeType::ChatView]);
+        let layer_children = layer.get_children(&[
+            SceneNodeType::RenderMesh,
+            SceneNodeType::RenderText,
+            SceneNodeType::EditBox,
+            SceneNodeType::ChatView,
+        ]);
         let layer_children = self.order_by_z_index(layer_children);
 
         // get the rectangle
@@ -592,7 +595,7 @@ impl<'a> RenderContext<'a> {
                             continue;
                         }
                         Pimpl::ChatView(e) => e.clone(),
-                        _ => panic!("wrong pimpl for editbox")
+                        _ => panic!("wrong pimpl for editbox"),
                     };
                     if let Err(err) = chatview.render(self, child.id, &rect) {
                         error!("error rendering chatview '{}': {}", child.name, err);
@@ -606,7 +609,7 @@ impl<'a> RenderContext<'a> {
                             continue;
                         }
                         Pimpl::EditBox(e) => e.clone(),
-                        _ => panic!("wrong pimpl for editbox")
+                        _ => panic!("wrong pimpl for editbox"),
                     };
                     if let Err(err) = editbox.render(self, child.id, &rect) {
                         error!("error rendering editbox '{}': {}", child.name, err);
@@ -733,9 +736,7 @@ impl<'a> RenderContext<'a> {
         color: Color,
         texture: TextureId,
     ) {
-        let Some(clipped) = bound.clip(&obj) else {
-            return
-        };
+        let Some(clipped) = bound.clip(&obj) else { return };
 
         let x1 = clipped.x;
         let y1 = clipped.y;
@@ -790,18 +791,11 @@ impl<'a> RenderContext<'a> {
         color: Color,
         texture: TextureId,
     ) {
-        let obj = Rectangle {
-            x: x1,
-            y: y1,
-            w: x2 - x1,
-            h: y2 - y1
-        };
+        let obj = Rectangle { x: x1, y: y1, w: x2 - x1, h: y2 - y1 };
         if obj.w == 0. || obj.h == 0. {
             return
         }
-        let Some(clipped) = bound_rect.clip(&obj) else {
-            return
-        };
+        let Some(clipped) = bound_rect.clip(&obj) else { return };
 
         let x1 = clipped.x;
         let y1 = clipped.y;
@@ -948,10 +942,7 @@ impl<'a> RenderContext<'a> {
         self.ctx.apply_uniforms_from_bytes(uniforms_data.as_ptr(), uniforms_data.len());
 
         // Used for scaling the font size
-        let window = self
-            .scene_graph
-            .lookup_node("/window")
-            .expect("no window attached!");
+        let window = self.scene_graph.lookup_node("/window").expect("no window attached!");
         let window_scale = window.get_property_f32("scale")?;
         let font_size = window_scale * font_size;
 
@@ -1049,8 +1040,8 @@ impl<'a> RenderContext<'a> {
                         let mut tdata = vec![];
                         tdata.resize(4 * bmp_width * bmp_height, 0);
                         // Convert from BGRA to RGBA
-                        for i in 0..bmp_width*bmp_height as usize {
-                            let idx = i*4;
+                        for i in 0..bmp_width * bmp_height as usize {
+                            let idx = i * 4;
                             let b = buffer[idx];
                             let g = buffer[idx + 1];
                             let r = buffer[idx + 2];
@@ -1076,7 +1067,7 @@ impl<'a> RenderContext<'a> {
                             .collect();
                         tdata
                     }
-                    _ => panic!("unsupport pixel mode: {:?}", pixel_mode)
+                    _ => panic!("unsupport pixel mode: {:?}", pixel_mode),
                 };
 
                 let (x1, y1, x2, y2) = if face.has_fixed_sizes() {
@@ -1112,16 +1103,23 @@ impl<'a> RenderContext<'a> {
                     (x1, y1, x2, y2)
                 };
 
-                let key = (gid, [
-                    (255. * color_r) as u8,
-                    (255. * color_g) as u8,
-                    (255. * color_b) as u8,
-                    (255. * color_a) as u8,
-                ]);
+                let key = (
+                    gid,
+                    [
+                        (255. * color_r) as u8,
+                        (255. * color_g) as u8,
+                        (255. * color_b) as u8,
+                        (255. * color_a) as u8,
+                    ],
+                );
                 let texture = if self.atlas.contains_key(&key) {
                     *self.atlas.get(&key).unwrap()
                 } else {
-                    let texture = self.ctx.new_texture_from_rgba8(bmp_width as u16, bmp_height as u16, &tdata);
+                    let texture = self.ctx.new_texture_from_rgba8(
+                        bmp_width as u16,
+                        bmp_height as u16,
+                        &tdata,
+                    );
                     self.atlas.insert(key, texture);
                     texture
                 };
@@ -1173,7 +1171,9 @@ impl EventHandler for Stage {
             let res = match event {
                 GraphicsMethodEvent::LoadTexture => self.method_load_texture(node_id, arg_data),
                 GraphicsMethodEvent::DeleteTexture => self.method_delete_texture(node_id, arg_data),
-                GraphicsMethodEvent::CreateChatView => self.method_create_chatview(node_id, arg_data),
+                GraphicsMethodEvent::CreateChatView => {
+                    self.method_create_chatview(node_id, arg_data)
+                }
                 GraphicsMethodEvent::CreateEditBox => self.method_create_editbox(node_id, arg_data),
             };
             response_fn(res);
@@ -1201,7 +1201,7 @@ impl EventHandler for Stage {
             proj,
             textures: &self.textures,
             font_faces: &self.font_faces,
-            atlas
+            atlas,
         };
 
         render_context.render_window();

+ 55 - 44
bin/darkwallet/src/gfx2.rs

@@ -17,9 +17,8 @@ use std::{
 };
 
 use crate::{
+    chatview, editbox,
     error::{Error, Result},
-    chatview,
-    editbox,
     expr::{SExprMachine, SExprVal},
     gfx::Rectangle,
     keysym::{KeyCodeAsStr, MouseButtonAsU8},
@@ -27,8 +26,8 @@ use crate::{
     pubsub::Publisher,
     res::{ResourceId, ResourceManager},
     scene::{
-        MethodResponseFn, SceneGraph, SceneGraphPtr, SceneNode, SceneNodeId, SceneNodeInfo,
-        SceneNodeType, Pimpl
+        MethodResponseFn, Pimpl, SceneGraph, SceneGraphPtr, SceneNode, SceneNodeId, SceneNodeInfo,
+        SceneNodeType,
     },
     shader,
 };
@@ -46,9 +45,7 @@ pub struct RenderApi {
 }
 
 impl RenderApi {
-    pub fn new(
-    method_sendr: mpsc::Sender<GraphicsMethod>,
-    ) -> Arc<Self> {
+    pub fn new(method_sendr: mpsc::Sender<GraphicsMethod>) -> Arc<Self> {
         Arc::new(Self { method_sendr })
     }
 
@@ -125,14 +122,14 @@ pub enum DrawInstruction {
 #[derive(Debug)]
 pub struct DrawCall {
     pub instrs: Vec<DrawInstruction>,
-    pub dcs: Vec<DrawCall>
+    pub dcs: Vec<DrawCall>,
 }
 
 struct RenderContext<'a> {
     ctx: &'a mut Box<dyn RenderingBackend>,
     root_dc: &'a DrawCall,
     uniforms_data: [u8; 128],
-    white_texture: TextureId
+    white_texture: TextureId,
 }
 
 impl<'a> RenderContext<'a> {
@@ -157,16 +154,22 @@ impl<'a> RenderContext<'a> {
                     //debug!("apply_matrix({:?})", model);
                     let data: [u8; 64] = unsafe { std::mem::transmute_copy(model) };
                     self.uniforms_data[64..].copy_from_slice(&data);
-                    self.ctx.apply_uniforms_from_bytes(self.uniforms_data.as_ptr(), self.uniforms_data.len());
+                    self.ctx.apply_uniforms_from_bytes(
+                        self.uniforms_data.as_ptr(),
+                        self.uniforms_data.len(),
+                    );
                 }
                 DrawInstruction::Draw(mesh) => {
                     //debug!("draw(mesh)");
                     let texture = match mesh.texture {
                         Some(texture) => texture,
-                        None => self.white_texture
+                        None => self.white_texture,
+                    };
+                    let bindings = Bindings {
+                        vertex_buffers: vec![mesh.vertex_buffer],
+                        index_buffer: mesh.index_buffer,
+                        images: vec![texture],
                     };
-                    let bindings =
-                        Bindings { vertex_buffers: vec![mesh.vertex_buffer], index_buffer: mesh.index_buffer, images: vec![texture] };
                     self.ctx.apply_bindings(&bindings);
                     self.ctx.draw(0, mesh.num_elements, 1);
                 }
@@ -203,14 +206,14 @@ struct Stage {
     last_draw_time: Option<Instant>,
 
     method_recvr: mpsc::Receiver<GraphicsMethod>,
-    event_pub: Arc<Publisher<GraphicsEvent>>,
+    event_pub: async_channel::Sender<GraphicsEvent>,
 }
 
 impl Stage {
     pub fn new(
-    method_recvr: mpsc::Receiver<GraphicsMethod>,
-    event_pub: Arc<Publisher<GraphicsEvent>>,
-        ) -> Self {
+        method_recvr: mpsc::Receiver<GraphicsMethod>,
+        event_pub: async_channel::Sender<GraphicsEvent>,
+    ) -> Self {
         let mut ctx: Box<dyn RenderingBackend> = window::new_rendering_backend();
 
         let white_texture = ctx.new_texture_from_rgba8(1, 1, &[255, 255, 255, 255]);
@@ -256,28 +259,31 @@ impl Stage {
             ctx,
             pipeline,
             white_texture,
-            root_dc: DrawCall {
-                instrs: vec![],
-                dcs: vec![]
-            },
+            root_dc: DrawCall { instrs: vec![], dcs: vec![] },
             last_draw_time: None,
             method_recvr,
             event_pub,
         }
     }
 
-    fn method_new_texture(&mut self, width: u16, height: u16, data: Vec<u8>,
-        sendr: async_channel::Sender<TextureId>
-        ) {
+    fn method_new_texture(
+        &mut self,
+        width: u16,
+        height: u16,
+        data: Vec<u8>,
+        sendr: async_channel::Sender<TextureId>,
+    ) {
         let texture = self.ctx.new_texture_from_rgba8(width, height, &data);
         sendr.try_send(texture).unwrap();
     }
     fn method_delete_texture(&mut self, texture: TextureId) {
         self.ctx.delete_texture(texture);
     }
-    fn method_new_vertex_buffer(&mut self, verts: Vec<Vertex>,
-        sendr: async_channel::Sender<BufferId>
-        ) {
+    fn method_new_vertex_buffer(
+        &mut self,
+        verts: Vec<Vertex>,
+        sendr: async_channel::Sender<BufferId>,
+    ) {
         let buffer = self.ctx.new_buffer(
             BufferType::VertexBuffer,
             BufferUsage::Immutable,
@@ -285,9 +291,11 @@ impl Stage {
         );
         sendr.try_send(buffer).unwrap();
     }
-    fn method_new_index_buffer(&mut self, indices: Vec<u16>,
-        sendr: async_channel::Sender<BufferId>
-        ) {
+    fn method_new_index_buffer(
+        &mut self,
+        indices: Vec<u16>,
+        sendr: async_channel::Sender<BufferId>,
+    ) {
         let buffer = self.ctx.new_buffer(
             BufferType::IndexBuffer,
             BufferUsage::Immutable,
@@ -328,18 +336,22 @@ impl EventHandler for Stage {
         let deadline = Instant::now() + allowed_time;
 
         loop {
-            let Ok(method) =
-                self.method_recvr.recv_deadline(deadline)
-            else {
-                break
-            };
+            let Ok(method) = self.method_recvr.recv_deadline(deadline) else { break };
             match method {
-                GraphicsMethod::NewTexture((width, height, data, sendr)) => self.method_new_texture(width, height, data, sendr),
+                GraphicsMethod::NewTexture((width, height, data, sendr)) => {
+                    self.method_new_texture(width, height, data, sendr)
+                }
                 GraphicsMethod::DeleteTexture(texture) => self.method_delete_texture(texture),
-                GraphicsMethod::NewVertexBuffer((verts, sendr)) => self.method_new_vertex_buffer(verts, sendr),
-                GraphicsMethod::NewIndexBuffer((indices, sendr)) => self.method_new_index_buffer(indices, sendr),
+                GraphicsMethod::NewVertexBuffer((verts, sendr)) => {
+                    self.method_new_vertex_buffer(verts, sendr)
+                }
+                GraphicsMethod::NewIndexBuffer((indices, sendr)) => {
+                    self.method_new_index_buffer(indices, sendr)
+                }
                 GraphicsMethod::DeleteBuffer(buffer) => self.method_delete_buffer(buffer),
-                GraphicsMethod::ReplaceDrawCall((loc, dc)) => self.method_replace_draw_call(loc, dc),
+                GraphicsMethod::ReplaceDrawCall((loc, dc)) => {
+                    self.method_replace_draw_call(loc, dc)
+                }
             };
         }
     }
@@ -375,18 +387,18 @@ impl EventHandler for Stage {
 
     fn key_down_event(&mut self, keycode: KeyCode, mods: KeyMods, repeat: bool) {
         let event = GraphicsEvent::KeyDown((keycode, mods, repeat));
-        self.event_pub.notify_sync(event);
+        self.event_pub.try_send(event).unwrap();
     }
     fn resize_event(&mut self, width: f32, height: f32) {
         let event = GraphicsEvent::Resize((width, height));
-        self.event_pub.notify_sync(event);
+        self.event_pub.try_send(event).unwrap();
     }
 }
 
 pub fn run_gui(
     method_recvr: mpsc::Receiver<GraphicsMethod>,
-    event_pub: Arc<Publisher<GraphicsEvent>>,
-    ) {
+    event_pub: async_channel::Sender<GraphicsEvent>,
+) {
     #[cfg(target_os = "android")]
     {
         android_logger::init_once(
@@ -421,4 +433,3 @@ pub fn run_gui(
 
     miniquad::start(conf, || Box::new(Stage::new(method_recvr, event_pub)));
 }
-

+ 1 - 4
bin/darkwallet/src/keysym.rs

@@ -1,6 +1,4 @@
-use miniquad::{
-    KeyCode, MouseButton
-};
+use miniquad::{KeyCode, MouseButton};
 
 pub trait KeyCodeAsStr {
     fn to_str(&self) -> &str;
@@ -416,4 +414,3 @@ impl MouseButtonAsU8 for MouseButton {
         }
     }
 }
-

+ 33 - 28
bin/darkwallet/src/main.rs

@@ -3,7 +3,7 @@
 
 use async_lock::Mutex;
 use std::{
-    sync::{Arc, mpsc},
+    sync::{mpsc, Arc},
     thread,
 };
 
@@ -44,7 +44,7 @@ mod shader;
 
 mod text;
 
-use crate::error::{Result, Error};
+use crate::error::{Error, Result};
 
 #[macro_use]
 extern crate log;
@@ -180,37 +180,42 @@ fn main() {
     let (method_sender, method_recvr) = mpsc::channel();
     let render_api = gfx2::RenderApi::new(method_sender);
 
-    let event_pub = pubsub::Publisher::new();
-    let event_sub = event_pub.clone().subscribe();
+    let (event_pub, event_sub) = async_channel::unbounded();
 
-    let gfx_handle = thread::spawn(move || {
-        gfx2::run_gui(method_recvr, event_pub);
+    let ev_relay_task = ex.spawn(async move {
+        loop {
+            let Ok(ev) = event_sub.recv().await else {
+                debug!("Event relayer closed");
+                break
+            };
+            debug!("event: {:?}", ev);
+        }
     });
 
     let n_threads = std::thread::available_parallelism().unwrap().get();
     let (signal, shutdown) = smol::channel::unbounded::<()>();
-    easy_parallel::Parallel::new()
-        // Executor threads
-        .each(1..n_threads, |_| smol::future::block_on(ex.run(shutdown.recv())))
-        // Run the main future on this thread
-        .finish(|| {
-            smol::future::block_on(async {
-                //amain(ex.clone(), render_api, event_sub).await;
-
-                // Need to figure out how closing the window works
-                // Some time to allow processes to clean up
-                // But a time limit whereby we just close
-                loop {
-                    smol::Timer::after(std::time::Duration::from_secs(2)).await;
-                }
-                drop(signal);
-
-                zmq_task.cancel().await;
-                Ok::<(), Error>(())
-            });
-        });
-
-    gfx_handle.join();
+    let exec_threadpool = thread::spawn(move || {
+        easy_parallel::Parallel::new()
+            // Executor threads
+            .each(1..n_threads, |_| smol::future::block_on(ex.run(shutdown.recv())))
+            // Run the main future on this thread
+            .finish(|| smol::future::block_on(ex.run(shutdown.recv())));
+    });
+
+    gfx2::run_gui(method_recvr, event_pub);
+
+    // Close all tasks
+    smol::future::block_on(async {
+        // Perform cleanup code
+        // If not finished in certain amount of time, then just exit
+
+        zmq_task.cancel().await;
+        ev_relay_task.cancel().await;
+    });
+
+    drop(signal);
+    exec_threadpool.join();
+    debug!("Application closed");
 }
 
 /*

+ 20 - 23
bin/darkwallet/src/net.rs

@@ -1,11 +1,11 @@
-use darkfi_serial::{deserialize, Decodable, Encodable, SerialDecodable, VarInt};
 use async_lock::Mutex;
+use darkfi_serial::{deserialize, Decodable, Encodable, SerialDecodable, VarInt};
 use std::{
     io::Cursor,
-    sync::{Arc, atomic::Ordering, mpsc},
+    sync::{atomic::Ordering, mpsc, Arc},
     thread,
 };
-use zeromq::{Socket, SocketSend, SocketRecv};
+use zeromq::{Socket, SocketRecv, SocketSend};
 
 use crate::{
     error::{Error, Result},
@@ -67,9 +67,7 @@ pub struct ZeroMQAdapter {
 }
 
 impl ZeroMQAdapter {
-    pub async fn new(scene_graph: SceneGraphPtr2,
-    ex: Arc<smol::Executor<'static>>,
-        ) -> Arc<Self> {
+    pub async fn new(scene_graph: SceneGraphPtr2, ex: Arc<smol::Executor<'static>>) -> Arc<Self> {
         let mut zmq_rep = zeromq::RepSocket::new();
         zmq_rep.bind("tcp://127.0.0.1:9484").await.unwrap();
 
@@ -425,26 +423,25 @@ impl ZeroMQAdapter {
                 let node = scene_graph.get_node_mut(node_id).ok_or(Error::NodeNotFound)?;
 
                 let (sendr, recvr) = async_channel::unbounded();
-                let slot = Slot {
-                    name: slot_name,
-                    notify: sendr
-                };
+                let slot = Slot { name: slot_name, notify: sendr };
 
                 // This task will auto-die when the slot is unregistered
                 let self2 = self.clone();
-                self.ex.spawn(async move {
-                    loop {
-                        let Ok(signal_data) = recvr.recv().await else {
-                            // Die
-                            break;
-                        };
-
-                        let mut m = zeromq::ZmqMessage::from(signal_data);
-                        m.push_back(user_data.clone().into());
-
-                        self2.zmq_pub.lock().await.send(m).await.unwrap();
-                    }
-                }).detach();
+                self.ex
+                    .spawn(async move {
+                        loop {
+                            let Ok(signal_data) = recvr.recv().await else {
+                                // Die
+                                break;
+                            };
+
+                            let mut m = zeromq::ZmqMessage::from(signal_data);
+                            m.push_back(user_data.clone().into());
+
+                            self2.zmq_pub.lock().await.send(m).await.unwrap();
+                        }
+                    })
+                    .detach();
 
                 let slot_id = node.register(&sig_name, slot)?;
                 slot_id.encode(&mut reply).unwrap();

+ 1 - 3
bin/darkwallet/src/prop/mod.rs

@@ -14,9 +14,7 @@ use std::{
 use crate::{expr::SExprCode, scene::SceneNodeId};
 
 mod wrap;
-pub use wrap::{
-    PropertyBool, PropertyFloat32, PropertyUint32, PropertyStr, PropertyColor,
-};
+pub use wrap::{PropertyBool, PropertyColor, PropertyFloat32, PropertyStr, PropertyUint32};
 
 type Buffer = Arc<Vec<u8>>;
 

+ 10 - 6
bin/darkwallet/src/prop/wrap.rs

@@ -1,7 +1,10 @@
 use std::sync::Arc;
 
-use crate::{scene::SceneNode, error::{Error, Result}};
 use super::Property;
+use crate::{
+    error::{Error, Result},
+    scene::SceneNode,
+};
 
 pub struct PropertyBool {
     prop: Arc<Property>,
@@ -118,10 +121,12 @@ impl PropertyColor {
     }
 
     pub fn get(&self) -> [f32; 4] {
-        [self.prop.get_f32(0).unwrap(),
-        self.prop.get_f32(1).unwrap(),
-        self.prop.get_f32(2).unwrap(),
-        self.prop.get_f32(3).unwrap()]
+        [
+            self.prop.get_f32(0).unwrap(),
+            self.prop.get_f32(1).unwrap(),
+            self.prop.get_f32(2).unwrap(),
+            self.prop.get_f32(3).unwrap(),
+        ]
     }
 
     pub fn set(&self, val: [f32; 4]) {
@@ -131,4 +136,3 @@ impl PropertyColor {
         self.prop.set_f32(3, val[3]).unwrap();
     }
 }
-

+ 5 - 3
bin/darkwallet/src/pubsub.rs

@@ -1,5 +1,8 @@
 use rand::{rngs::OsRng, Rng};
-use std::{collections::HashMap, sync::{Arc, Mutex}};
+use std::{
+    collections::HashMap,
+    sync::{Arc, Mutex},
+};
 
 pub type SubscriptionId = usize;
 
@@ -36,7 +39,7 @@ impl<T: Clone + Send + 'static> Subscription<T> {
 
 #[derive(Debug)]
 pub struct Publisher<T> {
-    subs: Mutex<HashMap<SubscriptionId, smol::channel::Sender<T>>>
+    subs: Mutex<HashMap<SubscriptionId, smol::channel::Sender<T>>>,
 }
 
 impl<T: Clone + Send + 'static> Publisher<T> {
@@ -80,4 +83,3 @@ impl<T: Clone + Send + 'static> Publisher<T> {
         }
     }
 }
-

+ 6 - 8
bin/darkwallet/src/scene.rs

@@ -1,21 +1,20 @@
+use async_channel::Sender;
+use async_lock::Mutex;
 use atomic_float::AtomicF32;
 use darkfi_serial::{SerialDecodable, SerialEncodable};
-use async_lock::Mutex;
-use async_channel::Sender;
 use futures::{stream::FuturesUnordered, StreamExt};
 use std::{
     fmt,
     str::FromStr,
     sync::{
         atomic::{AtomicBool, AtomicU32, Ordering},
-        Arc
+        Arc,
     },
 };
 
 use crate::{
+    chatview, editbox,
     error::{Error, Result},
-    chatview,
-    editbox,
     prop::{Property, PropertyType},
 };
 
@@ -365,7 +364,7 @@ pub struct SceneNode {
     pub props: Vec<Arc<Property>>,
     pub sigs: Vec<Signal>,
     pub methods: Vec<Method>,
-    pub pimpl: Pimpl
+    pub pimpl: Pimpl,
 }
 
 impl SceneNode {
@@ -584,7 +583,7 @@ pub type SlotId = u32;
 
 pub struct Slot {
     pub name: String,
-    pub notify: Sender<Vec<u8>>
+    pub notify: Sender<Vec<u8>>,
 }
 
 pub struct Signal {
@@ -636,4 +635,3 @@ pub enum Pimpl {
     EditBox(editbox::EditBoxPtr),
     ChatView(chatview::ChatViewPtr),
 }
-

+ 7 - 12
bin/darkwallet/src/text.rs

@@ -1,7 +1,7 @@
 use freetype as ft;
 use log::debug;
 
-use crate::gfx::{Rectangle, FreetypeFace};
+use crate::gfx::{FreetypeFace, Rectangle};
 
 #[derive(Clone)]
 pub struct Glyph {
@@ -129,8 +129,8 @@ impl TextShaper {
                         let mut tdata = vec![];
                         tdata.resize(4 * bmp_width * bmp_height, 0);
                         // Convert from BGRA to RGBA
-                        for i in 0..bmp_width*bmp_height {
-                            let idx = i*4;
+                        for i in 0..bmp_width * bmp_height {
+                            let idx = i * 4;
                             let b = buffer[idx];
                             let g = buffer[idx + 1];
                             let r = buffer[idx + 2];
@@ -156,7 +156,7 @@ impl TextShaper {
                             .collect();
                         tdata
                     }
-                    _ => panic!("unsupport pixel mode: {:?}", pixel_mode)
+                    _ => panic!("unsupport pixel mode: {:?}", pixel_mode),
                 };
 
                 let pos = if face.has_fixed_sizes() {
@@ -169,9 +169,7 @@ impl TextShaper {
 
                     current_x += w;
 
-                    Rectangle {
-                        x, y, w, h
-                    }
+                    Rectangle { x, y, w, h }
                 } else {
                     let (w, h) = (bmp_width as f32, bmp_height as f32);
 
@@ -186,9 +184,7 @@ impl TextShaper {
                     current_x += x_advance;
                     current_y += y_advance;
 
-                    Rectangle {
-                        x, y, w, h
-                    }
+                    Rectangle { x, y, w, h }
                 };
 
                 let glyph = Glyph {
@@ -197,7 +193,7 @@ impl TextShaper {
                     bmp,
                     bmp_width: bmp_width as u16,
                     bmp_height: bmp_height as u16,
-                    pos
+                    pos,
                 };
 
                 glyphs.push(glyph);
@@ -210,4 +206,3 @@ impl TextShaper {
         glyphs
     }
 }
-