GCC Code Coverage Report


Directory: src/gate/
File: src/gate/ui/buttons.c
Date: 2025-12-12 23:40:09
Exec Total Coverage
Lines: 24 30 80.0%
Functions: 3 3 100.0%
Branches: 6 12 50.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/buttons.h"
30 #include "gate/results.h"
31
32 #if defined(GATE_UI_WINAPI)
33
34
35 #include "gate/ui/gateui_winapi.h"
36 #include "gate/platforms.h"
37
38 static gate_bool_t gate_ui_button_events(void* hwnd, gate_ui_ctrl_t* ctrl, gate_uint32_t msg, gate_uintptr_t wParam, gate_intptr_t lParam, gate_intptr_t* lresult)
39 {
40 if ((ctrl != NULL) && (hwnd != NULL))
41 {
42 HWND hwndCtrl = GATE_UI_WINAPI_GET_HWND(ctrl);
43 if (hwndCtrl)
44 {
45 switch (msg)
46 {
47 case WM_COMMAND:
48 {
49 if (hwndCtrl == (HWND)lParam)
50 {
51 gate_ui_button_t* button = (gate_ui_button_t*)ctrl;
52 switch (HIWORD(wParam))
53 {
54 case BN_CLICKED:
55 {
56 if (button->on_click != NULL)
57 {
58 button->on_click(ctrl);
59 }
60 *lresult = 0;
61 return true;
62 }
63 default:
64 {
65 break;
66 }
67 }
68 }
69 break;
70 }
71 default:
72 {
73 break;
74 }
75 }
76 }
77 }
78 return false;
79 }
80
81 gate_result_t gate_ui_button_perform_action(gate_ui_button_t* button, gate_enumint_t action)
82 {
83 gate_ui_ctrl_t* const ctrl = &button->ctrl;
84 HWND const hwnd = GATE_UI_WINAPI_GET_HWND(ctrl);
85 gate_intptr_t lresult = 0;
86 switch (action)
87 {
88 case GATE_UI_ACTION_ACTIVATE:
89 gate_ui_button_events(hwnd, ctrl, WM_COMMAND, (gate_uintptr_t)MAKELONG(0, BN_CLICKED), (gate_uintptr_t)hwnd, &lresult);
90 return GATE_RESULT_OK;
91 default:
92 break;
93 }
94 return GATE_RESULT_NOTSUPPORTED;
95 }
96
97 gate_result_t gate_ui_button_create(
98 gate_ui_button_t* button, gate_ui_ctrl_t* parent,
99 gate_ui_position_t const* position,
100 gate_string_t const* caption,
101 gate_uint32_t flags,
102 void* userparam
103 )
104 {
105 gate_result_t ret;
106 do
107 {
108 gate_uint32_t styles, exstyles;
109 HWND hwndParent;
110 gate_ui_host_t* host = gate_ui_ctrl_get_host(parent);
111 if (!host)
112 {
113 ret = GATE_RESULT_INVALIDSTATE;
114 break;
115 }
116 hwndParent = GATE_UI_WINAPI_GET_HWND(parent);
117 if (!hwndParent)
118 {
119 ret = GATE_RESULT_INVALIDSTATE;
120 break;
121 }
122
123 gate_mem_clear(button, sizeof(gate_ui_button_t));
124
125 exstyles = 0;
126 styles = WS_CHILD | WS_CLIPSIBLINGS | WS_TABSTOP | BS_PUSHBUTTON;
127 #if !defined(GATE_SYS_WIN16)
128 styles |= (BS_MULTILINE | BS_VCENTER);
129 #endif
130 /*styles |= BS_FLAT;*/
131 if (!GATE_FLAG_ENABLED(flags, GATE_UI_FLAG_ENABLED)) styles |= WS_DISABLED;
132 if (GATE_FLAG_ENABLED(flags, GATE_UI_FLAG_VISIBLE)) styles |= WS_VISIBLE;
133
134 ret = gate_ui_winapi_create(&button->ctrl, host, (void*)hwndParent,
135 _T("BUTTON"), position, styles, exstyles, caption, userparam, true);
136 if (GATE_SUCCEEDED(ret))
137 {
138 gate_ui_winapi_register_event(host, (void*)hwndParent, WM_COMMAND, &gate_ui_button_events, &button->ctrl);
139 }
140 } while (0);
141
142 return ret;
143 }
144
145 #endif /*GATE_UI_WINAPI*/
146
147
148 #if defined(GATE_UI_GTK)
149
150 #include "gate/ui/gateui_gtk.h"
151
152 static gate_uint32_t gate_ui_gtk_button_get_text_length(gate_ui_ctrl_t* ctrl)
153 {
154 gint char_count = 0;
155 gchar const* ptr_text = NULL;
156 GtkButton* button = GTK_BUTTON(GATE_UI_GTK_GET_CTRL_WIDGET(ctrl));
157 if (button)
158 {
159 ptr_text = gtk_button_get_label(button);
160 if (ptr_text)
161 {
162 char_count = gate_str_length(ptr_text);
163 }
164 }
165 return (gate_uint32_t)char_count;
166 }
167 static gate_result_t gate_ui_gtk_button_get_text(gate_ui_ctrl_t* ctrl, gate_string_t* text)
168 {
169 gate_result_t ret = GATE_RESULT_FAILED;
170 gchar const* ptr_text = NULL;
171 GtkButton* button = GTK_BUTTON(GATE_UI_GTK_GET_CTRL_WIDGET(ctrl));
172 if (button)
173 {
174 ptr_text = gtk_button_get_label(button);
175 if (ptr_text)
176 {
177 if (NULL == gate_string_create(text, ptr_text, gate_str_length(ptr_text)))
178 {
179 ret = GATE_RESULT_OUTOFMEMORY;
180 }
181 else
182 {
183 ret = GATE_RESULT_OK;
184 }
185 }
186 else
187 {
188 gate_string_create_empty(text);
189 ret = GATE_RESULT_OK;
190 }
191 }
192 return ret;
193
194 }
195 static gate_result_t gate_ui_gtk_button_set_text(gate_ui_ctrl_t* ctrl, gate_string_t const* text)
196 {
197 gate_result_t ret = GATE_RESULT_FAILED;
198 gchar label[4096];
199 GtkButton* button = GTK_BUTTON(GATE_UI_GTK_GET_CTRL_WIDGET(ctrl));
200 if (button)
201 {
202 gate_str_print_text(label, sizeof(label), text->str, text->length);
203 gtk_button_set_label(button, label);
204 ret = GATE_RESULT_OK;
205 }
206 return ret;
207 }
208 static gate_result_t gate_ui_gtk_button_get_state(gate_ui_ctrl_t* ctrl, gate_int32_t* value)
209 {
210 return GATE_RESULT_NOTIMPLEMENTED;
211 }
212 static gate_result_t gate_ui_gtk_button_set_state(gate_ui_ctrl_t* ctrl, gate_int32_t value)
213 {
214 return GATE_RESULT_NOTIMPLEMENTED;
215 }
216
217 static gate_ui_gtk_dispatcher_t gate_ui_gtk_button_dispatcher =
218 {
219 gate_ui_gtk_button_get_text_length,
220 gate_ui_gtk_button_get_text,
221 gate_ui_gtk_button_set_text,
222 NULL,
223 NULL,
224 NULL
225 };
226
227
228 static void gate_ui_button_clicked(GtkButton* button, gpointer user_data)
229 {
230 gate_ui_button_t* button_ctrl = (gate_ui_button_t*)user_data;
231 if (button_ctrl)
232 {
233 if (button_ctrl->on_click != NULL)
234 {
235 button_ctrl->on_click(&button_ctrl->ctrl);
236 }
237 }
238 }
239
240 gate_result_t gate_ui_button_perform_action(gate_ui_button_t* button, gate_enumint_t action)
241 {
242 GtkWidget* widget = GATE_UI_GTK_GET_CTRL_WIDGET(&button->ctrl);
243 switch(action)
244 {
245 case GATE_UI_ACTION_ACTIVATE:
246 gate_ui_button_clicked((GtkButton*)widget, (gpointer)button);
247 return GATE_RESULT_OK;
248 }
249 return GATE_RESULT_NOTSUPPORTED;
250 }
251
252
253 gate_result_t gate_ui_button_create(gate_ui_button_t* button, gate_ui_ctrl_t* parent,
254 gate_ui_position_t const* position, gate_string_t const* caption,
255 gate_uint32_t flags, void* userparam)
256 {
257 gate_result_t ret = GATE_RESULT_OK;
258 GtkWidget* widget;
259 gate_ui_host_t* host = GATE_UI_GTK_GET_CTRL_HOST(parent);
260
261 gate_mem_clear(button, sizeof(gate_ui_button_t));
262 widget = gtk_button_new();
263 if (widget == NULL)
264 {
265 return GATE_RESULT_FAILED;
266 }
267
268 ret = gate_ui_gtk_ctrl_init(&button->ctrl, widget, host, userparam, parent,
269 &gate_ui_gtk_button_dispatcher, false, false, position, &flags);
270
271 if (GATE_SUCCEEDED(ret))
272 {
273 if (gate_string_length(caption) > 0)
274 {
275 gate_ui_ctrl_set_text(&button->ctrl, caption);
276 }
277
278 g_signal_connect(G_OBJECT(widget), "clicked", G_CALLBACK(gate_ui_button_clicked), (gpointer)button);
279 }
280
281 return ret;
282 }
283
284
285 #endif /* GATE_UI_GTK */
286
287 #if defined(GATE_UI_MOTIF)
288
289 #include "gate/ui/gateui_motif.h"
290 #include <Xm/PushB.h>
291
292 1 static void button_pushed(Widget widget, XtPointer client_data, XtPointer call_data)
293 {
294 1 gate_ui_button_t* ptr_button = (gate_ui_button_t*)client_data;
295
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if (!ptr_button || !ptr_button->on_click)
296 {
297 return;
298 }
299 1 ptr_button->on_click(&ptr_button->ctrl);
300 }
301
302 1 gate_result_t gate_ui_button_perform_action(gate_ui_button_t* button, gate_enumint_t action)
303 {
304 1 Widget const w = GATE_UI_MOTIF_GET_CTRL_WIDGET(&button->ctrl);
305
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 switch(action)
306 {
307 1 case GATE_UI_ACTION_ACTIVATE:
308 1 button_pushed(w, (XtPointer)button, NULL);
309 1 return GATE_RESULT_OK;
310 default:
311 break;
312 }
313 return GATE_RESULT_NOTSUPPORTED;
314 }
315
316 2 gate_result_t gate_ui_button_create(gate_ui_button_t* button, gate_ui_ctrl_t* parent,
317 gate_ui_position_t const* position, gate_string_t const* caption,
318 gate_uint32_t flags, void* userparam)
319 {
320 2 gate_result_t ret = GATE_RESULT_FAILED;
321 2 Widget w = NULL;
322 Arg args[8];
323 2 unsigned args_count = 0;
324
325 do
326 {
327
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 if (!button || !parent)
328 {
329 ret = GATE_RESULT_INVALIDARG;
330 break;
331 }
332
333 2 XtSetArg(args[args_count], XmNrecomputeSize, 0); ++args_count;
334 2 XtSetArg(args[args_count], XmNshadowThickness, 1); ++args_count;
335 2 XtSetArg(args[args_count], XmNhighlightThickness, 1); ++args_count;
336
337 2 ret = gate_ui_motif_ctrl_create(&button->ctrl, xmPushButtonWidgetClass, userparam, NULL, parent,
338 position, &flags, false, NULL, args, args_count);
339
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_BREAK_IF_FAILED(ret);
340
341 2 w = GATE_UI_MOTIF_GET_CTRL_WIDGET(&button->ctrl);
342 2 XtAddCallback(w, XmNactivateCallback, &button_pushed, button);
343 2 ret = gate_ui_motif_widget_set_label(w, caption);
344 } while (0);
345
346 2 return ret;
347 }
348
349 #endif /* GATE_UI_MOTIF */
350
351
352 #if defined(GATE_UI_WASMHTML)
353
354 #include "gate/ui/gateui_wasmhtml.h"
355
356 static gate_string_t const html_class_button = GATE_STRING_INIT_STATIC("button");
357
358 gate_result_t gate_ui_button_perform_action(gate_ui_button_t* button, gate_enumint_t action)
359 {
360 return GATE_RESULT_NOTSUPPORTED;
361 }
362
363 gate_result_t gate_ui_button_create(gate_ui_button_t* button, gate_ui_ctrl_t* parent,
364 gate_ui_position_t const* position, gate_string_t const* caption,
365 gate_uint32_t flags, void* userparam)
366 {
367 gate_result_t ret = GATE_RESULT_FAILED;
368 gate_ui_host_t* host = gate_ui_ctrl_get_host(parent);
369 gate_uint32_t parent_id = gate_ui_wasm_ctrl_get_container(parent);
370 gate_uint32_t new_id = 0;
371
372 do
373 {
374 gate_ui_wasm_new_ctrl_id(host, &new_id);
375 ret = gate_ui_wasm_ctrl_create(host, new_id, parent_id, &html_class_button, userparam, &button->ctrl);
376 GATE_BREAK_IF_FAILED(ret);
377
378 if (position)
379 {
380 gate_ui_wasm_ctrl_set_position(&button->ctrl, &position->pos, &position->size);
381 }
382 gate_ui_wasm_ctrl_set_text(&button->ctrl, caption);
383 } while (0);
384
385 return ret;
386 }
387
388 #endif /* GATE_UI_WASMHTML */
389
390