1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
use gtk::{
gio::{Cancellable, SimpleAction},
glib::SignalHandlerId,
prelude::{ActionExt, ToVariant},
};
use std::cell::RefCell;
// Defaults
/// C-compatible variant type
const DEFAULT_STATE: i32 = -1;
/// [SimpleAction](https://docs.gtk.org/gio/class.SimpleAction.html) wrapper for `Open` action
pub struct Open {
cancellable: RefCell<Cancellable>,
pub simple_action: SimpleAction,
}
impl Default for Open {
fn default() -> Self {
Self::new()
}
}
impl Open {
// Constructors
/// Create new `Self`
pub fn new() -> Self {
Self {
cancellable: RefCell::new(Cancellable::new()),
simple_action: SimpleAction::new_stateful(
>k::glib::uuid_string_random(),
None,
&DEFAULT_STATE.to_variant(),
),
}
}
// Actions
/// Change action [state](https://docs.gtk.org/gio/method.SimpleAction.set_state.html)
/// * set `DEFAULT_STATE` on `None`
pub fn change_state(&self, state: Option<i32>) {
self.simple_action.change_state(
&match state {
Some(value) => value,
None => DEFAULT_STATE,
}
.to_variant(),
)
}
// Actions
/// Formatted action connector for external implementation
pub fn on_activate(&self, callback: impl Fn(Option<i32>, &str) + 'static) -> SignalHandlerId {
use gtk::{prelude::FileExt, FileDialog, Window};
use std::rc::Rc;
let cancellable = self.cancellable();
let callback = Rc::new(callback);
self.simple_action.connect_activate(move |this, _| {
let state = this
.state()
.expect("State value required")
.get::<i32>()
.expect("Parameter type does not match `i32`");
FileDialog::builder()
.build()
.open(Window::NONE, Some(&cancellable), {
let callback = callback.clone();
move |result| {
if let Ok(file) = result {
callback(
if state == DEFAULT_STATE {
None
} else {
Some(state)
},
file.path().unwrap().to_str().unwrap(),
)
}
}
});
})
}
// Tools
/// Gent new `Cancellable` by cancel previous one
fn cancellable(&self) -> Cancellable {
use gtk::prelude::CancellableExt;
let cancellable = self.cancellable.replace(Cancellable::new());
if !cancellable.is_cancelled() {
cancellable.cancel();
}
self.cancellable.borrow().clone()
}
}