# HG changeset patch # User bsmith@81767d24-ef19-dc11-ae90-00e081727c95 # Date 1613457577 0 # Node ID a2020f907a6cf6054bd07823da29c383b9d27397 # Parent 1f85311baa65f3da1e446c58b918c60d76b91931 GTK4: Implement checkable menu items. diff -r 1f85311baa65 -r a2020f907a6c gtk4/dw.c --- a/gtk4/dw.c Tue Feb 16 05:22:28 2021 +0000 +++ b/gtk4/dw.c Tue Feb 16 06:39:37 2021 +0000 @@ -384,7 +384,6 @@ pthread_key_t _dw_bg_color_key; pthread_key_t _dw_event_key; -static int _dw_ignore_expand = 0; static pthread_t _dw_thread = (pthread_t)-1; #define _DW_TREE_TYPE_CONTAINER 1 @@ -1055,7 +1054,7 @@ SignalHandler work = _dw_get_signal_handler(data); int retval = FALSE; - if(!_dw_ignore_expand && work.window) + if(work.window) { int (*treeexpandfunc)(HWND, HTREEITEM, void *) = work.func; retval = treeexpandfunc(work.window, (HTREEITEM)iter, work.data); @@ -1301,6 +1300,15 @@ static void _dw_menu_handler(GSimpleAction *action, GVariant *param, gpointer data) { SignalHandler work = _dw_get_signal_handler(data); + GVariant *action_state = g_action_get_state(G_ACTION(action)); + + /* Handle toggling checkable menu items automatically, before the callback */ + if(action_state) + { + gboolean active = g_variant_get_boolean(action_state); + GVariant *new_state = g_variant_new_boolean(!active); + g_simple_action_set_state(action, new_state); + } if(work.window) { @@ -2737,7 +2745,10 @@ snprintf(tempbuf, 100, "menu%d.action%lu", menugroup, id); actionname = strchr(tempbuf, '.'); - action = g_simple_action_new(&actionname[1], NULL); + if(check) + action = g_simple_action_new_stateful(&actionname[1], NULL, g_variant_new_boolean (FALSE)); + else + action = g_simple_action_new(&actionname[1], NULL); g_action_map_add_action(G_ACTION_MAP(group), G_ACTION(action)); tmphandle=(HWND)g_menu_item_new(temptitle, tempbuf); snprintf(numbuf, 24, "%lu", id); @@ -2792,26 +2803,37 @@ * check: TRUE for checked FALSE for not checked. * deprecated: use dw_menu_item_set_state() */ -void dw_menu_item_set_check(HMENUI menu, unsigned long id, int check) -{ -#if 0 - char numbuf[25] = {0}; - GMenuItem *tmphandle; - - if(!menu) - return; - - snprintf(numbuf, 24, "%lu", id); - tmphandle = _dw_find_submenu_id(menu, numbuf); - - if(tmphandle && G_IS_MENU_ITEM(tmphandle)) - { - GSimpleAction *action = g_object_get_data(G_OBJECT(tmphandle), "_dw_action"); - - if(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(tmphandle)) != check) - gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(tmphandle), check); - } -#endif +DW_FUNCTION_DEFINITION(dw_menu_item_set_check, void, HMENUI menu, ULONG cid, int check) +DW_FUNCTION_ADD_PARAM3(menu, cid, check) +DW_FUNCTION_NO_RETURN(dw_menu_item_set_check) +DW_FUNCTION_RESTORE_PARAM3(menu, HMENUI, cid, ULONG, check, int) +{ + if(menu) + { + char numbuf[25] = {0}; + GMenuItem *tmphandle; + + snprintf(numbuf, 24, "%lu", cid); + tmphandle = _dw_find_submenu_id(menu, numbuf); + + if(tmphandle && G_IS_MENU_ITEM(tmphandle)) + { + GSimpleAction *action = g_object_get_data(G_OBJECT(tmphandle), "_dw_action"); + + if(action) + { + GVariant *action_state = g_action_get_state(G_ACTION(action)); + gboolean thischeck = check; + + if(!action_state || (g_variant_get_boolean(action_state) != thischeck)) + { + GVariant *new_state = g_variant_new_boolean(thischeck); + g_simple_action_set_state(action, new_state); + } + } + } + } + DW_FUNCTION_RETURN_NOTHING; } /* @@ -2826,11 +2848,11 @@ DW_FUNCTION_NO_RETURN(dw_menu_item_set_state) DW_FUNCTION_RESTORE_PARAM3(menu, HMENUI, cid, ULONG, state, ULONG) { - char numbuf[25] = {0}; - GMenuItem *tmphandle; - if(menu) { + char numbuf[25] = {0}; + GMenuItem *tmphandle; + snprintf(numbuf, 24, "%lu", cid); tmphandle = _dw_find_submenu_id(menu, numbuf); @@ -2838,24 +2860,29 @@ { GSimpleAction *action = g_object_get_data(G_OBJECT(tmphandle), "_dw_action"); - #if 0 - if((state & DW_MIS_CHECKED) || (state & DW_MIS_UNCHECKED)) + if(action) { - int check = 0; - - if(state & DW_MIS_CHECKED) - check = 1; - - if(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(tmphandle)) != check) - gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(tmphandle), check); - } - #endif - if((state & DW_MIS_ENABLED) || (state & DW_MIS_DISABLED)) - { - if(state & DW_MIS_ENABLED) - g_simple_action_set_enabled(action, TRUE); - else - g_simple_action_set_enabled(action, FALSE); + if((state & DW_MIS_CHECKED) || (state & DW_MIS_UNCHECKED)) + { + GVariant *action_state = g_action_get_state(G_ACTION(action)); + gboolean check = false; + + if(state & DW_MIS_CHECKED) + check = true; + + if(!action_state || (g_variant_get_boolean(action_state) != check)) + { + GVariant *new_state = g_variant_new_boolean(check); + g_simple_action_set_state(action, new_state); + } + } + if((state & DW_MIS_ENABLED) || (state & DW_MIS_DISABLED)) + { + if(state & DW_MIS_ENABLED) + g_simple_action_set_enabled(action, TRUE); + else + g_simple_action_set_enabled(action, FALSE); + } } } } @@ -8553,33 +8580,38 @@ if(style & DW_DT_WORDBREAK) gtk_label_set_wrap(GTK_LABEL(handle), TRUE); } - if(G_IS_MENU_ITEM(handle2) && (mask & (DW_MIS_ENABLED | DW_MIS_DISABLED))) + if(G_IS_MENU_ITEM(handle2)) { GSimpleAction *action = g_object_get_data(G_OBJECT(handle2), "_dw_action"); - if((style & DW_MIS_ENABLED) || (style & DW_MIS_DISABLED)) - { - if(style & DW_MIS_ENABLED) - g_simple_action_set_enabled(action, TRUE); - else - g_simple_action_set_enabled(action, FALSE); - } - } - /* TODO: Convert to GMenuModel */ -#if GTK3 - if(GTK_IS_CHECK_MENU_ITEM(handle2) && (mask & (DW_MIS_CHECKED | DW_MIS_UNCHECKED)) - { - int check = 0; - - if ( style & DW_MIS_CHECKED ) - check = 1; - - _dw_ignore_click = 1; - if(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(handle2)) != check) - gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(handle2), check); - _dw_ignore_click = 0; - } -#endif + if(action) + { + if(mask & (DW_MIS_ENABLED | DW_MIS_DISABLED)) + { + if((style & DW_MIS_ENABLED) || (style & DW_MIS_DISABLED)) + { + if(style & DW_MIS_ENABLED) + g_simple_action_set_enabled(action, TRUE); + else + g_simple_action_set_enabled(action, FALSE); + } + } + if(mask & (DW_MIS_CHECKED | DW_MIS_UNCHECKED)) + { + GVariant *action_state = g_action_get_state(G_ACTION(action)); + gboolean check = false; + + if(style & DW_MIS_CHECKED) + check = true; + + if(!action_state || (g_variant_get_boolean(action_state) != check)) + { + GVariant *new_state = g_variant_new_boolean(check); + g_simple_action_set_state(action, new_state); + } + } + } + } DW_FUNCTION_RETURN_NOTHING; }