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
105
106
107
108
109
110
111
112
113
use gtk::prelude::{Cast, IsA, StaticType, WidgetExt};
/// Trait that extends [`gtk::prelude::WidgetExt`].
///
/// This trait's main goal is to reduce redundant code and
/// to provide helpful methods for the widgets macro of relm4-macros.
pub trait RelmWidgetExt {
/// Attach widget to a `gtk::SizeGroup`.
fn set_size_group(&self, size_group: >k::SizeGroup);
/// Locate the top level window this widget is attached to.
///
/// Equivalent to `widget.ancestor(gtk::Window::static_type())`, then casting.
fn toplevel_window(&self) -> Option<gtk::Window>;
/// Set margin at start, end, top and bottom all at once.
fn set_margin_all(&self, margin: i32) {
self.set_margin_horizontal(margin);
self.set_margin_vertical(margin);
}
/// Set margin at top and bottom at once.
fn set_margin_vertical(&self, margin: i32);
/// Set margin at start and end at once.
fn set_margin_horizontal(&self, margin: i32);
/// Set both horizontal and vertical expand properties at once.
fn set_expand(&self, expand: bool);
/// Set both horizontal and vertical align properties at once.
fn set_align(&self, align: gtk::Align);
/// Add class name if active is [`true`] and
/// remove class name if active is [`false`]
fn set_class_active(&self, class: &str, active: bool);
/// Add inline CSS instructions to a widget.
/// ```
/// # use relm4::RelmWidgetExt;
/// # gtk::init().unwrap();
/// # let widget = gtk::Button::new();
/// widget.inline_css("border: 1px solid red");
/// ```
fn inline_css(&self, style: &str);
/// Sets the tooltip text of a widget and enables is.
///
/// This is basically, the same as using [`WidgetExt::set_has_tooltip()`]
/// and [`WidgetExt::set_tooltip_text()`], but with fewer steps.
fn set_tooltip(&self, test: &str);
}
impl<T: IsA<gtk::Widget>> RelmWidgetExt for T {
fn set_size_group(&self, size_group: >k::SizeGroup) {
size_group.add_widget(self);
}
fn toplevel_window(&self) -> Option<gtk::Window> {
self.ancestor(gtk::Window::static_type())
.and_then(|widget| widget.dynamic_cast::<gtk::Window>().ok())
}
fn set_margin_vertical(&self, margin: i32) {
self.set_margin_top(margin);
self.set_margin_bottom(margin);
}
fn set_margin_horizontal(&self, margin: i32) {
self.set_margin_start(margin);
self.set_margin_end(margin);
}
fn set_class_active(&self, class: &str, active: bool) {
if active {
self.add_css_class(class);
} else {
self.remove_css_class(class);
}
}
fn set_expand(&self, expand: bool) {
self.set_hexpand(expand);
self.set_vexpand(expand);
}
fn set_align(&self, align: gtk::Align) {
self.set_halign(align);
self.set_valign(align);
}
#[allow(deprecated)]
fn inline_css(&self, style: &str) {
use gtk::prelude::StyleContextExt;
let context = self.style_context();
let provider = gtk::CssProvider::new();
let data = if style.ends_with(';') {
["*{", style, "}"].concat()
} else {
["*{", style, ";}"].concat()
};
provider.load_from_data(&data);
context.add_provider(&provider, gtk::STYLE_PROVIDER_PRIORITY_APPLICATION + 1);
}
fn set_tooltip(&self, text: &str) {
self.set_has_tooltip(true);
self.set_tooltip_text(Some(text));
}
}