[gnome-flashback/wip/segeiger/statusicon: 4/4] input-sources: implement status icon with pango and cairo
- From: Sebastian Geiger <segeiger src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-flashback/wip/segeiger/statusicon: 4/4] input-sources: implement status icon with pango and cairo
- Date: Wed, 30 Sep 2015 12:55:36 +0000 (UTC)
commit f72dce4a398343bd59bb0a6e3b176133c12bd078
Author: Sebastian Geiger <sbastig gmx net>
Date: Wed Sep 30 14:54:55 2015 +0200
input-sources: implement status icon with pango and cairo
.../libinput-sources/gf-input-sources.c | 207 ++++++++++++++++++++
1 files changed, 207 insertions(+), 0 deletions(-)
---
diff --git a/gnome-flashback/libinput-sources/gf-input-sources.c
b/gnome-flashback/libinput-sources/gf-input-sources.c
index ce708ad..bad5e02 100644
--- a/gnome-flashback/libinput-sources/gf-input-sources.c
+++ b/gnome-flashback/libinput-sources/gf-input-sources.c
@@ -17,9 +17,33 @@
#include "config.h"
+#define _XOPEN_SOURCE
+
+#include <gtk/gtk.h>
+
#include "gf-ibus-manager.h"
#include "gf-input-sources.h"
#include "gf-input-source-manager.h"
+#include "gf-input-source.h"
+
+#include <pango/pangocairo.h>
+#include <math.h>
+
+#define INPUT_SOURCES_SCHEMA org.gnome.gnome-flashback.input-sources
+#define SIZE 256
+
+struct IconInfo_
+{
+ gchar *font_name,
+ *short_name;
+
+ gdouble font_size;
+
+ GdkRGBA fg_color,
+ bg_color;
+};
+
+typedef struct IconInfo_ IconInfo;
struct _GfInputSources
{
@@ -27,10 +51,121 @@ struct _GfInputSources
GfIBusManager *ibus_manager;
GfInputSourceManager *input_source_manager;
+
+ GtkStatusIcon *status_icon;
+
+ IconInfo *icon_info;
};
G_DEFINE_TYPE (GfInputSources, gf_input_sources, G_TYPE_OBJECT)
+static void draw_short_name (cairo_t *cr, IconInfo *info)
+{
+ gdouble text_width, text_y;
+ gdouble pango_font_size;
+ gdouble baseline;
+ gdouble x, y;
+
+ gint center;
+
+ gchar *short_name, *font_name;
+
+ PangoLayout *layout;
+ PangoFontDescription *font_description;
+ PangoRectangle ink_rect, logical_rect;
+
+ short_name = info->short_name;
+ font_name = info->font_name;
+
+ font_description = pango_font_description_new ();
+ pango_font_description_set_family (font_description, font_name);
+ pango_font_description_set_weight (font_description, PANGO_WEIGHT_BOLD);
+ pango_font_size = SIZE * info->font_size * PANGO_SCALE;
+ pango_font_description_set_absolute_size (font_description,
+ pango_font_size);
+
+ layout = pango_cairo_create_layout (cr);
+ pango_layout_set_font_description (layout, font_description);
+ pango_layout_set_text (layout, short_name, -1);
+
+ pango_layout_get_extents (layout, &ink_rect, &logical_rect);
+
+ text_width = ink_rect.width / (gdouble) PANGO_SCALE;
+ text_y = ink_rect.y / (gdouble) PANGO_SCALE;
+
+ baseline = pango_layout_get_baseline (layout) / PANGO_SCALE;
+
+ center = SIZE / 2;
+ y = center + baseline / 2.0 - text_y / 2.0;
+ x = (SIZE - text_width) / 2.0 - (ink_rect.x / PANGO_SCALE);
+
+ cairo_set_source_rgb (cr,
+ info->bg_color.red,
+ info->bg_color.green,
+ info->bg_color.blue);
+ cairo_move_to (cr, x, y);
+ pango_cairo_show_layout_line (cr, pango_layout_get_line (layout, 0));
+
+ g_object_unref (layout);
+ pango_font_description_free (font_description);
+}
+
+static void draw_background (cairo_t *cr, IconInfo *info)
+{
+ /* Draw a background */
+ cairo_set_source_rgba (cr,
+ info->bg_color.red,
+ info->bg_color.green,
+ info->bg_color.blue,
+ 0);
+ cairo_rectangle (cr, 0, 0, SIZE, SIZE);
+ cairo_fill (cr);
+}
+
+static void draw_rounded_rectangle (cairo_t *cr, IconInfo *info)
+{
+ double
+ x = 10,
+ y = 10,
+ width = SIZE - 2*x,
+ height = SIZE - 2*y,
+ aspect = 1.0, /* aspect ratio */
+ corner_radius = height / 10.0; /* and corner curvature radius */
+
+ double radius = corner_radius / aspect;
+ double degrees = M_PI / 180.0;
+
+ cairo_new_sub_path (cr);
+ cairo_arc (cr, x + width - radius, y + radius, radius, -90 * degrees, 0 * degrees);
+ cairo_arc (cr, x + width - radius, y + height - radius, radius, 0 * degrees, 90 * degrees);
+ cairo_arc (cr, x + radius, y + height - radius, radius, 90 * degrees, 180 * degrees);
+ cairo_arc (cr, x + radius, y + radius, radius, 180 * degrees, 270 * degrees);
+ cairo_close_path (cr);
+
+ cairo_set_source_rgb (cr,
+ info->fg_color.red,
+ info->fg_color.green,
+ info->fg_color.blue);
+ cairo_fill_preserve (cr);
+}
+
+static GdkPixbuf *get_pixbuf_for_icon_info(IconInfo *info)
+{
+ cairo_surface_t *surface;
+ cairo_t * cr;
+
+ surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, SIZE, SIZE);
+ cr = cairo_create (surface);
+
+ draw_background (cr, info);
+ draw_rounded_rectangle (cr, info);
+ draw_short_name (cr, info);
+
+ return gdk_pixbuf_get_from_surface (surface, 0, 0, SIZE, SIZE);
+
+}
+
+
static void
sources_changed_cb (GfInputSourceManager *manager,
gpointer user_data)
@@ -38,6 +173,48 @@ sources_changed_cb (GfInputSourceManager *manager,
}
static void
+status_icon_cliced_cb (GtkStatusIcon *icon,
+ GdkEvent *event,
+ gpointer user_data)
+{
+ g_warning ("NOT IMPLEMENTED: status icon clicked callback");
+}
+
+static void
+current_source_changed_cb (GfInputSourceManager *manager,
+ GfInputSource *source,
+ GfInputSources *sources)
+{
+ GdkPixbuf *pixbuf;
+ g_message ("current_source_changed");
+
+ gtk_status_icon_set_tooltip_text (sources->status_icon,
+ gf_input_source_get_display_name (source));
+
+ sources->icon_info->short_name = g_strdup (gf_input_source_get_short_name (source));
+
+ pixbuf = get_pixbuf_for_icon_info (sources->icon_info);
+
+ gtk_status_icon_set_from_pixbuf (sources->status_icon, pixbuf);
+
+}
+
+static GtkStatusIcon*
+gf_input_sources_init_status_icon (GfInputSources *sources)
+{
+ GtkStatusIcon *status_icon;
+
+ status_icon = gtk_status_icon_new ();
+
+ g_signal_connect (status_icon, "activate",
+ G_CALLBACK (status_icon_cliced_cb), sources);
+ g_signal_connect (sources->input_source_manager, "current-source-changed",
+ G_CALLBACK (current_source_changed_cb), sources);
+
+ return status_icon;
+}
+
+static void
gf_input_sources_dispose (GObject *object)
{
GfInputSources *sources;
@@ -51,6 +228,16 @@ gf_input_sources_dispose (GObject *object)
}
static void
+gf_input_sources_finalize (GObject *object)
+{
+ GfInputSources *sources;
+
+ sources = GF_INPUT_SOURCES (object);
+
+ g_free (sources->icon_info);
+}
+
+static void
gf_input_sources_class_init (GfInputSourcesClass *sources_class)
{
GObjectClass *object_class;
@@ -58,13 +245,33 @@ gf_input_sources_class_init (GfInputSourcesClass *sources_class)
object_class = G_OBJECT_CLASS (sources_class);
object_class->dispose = gf_input_sources_dispose;
+ object_class->finalize= gf_input_sources_finalize;
}
static void
gf_input_sources_init (GfInputSources *sources)
{
+ GdkRGBA fg, bg;
+
sources->ibus_manager = gf_ibus_manager_new ();
sources->input_source_manager = gf_input_source_manager_new (sources->ibus_manager);
+ sources->status_icon = gf_input_sources_init_status_icon (sources);
+ sources->icon_info = g_new0 (IconInfo, 1);
+
+ fg.red = 1.0;
+ fg.green= 1.0;
+ fg.blue = 1.0;
+ fg.alpha = 1.0;
+
+ bg.red = 0.0;
+ bg.green= 0.0;
+ bg.blue = 0.0;
+ bg.alpha = 1.0;
+
+ sources->icon_info->font_name = g_strdup ("Ubuntu");
+ sources->icon_info->fg_color = fg;
+ sources->icon_info->bg_color = bg;
+ sources->icon_info->font_size = 0.6;
g_signal_connect (sources->input_source_manager, "sources-changed",
G_CALLBACK (sources_changed_cb), sources);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]