GCC Code Coverage Report


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