diff options
author | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2016-02-02 06:10:53 +0100 |
---|---|---|
committer | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2016-02-02 06:10:53 +0100 |
commit | f25f97e4d0d9a1da69d0ee8fc4fbdff70760f805 (patch) | |
tree | 08397c47e8f20fc081fc37810ccc0b96eabacb67 | |
parent | ac3d8ca27239d586d5cd7fdbfbd3ec55713ae1aa (diff) | |
download | sciteco-f25f97e4d0d9a1da69d0ee8fc4fbdff70760f805.tar.gz |
Gtk UI: added a GtkHeaderBar and install it as the window's title bar
* the header bar takes the role of the "info" line in the Curses UI.
* even though the current file was already shown in the window title,
this has certain disadvantages:
* does not work well with decoration-less WMs like awesome.
The file name is important information and should always be at the
top of the window. The space in the task list of awesome is usually
not even large enough to show the file name.
* the title bar uses a canonicalized buffer/Q-Register name.
For the header bar we can use custom renderings using Pango
that highlight control characters just like the Curses UI does.
This is currently not implemented.
* An icon is now shown for the current file.
This is the same icon fetching code that gtk-info-popup uses.
We might want to move that code into a separate module, along
with Pango rendering - Gob2 could just as well generate C++ code.
* For Q-Registers, currently no icon is shown (FIXME).
* Currently, the subtitle is used to indicate which type of document
(buffer or q-register) is edited. This could be done using the
icons only, in which case we can disable the subtitles and save
screen space.
* Client-side decorations are known to cause problems with some
WMs and if using them fails, we end up with a titlebar and header
bar. It is probably a good idea to make titlebar installation
configurable, at least via a command-line switch (or perhaps
ED flag?)
-rw-r--r-- | src/interface-gtk/gtk-info-popup.gob | 5 | ||||
-rw-r--r-- | src/interface-gtk/interface-gtk.cpp | 101 | ||||
-rw-r--r-- | src/interface-gtk/interface-gtk.h | 20 |
3 files changed, 99 insertions, 27 deletions
diff --git a/src/interface-gtk/gtk-info-popup.gob b/src/interface-gtk/gtk-info-popup.gob index 1df52a9..f172de6 100644 --- a/src/interface-gtk/gtk-info-popup.gob +++ b/src/interface-gtk/gtk-info-popup.gob @@ -25,7 +25,6 @@ requires 2.0.20 #include <math.h> #include <glib/gprintf.h> -#include <gio/gio.h> #ifndef HAVE_GTK_FLOW_BOX_NEW #include "gtkflowbox.h" @@ -35,6 +34,8 @@ requires 2.0.20 %h{ #include <gtk/gtk.h> #include <gdk/gdk.h> + +#include <gio/gio.h> %} enum GTK_INFO_POPUP { @@ -206,7 +207,7 @@ class Gtk:Info:Popup from Gtk:Event:Box { return GTK_WIDGET(widget); } - private GIcon * + public GIcon * get_icon_for_path(const gchar *path, const gchar *fallback_name) { GFile *file; diff --git a/src/interface-gtk/interface-gtk.cpp b/src/interface-gtk/interface-gtk.cpp index d718deb..1babdff 100644 --- a/src/interface-gtk/interface-gtk.cpp +++ b/src/interface-gtk/interface-gtk.cpp @@ -39,6 +39,9 @@ #include <gdk-pixbuf/gdk-pixbuf.h> #include <gtk/gtk.h> + +#include <gio/gio.h> + #include "gtk-info-popup.h" #include <Scintilla.h> @@ -133,7 +136,7 @@ InterfaceGtk::main_impl(int &argc, char **&argv) { static const Cmdline empty_cmdline; GtkWidget *overlay_widget; - GtkWidget *info_content; + GtkWidget *message_bar_content; /* * g_thread_init() is required prior to v2.32 @@ -153,13 +156,27 @@ InterfaceGtk::main_impl(int &argc, char **&argv) event_queue = g_async_queue_new(); window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_title(GTK_WINDOW(window), PACKAGE_NAME); g_signal_connect(G_OBJECT(window), "delete-event", G_CALLBACK(window_delete_cb), event_queue); vbox = gtk_vbox_new(FALSE, 0); - info_current = g_strdup(PACKAGE_NAME); + info_current = g_strdup(""); + + /* + * The info bar is tried to be made the title bar of the + * window which also disables the default window decorations + * (client-side decorations). + * FIXME: This could fail, leaving us with a standard title + * bar and the info bar with close buttons. In this case, + * we should at least disable the info bar close button. + * FIXME: At lease on Gtk 3.12 we could disable the subtitle. + */ + info_bar_widget = gtk_header_bar_new(); + gtk_header_bar_set_show_close_button(GTK_HEADER_BAR(info_bar_widget), TRUE); + info_image = gtk_image_new(); + gtk_header_bar_pack_start(GTK_HEADER_BAR(info_bar_widget), info_image); + gtk_window_set_titlebar(GTK_WINDOW(window), info_bar_widget); /* * The event box is the parent of all Scintilla views @@ -174,12 +191,12 @@ InterfaceGtk::main_impl(int &argc, char **&argv) gtk_container_add(GTK_CONTAINER(overlay_widget), event_box_widget); gtk_box_pack_start(GTK_BOX(vbox), overlay_widget, TRUE, TRUE, 0); - info_widget = gtk_info_bar_new(); - info_content = gtk_info_bar_get_content_area(GTK_INFO_BAR(info_widget)); + message_bar_widget = gtk_info_bar_new(); + message_bar_content = gtk_info_bar_get_content_area(GTK_INFO_BAR(message_bar_widget)); message_widget = gtk_label_new(""); gtk_misc_set_alignment(GTK_MISC(message_widget), 0., 0.); - gtk_container_add(GTK_CONTAINER(info_content), message_widget); - gtk_box_pack_start(GTK_BOX(vbox), info_widget, FALSE, FALSE, 0); + gtk_container_add(GTK_CONTAINER(message_bar_content), message_widget); + gtk_box_pack_start(GTK_BOX(vbox), message_bar_widget, FALSE, FALSE, 0); cmdline_widget = gtk_entry_new(); gtk_entry_set_has_frame(GTK_ENTRY(cmdline_widget), FALSE); @@ -230,7 +247,7 @@ InterfaceGtk::vmsg_impl(MessageType type, const gchar *fmt, va_list ap) gdk_threads_enter(); - gtk_info_bar_set_message_type(GTK_INFO_BAR(info_widget), + gtk_info_bar_set_message_type(GTK_INFO_BAR(message_bar_widget), type2gtk[type]); gtk_label_set_text(GTK_LABEL(message_widget), buf); @@ -245,7 +262,7 @@ InterfaceGtk::msg_clear(void) { gdk_threads_enter(); - gtk_info_bar_set_message_type(GTK_INFO_BAR(info_widget), + gtk_info_bar_set_message_type(GTK_INFO_BAR(message_bar_widget), GTK_MESSAGE_OTHER); gtk_label_set_text(GTK_LABEL(message_widget), ""); @@ -259,23 +276,66 @@ InterfaceGtk::show_view_impl(ViewGtk *view) } void -InterfaceGtk::info_update_impl(const QRegister *reg) +InterfaceGtk::refresh_info(void) { - gchar *name = String::canonicalize_ctl(reg->name); + const gchar *info_type_str; + gchar *info_current_canon = String::canonicalize_ctl(info_current); + GIcon *icon; + gchar *title; + + switch (info_type) { + case INFO_TYPE_QREGISTER: + info_type_str = PACKAGE_NAME " - <QRegister> "; + gtk_header_bar_set_title(GTK_HEADER_BAR(info_bar_widget), + info_current_canon); + gtk_header_bar_set_subtitle(GTK_HEADER_BAR(info_bar_widget), + "QRegister"); + + gtk_image_clear(GTK_IMAGE(info_image)); + break; + case INFO_TYPE_BUFFER_DIRTY: + String::append(info_current_canon, "*"); + /* fall through */ + case INFO_TYPE_BUFFER: + info_type_str = PACKAGE_NAME " - <Buffer> "; + gtk_header_bar_set_title(GTK_HEADER_BAR(info_bar_widget), + info_current_canon); + gtk_header_bar_set_subtitle(GTK_HEADER_BAR(info_bar_widget), + "Buffer"); + + icon = gtk_info_popup_get_icon_for_path(info_current, + "text-x-generic"); + if (!icon) + break; + gtk_image_set_from_gicon(GTK_IMAGE(info_image), + icon, GTK_ICON_SIZE_LARGE_TOOLBAR); + g_object_unref(icon); + break; + } + + title = g_strconcat(info_type_str, info_current_canon, NIL); + gtk_window_set_title(GTK_WINDOW(window), title); + g_free(title); + g_free(info_current_canon); +} + +void +InterfaceGtk::info_update_impl(const QRegister *reg) +{ g_free(info_current); - info_current = g_strconcat(PACKAGE_NAME " - <QRegister> ", - name, NIL); - g_free(name); + info_type = INFO_TYPE_QREGISTER; + /* NOTE: will contain control characters */ + info_current = g_strdup(reg->name); } void InterfaceGtk::info_update_impl(const Buffer *buffer) { g_free(info_current); - info_current = g_strconcat(PACKAGE_NAME " - <Buffer> ", - buffer->filename ? : UNNAMED_FILE, - buffer->dirty ? "*" : "", NIL); + info_type = buffer->dirty ? INFO_TYPE_BUFFER_DIRTY + : INFO_TYPE_BUFFER; + info_current = g_strdup(buffer->filename ? : UNNAMED_FILE); } void @@ -431,6 +491,8 @@ InterfaceGtk::event_loop_impl(void) if (icon_list) g_list_free_full(icon_list, g_object_unref); + refresh_info(); + /* * When changing views, the new widget is not * added immediately to avoid flickering in the GUI. @@ -447,7 +509,6 @@ InterfaceGtk::event_loop_impl(void) gtk_container_add(GTK_CONTAINER(event_box_widget), current_view_widget); } - gtk_window_set_title(GTK_WINDOW(window), info_current); gtk_widget_show_all(window); /* don't show popup by default */ @@ -629,6 +690,8 @@ InterfaceGtk::handle_key_press(bool is_shift, bool is_ctl, guint keyval) */ gdk_threads_enter(); + refresh_info(); + if (current_view != last_view) { /* * The last view's object is not guaranteed to @@ -646,8 +709,6 @@ InterfaceGtk::handle_key_press(bool is_shift, bool is_ctl, guint keyval) gtk_widget_show(current_view_widget); } - gtk_window_set_title(GTK_WINDOW(window), info_current); - gdk_window_thaw_updates(view_window); gdk_threads_leave(); diff --git a/src/interface-gtk/interface-gtk.h b/src/interface-gtk/interface-gtk.h index b5200ea..a3a0af6 100644 --- a/src/interface-gtk/interface-gtk.h +++ b/src/interface-gtk/interface-gtk.h @@ -78,12 +78,20 @@ typedef class InterfaceGtk : public Interface<InterfaceGtk, ViewGtk> { GtkWidget *window; GtkWidget *vbox; - GtkWidget *event_box_widget; - + enum { + INFO_TYPE_BUFFER = 0, + INFO_TYPE_BUFFER_DIRTY, + INFO_TYPE_QREGISTER + } info_type; gchar *info_current; - GtkWidget *info_widget; + GtkWidget *info_bar_widget; + GtkWidget *info_image; + GtkWidget *event_box_widget; + + GtkWidget *message_bar_widget; GtkWidget *message_widget; + GtkWidget *cmdline_widget; GtkWidget *popup_widget; @@ -96,9 +104,10 @@ public: InterfaceGtk() : Interface(), window(NULL), vbox(NULL), + info_type(INFO_TYPE_BUFFER), info_current(NULL), + info_bar_widget(NULL), info_image(NULL), event_box_widget(NULL), - info_current(NULL), info_widget(NULL), - message_widget(NULL), + message_bar_widget(NULL), message_widget(NULL), cmdline_widget(NULL), popup_widget(NULL), current_view_widget(NULL), @@ -163,6 +172,7 @@ public: private: static void widget_set_font(GtkWidget *widget, const gchar *font_name); + void refresh_info(void); void cmdline_insert_chr(gint &pos, gchar chr); } InterfaceCurrent; |