GCC Code Coverage Report


Directory: src/gate/
File: src/gate/ui/checkboxes.c
Date: 2025-09-14 13:10:38
Exec Total Coverage
Lines: 0 25 0.0%
Functions: 0 3 0.0%
Branches: 0 4 0.0%

Line Branch Exec Source
1 /* GATE PROJECT LICENSE:
2 +----------------------------------------------------------------------------+
3 | Copyright(c) 2018-2025, Stefan Meislinger <sm@opengate.at> |
4 | All rights reserved. |
5 | |
6 | Redistribution and use in source and binary forms, with or without |
7 | modification, are permitted provided that the following conditions are met:|
8 | |
9 | 1. Redistributions of source code must retain the above copyright notice, |
10 | this list of conditions and the following disclaimer. |
11 | 2. Redistributions in binary form must reproduce the above copyright |
12 | notice, this list of conditions and the following disclaimer in the |
13 | documentation and/or other materials provided with the distribution. |
14 | |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"|
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
18 | ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
25 | THE POSSIBILITY OF SUCH DAMAGE. |
26 +----------------------------------------------------------------------------+
27 */
28
29 #include "gate/ui/checkboxes.h"
30 #include "gate/results.h"
31
32 #if defined(GATE_UI_WINAPI)
33
34 #include "gate/ui/gateui_winapi.h"
35 #include "gate/platforms.h"
36
37 static gate_bool_t gate_ui_checkbox_events(void* hwnd, gate_ui_ctrl_t* ctrl, gate_uint32_t msg, gate_uintptr_t wParam, gate_intptr_t lParam, gate_intptr_t* lresult)
38 {
39 HWND hwndCtrl;
40 gate_ui_checkbox_t* checkbox;
41 if ((ctrl != NULL) && (hwnd))
42 {
43 hwndCtrl = GATE_UI_WINAPI_GET_HWND(ctrl);
44 if (hwndCtrl)
45 {
46 switch (msg)
47 {
48 case WM_COMMAND:
49 {
50 if (hwndCtrl == (HWND)lParam)
51 {
52 checkbox = (gate_ui_checkbox_t*)ctrl;
53 switch (HIWORD(wParam))
54 {
55 case BN_CLICKED:
56 {
57 if (checkbox->on_click != NULL)
58 {
59 checkbox->on_click(ctrl);
60 }
61 *lresult = 0;
62 return true;
63 }
64 default:
65 {
66 break;
67 }
68 }
69 }
70 break;
71 }
72 default:
73 {
74 break;
75 }
76 }
77 }
78 }
79 return false;
80 }
81
82 #ifndef BST_CHECKED
83 #define BST_CHECKED 1
84 #endif
85
86 #ifndef BST_INDETERMINATE
87 #define BST_INDETERMINATE 2
88 #endif
89 #ifndef BST_UNCHECKED
90 #define BST_UNCHECKED 0
91 #endif
92
93 static gate_result_t gate_ui_checkbox_get_state(gate_ui_ctrl_t* ctrl, gate_int32_t* state)
94 {
95 gate_result_t ret = GATE_RESULT_OK;
96 HWND hwnd = GATE_UI_WINAPI_GET_HWND(ctrl);
97 LRESULT btn_state = SendMessage(hwnd, BM_GETCHECK, 0, 0);
98 switch (btn_state)
99 {
100 case BST_CHECKED:
101 {
102 *state = 1;
103 break;
104 }
105 case BST_INDETERMINATE:
106 {
107 *state = -1;
108 break;
109 }
110 case BST_UNCHECKED:
111 {
112 *state = 0;
113 break;
114 }
115 default:
116 {
117 ret = GATE_RESULT_FAILED;
118 break;
119 }
120 }
121 return ret;
122 }
123
124 static gate_result_t gate_ui_checkbox_set_state(gate_ui_ctrl_t* ctrl, gate_int32_t state)
125 {
126 gate_result_t ret = GATE_RESULT_OK;
127 HWND hwnd = GATE_UI_WINAPI_GET_HWND(ctrl);
128 WPARAM newstate = 0;
129
130 if (state == 0)
131 {
132 newstate = BST_UNCHECKED;
133 }
134 else if (state > 0)
135 {
136 newstate = BST_CHECKED;
137 }
138 else
139 {
140 newstate = BST_INDETERMINATE;
141 }
142 if (0 != SendMessage(hwnd, BM_SETCHECK, newstate, 0))
143 {
144 ret = GATE_RESULT_FAILED;
145 }
146 return ret;
147 }
148
149 static gate_result_t gate_ui_checkbox_refresh(gate_ui_ctrl_t* ctrl)
150 {
151 HWND hwnd_ctrl = GATE_UI_WINAPI_GET_HWND(ctrl);
152 #if defined(GATE_UI_WINAPI_DARKMODE_SUPPORT)
153 gate_ui_winapi_set_window_theme((void*)hwnd_ctrl, L"", L"");
154 #endif /* GATE_UI_WINAPI_DARKMODE_SUPPORT */
155 return gate_ui_winapi_refresh(ctrl);
156 }
157
158 static gate_ui_winapi_dispatchers_t global_win32_checkbox_dispatchers =
159 {
160 &gate_ui_winapi_destroy_with_font,
161 &gate_ui_winapi_is_enabled,
162 &gate_ui_winapi_is_visible,
163 &gate_ui_winapi_is_focused,
164 &gate_ui_winapi_get_position,
165 &gate_ui_winapi_get_size,
166 &gate_ui_winapi_get_children,
167 &gate_ui_winapi_get_text_length,
168 &gate_ui_winapi_get_text,
169 &gate_ui_checkbox_get_state,
170 &gate_ui_winapi_set_enabled,
171 &gate_ui_winapi_set_visible,
172 &gate_ui_winapi_set_focus,
173 &gate_ui_winapi_set_position,
174 &gate_ui_winapi_set_text,
175 &gate_ui_checkbox_set_state,
176 &gate_ui_checkbox_refresh
177 };
178
179 gate_result_t gate_ui_checkbox_create(
180 gate_ui_checkbox_t* checkbox, gate_ui_ctrl_t* parent,
181 gate_ui_position_t const* position,
182 gate_string_t const* caption,
183 gate_uint32_t flags,
184 void* userparam
185 )
186 {
187 gate_result_t ret;
188 gate_uint32_t styles, exstyles;
189 gate_ui_host_t* host;
190 HWND hwndParent;
191 HWND hwndCtrl;
192
193 do
194 {
195 host = gate_ui_ctrl_get_host(parent);
196 if (!host)
197 {
198 ret = GATE_RESULT_INVALIDSTATE;
199 break;
200 }
201 hwndParent = GATE_UI_WINAPI_GET_HWND(parent);
202 if (!hwndParent)
203 {
204 ret = GATE_RESULT_INVALIDSTATE;
205 break;
206 }
207
208 gate_mem_clear(checkbox, sizeof(gate_ui_checkbox_t));
209
210 exstyles = 0;
211 styles = WS_CHILD | WS_CLIPSIBLINGS | WS_TABSTOP | BS_AUTOCHECKBOX | BS_CHECKBOX;
212 #if !defined(GATE_SYS_WIN16)
213 styles |= (BS_MULTILINE | BS_TEXT | BS_VCENTER | BS_NOTIFY);
214 #endif
215
216 #if !defined(GATE_SYS_WINCE) && !defined(GATE_SYS_WIN16)
217 styles |= BS_FLAT;
218 #endif
219 if (!GATE_FLAG_ENABLED(flags, GATE_UI_FLAG_ENABLED)) styles |= WS_DISABLED;
220 if (GATE_FLAG_ENABLED(flags, GATE_UI_FLAG_VISIBLE)) styles |= WS_VISIBLE;
221
222 ret = gate_ui_winapi_create(&checkbox->ctrl, host, (void*)hwndParent,
223 _T("BUTTON"), position, styles, exstyles, caption, userparam, true);
224 if (GATE_SUCCEEDED(ret))
225 {
226 GATE_UI_WINAPI_SET_DISPATCHER(&checkbox->ctrl, &global_win32_checkbox_dispatchers);
227 gate_ui_winapi_register_event(host, (void*)hwndParent, WM_COMMAND, &gate_ui_checkbox_events, &checkbox->ctrl);
228
229 hwndCtrl = GATE_UI_WINAPI_GET_HWND(&checkbox->ctrl);
230 #if defined(GATE_UI_WINAPI_DARKMODE_SUPPORT)
231 gate_ui_winapi_set_window_theme((void*)hwndCtrl, L"", L"");
232 #endif /* GATE_UI_WINAPI_DARKMODE_SUPPORT */
233 }
234 } while (0);
235
236 return ret;
237 }
238
239 #endif /*GATE_UI_WINAPI*/
240
241
242 #if defined(GATE_UI_GTK)
243
244 #include "gate/ui/gateui_gtk.h"
245
246 static gate_uint32_t gate_ui_gtk_checkbox_get_text_length(gate_ui_ctrl_t* ctrl)
247 {
248 gint char_count = 0;
249 gchar const* ptr_text = NULL;
250 GtkButton* checkbox = GTK_BUTTON(GATE_UI_GTK_GET_CTRL_WIDGET(ctrl));
251 if (checkbox)
252 {
253 ptr_text = gtk_button_get_label(checkbox);
254 if (ptr_text)
255 {
256 char_count = gate_str_length(ptr_text);
257 }
258 }
259 return (gate_uint32_t)char_count;
260 }
261 static gate_result_t gate_ui_gtk_checkbox_get_text(gate_ui_ctrl_t* ctrl, gate_string_t* text)
262 {
263 gate_result_t ret = GATE_RESULT_FAILED;
264 gchar const* ptr_text = NULL;
265 GtkButton* checkbox = GTK_BUTTON(GATE_UI_GTK_GET_CTRL_WIDGET(ctrl));
266 if (checkbox)
267 {
268 ptr_text = gtk_button_get_label(checkbox);
269 if (ptr_text)
270 {
271 if (NULL == gate_string_create(text, ptr_text, gate_str_length(ptr_text)))
272 {
273 ret = GATE_RESULT_OUTOFMEMORY;
274 }
275 else
276 {
277 ret = GATE_RESULT_OK;
278 }
279 }
280 else
281 {
282 gate_string_create_empty(text);
283 ret = GATE_RESULT_OK;
284 }
285 }
286 return ret;
287
288 }
289 static gate_result_t gate_ui_gtk_checkbox_set_text(gate_ui_ctrl_t* ctrl, gate_string_t const* text)
290 {
291 gate_result_t ret = GATE_RESULT_FAILED;
292 gchar label[4096];
293 GtkButton* checkbox = GTK_BUTTON(GATE_UI_GTK_GET_CTRL_WIDGET(ctrl));
294 if (checkbox)
295 {
296 gate_str_print_text(label, sizeof(label), text->str, text->length);
297 gtk_button_set_label(checkbox, label);
298 ret = GATE_RESULT_OK;
299 }
300 return ret;
301 }
302 static gate_result_t gate_ui_gtk_checkbox_get_state(gate_ui_ctrl_t* ctrl, gate_int32_t* value)
303 {
304 gate_result_t ret = GATE_RESULT_FAILED;
305 gchar const* ptr_text = NULL;
306 GtkToggleButton* checkbox = GTK_TOGGLE_BUTTON(GATE_UI_GTK_GET_CTRL_WIDGET(ctrl));
307 if (checkbox)
308 {
309 if (gtk_toggle_button_get_active(checkbox))
310 {
311 *value = 1;
312 }
313 else
314 {
315 *value = 0;
316 }
317 ret = GATE_RESULT_OK;
318 }
319 return ret;
320 }
321 static gate_result_t gate_ui_gtk_checkbox_set_state(gate_ui_ctrl_t* ctrl, gate_int32_t value)
322 {
323 gate_result_t ret = GATE_RESULT_FAILED;
324 GtkToggleButton* checkbox = GTK_TOGGLE_BUTTON(GATE_UI_GTK_GET_CTRL_WIDGET(ctrl));
325 if (checkbox)
326 {
327 gtk_toggle_button_set_active(checkbox, (value == 0) ? FALSE : TRUE);
328 ret = GATE_RESULT_OK;
329 }
330 return ret;
331 }
332
333 static gate_ui_gtk_dispatcher_t gate_ui_gtk_checkbox_dispatcher =
334 {
335 gate_ui_gtk_checkbox_get_text_length,
336 gate_ui_gtk_checkbox_get_text,
337 gate_ui_gtk_checkbox_set_text,
338 gate_ui_gtk_checkbox_get_state,
339 gate_ui_gtk_checkbox_set_state,
340 NULL
341 };
342
343
344
345
346 gate_result_t gate_ui_checkbox_create(gate_ui_checkbox_t* checkbox, gate_ui_ctrl_t* parent,
347 gate_ui_position_t const* position, gate_string_t const* caption,
348 gate_uint32_t flags, void* userparam)
349 {
350 gate_result_t ret = GATE_RESULT_OK;
351 GtkWidget* widget;
352 gate_ui_host_t* host = GATE_UI_GTK_GET_CTRL_HOST(parent);
353
354 gate_mem_clear(checkbox, sizeof(checkbox));
355 widget = gtk_check_button_new();
356 if (widget == NULL)
357 {
358 return GATE_RESULT_FAILED;
359 }
360
361 ret = gate_ui_gtk_ctrl_init(&checkbox->ctrl, widget, host, userparam, parent,
362 &gate_ui_gtk_checkbox_dispatcher, false, false, position, &flags);
363
364 if (gate_string_length(caption) > 0)
365 {
366 gate_ui_ctrl_set_text(&checkbox->ctrl, caption);
367 }
368
369 //clicked
370
371 return ret;
372 }
373
374
375 #endif /* GATE_UI_GTK */
376
377
378
379 #if defined(GATE_UI_MOTIF)
380
381 #include "gate/ui/gateui_motif.h"
382 #include <Xm/ToggleB.h>
383
384 static gate_result_t checkbox_get_state(gate_ui_ctrl_t* ctrl, gate_int32_t* ptr_state)
385 {
386 Widget w = NULL;
387 int state = 0;
388 w = GATE_UI_MOTIF_GET_CTRL_WIDGET(ctrl);
389 XtVaGetValues(w, XmNset, &state, NULL);
390 if (ptr_state)
391 {
392 *ptr_state = (state == XmSET) ? 1 : 0;
393 }
394 return GATE_RESULT_OK;
395 }
396
397 static gate_result_t checkbox_set_state(gate_ui_ctrl_t* ctrl, gate_int32_t state)
398 {
399 Widget w = NULL;
400 w = GATE_UI_MOTIF_GET_CTRL_WIDGET(ctrl);
401 XtVaSetValues(w, XmNset, (state ? XmSET : XmUNSET), NULL);
402 return GATE_RESULT_OK;
403 }
404
405 static gate_ui_motif_dispatcher_t checkbox_disp =
406 {
407 NULL,
408 NULL,
409 NULL,
410 &checkbox_get_state,
411 &checkbox_set_state
412 };
413
414
415 gate_result_t gate_ui_checkbox_create(gate_ui_checkbox_t* checkbox, gate_ui_ctrl_t* parent, gate_ui_position_t const* position,
416 gate_string_t const* caption, gate_uint32_t flags, void* userparam)
417 {
418 gate_result_t ret = GATE_RESULT_FAILED;
419 Widget w = NULL;
420 Arg args[8];
421 unsigned args_count = 0;
422
423 do
424 {
425 XtSetArg(args[args_count], XmNtoggleMode, XmTOGGLE_BOOLEAN); ++args_count;
426 XtSetArg(args[args_count], XmNset, XmUNSET); ++args_count;
427 XtSetArg(args[args_count], XmNalignment, XmALIGNMENT_BEGINNING); ++args_count;
428
429 ret = gate_ui_motif_ctrl_create(&checkbox->ctrl, xmToggleButtonWidgetClass, userparam, NULL, parent,
430 position, &flags, false, &checkbox_disp, args, args_count);
431 GATE_BREAK_IF_FAILED(ret);
432
433 w = GATE_UI_MOTIF_GET_CTRL_WIDGET(&checkbox->ctrl);
434 gate_ui_motif_widget_set_label(w, caption);
435
436 } while (0);
437 return ret;
438 }
439
440 #endif /* GATE_UI_MOTIF */
441
442