From 17d2306bd7b88ee4f4ecee06f110f4988e79eedf Mon Sep 17 00:00:00 2001 From: Jean Sirmai Date: Sun, 8 Sep 2024 22:09:34 +0200 Subject: [PATCH] micro-commit buttons instead of labels in the right topbar popover --- (notes, menus) | 96 +++++++++++++++++++++++++++++ include/widget.h | 5 +- src/fsm/engine/engine.c | 53 ++++++++++++++++ src/fsm/prefer.c | 4 +- src/signal.c | 7 +-- src/widget/dispatch.c | 4 +- src/widget/rules/tree_tools/labo.c | 4 +- src/widget/topbar/right.c | 99 ++++++++++++++++++++++-------- src/widget/tree.c | 3 + 9 files changed, 240 insertions(+), 35 deletions(-) create mode 100644 (notes, menus) diff --git a/(notes, menus) b/(notes, menus) new file mode 100644 index 0000000..bfcfc12 --- /dev/null +++ b/(notes, menus) @@ -0,0 +1,96 @@ +https://discourse.gnome.org/t/when-do-we-really-have-to-use-gtk-popover-present-to-show-a-popover-at-a-given-widget/17566/5 +https://stackoverflow.com/questions/69135934/creating-a-simple-menubar-menu-and-menu-item-in-c-using-gtk4 + + + + +#include + +static void action_clbk ( GSimpleAction *simple_action, G_GNUC_UNUSED GVariant *parameter, G_GNUC_UNUSED gpointer *data ) +{ + g_print ( "The action %s was clicked.\n", g_action_get_name ( G_ACTION ( simple_action ) ) ); +} + +static void activate ( GApplication *app, G_GNUC_UNUSED gpointer *data ) +{ + GtkWidget *win; + GSimpleAction *act_connect; + GSimpleAction *act_disconnect; + + /// *** + GMenu *menu_bar; + GMenu *network_menu; + GMenu *server_menu; + + /// *** + GMenuItem *menu_item_connect; + GMenuItem *menu_item_disconnect; + + /// *** Menu Bar + menu_bar = g_menu_new(); + + /// *** Network_Menu + network_menu = g_menu_new(); + g_menu_append_submenu ( menu_bar, "Network", G_MENU_MODEL ( network_menu ) ); + + /// *** Server_Menu + server_menu = g_menu_new(); + g_menu_append_submenu ( network_menu, "Server", G_MENU_MODEL ( server_menu ) ); + /// *** + win = gtk_application_window_new ( GTK_APPLICATION ( app ) ); + gtk_window_set_title ( GTK_WINDOW ( win ), "IRC Client" ); + gtk_window_set_default_size ( GTK_WINDOW ( win ), 400, 400 ); + + /// *** Create Connect and Disconnect Actions + act_connect = g_simple_action_new ( "connect", NULL ); + act_disconnect = g_simple_action_new ( "disconnect", NULL ); + + /// *** Add them to the ActionMap + g_action_map_add_action ( G_ACTION_MAP ( app ), G_ACTION ( act_connect ) ); + g_action_map_add_action ( G_ACTION_MAP ( app ), G_ACTION ( act_disconnect ) ); + + /// *** Connect them to the activate Signal + g_signal_connect ( act_connect, "activate", G_CALLBACK ( action_clbk ), NULL ); + g_signal_connect ( act_disconnect, "activate", G_CALLBACK ( action_clbk ), NULL ); + + /// *** Create the Connect Item + menu_item_connect = g_menu_item_new ( "Connect", "app.connect" ); + g_menu_append_item ( server_menu, menu_item_connect ); + + /// *** Create the Disconnect Item + menu_item_disconnect = g_menu_item_new ( "Disconnect", "app.disconnect" ); + g_menu_append_item ( server_menu, menu_item_disconnect ); + + /// *** + gtk_application_set_menubar ( GTK_APPLICATION ( app ), G_MENU_MODEL ( menu_bar ) ); + gtk_application_window_set_show_menubar ( GTK_APPLICATION_WINDOW ( win ), TRUE ); + + /// *** + gtk_window_present ( GTK_WINDOW ( win ) ); + + /// *** Clean + g_object_unref ( act_connect ); + g_object_unref ( act_disconnect ); + g_object_unref ( menu_item_connect ); + g_object_unref ( menu_item_disconnect ); + g_object_unref ( server_menu ); + g_object_unref ( network_menu ); + g_object_unref ( menu_bar ); +} + +int main ( int argc, char **argv ) +{ + GtkApplication *app; + int stat; + + /// *** + app = gtk_application_new ( "com.ircclient", G_APPLICATION_FLAGS_NONE ); + g_signal_connect ( app, "activate", G_CALLBACK ( activate ), NULL ); + + /// *** + stat = g_application_run ( G_APPLICATION ( app ), argc, argv ); + g_object_unref ( app ); + + /// *** + return stat; +} diff --git a/include/widget.h b/include/widget.h index dce0a07..9406d4f 100644 --- a/include/widget.h +++ b/include/widget.h @@ -217,12 +217,15 @@ void *widget_get_time_results_box (); /* T R E E */ /******************************************************************************/ +//struct slist {gchar *text; struct slist *child;}; struct TreeNode_t {gchar *text; struct TreeNode_t *child, *next;}; struct TreeNode_t *widget_create_user_tree_node (const gchar* text); void widget_add_child_node (struct TreeNode_t *parent, struct TreeNode_t *child); -void *widget_get_user_rules_tree (); // see "labo.c" for specification of the tree +void *widget_get_user_rules_tree (); + // def: widget/rules/tree_tools/labo.c + // call: widget/rules/tree_tools/pilot_box.c widget_get_rules_tree_tools() /******************************************************************************/ diff --git a/src/fsm/engine/engine.c b/src/fsm/engine/engine.c index bb1558a..0730473 100644 --- a/src/fsm/engine/engine.c +++ b/src/fsm/engine/engine.c @@ -45,4 +45,57 @@ /* */ /******************************************************************************/ +static void +setup_listitem_cb (GtkListItemFactory *factory, + GtkListItem *list_item) +{ + GtkWidget *image; + image = gtk_image_new (); + gtk_image_set_icon_size (GTK_IMAGE (image), GTK_ICON_SIZE_LARGE); + gtk_list_item_set_child (list_item, image); +} + +static void +bind_listitem_cb (GtkListItemFactory *factory, + GtkListItem *list_item) +{ + GtkWidget *image; + GAppInfo *app_info; + + image = gtk_list_item_get_child (list_item); + app_info = gtk_list_item_get_item (list_item); + gtk_image_set_from_gicon (GTK_IMAGE (image), g_app_info_get_icon (app_info)); +} + +static void +activate_cb (GtkListView *list, + guint position, + gpointer unused) +{ + GAppInfo *app_info; + + app_info = g_list_model_get_item (G_LIST_MODEL (gtk_list_view_get_model (list)), position); + g_app_info_launch (app_info, NULL, NULL, NULL); + g_object_unref (app_info); +} + +/* +static void +its_up_to_me_to_invent_now () +{ + GtkStringList *my_model = gtk_string_list_new (NULL); // (const char * const *strings ); + my_model = NULL; // create_application_list (); + + GtkSignalListItemFactory *factory = NULL; // gtk_signal_list_item_factory_new (); + g_signal_connect (factory, "setup", G_CALLBACK (setup_listitem_cb), NULL); + g_signal_connect (factory, "bind", G_CALLBACK (bind_listitem_cb), NULL); + + GtkWidget *list = gtk_list_view_new (GTK_SELECTION_MODEL (gtk_single_selection_new (G_LIST_MODEL (my_model))), + *factory); + + g_signal_connect (list, "activate", G_CALLBACK (activate_cb), NULL); + + gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), list); +} +*/ diff --git a/src/fsm/prefer.c b/src/fsm/prefer.c index 1dbf05d..25a87b0 100644 --- a/src/fsm/prefer.c +++ b/src/fsm/prefer.c @@ -132,7 +132,7 @@ void fsm_add_displayable (char *displayable_name) /* P R E F E R E N C E S */ /******************************************************************************/ -void fsm_preferences_init () {printf("fsm/prefer.c |\ +void fsm_preferences_init () {printf("fsm/prefer |\ src/fsm/prefer.c fsm_preferences_init()\n");} -void fsm_displayable_list_init () {printf("fsm/prefer.c |\ +void fsm_displayable_list_init () {printf("fsm/prefer |\ src/fsm/prefer.c fsm_displayable_list_init()\n");} diff --git a/src/signal.c b/src/signal.c index 2498c40..088fd61 100644 --- a/src/signal.c +++ b/src/signal.c @@ -211,7 +211,7 @@ void on_discard_current_model_before_editing (GtkWidget *btt_SAVE_CURRENT_MODEL, gpointer data) { gtk_window_close (GTK_WINDOW (data)); - printf ("signal.c - DISCARD_CURRENT_MODEL_AND_START_EDITING\n"); + printf ("signal | on_discard_current_model_before_editing > gtk_window_close\n"); } void on_write_current_model (GtkWidget *btt_WRITE_CURRENT_MODEL, @@ -318,9 +318,8 @@ void on_clicked_topbar_right_search (GtkWidget *btt_menu, gpointer list_box) { void on_clicked_topbar_right_home (GtkWidget *btt_reset, gpointer data) { - printf ("signal.on_clicked_HOME() button presents the dialog_window\ - ( :- ) but it works only once.\n"); // TODO - gtk_window_present (GTK_WINDOW (widget_get_dialog_window())); + printf ("signal | on_clicked_topbar_right_home() presents the dialog_window\n"); + gtk_window_present (GTK_WINDOW (widget_get_dialog_window())); // NB it works only once. < TODO } diff --git a/src/widget/dispatch.c b/src/widget/dispatch.c index 510847f..ac3248e 100644 --- a/src/widget/dispatch.c +++ b/src/widget/dispatch.c @@ -63,14 +63,14 @@ static void action_b (GSimpleAction *action, void on_windows_startup (GtkApplication *app) { - printf ("widget/dispatch.c |\ + printf ("widget/dispatch |\ on_windows_startup() is in: widget/dispatch.c NOT in: src/signal.c\n"); } void on_windows_activation (GtkApplication *app) { - printf ("widget/dispatch.c |\ + printf ("widget/dispatch |\ on_windows_activation() is in: widget/dispatch.c NOT in: src/signal.c\n"); // g_application_activate (G_APPLICATION (app)); < how ? > in main.c is // g_signal_connect (app, "activate", G_CALLBACK (on_windows_activation), NULL); diff --git a/src/widget/rules/tree_tools/labo.c b/src/widget/rules/tree_tools/labo.c index ad39210..5913f40 100644 --- a/src/widget/rules/tree_tools/labo.c +++ b/src/widget/rules/tree_tools/labo.c @@ -96,8 +96,8 @@ void widget_let_us_create_a_complex_useless_and_expensive_tree (struct TreeNode_ struct TreeNode_t *aaaco = widget_create_user_tree_node("copy"); widget_add_child_node(aaaa, aaaco); - struct TreeNode_t *aaae = widget_create_user_tree_node("edit"); widget_add_child_node(aaab, aaae); - struct TreeNode_t *aaaf = widget_create_user_tree_node("publish"); widget_add_child_node(aaab, aaaf); + struct TreeNode_t *aaae = widget_create_user_tree_node("edit"); widget_add_child_node(aaab, aaae); + struct TreeNode_t *aaaf = widget_create_user_tree_node("publish"); widget_add_child_node(aaab, aaaf); // struct TreeNode_t *aaada = widget_create_user_tree_node("manifest"); widget_add_child_node(aaad, aaada); struct TreeNode_t *aaba = widget_create_user_tree_node("learn"); widget_add_child_node(aab, aaba); diff --git a/src/widget/topbar/right.c b/src/widget/topbar/right.c index c6a87ff..514cd59 100644 --- a/src/widget/topbar/right.c +++ b/src/widget/topbar/right.c @@ -36,16 +36,20 @@ /******************************************************************************/ /* M A I N W I N D O W T O P B A R ( R I G H T ) */ /******************************************************************************/ -static void action_a (GSimpleAction *action, GVariant *parameter, gpointer app) {puts("menu item A clicked.\n");} -static void connect(GApplication *app, gpointer *data) { puts("Connect menu item clicked.\n"); } +static GtkWidget *list_box = NULL; +static GtkWidget *btt_A = NULL; +static GtkWidget *btt_B = NULL; +static GtkWidget *btt_C = NULL; +static GtkWidget *pop = NULL; +static GtkMenuButton *open_menu = NULL; -void window_design_topbar_right (GtkWidget *header_bar, GtkApplication *app) +static void display_widgets_at_the_right_side (GtkWidget *header_bar) { gpointer no_local_data = NULL; GtkButton *btt_go_home = GTK_BUTTON (gtk_button_new ()); gtk_button_set_icon_name (btt_go_home, "go-home-symbolic"); -// gtk_widget_error_bell (GTK_WIDGET (btt_go_home)); << TODO si c'est possible ? + gtk_widget_error_bell (GTK_WIDGET (btt_go_home)); // << TODO est-ce possible ? g_signal_connect (btt_go_home, "clicked", G_CALLBACK (on_clicked_topbar_right_home), no_local_data); gtk_header_bar_pack_end (GTK_HEADER_BAR (header_bar), GTK_WIDGET (btt_go_home)); @@ -59,34 +63,81 @@ void window_design_topbar_right (GtkWidget *header_bar, GtkApplication *app) g_signal_connect (measure, "clicked", G_CALLBACK (on_clicked_topbar_right_measure), no_local_data); gtk_header_bar_pack_end (GTK_HEADER_BAR (header_bar), GTK_WIDGET (measure)); + list_box = gtk_list_box_new(); + btt_A = GTK_WIDGET (gtk_button_new_with_label("A")); gtk_list_box_append (GTK_LIST_BOX (list_box), btt_A); + btt_B = GTK_WIDGET (gtk_button_new_with_label("B")); gtk_list_box_append (GTK_LIST_BOX (list_box), btt_B); + btt_C = GTK_WIDGET (gtk_button_new_with_label("C")); gtk_list_box_append (GTK_LIST_BOX (list_box), btt_C); + pop = gtk_popover_new (); - - - - - - - - // https://discourse.gnome.org/t/when-do-we-really-have-to-use-gtk-popover-present-to-show-a-popover-at-a-given-widget/17566/5 - // https://stackoverflow.com/questions/69135934/creating-a-simple-menubar-menu-and-menu-item-in-c-using-gtk4 - - - GtkWidget* list_box = gtk_list_box_new(); - GtkWidget *label_A = GTK_WIDGET (gtk_label_new("A")); gtk_list_box_append (GTK_LIST_BOX (list_box), label_A); - GtkWidget *label_B = GTK_WIDGET (gtk_label_new("B")); gtk_list_box_append (GTK_LIST_BOX (list_box), label_B); - GtkWidget *label_C = GTK_WIDGET (gtk_label_new("C")); gtk_list_box_append (GTK_LIST_BOX (list_box), label_C); - - GtkWidget *pop = gtk_popover_new (); gtk_popover_set_child (GTK_POPOVER (pop), list_box); gtk_popover_present (GTK_POPOVER (pop)); gtk_popover_set_autohide (GTK_POPOVER (pop), FALSE); gtk_popover_set_cascade_popdown (GTK_POPOVER (pop), TRUE); - GtkMenuButton *open_menu = GTK_MENU_BUTTON (gtk_menu_button_new ()); + open_menu = GTK_MENU_BUTTON (gtk_menu_button_new ()); gtk_menu_button_set_icon_name (open_menu, "open-menu-symbolic"); gtk_menu_button_set_always_show_arrow (open_menu, TRUE); gtk_menu_button_set_popover (open_menu, GTK_WIDGET (pop)); gtk_header_bar_pack_end (GTK_HEADER_BAR (header_bar), GTK_WIDGET (open_menu)); +} + +// https://discourse.gnome.org/t/when-do-we-really-have-to-use-gtk-popover-present-to-show-a-popover-at-a-given-widget/17566/5 +// https://stackoverflow.com/questions/69135934/creating-a-simple-menubar-menu-and-menu-item-in-c-using-gtk4 + + + + + + + + + + +static void callback_aa () {puts("callback_aa() > menu item A clicked.\n");} +static void action_a (GSimpleAction *action, GVariant *parameter, gpointer app) {puts("menu item A clicked.\n");} +static void connect(GApplication *app, gpointer *data) { puts("Connect menu item clicked.\n"); } + +void window_design_topbar_right (GtkWidget *header_bar, GtkApplication *app) +{ + display_widgets_at_the_right_side (header_bar); + + GSimpleActionGroup *ga = g_simple_action_group_new (); + GtkShortcutAction *aa = gtk_named_action_new ("aa"); + gtk_widget_insert_action_group (btt_A, "aa", G_ACTION_GROUP (ga)); // GActionGroup* group +// GtkShortcutAction *act_aa = gtk_callback_action_new (callback_aa, NULL, NULL); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + GSimpleAction *act_connect = g_simple_action_new("connect", NULL); @@ -99,7 +150,7 @@ void window_design_topbar_right (GtkWidget *header_bar, GtkApplication *app) // GMenuItem *menu_item_do_a = g_menu_item_new ("do_a", "app.do_a"); // gtk_menu_button_popup (open_menu); gtk_menu_button_popdown (open_menu); - // gtk_menu_item_activate (label_C); + // gtk_menu_item_activate (btt_C); // g_action_map_add_action(G_ACTION_MAP(app), G_ACTION(act_connect)); // GMenuItem *label_E = g_menu_item_new("connect", "app.do_a"); // gtk_list_box_append (GTK_LIST_BOX (list_box), GTK_WIDGET (menu_item_do_a)); @@ -142,7 +193,7 @@ void window_design_topbar_right (GtkWidget *header_bar, GtkApplication *app) printf("selected_row = %s\n", gtk_button_get_label (GTK_BUTTON (gtk_list_box_row_get_child (selected_row)))); - // g_signal_connect (label_C, "clicked", G_CALLBACK (on_clicked_HOME), no_local_data); + // g_signal_connect (btt_C, "clicked", G_CALLBACK (on_clicked_HOME), no_local_data); } diff --git a/src/widget/tree.c b/src/widget/tree.c index f699cc9..a723025 100644 --- a/src/widget/tree.c +++ b/src/widget/tree.c @@ -83,6 +83,9 @@ static GListModel *get_user_tree_model (GObject *item, gpointer root) return get_user_tree_model_child (cur); } + +#define LIST_VS_TREE 0 // 0 list 1 tree + void *widget_get_user_rules_tree () { struct TreeNode_t *tree_root = widget_create_user_tree_node("We, the people,");