From 02a41a50c0bc0300bf8ee9b5ffe6bbf436232471 Mon Sep 17 00:00:00 2001
From: Julian Mutter <julian.mutter@comumail.de>
Date: Tue, 16 Jan 2024 18:08:22 +0100
Subject: [PATCH] Make mcdu work

---
 Cargo.lock  |  1 -
 Cargo.toml  |  2 +-
 src/main.rs | 63 +++++++++++++++++++----------------------------------
 src/mcdu.rs | 50 ++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 73 insertions(+), 43 deletions(-)
 create mode 100644 src/mcdu.rs

diff --git a/Cargo.lock b/Cargo.lock
index 05e06d0..21229e8 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -974,7 +974,6 @@ dependencies = [
  "relm4",
  "relm4-components",
  "relm4-icons",
- "relm4-macros",
 ]
 
 [[package]]
diff --git a/Cargo.toml b/Cargo.toml
index 058fd45..876a154 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -8,7 +8,7 @@ edition = "2021"
 [dependencies]
 # Core library
 relm4 = "0.6.2"
-relm4-macros = "0.6.2"
+# relm4-macros = "0.6.2"
 # Optional: reusable components
 relm4-components = "0.6.2"
 # Optional: icons
diff --git a/src/main.rs b/src/main.rs
index 5981c7a..95cdf03 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,16 +1,21 @@
+mod mcdu;
+
 use gtk::glib::clone;
 use gtk::prelude::{BoxExt, ButtonExt, GtkWindowExt};
+use mcdu::McduModel;
 use relm4::gtk::prelude::GridExt;
-use relm4::{gtk, ComponentParts, ComponentSender, RelmApp, RelmWidgetExt, SimpleComponent};
+use relm4::{
+    gtk, Component, ComponentController, ComponentParts, ComponentSender, RelmApp, RelmWidgetExt,
+    SimpleComponent,
+};
 
 struct AppModel {
-    counter: u8,
+    text: String,
 }
 
 #[derive(Debug)]
 enum AppInput {
-    Increment,
-    Decrement,
+    McduInput(char),
 }
 
 struct AppWidgets {
@@ -44,7 +49,9 @@ impl SimpleComponent for AppModel {
         sender: ComponentSender<Self>,
     ) -> relm4::ComponentParts<Self> {
         relm4_icons::initialize_icons();
-        let model = AppModel { counter };
+        let model = AppModel {
+            text: String::new(),
+        };
 
         let layout = gtk::Box::builder()
             .orientation(gtk::Orientation::Horizontal)
@@ -62,31 +69,11 @@ impl SimpleComponent for AppModel {
             .row_homogeneous(true)
             .build();
 
-        let mcdu = gtk::Grid::builder().build();
-        mcdu.set_column_spacing(5);
-        mcdu.set_row_spacing(5);
-        // mcdu.insert_row(0);
-        let a = gtk::Button::default();
-        a.set_label("a");
-        let b = gtk::Button::default();
-        b.set_label("b");
-
-        let alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
-
-        let mcdu_width = 6;
-        for (i, c) in alphabet.char_indices() {
-            let button = gtk::Button::default();
-            button.set_label(&c.to_string());
-
-            let column = i % mcdu_width;
-            let row = (i - column) / mcdu_width;
-
-            mcdu.attach(&button, column as i32, row as i32, 1, 1);
-        }
-        // mcdu.attach(&b, 1, 0, 1, 1);
-        // mcdu.
-        // .orientation(gtk::Orientation::Vertical)
-        // .build();
+        let mcdu = McduModel::builder()
+            .launch(())
+            .forward(sender.input_sender(), |response| match response {
+                mcdu::McduOutput::ButtonPress(c) => AppInput::McduInput(c),
+            });
 
         let inc_button = gtk::Button::with_label("Increment3");
         let dec_button = gtk::Button::with_label("Decrement");
@@ -97,14 +84,15 @@ impl SimpleComponent for AppModel {
 
         tab_chooser.append(&x);
 
-        let label = gtk::Label::new(Some(&format!("Counter: {}", model.counter)));
+        let label = gtk::Label::new(Some(&format!("Text: NONE")));
         label.set_margin_all(5);
 
         window.set_child(Some(&layout));
         layout.set_margin_all(5);
         layout.append(&tab_chooser);
         layout.append(&main_view);
-        layout.append(&mcdu);
+        layout.append(mcdu.widget());
+        layout.append(&label);
 
         let widgets = AppWidgets { label };
 
@@ -113,20 +101,13 @@ impl SimpleComponent for AppModel {
 
     fn update(&mut self, message: Self::Input, _sender: ComponentSender<Self>) {
         match message {
-            AppInput::Increment => {
-                self.counter = self.counter.wrapping_add(1);
-            }
-            AppInput::Decrement => {
-                self.counter = self.counter.wrapping_sub(1);
-            }
+            AppInput::McduInput(c) => self.text.push(c),
         }
     }
 
     /// Update the view to represent the updated model.
     fn update_view(&self, widgets: &mut Self::Widgets, _sender: ComponentSender<Self>) {
-        widgets
-            .label
-            .set_label(&format!("Counter: {}", self.counter));
+        widgets.label.set_label(&format!("Text: {}", self.text));
     }
 }
 
diff --git a/src/mcdu.rs b/src/mcdu.rs
new file mode 100644
index 0000000..0611947
--- /dev/null
+++ b/src/mcdu.rs
@@ -0,0 +1,50 @@
+use relm4::gtk::{glib, prelude::*};
+use relm4::{gtk, ComponentParts, ComponentSender, SimpleComponent};
+
+pub struct McduModel;
+
+#[derive(Debug)]
+pub enum McduOutput {
+    ButtonPress(char),
+}
+
+#[relm4::component(pub)]
+impl SimpleComponent for McduModel {
+    type Init = ();
+    type Input = ();
+    type Output = McduOutput;
+
+    view! {
+        #[root]
+        gtk::Grid {
+            set_column_spacing: 5,
+            set_row_spacing: 5,
+        }
+    }
+
+    fn init(
+        _init: Self::Init,
+        root: &Self::Root,
+        sender: ComponentSender<Self>,
+    ) -> ComponentParts<Self> {
+        let alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+        let mcdu_width = 6;
+
+        for (i, c) in alphabet.char_indices() {
+            let button = gtk::Button::default();
+            button.set_label(&c.to_string());
+            button.connect_clicked(glib::clone!(@strong sender => move |_| {
+                sender.output(McduOutput::ButtonPress(c)).unwrap();
+            }));
+
+            let column = i % mcdu_width;
+            let row = (i - column) / mcdu_width;
+
+            root.attach(&button, column as i32, row as i32, 1, 1);
+        }
+
+        let model = McduModel;
+        let widgets = view_output!();
+        ComponentParts { model, widgets }
+    }
+}