From 0af32b0022e77b4817f89fe177eee4e1dcf21890 Mon Sep 17 00:00:00 2001
From: MrGVSV <gino.valente.code@gmail.com>
Date: Sun, 19 Dec 2021 14:55:13 -0800
Subject: [PATCH] Extracted ChangeEvent and made it generic

---
 examples/text_box.rs          |  3 ++-
 kayak_core/src/event.rs       | 37 +++++++++++++++++++++++++++++++++++
 kayak_widgets/src/text_box.rs | 34 +++++---------------------------
 3 files changed, 44 insertions(+), 30 deletions(-)

diff --git a/examples/text_box.rs b/examples/text_box.rs
index bbf01ec..1cf61d2 100644
--- a/examples/text_box.rs
+++ b/examples/text_box.rs
@@ -3,13 +3,14 @@ use bevy::{
     window::WindowDescriptor,
     DefaultPlugins,
 };
+use kayak_core::OnChange;
 use kayak_ui::bevy::{BevyContext, BevyKayakUIPlugin, FontMapping, UICameraBundle};
 use kayak_ui::core::{
     render, rsx,
     styles::{Style, StyleProp, Units},
     widget, Bound, Index, MutableBound,
 };
-use kayak_widgets::{App, OnChange, TextBox, Window};
+use kayak_widgets::{App, TextBox, Window};
 
 #[widget]
 fn TextBoxExample(context: &mut KayakContext) {
diff --git a/kayak_core/src/event.rs b/kayak_core/src/event.rs
index 3142a86..daf64a3 100644
--- a/kayak_core/src/event.rs
+++ b/kayak_core/src/event.rs
@@ -1,3 +1,4 @@
+use std::sync::{Arc, RwLock};
 use crate::{Index, KeyCode};
 
 #[derive(Debug, Clone, Copy, PartialEq)]
@@ -28,3 +29,39 @@ pub enum EventType {
     CharInput { c: char },
     KeyboardInput { key: KeyCode },
 }
+
+/// An event denoting a change of some type
+#[derive(Debug, Clone, PartialEq)]
+pub struct ChangeEvent<T> {
+    pub value: T,
+}
+
+/// A handler struct for a [ChangeEvent].
+///
+/// ## Example
+/// ```rust
+/// let handler = OnChange::new(move |event| {
+///     let value = event.value;
+///     // Do something...
+/// });
+/// ```
+#[derive(Clone)]
+pub struct OnChange<T>(pub Arc<RwLock<dyn FnMut(ChangeEvent<T>) + Send + Sync + 'static>>);
+
+impl<T> OnChange<T> {
+    pub fn new<F: FnMut(ChangeEvent<T>) + Send + Sync + 'static>(f: F) -> Self {
+        Self(Arc::new(RwLock::new(f)))
+    }
+}
+
+impl<T> PartialEq for OnChange<T> {
+    fn eq(&self, _other: &Self) -> bool {
+        true
+    }
+}
+
+impl<T> std::fmt::Debug for OnChange<T> {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        f.debug_tuple("OnChange").finish()
+    }
+}
\ No newline at end of file
diff --git a/kayak_widgets/src/text_box.rs b/kayak_widgets/src/text_box.rs
index 5d22a3a..6a878f4 100644
--- a/kayak_widgets/src/text_box.rs
+++ b/kayak_widgets/src/text_box.rs
@@ -1,44 +1,20 @@
+use std::sync::{Arc, RwLock};
+
 use kayak_ui::core::{
+    Bound, ChangeEvent, Color, EventType, MutableBound, OnChange, OnEvent,
     render_command::RenderCommand,
     rsx,
     styles::{Style, StyleProp, Units},
-    widget, Bound, Color, EventType, MutableBound, OnEvent,
+    widget
 };
-use std::sync::{Arc, RwLock};
 
 use crate::{Background, Clip, Text};
 
-#[derive(Debug, Clone, PartialEq)]
-pub struct ChangeEvent {
-    pub value: String,
-}
-
-#[derive(Clone)]
-pub struct OnChange(pub Arc<RwLock<dyn FnMut(ChangeEvent) + Send + Sync + 'static>>);
-
-impl OnChange {
-    pub fn new<F: FnMut(ChangeEvent) + Send + Sync + 'static>(f: F) -> OnChange {
-        OnChange(Arc::new(RwLock::new(f)))
-    }
-}
-
-impl PartialEq for OnChange {
-    fn eq(&self, _other: &Self) -> bool {
-        true
-    }
-}
-
-impl std::fmt::Debug for OnChange {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        f.debug_tuple("OnChange").finish()
-    }
-}
-
 #[derive(Debug, Clone, Copy, PartialEq)]
 pub struct Focus(pub bool);
 
 #[widget(focusable)]
-pub fn TextBox(value: String, on_change: Option<OnChange>) {
+pub fn TextBox(value: String, on_change: Option<OnChange<String>>) {
     *styles = Some(Style {
         render_command: StyleProp::Value(RenderCommand::Layout),
         ..styles.clone().unwrap_or_default()
-- 
GitLab