Compare commits

...

13 Commits

12 changed files with 580 additions and 112 deletions

View File

@ -1,3 +1,8 @@
https://developer.gnome.org/hig/principles.html
// https://docs.gtk.org/gio/class.MenuModel.html
// https://www.geany.org/manual/gtk/gobject/index.html
// https://developer.gnome.org/hig/patterns/controls/menus.html

10
include/actions.h Normal file
View File

@ -0,0 +1,10 @@
// https://docs.gtk.org/gio/class.MenuItem.html
// https://docs.gtk.org/gio/ctor.MenuItem.new.html
//
// https://docs.gtk.org/gio/class.SimpleAction.html
// https://docs.gtk.org/gio/ctor.SimpleAction.new.html
//
// https://forge.a-lec.org/gem-graph/gem-graph-client/src/branch/devel/include/ui.h
// https://forge.a-lec.org/gem-graph/gem-graph-client/src/branch/devel/src/ui/events.c
// https://forge.a-lec.org/gem-graph/gem-graph-client/src/branch/devel/src/ui/application.c

View File

@ -47,11 +47,19 @@ void on_SAVE_CURRENT_MODEL_BEFORE_EDITING (GtkWidget *btt_SAVE_CURRENT_MODEL, gp
void on_DISCARD_CURRENT_MODEL_AND_START_EDITING (GtkWidget *btt_SAVE_CURRENT_MODEL, gpointer data);
void on_WRITE_CURRENT_MODEL (GtkWidget *btt_WRITE_CURRENT_MODEL, gpointer data);
void on_setup_user_menu_factory (GtkSignalListItemFactory *factory,
GObject* object, gpointer user_data);
void on_bind_user_menu_factory (GtkSignalListItemFactory *factory,
GObject* object, gpointer user_data);
void on_setup_user_tree_factory (GtkSignalListItemFactory *factory,
GObject* object, gpointer user_data);
void on_bind_user_tree_factory (GtkSignalListItemFactory *factory,
GObject* object, gpointer user_data);
gboolean on_glarea_render (GtkGLArea *area, GdkGLContext *context);
void on_glarea_realize (GtkWidget *widget);
void on_glarea_unrealize (GtkWidget *widget);
@ -63,8 +71,10 @@ void on_SITUATIONS_box_RESET_VALUE (GtkAdjustment *adjustment, gpointer data);
void on_SITUATIONS_box_DO_RESET (GtkWidget *btt_reset, gpointer data);
void on_clicked_HOME (GtkWidget *btt_reset, gpointer data);
void on_clicked_MENU (GtkWidget *btt_reset, gpointer data);
//void on_clicked_MENU_list_box (GtkWidget *btt_reset, gpointer data);
//void on_clicked_MENU_pop (GtkWidget *btt_reset, gpointer data);
void on_clicked_search (GtkWidget *btt_menu, gpointer list_box);
void on_clicked_menu_experiment (GtkWidget *btt_menu, gpointer list_box);

View File

@ -35,27 +35,25 @@
/* W I N D O W S */
/******************************************************************************/
void head_set_MAIN_WINDOW (GtkApplication *app);
void head_set_DIALOG_WINDOW (GtkApplication *app);
void head_set_TEXT_WINDOW (GtkApplication *app);
void widget_head_set_MAIN_WINDOW (GtkApplication *app);
void widget_head_set_DIALOG_WINDOW (GtkApplication *app);
void widget_head_set_TEXT_WINDOW (GtkApplication *app);
void widget_MAIN_WINDOW_design (GtkWindow *main_window);
void widget_DIALOG_WINDOW_design (GtkWindow *main_window,
GtkWindow *dialog_window);
void widget_TEXT_WINDOW_design (GtkWindow *main_window,
GtkWindow *text_window);
void widget_head_MAIN_WINDOW_design (GtkWindow *main_window);
void widget_head_DIALOG_WINDOW_design (GtkWindow *main_window,
GtkWindow *dialog_window);
void widget_head_TEXT_WINDOW_design (GtkWindow *main_window,
GtkWindow *text_window);
GtkWindow *head_get_MAIN_WINDOW();
GtkWindow *head_get_DIALOG_WINDOW();
GtkWindow *head_get_TEXT_WINDOW();
GtkWindow *widget_head_get_MAIN_WINDOW();
GtkWindow *widget_head_get_DIALOG_WINDOW();
GtkWindow *widget_head_get_TEXT_WINDOW();
/******************************************************************************/
/* W I D G E T S */
/******************************************************************************/
GtkButton *get_GtkButton (char *btt_name);
GtkWidget *get_STATE_page();
GtkWidget *get_RULES_page();
GtkWidget *get_STOCK_page();
@ -63,6 +61,16 @@ GtkWidget *get_STOCK_page();
GtkWidget *get_STOCK_text (gchar *text_name);
/******************************************************************************/
/* M E N U */
/******************************************************************************/
struct MenuNode_t {gchar *text; struct MenuNode_t *child, *next;};
struct MenuNode_t *create_user_menu_node (const gchar* text);
GtkWidget *get_menu_anchor();
/******************************************************************************/
/* T R E E */
/******************************************************************************/
@ -71,7 +79,7 @@ struct TreeNode_t {gchar *text; struct TreeNode_t *child, *next;};
struct TreeNode_t *create_user_tree_node (const gchar* text);
void add_child_node (struct TreeNode_t *parent, struct TreeNode_t *child);
void let_us_create_a_complex_useless_and_expensive_tree (struct TreeNode_t *tree_root);
void labo_let_us_create_a_complex_useless_and_expensive_tree (struct TreeNode_t *tree_root);
GtkScrolledWindow *get_user_rules_tree ();
@ -103,18 +111,5 @@ gchar *get_text_address_ANY ();
/******************************************************************************/
void learning_how_to_create_a_menu (GtkMenuButton* menu_button);
void labo_create_a_simple_gtk_string_list ();

79
src/actions.c Normal file
View File

@ -0,0 +1,79 @@
//
//
//
// https://docs.gtk.org/gio/class.MenuItem.html
// https://docs.gtk.org/gio/ctor.MenuItem.new.html
//
// https://docs.gtk.org/gio/class.SimpleAction.html
// https://docs.gtk.org/gio/ctor.SimpleAction.new.html
//
// https://forge.a-lec.org/gem-graph/gem-graph-client/src/branch/devel/include/ui.h
/* static const GActionEntry app_actions [] = {
{ "quit", on_quit_action, NULL, NULL, NULL },
{ "about", on_about_action, NULL, NULL, NULL },
{ "preferences", on_preferences_action, NULL, NULL, NULL },
.... }; */
//
// https://forge.a-lec.org/gem-graph/gem-graph-client/src/branch/devel/src/ui/events.c
/* void on_about_action(GSimpleAction *action,
GVariant *parameter,
gpointer user_data)
{
static const char *authors[] = { "Adrien Bourmault (neox@a-lec.org)",
"Jean Sirmai (jean@a-lec.org)",
"Arthur Menges (arthur.menges@a-lec.org)",
NULL};
GemGraphClientApplication *self = user_data;
GtkWindow *window = NULL;
g_assert (GEM_GRAPH_CLIENT_IS_APPLICATION(self));
window = gtk_application_get_active_window(GTK_APPLICATION (self));
gtk_show_about_dialog(window,
"program-name", "Gem-graph",
"logo-icon-name", "application-x-executable",
"authors", authors,
"version", "0.1.0",
"copyright", "Copyright © 2023 Libre en Communs",
NULL);
} */
//
// https://forge.a-lec.org/gem-graph/gem-graph-client/src/branch/devel/src/ui/application.c
/* void ui_enable_action(const char *name) {
g_simple_action_set_enabled(
(GSimpleAction *)g_action_map_lookup_action(
G_ACTION_MAP(application),
name),
true);
}
void ui_disable_action(const char *name) {
g_simple_action_set_enabled(
(GSimpleAction *)g_action_map_lookup_action(
G_ACTION_MAP(application),
name),
false);
}
*
* Window actual presentation on screen
*
*
static void gem_graph_client_application_activate(GApplication *app)
{
GtkWindow *window;
g_assert(GEM_GRAPH_CLIENT_IS_APPLICATION(app));
window = gtk_application_get_active_window(GTK_APPLICATION (app));
if (window == NULL)
window = g_object_new(GEM_GRAPH_CLIENT_TYPE_WINDOW,
"application", app,
NULL);
ui_set_stack(HOME_MODE);
gtk_window_present(window);
}
*/

View File

@ -62,16 +62,16 @@ static void on_auto_notification (const char *message)
/******************************************************************************/
void on_windows_activation (GtkApplication *app,
gpointer no_user_data)
gpointer no_user_data)
{
head_set_MAIN_WINDOW (app);
widget_MAIN_WINDOW_design (head_get_MAIN_WINDOW());
widget_head_set_MAIN_WINDOW (app);
widget_head_MAIN_WINDOW_design (widget_head_get_MAIN_WINDOW());
head_set_DIALOG_WINDOW (app);
widget_DIALOG_WINDOW_design (head_get_MAIN_WINDOW(), head_get_DIALOG_WINDOW());
widget_head_set_DIALOG_WINDOW (app);
widget_head_DIALOG_WINDOW_design (widget_head_get_MAIN_WINDOW(), widget_head_get_DIALOG_WINDOW());
head_set_TEXT_WINDOW (app);
widget_TEXT_WINDOW_design (head_get_MAIN_WINDOW(), head_get_TEXT_WINDOW());
widget_head_set_TEXT_WINDOW (app);
widget_head_TEXT_WINDOW_design (widget_head_get_MAIN_WINDOW(), widget_head_get_TEXT_WINDOW());
}
@ -251,17 +251,17 @@ static void switch_STATE_RULES_DATA()
switch (get_STATE_RULES_DATA()) {
case (STATE) :
gtk_window_set_child (head_get_MAIN_WINDOW(),
gtk_window_set_child (widget_head_get_MAIN_WINDOW(),
GTK_WIDGET (get_STATE_page()));
break;
case (RULES) :
gtk_window_set_child (head_get_MAIN_WINDOW(),
gtk_window_set_child (widget_head_get_MAIN_WINDOW(),
GTK_WIDGET (get_RULES_page()));
break;
case (DATA) :
gtk_window_set_child (head_get_MAIN_WINDOW(),
gtk_window_set_child (widget_head_get_MAIN_WINDOW(),
GTK_WIDGET (get_STOCK_page()));
break;
@ -284,7 +284,7 @@ void on_toggle_EXEC_EDIT (GtkWidget *toggled_button, gpointer user_data)
"text-editor-symbolic");
// https://docs.gtk.org/gtk4/class.Window.html TODO 2024-06-30
// gtk_window_present (GTK_WINDOW (head_get_DIALOG_WINDOW())); // works once only !
// gtk_window_present (GTK_WINDOW (widget_head_get_DIALOG_WINDOW())); // works once only !
set_EXEC_EDIT (EDIT);
}
@ -348,25 +348,146 @@ void on_SITUATIONS_box_DO_RESET (GtkWidget *btt_reset, gpointer data)
/******************************************************************************/
void on_clicked_MENU (GtkWidget *btt_reset, gpointer menu_button)
{
printf ("callback.on_clicked_MENU() button\n");
// presents the text_window and works only once.\nIt should present a menu.\n"); // TODO
learning_how_to_create_a_menu (menu_button);
gtk_window_present (GTK_WINDOW (head_get_TEXT_WINDOW()));
void on_clicked_search (GtkWidget *btt_menu, gpointer list_box) {
// next line presents the text_window and works only once.\nIt should present a menu.\n"); // TODO
gtk_window_present (GTK_WINDOW (widget_head_get_TEXT_WINDOW()));
}
void on_clicked_HOME (GtkWidget *btt_reset, gpointer data)
{
printf ("callback.on_clicked_HOME() button presents the dialog_window\
( :- ) but it works only once.\n"); // TODO
gtk_window_present (GTK_WINDOW (head_get_DIALOG_WINDOW()));
gtk_window_present (GTK_WINDOW (widget_head_get_DIALOG_WINDOW()));
}
// GTK itself does not support event sounds, << A GREAT WAY TO DEBUG ! TODO
// you have to use a loadable module like the one that comes with libcanberra.
/******************************************************************************/
/* M E N U */
/******************************************************************************/
void on_clicked_menu_experiment (GtkWidget *btt_menu, gpointer list_box) {
printf ("callback.on_clicked_MENU() button > %p < &list_box > children nb > 3\n", list_box);
// gpointer list_box = gtk_popover_get_child (GTK_POPOVER (pop));
/*
if (gtk_list_box_get_row_at_index (list_box, 3))
printf ("callback.on_clicked_MENU() button > %p < &list_box > children nb > 3\n", list_box);
else printf ("callback.on_clicked_MENU() button > in list_box are the three buttons : %s, %s, %s\n\
and now : how to display these three buttons (and make use of them) ? 2024-07-13 (20h)\n",\
gtk_button_get_label (GTK_BUTTON (gtk_list_box_row_get_child (gtk_list_box_get_row_at_index (list_box, 0)))),
gtk_button_get_label (GTK_BUTTON (gtk_list_box_row_get_child (gtk_list_box_get_row_at_index (list_box, 1)))),
gtk_button_get_label (GTK_BUTTON (gtk_list_box_row_get_child (gtk_list_box_get_row_at_index (list_box, 2)))));
// learning_how_to_create_a_menu (menu_button);
// https://docs.gtk.org/gtk4/class.ListBox.html
*/
}
/******************************************************************************/
/* M E N U (from TREE) */
/******************************************************************************/
static void on_user_menu_expander_toggled (GtkExpander *expander,
gpointer user_data)
{
GtkTreeListRow *row = GTK_TREE_LIST_ROW (user_data);
gboolean is_expanded = gtk_tree_list_row_get_expanded (row);
gtk_tree_list_row_set_expanded (row, ! is_expanded);
const gchar *text = gtk_string_object_get_string (
GTK_STRING_OBJECT (gtk_tree_list_row_get_item (row)));
if (1) printf("[on_user_menu_expander_toggled] > %s\n", text);
}
void on_bind_user_menu_factory (GtkSignalListItemFactory *factory,
GObject* object,
gpointer user_data)
{
GtkListItem *list_item = GTK_LIST_ITEM (object);
assert (list_item);
GtkTreeListRow *row = gtk_list_item_get_item (list_item);
assert (row); // if (row != NULL) {...} do something ? TODO Check !
const gchar *text = gtk_string_object_get_string (
GTK_STRING_OBJECT (gtk_tree_list_row_get_item (row)));
GtkWidget *expander = gtk_list_item_get_child (list_item);
gtk_expander_set_label (GTK_EXPANDER (expander), text);
g_signal_handlers_disconnect_by_func (expander,
G_CALLBACK (on_user_menu_expander_toggled),
row);
g_signal_connect (expander,
"activate",
G_CALLBACK (on_user_menu_expander_toggled),
row);
gtk_widget_set_margin_start (expander,
gtk_tree_list_row_get_depth(row) * 20);
}
void on_setup_user_menu_factory (GtkSignalListItemFactory *factory,
GObject* object, gpointer user_data){
GtkWidget* expander = gtk_expander_new (NULL);
gtk_list_item_set_child (GTK_LIST_ITEM (object), expander);
if (0) printf("[on_setup_user_menu_factory] here is an expander\n");
}

View File

@ -205,7 +205,7 @@
* Ces fonctions peuvent être énumérées selon leur source ou leur destination.
* Il y a, en tout, à ce jour :
* - (86) fonctions appelées (dont 6 data)
* - (m) fonctions appelantes
* - (m) appels de fonction
* - (e) enum
* - (s) struct
* - (d) define
@ -261,9 +261,9 @@
*
* Les autres fonctions appelées par les fonctions callback() sont :
*
* widget_MAIN_WINDOW_design()
* widget_DIALOG_WINDOW_design()
* widget_TEXT_WINDOW_design()
* widget_head_MAIN_WINDOW_design()
* widget_head_DIALOG_WINDOW_design()
* widget_head_TEXT_WINDOW_design()
*
*
* Widgets.c appelle :

0
src/widget.c/action.c Normal file
View File

View File

@ -35,39 +35,34 @@
#define W_TEXT_WINDOW 700
#define H_TEXT_WINDOW 1000
/******************************************************************************/
/* G E T + S E T A L L W I N D O W S */
/******************************************************************************/
static GtkWindow *main_window, *dialog_window, *text_window;
static GtkButton *btt_STATE, *btt_RULES, *btt_DATA;
GtkWindow *head_get_MAIN_WINDOW() {return main_window;}
GtkWindow *head_get_DIALOG_WINDOW() {return dialog_window;}
GtkWindow *head_get_TEXT_WINDOW() {return text_window;}
GtkWindow *widget_head_get_MAIN_WINDOW() { return main_window; }
GtkWindow *widget_head_get_DIALOG_WINDOW() { return dialog_window; }
GtkWindow *widget_head_get_TEXT_WINDOW() { return text_window; }
void head_set_MAIN_WINDOW (GtkApplication *app)
{
main_window = GTK_WINDOW (gtk_application_window_new (app));
}
void widget_head_set_MAIN_WINDOW (GtkApplication *app)
{ main_window = GTK_WINDOW (gtk_application_window_new (app)); }
void head_set_DIALOG_WINDOW (GtkApplication *app)
{
dialog_window = GTK_WINDOW (gtk_application_window_new (app));
}
void widget_head_set_DIALOG_WINDOW (GtkApplication *app)
{ dialog_window = GTK_WINDOW (gtk_application_window_new (app)); }
void head_set_TEXT_WINDOW (GtkApplication *app)
{
text_window = GTK_WINDOW (gtk_application_window_new (app));
}
void widget_head_set_TEXT_WINDOW (GtkApplication *app)
{ text_window = GTK_WINDOW (gtk_application_window_new (app)); }
GtkButton *get_GtkButton (char *btt_name)
{
if (strcmp (btt_name, "state")) return btt_STATE;
if (strcmp (btt_name, "rules")) return btt_RULES;
if (strcmp (btt_name, "data analysis")) return btt_DATA;
return NULL;
}
//------------------------------------------------------------------------------
void widget_TEXT_WINDOW_design (GtkWindow *main_window, GtkWindow *text_window)
/******************************************************************************/
/* T E X T W I N D O W */
/******************************************************************************/
void widget_head_TEXT_WINDOW_design (GtkWindow *main_window, GtkWindow *text_window)
{
char *title = " Learn more about Gem Graph. ";
GtkWidget *header_bar = GTK_WIDGET (gtk_header_bar_new ());
@ -84,7 +79,13 @@ void widget_TEXT_WINDOW_design (GtkWindow *main_window, GtkWindow *text_window)
gtk_window_set_destroy_with_parent (GTK_WINDOW (text_window), TRUE);
}
void widget_DIALOG_WINDOW_design (GtkWindow *main_window, GtkWindow *dialog_window)
/******************************************************************************/
/* D I A L O G W I N D O W */
/******************************************************************************/
void widget_head_DIALOG_WINDOW_design (GtkWindow *main_window, GtkWindow *dialog_window)
{
char *title = " Save the current model before modifying it? ";
GtkWidget *header_bar = GTK_WIDGET (gtk_header_bar_new ());
@ -118,14 +119,42 @@ void widget_DIALOG_WINDOW_design (GtkWindow *main_window, GtkWindow *dialog_wind
gtk_window_set_modal (GTK_WINDOW (dialog_window), TRUE);
}
//------------------------------------------------------------------------------
static void window_header_bar (GtkWindow *window, char *title)
/******************************************************************************/
/* M A I N W I N D O W C E N T E R */
/******************************************************************************/
static GtkWidget *window_header_bar (GtkWindow *window);
static void window_header_bar_left (GtkWidget *header_bar);
static void window_header_bar_right (GtkWidget *header_bar);
void widget_head_MAIN_WINDOW_design (GtkWindow *main_window){
GtkWidget *header_bar = window_header_bar (main_window);
window_header_bar_left (header_bar);
window_header_bar_right (header_bar);
// next line <=> calls.on_toggle_STATE_RULES_DATA (btt_STATE)
gtk_check_button_set_active (GTK_CHECK_BUTTON (btt_STATE), TRUE);
gtk_window_present (GTK_WINDOW (main_window));
}
static GtkWidget *window_header_bar (GtkWindow *window)
{
char *title = "E coli (with permission from David S. Goodsell, 2009)";
GtkWidget *header_bar = GTK_WIDGET (gtk_header_bar_new ());
gtk_header_bar_set_title_widget (GTK_HEADER_BAR (header_bar), gtk_label_new (title));
gtk_window_set_titlebar (window, header_bar);
return header_bar;
}
/******************************************************************************/
/* M A I N W I N D O W L E F T */
/******************************************************************************/
static void window_header_bar_left (GtkWidget *header_bar)
{
gpointer no_local_data = NULL;
GtkButton *btt_XOR_EXEC_EDIT = GTK_BUTTON (gtk_toggle_button_new ());
@ -155,7 +184,19 @@ static void window_header_bar (GtkWindow *window, char *title)
gtk_header_bar_pack_start (GTK_HEADER_BAR (header_bar), GTK_WIDGET (btt_RULES));
gtk_header_bar_pack_start (GTK_HEADER_BAR (header_bar), GTK_WIDGET (btt_DATA));
// https://iconduck.com/sets/adwaita-icon-theme https://iconduck.com/sets/carbon-icons
}
/******************************************************************************/
/* M A I N W I N D O W R I G H T */
/******************************************************************************/
static void connect(GApplication *app, gpointer *data) { puts("Connect menu item clicked.\n"); }
static void window_header_bar_right (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");
@ -163,38 +204,109 @@ static void window_header_bar (GtkWindow *window, char *title)
gtk_header_bar_pack_end (GTK_HEADER_BAR (header_bar), GTK_WIDGET (btt_go_home));
GtkButton *search = GTK_BUTTON (gtk_button_new ());
gtk_button_set_icon_name (search, "user-trash-symbolic");
gtk_button_set_icon_name (search, "emblem-documents-symbolic");
gtk_button_set_icon_name (search, "preferences-desktop-appearance-symbolic");
gtk_button_set_icon_name (search, "applications-utilities-symbolic");
gtk_button_set_icon_name (search, "folder-saved-search-symbolic");
g_signal_connect (search, "clicked", G_CALLBACK (on_clicked_search), no_local_data);
gtk_header_bar_pack_end (GTK_HEADER_BAR (header_bar), GTK_WIDGET (search));
GtkButton *open_menu = GTK_BUTTON (gtk_button_new ()); // gtk_button_new or gtk_menu_button_new ?
gtk_button_set_icon_name (GTK_BUTTON (open_menu), "open-menu-symbolic");
// gtk_menu_button_set_label (open_menu, "open-menu-symbolic");
char *array[] = {"one", "two", "three", "four", NULL};
GtkStringList *list = gtk_string_list_new ((const char * const *) array);
if (0) printf ("heads.window_header_bar() > list [2] = %s\n",
gtk_string_list_get_string (list, 1));
// gtk_menu_button_set_child (open_menu, list);
g_signal_connect (open_menu, "clicked", G_CALLBACK (on_clicked_MENU), open_menu);
GtkWidget* list_box = gtk_list_box_new();
GtkWidget *menu_item_A;
if (0) menu_item_A = GTK_WIDGET (g_menu_item_new ("A", "activate"));
else menu_item_A = GTK_WIDGET (gtk_label_new("A")); gtk_list_box_append (GTK_LIST_BOX (list_box), menu_item_A);
GtkWidget *menu_item_B = GTK_WIDGET (gtk_label_new("B")); gtk_list_box_append (GTK_LIST_BOX (list_box), menu_item_B);
GtkWidget *menu_item_C = GTK_WIDGET (gtk_label_new("C")); gtk_list_box_append (GTK_LIST_BOX (list_box), menu_item_C);
// gtk_menu_item_activate (menu_item_C);
// 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
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 ());
// gtk_menu_button_popup (open_menu); gtk_menu_button_popdown (open_menu);
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://stackoverflow.com/questions/69135934/creating-a-simple-menubar-menu-and-menu-item-in-c-using-gtk4
GSimpleAction *act_connect = g_simple_action_new("connect", NULL);
// g_action_map_add_action(G_ACTION_MAP(app), G_ACTION(act_connect));
g_signal_connect(act_connect, "activate", G_CALLBACK(connect), NULL);
// GMenuItem *menu_item_E = g_menu_item_new("connect", "app.connect");
// gtk_list_box_append (GTK_LIST_BOX (list_box), GTK_WIDGET (menu_item_E));
g_signal_connect (open_menu, "activate", G_CALLBACK (on_clicked_menu_experiment), list_box);
// signal 'clicked' is invalid for instance '0xbcb2900' of type 'GtkMenuButton'
// signal 'clicked' is invalid for instance '0x2c992b9' of type 'GtkPopover'
// signal 'clicked' is invalid for instance '0x2812f80' of type 'GtkListBox'
// signal 'clicked' is invalid for instance '0x2a15120' of type 'GtkLabel'
//
// signal 'activate' is invalid for instance '0x3c3de7a' of type 'GtkPopover'
// signal 'activate' is invalid for instance '0x3d62f80' of type 'GtkListBox'
// signal 'activate' is invalid for instance '0x17fb93d' of type 'GtkLabel'
/*
https://docs.gtk.org/gtk4/class.ListView.html
GtkStringList *model = gtk_string_list_new (NULL); // model = create_application_list ();
GtkSignalListItemFactory *factory = GTK_SIGNAL_LIST_ITEM_FACTORY (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);
GtkStringList *list = gtk_list_view_new (GTK_SELECTION_MODEL (gtk_single_selection_new (model)), factory);
g_signal_connect (list, "activate", G_CALLBACK (activate_cb), NULL);
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), list);
*/
// ce qui suit ira dans le callback
GtkListBoxRow *selected_row = gtk_list_box_get_selected_row (GTK_LIST_BOX (list_box));
if (selected_row != NULL)
printf("selected_row = %s\n",
gtk_button_get_label (GTK_BUTTON (gtk_list_box_row_get_child (selected_row))));
// g_signal_connect (menu_item_C, "clicked", G_CALLBACK (on_clicked_HOME), no_local_data);
GtkWidget *menu_btt = gtk_menu_button_new ();
gtk_menu_button_set_child (GTK_MENU_BUTTON (menu_btt), NULL);
gtk_menu_button_set_menu_model (GTK_MENU_BUTTON (menu_btt), NULL); // GMenuModel* menu_model
gtk_header_bar_pack_end (GTK_HEADER_BAR (header_bar), GTK_WIDGET (menu_btt));
}
void widget_MAIN_WINDOW_design (GtkWindow *main_window){
window_header_bar (main_window,
"E coli (with permission from David S. Goodsell, 2009)");
gtk_check_button_set_active (GTK_CHECK_BUTTON (btt_STATE), TRUE);
gtk_window_present (GTK_WINDOW (main_window));
}
/******************************************************************************/
/* L O C A L L A B ( I C O N S ) */
/******************************************************************************/
// https://iconduck.com/sets/adwaita-icon-theme
// https://iconduck.com/sets/carbon-icons
//
// gtk_button_set_icon_name (search, "user-trash-symbolic");
// gtk_button_set_icon_name (search, "emblem-documents-symbolic");
// gtk_button_set_icon_name (search, "preferences-desktop-appearance-symbolic");
// gtk_button_set_icon_name (search, "applications-utilities-symbolic");

View File

@ -61,12 +61,8 @@ void learning_how_to_create_a_menu (GtkMenuButton* menu_button) { // Je veux qu
// GtkWidget ex = *gtk_menu_bar_new();
char *array[] = {"one", "two", "three", "four", NULL};
GtkStringList *list = gtk_string_list_new ((const char * const *) array);
printf ("labo.learning_how_to_create_a_menu () > list [3] = %s\n", gtk_string_list_get_string (list, 2));
GtkWidget* list_box = gtk_list_box_new ();
gtk_list_box_append (GTK_LIST_BOX (list_box), GTK_WIDGET (list));
gtk_list_box_append (GTK_LIST_BOX (menu_button), GTK_WIDGET (list_box));
gtk_list_box_bind_model (GTK_LIST_BOX (list_box),
NULL, // GListModel* model,
NULL, // GtkListBoxCreateWidgetFunc create_widget_func,
@ -106,7 +102,7 @@ void learning_how_to_create_a_menu (GtkMenuButton* menu_button) { // Je veux qu
void let_us_create_a_complex_useless_and_expensive_tree (struct TreeNode_t *tree_root) {
void labo_let_us_create_a_complex_useless_and_expensive_tree (struct TreeNode_t *tree_root) {
struct TreeNode_t *a = create_user_tree_node("We, the people");add_child_node(tree_root, a);
struct TreeNode_t *b = create_user_tree_node("in Order to"); add_child_node(tree_root, b);
struct TreeNode_t *c = create_user_tree_node("do establish"); add_child_node(tree_root, c);
@ -138,6 +134,14 @@ void let_us_create_a_complex_useless_and_expensive_tree (struct TreeNode_t *tree
struct TreeNode_t *cc = create_user_tree_node("access"); add_child_node(c, cc);
}
void labo_create_a_simple_gtk_string_list () {
char *array[] = {"one", "two", "three", "four", NULL};
GtkStringList *list = gtk_string_list_new ((const char * const *) array);
for (int i = 0; i < 4; i++)
printf ("in labo.a_simple_gtk_string_list() > list [%d + 1] = %s\n",\
i,
gtk_string_list_get_string (list, i));
}
/*
"rule effect"

132
src/widget.c/menu.c Normal file
View File

@ -0,0 +1,132 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Gem-graph client *
* *
* Tree *
* *
* Copyright © 2021 Libre en Communs <contact@a-lec.org> *
* Copyright © 2021 Adrien Bourmault <neox@a-lec.org> *
* Copyright © 2021 Jean Sirmai <jean@a-lec.org> *
* *
* This file is part of Gem-graph. *
* *
* This program is free software: you can redistribute it and/or modify it *
* under the terms of the GNU Affero General Public License *
* as published by the Free Software Foundation, *
* either version 3 of the License, *
* or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; *
* without even the implied warranty of MERCHANTABILITY *
* or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU Affero General Public License for more details. *
* *
* You should have received a copy of the GNU Affero General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "../../include/calls.h"
#include "../../include/widgets.h"
// GTK_ORIENTATION_VERTICAL GTK_ORIENTATION_HORIZONTAL
static void add_menu_item (struct MenuNode_t *parent, struct MenuNode_t *child){
if (parent->child) {
struct MenuNode_t *cur = parent->child;
while (cur && cur->next) {cur = cur->next;}
cur->next = child;
} else parent->child = child;
}
struct MenuNode_t *create_user_menu_node (const gchar* text){
struct MenuNode_t *node = g_malloc0 (sizeof(struct MenuNode_t));
node->text = g_strdup (text);
node->child = NULL; // if (0) printf("create_user_menu_node %s\n", text);
return node;
}
static GListModel* get_user_menu_model_child (struct MenuNode_t *parent){
GtkStringList *list = NULL;
if (parent) {
if (0) printf("[get_user_menu_model_child] here is %s content : ", parent->text);
struct MenuNode_t *child = parent->child;
if (child) {list = gtk_string_list_new(NULL);}
while(child) {
gtk_string_list_append(list, child->text);
if (0) printf("%s ", child->text);
child = child->next;
}
} // else printf("hot.c GListModel* get_user_menu_model_child (struct MenuNode_t *parent) child = %d \n", parent);
if (0) printf("\n");
return G_LIST_MODEL(list);
}
static GListModel* get_user_menu_model (GObject *item, gpointer root){
struct MenuNode_t *cur = (struct MenuNode_t *)root;
struct MenuNode_t *parent = root;
const gchar *string = gtk_string_object_get_string (GTK_STRING_OBJECT (item));
while (cur) {
if (strcmp(string, cur->text) == 0) break;
cur = cur->next;
if (cur == NULL) {cur = parent->child; parent = cur;}
}
if (0) printf("[get_user_user_menu_model] looked for %s in %s item\n", cur->text, string);
// ! WARNING ! TODO CUR EST L'ENFANT, MAINTENANT DONC, SI CUR EST UNE FEUILLE, JE N'ATTEINDRAI PAS SON ENFANT
return get_user_menu_model_child (cur);
}
GtkWidget *get_menu_anchor()
{
// https://docs.gtk.org/gio/class.MenuModel.html
// https://www.geany.org/manual/gtk/gobject/index.html
// https://developer.gnome.org/hig/patterns/controls/menus.html
if (0) labo_create_a_simple_gtk_string_list ();
struct MenuNode_t *menu_root = create_user_menu_node("menu");
struct MenuNode_t *item_a = create_user_menu_node("item_a");add_menu_item (menu_root, item_a);
struct MenuNode_t *item_b = create_user_menu_node("item_b");add_menu_item (menu_root, item_b);
struct MenuNode_t *item_c = create_user_menu_node("item_c");add_menu_item (menu_root, item_c);
// GtkWidget* list_box = gtk_list_box_new();
GtkStringList *model = gtk_string_list_new (NULL);
gtk_string_list_append (model, menu_root->text);
GtkSignalListItemFactory *factory = GTK_SIGNAL_LIST_ITEM_FACTORY (gtk_signal_list_item_factory_new());
g_signal_connect (factory, "setup", G_CALLBACK(on_setup_user_menu_factory), NULL);
g_signal_connect (factory, "bind", G_CALLBACK(on_bind_user_menu_factory), NULL);
GtkTreeListModel *menu_model = gtk_tree_list_model_new (
G_LIST_MODEL (model),
FALSE, // Passthrough - False in actual usage with dynamic children retrieval
FALSE, // TRUE, // FALSE, // autoexpand
(GtkTreeListModelCreateModelFunc) &get_user_menu_model,
menu_root,
NULL // (GDestroyNotify) free_user_menu_node
);
GtkSingleSelection *selection_model = gtk_single_selection_new (G_LIST_MODEL (menu_model));
gtk_single_selection_set_autoselect (selection_model, FALSE);
gtk_single_selection_set_can_unselect (selection_model, TRUE);
GtkWidget *list_view = gtk_list_view_new (GTK_SELECTION_MODEL (selection_model),
GTK_LIST_ITEM_FACTORY (factory));
return list_view;
}
/*
GtkScrolledWindow *scrolled_window = GTK_SCROLLED_WINDOW (gtk_scrolled_window_new());
// Allocation height too small. Tried to allocate 1922x1030, but GtkNotebook 0x25cd4c0 needs at least 1922x1064.
// even if I remove (comment) the next line :
gtk_scrolled_window_set_child (scrolled_window, list_view);
gtk_scrolled_window_set_policy (scrolled_window, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
gtk_widget_set_vexpand (GTK_WIDGET (scrolled_window), TRUE);
gtk_widget_set_visible (GTK_WIDGET (scrolled_window), TRUE);
gtk_widget_set_visible (GTK_WIDGET (list_view), TRUE);
return scrolled_window;
}
*/

View File

@ -82,7 +82,7 @@ static GListModel* get_user_tree_model (GObject *item, gpointer root){
GtkScrolledWindow *get_user_rules_tree ()
{
struct TreeNode_t *tree_root = create_user_tree_node("root");
let_us_create_a_complex_useless_and_expensive_tree (tree_root);
labo_let_us_create_a_complex_useless_and_expensive_tree (tree_root);
GtkStringList *model = gtk_string_list_new(NULL);
gtk_string_list_append (model, tree_root->text);