GCC Code Coverage Report


Directory: src/gate/
File: src/gate/ui/treeviews.c
Date: 2025-09-14 13:10:38
Exec Total Coverage
Lines: 0 239 0.0%
Functions: 0 28 0.0%
Branches: 0 82 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/treeviews.h"
30 #include "gate/results.h"
31 #include "gate/debugging.h"
32
33 #if defined(GATE_UI_WINAPI)
34
35 #include "gate/ui/gateui_winapi.h"
36 #include "gate/platforms.h"
37 #ifdef _WIN32_IE
38 # undef _WIN32_IE
39 # if defined(GATE_COMPILER_TCC)
40 # define _WIN32_IE 0x0501
41 # else
42 # define _WIN32_IE 0x0400
43 # endif
44 #endif
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 #define TV_HITTESTINFO TVHITTESTINFO
56
57 struct _TREEITEM;
58 typedef struct _TREEITEM* HTREEITEM;
59
60 typedef struct tagTVHITTESTINFO {
61 POINT pt;
62 UINT flags;
63 HTREEITEM hItem;
64 } TVHITTESTINFO, * LPTVHITTESTINFO;
65
66 #define LPTV_ITEM LPTVITEM
67 #define TV_ITEM TVITEM
68
69 typedef struct tagTVITEM {
70 UINT mask;
71 HTREEITEM hItem;
72 UINT state;
73 UINT stateMask;
74 LPSTR pszText;
75 int cchTextMax;
76 int iImage;
77 int iSelectedImage;
78 int cChildren;
79 LPARAM lParam;
80 } TVITEM, * LPTVITEM;
81
82 typedef struct tagNMTREEVIEW {
83 NMHDR hdr;
84 UINT action;
85 TVITEM itemOld;
86 TVITEM itemNew;
87 POINT ptDrag;
88 } NMTREEVIEW, * LPNMTREEVIEW;
89
90 #define WM_NOTIFY 0x004E
91 #define TV_FIRST 0x1100 // TreeView messages
92 #define TVHT_NOWHERE 0x0001
93 #define TVHT_ONITEMICON 0x0002
94 #define TVHT_ONITEMLABEL 0x0004
95 #define TVHT_ONITEMSTATEICON 0x0040
96 #define TVHT_ONITEM (TVHT_ONITEMICON | TVHT_ONITEMLABEL | TVHT_ONITEMSTATEICON)
97 #define TVHT_ONITEMINDENT 0x0008
98 #define TVHT_ONITEMBUTTON 0x0010
99 #define TVHT_ONITEMRIGHT 0x0020
100 #define TVHT_ONITEMSTATEICON 0x0040
101
102 #define TVHT_ABOVE 0x0100
103 #define TVHT_BELOW 0x0200
104 #define TVHT_TORIGHT 0x0400
105 #define TVHT_TOLEFT 0x0800
106
107 #define TVGN_ROOT 0x0000
108 #define TVGN_NEXT 0x0001
109 #define TVGN_PREVIOUS 0x0002
110 #define TVGN_PARENT 0x0003
111 #define TVGN_CHILD 0x0004
112 #define TVGN_FIRSTVISIBLE 0x0005
113 #define TVGN_NEXTVISIBLE 0x0006
114 #define TVGN_PREVIOUSVISIBLE 0x0007
115 #define TVGN_DROPHILITE 0x0008
116 #define TVGN_CARET 0x0009
117 #define TVGN_LASTVISIBLE 0x000A
118
119 #define TVS_HASBUTTONS 0x0001
120 #define TVS_HASLINES 0x0002
121 #define TVS_LINESATROOT 0x0004
122 #define TVS_EDITLABELS 0x0008
123 #define TVS_DISABLEDRAGDROP 0x0010
124 #define TVS_SHOWSELALWAYS 0x0020
125 #define TVS_RTLREADING 0x0040
126
127 #define TVS_NOTOOLTIPS 0x0080
128 #define TVS_CHECKBOXES 0x0100
129 #define TVS_TRACKSELECT 0x0200
130 #define TVS_SINGLEEXPAND 0x0400
131 #define TVS_INFOTIP 0x0800
132 #define TVS_FULLROWSELECT 0x1000
133 #define TVS_NOSCROLL 0x2000
134 #define TVS_NONEVENHEIGHT 0x4000
135 #define TVS_NOHSCROLL 0x8000
136
137 #define TVE_COLLAPSE 0x0001
138 #define TVE_EXPAND 0x0002
139 #define TVE_TOGGLE 0x0003
140 #define TVE_EXPANDPARTIAL 0x4000
141 #define TVE_COLLAPSERESET 0x8000
142
143 #define TVN_FIRST (0U-400U) // treeview
144 #define TVN_LAST (0U-499U)
145 #define TVN_SELCHANGED (TVN_FIRST-2)
146
147 #define WC_TREEVIEW "SysTreeView"
148
149
150
151 #define TVM_SELECTITEM (TV_FIRST + 11)
152 #define TreeView_Select(hwnd, hitem, code) \
153 (BOOL)SendMessage((hwnd), TVM_SELECTITEM, (WPARAM)(code), (LPARAM)(HTREEITEM)(hitem))
154
155
156 #define TreeView_SelectItem(hwnd, hitem) TreeView_Select(hwnd, hitem, TVGN_CARET)
157 #define TreeView_SelectDropTarget(hwnd, hitem) TreeView_Select(hwnd, hitem, TVGN_DROPHILITE)
158 #define TreeView_SelectSetFirstVisible(hwnd, hitem) TreeView_Select(hwnd, hitem, TVGN_FIRSTVISIBLE)
159
160 #define TVM_HITTEST (TV_FIRST + 17)
161 #define TreeView_HitTest(hwnd, lpht) \
162 (HTREEITEM)SendMessage((hwnd), TVM_HITTEST, 0, (LPARAM)(LPTV_HITTESTINFO)(lpht))
163
164 #define LPTV_HITTESTINFO LPTVHITTESTINFO
165
166 #define TVM_INSERTITEM (TV_FIRST + 0)
167 #define TreeView_InsertItem(hwnd, lpis) \
168 (HTREEITEM)SendMessage((hwnd), TVM_INSERTITEM, 0, (LPARAM)(LPTV_INSERTSTRUCT)(lpis))
169
170
171 #define TVM_DELETEITEM (TV_FIRST + 1)
172 #define TreeView_DeleteItem(hwnd, hitem) \
173 (BOOL)SendMessage((hwnd), TVM_DELETEITEM, 0, (LPARAM)(HTREEITEM)(hitem))
174
175
176 #define TreeView_DeleteAllItems(hwnd) \
177 (BOOL)SendMessage((hwnd), TVM_DELETEITEM, 0, (LPARAM)TVI_ROOT)
178
179
180 #define TVM_EXPAND (TV_FIRST + 2)
181 #define TreeView_Expand(hwnd, hitem, code) \
182 (BOOL)SendMessage((hwnd), TVM_EXPAND, (WPARAM)(code), (LPARAM)(HTREEITEM)(hitem))
183
184 #define TVM_GETNEXTITEM (TV_FIRST + 10)
185 #define TreeView_GetNextItem(hwnd, hitem, code) \
186 (HTREEITEM)SendMessage((hwnd), TVM_GETNEXTITEM, (WPARAM)(code), (LPARAM)(HTREEITEM)(hitem))
187
188 #define TVM_GETITEM (TV_FIRST + 12)
189 #define TreeView_GetItem(hwnd, pitem) \
190 (BOOL)SendMessage((hwnd), TVM_GETITEM, 0, (LPARAM)(TV_ITEM *)(pitem))
191
192 #define TVM_SETITEM (TV_FIRST + 13)
193 #define TreeView_SetItem(hwnd, pitem) \
194 (BOOL)SendMessage((hwnd), TVM_SETITEM, 0, (LPARAM)(const TV_ITEM *)(pitem))
195
196
197 #define TreeView_GetChild(hwnd, hitem) TreeView_GetNextItem(hwnd, hitem, TVGN_CHILD)
198 #define TreeView_GetNextSibling(hwnd, hitem) TreeView_GetNextItem(hwnd, hitem, TVGN_NEXT)
199 #define TreeView_GetPrevSibling(hwnd, hitem) TreeView_GetNextItem(hwnd, hitem, TVGN_PREVIOUS)
200 #define TreeView_GetParent(hwnd, hitem) TreeView_GetNextItem(hwnd, hitem, TVGN_PARENT)
201 #define TreeView_GetFirstVisible(hwnd) TreeView_GetNextItem(hwnd, NULL, TVGN_FIRSTVISIBLE)
202 #define TreeView_GetNextVisible(hwnd, hitem) TreeView_GetNextItem(hwnd, hitem, TVGN_NEXTVISIBLE)
203 #define TreeView_GetPrevVisible(hwnd, hitem) TreeView_GetNextItem(hwnd, hitem, TVGN_PREVIOUSVISIBLE)
204 #define TreeView_GetSelection(hwnd) TreeView_GetNextItem(hwnd, NULL, TVGN_CARET)
205 #define TreeView_GetDropHilight(hwnd) TreeView_GetNextItem(hwnd, NULL, TVGN_DROPHILITE)
206 #define TreeView_GetRoot(hwnd) TreeView_GetNextItem(hwnd, NULL, TVGN_ROOT)
207 #define TreeView_GetLastVisible(hwnd) TreeView_GetNextItem(hwnd, NULL, TVGN_LASTVISIBLE)
208
209
210 typedef struct tagTVINSERTSTRUCT {
211 HTREEITEM hParent;
212 HTREEITEM hInsertAfter;
213 TV_ITEM item;
214 } TVINSERTSTRUCT, * LPTVINSERTSTRUCT;
215
216 #define TV_INSERTSTRUCT TVINSERTSTRUCT
217 #define LPTV_INSERTSTRUCT LPTVINSERTSTRUCT
218
219 #define TVIF_TEXT 0x0001
220 #define TVIF_IMAGE 0x0002
221 #define TVIF_PARAM 0x0004
222 #define TVIF_STATE 0x0008
223 #define TVIF_HANDLE 0x0010
224 #define TVIF_SELECTEDIMAGE 0x0020
225 #define TVIF_CHILDREN 0x0040
226 #define TVIF_INTEGRAL 0x0080
227
228 #define TVIS_SELECTED 0x0002
229 #define TVIS_CUT 0x0004
230 #define TVIS_DROPHILITED 0x0008
231 #define TVIS_BOLD 0x0010
232 #define TVIS_EXPANDED 0x0020
233 #define TVIS_EXPANDEDONCE 0x0040
234 #define TVIS_EXPANDPARTIAL 0x0080
235
236 #define TVIS_OVERLAYMASK 0x0F00
237 #define TVIS_STATEIMAGEMASK 0xF000
238 #define TVIS_USERMASK 0xF000
239
240 #define TVI_ROOT ((HTREEITEM)(ULONG_PTR)-0x10000)
241 #define TVI_FIRST ((HTREEITEM)(ULONG_PTR)-0x0FFFF)
242 #define TVI_LAST ((HTREEITEM)(ULONG_PTR)-0x0FFFE)
243 #define TVI_SORT ((HTREEITEM)(ULONG_PTR)-0x0FFFD)
244
245
246 #else /* GATE_SYS_WIN16 */
247 #include <commctrl.h>
248 #endif
249
250
251
252 static COLORREF gate_ui_treeview_get_bk_color(gate_ui_ctrl_t* ctrl)
253 {
254 gate_ui_host_t* host = GATE_UI_WINAPI_GET_HOST(ctrl);
255 gate_color_t color;
256 gate_ui_host_default_color(host, GATE_UI_COLOR_CONTENTBACKGROUND, &color);
257 return RGB(color.r, color.g, color.b);
258 }
259
260 static COLORREF gate_ui_treeview_get_text_color(gate_ui_ctrl_t* ctrl)
261 {
262 gate_ui_host_t* host = GATE_UI_WINAPI_GET_HOST(ctrl);
263 gate_color_t color;
264 gate_ui_host_default_color(host, GATE_UI_COLOR_CONTENTTEXT, &color);
265 return RGB(color.r, color.g, color.b);
266 }
267
268
269 static void gate_ui_treeview_update_colors(gate_ui_ctrl_t* ctrl)
270 {
271 #if !defined(GATE_SYS_WINCE) && !defined(GATE_SYS_WIN16)
272 HWND hwnd = GATE_UI_WINAPI_GET_HWND(ctrl);
273 COLORREF colref_bk = gate_ui_treeview_get_bk_color(ctrl);
274 COLORREF colref_text = gate_ui_treeview_get_text_color(ctrl);
275
276 if ((TreeView_GetBkColor(hwnd) != colref_bk) || (TreeView_GetTextColor(hwnd) != colref_text))
277 {
278 TreeView_SetBkColor(hwnd, colref_bk);
279 TreeView_SetTextColor(hwnd, colref_text);
280 }
281 #endif /* !GATE_SYS_WINCE */
282 }
283
284 static gate_bool_t gate_ui_treeview_events(void* hwnd, gate_ui_ctrl_t* ctrl, gate_uint32_t msg, gate_uintptr_t wParam, gate_intptr_t lParam, gate_intptr_t* lresult)
285 {
286 HWND hwndCtrl;
287 gate_ui_treeview_t* trvw;
288 TV_HITTESTINFO hti;
289 HTREEITEM hItem;
290 NMHDR* nmhdr;
291 NMTREEVIEW* nmtv;
292 HDC hdc;
293 HBRUSH hbrush;
294 RECT rect;
295 BOOL succeeded = TRUE;
296
297 if ((ctrl) && (hwnd))
298 {
299 trvw = (gate_ui_treeview_t*)ctrl;
300 hwndCtrl = GATE_UI_WINAPI_GET_HWND(ctrl);
301
302 if (hwndCtrl)
303 {
304 switch (msg)
305 {
306 case WM_ERASEBKGND:
307 {
308 gate_ui_treeview_update_colors(ctrl);
309
310 hdc = (HDC)wParam;
311 #if !defined(GATE_SYS_WIN16)
312 succeeded =
313 #endif
314 GetClientRect(hwndCtrl, &rect);
315 if (succeeded)
316 {
317 hbrush = CreateSolidBrush(gate_ui_treeview_get_bk_color(ctrl));
318 if (hbrush)
319 {
320 FillRect(hdc, &rect, hbrush);
321 DeleteObject((HGDIOBJ)hbrush);
322 }
323 }
324 *lresult = 1;
325 return true;
326 break;
327 }
328 case WM_LBUTTONDBLCLK:
329 {
330 hti.flags = TVHT_ONITEM;
331 hti.hItem = NULL;
332 hti.pt.x = (LONG)LOWORD(lParam);
333 hti.pt.y = (LONG)HIWORD(lParam);
334 hItem = TreeView_HitTest(hwndCtrl, &hti);
335 if (hItem != NULL)
336 {
337 if (trvw->on_dblclick != NULL)
338 {
339 trvw->on_dblclick(&trvw->ctrl, (gate_ui_treeview_item_t)hItem);
340 }
341 }
342 *lresult = 0;
343 return true;
344 }
345 case WM_RBUTTONDOWN:
346 {
347 hti.flags = TVHT_ONITEM;
348 hti.hItem = NULL;
349 hti.pt.x = (LONG)LOWORD(lParam);
350 hti.pt.y = (LONG)HIWORD(lParam);
351 hItem = TreeView_HitTest(hwndCtrl, &hti);
352 if (hItem != NULL)
353 {
354 if (trvw->on_contextmenu != NULL)
355 {
356 TreeView_SelectDropTarget(hwndCtrl, hItem);
357 trvw->on_contextmenu(&trvw->ctrl, (gate_ui_treeview_item_t)hItem);
358 TreeView_SelectDropTarget(hwndCtrl, NULL);
359 }
360 }
361 *lresult = 0;
362 return true;
363 }
364 case WM_NOTIFY:
365 {
366 nmhdr = (NMHDR*)lParam;
367 if (nmhdr->hwndFrom == hwndCtrl)
368 {
369 switch (nmhdr->code)
370 {
371 case TVN_SELCHANGED:
372 {
373 nmtv = (NMTREEVIEW*)nmhdr;
374 trvw->on_select(&trvw->ctrl, (gate_ui_treeview_item_t)nmtv->itemNew.hItem);
375 *lresult = 0;
376 return true;
377 }
378 }
379 }
380 break;
381 }
382 default:
383 {
384 break;
385 }
386 }
387 }
388 }
389 return false;
390 }
391
392 gate_result_t gate_ui_treeview_create(
393 gate_ui_treeview_t* trvw, gate_ui_ctrl_t* parent,
394 gate_ui_position_t const* position,
395 gate_uint32_t flags,
396 void* userparam
397 )
398 {
399 gate_result_t ret;
400 gate_uint32_t styles, exstyles;
401 gate_ui_host_t* host;
402 HWND hwndParent;
403 HWND hwnd;
404
405 do
406 {
407 host = gate_ui_ctrl_get_host(parent);
408 if (host == NULL)
409 {
410 ret = GATE_RESULT_INVALIDSTATE;
411 break;
412 }
413 hwndParent = GATE_UI_WINAPI_GET_HWND(parent);
414 if (hwndParent == NULL)
415 {
416 ret = GATE_RESULT_INVALIDSTATE;
417 break;
418 }
419
420 gate_mem_clear(trvw, sizeof(gate_ui_treeview_t));
421
422 exstyles = 0;
423 #if !defined(GATE_SYS_WIN16)
424 exstyles |= WS_EX_CLIENTEDGE;
425 #endif
426 styles = WS_CHILD | WS_CLIPSIBLINGS | WS_TABSTOP | TVS_HASLINES | TVS_LINESATROOT | TVS_HASBUTTONS | TVS_SHOWSELALWAYS;
427
428 if (!GATE_FLAG_ENABLED(flags, GATE_UI_FLAG_ENABLED)) styles |= WS_DISABLED;
429 if (GATE_FLAG_ENABLED(flags, GATE_UI_FLAG_VISIBLE)) styles |= WS_VISIBLE;
430
431 ret = gate_ui_winapi_create(&trvw->ctrl, host, hwndParent, WC_TREEVIEW, position, styles, exstyles, NULL, userparam, true);
432 if (GATE_SUCCEEDED(ret))
433 {
434 hwnd = GATE_UI_WINAPI_GET_HWND(&trvw->ctrl);
435
436 #if !defined(GATE_SYS_WIN16)
437 if (GATE_FLAG_ENABLED(flags, GATE_UI_FLAG_TREEVIEW_ICONS))
438 {
439 ret = gate_ui_iconlist_create(&trvw->icons, host, 16, 16);
440 if (GATE_FAILED(ret))
441 {
442 gate_ui_winapi_destroy(&trvw->ctrl);
443 break;
444 }
445 TreeView_SetImageList(hwnd, (HIMAGELIST)trvw->icons.resources[0], TVSIL_NORMAL);
446 }
447 #endif
448 gate_ui_winapi_register_event(host, hwndParent, WM_NOTIFY, &gate_ui_treeview_events, &trvw->ctrl);
449 gate_ui_winapi_register_event(host, hwnd, WM_RBUTTONDOWN, &gate_ui_treeview_events, &trvw->ctrl);
450 gate_ui_winapi_register_event(host, hwnd, WM_LBUTTONDBLCLK, &gate_ui_treeview_events, &trvw->ctrl);
451 gate_ui_winapi_register_event(host, hwnd, WM_ERASEBKGND, &gate_ui_treeview_events, &trvw->ctrl);
452
453 gate_ui_treeview_update_colors(&trvw->ctrl);
454 gate_ui_winapi_refresh(&trvw->ctrl);
455 }
456 } while (0);
457
458 return ret;
459 }
460
461 gate_result_t gate_ui_treeview_add_icon(gate_ui_treeview_t* trvw, gate_ui_icon_t const* icon, gate_intptr_t* icon_key)
462 {
463 return gate_ui_iconlist_add(&trvw->icons, icon, icon_key);
464 }
465
466 gate_result_t gate_ui_treeview_add_icon_image(gate_ui_treeview_t* trvw, gate_rasterimage_t const* image, gate_intptr_t* icon_key)
467 {
468 return gate_ui_iconlist_add_image(&trvw->icons, image, icon_key);
469 }
470
471 gate_result_t gate_ui_treeview_add(gate_ui_treeview_t* trvw, gate_ui_treeview_item_t const* parent, gate_string_t const* text,
472 gate_intptr_t iconkey, void* itemparam, gate_ui_treeview_item_t* newitem)
473 {
474 HWND hwnd = GATE_UI_WINAPI_GET_HWND(&trvw->ctrl);
475 TVINSERTSTRUCT insert;
476 HTREEITEM newtreeitem;
477 TCHAR txtbuffer[4096];
478 gate_size_t txtbufferused = gate_win32_utf8_2_winstr(text->str, text->length, txtbuffer, sizeof(txtbuffer) / sizeof(txtbuffer[0]));
479 gate_mem_clear(&insert, sizeof(insert));
480 insert.item.mask = TVIF_PARAM | TVIF_TEXT | TVIF_STATE;
481 insert.item.pszText = &txtbuffer[0];
482 insert.item.cchTextMax = (int)txtbufferused;
483 insert.item.stateMask = TVIS_SELECTED;
484 insert.item.lParam = (LPARAM)(gate_intptr_t)itemparam;
485 if (parent == NULL)
486 {
487 insert.hParent = NULL;
488 insert.hInsertAfter = TVI_ROOT;
489 }
490 else
491 {
492 insert.hParent = (HTREEITEM)*parent;
493 insert.hInsertAfter = TVI_LAST;
494 }
495 if (trvw->icons.resources[0] != NULL)
496 {
497 if (iconkey != GATE_UI_TREEVIEW_INVALID_ICON)
498 {
499 insert.item.iImage = (int)iconkey;
500 insert.item.iSelectedImage = (int)iconkey;
501 insert.item.mask |= (TVIF_IMAGE | TVIF_SELECTEDIMAGE);
502 }
503 }
504
505 newtreeitem = TreeView_InsertItem(hwnd, &insert);
506 if (newtreeitem)
507 {
508 *newitem = (gate_ui_treeview_item_t)newtreeitem;
509 return GATE_RESULT_OK;
510 }
511 else
512 {
513 return GATE_RESULT_FAILED;
514 }
515 }
516
517 gate_result_t gate_ui_treeview_remove(gate_ui_treeview_t* trvw, gate_ui_treeview_item_t item)
518 {
519 HWND hwnd = GATE_UI_WINAPI_GET_HWND(&trvw->ctrl);
520 if (TreeView_DeleteItem(hwnd, (HTREEITEM)item))
521 {
522 return GATE_RESULT_OK;
523 }
524 else
525 {
526 return GATE_RESULT_FAILED;
527 }
528 }
529
530 gate_result_t gate_ui_treeview_clear(gate_ui_treeview_t* trvw)
531 {
532 HWND hwnd = GATE_UI_WINAPI_GET_HWND(&trvw->ctrl);
533 if (TreeView_DeleteAllItems(hwnd))
534 {
535 return GATE_RESULT_OK;
536 }
537 else
538 {
539 return GATE_RESULT_FAILED;
540 }
541 }
542
543 void* gate_ui_treeview_get_itemparam(gate_ui_treeview_t* trvw, gate_ui_treeview_item_t item)
544 {
545 HWND hwnd = GATE_UI_WINAPI_GET_HWND(&trvw->ctrl);
546 TVITEM tvitem;
547 gate_mem_clear(&tvitem, sizeof(tvitem));
548 tvitem.hItem = (HTREEITEM)item;
549 tvitem.mask = TVIF_PARAM;
550 if (TreeView_GetItem(hwnd, &tvitem))
551 {
552 return (void*)(gate_intptr_t)tvitem.lParam;
553 }
554 return NULL;
555 }
556
557
558 gate_result_t gate_ui_treeview_get_parent(gate_ui_treeview_t* trvw, gate_ui_treeview_item_t item, gate_ui_treeview_item_t* parent)
559 {
560 HWND hwnd = GATE_UI_WINAPI_GET_HWND(&trvw->ctrl);
561 HTREEITEM parentItem = TreeView_GetParent(hwnd, (HTREEITEM)item);
562 if (parentItem == NULL)
563 {
564 return GATE_RESULT_NOTAVAILABLE;
565 }
566 else
567 {
568 *parent = (gate_ui_treeview_item_t)parentItem;
569 return GATE_RESULT_OK;
570 }
571 }
572 gate_result_t gate_ui_treeview_get_children(gate_ui_treeview_t* trvw, gate_ui_treeview_item_t item, gate_array_t* children)
573 {
574 gate_result_t ret;
575 HWND hwnd = GATE_UI_WINAPI_GET_HWND(&trvw->ctrl);
576 HTREEITEM child = TreeView_GetChild(hwnd, (HTREEITEM)item);
577 TVITEM itemdata;
578 gate_arraylist_t itemlist;
579 gate_size_t prealloc = 0;
580 gate_ui_treeview_item_t nextitem;
581 if (child != NULL)
582 {
583 gate_mem_clear(&itemdata, sizeof(itemdata));
584 itemdata.hItem = (HTREEITEM)item;
585 itemdata.mask = TVIF_CHILDREN;
586 if (TreeView_GetItem(hwnd, &itemdata))
587 {
588 prealloc = itemdata.cChildren;
589 }
590 }
591 itemlist = gate_arraylist_create(sizeof(gate_ui_treeview_item_t), NULL, prealloc, NULL, NULL);
592 if (!itemlist)
593 {
594 ret = GATE_RESULT_OUTOFMEMORY;
595 }
596 else
597 {
598 ret = GATE_RESULT_OK;
599 while (child != NULL)
600 {
601 nextitem = (gate_ui_treeview_item_t)child;
602 if (NULL == gate_arraylist_add(itemlist, &nextitem))
603 {
604 ret = GATE_RESULT_OUTOFMEMORY;
605 break;
606 }
607 child = TreeView_GetNextItem(hwnd, child, TVGN_NEXT);
608 }
609 if (GATE_SUCCEEDED(ret))
610 {
611 if (NULL == gate_array_create(children, itemlist))
612 {
613 ret = GATE_RESULT_FAILED;
614 }
615 }
616 gate_arraylist_release(itemlist);
617 }
618 return ret;
619 }
620 gate_result_t gate_ui_treeview_get_text(gate_ui_treeview_t* trvw, gate_ui_treeview_item_t item, gate_string_t* text)
621 {
622 HWND hwnd = GATE_UI_WINAPI_GET_HWND(&trvw->ctrl);
623 TCHAR buffer[4096];
624 TVITEM tvitem;
625 gate_mem_clear(&tvitem, sizeof(tvitem));
626 tvitem.hItem = (HTREEITEM)item;
627 tvitem.mask = TVIF_TEXT;
628 tvitem.pszText = &buffer[0];
629 tvitem.cchTextMax = sizeof(buffer) / sizeof(buffer[0]);
630 if (TreeView_GetItem(hwnd, &tvitem))
631 {
632 if (NULL != gate_win32_winstr_2_utf8_string(buffer, tvitem.cchTextMax, text))
633 {
634 return GATE_RESULT_OK;
635 }
636 }
637 return GATE_RESULT_FAILED;
638 }
639 gate_result_t gate_ui_treeview_set_text(gate_ui_treeview_t* trvw, gate_ui_treeview_item_t item, gate_string_t const* text)
640 {
641 HWND hwnd = GATE_UI_WINAPI_GET_HWND(&trvw->ctrl);
642 TCHAR buffer[4096];
643 TVITEM tvitem;
644 gate_mem_clear(&tvitem, sizeof(tvitem));
645 tvitem.hItem = (HTREEITEM)item;
646 tvitem.mask = TVIF_TEXT;
647 tvitem.pszText = &buffer[0];
648 tvitem.cchTextMax = (int)gate_win32_utf8_2_winstr(text->str, text->length, buffer, sizeof(buffer) / sizeof(buffer[0]));
649 if (TreeView_SetItem(hwnd, &tvitem))
650 {
651 return GATE_RESULT_OK;
652 }
653 return GATE_RESULT_FAILED;
654 }
655
656 gate_bool_t gate_ui_treeview_is_expanded(gate_ui_treeview_t* trvw, gate_ui_treeview_item_t item)
657 {
658 HWND hwnd = GATE_UI_WINAPI_GET_HWND(&trvw->ctrl);
659 TVITEM tvitem;
660 gate_mem_clear(&tvitem, sizeof(tvitem));
661 tvitem.hItem = (HTREEITEM)item;
662 tvitem.mask = TVIF_STATE;
663 tvitem.stateMask = TVIS_EXPANDED;
664 tvitem.state = 0;
665 if (TreeView_GetItem(hwnd, &tvitem))
666 {
667 return (tvitem.state & TVIS_EXPANDED) == TVIS_EXPANDED;
668 }
669 return false;
670 }
671 gate_result_t gate_ui_treeview_set_expanded(gate_ui_treeview_t* trvw, gate_ui_treeview_item_t item, gate_bool_t expanded)
672 {
673 HWND hwnd = GATE_UI_WINAPI_GET_HWND(&trvw->ctrl);
674 if (TreeView_Expand(hwnd, (HTREEITEM)item, expanded ? TVE_EXPAND : TVE_COLLAPSE))
675 {
676 return GATE_RESULT_OK;
677 }
678 return GATE_RESULT_FAILED;
679 }
680
681 gate_result_t gate_ui_treeview_get_selected_item(gate_ui_treeview_t* trvw, gate_ui_treeview_item_t* item)
682 {
683 HWND hwnd = GATE_UI_WINAPI_GET_HWND(&trvw->ctrl);
684 HTREEITEM hitem = TreeView_GetSelection(hwnd);
685 if (hitem == NULL)
686 {
687 *item = (gate_ui_treeview_item_t)hitem;
688 return GATE_RESULT_OK;
689 }
690 else
691 {
692 return GATE_RESULT_NOMATCH;
693 }
694 }
695
696 gate_result_t gate_ui_treeview_select_item(gate_ui_treeview_t* trvw, gate_ui_treeview_item_t item)
697 {
698 HWND hwnd = GATE_UI_WINAPI_GET_HWND(&trvw->ctrl);
699 if (TreeView_SelectItem(hwnd, (HTREEITEM)item))
700 {
701 return GATE_RESULT_OK;
702 }
703 else
704 {
705 return GATE_RESULT_FAILED;
706 }
707 }
708
709
710 #endif /*GATE_UI_WINAPI*/
711
712
713
714 #if defined(GATE_UI_GTK)
715
716 #include "gate/ui/gateui_gtk.h"
717
718 #define GATE_UI_GTK_TREEVIEW_FIELD_TEXT 0
719 #define GATE_UI_GTK_TREEVIEW_FIELD_ID 1
720 #define GATE_UI_GTK_TREEVIEW_FIELD_PARAM 2
721 #define GATE_UI_GTK_TREEVIEW_FIELD_ICON 3
722
723 static void gate_ui_gtk_treeview_on_cursor_changed(GtkTreeView* tree_view, gpointer user_data)
724 {
725 gate_ui_treeview_t* trvw = (gate_ui_treeview_t*)user_data;
726 gate_ui_treeview_item_t item;
727 gate_result_t result;
728 result = gate_ui_treeview_get_selected_item(trvw, &item);
729 if (GATE_SUCCEEDED(result))
730 {
731 trvw->on_select(&trvw->ctrl, item);
732 }
733 else
734 {
735 trvw->on_select(&trvw->ctrl, GATE_UI_TREEVIEW_INVALID_ITEM);
736 }
737 }
738
739 static void gate_ui_gtk_treeview_on_destroy(GtkWidget* object, gpointer user_data)
740 {
741 gate_ui_treeview_t* trvw = (gate_ui_treeview_t*)user_data;
742 gate_ui_iconlist_destroy(&trvw->icons);
743 }
744
745 gate_result_t gate_ui_treeview_create(gate_ui_treeview_t* trvw, gate_ui_ctrl_t* parent,
746 gate_ui_position_t const* position, gate_uint32_t flags, void* userparam)
747 {
748 gate_result_t ret = GATE_RESULT_FAILED;
749 GtkWidget* widget;
750 GtkTreeViewColumn* col;
751 GtkCellRenderer* renderer;
752 GtkTreeModel* model;
753 /*GtkTreeStore* treestore;*/
754 GtkWidget* scroll_widget;
755
756 gate_ui_host_t* host = GATE_UI_GTK_GET_CTRL_HOST(parent);
757
758 do
759 {
760 gate_mem_clear(trvw, sizeof(gate_ui_treeview_t));
761 widget = gtk_tree_view_new();
762 if (widget == NULL)
763 {
764 ret = GATE_RESULT_OUTOFRESOURCES;
765 break;
766 }
767
768 col = gtk_tree_view_column_new();
769 gtk_tree_view_column_set_title(col, "Tree view");
770
771 renderer = gtk_cell_renderer_pixbuf_new();
772 gtk_tree_view_column_pack_start(col, renderer, FALSE);
773 gtk_tree_view_column_add_attribute(col, renderer, "pixbuf", GATE_UI_GTK_TREEVIEW_FIELD_ICON);
774 renderer = gtk_cell_renderer_text_new();
775 gtk_tree_view_column_pack_start(col, renderer, FALSE);
776 gtk_tree_view_column_add_attribute(col, renderer, "text", GATE_UI_GTK_TREEVIEW_FIELD_TEXT);
777
778 model = GTK_TREE_MODEL(gtk_tree_store_new(4,
779 G_TYPE_STRING, /* text */
780 G_TYPE_POINTER, /* item-id */
781 G_TYPE_POINTER, /* item-param */
782 GDK_TYPE_PIXBUF, /* icon */
783 -1));
784
785 gtk_tree_view_set_model(GTK_TREE_VIEW(widget), model);
786 g_object_unref(model);
787
788 gtk_tree_view_append_column(GTK_TREE_VIEW(widget), col);
789
790 scroll_widget = gtk_scrolled_window_new(NULL, NULL);
791 if (scroll_widget == NULL)
792 {
793 gtk_widget_destroy(widget);
794 ret = GATE_RESULT_OUTOFRESOURCES;
795 break;
796 }
797
798 gtk_container_add(GTK_CONTAINER(scroll_widget), widget);
799 gtk_widget_show(widget);
800
801 ret = gate_ui_gtk_ctrl_init(&trvw->ctrl, scroll_widget, host, userparam, parent,
802 NULL, false, false, position, &flags);
803
804 if (GATE_SUCCEEDED(ret))
805 {
806 ret = gate_ui_iconlist_create(&trvw->icons, host, 16, 16);
807 if (GATE_FAILED(ret))
808 {
809 gate_ui_gtk_ctrl_destroy(&trvw->ctrl);
810 break;
811 }
812
813 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(widget), FALSE);
814 gtk_tree_view_set_show_expanders(GTK_TREE_VIEW(widget), TRUE);
815
816 g_signal_connect(G_OBJECT(widget), "cursor-changed", G_CALLBACK(gate_ui_gtk_treeview_on_cursor_changed), (gpointer)trvw);
817 g_signal_connect(G_OBJECT(widget), "destroy", G_CALLBACK(gate_ui_gtk_treeview_on_destroy), (gpointer)trvw);
818 }
819 //cursor-changed
820 } while (0);
821
822 return ret;
823 }
824
825 gate_result_t gate_ui_treeview_add_icon(gate_ui_treeview_t* trvw, gate_ui_icon_t const* icon, gate_intptr_t* icon_key)
826 {
827 return gate_ui_iconlist_add(&trvw->icons, icon, icon_key);
828 }
829
830 gate_result_t gate_ui_treeview_add_icon_image(gate_ui_treeview_t* trvw, gate_rasterimage_t const* image, gate_intptr_t* icon_key)
831 {
832 return gate_ui_iconlist_add_image(&trvw->icons, image, icon_key);
833 }
834
835 static gate_atomic_int64_t gate_ui_treeview_item_id = 0;
836
837 static gate_bool_t gate_ui_treeview_resolve(GtkTreeModel* model, GtkTreeIter* current_iter, void* id, GtkTreeIter* found_iter)
838 {
839 GtkTreeIter first;
840 GtkTreeIter first_child;
841 GValue value = GATE_INIT_EMPTY;
842
843 if (current_iter == NULL)
844 {
845 if (!gtk_tree_model_get_iter_first(model, &first))
846 {
847 return false;
848 }
849 current_iter = &first;
850 }
851 do
852 {
853 gtk_tree_model_get_value(model, current_iter, 1, &value);
854 if (g_value_get_pointer(&value) == id)
855 {
856 *found_iter = *current_iter;
857 return true;
858 }
859 g_value_unset(&value);
860
861 if (gtk_tree_model_iter_children(model, &first_child, current_iter))
862 {
863 if (gate_ui_treeview_resolve(model, &first_child, id, found_iter))
864 {
865 return true;
866 }
867 }
868 } while (gtk_tree_model_iter_next(model, current_iter));
869 return false;
870 }
871
872 gate_result_t gate_ui_treeview_add(gate_ui_treeview_t* trvw, gate_ui_treeview_item_t const* parent, gate_string_t const* text,
873 gate_intptr_t icon_key, void* itemparam, gate_ui_treeview_item_t* newitem)
874 {
875 gate_result_t ret = GATE_RESULT_FAILED;
876 GtkWidget* scroll_widget = GATE_UI_GTK_GET_CTRL_WIDGET(&trvw->ctrl);
877 GtkWidget* widget = gtk_bin_get_child(GTK_BIN(scroll_widget));
878 GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(widget));
879 GtkTreeStore* store = GTK_TREE_STORE(model);
880 GtkTreeIter tree_iter;
881 GtkTreeIter parent_iter;
882 gate_ui_treeview_item_t new_item_id = (gate_uintptr_t)gate_atomic_int64_inc(&gate_ui_treeview_item_id);
883 char textbuffer[4096];
884 gate_ui_icon_t const* ptr_icon = NULL;
885 void* ptr_pixbuf = NULL;
886
887 do
888 {
889 GATE_STRING_TO_BUFFER(text, textbuffer);
890 if (parent != NULL)
891 {
892 if (!gate_ui_treeview_resolve(model, NULL, (void*)(gate_uintptr_t)*parent, &parent_iter))
893 {
894 ret = GATE_RESULT_NOMATCH;
895 break;
896 }
897 }
898
899 gtk_tree_store_append(store, &tree_iter, parent ? &parent_iter : NULL);
900 gtk_tree_store_set(store, &tree_iter,
901 GATE_UI_GTK_TREEVIEW_FIELD_TEXT, textbuffer,
902 GATE_UI_GTK_TREEVIEW_FIELD_ID, (void*)new_item_id,
903 GATE_UI_GTK_TREEVIEW_FIELD_PARAM, itemparam,
904 -1);
905
906 if (trvw->icons.resources[0] && (icon_key != GATE_UI_TREEVIEW_INVALID_ICON))
907 {
908 ptr_icon = gate_arraylist_get((gate_arraylist_t)trvw->icons.resources[0], (gate_size_t)icon_key);
909 if (ptr_icon)
910 {
911 ptr_pixbuf = ptr_icon->resources[0];
912 if (ptr_pixbuf)
913 {
914 gtk_tree_store_set(store, &tree_iter, GATE_UI_GTK_TREEVIEW_FIELD_ICON, ptr_pixbuf, -1);
915 }
916 }
917 }
918
919
920 if (newitem != NULL)
921 {
922 *newitem = new_item_id;
923 }
924 ret = GATE_RESULT_OK;
925
926 } while (0);
927 return ret;
928 }
929 void* gate_ui_treeview_get_itemparam(gate_ui_treeview_t* trvw, gate_ui_treeview_item_t item)
930 {
931 void* ret = NULL;
932 GtkWidget* scroll_widget = GATE_UI_GTK_GET_CTRL_WIDGET(&trvw->ctrl);
933 GtkWidget* widget = gtk_bin_get_child(GTK_BIN(scroll_widget));
934 GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(widget));
935 GtkTreeIter iter_found;
936 GValue value = GATE_INIT_EMPTY;
937
938 if (gate_ui_treeview_resolve(model, NULL, (void*)(gate_uintptr_t)item, &iter_found))
939 {
940 gtk_tree_model_get_value(model, &iter_found, 2, &value);
941 ret = g_value_get_pointer(&value);
942 g_value_unset(&value);
943
944 }
945
946 /* error / unresolved case */
947 return ret;
948 }
949
950 static void gate_ui_treeview_remove_recursive(GtkTreeModel* model, GtkTreeIter* current_iter)
951 {
952 GtkTreeIter item;
953 if (gtk_tree_model_iter_children(model, &item, current_iter))
954 {
955 do
956 {
957 gate_ui_treeview_remove_recursive(model, &item);
958 } while (gtk_tree_model_iter_next(model, &item));
959 }
960
961 item = *current_iter;
962 gtk_tree_store_remove(GTK_TREE_STORE(model), &item);
963 }
964
965 gate_result_t gate_ui_treeview_remove(gate_ui_treeview_t* trvw, gate_ui_treeview_item_t item)
966 {
967 gate_result_t ret = GATE_RESULT_FAILED;
968 GtkWidget* scroll_widget = GATE_UI_GTK_GET_CTRL_WIDGET(&trvw->ctrl);
969 GtkWidget* widget = gtk_bin_get_child(GTK_BIN(scroll_widget));
970 GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(widget));
971 GtkTreeIter iter_found;
972 if (gate_ui_treeview_resolve(model, NULL, (void*)(gate_uintptr_t)item, &iter_found))
973 {
974 gate_ui_treeview_remove_recursive(model, &iter_found);
975 ret = GATE_RESULT_OK;
976 }
977 else
978 {
979 ret = GATE_RESULT_NOMATCH;
980 }
981 return ret;
982 }
983 gate_result_t gate_ui_treeview_clear(gate_ui_treeview_t* trvw)
984 {
985 gate_result_t ret = GATE_RESULT_OK;
986 GtkWidget* scroll_widget = GATE_UI_GTK_GET_CTRL_WIDGET(&trvw->ctrl);
987 GtkWidget* widget = gtk_bin_get_child(GTK_BIN(scroll_widget));
988 GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(widget));
989 gtk_tree_store_clear(GTK_TREE_STORE(model));
990 return ret;
991 }
992 gate_result_t gate_ui_treeview_get_parent(gate_ui_treeview_t* trvw, gate_ui_treeview_item_t item, gate_ui_treeview_item_t* parent)
993 {
994 gate_result_t ret = GATE_RESULT_NOMATCH;
995 GtkWidget* scroll_widget = GATE_UI_GTK_GET_CTRL_WIDGET(&trvw->ctrl);
996 GtkWidget* widget = gtk_bin_get_child(GTK_BIN(scroll_widget));
997 GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(widget));
998 GtkTreeIter found_iter;
999 GtkTreeIter parent_iter;
1000 GValue value = GATE_INIT_EMPTY;
1001 if (gate_ui_treeview_resolve(model, NULL, (void*)(gate_uintptr_t)item, &found_iter))
1002 {
1003 if (gtk_tree_model_iter_parent(model, &parent_iter, &found_iter))
1004 {
1005 gtk_tree_model_get_value(model, &parent_iter, 1, &value);
1006 if (parent != NULL)
1007 {
1008 *parent = (gate_ui_treeview_item_t)(gate_uintptr_t)g_value_get_pointer(&value);
1009 }
1010 g_value_unset(&value);
1011 ret = GATE_RESULT_OK;
1012 }
1013 }
1014 return ret;
1015 }
1016 gate_result_t gate_ui_treeview_get_children(gate_ui_treeview_t* trvw, gate_ui_treeview_item_t item, gate_array_t* children)
1017 {
1018 gate_result_t ret = GATE_RESULT_FAILED;
1019 GtkWidget* scroll_widget = GATE_UI_GTK_GET_CTRL_WIDGET(&trvw->ctrl);
1020 GtkWidget* widget = gtk_bin_get_child(GTK_BIN(scroll_widget));
1021 GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(widget));
1022 GtkTreeIter found_iter;
1023 GtkTreeIter child_iter;
1024 GValue value = GATE_INIT_EMPTY;
1025 void* ptr_value = NULL;
1026 gate_arraylist_t arraylist = NULL;
1027 do
1028 {
1029 if (!gate_ui_treeview_resolve(model, NULL, (void*)(gate_uintptr_t)item, &found_iter))
1030 {
1031 ret = GATE_RESULT_NOMATCH;
1032 break;
1033 }
1034
1035 arraylist = gate_arraylist_create(sizeof(gate_ui_treeview_item_t), NULL, 0, NULL, NULL);
1036 if (arraylist == NULL)
1037 {
1038 ret = GATE_RESULT_OUTOFMEMORY;
1039 break;
1040 }
1041
1042 if (gtk_tree_model_iter_children(model, &child_iter, &found_iter))
1043 {
1044 do
1045 {
1046 gtk_tree_model_get_value(model, &child_iter, 1, &value);
1047 ptr_value = g_value_get_pointer(&value);
1048 gate_arraylist_add(arraylist, (void const*)&ptr_value);
1049 g_value_unset(&value);
1050 } while (gtk_tree_model_iter_next(model, &child_iter));
1051 }
1052
1053 if (NULL != gate_array_create(children, arraylist))
1054 {
1055 ret = GATE_RESULT_OK;
1056 }
1057 } while (0);
1058 if (arraylist != NULL)
1059 {
1060 gate_arraylist_release(arraylist);
1061 }
1062 return ret;
1063 }
1064 gate_result_t gate_ui_treeview_get_text(gate_ui_treeview_t* trvw, gate_ui_treeview_item_t item, gate_string_t* text)
1065 {
1066 gate_result_t ret = GATE_RESULT_NOMATCH;
1067 GtkWidget* scroll_widget = GATE_UI_GTK_GET_CTRL_WIDGET(&trvw->ctrl);
1068 GtkWidget* widget = gtk_bin_get_child(GTK_BIN(scroll_widget));
1069 GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(widget));
1070 GtkTreeIter found_iter;
1071 GValue value = GATE_INIT_EMPTY;
1072 char const* text_buffer = NULL;
1073 if (gate_ui_treeview_resolve(model, NULL, (void*)(gate_uintptr_t)item, &found_iter))
1074 {
1075 gtk_tree_model_get_value(model, &found_iter, 0, &value);
1076 text_buffer = g_value_get_string(&value);
1077 if (NULL != gate_string_create(text, text_buffer, gate_str_length(text_buffer)))
1078 {
1079 ret = GATE_RESULT_OK;
1080 }
1081 g_value_unset(&value);
1082 }
1083 return ret;
1084 }
1085 gate_result_t gate_ui_treeview_set_text(gate_ui_treeview_t* trvw, gate_ui_treeview_item_t item, gate_string_t const* text)
1086 {
1087 gate_result_t ret = GATE_RESULT_NOMATCH;
1088 GtkWidget* scroll_widget = GATE_UI_GTK_GET_CTRL_WIDGET(&trvw->ctrl);
1089 GtkWidget* widget = gtk_bin_get_child(GTK_BIN(scroll_widget));
1090 GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(widget));
1091 GtkTreeIter found_iter;
1092 GValue value = GATE_INIT_EMPTY;
1093 gchar text_buffer[4096];
1094 if (gate_ui_treeview_resolve(model, NULL, (void*)(gate_uintptr_t)item, &found_iter))
1095 {
1096 GATE_STRING_TO_BUFFER(text, text_buffer);
1097 g_value_init(&value, G_TYPE_STRING);
1098 g_value_set_string(&value, text_buffer);
1099 gtk_tree_store_set_value(GTK_TREE_STORE(model), &found_iter, 0, &value);
1100 g_value_unset(&value);
1101 ret = GATE_RESULT_OK;
1102 }
1103 return ret;
1104 }
1105 gate_bool_t gate_ui_treeview_is_expanded(gate_ui_treeview_t* trvw, gate_ui_treeview_item_t item)
1106 {
1107 gate_result_t ret = false;
1108 GtkWidget* scroll_widget = GATE_UI_GTK_GET_CTRL_WIDGET(&trvw->ctrl);
1109 GtkWidget* widget = gtk_bin_get_child(GTK_BIN(scroll_widget));
1110 GtkTreeView* treeview = GTK_TREE_VIEW(widget);
1111 GtkTreeModel* model = gtk_tree_view_get_model(treeview);
1112 GtkTreeIter found_iter;
1113 GtkTreePath* path;
1114
1115 if (gate_ui_treeview_resolve(model, NULL, (void*)(gate_uintptr_t)item, &found_iter))
1116 {
1117 path = gtk_tree_model_get_path(model, &found_iter);
1118 ret = gtk_tree_view_row_expanded(treeview, path);
1119 gtk_tree_path_free(path);
1120 }
1121 return ret;
1122 }
1123 gate_result_t gate_ui_treeview_set_expanded(gate_ui_treeview_t* trvw, gate_ui_treeview_item_t item, gate_bool_t expanded)
1124 {
1125 gate_result_t ret = GATE_RESULT_NOMATCH;
1126 GtkWidget* scroll_widget = GATE_UI_GTK_GET_CTRL_WIDGET(&trvw->ctrl);
1127 GtkWidget* widget = gtk_bin_get_child(GTK_BIN(scroll_widget));
1128 GtkTreeView* treeview = GTK_TREE_VIEW(widget);
1129 GtkTreeModel* model = gtk_tree_view_get_model(treeview);
1130 GtkTreeIter found_iter;
1131 GtkTreePath* path;
1132
1133 if (gate_ui_treeview_resolve(model, NULL, (void*)(gate_uintptr_t)item, &found_iter))
1134 {
1135 path = gtk_tree_model_get_path(model, &found_iter);
1136 if (expanded)
1137 {
1138 gtk_tree_view_expand_to_path(treeview, path);
1139 }
1140 else
1141 {
1142 gtk_tree_view_collapse_row(treeview, path);
1143 }
1144 gtk_tree_path_free(path);
1145 ret = GATE_RESULT_OK;
1146 }
1147 return ret;
1148 }
1149 gate_result_t gate_ui_treeview_get_selected_item(gate_ui_treeview_t* trvw, gate_ui_treeview_item_t* item)
1150 {
1151 gate_result_t ret = GATE_RESULT_FAILED;
1152 GtkWidget* scroll_widget = GATE_UI_GTK_GET_CTRL_WIDGET(&trvw->ctrl);
1153 GtkWidget* widget = gtk_bin_get_child(GTK_BIN(scroll_widget));
1154 GtkTreeView* treeview = GTK_TREE_VIEW(widget);
1155 GtkTreeModel* model = gtk_tree_view_get_model(treeview);
1156 GtkTreeSelection* selection = gtk_tree_view_get_selection(treeview);
1157 GtkTreeIter found_iter;
1158 GValue value = GATE_INIT_EMPTY;
1159
1160 if (gtk_tree_selection_get_selected(selection, &model, &found_iter))
1161 {
1162 gtk_tree_model_get_value(model, &found_iter, 1, &value);
1163 *item = (gate_ui_treeview_item_t)(gate_uintptr_t)g_value_get_pointer(&value);
1164 g_value_unset(&value);
1165 ret = GATE_RESULT_OK;
1166 }
1167 else
1168 {
1169 *item = GATE_UI_TREEVIEW_INVALID_ITEM;
1170 ret = GATE_RESULT_NOMATCH;
1171 }
1172 return ret;
1173 }
1174 gate_result_t gate_ui_treeview_select_item(gate_ui_treeview_t* trvw, gate_ui_treeview_item_t item)
1175 {
1176 gate_result_t ret = GATE_RESULT_FAILED;
1177 GtkWidget* scroll_widget = GATE_UI_GTK_GET_CTRL_WIDGET(&trvw->ctrl);
1178 GtkWidget* widget = gtk_bin_get_child(GTK_BIN(scroll_widget));
1179 GtkTreeView* treeview = GTK_TREE_VIEW(widget);
1180 GtkTreeModel* model = gtk_tree_view_get_model(treeview);
1181 GtkTreeSelection* selection = gtk_tree_view_get_selection(treeview);
1182 GtkTreePath* path;
1183 GtkTreeIter found_iter;
1184 if (gate_ui_treeview_resolve(model, NULL, (void*)(gate_uintptr_t)item, &found_iter))
1185 {
1186 path = gtk_tree_model_get_path(model, &found_iter);
1187 gtk_tree_selection_select_iter(selection, &found_iter);
1188 gtk_tree_path_free(path);
1189 ret = GATE_RESULT_OK;
1190 }
1191
1192 return ret;
1193 }
1194
1195 #endif /* GATE_UI_GTK */
1196
1197
1198
1199 #if defined(GATE_UI_MOTIF)
1200
1201 #include "gate/ui/gateui_motif.h"
1202 #include <Xm/List.h>
1203 #include <Xm/Tree.h>
1204 #include <Xm/Hierarchy.h>
1205 #include <Xm/Label.h>
1206 #include <Xm/PushB.h>
1207 #include <Xm/Outline.h>
1208 #include <Xm/ScrolledW.h>
1209 #include <Xm/ToggleB.h>
1210 #include <Xm/Manager.h>
1211
1212 static void motif_treeview_remove_node_widget(Widget node)
1213 {
1214 XtUnmanageChild(node);
1215 XtDestroyWidget(node);
1216 }
1217
1218 static void motif_treeview_remove_nodes_recursive(Widget node)
1219 {
1220 WidgetList wlist = NULL;
1221 gate_size_t ndx;
1222
1223 wlist = XmHierarchyGetChildNodes(node);
1224 if (wlist)
1225 {
1226 for (ndx = 0; wlist[ndx]; ++ndx)
1227 {
1228 motif_treeview_remove_nodes_recursive(wlist[ndx]);
1229 }
1230 XtFree((char*)wlist);
1231 }
1232 motif_treeview_remove_node_widget(node);
1233 }
1234
1235 static gate_result_t motif_treeview_root_elements(gate_ui_treeview_t* tv, gate_array_t* list)
1236 {
1237 WidgetList children = NULL;
1238 Widget child_widget;
1239 Cardinal num_children = 0;
1240 Widget w;
1241 Widget parent_widget;
1242 unsigned ndx;
1243 gate_arraylist_t arr;
1244
1245 GATE_DEBUG_ASSERT(tv != NULL);
1246 w = GATE_UI_MOTIF_GET_CTRL_CONTAINER(&tv->ctrl);
1247
1248 arr = gate_arraylist_create(sizeof(Widget), NULL, 0, NULL, NULL);
1249
1250 XtVaGetValues(w, XmNchildren, &children, XmNnumChildren, &num_children, NULL, NULL);
1251 for (ndx = 0; ndx != num_children; ++ndx)
1252 {
1253 child_widget = children[ndx];
1254 if (!XmIsPushButton(child_widget))
1255 {
1256 continue;
1257 }
1258 parent_widget = NULL;
1259 XtVaGetValues(child_widget, XmNparentNode, &parent_widget, NULL, NULL);
1260 if (parent_widget == NULL)
1261 {
1262 gate_arraylist_add(arr, &child_widget);
1263 }
1264 }
1265 gate_array_create(list, arr);
1266 gate_arraylist_release(arr);
1267 return GATE_RESULT_OK;
1268 }
1269
1270 static gate_result_t motif_treeview_destroy(gate_ui_ctrl_t* ctrl)
1271 {
1272 gate_ui_treeview_t* tv = (gate_ui_treeview_t*)ctrl;
1273 gate_array_t arr;
1274 unsigned ndx;
1275 gate_size_t cnt;
1276 Widget w;
1277 Widget* ptr_node;
1278
1279 GATE_DEBUG_ASSERT(tv != NULL);
1280
1281 motif_treeview_root_elements(tv, &arr);
1282 cnt = gate_array_length(&arr);
1283 for (ndx = 0; ndx < cnt; ++ndx)
1284 {
1285 ptr_node = (Widget*)gate_array_get(&arr, ndx);
1286 if (!ptr_node || !*ptr_node) continue;
1287 motif_treeview_remove_nodes_recursive(*ptr_node);
1288 }
1289 gate_array_release(&arr);
1290
1291 w = GATE_UI_MOTIF_GET_CTRL_CONTAINER(ctrl);
1292 if (w)
1293 {
1294 XtUnmanageChild(w);
1295 XtDestroyWidget(w);
1296 }
1297
1298 w = GATE_UI_MOTIF_GET_CTRL_WIDGET(ctrl);
1299 if (w)
1300 {
1301 XtUnmanageChild(w);
1302 XtDestroyWidget(w);
1303 }
1304
1305 gate_mem_clear(ctrl, sizeof(gate_ui_ctrl_t));
1306 return GATE_RESULT_OK;
1307 }
1308
1309 static gate_result_t motif_treeview_get_children(gate_ui_ctrl_t* ctrl, void** ptr_to_widgetlist, gate_size_t* ptr_to_children_count)
1310 {
1311 GATE_UNUSED_ARG(ctrl);
1312
1313 if (ptr_to_widgetlist) *ptr_to_widgetlist = NULL;
1314 if (ptr_to_children_count) *ptr_to_children_count = 0;
1315 return GATE_RESULT_OK;
1316 }
1317
1318
1319 static gate_ui_motif_dispatcher_t treeview_dispatcher =
1320 {
1321 &motif_treeview_destroy,
1322 NULL,
1323 NULL,
1324 NULL,
1325 NULL,
1326 NULL,
1327 &motif_treeview_get_children
1328 };
1329
1330 gate_result_t gate_ui_treeview_create(
1331 gate_ui_treeview_t* trvw, gate_ui_ctrl_t* parent, gate_ui_position_t const* position,
1332 gate_uint32_t flags, void* userparam)
1333 {
1334 gate_result_t ret = GATE_RESULT_FAILED;
1335 Widget parent_widget = NULL;
1336 Widget w;
1337 Widget w_tree;
1338 Widget w_scroll1 = NULL;
1339 Widget w_scroll2 = NULL;
1340 Arg args[10];
1341 Cardinal args_count;
1342
1343 do
1344 {
1345 /* XmNtreeDefaultLineStyle; */
1346
1347 if (!trvw || !parent)
1348 {
1349 ret = GATE_RESULT_INVALIDARG;
1350 break;
1351 }
1352
1353 parent_widget = GATE_UI_MOTIF_GET_CTRL_CONTAINER(parent);
1354 if (!parent_widget)
1355 {
1356 parent_widget = GATE_UI_MOTIF_GET_CTRL_WIDGET(parent);
1357 }
1358
1359 args_count = 0;
1360 XtSetArg(args[args_count], XmNscrollingPolicy, XmAUTOMATIC); ++args_count;
1361 XtSetArg(args[args_count], XmNvisualPolicy, XmVARIABLE); ++args_count;
1362 XtSetArg(args[args_count], XmNshowSash, True); ++args_count;
1363 XtSetArg(args[args_count], XmNscrollBarDisplayPolicy, XmSTATIC); ++args_count;
1364 //XtSetArg(args[args_count], XmNallowResize, True); ++args_count;
1365 XtSetArg(args[args_count], XmNshadowThickness, 1); ++args_count;
1366 XtSetArg(args[args_count], XmNhighlightThickness, 1); ++args_count;
1367
1368 w = XmCreateScrolledWindow(parent_widget, NULL, args, args_count);
1369 if (!w)
1370 {
1371 ret = GATE_RESULT_OUTOFRESOURCES;
1372 break;
1373 }
1374
1375 XtVaGetValues(w, XmNhorizontalScrollBar, &w_scroll1, XmNverticalScrollBar, &w_scroll2, NULL);
1376 if (w_scroll1)
1377 {
1378 XtVaSetValues(w_scroll1, XmNshadowThickness, 1, NULL);
1379 }
1380 if (w_scroll2)
1381 {
1382 XtVaSetValues(w_scroll2, XmNshadowThickness, 1, NULL);
1383 }
1384
1385 args_count = 0;
1386 XtSetArg(args[args_count], XmNunitType, XmPIXELS); ++args_count;
1387 XtSetArg(args[args_count], XmNconnectNodes, True); ++args_count;
1388 XtSetArg(args[args_count], XmNindentSpace, 24); ++args_count;
1389 XtSetArg(args[args_count], XmNshadowThickness, 0); ++args_count;
1390 XtSetArg(args[args_count], XmNhighlightThickness, 0); ++args_count;
1391 XtSetArg(args[args_count], XmNhorizontalMargin, 1); ++args_count;
1392 XtSetArg(args[args_count], XmNverticalMargin, 1); ++args_count;
1393
1394 w_tree = XmCreateOutline(w, NULL, args, args_count);
1395 if (!w_tree)
1396 {
1397 XtDestroyWidget(w);
1398 ret = GATE_RESULT_OUTOFRESOURCES;
1399 break;
1400 }
1401
1402 ret = gate_ui_motif_ctrl_init(&trvw->ctrl, w, userparam, NULL, parent, w_tree, position, &flags, &treeview_dispatcher);
1403 GATE_BREAK_IF_FAILED(ret);
1404
1405 XtManageChild(w);
1406 XtManageChild(w_tree);
1407 } while (0);
1408
1409 return ret;
1410 return GATE_RESULT_NOTIMPLEMENTED;
1411 }
1412
1413 gate_result_t gate_ui_treeview_add_icon(gate_ui_treeview_t* trvw, gate_ui_icon_t const* icon, gate_intptr_t* icon_key)
1414 {
1415 return GATE_RESULT_NOTIMPLEMENTED;
1416 }
1417
1418 gate_result_t gate_ui_treeview_add_icon_image(gate_ui_treeview_t* trvw, gate_rasterimage_t const* image, gate_intptr_t* icon_key)
1419 {
1420 return GATE_RESULT_NOTIMPLEMENTED;
1421 }
1422
1423 static gate_bool_t gate_ui_treeview_is_node_selected(Widget node)
1424 {
1425 Dimension dim = 0;
1426 XtVaGetValues(node, XmNshadowThickness, &dim, NULL, NULL);
1427 return dim != 0;
1428 }
1429
1430 static void gate_ui_treeview_set_node_selected(Widget node, gate_bool_t selected)
1431 {
1432 Dimension olddim = 0;
1433 Dimension newdim = selected ? 1 : 0;
1434 XtVaGetValues(node, XmNshadowThickness, &olddim, NULL, NULL);
1435 if (olddim != newdim)
1436 {
1437 XtVaSetValues(node, XmNshadowThickness, newdim, NULL, NULL);
1438 /* TODO: update UI*/
1439 }
1440 }
1441
1442 typedef gate_bool_t(*gate_ui_treeview_node_iterate_callback_t)(gate_ui_treeview_t* ptr_trvw, Widget node, void* param);
1443
1444 static gate_result_t gate_ui_treeview_node_iterate(gate_ui_treeview_t* ptr_trvw, gate_ui_treeview_node_iterate_callback_t callback, void* param)
1445 {
1446 gate_result_t ret;
1447 WidgetList root_nodes = NULL;
1448 gate_size_t root_nodes_count = 0;
1449 gate_size_t ndx;
1450 gate_bool_t continue_iterate = true;
1451
1452 ret = gate_ui_motif_ctrl_get_children(&ptr_trvw->ctrl, (void**)&root_nodes, &root_nodes_count);
1453 if (GATE_FAILED(ret))
1454 {
1455 return ret;
1456 }
1457
1458 for (ndx = 0; continue_iterate && (ndx != root_nodes_count); ++ndx)
1459 {
1460 continue_iterate = callback(ptr_trvw, root_nodes[ndx], param);
1461 }
1462 return ret;
1463 }
1464
1465 static void gate_ui_treeview_set_node_selected_recursive(Widget node, Widget node_to_select)
1466 {
1467 WidgetList sub_nodes = NULL;
1468 gate_size_t ndx = 0;
1469 gate_ui_treeview_set_node_selected(node, node == node_to_select);
1470 sub_nodes = XmHierarchyGetChildNodes(node);
1471 if (sub_nodes)
1472 {
1473 for (ndx = 0; sub_nodes[ndx]; ++ndx)
1474 {
1475 gate_ui_treeview_set_node_selected_recursive(sub_nodes[ndx], node_to_select);
1476 }
1477 XtFree((char*)sub_nodes);
1478 }
1479 }
1480
1481 static gate_bool_t gate_ui_treeview_node_iterate_select(gate_ui_treeview_t* ptr_trvw, Widget node, void* param)
1482 {
1483 Widget to_select = (Widget)param;
1484 gate_ui_treeview_set_node_selected(node, node == to_select);
1485 return true;
1486 }
1487
1488 static void gate_ui_treeview_select_node_widget_and_unselect_others(gate_ui_treeview_t* ptr_trvw, Widget node_to_select)
1489 {
1490 gate_ui_treeview_node_iterate(ptr_trvw, &gate_ui_treeview_node_iterate_select, (void*)node_to_select);
1491 }
1492
1493 static Widget gate_ui_treeview_get_selected_node_widget(gate_ui_treeview_t* ptr_trvw)
1494 {
1495 Widget ret = NULL;
1496 Widget node;
1497 WidgetList children = NULL;
1498 gate_size_t ndx;
1499 gate_size_t children_count = 0;
1500 gate_result_t result;
1501
1502 result = gate_ui_motif_ctrl_get_children(&ptr_trvw->ctrl, (void**)&children, &children_count);
1503 if (GATE_FAILED(result))
1504 {
1505 return NULL;
1506 }
1507
1508 for (ndx = 0; ndx != children_count; ++ndx)
1509 {
1510 node = children[ndx];
1511 if (node)
1512 {
1513 if (gate_ui_treeview_is_node_selected(node))
1514 {
1515 ret = node;
1516 break;
1517 }
1518 }
1519 }
1520 return ret;
1521 }
1522
1523 static void gate_ui_treeview_on_node_widget_click(Widget node_widget, XtPointer client_data, XtPointer event_data)
1524 {
1525 Widget trvw_widget;
1526 gate_ui_treeview_t* ptr_trvw = (gate_ui_treeview_t*)client_data;
1527 if (ptr_trvw)
1528 {
1529 gate_ui_treeview_select_node_widget_and_unselect_others(ptr_trvw, node_widget);
1530 if (ptr_trvw->on_select)
1531 {
1532 ptr_trvw->on_select(&ptr_trvw->ctrl, (gate_ui_treeview_item_t)node_widget);
1533 }
1534 }
1535 }
1536
1537 gate_result_t gate_ui_treeview_add(gate_ui_treeview_t* trvw, gate_ui_treeview_item_t const* parent, gate_string_t const* text,
1538 gate_intptr_t iconkey, void* itemparam, gate_ui_treeview_item_t* newitem)
1539 {
1540 Widget w_tree;
1541 Widget w_node;
1542 XmString xmstr;
1543 Arg args[10];
1544 Cardinal args_count;
1545
1546 w_tree = GATE_UI_MOTIF_GET_CTRL_CONTAINER(&trvw->ctrl);
1547
1548 xmstr = gate_ui_motif_create_string(text);
1549
1550 args_count = 0;
1551 XtSetArg(args[args_count], XmNlabelString, xmstr); ++args_count;
1552 XtSetArg(args[args_count], XmNnodeState, XmClosed); ++args_count;
1553 XtSetArg(args[args_count], XmNparentNode, parent ? (Widget)*parent : (Widget)NULL); ++args_count;
1554 //XtSetArg(args[args_count], XmNlineStyle, 99); ++args_count;
1555 XtSetArg(args[args_count], XmNshadowThickness, 0); ++args_count;
1556 //XtSetArg(args[args_count], XmNtoggleMode, XmTOGGLE_BOOLEAN); ++args_count;
1557 //XtSetArg(args[args_count], XmNset, XmUNSET); ++args_count;
1558 //XtSetArg(args[args_count], XmNalignment, XmALIGNMENT_BEGINNING); ++args_count;
1559 XtSetArg(args[args_count], XmNuserData, itemparam); ++args_count;
1560 XtSetArg(args[args_count], XmNhighlightThickness, 1); ++args_count;
1561
1562 w_node = XtCreateWidget(NULL, xmPushButtonWidgetClass, w_tree, args, args_count);
1563 //w_node = XtCreateWidget(NULL, xmLabelWidgetClass, w_tree, args, argcount);
1564 //w_node = XtCreateWidget(NULL, xmToggleButtonWidgetClass, w_tree, args, argcount);
1565 XmStringFree(xmstr);
1566
1567 XtAddCallback(w_node, XmNactivateCallback, gate_ui_treeview_on_node_widget_click, trvw);
1568
1569 *newitem = (gate_uintptr_t)w_node;
1570 XtManageChild(w_node);
1571 return GATE_RESULT_OK;
1572 }
1573
1574 void* gate_ui_treeview_get_itemparam(gate_ui_treeview_t* trvw, gate_ui_treeview_item_t item)
1575 {
1576 Widget w = (Widget)item;
1577 void* userdata = NULL;
1578
1579 XtVaGetValues(w, XmNuserData, &userdata, NULL, NULL);
1580 return userdata;
1581 }
1582
1583 gate_result_t gate_ui_treeview_remove(gate_ui_treeview_t* trvw, gate_ui_treeview_item_t item)
1584 {
1585 Widget trvw_widget = GATE_UI_MOTIF_GET_CTRL_WIDGET(&trvw->ctrl);
1586 Widget w = (Widget)item;
1587 motif_treeview_remove_nodes_recursive(w);
1588 return GATE_RESULT_OK;
1589 }
1590
1591 gate_result_t gate_ui_treeview_clear(gate_ui_treeview_t* trvw)
1592 {
1593 return GATE_RESULT_NOTIMPLEMENTED;
1594 }
1595
1596 gate_result_t gate_ui_treeview_get_parent(gate_ui_treeview_t* trvw, gate_ui_treeview_item_t item, gate_ui_treeview_item_t* parent)
1597 {
1598 Widget w = (Widget)item;
1599 Widget w_parent = NULL;
1600
1601 XtVaGetValues(w, XmNparentNode, &w_parent, NULL, NULL);
1602 if (w_parent)
1603 {
1604 *parent = (gate_ui_treeview_item_t)w_parent;
1605 }
1606 else
1607 {
1608 *parent = 0;
1609 }
1610 return GATE_RESULT_OK;
1611 }
1612
1613 gate_result_t gate_ui_treeview_get_children(gate_ui_treeview_t* trvw, gate_ui_treeview_item_t item, gate_array_t* children)
1614 {
1615 Widget w = (Widget)item;
1616 WidgetList wlist = NULL;
1617 gate_ui_treeview_item_t subitem;
1618 gate_size_t ndx;
1619 gate_arraylist_t arr = gate_arraylist_create(sizeof(gate_ui_treeview_item_t), NULL, 0, NULL, NULL);
1620
1621 if (NULL == arr)
1622 {
1623 return GATE_RESULT_OUTOFMEMORY;
1624 }
1625
1626 if (item)
1627 {
1628 wlist = XmHierarchyGetChildNodes(w);
1629 }
1630
1631 if (wlist)
1632 {
1633 for (ndx = 0; wlist[ndx]; ++ndx)
1634 {
1635 subitem = (gate_ui_treeview_item_t)wlist[ndx];
1636 gate_arraylist_add(arr, &subitem);
1637 }
1638 XtFree((char*)wlist);
1639 }
1640
1641 if (NULL == gate_array_create(children, arr))
1642 {
1643 gate_arraylist_release(arr);
1644 return GATE_RESULT_OUTOFMEMORY;
1645 }
1646 else
1647 {
1648 gate_arraylist_release(arr);
1649 return GATE_RESULT_OK;
1650 }
1651 }
1652
1653 gate_result_t gate_ui_treeview_get_text(gate_ui_treeview_t* trvw, gate_ui_treeview_item_t item, gate_string_t* text)
1654 {
1655 Widget w = (Widget)item;
1656 return gate_ui_motif_widget_get_label(w, text);
1657 }
1658
1659 gate_result_t gate_ui_treeview_set_text(gate_ui_treeview_t* trvw, gate_ui_treeview_item_t item, gate_string_t const* text)
1660 {
1661 Widget w = (Widget)item;
1662 return gate_ui_motif_widget_set_label(w, text);
1663 }
1664
1665 gate_bool_t gate_ui_treeview_is_expanded(gate_ui_treeview_t* trvw, gate_ui_treeview_item_t item)
1666 {
1667 return GATE_RESULT_NOTIMPLEMENTED;
1668 }
1669
1670 gate_result_t gate_ui_treeview_set_expanded(gate_ui_treeview_t* trvw, gate_ui_treeview_item_t item, gate_bool_t expanded)
1671 {
1672 //return GATE_RESULT_NOTIMPLEMENTED;
1673 return GATE_RESULT_OK;
1674 }
1675
1676 gate_result_t gate_ui_treeview_get_selected_item(gate_ui_treeview_t* trvw, gate_ui_treeview_item_t* item)
1677 {
1678 Widget sel_widget = gate_ui_treeview_get_selected_node_widget(trvw);
1679 if (sel_widget)
1680 {
1681 *item = (gate_ui_treeview_item_t)sel_widget;
1682 return GATE_RESULT_OK;
1683 }
1684 else
1685 {
1686 return GATE_RESULT_NOMATCH;
1687 }
1688 }
1689
1690 gate_result_t gate_ui_treeview_select_item(gate_ui_treeview_t* trvw, gate_ui_treeview_item_t item)
1691 {
1692 Widget w_to_select = (Widget)item;
1693 gate_ui_treeview_select_node_widget_and_unselect_others(trvw, w_to_select);
1694 if (trvw->on_select)
1695 {
1696 trvw->on_select(&trvw->ctrl, item);
1697 }
1698 return GATE_RESULT_OK;
1699 }
1700
1701 #endif /* GATE_UI_MOTIF */
1702