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 #include "pch.h"
30
31 #include "button.h"
32
33 #include "util.h"
34 #include "container.h"
35 #include "icons.h"
36
37 #include "../common/object.h"
38 #include "../common/context.h"
39
40 using namespace winrt;
41 using namespace Microsoft::
UI::Xaml;
42 using namespace Microsoft::
UI::Xaml::Controls;
43 using namespace Windows::
UI::Xaml::Interop;
44 using namespace winrt::Windows::Foundation;
45 using namespace winrt::Microsoft::
UI::Xaml::Controls::Primitives;
46
47
48
49 void ui_set_button_label(ButtonBase button,
const char* label,
const char* stockid,
const char *icon, UiLabelType type) {
50
51
52 if (type ==
UI_LABEL_ICON) {
53 label =
NULL;
54 }
55 else if (type ==
UI_LABEL_TEXT) {
56 icon =
NULL;
57 }
58
59 IconElement icon_elm = { nullptr };
60 if (icon) {
61 icon_elm = ui_get_icon(icon);
62 }
63
64 if (label && icon_elm) {
65 StackPanel panel = StackPanel();
66 panel.Orientation(Orientation::Horizontal);
67 panel.Spacing(
5);
68
69 panel.Children().Append(icon_elm);
70
71 wchar_t* wlabel = str2wstr(label, nullptr);
72 TextBlock label = TextBlock();
73 label.Text(wlabel);
74 panel.Children().Append(label);
75 free(wlabel);
76
77 button.Content(panel);
78 }
79 else if (label) {
80 wchar_t* wlabel = str2wstr(label, nullptr);
81 button.Content(box_value(wlabel));
82 free(wlabel);
83 }
84 else if (icon_elm) {
85 button.Content(ui_get_icon(icon));
86 }
87 }
88
89
90 UIWIDGET ui_button_create(UiObject* obj, UiButtonArgs args) {
91 UiObject* current = uic_current_obj(obj);
92
93
94 Button button = Button();
95 ui_set_button_label(button, args.label, args.stockid, args.icon, args.labeltype);
96
97
98 UIElement elm = button;
99 UiWidget* widget = new UiWidget(elm);
100 ui_context_add_widget_destructor(current->ctx, widget);
101 ui_set_widget_groups(current->ctx, widget, args.groups);
102
103
104 if (args.onclick) {
105 ui_callback cbfunc = args.onclick;
106 void* cbdata = args.onclickdata;
107 button.Click([cbfunc, cbdata, obj](IInspectable
const& sender, RoutedEventArgs) {
108 UiEvent evt;
109 evt.obj = obj;
110 evt.window = obj->window;
111 evt.document = obj->ctx->document;
112 evt.eventdata = nullptr;
113 evt.intval =
0;
114 cbfunc(&evt, cbdata);
115 });
116 }
117
118
119 UI_APPLY_LAYOUT1(current, args);
120
121 current->container->Add(button, false);
122
123 return widget;
124 }
125
126
127 void togglebutton_register_checked_observers(ToggleButton button, UiObject* obj, UiVar* var) {
128 button.Checked([button, obj, var](IInspectable
const& sender, RoutedEventArgs) {
129 UiInteger* i = (UiInteger*)var->value;
130 UiEvent evt = ui_create_int_event(obj, i->get(i));
131 ui_notify_evt(i->observers, &evt);
132 });
133 }
134
135 void togglebutton_register_unchecked_observers(ToggleButton button, UiObject* obj, UiVar* var) {
136 button.Unchecked([button, obj, var](IInspectable
const& sender, RoutedEventArgs) {
137 UiInteger* i = (UiInteger*)var->value;
138 UiEvent evt = ui_create_int_event(obj, i->get(i));
139 ui_notify_evt(i->observers, &evt);
140 });
141 }
142
143 void togglebutton_register_callback(ToggleButton button, UiObject *obj, UiToggleArgs& args) {
144 ui_callback callback = args.onchange;
145 void* cbdata = args.onchangedata;
146 if (callback) {
147 button.Checked([button, obj, callback, cbdata](IInspectable
const& sender, RoutedEventArgs) {
148 UiEvent evt = ui_create_int_event(obj, true);
149 callback(&evt, cbdata);
150 });
151 button.Unchecked([button, obj, callback, cbdata](IInspectable
const& sender, RoutedEventArgs) {
152 UiEvent evt = ui_create_int_event(obj, false);
153 callback(&evt, cbdata);
154 });
155 }
156 }
157
158
159
160 static void switch_register_observers(ToggleSwitch button, UiObject* obj, UiVar* var) {
161 button.Toggled([button, obj, var](IInspectable
const& sender, RoutedEventArgs) {
162 UiInteger* i = (UiInteger*)var->value;
163 UiEvent evt = ui_create_int_event(obj, i->get(i));
164 ui_notify_evt(i->observers, &evt);
165 });
166 }
167
168 static void switch_register_callback(ToggleSwitch button, UiObject* obj, UiToggleArgs& args) {
169 ui_callback callback = args.onchange;
170 void* cbdata = args.onchangedata;
171 if (callback) {
172 button.Toggled([button, obj, callback, cbdata](IInspectable
const& sender, RoutedEventArgs) {
173 UiEvent evt = ui_create_int_event(obj, button.IsOn());
174 callback(&evt, cbdata);
175 });
176 }
177 }
178
179 static void togglebutton_changed(UiObject *obj, bool checked, ui_callback onchange,
void *onchangedata,
int enable_state) {
180 if (onchange) {
181 UiEvent evt;
182 evt.obj = obj;
183 evt.window = obj->window;
184 evt.document = obj->ctx->document;
185 evt.eventdata = nullptr;
186 evt.intval = checked;
187 onchange(&evt, onchangedata);
188 }
189 if (enable_state >
0) {
190 if (checked) {
191 ui_set_group(obj->ctx, enable_state);
192 }
else {
193 ui_unset_group(obj->ctx, enable_state);
194 }
195 }
196 }
197
198 static UIWIDGET create_togglebutton(UiObject *obj, ToggleButton button, UiToggleArgs args) {
199 UiObject* current = uic_current_obj(obj);
200
201
202 ui_set_button_label(button, args.label, args.stockid, args.icon, args.labeltype);
203 togglebutton_register_callback(button, obj, args);
204
205
206 UIElement elm = button;
207 UiWidget* widget = new UiWidget(elm);
208 ui_context_add_widget_destructor(current->ctx, widget);
209 ui_set_widget_groups(current->ctx, widget, args.groups);
210
211
212 UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.value, args.varname,
UI_VAR_INTEGER);
213 if (var) {
214 UiInteger* value = (UiInteger*)var->value;
215 value->obj = widget;
216 value->get = ui_toggle_button_get;
217 value->set = ui_toggle_button_set;
218
219
220 togglebutton_register_checked_observers(button, obj, var);
221 togglebutton_register_unchecked_observers(button, obj, var);
222 }
223
224 if (args.enable_group >
0 || args.onchange) {
225 button.Checked([obj, args](IInspectable
const& sender, RoutedEventArgs) {
226 togglebutton_changed(obj, true, args.onchange, args.onchangedata, args.enable_group);
227 });
228 button.Unchecked([obj, args](IInspectable
const& sender, RoutedEventArgs) {
229 togglebutton_changed(obj, false, args.onchange, args.onchangedata, args.enable_group);
230 });
231 }
232
233
234 UI_APPLY_LAYOUT1(current, args);
235
236 current->container->Add(button, false);
237
238 return widget;
239 }
240
241 UIWIDGET ui_togglebutton_create(UiObject* obj, UiToggleArgs args) {
242 ToggleButton button = ToggleButton();
243 return create_togglebutton(obj, button, args);
244 }
245
246 UIWIDGET ui_checkbox_create(UiObject* obj, UiToggleArgs args) {
247 CheckBox button = CheckBox();
248 return create_togglebutton(obj, button, args);
249 }
250
251 UIWIDGET ui_switch_create(UiObject* obj, UiToggleArgs args) {
252 ToggleSwitch button = ToggleSwitch();
253 if (args.label) {
254 wchar_t* wlabel = str2wstr(args.label, nullptr);
255 button.Header(box_value(wlabel));
256 free(wlabel);
257 }
258 switch_register_callback(button, obj, args);
259
260 UiObject* current = uic_current_obj(obj);
261
262
263 UIElement elm = button;
264 UiWidget* widget = new UiWidget(elm);
265 ui_context_add_widget_destructor(current->ctx, widget);
266 ui_set_widget_groups(current->ctx, widget, args.groups);
267
268
269 UiVar* var = nullptr;
270 if (args.value) {
271 var = uic_create_value_var(current->ctx, args.value);
272 }
273 else if (args.varname) {
274 var = uic_create_var(obj->ctx, args.varname,
UI_VAR_INTEGER);
275 }
276 if (var) {
277 UiInteger* value = (UiInteger*)var->value;
278 value->obj = widget;
279 value->get = ui_toggle_button_get;
280 value->set = ui_toggle_button_set;
281
282
283 switch_register_observers(button, obj, var);
284 }
285
286
287 UI_APPLY_LAYOUT1(current, args);
288
289 current->container->Add(button, false);
290
291 return widget;
292 }
293
294 UIWIDGET ui_radiobutton_create(UiObject* obj, UiToggleArgs args) {
295 RadioButton button = RadioButton();
296
297 UiObject* current = uic_current_obj(obj);
298
299
300 ui_set_button_label(button, args.label, args.stockid, args.icon, args.labeltype);
301 togglebutton_register_callback(button, obj, args);
302
303
304 UIElement elm = button;
305 UiWidget* widget = new UiWidget(elm);
306 ui_context_add_widget_destructor(current->ctx, widget);
307 ui_set_widget_groups(current->ctx, widget, args.groups);
308
309 UiVar* var = nullptr;
310 if (args.value) {
311 var = uic_create_value_var(current->ctx, args.value);
312 }
313 else if (args.varname) {
314 var = uic_create_var(obj->ctx, args.varname,
UI_VAR_INTEGER);
315 }
316
317
318 if (var) {
319 UiInteger* value = (UiInteger*)var->value;
320
321
322 CxList* radioButtons = (CxList*) (value->obj ? value->obj : cxLinkedListCreate(current->ctx->allocator,
NULL,
CX_STORE_POINTERS));
323
324 static int groupCount =
0;
325 winrt::hstring groupName;
326 if (cxListSize(radioButtons) ==
0) {
327 groupName = winrt::to_hstring(groupCount++);
328 }
else {
329 UiWidget* firstButtonWidget = (UiWidget*)cxListAt(radioButtons,
0);
330 RadioButton firstRadioButton = firstButtonWidget->uielement.as<RadioButton>();
331 groupName = firstRadioButton.GroupName();
332 }
333
334
335 cxListAdd(radioButtons, widget);
336 button.GroupName(groupName);
337
338 value->obj = radioButtons;
339 value->get = ui_radio_button_get;
340 value->set = ui_radio_button_set;
341
342
343 togglebutton_register_checked_observers(button, obj, var);
344 }
345
346
347 UI_APPLY_LAYOUT1(current, args);
348
349 current->container->Add(button, false);
350
351 return widget;
352 }
353
354
355 int64_t ui_toggle_button_get(UiInteger* integer) {
356 UiWidget* widget = (UiWidget*)integer->obj;
357 ToggleButton toggleButton = widget->uielement.as<ToggleButton>();
358 int val = toggleButton.IsChecked().GetBoolean();
359 integer->value = val;
360 return val;
361 }
362
363 void ui_toggle_button_set(UiInteger* integer,
int64_t value) {
364 UiWidget* widget = (UiWidget*)integer->obj;
365 ToggleButton toggleButton = widget->uielement.as<ToggleButton>();
366 toggleButton.IsChecked((bool)value);
367 integer->value = value;
368 }
369
370 int64_t ui_switch_get(UiInteger * integer) {
371 UiWidget* widget = (UiWidget*)integer->obj;
372 ToggleSwitch toggleButton = widget->uielement.as<ToggleSwitch>();
373 int val = toggleButton.IsOn();
374 integer->value = val;
375 return val;
376 }
377
378 void ui_switch_set(UiInteger * integer,
int64_t value) {
379 UiWidget* widget = (UiWidget*)integer->obj;
380 ToggleSwitch toggleButton = widget->uielement.as<ToggleSwitch>();
381 toggleButton.IsOn((bool)value);
382 integer->value = value;
383 }
384
385 int64_t ui_radio_button_get(UiInteger * integer) {
386 CxList* list = (CxList*)integer->obj;
387 CxIterator i = cxListIterator(list);
388 int selection = -
1;
389 cx_foreach(UiWidget*, widget, i) {
390 ToggleButton button = widget->uielement.as<ToggleButton>();
391 if (button.IsChecked().GetBoolean()) {
392 selection = i.index;
393 break;
394 }
395 }
396 integer->value = selection;
397 return selection;
398 }
399
400 void ui_radio_button_set(UiInteger * integer,
int64_t value) {
401 CxList* list = (CxList*)integer->obj;
402 UiWidget* widget = (UiWidget*)cxListAt(list, value);
403 if (widget) {
404 ToggleButton button = widget->uielement.as<ToggleButton>();
405 button.IsChecked(true);
406 integer->value = value;
407 }
408 }
409