GCC Code Coverage Report


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