GCC Code Coverage Report


Directory: src/gate/
File: src/gate/ui/panels.c
Date: 2026-09-21 06:26:40
Exec Total Coverage
Lines: 122 141 86.5%
Functions: 8 8 100.0%
Branches: 18 34 52.9%

Line Branch Exec Source
1 /* GATE PROJECT LICENSE:
2 +----------------------------------------------------------------------------+
3 | Copyright (c) 2018-2026, 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/panels.h"
30 #include "gate/results.h"
31 #include <stdio.h>
32
33 #if defined(GATE_UI_WINAPI)
34
35 #include "gate/ui/gateui_winapi.h"
36 #include "gate/platforms.h"
37
38
39 static gate_bool_t WINAPI gate_ui_panel_events(ui_hwnd_t ui_hwnd, gate_ui_ctrl_t* ctrl, gate_uint32_t msg, gate_uintptr_t wParam, gate_intptr_t lParam, gate_intptr_t* lresult)
40 {
41 if (ctrl != NULL)
42 {
43 HWND hwnd = (HWND)ui_hwnd;
44 HWND hwnd_ctrl = (HWND)GATE_UI_WINAPI_GET_HWND(ctrl);
45 if (hwnd == hwnd_ctrl)
46 {
47 gate_ui_panel_t* panel = (gate_ui_panel_t*)ctrl;
48 switch (msg)
49 {
50 #if !defined(GATE_SYS_WIN16)
51 case WM_CTLCOLOREDIT:
52 case WM_CTLCOLORBTN:
53 case WM_CTLCOLORLISTBOX:
54 case WM_CTLCOLORMSGBOX:
55 case WM_CTLCOLORSCROLLBAR:
56 case WM_CTLCOLORDLG:
57 case WM_CTLCOLORSTATIC:
58 {
59 *lresult = SendMessage(GetParent((HWND)hwnd), msg, wParam, lParam);
60 return true;
61 }
62 #endif
63 case WM_MOVE:
64 {
65 gate_ui_point_t pnt;
66 pnt.x = (int)(short)LOWORD(lParam);
67 pnt.y = (int)(short)HIWORD(lParam);
68 if (panel->on_move != NULL)
69 {
70 panel->on_move(ctrl, &pnt);
71 }
72 *lresult = 0;
73 break;
74 }
75 case WM_SIZE:
76 {
77 gate_ui_size_t sz;
78 if (panel->layout != NULL)
79 {
80 gate_ui_position_t position;
81 gate_ui_host_t* host = GATE_UI_WINAPI_GET_HOST(&panel->ctrl);
82 gate_uint32_t lineheight = gate_ui_host_default_control_height(host, 1);
83 position.pos.x = 0;
84 position.pos.y = 0;
85 gate_ui_ctrl_get_size(&panel->ctrl, &position.size);
86 gate_ui_layout_apply(panel->layout, lineheight, &position);
87 }
88 sz.width = (int)(short)LOWORD(lParam);
89 sz.height = (int)(short)HIWORD(lParam);
90 if (panel->on_resize != NULL)
91 {
92 panel->on_resize(ctrl, &sz);
93 }
94 break;
95 }
96 case WM_ERASEBKGND:
97 {
98 RECT rect;
99 HDC hdc = hdc = (HDC)wParam;
100 HBRUSH bk_ground;
101
102 GetClientRect(hwnd_ctrl, &rect);
103 #if defined(GATE_SYS_WIN16)
104 bk_ground = (HBRUSH)GetStockObject(WHITE_BRUSH);
105 #else
106 bk_ground = (HBRUSH)SendMessage(hwnd_ctrl, WM_CTLCOLORDLG, (WPARAM)hdc, (LPARAM)hwnd_ctrl);
107 #endif
108 FillRect(hdc, &rect, bk_ground);
109 *lresult = TRUE;
110 return true;
111 }
112 }
113 }
114 }
115 return false;
116 }
117
118 gate_result_t gate_ui_panel_create(
119 gate_ui_panel_t* panel, gate_ui_ctrl_t* parent,
120 gate_ui_position_t const* position, gate_uint32_t flags, void* userparam)
121 {
122 gate_result_t ret;
123
124 do
125 {
126 gate_uint32_t styles = WS_CHILD | WS_GROUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
127 gate_uint32_t exstyles = 0;
128 gate_ui_host_t* host = gate_ui_ctrl_get_host(parent);
129 ui_hwnd_t hwndParent;
130 if (host == NULL)
131 {
132 ret = GATE_RESULT_INVALIDSTATE;
133 break;
134 }
135 hwndParent = GATE_UI_WINAPI_GET_HWND(parent);
136 if (hwndParent == UI_HWND_NULL)
137 {
138 ret = GATE_RESULT_INVALIDSTATE;
139 break;
140 }
141
142 gate_mem_clear(panel, sizeof(gate_ui_panel_t));
143
144 #if !defined(GATE_SYS_WINCE) && !defined(GATE_SYS_WIN16)
145 exstyles |= WS_EX_CONTROLPARENT;
146 #endif
147
148 if (!GATE_FLAG_ENABLED(flags, GATE_UI_FLAG_ENABLED)) styles |= WS_DISABLED;
149 if (GATE_FLAG_ENABLED(flags, GATE_UI_FLAG_VISIBLE)) styles |= WS_VISIBLE;
150
151 ret = gate_ui_winapi_create(&panel->ctrl, host, hwndParent, NULL, position, styles, exstyles, NULL, userparam, false);
152 if (GATE_SUCCEEDED(ret))
153 {
154 ui_hwnd_t hwnd = GATE_UI_WINAPI_GET_HWND(&panel->ctrl);
155 gate_ui_winapi_register_event(host, hwnd, WM_MOVE, &gate_ui_panel_events, &panel->ctrl);
156 gate_ui_winapi_register_event(host, hwnd, WM_SIZE, &gate_ui_panel_events, &panel->ctrl);
157 gate_ui_winapi_register_event(host, hwnd, WM_ERASEBKGND, &gate_ui_panel_events, &panel->ctrl);
158
159 #if !defined(GATE_SYS_WIN16)
160 gate_ui_winapi_register_event(host, hwnd, WM_CTLCOLORDLG, &gate_ui_panel_events, &panel->ctrl);
161 gate_ui_winapi_register_event(host, hwnd, WM_CTLCOLORSTATIC, &gate_ui_panel_events, &panel->ctrl);
162 gate_ui_winapi_register_event(host, hwnd, WM_CTLCOLOREDIT, &gate_ui_panel_events, &panel->ctrl);
163 gate_ui_winapi_register_event(host, hwnd, WM_CTLCOLORBTN, &gate_ui_panel_events, &panel->ctrl);
164 gate_ui_winapi_register_event(host, hwnd, WM_CTLCOLORLISTBOX, &gate_ui_panel_events, &panel->ctrl);
165 gate_ui_winapi_register_event(host, hwnd, WM_CTLCOLORMSGBOX, &gate_ui_panel_events, &panel->ctrl);
166 gate_ui_winapi_register_event(host, hwnd, WM_CTLCOLORSCROLLBAR, &gate_ui_panel_events, &panel->ctrl);
167 #endif
168 }
169
170 } while (0);
171
172 return ret;
173 }
174
175
176 gate_result_t gate_ui_panel_set_layout(gate_ui_panel_t* panel, gate_ui_layout_t const* layout)
177 {
178 panel->layout = layout;
179 if (layout != NULL)
180 {
181 if (gate_ui_ctrl_is_created(&panel->ctrl))
182 {
183 gate_ui_host_t* host = GATE_UI_WINAPI_GET_HOST(&panel->ctrl);
184 gate_uint32_t line_height = gate_ui_host_default_control_height(host, 1);
185 gate_ui_position_t pose;
186
187 pose.pos.x = 0;
188 pose.pos.y = 0;
189 gate_ui_ctrl_get_size(&panel->ctrl, &pose.size);
190 gate_ui_layout_apply(layout, line_height, &pose);
191 }
192 }
193 return GATE_RESULT_OK;
194 }
195
196
197
198
199
200 static void WINAPI gate_ui_framepanel_calc_client_border(gate_int32_t line_height, LPRECT rect)
201 {
202 gate_int32_t border = line_height * 2 / 3;
203 rect->left = border;
204 rect->right = border;
205 rect->top = line_height + border / 2;
206 rect->bottom = border;
207 }
208
209 static gate_bool_t WINAPI gate_ui_framepanel_events(ui_hwnd_t ui_hwnd, gate_ui_ctrl_t* ctrl, gate_uint32_t msg, gate_uintptr_t wParam, gate_intptr_t lParam, gate_intptr_t* lresult)
210 {
211 #if !defined(GATE_SYS_WINCE) && !defined(GATE_SYS_WIN16)
212 #endif
213
214 if (ctrl != NULL)
215 {
216 const HWND hwnd = (HWND)ui_hwnd;
217 const HWND hwnd_ctrl = (HWND)GATE_UI_WINAPI_GET_HWND(ctrl);
218 if (hwnd == hwnd_ctrl)
219 {
220 gate_ui_framepanel_t* frame = (gate_ui_framepanel_t*)ctrl;
221 switch (msg)
222 {
223 #if !defined(GATE_SYS_WIN16)
224 case WM_CTLCOLOREDIT:
225 case WM_CTLCOLORBTN:
226 case WM_CTLCOLORLISTBOX:
227 case WM_CTLCOLORMSGBOX:
228 case WM_CTLCOLORSCROLLBAR:
229 case WM_CTLCOLORDLG:
230 case WM_CTLCOLORSTATIC:
231 {
232 *lresult = SendMessage(GetParent(hwnd), msg, wParam, lParam);
233 return true;
234 }
235 #endif
236 case WM_MOVE:
237 {
238 gate_ui_point_t pnt;
239 pnt.x = (int)(short)LOWORD(lParam);
240 pnt.y = (int)(short)HIWORD(lParam);
241 if (frame->on_move != NULL)
242 {
243 frame->on_move(ctrl, &pnt);
244 }
245 break;
246 }
247 case WM_SIZE:
248 {
249 gate_ui_size_t sz;
250 sz.width = (int)(short)LOWORD(lParam);
251 sz.height = (int)(short)HIWORD(lParam);
252 if (frame->layout != NULL)
253 {
254 gate_ui_host_t* host = GATE_UI_WINAPI_GET_HOST(&frame->ctrl);
255 gate_uint32_t lineheight = gate_ui_host_default_control_height(host, 1);
256 gate_ui_position_t position;
257 position.pos.x = 0;
258 position.pos.y = 0;
259 position.size.width = sz.width;
260 position.size.height = sz.height;
261 gate_ui_layout_apply(frame->layout, lineheight, &position);
262 }
263 if (frame->on_resize != NULL)
264 {
265 frame->on_resize(ctrl, &sz);
266 }
267 /*RedrawWindow(hwnd_ctrl, NULL, NULL, RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);*/
268 break;
269 }
270 case WM_ERASEBKGND:
271 {
272 HDC hdc = (HDC)wParam;
273 HBRUSH bk_ground;
274 RECT rect;
275 GetClientRect(hwnd_ctrl, &rect);
276 #if defined(GATE_SYS_WIN16)
277 bk_ground = (HBRUSH)GetStockObject(WHITE_BRUSH);
278 #else
279 bk_ground = (HBRUSH)SendMessage(hwnd_ctrl, WM_CTLCOLORDLG, (WPARAM)hdc, (LPARAM)hwnd_ctrl);
280 #endif
281 FillRect(hdc, &rect, bk_ground);
282 *lresult = TRUE;
283 return true;
284 }
285
286 #if !defined(GATE_SYS_WINCE) && !defined(GATE_SYS_WIN16)
287 case WM_NCHITTEST:
288 {
289 *lresult = HTBORDER;
290 return true;
291 }
292 case WM_NCCALCSIZE:
293 {
294 gate_ui_host_t* host = GATE_UI_WINAPI_GET_HOST(ctrl);
295 gate_int32_t lineheight;
296 LPRECT lprect = NULL;
297 gate_ui_font_t font;
298 NCCALCSIZE_PARAMS* nccalcsize;
299 RECT border;
300
301 gate_ui_host_default_font(host, GATE_UI_FONT_TYPE_STANDARD, &font);
302 lineheight = font.size;
303 if (wParam)
304 {
305 nccalcsize = (NCCALCSIZE_PARAMS*)lParam;
306 lprect = &nccalcsize->rgrc[0];
307 *lresult = 0 /* | WVR_ALIGNLEFT | WVR_ALIGNTOP| WVR_ALIGNRIGHT | WVR_ALIGNBOTTOM | WVR_REDRAW */;
308 }
309 else
310 {
311 nccalcsize = NULL;
312 lprect = (RECT*)lParam;
313 *lresult = 0;
314 }
315 gate_ui_framepanel_calc_client_border(lineheight, &border);
316 lprect->left += border.left;
317 lprect->right -= border.right;
318 lprect->top += border.top;
319 lprect->bottom -= border.bottom;
320 //InvalidateRect(hwnd, NULL, true);
321 return true;
322 }
323 case WM_NCPAINT:
324 {
325 gate_ui_host_t* host = GATE_UI_WINAPI_GET_HOST(ctrl);
326 gate_int32_t lineheight;
327 RECT rect;
328 HDC hdc;
329 HBRUSH bk_ground;
330 gate_ui_font_t font;
331 RECT border;
332
333 gate_ui_host_default_font(host, GATE_UI_FONT_TYPE_STANDARD, &font);
334 lineheight = font.size;
335 gate_ui_framepanel_calc_client_border(lineheight, &border);
336
337 GetWindowRect(hwnd_ctrl, &rect);
338 rect.bottom -= rect.top;
339 rect.right -= rect.left;
340 rect.top = 0;
341 rect.left = 0;
342 hdc = GetWindowDC(hwnd_ctrl);
343 if (hdc != NULL)
344 {
345 HFONT hfont;
346 TCHAR text[2048];
347 int textlen = sizeof(text) / sizeof(text[0]);
348 HRGN hrgnall, hrgnclient;
349
350
351 bk_ground = (HBRUSH)SendMessage(GetParent(hwnd_ctrl), WM_CTLCOLORSTATIC, (WPARAM)hdc, (LPARAM)hwnd_ctrl);
352
353 hrgnall = CreateRectRgn(0, 0, rect.right, rect.bottom);
354 hrgnclient = CreateRectRgn(border.left, border.top, rect.right - border.right, rect.bottom - border.bottom);
355 CombineRgn(hrgnall, hrgnall, hrgnclient, RGN_XOR);
356 DeleteObject((HGDIOBJ)hrgnclient);
357 hrgnclient = (HGDIOBJ)SelectObject(hdc, hrgnall);
358
359 FillRect(hdc, &rect, bk_ground);
360 rect.top = lineheight / 2;
361 #if defined(GATE_UI_WINAPI_DARKMODE_SUPPORT)
362 if (gate_ui_winapi_is_darkmode_applied(hwnd_ctrl))
363 {
364 HPEN hpen = CreatePen(PS_SOLID, 0, RGB(128, 128, 128));
365 HGDIOBJ oldpen = SelectObject(hdc, (HGDIOBJ)hpen);
366 rect.bottom -= 1;
367 rect.right -= 1;
368 MoveToEx(hdc, rect.left, rect.top, NULL);
369 LineTo(hdc, rect.right, rect.top);
370 LineTo(hdc, rect.right, rect.bottom);
371 LineTo(hdc, rect.left, rect.bottom);
372 LineTo(hdc, rect.left, rect.top);
373 SelectObject(hdc, oldpen);
374 DeleteObject((HGDIOBJ)hpen);
375 }
376 else
377 #endif /* GATE_UI_WINAPI_DARKMODE_SUPPORT */
378 {
379 DrawEdge(hdc, &rect, EDGE_ETCHED, BF_RECT);
380 }
381
382 rect.top = 0;
383 rect.left = lineheight;
384 rect.bottom = lineheight;
385 textlen = GetWindowText(hwnd_ctrl, text, textlen - 1);
386
387 hfont = (HFONT)gate_ui_winapi_create_font(&font);
388 if (hfont != NULL)
389 {
390 HGDIOBJ oldgdi = SelectObject(hdc, (HGDIOBJ)hfont);
391 DrawText(hdc, text, textlen, &rect, DT_TOP | DT_LEFT | DT_NOCLIP);
392 SelectObject(hdc, oldgdi);
393 gate_ui_winapi_destroy_font(hfont);
394 }
395 SelectObject(hdc, (HGDIOBJ)hrgnclient);
396 DeleteObject((HGDIOBJ)hrgnall);
397 ReleaseDC(hwnd_ctrl, hdc);
398 }
399 *lresult = 0;
400 return true;
401 }
402 #endif
403 }
404 }
405 }
406 return false;
407 }
408
409 gate_result_t gate_ui_framepanel_create(
410 gate_ui_framepanel_t* panel, gate_ui_ctrl_t* parent, gate_ui_position_t const* position,
411 gate_string_t const* text, gate_uint32_t flags, void* userparam)
412 {
413 gate_result_t ret;
414 do
415 {
416 gate_uint32_t styles = WS_CHILD | WS_GROUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
417 gate_uint32_t exstyles = 0;
418 ui_hwnd_t hwndParent;
419 gate_ui_host_t* host = gate_ui_ctrl_get_host(parent);
420 if (host == NULL)
421 {
422 ret = GATE_RESULT_INVALIDSTATE;
423 break;
424 }
425 hwndParent = GATE_UI_WINAPI_GET_HWND(parent);
426 if (hwndParent == UI_HWND_NULL)
427 {
428 ret = GATE_RESULT_INVALIDSTATE;
429 break;
430 }
431
432 gate_mem_clear(panel, sizeof(gate_ui_framepanel_t));
433
434 #if !defined(GATE_SYS_WINCE) && !defined(GATE_SYS_WIN16)
435 exstyles |= WS_EX_CONTROLPARENT;
436 #endif
437
438 if (!GATE_FLAG_ENABLED(flags, GATE_UI_FLAG_ENABLED)) styles |= WS_DISABLED;
439 if (GATE_FLAG_ENABLED(flags, GATE_UI_FLAG_VISIBLE)) styles |= WS_VISIBLE;
440
441 ret = gate_ui_winapi_create(&panel->ctrl, host, hwndParent, NULL, position, styles, exstyles, text, userparam, false);
442 if (GATE_SUCCEEDED(ret))
443 {
444 ui_hwnd_t hwnd = GATE_UI_WINAPI_GET_HWND(&panel->ctrl);
445 #if defined(GATE_SYS_WINCE) || defined(GATE_SYS_WIN16)
446 #else
447 gate_ui_winapi_register_event(host, hwnd, WM_NCCALCSIZE, &gate_ui_framepanel_events, &panel->ctrl);
448 gate_ui_winapi_register_event(host, hwnd, WM_NCPAINT, &gate_ui_framepanel_events, &panel->ctrl);
449 gate_ui_winapi_register_event(host, hwnd, WM_ERASEBKGND, &gate_ui_framepanel_events, &panel->ctrl);
450
451 gate_ui_winapi_register_event(host, hwnd, WM_CTLCOLORDLG, &gate_ui_framepanel_events, &panel->ctrl);
452 gate_ui_winapi_register_event(host, hwnd, WM_CTLCOLORSTATIC, &gate_ui_framepanel_events, &panel->ctrl);
453 gate_ui_winapi_register_event(host, hwnd, WM_CTLCOLOREDIT, &gate_ui_framepanel_events, &panel->ctrl);
454 gate_ui_winapi_register_event(host, hwnd, WM_CTLCOLORBTN, &gate_ui_framepanel_events, &panel->ctrl);
455 gate_ui_winapi_register_event(host, hwnd, WM_CTLCOLORLISTBOX, &gate_ui_framepanel_events, &panel->ctrl);
456 gate_ui_winapi_register_event(host, hwnd, WM_CTLCOLORMSGBOX, &gate_ui_framepanel_events, &panel->ctrl);
457 gate_ui_winapi_register_event(host, hwnd, WM_CTLCOLORSCROLLBAR, &gate_ui_framepanel_events, &panel->ctrl);
458
459 #endif
460
461 gate_ui_winapi_register_event(host, hwnd, WM_MOVE, &gate_ui_framepanel_events, &panel->ctrl);
462 gate_ui_winapi_register_event(host, hwnd, WM_SIZE, &gate_ui_framepanel_events, &panel->ctrl);
463
464 SetWindowPos((HWND)hwnd,
465 NULL, position->pos.x, position->pos.y, position->size.width, position->size.height,
466 SWP_DRAWFRAME | SWP_FRAMECHANGED);
467 }
468
469 } while (0);
470
471 return ret;
472 }
473
474
475 gate_result_t gate_ui_framepanel_set_layout(gate_ui_framepanel_t* panel, gate_ui_layout_t const* layout)
476 {
477 panel->layout = layout;
478 if (layout != NULL)
479 {
480 if (gate_ui_ctrl_is_created(&panel->ctrl))
481 {
482 gate_ui_host_t* host = GATE_UI_WINAPI_GET_HOST(&panel->ctrl);
483 gate_uint32_t line_height = gate_ui_host_default_control_height(host, 1);
484 gate_ui_position_t pose;
485 pose.pos.x = 0;
486 pose.pos.y = 0;
487 gate_ui_ctrl_get_size(&panel->ctrl, &pose.size);
488 gate_ui_layout_apply(layout, line_height, &pose);
489 }
490 }
491 return GATE_RESULT_OK;
492 }
493
494 #endif /* GATE_UI_WINAPI */
495
496
497 #if defined(GATE_UI_GTK)
498
499 #include "gate/ui/gateui_gtk.h"
500
501
502 static gboolean gate_ui_panel_refresh_idle_callback(gpointer user_data)
503 {
504 gate_ui_panel_t* panel = (gate_ui_panel_t*)user_data;
505 gate_ui_panel_refresh(panel);
506 return FALSE; /* FALSE means: do not invoke this callback again (until next call to g_idle_add()) */
507 }
508
509 static void gate_ui_panel_check_resize(GtkContainer* container, gpointer user_data)
510 {
511 gate_ui_panel_t* panel = (gate_ui_panel_t*)user_data;
512 g_idle_add(&gate_ui_panel_refresh_idle_callback, panel);
513 }
514
515 static void gate_ui_panel_size_allocate(GtkWidget* widget, GdkRectangle* allocation, gpointer user_data)
516 {
517 gate_ui_panel_t* panel = (gate_ui_panel_t*)user_data;
518 g_idle_add(&gate_ui_panel_refresh_idle_callback, panel);
519 }
520
521 static gboolean gate_ui_panel_event_configure(GtkWindow* window, GdkEventConfigure* evt, gpointer data)
522 {
523 gate_ui_panel_t* panel = (gate_ui_panel_t*)data;
524 gate_ui_position_t position;
525
526 g_idle_add(&gate_ui_panel_refresh_idle_callback, panel);
527
528 position.pos.x = evt->x;
529 position.pos.y = evt->y;
530 position.size.width = evt->width;
531 position.size.height = evt->height;
532
533 if (panel->on_move != NULL)
534 {
535 panel->on_move(&panel->ctrl, &position.pos);
536 }
537 if (panel->on_resize != NULL)
538 {
539 panel->on_resize(&panel->ctrl, &position.size);
540 }
541 return FALSE;
542 }
543
544 static gate_result_t gate_ui_gtk_panel_refresh(gate_ui_ctrl_t* ctrl)
545 {
546 gate_ui_panel_t* panel = (gate_ui_panel_t*)ctrl;
547 g_idle_add(&gate_ui_panel_refresh_idle_callback, panel);
548 return gate_ui_panel_refresh(panel);
549 }
550 static gate_result_t gate_ui_gtk_panel_destroy(gate_ui_ctrl_t* ctrl)
551 {
552 gate_result_t ret = gate_ui_gtk_ctrl_destroy_native(ctrl);
553 return ret;
554 }
555
556
557 static gate_ui_gtk_dispatcher_t gate_ui_gtk_panel_dispatcher =
558 {
559 NULL /*get_text_length*/,
560 NULL /*get_text*/,
561 NULL /*set_text*/,
562 NULL /*get_state*/,
563 NULL /*set_state*/,
564 &gate_ui_gtk_panel_refresh,
565 &gate_ui_gtk_panel_destroy
566 };
567
568
569
570 gate_result_t gate_ui_panel_create(
571 gate_ui_panel_t* panel, gate_ui_ctrl_t* parent,
572 gate_ui_position_t const* position, gate_uint32_t flags, void* userparam)
573 {
574 gate_result_t ret = GATE_RESULT_OK;
575
576 do
577 {
578 gate_ui_host_t* host = parent ? GATE_UI_GTK_GET_CTRL_HOST(parent) : NULL;
579 GtkWidget* widget = gtk_layout_new(NULL, NULL);
580
581 if (widget == NULL)
582 {
583 ret = GATE_RESULT_OUTOFRESOURCES;
584 break;
585 }
586
587 gate_mem_clear(panel, sizeof(gate_ui_panel_t));
588
589 ret = gate_ui_gtk_ctrl_init(&panel->ctrl, widget, host, userparam, parent,
590 &gate_ui_gtk_panel_dispatcher, false, false, position, &flags);
591 GATE_BREAK_IF_FAILED(ret);
592
593 gtk_widget_add_events(widget, GDK_STRUCTURE_MASK);
594
595 g_signal_connect(G_OBJECT(widget), "configure-event", G_CALLBACK(gate_ui_panel_event_configure), (gpointer)panel);
596 g_signal_connect(G_OBJECT(widget), "check-resize", G_CALLBACK(gate_ui_panel_check_resize), (gpointer)panel);
597 //g_signal_connect(G_OBJECT(widget), "size-allocate", G_CALLBACK(gate_ui_panel_size_allocate), (gpointer)panel);
598 } while (0);
599
600 return ret;
601 }
602
603 gate_result_t gate_ui_panel_set_layout(gate_ui_panel_t* panel, gate_ui_layout_t const* layout)
604 {
605 gate_result_t ret = GATE_RESULT_OK;
606 panel->layout = layout;
607 if (layout != NULL)
608 {
609 if (gate_ui_ctrl_is_created(&panel->ctrl))
610 {
611 gate_ui_host_t* host = GATE_UI_GTK_GET_CTRL_HOST(&panel->ctrl);
612 gate_uint32_t line_height = gate_ui_host_default_control_height(host, 1);
613 gate_ui_position_t pose;
614 pose.pos.x = 0;
615 pose.pos.y = 0;
616 gate_ui_ctrl_get_size(&panel->ctrl, &pose.size);
617 ret = gate_ui_layout_apply(layout, line_height, &pose);
618 }
619 }
620 return ret;
621 }
622
623 gate_result_t gate_ui_panel_refresh(gate_ui_panel_t* panel)
624 {
625 gate_result_t ret = GATE_RESULT_OK;
626 if (panel->layout != NULL)
627 {
628 GtkWidget* widget = GATE_UI_GTK_GET_CTRL_WIDGET(&panel->ctrl);
629 gate_ui_host_t* host = GATE_UI_GTK_GET_CTRL_HOST(&panel->ctrl);
630 gate_uint32_t unit_height = gate_ui_host_default_control_height(host, 1);
631 gate_ui_position_t position;
632 GtkAllocation widget_alloc;
633
634 gtk_widget_get_allocation(GTK_WIDGET(widget), &widget_alloc);
635 position.pos.x = 0;
636 position.pos.y = 0;
637 position.size.width = widget_alloc.width;
638 position.size.height = widget_alloc.height;
639 ret = gate_ui_layout_apply(panel->layout, unit_height, &position);
640 }
641 return ret;
642 }
643
644
645
646
647
648 static gate_uint32_t gate_ui_gtk_framepanel_get_text_length(gate_ui_ctrl_t* ctrl)
649 {
650 gint char_count = 0;
651 GtkFrame* frame = GTK_FRAME(GATE_UI_GTK_GET_CTRL_WIDGET(ctrl));
652 if (frame)
653 {
654 gchar const* ptr_text = gtk_frame_get_label(frame);
655 if (ptr_text)
656 {
657 char_count = gate_str_length(ptr_text);
658 }
659 }
660 return (gate_uint32_t)char_count;
661 }
662 static gate_result_t gate_ui_gtk_framepanel_get_text(gate_ui_ctrl_t* ctrl, gate_string_t* text)
663 {
664 gate_result_t ret = GATE_RESULT_FAILED;
665 GtkFrame* frame = GTK_FRAME(GATE_UI_GTK_GET_CTRL_WIDGET(ctrl));
666 if (frame)
667 {
668 gchar const* ptr_text = gtk_frame_get_label(frame);
669 if (ptr_text)
670 {
671 if (NULL == gate_string_create(text, ptr_text, gate_str_length(ptr_text)))
672 {
673 ret = GATE_RESULT_OUTOFMEMORY;
674 }
675 else
676 {
677 ret = GATE_RESULT_OK;
678 }
679 }
680 else
681 {
682 gate_string_create_empty(text);
683 ret = GATE_RESULT_OK;
684 }
685 }
686 return ret;
687
688 }
689 static gate_result_t gate_ui_gtk_framepanel_set_text(gate_ui_ctrl_t* ctrl, gate_string_t const* text)
690 {
691 gate_result_t ret = GATE_RESULT_FAILED;
692 GtkFrame* frame = GTK_FRAME(GATE_UI_GTK_GET_CTRL_WIDGET(ctrl));
693 if (frame)
694 {
695 gchar label[4096];
696 gate_str_print_text(label, sizeof(label), text->str, text->length);
697 gtk_frame_set_label(frame, label);
698 ret = GATE_RESULT_OK;
699 }
700 return ret;
701 }
702 static gate_result_t gate_ui_gtk_framepanel_refresh(gate_ui_ctrl_t* ctrl)
703 {
704 gate_result_t ret = GATE_RESULT_OK;
705 gate_ui_framepanel_t* frame = (gate_ui_framepanel_t*)ctrl;
706 if (frame->layout)
707 {
708 ret = gate_ui_gtk_ctrl_apply_layout(ctrl, frame->layout, 0);
709 }
710 return ret;
711 }
712
713
714 static gate_ui_gtk_dispatcher_t gate_ui_gtk_framepanel_dispatcher =
715 {
716 &gate_ui_gtk_framepanel_get_text_length,
717 &gate_ui_gtk_framepanel_get_text,
718 &gate_ui_gtk_framepanel_set_text,
719 NULL,
720 NULL,
721 &gate_ui_gtk_framepanel_refresh
722 };
723
724
725
726 gate_result_t gate_ui_framepanel_create(
727 gate_ui_framepanel_t* frame, gate_ui_ctrl_t* parent,
728 gate_ui_position_t const* position,
729 gate_string_t const* text,
730 gate_uint32_t flags,
731 void* userparam
732 )
733 {
734 gate_result_t ret = GATE_RESULT_FAILED;
735 do
736 {
737 gate_ui_host_t* host = GATE_UI_GTK_GET_CTRL_HOST(parent);
738 GtkWidget* widget = gtk_frame_new("");
739 if (widget == NULL)
740 {
741 ret = GATE_RESULT_FAILED;
742 break;
743 }
744 gate_mem_clear(frame, sizeof(gate_ui_framepanel_t));
745
746 ret = gate_ui_gtk_ctrl_init(&frame->ctrl, widget, host, userparam, parent,
747 &gate_ui_gtk_framepanel_dispatcher, true, true,
748 position, &flags
749 );
750 GATE_BREAK_IF_FAILED(ret);
751
752 if (gate_string_length(text) > 0)
753 {
754 ret = gate_ui_ctrl_set_text(&frame->ctrl, text);
755 GATE_BREAK_IF_FAILED(ret);
756 }
757
758 } while (0);
759
760 return ret;
761 }
762
763 gate_result_t gate_ui_framepanel_set_layout(
764 gate_ui_framepanel_t* panel,
765 gate_ui_layout_t const* layout
766 )
767 {
768 panel->layout = layout;
769 return GATE_RESULT_OK;
770 }
771
772 #endif /* GATE_UI_GTK */
773
774
775
776 #if defined(GATE_UI_MOTIF)
777
778 #include "gate/ui/gateui_motif.h"
779 #include <Xm/BulletinB.h>
780 #include <Xm/Frame.h>
781 #include <Xm/Label.h>
782 #include <Xm/Manager.h>
783
784 12 static void panel_resize(Widget w, XEvent* evt, String args[], Cardinal* num_args)
785 {
786 WidgetList children;
787 12 gate_ui_panel_t* ptr_panel = (gate_ui_panel_t*)gate_ui_motif_widget_get_ctrl(w);
788
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (NULL == ptr_panel)
789 {
790 return;
791 }
792
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 10 times.
12 if (ptr_panel->layout)
793 {
794 2 XConfigureEvent* cfg_event = (XConfigureEvent*)evt;
795 2 gate_ui_host_t* host = GATE_UI_MOTIF_GET_CTRL_HOST(&ptr_panel->ctrl);
796 gate_ui_position_t pose;
797 2 gate_uint32_t line_height = gate_ui_host_default_control_height(host, 1);
798 2 pose.pos.x = 0;
799 2 pose.pos.y = 0;
800 2 pose.size.width = cfg_event->width;
801 2 pose.size.height = cfg_event->height;
802
803 2 gate_ui_layout_apply(ptr_panel->layout, line_height, &pose);
804 }
805 }
806
807 6 gate_result_t gate_ui_panel_create(gate_ui_panel_t* panel, gate_ui_ctrl_t* parent, gate_ui_position_t const* position,
808 gate_uint32_t flags, void* userparam)
809 {
810 6 gate_result_t ret = GATE_RESULT_FAILED;
811
812 do
813 {
814 6 Widget w = NULL;
815 6 XtAppContext appctx = NULL;
816 XtActionsRec actions[1];
817 6 gate_ui_host_t* host = NULL;
818 Arg args[12];
819 6 unsigned args_count = 0;
820
821
2/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
6 if (!panel || !parent)
822 {
823 ret = GATE_RESULT_INVALIDARG;
824 break;
825 }
826
827 6 host = GATE_UI_MOTIF_GET_CTRL_HOST(parent);
828
829 6 XtSetArg(args[args_count], XmNresizePolicy, XmRESIZE_NONE); ++args_count;
830 6 XtSetArg(args[args_count], XmNnoResize, True); ++args_count;
831 6 XtSetArg(args[args_count], XmNmarginWidth, 0); ++args_count;
832 6 XtSetArg(args[args_count], XmNmarginHeight, 0); ++args_count;
833 6 XtSetArg(args[args_count], XmNshadowThickness, 0); ++args_count;
834 6 XtSetArg(args[args_count], XmNhighlightThickness, 0); ++args_count;
835
836 6 ret = gate_ui_motif_ctrl_create(&panel->ctrl, xmBulletinBoardWidgetClass, userparam, NULL, parent,
837 position, &flags, false, NULL, args, args_count);
838
839
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 GATE_BREAK_IF_FAILED(ret);
840 6 w = GATE_UI_MOTIF_GET_CTRL_WIDGET(&panel->ctrl);
841
842 6 appctx = (XtAppContext)GATE_UI_MOTIF_GET_HOST_APPHANDLE(host);
843 6 actions[0].string = "resize";
844 6 actions[0].proc = &panel_resize;
845 6 XtAppAddActions(appctx, actions, 1);
846 6 XtOverrideTranslations(w, XtParseTranslationTable("<Configure>: resize()"));
847 } while (0);
848
849 6 return ret;
850 }
851
852 3 gate_result_t gate_ui_panel_set_layout(gate_ui_panel_t* panel, gate_ui_layout_t const* layout)
853 {
854 3 panel->layout = layout;
855 3 return gate_ui_panel_refresh(panel);
856 }
857
858 3 gate_result_t gate_ui_panel_refresh(gate_ui_panel_t* panel)
859 {
860 3 gate_result_t ret = GATE_RESULT_FAILED;
861 do
862 {
863 gate_ui_position_t pose;
864 3 pose.pos.x = 0;
865 3 pose.pos.y = 0;
866 3 ret = gate_ui_ctrl_get_size(&panel->ctrl, &pose.size);
867
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 GATE_BREAK_IF_FAILED(ret);
868 3 ret = gate_ui_layout_apply(panel->layout, 0, &pose);
869 } while (0);
870 3 return ret;
871 }
872
873
874
875
876 1 static void framepanel_resize(Widget w, XEvent* evt, String args[], Cardinal* num_args)
877 {
878 1 gate_ui_framepanel_t* ptr_frame = (gate_ui_framepanel_t*)gate_ui_motif_widget_get_ctrl(w);
879
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (NULL == ptr_frame)
880 {
881 return;
882 }
883
884
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (ptr_frame->layout)
885 {
886 1 XConfigureEvent* cfg_event = (XConfigureEvent*)evt;
887 1 gate_ui_host_t* host = GATE_UI_MOTIF_GET_CTRL_HOST(&ptr_frame->ctrl);
888 1 gate_uint32_t line_height = gate_ui_host_default_control_height(host, 1);
889 gate_ui_position_t pose;
890 1 pose.pos.x = 0;
891 1 pose.pos.y = 0;
892 1 pose.size.width = cfg_event->width;
893 1 pose.size.height = cfg_event->height;
894 1 gate_ui_layout_apply(ptr_frame->layout, line_height, &pose);
895 }
896 }
897
898 1 gate_result_t gate_ui_framepanel_create(gate_ui_framepanel_t* frame, gate_ui_ctrl_t* parent, gate_ui_position_t const* position,
899 gate_string_t const* text, gate_uint32_t flags, void* userparam)
900 {
901 1 gate_result_t ret = GATE_RESULT_FAILED;
902 1 XmString label = NULL;
903
904 do
905 {
906 1 Widget w = NULL;
907 1 Widget w_parent = NULL;
908 1 Widget w_title = NULL;
909 1 Widget w_board = NULL;
910 1 XtAppContext appctx = NULL;
911 XtActionsRec actions[1];
912 1 gate_ui_host_t* host = NULL;
913 Arg args[12];
914 1 unsigned args_count = 0;
915
916
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if (!frame || !parent)
917 {
918 ret = GATE_RESULT_INVALIDARG;
919 break;
920 }
921
922 1 host = GATE_UI_MOTIF_GET_CTRL_HOST(parent);
923 1 w_parent = GATE_UI_MOTIF_GET_CTRL_CONTAINER(parent);
924
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (w_parent == NULL)
925 {
926 1 w_parent = GATE_UI_MOTIF_GET_CTRL_WIDGET(parent);
927 }
928
929 1 args_count = 0;
930 1 XtSetArg(args[args_count], XmNresizePolicy, XmRESIZE_NONE); ++args_count;
931 1 XtSetArg(args[args_count], XmNmarginWidth, 2); ++args_count;
932 1 XtSetArg(args[args_count], XmNmarginHeight, 2); ++args_count;
933 1 XtSetArg(args[args_count], XmNshadowType, XmSHADOW_ETCHED_IN); ++args_count;
934
935 1 w = XtCreateWidget(NULL, xmFrameWidgetClass, w_parent, args, args_count);
936
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (NULL == w)
937 {
938 ret = GATE_RESULT_OUTOFRESOURCES;
939 break;
940 }
941 1 XtManageChild(w);
942
943 1 label = gate_ui_motif_create_string(text);
944 1 args_count = 0;
945 1 XtSetArg(args[args_count], XmNframeChildType, XmFRAME_TITLE_CHILD); ++args_count;
946 1 XtSetArg(args[args_count], XmNlabelString, label); ++args_count;
947 1 w_title = XtCreateWidget(NULL, xmLabelWidgetClass, w, args, args_count);
948
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (NULL == w_title)
949 {
950 XtDestroyWidget(w);
951 ret = GATE_RESULT_OUTOFRESOURCES;
952 break;
953 }
954 1 XtManageChild(w_title);
955 1 XtRealizeWidget(w_title);
956 1 XtMapWidget(w_title);
957
958 1 args_count = 0;
959 1 XtSetArg(args[args_count], XmNframeChildType, XmFRAME_WORKAREA_CHILD); ++args_count;
960 1 XtSetArg(args[args_count], XmNresizePolicy, XmRESIZE_NONE); ++args_count;
961 1 XtSetArg(args[args_count], XmNnoResize, True); ++args_count;
962 1 XtSetArg(args[args_count], XmNmarginWidth, 0); ++args_count;
963 1 XtSetArg(args[args_count], XmNmarginHeight, 0); ++args_count;
964 1 w_board = XtCreateWidget(NULL, xmBulletinBoardWidgetClass, w, args, args_count);
965
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (NULL == w_board)
966 {
967 XtDestroyWidget(w_title);
968 XtDestroyWidget(w);
969 ret = GATE_RESULT_OUTOFRESOURCES;
970 break;
971 }
972 1 XtManageChild(w_board);
973 1 XtRealizeWidget(w_board);
974 1 XtMapWidget(w_board);
975
976 1 ret = gate_ui_motif_ctrl_init(&frame->ctrl, w, userparam, host, parent, w_board, position, &flags, NULL);
977
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (GATE_FAILED(ret))
978 {
979 XtDestroyWidget(w_board);
980 XtDestroyWidget(w_title);
981 XtDestroyWidget(w);
982 break;
983 }
984
985 1 appctx = (XtAppContext)GATE_UI_MOTIF_GET_HOST_APPHANDLE(host);
986 1 actions[0].string = "resize";
987 1 actions[0].proc = &framepanel_resize;
988 1 XtAppAddActions(appctx, actions, 1);
989 1 XtOverrideTranslations(w_board, XtParseTranslationTable("<Configure>: resize()"));
990 } while (0);
991
992
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (label != NULL)
993 {
994 1 XmStringFree(label);
995 }
996
997 1 return ret;
998 }
999
1000 1 gate_result_t gate_ui_framepanel_set_layout(gate_ui_framepanel_t* frame, gate_ui_layout_t const* layout)
1001 {
1002 1 frame->layout = layout;
1003 1 return gate_ui_framepanel_refresh(frame);
1004 }
1005
1006 1 gate_result_t gate_ui_framepanel_refresh(gate_ui_framepanel_t* frame)
1007 {
1008 1 gate_result_t ret = GATE_RESULT_FAILED;
1009 do
1010 {
1011 gate_ui_position_t pose;
1012 1 pose.pos.x = 0;
1013 1 pose.pos.y = 0;
1014 1 ret = gate_ui_ctrl_get_size(&frame->ctrl, &pose.size);
1015
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
1016 1 ret = gate_ui_layout_apply(frame->layout, 0, &pose);
1017 } while (0);
1018 1 return ret;
1019
1020 }
1021
1022 #endif /* GATE_UI_MOTIF */
1023
1024
1025 #if defined(GATE_UI_WASMHTML)
1026
1027 #include "gate/ui/gateui_wasmhtml.h"
1028 #include "gate/platform/wasm/wasm_gate.h"
1029
1030 gate_result_t gate_ui_panel_create(gate_ui_panel_t* panel, gate_ui_ctrl_t* parent,
1031 gate_ui_position_t const* position, gate_uint32_t flags, void* userparam)
1032 {
1033 return GATE_RESULT_NOTIMPLEMENTED;
1034 }
1035
1036 gate_result_t gate_ui_panel_set_layout(gate_ui_panel_t* panel, gate_ui_layout_t const* layout)
1037 {
1038 return GATE_RESULT_NOTIMPLEMENTED;
1039 }
1040
1041 gate_result_t gate_ui_panel_refresh(gate_ui_panel_t* panel)
1042 {
1043 return GATE_RESULT_NOTIMPLEMENTED;
1044 }
1045
1046 gate_result_t gate_ui_framepanel_create(gate_ui_framepanel_t* frame, gate_ui_ctrl_t* parent,
1047 gate_ui_position_t const* position, gate_string_t const* text, gate_uint32_t flags, void* userparam)
1048 {
1049 return GATE_RESULT_NOTIMPLEMENTED;
1050 }
1051
1052 gate_result_t gate_ui_framepanel_set_layout(gate_ui_framepanel_t* frame, gate_ui_layout_t const* layout)
1053 {
1054 return GATE_RESULT_NOTIMPLEMENTED;
1055 }
1056
1057 gate_result_t gate_ui_framepanel_refresh(gate_ui_framepanel_t* frame)
1058 {
1059 return GATE_RESULT_NOTIMPLEMENTED;
1060 }
1061
1062
1063 #endif
1064