From 977925a7005678226be7faa1762c6117b240c231 Mon Sep 17 00:00:00 2001 From: Conor Curran Date: Fri, 10 Sep 2010 12:28:57 +0100 Subject: play button and metadata widgets now handle theme changes --- src/metadata-widget.c | 64 ++++++----- src/music-player-bridge.vala | 2 + src/play-button.c | 261 +++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 289 insertions(+), 38 deletions(-) (limited to 'src') diff --git a/src/metadata-widget.c b/src/metadata-widget.c index 18ebd38..c98877f 100644 --- a/src/metadata-widget.c +++ b/src/metadata-widget.c @@ -33,6 +33,7 @@ typedef struct _MetadataWidgetPrivate MetadataWidgetPrivate; struct _MetadataWidgetPrivate { + gboolean theme_change_occured; GtkWidget* hbox; GtkWidget* album_art; GString* image_path; @@ -40,18 +41,18 @@ struct _MetadataWidgetPrivate GtkWidget* artist_label; GtkWidget* piece_label; GtkWidget* container_label; - GdkColor bevel_colour; - GdkColor eight_note_colour; }; #define METADATA_WIDGET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), METADATA_WIDGET_TYPE, MetadataWidgetPrivate)) /* Prototypes */ -static void metadata_widget_class_init (MetadataWidgetClass *klass); -static void metadata_widget_init (MetadataWidget *self); -static void metadata_widget_dispose (GObject *object); -static void metadata_widget_finalize (GObject *object); -static gboolean metadata_image_expose (GtkWidget *image, GdkEventExpose *event, gpointer user_data); +static void metadata_widget_class_init (MetadataWidgetClass *klass); +static void metadata_widget_init (MetadataWidget *self); +static void metadata_widget_dispose (GObject *object); +static void metadata_widget_finalize (GObject *object); +static gboolean metadata_image_expose (GtkWidget *image, GdkEventExpose *event, gpointer user_data); +//static void metadata_widget_style_changed_cb(GtkWidget *widget, gpointer user_data); +static void metadata_widget_set_style (GtkWidget* button, GtkStyle* style); // keyevent consumers static gboolean metadata_widget_button_press_event (GtkWidget *menuitem, @@ -61,15 +62,11 @@ static void metadata_widget_property_update (DbusmenuMenuitem* item, gchar* property, GValue* value, gpointer userdata); - static void metadata_widget_style_labels(MetadataWidget* self, GtkLabel* label); - -void metadata_widget_set_style(GtkWidget* button, GtkStyle* style); static void image_set_from_pixbuf (GtkWidget *widget, MetadataWidget* metadata, GdkPixbuf *source); - static void draw_album_art_placeholder(GtkWidget *metadata); G_DEFINE_TYPE (MetadataWidget, metadata_widget, GTK_TYPE_MENU_ITEM); @@ -95,7 +92,6 @@ metadata_widget_init (MetadataWidget *self) g_debug("MetadataWidget::metadata_widget_init"); MetadataWidgetPrivate * priv = METADATA_WIDGET_GET_PRIVATE(self); - GtkWidget *hbox; hbox = gtk_hbox_new(FALSE, 0); @@ -114,7 +110,9 @@ metadata_widget_init (MetadataWidget *self) gtk_box_pack_start (GTK_BOX (priv->hbox), priv->album_art, FALSE, FALSE, 0); - GtkWidget* vbox = gtk_vbox_new(FALSE, 0); + priv->theme_change_occured = FALSE; + + GtkWidget* vbox = gtk_vbox_new(FALSE, 0); // artist GtkWidget* artist; @@ -177,6 +175,12 @@ metadata_widget_finalize (GObject *object) G_OBJECT_CLASS (metadata_widget_parent_class)->finalize (object); } +static void metadata_widget_style_changed_cb(GtkWidget *widget, + gpointer user_data) +{ + +} + /** * We override the expose method to enable primitive drawing of the * empty album art image and rounded rectangles on the album art. @@ -188,7 +192,9 @@ metadata_image_expose (GtkWidget *metadata, GdkEventExpose *event, gpointer user MetadataWidget* widget = METADATA_WIDGET(user_data); MetadataWidgetPrivate * priv = METADATA_WIDGET_GET_PRIVATE(widget); if(priv->image_path->len > 0){ - if(g_string_equal(priv->image_path, priv->old_image_path) == FALSE){ + if(g_string_equal(priv->image_path, priv->old_image_path) == FALSE || + priv->theme_change_occured == TRUE){ + priv->theme_change_occured = FALSE; GdkPixbuf* pixbuf; pixbuf = gdk_pixbuf_new_from_file(priv->image_path->str, NULL); g_debug("metadata_load_new_image -> pixbuf from %s", @@ -216,6 +222,9 @@ static void draw_album_art_placeholder(GtkWidget *metadata) cairo_t *cr; cr = gdk_cairo_create (metadata->window); + GtkStyle *style; + style = gtk_widget_get_style (metadata); + GtkAllocation alloc; gtk_widget_get_allocation (metadata, &alloc); @@ -234,7 +243,11 @@ static void draw_album_art_placeholder(GtkWidget *metadata) cairo_close_path (cr); - cairo_set_source_rgba (cr, 123.0f / 255.0f, 123.0f / 255.0f, 120.0f / 255.0f, .8f); + cairo_set_source_rgba (cr, + style->fg[0].red/65535.0, + style->fg[0].green/65535.0, + style->fg[0].blue/65535.0, + 0.6); cairo_set_line_width (cr, 2.0); cairo_stroke (cr); @@ -256,7 +269,12 @@ static void draw_album_art_placeholder(GtkWidget *metadata) pango_layout_set_font_description(layout, desc); pango_font_description_free(desc); - cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.8); + cairo_set_source_rgba (cr, + style->fg[0].red/65535.0, + style->fg[0].green/65535.0, + style->fg[0].blue/65535.0, + 0.8); + pango_cairo_update_layout(cr, layout); cairo_move_to (cr, alloc.x + alloc.width/6, alloc.y); pango_cairo_show_layout(cr, layout); @@ -487,21 +505,15 @@ metadata_widget_style_labels(MetadataWidget* self, GtkLabel* label) g_free(markup); } -void +static void metadata_widget_set_style(GtkWidget* metadata, GtkStyle* style) { g_return_if_fail(IS_METADATA_WIDGET(metadata)); MetadataWidget* widg = METADATA_WIDGET(metadata); MetadataWidgetPrivate * priv = METADATA_WIDGET_GET_PRIVATE(widg); - if(style == NULL){ - g_warning("metadata_widget_set_style -> style is NULL!"); - return; - } - else{ - g_debug("metadata_widget: about to set the style colours"); - priv->eight_note_colour = style->fg[GTK_STATE_NORMAL]; - priv->bevel_colour = style->bg[GTK_STATE_NORMAL]; - } + priv->theme_change_occured = TRUE; + gtk_widget_queue_draw(GTK_WIDGET(metadata)); + g_debug("metadata_widget: theme change"); } /** diff --git a/src/music-player-bridge.vala b/src/music-player-bridge.vala index 26bf2c2..61dfa2e 100644 --- a/src/music-player-bridge.vala +++ b/src/music-player-bridge.vala @@ -58,6 +58,8 @@ public class MusicPlayerBridge : GLib.Object continue; } GLib.AppInfo app_info = info as GLib.AppInfo; + // TODO refactor to remove need for further name refactoring in the player controller + // truncate should not do a down() on the name PlayerController ctrl = new PlayerController(this.root_menu, truncate_player_name(app_info.get_name()), calculate_menu_position(), diff --git a/src/play-button.c b/src/play-button.c index a40b683..31cdf5a 100644 --- a/src/play-button.c +++ b/src/play-button.c @@ -55,6 +55,18 @@ Uses code from ctk #define PLAY_WIDTH 28.0f #define PLAY_HEIGHT 29.0f #define PLAY_PADDING 5.0f +#define INNER_START_SHADE 0.98 +#define INNER_END_SHADE 0.98 +#define MIDDLE_START_SHADE 0.7 +#define MIDDLE_END_SHADE 1.4 +#define OUTER_START_SHADE 0.96 +#define OUTER_END_SHADE 0.96 +#define BUTTON_START_SHADE 1.1 +#define BUTTON_END_SHADE 0.9 +#define BUTTON_SHADOW_SHADE 0.8 +#define INNER_COMPRESSED_START_SHADE 0.95 +#define INNER_COMPRESSED_END_SHADE 1.05 + typedef struct _PlayButtonPrivate PlayButtonPrivate; @@ -70,6 +82,14 @@ struct _PlayButtonPrivate GHashTable* command_coordinates; }; +typedef struct +{ + double r; + double g; + double b; +} CairoColorRGB; + + #define PLAY_BUTTON_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), PLAY_BUTTON_TYPE, PlayButtonPrivate)) /* Gobject boiler plate */ @@ -722,6 +742,198 @@ _finalize (cairo_t* cr, cairo_destroy (*cr_surf); } +static void +_color_rgb_to_hls (gdouble *r, + gdouble *g, + gdouble *b) +{ + gdouble min; + gdouble max; + gdouble red; + gdouble green; + gdouble blue; + gdouble h, l, s; + gdouble delta; + + red = *r; + green = *g; + blue = *b; + + if (red > green) + { + if (red > blue) + max = red; + else + max = blue; + + if (green < blue) + min = green; + else + min = blue; + } + else + { + if (green > blue) + max = green; + else + max = blue; + + if (red < blue) + min = red; + else + min = blue; + } + l = (max+min)/2; + if (fabs (max-min) < 0.0001) + { + h = 0; + s = 0; + } + else + { + if (l <= 0.5) + s = (max-min)/(max+min); + else + s = (max-min)/(2-max-min); + + delta = max -min; + if (red == max) + h = (green-blue)/delta; + else if (green == max) + h = 2+(blue-red)/delta; + else if (blue == max) + h = 4+(red-green)/delta; + + h *= 60; + if (h < 0.0) + h += 360; + } + + *r = h; + *g = l; + *b = s; +} + +static void +_color_hls_to_rgb (gdouble *h, + gdouble *l, + gdouble *s) +{ + gdouble hue; + gdouble lightness; + gdouble saturation; + gdouble m1, m2; + gdouble r, g, b; + + lightness = *l; + saturation = *s; + + if (lightness <= 0.5) + m2 = lightness*(1+saturation); + else + m2 = lightness+saturation-lightness*saturation; + + m1 = 2*lightness-m2; + + if (saturation == 0) + { + *h = lightness; + *l = lightness; + *s = lightness; + } + else + { + hue = *h+120; + while (hue > 360) + hue -= 360; + while (hue < 0) + hue += 360; + + if (hue < 60) + r = m1+(m2-m1)*hue/60; + else if (hue < 180) + r = m2; + else if (hue < 240) + r = m1+(m2-m1)*(240-hue)/60; + else + r = m1; + + hue = *h; + while (hue > 360) + hue -= 360; + while (hue < 0) + hue += 360; + + if (hue < 60) + g = m1+(m2-m1)*hue/60; + else if (hue < 180) + g = m2; + else if (hue < 240) + g = m1+(m2-m1)*(240-hue)/60; + else + g = m1; + + hue = *h-120; + while (hue > 360) + hue -= 360; + while (hue < 0) + hue += 360; + + if (hue < 60) + b = m1+(m2-m1)*hue/60; + else if (hue < 180) + b = m2; + else if (hue < 240) + b = m1+(m2-m1)*(240-hue)/60; + else + b = m1; + + *h = r; + *l = g; + *s = b; + } +} + +static void +_color_shade (const CairoColorRGB *a, float k, CairoColorRGB *b) +{ + double red; + double green; + double blue; + + red = a->r; + green = a->g; + blue = a->b; + + if (k == 1.0) + { + b->r = red; + b->g = green; + b->b = blue; + return; + } + + _color_rgb_to_hls (&red, &green, &blue); + + green *= k; + if (green > 1.0) + green = 1.0; + else if (green < 0.0) + green = 0.0; + + blue *= k; + if (blue > 1.0) + blue = 1.0; + else if (blue < 0.0) + blue = 0.0; + + _color_hls_to_rgb (&red, &green, &blue); + + b->r = red; + b->g = green; + b->b = blue; +} + static void draw (GtkWidget* button, cairo_t *cr) { @@ -731,18 +943,43 @@ draw (GtkWidget* button, cairo_t *cr) cairo_surface_t* surf = NULL; cairo_t* cr_surf = NULL; - //double INNER_START[] = {229.0f/255.0f, 223.0f/255.0f, 215.0f/255.0f, 1.0f}; - //double INNER_END[] = {183.0f / 255.0f, 178.0f / 255.0f, 172.0f / 255.0f, 1.0f}; - double MIDDLE_END[] = {61.0f / 255.0f, 60.0f / 255.0f, 57.0f / 255.0f, 1.0f}; - double MIDDLE_START[] = {94.0f / 255.0f,93.0f / 255.0f, 90.0f / 255.0f,1.0f}; - double OUTER_END[] = {36.0f / 255.0f, 35.0f / 255.0f, 33.0f / 255.0f, 1.0f}; - double OUTER_START[] = {123.0f / 255.0f, 123.0f / 255.0f, 120.0f / 255.0f, 1.0f}; - double BUTTON_END[] = {252.0f / 255.0f, 251.0f / 255.0f, 251.0f / 255.0f,1.0f}; - double BUTTON_START[] = {186.0f / 255.0f,180.0f / 255.0f, 170.0f / 255.0f, 1.0f}; - double BUTTON_SHADOW[] = {0.0f / 255.0f, 0.0f / 255.0f, 0.0f / 255.0f, 0.75f}; - double INNER_COMPRESSED_START[] = {61.0f / 255.0f, 60.0f / 255.0f, 57.0f / 255.0f, 1.0f}; - double INNER_COMPRESSED_END[] = {36.0f / 255.0f, 35.0f / 255.0f, 33.0f / 255.0f, 1.0f}; - + GtkStyle *style; + + CairoColorRGB bg_normal, fg_normal; + CairoColorRGB color_inner[2], color_middle[2], color_outer[2], color_button[3], color_inner_compressed[2]; + + style = gtk_widget_get_style (button); + + bg_normal.r = style->bg[0].red/65535.0; + bg_normal.g = style->bg[0].green/65535.0; + bg_normal.b = style->bg[0].blue/65535.0; + + fg_normal.r = style->fg[0].red/65535.0; + fg_normal.g = style->fg[0].green/65535.0; + fg_normal.b = style->fg[0].blue/65535.0; + + _color_shade (&bg_normal, INNER_START_SHADE, &color_inner[0]); + _color_shade (&bg_normal, INNER_END_SHADE, &color_inner[1]); + _color_shade (&bg_normal, MIDDLE_START_SHADE, &color_middle[0]); + _color_shade (&bg_normal, MIDDLE_END_SHADE, &color_middle[1]); + _color_shade (&bg_normal, OUTER_START_SHADE, &color_outer[0]); + _color_shade (&bg_normal, OUTER_END_SHADE, &color_outer[1]); + _color_shade (&fg_normal, BUTTON_START_SHADE, &color_button[0]); + _color_shade (&fg_normal, BUTTON_END_SHADE, &color_button[1]); + _color_shade (&bg_normal, BUTTON_SHADOW_SHADE, &color_button[2]); + _color_shade (&bg_normal, INNER_COMPRESSED_START_SHADE, &color_inner_compressed[0]); + _color_shade (&bg_normal, INNER_COMPRESSED_END_SHADE, &color_inner_compressed[1]); + + double MIDDLE_END[] = {color_middle[0].r, color_middle[0].g, color_middle[0].b, 1.0f}; + double MIDDLE_START[] = {color_middle[1].r, color_middle[1].g, color_middle[1].b, 1.0f}; + double OUTER_END[] = {color_outer[0].r, color_outer[0].g, color_outer[0].b, 1.0f}; + double OUTER_START[] = {color_outer[1].r, color_outer[1].g, color_outer[1].b, 1.0f}; + double BUTTON_END[] = {color_button[0].r, color_button[0].g, color_button[0].b, 1.0f}; + double BUTTON_START[] = {color_button[1].r, color_button[1].g, color_button[1].b, 1.0f}; + double BUTTON_SHADOW[] = {color_button[2].r, color_button[2].g, color_button[2].b, 0.75f}; + double INNER_COMPRESSED_END[] = {color_inner_compressed[1].r, color_inner_compressed[1].g, color_inner_compressed[1].b, 1.0f}; + double INNER_COMPRESSED_START[] = {color_inner_compressed[0].r, color_inner_compressed[0].g, color_inner_compressed[0].b, 1.0f}; + // prev/next-background draw_gradient (cr, X, -- cgit v1.2.3