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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
use geom::CornerRadii;
use super::ButtonStyle;
use crate::{
include_labeled_bytes, ButtonBuilder, ControlState, EventCtx, Key, ScreenDims, Style, Widget,
};
pub trait StyledButtons<'a> {
fn btn_plain(&self) -> ButtonBuilder<'a>;
fn btn_plain_text(&self, text: &'a str) -> ButtonBuilder<'a> {
self.btn_plain().label_text(text)
}
fn btn_plain_icon(&self, image_path: &'a str) -> ButtonBuilder<'a> {
icon_button(self.btn_plain().image_path(image_path))
}
fn btn_plain_icon_bytes(&self, labeled_bytes: (&'a str, &'a [u8])) -> ButtonBuilder<'a> {
icon_button(self.btn_plain().image_bytes(labeled_bytes))
}
fn btn_plain_icon_text(&self, image_path: &'a str, text: &'a str) -> ButtonBuilder<'a> {
self.btn_plain()
.label_text(text)
.image_path(image_path)
.image_dims(ScreenDims::square(18.0))
}
fn btn_outline(&self) -> ButtonBuilder<'a>;
fn btn_outline_text(&self, text: &'a str) -> ButtonBuilder<'a> {
self.btn_outline().label_text(text)
}
fn btn_outline_icon(&self, image_path: &'a str) -> ButtonBuilder<'a> {
icon_button(self.btn_outline().image_path(image_path))
}
fn btn_outline_icon_text(&self, image_path: &'a str, text: &'a str) -> ButtonBuilder<'a> {
self.btn_outline()
.label_text(text)
.image_path(image_path)
.image_dims(ScreenDims::square(18.0))
}
fn btn_solid(&self) -> ButtonBuilder<'a>;
fn btn_solid_floating(&self) -> ButtonBuilder<'a>;
fn btn_solid_text(&self, text: &'a str) -> ButtonBuilder<'a> {
self.btn_solid().label_text(text)
}
fn btn_solid_icon(&self, image_path: &'a str) -> ButtonBuilder<'a> {
icon_button(self.btn_solid().image_path(image_path))
}
fn btn_solid_icon_bytes(&self, labeled_bytes: (&'a str, &'a [u8])) -> ButtonBuilder<'a> {
icon_button(self.btn_solid().image_bytes(labeled_bytes))
}
fn btn_solid_icon_text(&self, image_path: &'a str, text: &'a str) -> ButtonBuilder<'a> {
self.btn_solid()
.label_text(text)
.image_path(image_path)
.image_dims(ScreenDims::square(18.0))
}
fn btn_plain_destructive(&self) -> ButtonBuilder<'a>;
fn btn_plain_destructive_text(&self, text: &'a str) -> ButtonBuilder<'a> {
self.btn_plain_destructive().label_text(text)
}
fn btn_plain_destructive_icon(&self, image_path: &'a str) -> ButtonBuilder<'a> {
icon_button(self.btn_plain_destructive().image_path(image_path))
}
fn btn_solid_destructive(&self) -> ButtonBuilder<'a>;
fn btn_solid_destructive_text(&self, text: &'a str) -> ButtonBuilder<'a> {
self.btn_solid_destructive().label_text(text)
}
fn btn_solid_destructive_icon(&self, image_path: &'a str) -> ButtonBuilder<'a> {
icon_button(self.btn_solid_destructive().image_path(image_path))
}
fn btn_solid_destructive_icon_text(
&self,
image_path: &'a str,
text: &'a str,
) -> ButtonBuilder<'a> {
self.btn_solid_destructive()
.label_text(text)
.image_path(image_path)
.image_dims(ScreenDims::square(18.0))
}
fn btn_outline_destructive(&self) -> ButtonBuilder<'a>;
fn btn_outline_destructive_text(&self, text: &'a str) -> ButtonBuilder<'a> {
self.btn_outline_destructive().label_text(text)
}
fn btn_outline_destructive_icon(&self, image_path: &'a str) -> ButtonBuilder<'a> {
icon_button(self.btn_outline_destructive().image_path(image_path))
}
fn btn_outline_destructive_icon_text(
&self,
image_path: &'a str,
text: &'a str,
) -> ButtonBuilder<'a> {
self.btn_outline_destructive()
.label_text(text)
.image_path(image_path)
.image_dims(ScreenDims::square(18.0))
}
fn btn_back(&self, title: &'a str) -> ButtonBuilder<'a> {
back_button(self.btn_plain(), title)
}
fn btn_outline_dropdown(&self) -> ButtonBuilder<'a> {
dropdown_button(self.btn_outline())
}
fn btn_solid_dropdown(&self) -> ButtonBuilder<'a> {
dropdown_button(self.btn_solid())
}
fn btn_outline_popup(&self, text: &'a str) -> ButtonBuilder<'a> {
self.btn_outline_dropdown().label_text(text)
}
fn btn_next(&self) -> ButtonBuilder<'a> {
self.btn_plain_icon_bytes(include_labeled_bytes!("../../icons/next.svg"))
}
fn btn_prev(&self) -> ButtonBuilder<'a> {
self.btn_plain_icon_bytes(include_labeled_bytes!("../../icons/prev.svg"))
}
fn btn_close(&self) -> ButtonBuilder<'a> {
self.btn_plain_icon_bytes(include_labeled_bytes!("../../icons/close.svg"))
.hotkey(Key::Escape)
}
fn btn_close_widget(&self, ctx: &EventCtx) -> Widget {
self.btn_close().build_widget(ctx, "close").align_right()
}
}
impl<'a> StyledButtons<'a> for Style {
fn btn_solid(&self) -> ButtonBuilder<'a> {
basic_button(&self.btn_solid, Some(self.outline_thickness))
}
fn btn_outline(&self) -> ButtonBuilder<'a> {
basic_button(&self.btn_outline, Some(self.outline_thickness))
}
fn btn_solid_floating(&self) -> ButtonBuilder<'a> {
basic_button(&self.btn_solid_floating, Some(self.outline_thickness))
}
fn btn_plain(&self) -> ButtonBuilder<'a> {
basic_button(&self.btn_outline, None)
}
fn btn_plain_destructive(&self) -> ButtonBuilder<'a> {
basic_button(&self.btn_outline_destructive, None)
}
fn btn_solid_destructive(&self) -> ButtonBuilder<'a> {
basic_button(&self.btn_solid_destructive, Some(self.outline_thickness))
}
fn btn_outline_destructive(&self) -> ButtonBuilder<'a> {
basic_button(&self.btn_solid_destructive, Some(self.outline_thickness))
}
}
impl<'a> Style {
pub fn btn_popup_icon_text(&self, icon_path: &'a str, text: &'a str) -> ButtonBuilder<'a> {
let outline_style = &self.btn_outline;
let solid_style = &self.btn_solid;
basic_button(outline_style, Some(self.outline_thickness))
.label_text(text)
.image_path(icon_path)
.image_dims(25.0)
.image_color(solid_style.fg, ControlState::Default)
.image_bg_color(solid_style.bg, ControlState::Default)
.image_bg_color(solid_style.bg_hover, ControlState::Hovered)
.padding(0)
.image_padding(8.0)
.padding_right(8.0)
.image_corner_rounding(CornerRadii {
top_left: 2.0,
top_right: 0.0,
bottom_right: 0.0,
bottom_left: 2.0,
})
}
}
fn icon_button<'a>(builder: ButtonBuilder<'a>) -> ButtonBuilder<'a> {
builder.padding(8.0).image_dims(25.0)
}
fn back_button<'a>(builder: ButtonBuilder<'a>, title: &'a str) -> ButtonBuilder<'a> {
builder
.image_bytes(include_labeled_bytes!("../../icons/nav_back.svg"))
.label_text(title)
.padding_left(8.0)
.font_size(30)
}
fn dropdown_button<'a>(builder: ButtonBuilder<'a>) -> ButtonBuilder<'a> {
builder
.image_bytes(include_labeled_bytes!("../../icons/arrow_drop_down.svg"))
.image_dims(12.0)
.stack_spacing(12.0)
.label_first()
}
fn basic_button<'a>(
button_style: &ButtonStyle,
outline_thickness: Option<f64>,
) -> ButtonBuilder<'a> {
let builder = ButtonBuilder::new()
.label_color(button_style.fg, ControlState::Default)
.label_color(button_style.fg_disabled, ControlState::Disabled)
.image_color(button_style.fg, ControlState::Default)
.image_color(button_style.fg_disabled, ControlState::Disabled)
.bg_color(button_style.bg, ControlState::Default)
.bg_color(button_style.bg_hover, ControlState::Hovered)
.bg_color(button_style.bg_disabled, ControlState::Disabled);
if let Some(outline_thickness) = outline_thickness {
builder.outline(
outline_thickness,
button_style.outline,
ControlState::Default,
)
} else {
builder
}
}