From 4d65a51e09a2929eb4eacec0c6d1ef6f91212aef Mon Sep 17 00:00:00 2001 From: Adrien Bourmault Date: Wed, 25 Jan 2023 18:48:01 +0100 Subject: [PATCH] Obtained open/close with changing mode --- include/ui.h | 45 ++++++++++--- src/ui/actions.c | 153 +++++++++++++++++++++++++++++++++---------- src/ui/application.c | 108 ++++++++++++++++++++++-------- src/ui/gemgraph.ui | 18 ++--- src/ui/window.c | 39 +++++++++++ 5 files changed, 283 insertions(+), 80 deletions(-) diff --git a/include/ui.h b/include/ui.h index 28fe558..6d3c8ea 100644 --- a/include/ui.h +++ b/include/ui.h @@ -103,14 +103,39 @@ void on_savefile_action(GSimpleAction *action, static const GActionEntry app_actions[] = { - { "quit", on_quit_action }, - { "about", on_about_action }, - { "preferences", on_preferences_action }, - { "togglesidebar", on_togglesidebar_action }, - { "editmode", on_editmode_action }, - { "runmode", on_runmode_action }, - { "presentmode", on_presentmode_action }, - { "openfile", on_openfile_action }, - { "closefile", on_closefile_action }, - { "savefile", on_savefile_action }, + { "quit", on_quit_action, NULL, NULL, NULL }, + { "about", on_about_action, NULL, NULL, NULL }, + { "preferences", on_preferences_action, NULL, NULL, NULL }, + { "togglesidebar", on_togglesidebar_action, NULL, NULL, NULL }, + { "editmode", on_editmode_action, NULL, NULL, NULL }, + { "runmode", on_runmode_action, NULL, NULL, NULL }, + { "presentmode", on_presentmode_action, NULL, NULL, NULL }, + { "openfile", on_openfile_action, NULL, NULL, NULL }, + { "closefile", on_closefile_action, NULL, NULL, NULL }, + { "savefile", on_savefile_action, NULL, NULL, NULL }, }; + +void uiApplicationEnableAction(const char *name); + +void uiApplicationDisableAction(const char *name); + +// +// Actions responses +// +void on_openfile_response(GtkNativeDialog *native, + int response, + GemGraphClientWindow *self); + +void on_openfile_response_complete(GObject *source_object, + GAsyncResult *result, + GemGraphClientWindow *self); + +/* -------------------------------------------------------------------------- */ + +// +// Window primitives +// + +void uiWindowStackChange(const char *mode); + +void uiWindowSendNotification(const char *message); diff --git a/src/ui/actions.c b/src/ui/actions.c index cc6a920..3d11181 100644 --- a/src/ui/actions.c +++ b/src/ui/actions.c @@ -22,6 +22,8 @@ * along with this program. If not, see . */ +#include + #include "../../include/base.h" #include "../../include/ui.h" @@ -29,17 +31,17 @@ void on_about_action(GSimpleAction *action, GVariant *parameter, gpointer user_data) { - static const char *authors[] = { "Adrien Bourmault ", + static const char *authors[] = { "Adrien Bourmault ", "Jean Sirmai ", NULL}; - GemGraphClientApplication *self = user_data; - GtkWindow *window = NULL; + GemGraphClientApplication *self = user_data; + GtkWindow *window = NULL; - g_assert (GEM_GRAPH_CLIENT_IS_APPLICATION(self)); + g_assert (GEM_GRAPH_CLIENT_IS_APPLICATION(self)); - window = gtk_application_get_active_window(GTK_APPLICATION (self)); + window = gtk_application_get_active_window(GTK_APPLICATION (self)); - gtk_show_about_dialog(window, + gtk_show_about_dialog(window, "program-name", "Gem-graph", "logo-icon-name", "application-x-executable", "authors", authors, @@ -52,98 +54,183 @@ void on_quit_action(GSimpleAction *action, GVariant *parameter, gpointer user_data) { - GemGraphClientApplication *self = user_data; + GemGraphClientApplication *self = user_data; - g_assert(GEM_GRAPH_CLIENT_IS_APPLICATION(self)); + g_assert(GEM_GRAPH_CLIENT_IS_APPLICATION(self)); - g_application_quit(G_APPLICATION(self)); + g_application_quit(G_APPLICATION(self)); } void on_preferences_action(GSimpleAction *action, GVariant *parameter, gpointer user_data) { - GemGraphClientApplication *self = user_data; + GemGraphClientApplication *self = user_data; - g_assert(GEM_GRAPH_CLIENT_IS_APPLICATION(self)); + g_assert(GEM_GRAPH_CLIENT_IS_APPLICATION(self)); - g_application_quit(G_APPLICATION(self)); + uiWindowSendNotification("Not implemented !"); } void on_togglesidebar_action(GSimpleAction *action, GVariant *parameter, gpointer user_data) { - GemGraphClientApplication *self = user_data; + GemGraphClientApplication *self = user_data; - g_assert(GEM_GRAPH_CLIENT_IS_APPLICATION(self)); + g_assert(GEM_GRAPH_CLIENT_IS_APPLICATION(self)); - g_application_quit(G_APPLICATION(self)); + uiWindowSendNotification("Not implemented !"); } void on_editmode_action(GSimpleAction *action, GVariant *parameter, gpointer user_data) { - GemGraphClientApplication *self = user_data; + GemGraphClientApplication *self = user_data; - g_assert(GEM_GRAPH_CLIENT_IS_APPLICATION(self)); + g_assert(GEM_GRAPH_CLIENT_IS_APPLICATION(self)); - g_application_quit(G_APPLICATION(self)); + g_application_quit(G_APPLICATION(self)); } void on_runmode_action(GSimpleAction *action, GVariant *parameter, gpointer user_data) { - GemGraphClientApplication *self = user_data; + GemGraphClientApplication *self = user_data; - g_assert(GEM_GRAPH_CLIENT_IS_APPLICATION(self)); + g_assert(GEM_GRAPH_CLIENT_IS_APPLICATION(self)); - g_application_quit(G_APPLICATION(self)); + g_application_quit(G_APPLICATION(self)); } void on_presentmode_action(GSimpleAction *action, GVariant *parameter, gpointer user_data) { - GemGraphClientApplication *self = user_data; + GemGraphClientApplication *self = user_data; - g_assert(GEM_GRAPH_CLIENT_IS_APPLICATION(self)); + g_assert(GEM_GRAPH_CLIENT_IS_APPLICATION(self)); - g_application_quit(G_APPLICATION(self)); + g_application_quit(G_APPLICATION(self)); } void on_openfile_action(GSimpleAction *action, GVariant *parameter, gpointer user_data) { - GemGraphClientApplication *self = user_data; + GemGraphClientApplication *self = user_data; - g_assert(GEM_GRAPH_CLIENT_IS_APPLICATION(self)); + g_assert(GEM_GRAPH_CLIENT_IS_APPLICATION(self)); - g_application_quit(G_APPLICATION(self)); + // Create a new file selection dialog, using the "open" mode + GtkFileChooserNative *native = + gtk_file_chooser_native_new("Open File", + GTK_WINDOW(self), + GTK_FILE_CHOOSER_ACTION_OPEN, + "_Open", + "_Cancel"); + + // Connect the "response" signal of the file selection dialog; + // this signal is emitted when the user selects a file, or when + // they cancel the operation + g_signal_connect (native, + "response", + G_CALLBACK(on_openfile_response), + self); + + // Present the dialog to the user + gtk_native_dialog_show (GTK_NATIVE_DIALOG (native)); } void on_closefile_action(GSimpleAction *action, GVariant *parameter, gpointer user_data) { - GemGraphClientApplication *self = user_data; + GemGraphClientApplication *self = user_data; - g_assert(GEM_GRAPH_CLIENT_IS_APPLICATION(self)); + g_assert(GEM_GRAPH_CLIENT_IS_APPLICATION(self)); - g_application_quit(G_APPLICATION(self)); + uiApplicationDisableAction("closefile"); + uiApplicationDisableAction("savefile"); + uiApplicationDisableAction("runmode"); + uiApplicationDisableAction("editmode"); + uiApplicationDisableAction("presentmode"); + uiWindowStackChange("home"); } void on_savefile_action(GSimpleAction *action, GVariant *parameter, gpointer user_data) { - GemGraphClientApplication *self = user_data; + GemGraphClientApplication *self = user_data; - g_assert(GEM_GRAPH_CLIENT_IS_APPLICATION(self)); + g_assert(GEM_GRAPH_CLIENT_IS_APPLICATION(self)); - g_application_quit(G_APPLICATION(self)); } +/* -------------------------------------------------------------------------- */ + +/* + * Responses + */ +void on_openfile_response(GtkNativeDialog *native, + int response, + GemGraphClientWindow *self) +{ + g_autoptr (GFile) file; + GtkFileChooser *chooser; + + if (response == GTK_RESPONSE_ACCEPT) { + chooser = GTK_FILE_CHOOSER(native); + file = gtk_file_chooser_get_file(chooser); + + // Load asynchroneously not to block control flow + g_file_load_contents_async (file, + NULL, + (GAsyncReadyCallback)on_openfile_response_complete, + self); + } + + g_object_unref (native); +} + +void on_openfile_response_complete(GObject *source_object, + GAsyncResult *result, + GemGraphClientWindow *self) +{ + GFile *file = G_FILE(source_object); + + char *contents = NULL; + gsize length = 0; + + g_autoptr(GError) error = NULL; + + // Gives you the contents of the file as a byte array, or + // set the error argument + g_file_load_contents_finish(file, + result, + &contents, + &length, + NULL, + &error); + + // In case of error, print a warning to the standard error output + if (error != NULL) + { + g_printerr("Unable to open ā€œ%sā€: %s\n", + g_file_peek_path(file), + error->message); + return; + } + + g_print("File content is :\n%s\n", contents); + + uiApplicationEnableAction("closefile"); + uiApplicationEnableAction("savefile"); + uiApplicationEnableAction("runmode"); + uiApplicationEnableAction("editmode"); + uiApplicationEnableAction("presentmode"); + uiWindowStackChange("edit"); +} diff --git a/src/ui/application.c b/src/ui/application.c index 47d3f78..b4d9261 100644 --- a/src/ui/application.c +++ b/src/ui/application.c @@ -27,49 +27,59 @@ struct _GemGraphClientApplication { - GtkApplication parent_instance; + GtkApplication parent_instance; }; G_DEFINE_TYPE (GemGraphClientApplication, gem_graph_client_application, GTK_TYPE_APPLICATION) -GemGraphClientApplication *gem_graph_client_application_new( - const char *application_id, - GApplicationFlags flags) -{ - g_return_val_if_fail(application_id != NULL, NULL); - return g_object_new(GEM_GRAPH_CLIENT_TYPE_APPLICATION, - "application-id", application_id, - "flags", flags, - NULL); +static GemGraphClientApplication *application; + +/* -------------------------------------------------------------------------- */ + +void uiApplicationEnableAction(const char *name) { + g_simple_action_set_enabled( + (GSimpleAction *)g_action_map_lookup_action( + G_ACTION_MAP(application), + name), + true); } +void uiApplicationDisableAction(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; + GtkWindow *window; - g_assert (GEM_GRAPH_CLIENT_IS_APPLICATION (app)); + g_assert(GEM_GRAPH_CLIENT_IS_APPLICATION(app)); - window = gtk_application_get_active_window(GTK_APPLICATION (app)); - if (window == NULL) + window = gtk_application_get_active_window(GTK_APPLICATION (app)); + if (window == NULL) window = g_object_new(GEM_GRAPH_CLIENT_TYPE_WINDOW, "application", app, NULL); - gtk_window_present (window); + uiWindowStackChange("home"); + + gtk_window_present(window); } -static void gem_graph_client_application_class_init( - GemGraphClientApplicationClass *klass) -{ - GApplicationClass *app_class = G_APPLICATION_CLASS(klass); - - app_class->activate = gem_graph_client_application_activate; -} - - +/* + * Action records are registered here + * + */ static void gem_graph_client_application_init(GemGraphClientApplication *self) { g_action_map_add_action_entries(G_ACTION_MAP(self), @@ -77,11 +87,53 @@ static void gem_graph_client_application_init(GemGraphClientApplication *self) G_N_ELEMENTS(app_actions), self); - gtk_application_set_accels_for_action(GTK_APPLICATION (self), - "app.quit", - (const char *[]) { "q", NULL }); + // Setup shortcuts + gtk_application_set_accels_for_action(GTK_APPLICATION(self), + "app.quit", + (const char *[]) { "q", NULL }); + gtk_application_set_accels_for_action(GTK_APPLICATION(self), + "app.editmode", + (const char *[]) { "e", NULL }); + gtk_application_set_accels_for_action(GTK_APPLICATION(self), + "app.runmode", + (const char *[]) { "r", NULL }); + gtk_application_set_accels_for_action(GTK_APPLICATION(self), + "app.presentmode", + (const char *[]) { "p", NULL }); + gtk_application_set_accels_for_action(GTK_APPLICATION(self), + "app.savefile", + (const char *[]) { "s", NULL }); + application = self; + + // + // Disable unneeded/inoperant actions + // + uiApplicationDisableAction("savefile"); + uiApplicationDisableAction("closefile"); + uiApplicationDisableAction("editmode"); + uiApplicationDisableAction("runmode"); + uiApplicationDisableAction("presentmode"); } +/* -------------------------------------------------------------------------- */ -// XXX changer tous les noms +static void gem_graph_client_application_class_init( + GemGraphClientApplicationClass *klass) +{ + GApplicationClass *app_class = G_APPLICATION_CLASS(klass); + + app_class->activate = gem_graph_client_application_activate; +} + +GemGraphClientApplication *gem_graph_client_application_new( + const char *application_id, + GApplicationFlags flags) +{ + g_return_val_if_fail(application_id != NULL, NULL); + + return g_object_new(GEM_GRAPH_CLIENT_TYPE_APPLICATION, + "application-id", application_id, + "flags", flags, + NULL); +} diff --git a/src/ui/gemgraph.ui b/src/ui/gemgraph.ui index edfe3b9..4ba441d 100644 --- a/src/ui/gemgraph.ui +++ b/src/ui/gemgraph.ui @@ -54,7 +54,7 @@ - side_run + run center @@ -66,9 +66,9 @@ - side_home + home - + center <b>Sidebar: home</b> True @@ -78,7 +78,7 @@ - side_presentation + presentation center @@ -90,7 +90,7 @@ - side_edit + edit center @@ -106,7 +106,7 @@ - main_run + run center @@ -118,7 +118,7 @@ - main_home + home center @@ -130,7 +130,7 @@ - main_presentation + presentation center @@ -142,7 +142,7 @@ - main_edit + edit center diff --git a/src/ui/window.c b/src/ui/window.c index 31082bc..e49182e 100644 --- a/src/ui/window.c +++ b/src/ui/window.c @@ -36,6 +36,8 @@ float rotation_angles[N_AXIS] = { 0.0 }; // Rotation angles on each axis static GtkWidget *gl_area = NULL; +static GemGraphClientWindow *window; + /* -------------------------------------------------------------------------- */ static void on_axis_value_change(GtkAdjustment *adjustment, gpointer data); @@ -204,6 +206,7 @@ struct _GemGraphClientWindow GtkPaned *main_paned; GtkMenuButton *main_button_mode; GtkToggleButton *main_button_sidebar; + GtkOverlay *toast_overlay; }; G_DEFINE_FINAL_TYPE (GemGraphClientWindow, @@ -243,9 +246,45 @@ static void gem_graph_client_window_class_init(GemGraphClientWindowClass *klass) gtk_widget_class_bind_template_child(widget_class, GemGraphClientWindow, main_button_sidebar); + gtk_widget_class_bind_template_child(widget_class, + GemGraphClientWindow, + toast_overlay); } static void gem_graph_client_window_init(GemGraphClientWindow *self) { gtk_widget_init_template(GTK_WIDGET(self)); + + window = self; +} + +/* -------------------------------------------------------------------------- */ + +void uiWindowStackChange(const char *mode) +{ + if (window->main_stack == NULL) { + g_printerr("Can't find self->main_stack !\n"); + return; + } + if (window->side_stack == NULL) { + g_printerr("Can't find self->side_stack !\n"); + return; + } + gtk_stack_set_visible_child_full(window->main_stack, + mode, + GTK_STACK_TRANSITION_TYPE_CROSSFADE); + gtk_stack_set_visible_child_full(window->side_stack, + mode, + GTK_STACK_TRANSITION_TYPE_CROSSFADE); +} + +void uiWindowSendNotification(const char *message) +{ + if (window->toast_overlay == NULL) { + g_printerr("Can't find self->toast_overlay !\n"); + return; + } + + //gtk_overlay_add_overlay(self->toast_overlay, //XXX); + g_print("NOTIFICATION: %s\n", message); }