aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/interface-gtk/interface-gtk.cpp
diff options
context:
space:
mode:
authorRobin Haberkorn <robin.haberkorn@googlemail.com>2016-02-02 14:42:58 +0100
committerRobin Haberkorn <robin.haberkorn@googlemail.com>2016-02-02 17:49:42 +0100
commite768487fe3ef9ec8f94cea11ad6587c49c32422a (patch)
tree2d9b3a6fdea2fc8dc06c4fbd548eee4b9bf95cab /src/interface-gtk/interface-gtk.cpp
parent8627a00e3b25cdd80d88ddcef9d2d73cc784d571 (diff)
downloadsciteco-e768487fe3ef9ec8f94cea11ad6587c49c32422a.tar.gz
Gtk UI: full color scheme support
* implemented by exporting the most important Scintilla STYLEs as CSS variables and defining named widgets for the main UI components. * ~/.teco_css will then apply the Scintilla styles to the Gtk UI. This file is also for additional tweaks, e.g. enabling translucency. * A fallback.css is provided which does just that and is able to apply the terminal.tes and solarized.tes color schemes. * Other important aspects of theming like font sizes and names have not yet been dealt with. (We may want to apply the corresponding Scintilla settings to some widgets...)
Diffstat (limited to 'src/interface-gtk/interface-gtk.cpp')
-rw-r--r--src/interface-gtk/interface-gtk.cpp120
1 files changed, 113 insertions, 7 deletions
diff --git a/src/interface-gtk/interface-gtk.cpp b/src/interface-gtk/interface-gtk.cpp
index ebd3c91..7938131 100644
--- a/src/interface-gtk/interface-gtk.cpp
+++ b/src/interface-gtk/interface-gtk.cpp
@@ -25,6 +25,7 @@
#include <glib.h>
#include <glib/gprintf.h>
+#include <glib/gstdio.h>
/*
* FIXME: Because of gdk_threads_enter().
@@ -42,11 +43,11 @@
#include <gio/gio.h>
-#include "gtk-info-popup.h"
-
#include <Scintilla.h>
#include <ScintillaWidget.h>
+#include "gtk-info-popup.h"
+
#include "sciteco.h"
#include "string-utils.h"
#include "cmdline.h"
@@ -84,7 +85,24 @@ static gboolean sigterm_handler(gpointer user_data) G_GNUC_UNUSED;
} /* extern "C" */
-#define UNNAMED_FILE "(Unnamed)"
+#define UNNAMED_FILE "(Unnamed)"
+
+#define USER_CSS_FILE ".teco_css"
+
+/** printf() format for CSS RGB colors given as guint32 */
+#define CSS_COLOR_FORMAT "#%06" G_GINT32_MODIFIER "X"
+
+/**
+ * Convert Scintilla-style BGR color triple to
+ * RGB.
+ */
+static inline guint32
+bgr2rgb(guint32 bgr)
+{
+ return ((bgr & 0x0000FF) << 16) |
+ ((bgr & 0x00FF00) << 0) |
+ ((bgr & 0xFF0000) >> 16);
+}
void
ViewGtk::initialize_impl(void)
@@ -189,6 +207,7 @@ InterfaceGtk::main_impl(int &argc, char **&argv)
* FIXME: At lease on Gtk 3.12 we could disable the subtitle.
*/
info_bar_widget = gtk_header_bar_new();
+ gtk_widget_set_name(info_bar_widget, "sciteco-info-bar");
info_image = gtk_image_new();
gtk_header_bar_pack_start(GTK_HEADER_BAR(info_bar_widget), info_image);
if (use_csd) {
@@ -214,6 +233,7 @@ InterfaceGtk::main_impl(int &argc, char **&argv)
gtk_box_pack_start(GTK_BOX(vbox), overlay_widget, TRUE, TRUE, 0);
message_bar_widget = gtk_info_bar_new();
+ gtk_widget_set_name(message_bar_widget, "sciteco-message-bar");
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.);
@@ -221,6 +241,7 @@ InterfaceGtk::main_impl(int &argc, char **&argv)
gtk_box_pack_start(GTK_BOX(vbox), message_bar_widget, FALSE, FALSE, 0);
cmdline_widget = gtk_entry_new();
+ gtk_widget_set_name(cmdline_widget, "sciteco-cmdline");
gtk_entry_set_has_frame(GTK_ENTRY(cmdline_widget), FALSE);
gtk_editable_set_editable(GTK_EDITABLE(cmdline_widget), FALSE);
widget_set_font(cmdline_widget, "Courier");
@@ -236,6 +257,7 @@ InterfaceGtk::main_impl(int &argc, char **&argv)
* filling the entire width.
*/
popup_widget = gtk_info_popup_new();
+ gtk_widget_set_name(popup_widget, "sciteco-info-popup");
gtk_overlay_add_overlay(GTK_OVERLAY(overlay_widget), popup_widget);
g_signal_connect(overlay_widget, "get-child-position",
G_CALLBACK(gtk_info_popup_get_position_in_overlay), NULL);
@@ -248,8 +270,13 @@ InterfaceGtk::main_impl(int &argc, char **&argv)
void
InterfaceGtk::vmsg_impl(MessageType type, const gchar *fmt, va_list ap)
{
+ /*
+ * The message types are chosen such that there is a CSS class
+ * for every one of them. GTK_MESSAGE_OTHER does not have
+ * a CSS class.
+ */
static const GtkMessageType type2gtk[] = {
- /* [MSG_USER] = */ GTK_MESSAGE_OTHER,
+ /* [MSG_USER] = */ GTK_MESSAGE_QUESTION,
/* [MSG_INFO] = */ GTK_MESSAGE_INFO,
/* [MSG_WARNING] = */ GTK_MESSAGE_WARNING,
/* [MSG_ERROR] = */ GTK_MESSAGE_ERROR
@@ -285,7 +312,7 @@ InterfaceGtk::msg_clear(void)
gdk_threads_enter();
gtk_info_bar_set_message_type(GTK_INFO_BAR(message_bar_widget),
- GTK_MESSAGE_OTHER);
+ GTK_MESSAGE_QUESTION);
gtk_label_set_text(GTK_LABEL(message_widget), "");
gdk_threads_leave();
@@ -482,6 +509,38 @@ InterfaceGtk::widget_set_font(GtkWidget *widget, const gchar *font_name)
}
void
+InterfaceGtk::set_css_variables_from_view(ViewGtk *view)
+{
+ gchar buffer[256];
+
+ /*
+ * Generates a CSS that sets some predefined color variables.
+ * This effectively "exports" Scintilla styles into the CSS
+ * world.
+ * Those colors are used by the fallback.css shipping with SciTECO
+ * in order to apply the SciTECO-controlled color scheme to all the
+ * predefined UI elements.
+ * They can also be used in user-customizations.
+ */
+ g_snprintf(buffer, sizeof(buffer),
+ "@define-color sciteco_default_fg_color " CSS_COLOR_FORMAT ";"
+ "@define-color sciteco_default_bg_color " CSS_COLOR_FORMAT ";"
+ "@define-color sciteco_calltip_fg_color " CSS_COLOR_FORMAT ";"
+ "@define-color sciteco_calltip_bg_color " CSS_COLOR_FORMAT ";",
+ bgr2rgb(view->ssm(SCI_STYLEGETFORE, STYLE_DEFAULT)),
+ bgr2rgb(view->ssm(SCI_STYLEGETBACK, STYLE_DEFAULT)),
+ bgr2rgb(view->ssm(SCI_STYLEGETFORE, STYLE_CALLTIP)),
+ bgr2rgb(view->ssm(SCI_STYLEGETBACK, STYLE_CALLTIP)));
+
+ /*
+ * The GError and return value has been deprecated.
+ * A CSS parsing error would point to a programming
+ * error anyway.
+ */
+ gtk_css_provider_load_from_data(css_var_provider, buffer, -1, NULL);
+}
+
+void
InterfaceGtk::event_loop_impl(void)
{
static const gchar *icon_files[] = {
@@ -491,6 +550,10 @@ InterfaceGtk::event_loop_impl(void)
NULL
};
+ GdkScreen *default_screen = gdk_screen_get_default();
+ GtkCssProvider *user_css_provider;
+ gchar *config_path, *user_css_file;
+
GList *icon_list = NULL;
GThread *thread;
@@ -516,6 +579,41 @@ InterfaceGtk::event_loop_impl(void)
refresh_info();
/*
+ * Initialize the CSS variable provider and the CSS provider
+ * for the included fallback.css.
+ * NOTE: The return value of gtk_css_provider_load() is deprecated.
+ * Instead we could register for the "parsing-error" signal.
+ * For the time being we just silently ignore parsing errors.
+ * They will be printed to stderr by Gtk anyway.
+ */
+ css_var_provider = gtk_css_provider_new();
+ if (current_view)
+ /* set CSS variables initially */
+ set_css_variables_from_view(current_view);
+ gtk_style_context_add_provider_for_screen(default_screen,
+ GTK_STYLE_PROVIDER(css_var_provider),
+ GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+ user_css_provider = gtk_css_provider_new();
+ /* get path of $SCITECOCONFIG/.teco_css */
+ config_path = QRegisters::globals["$SCITECOCONFIG"]->get_string();
+ user_css_file = g_build_filename(config_path, USER_CSS_FILE, NIL);
+ if (g_file_test(user_css_file, G_FILE_TEST_IS_REGULAR))
+ /* open user CSS */
+ gtk_css_provider_load_from_path(user_css_provider,
+ user_css_file, NULL);
+ else
+ /* use fallback CSS */
+ gtk_css_provider_load_from_path(user_css_provider,
+ SCITECODATADIR G_DIR_SEPARATOR_S
+ "fallback.css",
+ NULL);
+ g_free(user_css_file);
+ g_free(config_path);
+ gtk_style_context_add_provider_for_screen(default_screen,
+ GTK_STYLE_PROVIDER(user_css_provider),
+ GTK_STYLE_PROVIDER_PRIORITY_USER);
+
+ /*
* When changing views, the new widget is not
* added immediately to avoid flickering in the GUI.
* It is only updated once per key press and only
@@ -702,6 +800,12 @@ InterfaceGtk::handle_key_press(bool is_shift, bool is_ctl, guint keyval)
}
/*
+ * The styles configured via Scintilla might change
+ * with every keypress.
+ */
+ set_css_variables_from_view(current_view);
+
+ /*
* The info area is updated very often and setting the
* window title each time it is updated is VERY costly.
* So we set it here once after every keypress even if the
@@ -739,8 +843,7 @@ InterfaceGtk::handle_key_press(bool is_shift, bool is_ctl, guint keyval)
InterfaceGtk::~InterfaceGtk()
{
g_free(info_current);
- if (popup_widget)
- gtk_widget_destroy(popup_widget);
+
if (window)
gtk_widget_destroy(window);
@@ -754,6 +857,9 @@ InterfaceGtk::~InterfaceGtk()
g_async_queue_unref(event_queue);
}
+
+ if (css_var_provider)
+ g_object_unref(css_var_provider);
}
/*