From 34dc0b375065d839dea1e24f8e0f18cdfe34b48d Mon Sep 17 00:00:00 2001 From: Perry Werneck Date: Tue, 17 Dec 2019 10:20:37 -0300 Subject: [PATCH] Buttons on the header bar are now configurable. --- src/include/pw3270/application.h | 4 ++++ src/main/tools.c | 24 ++++++++++++++++++++++++ src/objects/toolbar/toolbar.c | 16 +--------------- src/objects/window/header.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/objects/window/private.h | 12 ++++++++---- src/objects/window/window.c | 210 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------------------------------------------------------------------------------------------------- 6 files changed, 220 insertions(+), 138 deletions(-) diff --git a/src/include/pw3270/application.h b/src/include/pw3270/application.h index 53f7e6f..4c69e97 100644 --- a/src/include/pw3270/application.h +++ b/src/include/pw3270/application.h @@ -72,6 +72,10 @@ gboolean pw3270_settings_set_int(const gchar *key, gint value); + // Tools + GtkBuilder * pw3270_application_get_builder(const gchar *name); + void gtk_container_remove_all(GtkContainer *container); + // Actions void pw3270_application_print_copy_activated(GAction *action, GVariant *parameter, GtkWidget *terminal); void pw3270_application_save_copy_activated(GAction *action, GVariant *parameter, GtkWidget *terminal); diff --git a/src/main/tools.c b/src/main/tools.c index 275f93d..99d2c8b 100644 --- a/src/main/tools.c +++ b/src/main/tools.c @@ -38,4 +38,28 @@ /*---[ Implement ]----------------------------------------------------------------------------------*/ + GtkBuilder * pw3270_application_get_builder(const gchar *name) { + +#ifdef DEBUG + g_autofree gchar * filename = g_build_filename("ui",name,NULL); +#else + lib3270_autoptr(char) filename = lib3270_build_data_filename("ui",name,NULL); +#endif // DEBUG + + return gtk_builder_new_from_file(filename); + } + + void gtk_container_remove_all(GtkContainer *container) { + + GList * children = gtk_container_get_children(container); + GList * item; + + for(item = children;item;item = g_list_next(item)) { + gtk_container_remove(container,GTK_WIDGET(item->data)); + } + + g_list_free(children); + + } + diff --git a/src/objects/toolbar/toolbar.c b/src/objects/toolbar/toolbar.c index 525c76b..1ea85f3 100644 --- a/src/objects/toolbar/toolbar.c +++ b/src/objects/toolbar/toolbar.c @@ -91,7 +91,6 @@ PROP_ACTION_NAMES, }; - struct _pw3270ToolBar { GtkToolbar parent; @@ -375,24 +374,12 @@ } - void pw3270_toolbar_clear(GtkWidget *toolbar) { - - GList * children = gtk_container_get_children(GTK_CONTAINER(toolbar)); - GList * item; - - for(item = children;item;item = g_list_next(item)) { - gtk_container_remove(GTK_CONTAINER(toolbar),GTK_WIDGET(item->data)); - } - - g_list_free(children); - } - void pw3270_toolbar_set_actions(GtkWidget *toolbar, const gchar *action_names) { gchar ** actions = g_strsplit(action_names,",",-1); size_t ix; - pw3270_toolbar_clear(toolbar); + gtk_container_remove_all(GTK_CONTAINER(toolbar)); for(ix = 0; actions[ix]; ix++) { pw3270_toolbar_insert_action(toolbar,actions[ix],-1); @@ -426,6 +413,5 @@ g_list_free(children); - return g_string_free(str,FALSE); } diff --git a/src/objects/window/header.c b/src/objects/window/header.c index dc9efd0..9ad03b6 100644 --- a/src/objects/window/header.c +++ b/src/objects/window/header.c @@ -33,6 +33,53 @@ #include #include + void pw3270_window_set_header_action_names(GtkWidget *window, const gchar *action_names) { + + GtkWidget * header = gtk_window_get_titlebar(GTK_WINDOW(window)); + + if(!(header && GTK_IS_HEADER_BAR(header))) + return; + + gtk_container_remove_all(GTK_CONTAINER(header)); + + if(action_names && *action_names) { + + size_t ix; + gchar ** header_blocks = g_strsplit(action_names,":",-1); + + g_autoptr(GtkBuilder) builder = pw3270_application_get_builder("window.xml"); + + if(g_strv_length(header_blocks) >= 2) { + + gchar ** elements; + GtkWidget * button; + + // First the left side actions. + elements = g_strsplit(header_blocks[0],",",-1); + for(ix=0;elements[ix];ix++) { + button = pw3270_header_button_new_from_builder(GTK_WIDGET(window),builder,elements[ix]); + g_object_set_data(G_OBJECT(button),"header-position-id",GINT_TO_POINTER(0)); + gtk_header_bar_pack_start(GTK_HEADER_BAR(header), button); + } + g_strfreev(elements); + + // And then, the right side actions; + elements = g_strsplit(header_blocks[1],",",-1); + for(ix=0;elements[ix];ix++) { + button = pw3270_header_button_new_from_builder(GTK_WIDGET(window),builder,elements[ix]); + g_object_set_data(G_OBJECT(button),"header-position-id",GINT_TO_POINTER(1)); + gtk_header_bar_pack_end(GTK_HEADER_BAR(header), button); + } + g_strfreev(elements); + + } + + g_strfreev(header_blocks); + + } + + } + static void on_sensitive(GtkWidget *button, GParamSpec *spec, GtkWidget *widget) { gboolean sensitive; @@ -73,8 +120,53 @@ gtk_widget_set_focus_on_click(button,FALSE); gtk_widget_set_can_focus(button,FALSE); gtk_widget_set_can_default(button,FALSE); + gtk_widget_set_name(button,action_name); } return button; } + + gchar * pw3270_window_get_action_names(GtkWidget *window) { + + GtkWidget * header = gtk_window_get_titlebar(GTK_WINDOW(window)); + + if(!(header && GTK_IS_HEADER_BAR(header))) + return g_strdup("win.disconnect,win.reconnect,win.file.transfer,win.print:menu.open-menu"); + + GString * str = g_string_new(""); + + GList * children = gtk_container_get_children(GTK_CONTAINER(header)); + GList * item; + + int id; + for(id = 0; id < 2; id++) { + + gboolean sep = FALSE; + + for(item = children;item;item = g_list_next(item)) { + + if(GPOINTER_TO_INT(g_object_get_data(G_OBJECT(item->data),"header-position-id") != id)) + continue; + + if(sep) + g_string_append(str,","); + + if(GTK_IS_MENU_BUTTON(item->data)) { + g_string_append(str,gtk_widget_get_name(GTK_WIDGET(item->data))); + } else if(GTK_IS_ACTIONABLE(item->data)) { + g_string_append(str,gtk_actionable_get_action_name(GTK_ACTIONABLE(item->data))); + } + + sep = TRUE; + } + + if(!id) + g_string_append(str,":"); + + } + + g_list_free(children); + + return g_string_free(str,FALSE); + } diff --git a/src/objects/window/private.h b/src/objects/window/private.h index 5a1de79..af2401b 100644 --- a/src/objects/window/private.h +++ b/src/objects/window/private.h @@ -77,14 +77,18 @@ G_GNUC_INTERNAL GtkWidget * pw3270_setup_image_button(GtkWidget *button, const gchar *image_name); // Actions - GAction * pw3270_action_host_properties_new(void); - GAction * pw3270_set_color_action_new(void); - GAction * pw3270_file_transfer_action_new(void); + G_GNUC_INTERNAL GAction * pw3270_action_host_properties_new(void); + G_GNUC_INTERNAL GAction * pw3270_set_color_action_new(void); + G_GNUC_INTERNAL GAction * pw3270_file_transfer_action_new(void); GAction * pw3270_action_session_properties_new(void); + // Header bar + G_GNUC_INTERNAL void pw3270_window_set_header_action_names(GtkWidget *window, const gchar *action_names); + G_GNUC_INTERNAL gchar * pw3270_window_get_action_names(GtkWidget *window); + // Terminal actions. - GAction * pw3270_model_number_action_new(GtkWidget *terminal); + G_GNUC_INTERNAL GAction * pw3270_model_number_action_new(GtkWidget *terminal); G_GNUC_INTERNAL void pw3270_window_open_activated(GSimpleAction * action, GVariant *parameter, gpointer window); G_GNUC_INTERNAL void pw3270_window_close_activated(GSimpleAction * action, GVariant *parameter, gpointer window); diff --git a/src/objects/window/window.c b/src/objects/window/window.c index a929d8a..93e4c9a 100644 --- a/src/objects/window/window.c +++ b/src/objects/window/window.c @@ -33,8 +33,16 @@ #include #include + static void get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec); + static void set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec); + G_DEFINE_TYPE(pw3270ApplicationWindow, pw3270ApplicationWindow, GTK_TYPE_APPLICATION_WINDOW); + enum { + PROP_NONE, + PROP_ACTION_NAMES, + }; + static void destroy(GtkWidget *widget) { size_t ix; @@ -70,9 +78,39 @@ static void pw3270ApplicationWindow_class_init(pw3270ApplicationWindowClass *klass) { - GtkWidgetClass * widget = GTK_WIDGET_CLASS(klass); - widget->destroy = destroy; + GTK_WIDGET_CLASS(klass)->destroy = destroy; + + GObjectClass *object_class = G_OBJECT_CLASS(klass); + + object_class->set_property = set_property; + object_class->get_property = get_property; + + g_object_class_install_property( + object_class, + PROP_ACTION_NAMES, + g_param_spec_string ("action-names", + N_("Action Names"), + N_("The name of the actions in the header bar"), + NULL, + G_PARAM_WRITABLE|G_PARAM_READABLE) + ); + + + } + + void set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec G_GNUC_UNUSED(*pspec)) { + + if(prop_id == PROP_ACTION_NAMES) { + pw3270_window_set_header_action_names(GTK_WIDGET(object), g_value_get_string(value)); + } + + } + + void get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { + if(prop_id == PROP_ACTION_NAMES) { + g_value_take_string(value,pw3270_window_get_action_names(GTK_WIDGET(object))); + } } @@ -178,8 +216,11 @@ GtkWidget * pw3270_application_window_new(GtkApplication * application) { + gchar *title = _( "IBM 3270 Terminal emulator" ); + + g_return_val_if_fail(PW3270_IS_APPLICATION(application),NULL); + size_t ix; - const gchar * title = _( "IBM 3270 Terminal emulator" ); g_autoptr(GSettings) settings = pw3270_application_get_settings(G_APPLICATION(application)); @@ -190,138 +231,69 @@ "application", application, NULL); - if(PW3270_IS_APPLICATION(gtk_window_get_application(GTK_WINDOW(window)))) { - - GtkBuilder * builder; -#ifdef DEBUG - builder = gtk_builder_new_from_file("ui/window.xml"); -#else - { - lib3270_autoptr(char) build_file = lib3270_build_data_filename("ui","window.xml",NULL); - builder = gtk_builder_new_from_file(build_file); - } -#endif // DEBUG - - switch(pw3270_application_get_ui_style(G_APPLICATION(application))) { - case PW3270_UI_STYLE_CLASSICAL: - { - gtk_window_set_title(GTK_WINDOW(window), title); - - } - break; - - case PW3270_UI_STYLE_GNOME: - { - // Create header bar - GtkHeaderBar * header = GTK_HEADER_BAR(gtk_header_bar_new()); - gtk_window_set_titlebar(GTK_WINDOW(window), GTK_WIDGET(header)); - gtk_header_bar_set_show_close_button(header,TRUE); - - gtk_header_bar_set_title(header,title); - if(settings) - g_settings_bind(settings, "has-subtitle", header, "has-subtitle", G_SETTINGS_BIND_DEFAULT); - else - gtk_header_bar_set_has_subtitle(header,TRUE); - - // Show the new header - gtk_widget_show_all(GTK_WIDGET(header)); - - // Create header's action buttons - // https://wiki.gnome.org/Initiatives/GnomeGoals/GearIcons - { - g_autofree gchar * header_actions = g_settings_get_string(settings, "header-action-names"); - gchar ** header_blocks = g_strsplit(header_actions,":",-1); - - if(g_strv_length(header_blocks) >= 2) { - - gchar ** elements; - - // First the left side actions. - elements = g_strsplit(header_blocks[0],",",-1); - for(ix=0;elements[ix];ix++) { - gtk_header_bar_pack_start(header, pw3270_header_button_new_from_builder(GTK_WIDGET(window),builder,elements[ix])); - } - g_strfreev(elements); - - // And then, the right side actions; - elements = g_strsplit(header_blocks[1],",",-1); - for(ix=0;elements[ix];ix++) { - gtk_header_bar_pack_end(header, pw3270_header_button_new_from_builder(GTK_WIDGET(window),builder,elements[ix])); - } - g_strfreev(elements); - - } - - g_strfreev(header_blocks); - - } + // + // Get builder + // + g_autoptr(GtkBuilder) builder = pw3270_application_get_builder("window.xml"); - /* - { - g_autofree gchar * left = g_settings_get_string(settings, "header-start-action-names"); - g_autofree gchar * right = g_settings_get_string(settings, "header-end-action-names"); + // Load popup menus. + const gchar * popup_menus[G_N_ELEMENTS(window->popups)] = { + "popup-over-selected-area", + "popup-over-unselected-area", + "popup-when-offline" + }; + for(ix = 0; ix < G_N_ELEMENTS(popup_menus); ix++) { - } - */ + GObject * model = gtk_builder_get_object(builder, popup_menus[ix]); + if(model) { + window->popups[ix] = gtk_menu_new_from_model(G_MENU_MODEL(model)); + gtk_menu_attach_to_widget(GTK_MENU(window->popups[ix]),GTK_WIDGET(window),NULL); + } - /* - static const gchar * end_actions[] = { - "menu.open-menu", - }; + } - for(ix = 0; ix < G_N_ELEMENTS(end_actions); ix++) { - gtk_header_bar_pack_end(header, pw3270_header_button_new_from_builder(GTK_WIDGET(window),builder,end_actions[ix])); - } + if(pw3270_application_get_ui_style(G_APPLICATION(application)) == PW3270_UI_STYLE_GNOME) { + // Create header bar - static const gchar * start_actions[] = { - "win.disconnect", - "win.reconnect", - "win.file.transfer", - "win.print" - }; + GtkHeaderBar * header = GTK_HEADER_BAR(gtk_header_bar_new()); + gtk_window_set_titlebar(GTK_WINDOW(window), GTK_WIDGET(header)); + gtk_header_bar_set_show_close_button(header,TRUE); - for(ix = 0; ix < G_N_ELEMENTS(start_actions); ix++) { - gtk_header_bar_pack_start(header, pw3270_header_button_new_from_builder(GTK_WIDGET(window),builder,start_actions[ix])); - } - */ + gtk_header_bar_set_title(header,title); + g_settings_bind( + settings, + "has-subtitle", + header, + "has-subtitle", + G_SETTINGS_BIND_DEFAULT + ); + // Show the new header + gtk_widget_show_all(GTK_WIDGET(header)); - /* - // Create "new tab" bar - GtkWidget * new_tab_button = pw3270_setup_image_button(gtk_button_new(),"tab-new-symbolic"); - gtk_actionable_set_action_name(GTK_ACTIONABLE(new_tab_button),"app.new.tab"); - gtk_header_bar_pack_start(header, new_tab_button); - gtk_widget_show(new_tab_button); - */ + // g_autofree gchar * header_actions = g_settings_get_string(settings, "header-action-names"); + // pw3270_window_set_header_action_names(GTK_WIDGET(window), header_actions); - } - break; + g_settings_bind( + settings, + "header-action-names", + window, + "action-names", + G_SETTINGS_BIND_DEFAULT + ); - default: - g_warning("Unexpected UI"); +#ifdef DEBUG + { + g_autofree gchar * an = pw3270_window_get_action_names(window); } +#endif // DEBUG - // Load popup menus. - const gchar * popup_menus[G_N_ELEMENTS(window->popups)] = { - "popup-over-selected-area", - "popup-over-unselected-area", - "popup-when-offline" - }; - - for(ix = 0; ix < G_N_ELEMENTS(popup_menus); ix++) { - - GObject * model = gtk_builder_get_object(builder, popup_menus[ix]); - if(model) { - window->popups[ix] = gtk_menu_new_from_model(G_MENU_MODEL(model)); - gtk_menu_attach_to_widget(GTK_MENU(window->popups[ix]),GTK_WIDGET(window),NULL); - } - - } + } else { - g_object_unref(builder); + gtk_window_set_title(GTK_WINDOW(window), title); } -- libgit2 0.21.2