GCC Code Coverage Report


Directory: src/gate/
File: src/gate/ui/toolbars.c
Date: 2025-12-12 23:40:09
Exec Total Coverage
Lines: 69 95 72.6%
Functions: 5 12 41.7%
Branches: 18 40 45.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/toolbars.h"
30 #include "gate/results.h"
31
32 #if defined(GATE_UI_WINAPI)
33
34 #ifndef _WIN32_IE
35 # if defined(GATE_COMPILER_TCC)
36 # define _WIN32_IE 0x0501
37 # else
38 # define _WIN32_IE 0x0400
39 # endif
40 #endif
41
42 #include "gate/ui/gateui_winapi.h"
43 #include "gate/ui/graphics.h"
44 #include "gate/platforms.h"
45
46 #if defined(GATE_SYS_WIN16)
47
48 typedef struct tagNMHDR
49 {
50 HWND hwndFrom;
51 UINT_PTR idFrom;
52 UINT code;
53 } NMHDR;
54
55 typedef struct tagNMMOUSE
56 {
57 NMHDR hdr;
58 DWORD dwItemSpec;
59 DWORD dwItemData;
60 POINT pt;
61 LPARAM dwHitInfo;
62 } NMMOUSE, * LPNMMOUSE;
63
64 typedef struct _TBBUTTON
65 {
66 int iBitmap;
67 int idCommand;
68 BYTE fsState;
69 BYTE fsStyle;
70 DWORD dwData;
71 INT_PTR iString;
72 } TBBUTTON, * LPTBBUTTON;
73
74 typedef struct
75 {
76 UINT cbSize;
77 DWORD dwMask;
78 int idCommand;
79 int iImage;
80 BYTE fsState;
81 BYTE fsStyle;
82 WORD cx;
83 DWORD lParam;
84 LPSTR pszText;
85 int cchText;
86 } TBBUTTONINFO, * LPTBBUTTONINFO;
87
88 #define NM_FIRST (0U- 0U)
89 #define NM_LAST (0U- 99U)
90 #define TBN_FIRST (0U-700U)
91 #define TBN_LAST (0U-720U)
92 #define WM_NOTIFY 0x004E
93 #define NM_CLICK (NM_FIRST-2)
94 #define NM_DBLCLK (NM_FIRST-3)
95 #define TB_GETBUTTONINFO (WM_USER + 65)
96 #define TB_SETBUTTONINFO (WM_USER + 66)
97 #define TB_AUTOSIZE (WM_USER + 33)
98 #define TBIF_IMAGE 0x00000001
99 #define TBIF_TEXT 0x00000002
100 #define TBIF_STATE 0x00000004
101 #define TBIF_STYLE 0x00000008
102 #define TBIF_LPARAM 0x00000010
103 #define TBIF_COMMAND 0x00000020
104 #define TBIF_SIZE 0x00000040
105
106 #define TBIF_BYINDEX 0x80000000
107
108 #define TBSTYLE_BUTTON 0x0000
109 #define TBSTYLE_SEP 0x0001
110 #define TBSTYLE_CHECK 0x0002
111 #define TBSTYLE_GROUP 0x0004
112 #define TBSTYLE_CHECKGROUP (TBSTYLE_GROUP | TBSTYLE_CHECK)
113 #define TBSTYLE_DROPDOWN 0x0008
114 #define TBSTYLE_AUTOSIZE 0x0010
115 #define TBSTYLE_NOPREFIX 0x0020
116
117 #define TBSTYLE_TOOLTIPS 0x0100
118 #define TBSTYLE_WRAPABLE 0x0200
119 #define TBSTYLE_ALTDRAG 0x0400
120 #define TBSTYLE_FLAT 0x0800
121 #define TBSTYLE_LIST 0x1000
122 #define TBSTYLE_CUSTOMERASE 0x2000
123 #define TBSTYLE_REGISTERDROP 0x4000
124 #define TBSTYLE_TRANSPARENT 0x8000
125
126 #define CCS_NORESIZE 0x00000004L
127 #define CCS_NOPARENTALIGN 0x00000008L
128
129 #define TBSTATE_CHECKED 0x01
130 #define TBSTATE_PRESSED 0x02
131 #define TBSTATE_ENABLED 0x04
132 #define TBSTATE_HIDDEN 0x08
133 #define TBSTATE_INDETERMINATE 0x10
134 #define TBSTATE_WRAP 0x20
135 #define TBSTATE_ELLIPSES 0x40
136 #define TBSTATE_MARKED 0x80
137
138 #define TB_ADDBUTTONS (WM_USER + 20)
139 #define TB_INSERTBUTTON (WM_USER + 21)
140
141 #define TB_DELETEBUTTON (WM_USER + 22)
142 #define TB_GETBUTTON (WM_USER + 23)
143 #define TB_BUTTONCOUNT (WM_USER + 24)
144 #define TB_COMMANDTOINDEX (WM_USER + 25)
145
146 #define TOOLBARCLASSNAME "ToolbarWindow"
147
148 #else
149 # include <commctrl.h>
150 #endif
151
152
153 #ifndef TBCDRF_USECDCOLORS
154 #define TBCDRF_USECDCOLORS 0x00800000
155 #endif
156
157 static gate_bool_t gate_ui_toolbar_events(void* hwnd, gate_ui_ctrl_t* ctrl, gate_uint32_t msg, gate_uintptr_t wParam, gate_intptr_t lParam, gate_intptr_t* lresult)
158 {
159
160 if ((ctrl != NULL) && (hwnd != NULL))
161 {
162 HWND hwndCtrl = GATE_UI_WINAPI_GET_HWND(ctrl);
163 if (NULL != hwndCtrl)
164 {
165 gate_ui_toolbar_t* toolbar = (gate_ui_toolbar_t*)ctrl;
166 gate_ui_host_t* host = GATE_UI_WINAPI_GET_HOST(ctrl);
167
168 switch (msg)
169 {
170 case WM_COMMAND:
171 {
172 if ((HWND)lParam == hwndCtrl)
173 {
174 /* toolbar button was clicked */
175 if (toolbar->on_click != NULL)
176 {
177 LPARAM lparam_button = 0;
178 int buttonindex = (int)SendMessage(hwndCtrl, TB_BUTTONCOUNT, 0, 0);
179 while (buttonindex > 0)
180 {
181 TBBUTTON tb_button;
182 --buttonindex;
183 gate_mem_clear(&tb_button, sizeof(tb_button));
184 if (SendMessage(hwndCtrl, TB_GETBUTTON, (WPARAM)buttonindex, (LPARAM)&tb_button))
185 {
186 if (tb_button.idCommand == (WPARAM)LOWORD(wParam))
187 {
188 /* we found our clicked button */
189 toolbar->on_click(&toolbar->ctrl, (gate_ui_toolbar_button_t)(LOWORD(wParam)), (void*)tb_button.dwData);
190 break;
191 }
192 }
193 }
194 }
195 *lresult = 0;
196 return true;
197 }
198 break;
199 }
200 case WM_NOTIFY:
201 {
202 NMHDR* nmhdr = (NMHDR*)(lParam);
203 if (nmhdr->hwndFrom == hwndCtrl)
204 {
205 switch (nmhdr->code)
206 {
207 case NM_DBLCLK:
208 {
209 break;
210 }
211 #if defined(GATE_UI_WINAPI_DARKMODE_SUPPORT)
212 case NM_CUSTOMDRAW:
213 {
214 HBRUSH hbgbrush;
215 NMTBCUSTOMDRAW* tb_draw;
216 gate_ui_color_t color;
217 if (!gate_ui_winapi_darkmode_enabled())
218 {
219 break;
220 }
221
222 tb_draw = (NMTBCUSTOMDRAW*)lParam;
223
224 switch (tb_draw->nmcd.dwDrawStage)
225 {
226 case CDDS_PREPAINT:
227 {
228 gate_ui_host_default_color(host, GATE_UI_COLOR_MENUBACKGROUND, &color);
229 hbgbrush = (HBRUSH)gate_ui_winapi_host_get_brush(host, &color);
230 FillRect(tb_draw->nmcd.hdc, &tb_draw->nmcd.rc, hbgbrush);
231
232 *lresult = CDRF_NOTIFYITEMDRAW;
233 return true;
234 }
235 case CDDS_ITEMPREPAINT:
236 {
237 //gate_ui_host_default_color(host, GATE_UI_COLOR_MENUTEXT, &color);
238 //tb_draw->clrText = RGB(color.r, color.g, color.b);
239 //gate_ui_host_default_color(host, GATE_UI_COLOR_SELECTEDMENUTEXT, &color);
240 // tb_draw->clrTextHighlight = RGB(color.r, color.g, color.b);
241
242 if (tb_draw->nmcd.uItemState & CDIS_SELECTED)
243 {
244 gate_ui_host_default_color(host, GATE_UI_COLOR_SELECTEDMENUBACKGROUND, &color);
245 hbgbrush = (HBRUSH)gate_ui_winapi_host_get_brush(host, &color);
246 }
247 else if (tb_draw->nmcd.uItemState & CDIS_HOT)
248 {
249 //gate_ui_host_default_color(host, GATE_UI_COLOR_HOVERMENUBACKGROUND, &color);
250 //hbgbrush = (HBRUSH)gate_ui_winapi_host_get_brush(host, &color);
251 hbgbrush = NULL;
252 }
253 else
254 {
255 gate_ui_host_default_color(host, GATE_UI_COLOR_MENUBACKGROUND, &color);
256 hbgbrush = (HBRUSH)gate_ui_winapi_host_get_brush(host, &color);
257 }
258
259 if (NULL != hbgbrush)
260 {
261 FillRect(tb_draw->nmcd.hdc, &tb_draw->nmcd.rc, hbgbrush);
262 }
263
264 *lresult = CDRF_NEWFONT;
265 return true;
266 }
267 case (CDDS_SUBITEM | CDDS_ITEMPREPAINT):
268 {
269 //SelectObject(tb_draw->nmcd.hdc, CreateSolidBrush(RGB(0, 0, 0)));
270 //FillRect(tb_draw->nmcd.hdc, &tb_draw->nmcd.rc, tb_draw->clrBtnFace);
271 *lresult = CDRF_NEWFONT;
272 return true;
273 }
274 default:
275 {
276 *lresult = CDRF_DODEFAULT;
277 return true;
278 }
279 }
280
281 break;
282 }
283 #endif /* GATE_UI_WINAPI_DARKMODE_SUPPORT */
284 } /* switch */
285 }
286
287 break;
288 }
289 case WM_DESTROY:
290 {
291 #if defined(GATE_SYS_WINCE) || defined(GATE_SYS_WIN16)
292 #else
293 HIMAGELIST himagelist = (HIMAGELIST)SendMessage(hwnd, TB_GETIMAGELIST, 0, 0);
294 if (himagelist)
295 {
296 SendMessage(hwnd, TB_SETIMAGELIST, 0, 0);
297 gate_ui_winapi_imagelist_destroy(himagelist);
298 }
299 #endif
300 gate_ui_winapi_unregister_window(host, hwnd);
301 break;
302 }
303 default:
304 {
305 break;
306 }
307 }
308 }
309 }
310 return false;
311 }
312
313 #if !defined(ILC_COLOR16) && defined(ILC_COLOR)
314 # define ILC_COLOR16 ILC_COLOR
315 #endif
316
317 gate_result_t gate_ui_toolbar_create(gate_ui_toolbar_t* toolbar, gate_ui_ctrl_t* parent,
318 gate_ui_position_t const* position, gate_uint32_t flags, void* userparam)
319 {
320 gate_result_t ret;
321
322 do
323 {
324 gate_ui_host_t* host = gate_ui_ctrl_get_host(parent);
325 HWND hwndParent;
326 HWND hwnd;
327 gate_uint32_t styles;
328 gate_uint32_t exstyles = 0;
329 #if defined(GATE_SYS_WINCE) || defined(GATE_SYS_WIN16)
330 HINSTANCE hinst;
331 #else
332 HIMAGELIST himagelist;
333 #endif
334
335 if (host == NULL)
336 {
337 ret = GATE_RESULT_INVALIDSTATE;
338 break;
339 }
340 hwndParent = GATE_UI_WINAPI_GET_HWND(parent);
341 if (hwndParent == NULL)
342 {
343 ret = GATE_RESULT_INVALIDSTATE;
344 break;
345 }
346
347 gate_mem_clear(toolbar, sizeof(gate_ui_toolbar_t));
348
349 #if defined(GATE_SYS_WINCE)
350 hinst = (HINSTANCE)GATE_UI_WINAPI_GET_HOST_APPHANDLE(host);
351 styles = WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_TABSTOP;
352 hwnd = CreateToolbarEx(hwndParent, styles,
353 0, 0, hinst, 0, NULL, 0, 0, 0, 0, 0, sizeof(TBBUTTON));
354
355 ret = gate_ui_winapi_setup_control(&toolbar->ctrl, host, hwnd, hwndParent, userparam);
356 if (GATE_FAILED(ret))
357 {
358 DestroyWindow(hwnd);
359 break;
360 }
361 #else /* GATE_SYS_WINCE */
362 styles = WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_TABSTOP | TBSTYLE_TOOLTIPS | CCS_NOPARENTALIGN | CCS_NORESIZE;
363 if (!GATE_FLAG_ENABLED(flags, GATE_UI_FLAG_ENABLED)) styles |= WS_DISABLED;
364 if (GATE_FLAG_ENABLED(flags, GATE_UI_FLAG_VISIBLE)) styles |= WS_VISIBLE;
365
366 ret = gate_ui_winapi_create(&toolbar->ctrl, host, hwndParent, TOOLBARCLASSNAME, position, styles, exstyles, NULL, userparam, true);
367 if (GATE_FAILED(ret))
368 {
369 break;
370 }
371
372 #if !defined(GATE_SYS_WIN16)
373 hwnd = GATE_UI_WINAPI_GET_HWND(&toolbar->ctrl);
374 SendMessage(hwnd, TB_SETBITMAPSIZE, 0, MAKELONG(16, 16));
375 SendMessage(hwnd, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0);
376 himagelist = (HIMAGELIST)gate_ui_winapi_imagelist_create(16, 16, ILC_COLOR16 | ILC_MASK, 0, 0);
377 if (!himagelist)
378 {
379 gate_ui_winapi_destroy(&toolbar->ctrl);
380 ret = GATE_RESULT_OUTOFRESOURCES;
381 break;
382 }
383 SendMessage(hwnd, TB_SETIMAGELIST, 0, (LPARAM)himagelist);
384 #endif
385
386 #endif /* GATE_SYS_WINCE */
387
388 gate_ui_winapi_register_event(host, hwndParent, WM_NOTIFY, &gate_ui_toolbar_events, &toolbar->ctrl);
389 gate_ui_winapi_register_event(host, hwndParent, WM_COMMAND, &gate_ui_toolbar_events, &toolbar->ctrl);
390 gate_ui_winapi_register_event(host, hwnd, WM_DESTROY, &gate_ui_toolbar_events, &toolbar->ctrl);
391 /*
392 gate_ui_winapi_register_event(host, hwndParent, WM_DRAWITEM, &gate_ui_label_events, &label->ctrl);
393 */
394
395 } while (0);
396
397 return ret;
398 }
399
400 static int volatile global_gate_toolbar_id = 0;
401
402 #if !defined(I_IMAGENONE)
403 # define I_IMAGENONE (-2)
404 #endif
405
406 static gate_result_t gate_ui_toolbar_add_bitmap_id(gate_ui_toolbar_t* toolbar, int bitmap_id, void* button_param,
407 gate_ui_toolbar_button_t* button_id)
408 {
409 gate_result_t ret = GATE_RESULT_FAILED;
410 do
411 {
412 HWND hwnd = GATE_UI_WINAPI_GET_HWND(&toolbar->ctrl);
413 TBBUTTON button;
414
415 button.iBitmap = bitmap_id;
416 button.idCommand = ++global_gate_toolbar_id;
417 button.fsState = TBSTATE_ENABLED;
418 button.fsStyle = TBSTYLE_BUTTON;
419 button.dwData = (DWORD_PTR)button_param;
420 button.iString = 0;
421
422 if (FALSE == SendMessage(hwnd, TB_ADDBUTTONS, 1, (LPARAM)&button))
423 {
424 ret = GATE_RESULT_FAILED;
425 }
426 else
427 {
428 TBBUTTONINFO buttoninfo;
429 gate_mem_clear(&buttoninfo, sizeof(buttoninfo));
430 buttoninfo.cbSize = sizeof(buttoninfo);
431 buttoninfo.dwMask = TBIF_COMMAND | TBIF_LPARAM;
432 buttoninfo.idCommand = button.idCommand;
433 buttoninfo.lParam = (LPARAM)button_param;
434 SendMessage(hwnd, TB_SETBUTTONINFO, (WPARAM)button.idCommand, (LPARAM)&buttoninfo);
435
436 SendMessage(hwnd, TB_AUTOSIZE, 0, 0);
437 *button_id = button.idCommand;
438 ret = GATE_RESULT_OK;
439 }
440 } while (0);
441
442 return ret;
443 }
444
445 static gate_result_t gate_ui_toolbar_add_HICON(gate_ui_toolbar_t* toolbar, HICON hicon,
446 void* button_param, gate_ui_toolbar_button_t* button_id)
447 {
448 gate_result_t ret = GATE_RESULT_FAILED;
449 #if !defined(GATE_SYS_WIN16)
450 HWND hwnd = GATE_UI_WINAPI_GET_HWND(&toolbar->ctrl);
451 int bitmap_id;
452 HIMAGELIST himagelist = (HIMAGELIST)SendMessage(hwnd, TB_GETIMAGELIST, 0, 0);
453
454 #if !defined(GATE_SYS_WINCE)
455 if (himagelist == NULL)
456 {
457 /* NT3 or Win9x without IE does not support GETIMAGELIST */
458 ICONINFO iconinfo;
459 TBADDBITMAP bminfo;
460
461 GetIconInfo(hicon, &iconinfo);
462 bminfo.hInst = NULL;
463 bminfo.nID = (UINT_PTR)iconinfo.hbmColor;
464 bitmap_id = (int)SendMessage(hwnd, TB_ADDBITMAP, 1, (LRESULT)&bminfo);
465 }
466 else
467 #endif
468 {
469 bitmap_id = gate_ui_winapi_imagelist_replace_icon(himagelist, -1, hicon);
470 if (bitmap_id == -1)
471 {
472 #if defined(GATE_SYS_WINCE)
473 hicon = (HICON)LoadCursor(NULL, IDC_ICON);
474 #else
475 hicon = LoadIcon(NULL, IDI_WARNING);
476 #endif
477 bitmap_id = gate_ui_winapi_imagelist_replace_icon(himagelist, -1, hicon);
478 }
479 }
480
481 if (bitmap_id == -1)
482 {
483 /* Failed to add ICON bitmap to toolbar's image list */
484 ret = GATE_RESULT_FAILED;
485 }
486 else
487 {
488 ret = gate_ui_toolbar_add_bitmap_id(toolbar, bitmap_id, button_param, button_id);
489 }
490
491 #endif
492 return ret;
493 }
494
495 gate_result_t gate_ui_toolbar_add_icon_button(gate_ui_toolbar_t* toolbar, gate_ui_icon_t const* icon,
496 void* button_param, gate_ui_toolbar_button_t* button_id)
497 {
498 gate_result_t ret = GATE_RESULT_FAILED;
499
500 #if !defined(GATE_SYS_WIN16)
501 if (GATE_FLAG_ENABLED(icon->flags, GATE_UI_ICON_FLAG_STOCK))
502 {
503 int bitmap_id = 0xff;
504 gate_uint32_t stock_id = (gate_uint32_t)(gate_uintptr_t)icon->resources[1];
505 switch (stock_id)
506 {
507 case GATE_UI_ICON_STOCK_APP:
508 case GATE_UI_ICON_STOCK_DOCUMENT:
509 case GATE_UI_ICON_STOCK_FOLDER:
510 case GATE_UI_ICON_STOCK_FOLDEROPEN:
511 case GATE_UI_ICON_STOCK_NEWFILE: bitmap_id = STD_FILENEW; break;
512 case GATE_UI_ICON_STOCK_OPENFILE: bitmap_id = STD_FILEOPEN; break;
513 case GATE_UI_ICON_STOCK_SAVEFILE: bitmap_id = STD_FILESAVE; break;
514 case GATE_UI_ICON_STOCK_PRINTER: bitmap_id = STD_PRINT; break;
515 case GATE_UI_ICON_STOCK_CUT: bitmap_id = STD_CUT; break;
516 case GATE_UI_ICON_STOCK_COPY: bitmap_id = STD_COPY; break;
517 case GATE_UI_ICON_STOCK_PASTE: bitmap_id = STD_PASTE; break;
518 case GATE_UI_ICON_STOCK_DELETE: bitmap_id = STD_DELETE; break;
519 case GATE_UI_ICON_STOCK_FIND: bitmap_id = STD_FIND; break;
520 case GATE_UI_ICON_STOCK_HELP: bitmap_id = STD_HELP; break;
521
522 case GATE_UI_ICON_STOCK_STORAGE:
523 case GATE_UI_ICON_STOCK_COMPUTER:
524 case GATE_UI_ICON_STOCK_NETWORK:
525 case GATE_UI_ICON_STOCK_GLOBE:
526 case GATE_UI_ICON_STOCK_HOME:
527 case GATE_UI_ICON_STOCK_IMAGE:
528 case GATE_UI_ICON_STOCK_AUDIO:
529 case GATE_UI_ICON_STOCK_VIDEO:
530 case GATE_UI_ICON_STOCK_MAIL:
531 case GATE_UI_ICON_STOCK_SETTINGS: bitmap_id = STD_PROPERTIES; break;
532 default:
533 break;
534 }
535 ret = gate_ui_toolbar_add_bitmap_id(toolbar, bitmap_id, button_param, button_id);
536 }
537 else
538 {
539 HICON hicon = (HICON)icon->resources[0];
540 ret = gate_ui_toolbar_add_HICON(toolbar, hicon, button_param, button_id);
541 }
542 #endif /* GATE_SYS_WIN16 */
543 return ret;
544 }
545
546 gate_result_t gate_ui_toolbar_add_image_button(gate_ui_toolbar_t* toolbar, gate_rasterimage_t const* raster,
547 void* button_param, gate_ui_toolbar_button_t* button_id)
548 {
549 gate_ui_host_t* host = GATE_UI_WINAPI_GET_HOST(&toolbar->ctrl);
550 gate_ui_icon_t icon;
551 gate_result_t ret;
552 HICON hicon;
553
554 ret = gate_ui_icon_create_image(&icon, host, raster);
555 hicon = (HICON)icon.resources[0];
556
557 if (GATE_SUCCEEDED(ret))
558 {
559 ret = gate_ui_toolbar_add_HICON(toolbar, hicon, button_param, button_id);
560 gate_ui_icon_destroy(&icon);
561 }
562 return ret;
563 }
564 gate_result_t gate_ui_toolbar_add_separator(gate_ui_toolbar_t* toolbar)
565 {
566 gate_result_t ret = GATE_RESULT_OK;
567 HWND hwnd = GATE_UI_WINAPI_GET_HWND(&toolbar->ctrl);
568 TBBUTTON button;
569 button.iBitmap = 0;
570 button.idCommand = 0;
571 button.fsState = TBSTATE_ENABLED;
572 button.fsStyle = TBSTYLE_SEP;
573 button.dwData = 0;
574 button.iString = 0;
575 if (FALSE == SendMessage(hwnd, TB_ADDBUTTONS, 1, (LPARAM)&button))
576 {
577 //ret = GATE_RESULT_FAILED;
578 }
579 else
580 {
581 SendMessage(hwnd, TB_AUTOSIZE, 0, 0);
582 }
583
584 return ret;
585 }
586
587 #endif /* GATE_UI_WINAPI */
588
589
590 #if defined(GATE_UI_GTK)
591
592 #include "gate/ui/gateui_gtk.h"
593
594 gate_result_t gate_ui_toolbar_create(gate_ui_toolbar_t* toolbar, gate_ui_ctrl_t* parent,
595 gate_ui_position_t const* position, gate_uint32_t flags, void* userparam)
596 {
597 gate_result_t ret;
598 do
599 {
600 GtkWidget* widget;
601 gate_ui_host_t* host = GATE_UI_GTK_GET_CTRL_HOST(parent);
602 GtkContainer* parentContainer = GATE_UI_GTK_GET_CTRL_CONTAINER(parent);
603
604 gate_mem_clear(toolbar, sizeof(gate_ui_toolbar_t));
605 widget = gtk_toolbar_new();
606 if (widget == NULL)
607 {
608 ret = GATE_RESULT_FAILED;
609 break;
610 }
611
612 ret = gate_ui_gtk_ctrl_init(&toolbar->ctrl, widget, host, userparam, parent,
613 NULL, false, false, position, &flags);
614 GATE_BREAK_IF_FAILED(ret);
615 gtk_toolbar_set_style(GTK_TOOLBAR(widget), GTK_TOOLBAR_ICONS);
616
617
618 } while (0);
619 return ret;
620 }
621
622 static void gate_ui_toolbar_button_clicked(GtkToolButton* toolbutton, gpointer user_data)
623 {
624 GtkWidget* toolbar_widget = gtk_widget_get_parent(GTK_WIDGET(toolbutton));
625
626 if (NULL != toolbar_widget)
627 {
628 gate_ui_ctrl_t* toolbar_ctrl = gate_ui_gtk_ctrl_resolve(toolbar_widget);
629
630 if (toolbar_ctrl)
631 {
632 gate_ui_toolbar_t* toolbar = (gate_ui_toolbar_t*)toolbar_ctrl;
633 if (toolbar->on_click)
634 {
635 toolbar->on_click(&toolbar->ctrl, (gate_ui_toolbar_button_t)toolbutton, user_data);
636 }
637 }
638 }
639 }
640
641 gate_result_t gate_ui_toolbar_add_icon_button(gate_ui_toolbar_t* toolbar, gate_ui_icon_t const* icon,
642 void* button_param, gate_ui_toolbar_button_t* button_id)
643 {
644 gate_result_t ret = GATE_RESULT_OK;
645 do
646 {
647 GtkWidget* widget = GATE_UI_GTK_GET_CTRL_WIDGET(&toolbar->ctrl);
648 GtkWidget* icon_widget = gtk_image_new_from_pixbuf((GdkPixbuf*)icon->resources[0]);
649 GtkToolItem* item = gtk_tool_button_new(icon_widget, NULL);
650 if (NULL == item)
651 {
652 ret = GATE_RESULT_OUTOFMEMORY;
653 break;
654 }
655 gtk_toolbar_insert(GTK_TOOLBAR(widget), item, -1);
656 gtk_widget_show_all(widget);
657 g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(gate_ui_toolbar_button_clicked), (gpointer)button_param);
658
659 if (button_id)
660 {
661 *button_id = (gate_ui_toolbar_button_t)item;
662 }
663 } while (0);
664 return ret;
665 }
666
667 gate_result_t gate_ui_toolbar_add_image_button(gate_ui_toolbar_t* toolbar, gate_rasterimage_t const* raster,
668 void* button_param, gate_ui_toolbar_button_t* button_id)
669 {
670 gate_result_t ret = GATE_RESULT_OK;
671 gate_ui_icon_t icon = GATE_INIT_EMPTY;
672 do
673 {
674 GtkWidget* widget = GATE_UI_GTK_GET_CTRL_WIDGET(&toolbar->ctrl);
675 gate_ui_host_t* host = GATE_UI_GTK_GET_CTRL_HOST(&toolbar->ctrl);
676 GtkWidget* icon_widget;
677 GtkToolItem* item;
678
679 ret = gate_ui_icon_create_image(&icon, host, raster);
680 GATE_BREAK_IF_FAILED(ret);
681 icon_widget = gtk_image_new_from_pixbuf((GdkPixbuf*)icon.resources[0]);
682 if (NULL == icon_widget)
683 {
684 ret = GATE_RESULT_FAILED;
685 break;
686 }
687 item = gtk_tool_button_new(icon_widget, NULL);
688 if (NULL == item)
689 {
690 gtk_widget_destroy(icon_widget);
691 ret = GATE_RESULT_FAILED;
692 break;
693 }
694 gtk_toolbar_insert(GTK_TOOLBAR(widget), item, -1);
695 gtk_widget_show_all(widget);
696
697 g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(gate_ui_toolbar_button_clicked), (gpointer)button_param);
698
699 if (button_id)
700 {
701 *button_id = (gate_ui_toolbar_button_t)item;
702 }
703
704 } while (0);
705
706 gate_ui_icon_destroy(&icon);
707
708 return ret;
709 }
710
711 gate_result_t gate_ui_toolbar_add_separator(gate_ui_toolbar_t* toolbar)
712 {
713 gate_result_t ret = GATE_RESULT_OK;
714 do
715 {
716 GtkWidget* widget = GATE_UI_GTK_GET_CTRL_WIDGET(&toolbar->ctrl);
717 GtkToolItem* item = gtk_tool_item_new();
718 if (NULL == item)
719 {
720 ret = GATE_RESULT_OUTOFMEMORY;
721 break;
722 }
723 gtk_toolbar_insert(GTK_TOOLBAR(widget), item, -1);
724 } while (0);
725 return ret;
726 }
727
728 #endif
729
730
731
732 #if defined(GATE_UI_MOTIF)
733
734 #include "gate/ui/gateui_motif.h"
735 #include "gate/debugging.h"
736 #include <Xm/RowColumn.h>
737 #include <Xm/PushB.h>
738
739 1 static gate_result_t motif_toolbar_destroy(gate_ui_ctrl_t* ctrl)
740 {
741 Widget w;
742 1 gate_ui_host_t* host = NULL;
743
744
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_DEBUG_ASSERT(ctrl != NULL);
745
746 1 w = GATE_UI_MOTIF_GET_CTRL_WIDGET(ctrl);
747 1 host = GATE_UI_MOTIF_GET_CTRL_HOST(ctrl);
748
749
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 if (w && host)
750 {
751 1 Cardinal wcnt = 0;
752 1 WidgetList wl = NULL;
753 1 Display* dpy = GATE_UI_MOTIF_GET_HOST_DISPLAY(host);
754 1 XtVaGetValues(w, XmNnumChildren, &wcnt, XmNchildren, &wl, NULL, NULL);
755
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 while (wcnt-- > 0)
756 {
757 1 Widget child = wl[wcnt];
758 1 Pixmap pm = 0;
759
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!child) continue;
760 1 XtVaGetValues(child, XmNarmPixmap, &pm, NULL, NULL);
761
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (pm)
762 {
763 1 XFreePixmap(dpy, pm);
764 }
765 1 XtUnmanageChild(child);
766 1 XtDestroyWidget(child);
767 }
768
769 1 gate_ui_motif_widget_destroy_children(w, false);
770 }
771 1 return gate_ui_motif_ctrl_destroy_default(ctrl);
772 }
773
774 static gate_result_t motif_toolbar_get_text(gate_ui_ctrl_t* ctrl, gate_string_t* ptr_text)
775 {
776 GATE_UNUSED_ARG(ctrl);
777 GATE_UNUSED_ARG(ptr_text);
778 return GATE_RESULT_NOTIMPLEMENTED;
779 }
780
781 static gate_result_t motif_toolbar_set_text(gate_ui_ctrl_t* ctrl, gate_string_t const* text)
782 {
783 GATE_UNUSED_ARG(ctrl);
784 GATE_UNUSED_ARG(text);
785 return GATE_RESULT_NOTIMPLEMENTED;
786 }
787
788 static gate_result_t motif_toolbar_get_state(gate_ui_ctrl_t* ctrl, gate_int32_t* ptr_state)
789 {
790 GATE_UNUSED_ARG(ctrl);
791 GATE_UNUSED_ARG(ptr_state);
792 return GATE_RESULT_NOTIMPLEMENTED;
793 }
794
795 static gate_result_t motif_toolbar_set_state(gate_ui_ctrl_t* ctrl, gate_int32_t state)
796 {
797 GATE_UNUSED_ARG(ctrl);
798 GATE_UNUSED_ARG(state);
799 return GATE_RESULT_NOTIMPLEMENTED;
800 }
801
802 2 static gate_result_t motif_toolbar_refresh(gate_ui_ctrl_t* ctrl)
803 {
804 2 return gate_ui_motif_ctrl_refresh(ctrl);
805 }
806
807 1 static gate_result_t motif_toolbar_get_children(gate_ui_ctrl_t* ctrl, void** ptr_to_widgetlist, gate_size_t* ptr_to_children_count)
808 {
809 GATE_UNUSED_ARG(ctrl);
810
811
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (ptr_to_widgetlist) *ptr_to_widgetlist = NULL;
812
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (ptr_to_children_count) *ptr_to_children_count = 0;
813 1 return GATE_RESULT_OK;
814 }
815
816
817 static gate_ui_motif_dispatcher_t tb_dispatcher =
818 {
819 &motif_toolbar_destroy,
820 &motif_toolbar_get_text,
821 &motif_toolbar_set_text,
822 &motif_toolbar_get_state,
823 &motif_toolbar_set_state,
824 &motif_toolbar_refresh,
825 &motif_toolbar_get_children
826 };
827
828 1 gate_result_t gate_ui_toolbar_create(gate_ui_toolbar_t* toolbar, gate_ui_ctrl_t* parent, gate_ui_position_t const* position,
829 gate_uint32_t flags, void* userparam)
830 {
831 1 gate_result_t ret = GATE_RESULT_FAILED;
832
833 do
834 {
835 Arg args[8];
836 1 unsigned args_count = 0;
837
838
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if (!toolbar || !parent)
839 {
840 ret = GATE_RESULT_INVALIDARG;
841 break;
842 }
843
844 1 XtSetArg(args[args_count], XmNorientation, XmHORIZONTAL); ++args_count;
845 1 XtSetArg(args[args_count], XmNshadowThickness, 1); ++args_count;
846 1 XtSetArg(args[args_count], XmNhighlightThickness, 1); ++args_count;
847
848 1 ret = gate_ui_motif_ctrl_create(&toolbar->ctrl, xmRowColumnWidgetClass, userparam, NULL, parent,
849 position, &flags, false, &tb_dispatcher, args, args_count);
850
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
851 } while (0);
852
853 1 return ret;
854 }
855
856 static void toolbar_button_pushed(Widget widget, XtPointer client_data, XtPointer call_data)
857 {
858 void* button_param = (void*)client_data;
859 Widget parent = XtParent(widget);
860 gate_ui_ctrl_t* ptr_ctrl = gate_ui_motif_widget_get_ctrl(parent);
861 gate_ui_toolbar_t* ptr_toolbar = (gate_ui_toolbar_t*)ptr_ctrl;
862 gate_ui_toolbar_button_t button_id = (gate_ui_toolbar_button_t)widget;
863
864
865 if (!ptr_toolbar || !ptr_toolbar->on_click)
866 {
867 return;
868 }
869 ptr_toolbar->on_click(ptr_ctrl, button_id, button_param);
870 }
871
872 gate_result_t gate_ui_toolbar_add_icon_button(gate_ui_toolbar_t* toolbar, gate_ui_icon_t const* icon, void* button_param,
873 gate_ui_toolbar_button_t* button_id)
874 {
875 return GATE_RESULT_NOTIMPLEMENTED;
876 }
877
878 1 gate_result_t gate_ui_toolbar_add_image_button(gate_ui_toolbar_t* toolbar, gate_rasterimage_t const* raster, void* button_param,
879 gate_ui_toolbar_button_t* button_id)
880 {
881 1 gate_result_t ret = GATE_RESULT_FAILED;
882 1 Widget new_button = NULL;
883
884
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_DEBUG_ASSERT(toolbar != NULL);
885
886 do
887 {
888 1 gate_ui_host_t* host = GATE_UI_MOTIF_GET_CTRL_HOST(&toolbar->ctrl);
889 1 Widget widget_tb = GATE_UI_MOTIF_GET_CTRL_WIDGET(&toolbar->ctrl);
890 gate_ui_graphics_t graph;
891 1 gate_ui_position_t pos = { 0, 0, 32, 32 };
892 1 gate_ui_color_t bg_col = { 192, 192, 192, 255 };
893 1 Pixmap pm = 0;
894 Arg args[8];
895 1 Cardinal args_count = 0;
896
897
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_DEBUG_ASSERT(widget_tb != NULL);
898
899 1 ret = gate_ui_graphics_create_image(&graph, host, raster->width, raster->height, 0);
900
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
901
902 1 gate_ui_graphics_rect(&graph, pos, &bg_col, 0, &bg_col);
903 1 ret = gate_ui_graphics_draw_image(&graph, raster, NULL, NULL, NULL);
904
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
905
906 1 pm = (Pixmap)gate_ui_graphics_surface(&graph);
907 1 graph.resources[1] = NULL; /* remove pixmap resource from graphics object */
908
909 1 XtSetArg(args[args_count], XmNuserData, NULL); ++args_count;
910 1 XtSetArg(args[args_count], XmNlabelType, XmPIXMAP); ++args_count;
911 1 XtSetArg(args[args_count], XmNarmPixmap, pm); ++args_count;
912 1 XtSetArg(args[args_count], XmNshadowThickness, 1); ++args_count;
913 1 XtSetArg(args[args_count], XmNhighlightThickness, 1); ++args_count;
914
915 1 new_button = XtCreateWidget(NULL, xmPushButtonWidgetClass, widget_tb, args, args_count);
916 1 gate_ui_graphics_destroy(&graph);
917
918
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!new_button)
919 {
920 ret = GATE_RESULT_FAILED;
921 break;
922 }
923
924 1 XtManageChild(new_button);
925
926 1 XtAddCallback(new_button, XmNactivateCallback, &toolbar_button_pushed, button_param);
927
928 1 *button_id = (gate_ui_toolbar_button_t)(gate_intptr_t)new_button;
929 1 ret = GATE_RESULT_OK;
930 } while (0);
931
932
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 if (GATE_FAILED(ret) && (new_button != NULL))
933 {
934 XtDestroyWidget(new_button);
935 }
936 1 return ret;
937 }
938
939 gate_result_t gate_ui_toolbar_add_separator(gate_ui_toolbar_t* toolbar)
940 {
941 return GATE_RESULT_OK;
942 }
943
944
945
946 #endif /* GATE_UI_MOTIF */
947