Skip to content

Commit b319ed3

Browse files
committed
chore: Make PickerGroupBox emit signal when key pressed
1 parent 30aaf0a commit b319ed3

File tree

2 files changed

+71
-41
lines changed

2 files changed

+71
-41
lines changed

src/picker/mod.rs

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
use cascade::cascade;
2+
use futures::{prelude::*, stream::FuturesUnordered};
3+
use glib::clone;
24
use gtk::prelude::*;
35
use gtk::subclass::prelude::*;
46
use once_cell::sync::Lazy;
5-
use std::collections::HashMap;
7+
use std::{cell::RefCell, collections::HashMap};
68

79
use crate::Keyboard;
810
use backend::DerefCell;
@@ -29,6 +31,7 @@ pub static SCANCODE_LABELS: Lazy<HashMap<String, String>> = Lazy::new(|| {
2931
#[derive(Default)]
3032
pub struct PickerInner {
3133
group_box: DerefCell<PickerGroupBox>,
34+
keyboard: RefCell<Option<Keyboard>>,
3235
}
3336

3437
#[glib::object_subclass]
@@ -42,7 +45,12 @@ impl ObjectImpl for PickerInner {
4245
fn constructed(&self, picker: &Picker) {
4346
self.parent_constructed(picker);
4447

45-
let group_box = PickerGroupBox::new();
48+
let group_box = cascade! {
49+
PickerGroupBox::new();
50+
..connect_key_pressed(clone!(@weak picker => move |name| {
51+
picker.key_pressed(name)
52+
}));
53+
};
4654

4755
cascade! {
4856
picker;
@@ -75,16 +83,48 @@ impl Picker {
7583
}
7684

7785
pub(crate) fn set_keyboard(&self, keyboard: Option<Keyboard>) {
78-
self.inner().group_box.set_keyboard(keyboard.clone());
86+
if let Some(old_kb) = &*self.inner().keyboard.borrow() {
87+
old_kb.set_picker(None);
88+
}
7989

8090
if let Some(kb) = &keyboard {
91+
// Check that scancode is available for the keyboard
92+
self.inner().group_box.set_key_visibility(|name| {
93+
let visible = kb.has_scancode(name);
94+
let sensitive = true;
95+
(visible, sensitive)
96+
});
8197
kb.set_picker(Some(&self));
8298
}
99+
100+
*self.inner().keyboard.borrow_mut() = keyboard;
83101
}
84102

85103
pub(crate) fn set_selected(&self, scancode_names: Vec<String>) {
86104
self.inner().group_box.set_selected(scancode_names);
87105
}
106+
107+
fn key_pressed(&self, name: String) {
108+
let kb = match self.inner().keyboard.borrow().clone() {
109+
Some(kb) => kb,
110+
None => {
111+
return;
112+
}
113+
};
114+
let layer = kb.layer();
115+
116+
info!("Clicked {} layer {:?}", name, layer);
117+
if let Some(layer) = layer {
118+
let futures = FuturesUnordered::new();
119+
for i in kb.selected().iter() {
120+
let i = *i;
121+
futures.push(clone!(@strong kb, @strong name => async move {
122+
kb.keymap_set(i, layer, &name).await;
123+
}));
124+
}
125+
glib::MainContext::default().spawn_local(async { futures.collect::<()>().await });
126+
}
127+
}
88128
}
89129

90130
#[cfg(test)]

src/picker/picker_group_box.rs

Lines changed: 28 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
use cascade::cascade;
2-
use futures::{prelude::*, stream::FuturesUnordered};
3-
use glib::clone;
2+
use glib::{clone, subclass::Signal, SignalHandlerId};
43
use gtk::prelude::*;
54
use gtk::subclass::prelude::*;
5+
use once_cell::sync::Lazy;
66
use std::{cell::RefCell, collections::HashMap, rc::Rc};
77

8-
use crate::Keyboard;
98
use backend::DerefCell;
109

1110
use super::{picker_group::PickerGroup, picker_json::picker_json, picker_key::PickerKey};
@@ -29,7 +28,6 @@ button {
2928
pub struct PickerGroupBoxInner {
3029
groups: DerefCell<Vec<PickerGroup>>,
3130
keys: DerefCell<HashMap<String, Rc<PickerKey>>>,
32-
keyboard: RefCell<Option<Keyboard>>,
3331
selected: RefCell<Vec<String>>,
3432
}
3533

@@ -84,6 +82,18 @@ impl ObjectImpl for PickerGroupBoxInner {
8482
..show_all();
8583
};
8684
}
85+
86+
fn signals() -> &'static [Signal] {
87+
static SIGNALS: Lazy<Vec<Signal>> = Lazy::new(|| {
88+
vec![Signal::builder(
89+
"key-pressed",
90+
&[String::static_type().into()],
91+
glib::Type::UNIT.into(),
92+
)
93+
.build()]
94+
});
95+
SIGNALS.as_ref()
96+
}
8797
}
8898

8999
impl WidgetImpl for PickerGroupBoxInner {
@@ -226,50 +236,30 @@ impl PickerGroupBox {
226236
let button = &key.gtk;
227237
let name = key.name.to_string();
228238
button.connect_clicked(clone!(@weak picker => @default-panic, move |_| {
229-
let kb = match picker.inner().keyboard.borrow().clone() {
230-
Some(kb) => kb,
231-
None => {
232-
return;
233-
}
234-
};
235-
let layer = kb.layer();
236-
237-
info!("Clicked {} layer {:?}", name, layer);
238-
if let Some(layer) = layer {
239-
let futures = FuturesUnordered::new();
240-
for i in kb.selected().iter() {
241-
let i = *i;
242-
futures.push(clone!(@strong kb, @strong name => async move {
243-
kb.keymap_set(i, layer, &name).await;
244-
}));
245-
}
246-
glib::MainContext::default().spawn_local(async {futures.collect::<()>().await});
247-
}
239+
picker.emit_by_name("key-pressed", &[&name]).unwrap();
248240
}));
249241
}
250242
}
251243
}
252244

245+
pub fn connect_key_pressed<F: Fn(String) + 'static>(&self, cb: F) -> SignalHandlerId {
246+
self.connect_local("key-pressed", false, move |values| {
247+
cb(values[1].get::<String>().unwrap().unwrap());
248+
None
249+
})
250+
.unwrap()
251+
}
252+
253253
fn get_button(&self, scancode_name: &str) -> Option<&gtk::Button> {
254254
self.inner().keys.get(scancode_name).map(|k| &k.gtk)
255255
}
256256

257-
pub(crate) fn set_keyboard(&self, keyboard: Option<Keyboard>) {
258-
if let Some(old_kb) = &*self.inner().keyboard.borrow() {
259-
old_kb.set_picker(None);
257+
pub(crate) fn set_key_visibility<F: Fn(&str) -> (bool, bool)>(&self, f: F) {
258+
for key in self.inner().keys.values() {
259+
let (visible, sensitive) = f(&key.name);
260+
key.gtk.set_visible(visible);
261+
key.gtk.set_sensitive(sensitive);
260262
}
261-
262-
if let Some(kb) = &keyboard {
263-
for group in self.inner().groups.iter() {
264-
for key in group.iter_keys() {
265-
// Check that scancode is available for the keyboard
266-
let visible = kb.has_scancode(&key.name);
267-
key.gtk.set_visible(visible);
268-
}
269-
}
270-
}
271-
272-
*self.inner().keyboard.borrow_mut() = keyboard;
273263
}
274264

275265
pub(crate) fn set_selected(&self, scancode_names: Vec<String>) {

0 commit comments

Comments
 (0)