GCC Code Coverage Report


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