From a280dcda23c3c3432f12776b2fe69c4ed39cd99a Mon Sep 17 00:00:00 2001
From: Héctor Ramón Jiménez <hector0193@gmail.com>
Date: Tue, 17 Mar 2020 06:53:57 +0100
Subject: Add `PaneGrid::on_key_press` for hotkey logic

---
 native/src/widget/pane_grid.rs       | 48 +++++++++++++++++++++++++++++++++---
 native/src/widget/pane_grid/state.rs |  7 ++++++
 2 files changed, 52 insertions(+), 3 deletions(-)

(limited to 'native/src')

diff --git a/native/src/widget/pane_grid.rs b/native/src/widget/pane_grid.rs
index 7135efe4..8410f95c 100644
--- a/native/src/widget/pane_grid.rs
+++ b/native/src/widget/pane_grid.rs
@@ -25,8 +25,10 @@ pub struct PaneGrid<'a, Message, Renderer> {
     width: Length,
     height: Length,
     spacing: u16,
+    modifier_keys: keyboard::ModifiersState,
     on_drag: Option<Box<dyn Fn(DragEvent) -> Message>>,
     on_resize: Option<Box<dyn Fn(ResizeEvent) -> Message>>,
+    on_key_press: Option<Box<dyn Fn(keyboard::KeyCode) -> Option<Message>>>,
 }
 
 impl<'a, Message, Renderer> PaneGrid<'a, Message, Renderer> {
@@ -67,8 +69,13 @@ impl<'a, Message, Renderer> PaneGrid<'a, Message, Renderer> {
             width: Length::Fill,
             height: Length::Fill,
             spacing: 0,
+            modifier_keys: keyboard::ModifiersState {
+                control: true,
+                ..Default::default()
+            },
             on_drag: None,
             on_resize: None,
+            on_key_press: None,
         }
     }
 
@@ -96,6 +103,14 @@ impl<'a, Message, Renderer> PaneGrid<'a, Message, Renderer> {
         self
     }
 
+    pub fn modifier_keys(
+        mut self,
+        modifier_keys: keyboard::ModifiersState,
+    ) -> Self {
+        self.modifier_keys = modifier_keys;
+        self
+    }
+
     pub fn on_drag(
         mut self,
         f: impl Fn(DragEvent) -> Message + 'static,
@@ -112,6 +127,14 @@ impl<'a, Message, Renderer> PaneGrid<'a, Message, Renderer> {
         self
     }
 
+    pub fn on_key_press(
+        mut self,
+        f: impl Fn(keyboard::KeyCode) -> Option<Message> + 'static,
+    ) -> Self {
+        self.on_key_press = Some(Box::new(f));
+        self
+    }
+
     fn trigger_resize(
         &mut self,
         layout: Layout<'_>,
@@ -230,7 +253,9 @@ where
 
                     if let Some(((pane, _), _)) = clicked_region.next() {
                         match &self.on_drag {
-                            Some(on_drag) if self.modifiers.alt => {
+                            Some(on_drag)
+                                if *self.modifiers == self.modifier_keys =>
+                            {
                                 self.state.pick_pane(pane);
 
                                 messages.push(on_drag(DragEvent::Picked {
@@ -278,7 +303,7 @@ where
                 state: ButtonState::Pressed,
             }) if self.on_resize.is_some()
                 && self.state.picked_pane().is_none()
-                && self.modifiers.alt =>
+                && *self.modifiers == self.modifier_keys =>
             {
                 let bounds = layout.bounds();
                 let relative_cursor = Point::new(
@@ -334,7 +359,24 @@ where
             Event::Mouse(mouse::Event::CursorMoved { .. }) => {
                 self.trigger_resize(layout, cursor_position, messages);
             }
-            Event::Keyboard(keyboard::Event::Input { modifiers, .. }) => {
+            Event::Keyboard(keyboard::Event::Input {
+                modifiers,
+                key_code,
+                state,
+            }) => {
+                if let Some(on_key_press) = &self.on_key_press {
+                    // TODO: Discard when event is captured
+                    if state == ButtonState::Pressed {
+                        if let Some(_) = self.state.idle_pane() {
+                            if modifiers == self.modifier_keys {
+                                if let Some(message) = on_key_press(key_code) {
+                                    messages.push(message);
+                                }
+                            }
+                        }
+                    }
+                }
+
                 *self.modifiers = modifiers;
             }
             _ => {}
diff --git a/native/src/widget/pane_grid/state.rs b/native/src/widget/pane_grid/state.rs
index 456ad78a..9103dcd0 100644
--- a/native/src/widget/pane_grid/state.rs
+++ b/native/src/widget/pane_grid/state.rs
@@ -186,6 +186,13 @@ impl Internal {
         self.action
     }
 
+    pub fn idle_pane(&self) -> Option<Pane> {
+        match self.action {
+            Action::Idle { focus } => focus,
+            _ => None,
+        }
+    }
+
     pub fn picked_pane(&self) -> Option<Pane> {
         match self.action {
             Action::Dragging { pane } => Some(pane),
-- 
cgit