aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Makefile.am4
-rw-r--r--src/metadata-widget.c19
-rw-r--r--src/play-button.c770
-rw-r--r--src/play-button.h51
-rw-r--r--src/transport-widget.c133
5 files changed, 874 insertions, 103 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 327fcbb..79ba7d2 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -13,13 +13,15 @@ libsoundmenu_la_SOURCES = \
transport-widget.h \
metadata-widget.c \
metadata-widget.h \
+ play-button.c \
+ play-button.h \
indicator-sound.c \
title-widget.c \
title-widget.h \
dbus-shared-names.h \
sound-service-client.h
-libsoundmenu_la_CFLAGS = $(APPLET_CFLAGS) -Wall -Werror -DG_LOG_DOMAIN=\"Indicator-Sound\"
+libsoundmenu_la_CFLAGS = $(APPLET_CFLAGS) -Wall -DG_LOG_DOMAIN=\"Indicator-Sound\"
libsoundmenu_la_LIBADD = $(APPLET_LIBS)
libsoundmenu_la_LDFLAGS = -module -avoid-version
diff --git a/src/metadata-widget.c b/src/metadata-widget.c
index ce3bcd1..bb9c8a8 100644
--- a/src/metadata-widget.c
+++ b/src/metadata-widget.c
@@ -47,6 +47,8 @@ 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_widget_expose_event(GtkWidget* widget, GdkEventExpose* event);
+
// keyevent consumers
static gboolean metadata_widget_button_press_event (GtkWidget *menuitem,
GdkEventButton *event);
@@ -74,7 +76,7 @@ metadata_widget_class_init (MetadataWidgetClass *klass)
widget_class->button_press_event = metadata_widget_button_press_event;
widget_class->button_release_event = metadata_widget_button_release_event;
-
+ widget_class->expose_event = metadata_widget_expose_event;
g_type_class_add_private (klass, sizeof (MetadataWidgetPrivate));
gobject_class->dispose = metadata_widget_dispose;
@@ -111,7 +113,7 @@ metadata_widget_init (MetadataWidget *self)
gtk_misc_set_alignment(GTK_MISC(artist), (gfloat)0, (gfloat)0);
gtk_label_set_width_chars(GTK_LABEL(artist), 20);
- gtk_label_set_ellipsize(GTK_LABEL(artist), PANGO_ELLIPSIZE_END);
+ gtk_label_set_ellipsize(GTK_LABEL(artist), PANGO_ELLIPSIZE_MIDDLE);
priv->artist_label = artist;
// Style it up.
style_artist_text(self);
@@ -122,7 +124,7 @@ metadata_widget_init (MetadataWidget *self)
DBUSMENU_METADATA_MENUITEM_TEXT_TITLE));
gtk_misc_set_alignment(GTK_MISC(piece), (gfloat)0, (gfloat)0);
gtk_label_set_width_chars(GTK_LABEL(piece), 16);
- gtk_label_set_ellipsize(GTK_LABEL(piece), PANGO_ELLIPSIZE_END);
+ gtk_label_set_ellipsize(GTK_LABEL(piece), PANGO_ELLIPSIZE_MIDDLE);
priv->piece_label = piece;
// Style it up.
style_title_text(self);
@@ -133,7 +135,7 @@ metadata_widget_init (MetadataWidget *self)
DBUSMENU_METADATA_MENUITEM_TEXT_ALBUM));
gtk_misc_set_alignment(GTK_MISC(container), (gfloat)0, (gfloat)0);
gtk_label_set_width_chars(GTK_LABEL(container), 20);
- gtk_label_set_ellipsize(GTK_LABEL(container), PANGO_ELLIPSIZE_END);
+ gtk_label_set_ellipsize(GTK_LABEL(container), PANGO_ELLIPSIZE_MIDDLE);
priv->container_label = container;
// Style it up.
style_album_text(self);
@@ -152,6 +154,15 @@ metadata_widget_init (MetadataWidget *self)
}
+static gboolean
+metadata_widget_expose_event(GtkWidget* widget, GdkEventExpose* event)
+{
+ MetadataWidgetPrivate * priv = METADATA_WIDGET_GET_PRIVATE(widget);
+
+ gtk_container_propagate_expose(GTK_CONTAINER(widget), priv->hbox, event);
+ return TRUE;
+}
+
static void
metadata_widget_dispose (GObject *object)
{
diff --git a/src/play-button.c b/src/play-button.c
new file mode 100644
index 0000000..136f25d
--- /dev/null
+++ b/src/play-button.c
@@ -0,0 +1,770 @@
+/*
+Copyright 2010 Canonical Ltd.
+
+Authors:
+ Conor Curran <conor.curran@canonical.com>
+ Mirco Müller <mirco.mueller@canonical.com>
+
+This program is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 3, as published
+by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranties of
+MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
+PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program. If not, see <http://www.gnu.org/licenses/>.
+
+Uses code from ctk
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <math.h>
+#include "play-button.h"
+
+#define RECT_WIDTH 130.0f
+#define Y 15.0f
+#define X 22.0f
+#define INNER_RADIUS 12.5
+#define MIDDLE_RADIUS 13.5f
+#define OUTER_RADIUS 14.5f
+#define CIRCLE_RADIUS 19.0f
+#define PREV_WIDTH 25.0f
+#define PREV_HEIGHT 17.0f
+#define NEXT_WIDTH 25.0f //PREV_WIDTH
+#define NEXT_HEIGHT 17.0f //PREV_HEIGHT
+#define TRI_WIDTH 11.0f
+#define TRI_HEIGHT 13.0f
+#define TRI_OFFSET 6.0f
+#define PREV_X 20.0f
+#define PREV_Y 21.0f
+#define NEXT_X 98.0f
+#define NEXT_Y 21.0f //prev_y
+#define PAUSE_WIDTH 21.0f
+#define PAUSE_HEIGHT 27.0f
+#define BAR_WIDTH 4.5f
+#define BAR_HEIGHT 24.0f
+#define BAR_OFFSET 10.0f
+#define PAUSE_X 62.0f
+#define PAUSE_Y 15.0f
+
+typedef struct _PlayButtonPrivate PlayButtonPrivate;
+
+struct _PlayButtonPrivate
+{
+ GdkColor background_colour_fg;
+ GdkColor background_colour_bg_dark;
+ GdkColor background_colour_bg_light;
+ GdkColor foreground_colour_fg;
+ GdkColor foreground_colour_bg;
+};
+
+#define PLAY_BUTTON_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), PLAY_BUTTON_TYPE, PlayButtonPrivate))
+
+/* Gobject boiler plate */
+static void play_button_class_init (PlayButtonClass *klass);
+static void play_button_init (PlayButton *self);
+static void play_button_dispose (GObject *object);
+static void play_button_finalize (GObject *object);
+
+static gboolean play_button_expose (GtkWidget *button, GdkEventExpose *event);
+static void draw (GtkWidget* button, cairo_t *cr);
+
+G_DEFINE_TYPE (PlayButton, play_button, GTK_TYPE_DRAWING_AREA);
+
+/// internal helper functions //////////////////////////////////////////////////
+
+static double
+_align (double val)
+{
+ double fract = val - (int) val;
+
+ if (fract != 0.5f)
+ return (double) ((int) val + 0.5f);
+ else
+ return val;
+}
+
+static inline void
+_blurinner (guchar* pixel,
+ gint* zR,
+ gint* zG,
+ gint* zB,
+ gint* zA,
+ gint alpha,
+ gint aprec,
+ gint zprec)
+{
+ gint R;
+ gint G;
+ gint B;
+ guchar A;
+
+ R = *pixel;
+ G = *(pixel + 1);
+ B = *(pixel + 2);
+ A = *(pixel + 3);
+
+ *zR += (alpha * ((R << zprec) - *zR)) >> aprec;
+ *zG += (alpha * ((G << zprec) - *zG)) >> aprec;
+ *zB += (alpha * ((B << zprec) - *zB)) >> aprec;
+ *zA += (alpha * ((A << zprec) - *zA)) >> aprec;
+
+ *pixel = *zR >> zprec;
+ *(pixel + 1) = *zG >> zprec;
+ *(pixel + 2) = *zB >> zprec;
+ *(pixel + 3) = *zA >> zprec;
+}
+
+static inline void
+_blurrow (guchar* pixels,
+ gint width,
+ gint height,
+ gint channels,
+ gint line,
+ gint alpha,
+ gint aprec,
+ gint zprec)
+{
+ gint zR;
+ gint zG;
+ gint zB;
+ gint zA;
+ gint index;
+ guchar* scanline;
+
+ scanline = &(pixels[line * width * channels]);
+
+ zR = *scanline << zprec;
+ zG = *(scanline + 1) << zprec;
+ zB = *(scanline + 2) << zprec;
+ zA = *(scanline + 3) << zprec;
+
+ for (index = 0; index < width; index ++)
+ _blurinner (&scanline[index * channels],
+ &zR,
+ &zG,
+ &zB,
+ &zA,
+ alpha,
+ aprec,
+ zprec);
+
+ for (index = width - 2; index >= 0; index--)
+ _blurinner (&scanline[index * channels],
+ &zR,
+ &zG,
+ &zB,
+ &zA,
+ alpha,
+ aprec,
+ zprec);
+}
+
+static inline void
+_blurcol (guchar* pixels,
+ gint width,
+ gint height,
+ gint channels,
+ gint x,
+ gint alpha,
+ gint aprec,
+ gint zprec)
+{
+ gint zR;
+ gint zG;
+ gint zB;
+ gint zA;
+ gint index;
+ guchar* ptr;
+
+ ptr = pixels;
+
+ ptr += x * channels;
+
+ zR = *((guchar*) ptr ) << zprec;
+ zG = *((guchar*) ptr + 1) << zprec;
+ zB = *((guchar*) ptr + 2) << zprec;
+ zA = *((guchar*) ptr + 3) << zprec;
+
+ for (index = width; index < (height - 1) * width; index += width)
+ _blurinner ((guchar*) &ptr[index * channels],
+ &zR,
+ &zG,
+ &zB,
+ &zA,
+ alpha,
+ aprec,
+ zprec);
+
+ for (index = (height - 2) * width; index >= 0; index -= width)
+ _blurinner ((guchar*) &ptr[index * channels],
+ &zR,
+ &zG,
+ &zB,
+ &zA,
+ alpha,
+ aprec,
+ zprec);
+}
+
+void
+_expblur (guchar* pixels,
+ gint width,
+ gint height,
+ gint channels,
+ gint radius,
+ gint aprec,
+ gint zprec)
+{
+ gint alpha;
+ gint row = 0;
+ gint col = 0;
+
+ if (radius < 1)
+ return;
+
+ // calculate the alpha such that 90% of
+ // the kernel is within the radius.
+ // (Kernel extends to infinity)
+ alpha = (gint) ((1 << aprec) * (1.0f - expf (-2.3f / (radius + 1.f))));
+
+ for (; row < height; row++)
+ _blurrow (pixels,
+ width,
+ height,
+ channels,
+ row,
+ alpha,
+ aprec,
+ zprec);
+
+ for(; col < width; col++)
+ _blurcol (pixels,
+ width,
+ height,
+ channels,
+ col,
+ alpha,
+ aprec,
+ zprec);
+
+ return;
+}
+
+void
+_surface_blur (cairo_surface_t* surface,
+ guint radius)
+{
+ guchar* pixels;
+ guint width;
+ guint height;
+ cairo_format_t format;
+
+ // before we mess with the surface execute any pending drawing
+ cairo_surface_flush (surface);
+
+ pixels = cairo_image_surface_get_data (surface);
+ width = cairo_image_surface_get_width (surface);
+ height = cairo_image_surface_get_height (surface);
+ format = cairo_image_surface_get_format (surface);
+
+ switch (format)
+ {
+ case CAIRO_FORMAT_ARGB32:
+ _expblur (pixels, width, height, 4, radius, 16, 7);
+ break;
+
+ case CAIRO_FORMAT_RGB24:
+ _expblur (pixels, width, height, 3, radius, 16, 7);
+ break;
+
+ case CAIRO_FORMAT_A8:
+ _expblur (pixels, width, height, 1, radius, 16, 7);
+ break;
+
+ default :
+ // do nothing
+ break;
+ }
+
+ // inform cairo we altered the surfaces contents
+ cairo_surface_mark_dirty (surface);
+}
+
+/// GObject functions //////////////////////////////////////////////////////////
+
+static void
+play_button_class_init (PlayButtonClass *klass)
+{
+
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass* widget_class = GTK_WIDGET_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (PlayButtonPrivate));
+
+ widget_class->expose_event = play_button_expose;
+
+ gobject_class->dispose = play_button_dispose;
+ gobject_class->finalize = play_button_finalize;
+}
+
+static void
+play_button_init (PlayButton *self)
+{
+ gtk_widget_set_size_request(GTK_WIDGET(self), 200, 80);
+}
+
+static void
+play_button_dispose (GObject *object)
+{
+ G_OBJECT_CLASS (play_button_parent_class)->dispose (object);
+}
+
+static void
+play_button_finalize (GObject *object)
+{
+ G_OBJECT_CLASS (play_button_parent_class)->finalize (object);
+}
+
+static gboolean
+play_button_expose (GtkWidget *button, GdkEventExpose *event)
+{
+ cairo_t *cr;
+ cr = gdk_cairo_create (button->window);
+
+ cairo_rectangle (cr,
+ event->area.x, event->area.y,
+ event->area.width, event->area.height);
+
+ cairo_clip(cr);
+ draw (button, cr);
+ cairo_destroy (cr);
+ return FALSE;
+}
+
+
+void
+play_button_set_style(GtkWidget* button, GtkStyle* style)
+{
+ PlayButtonPrivate* priv = PLAY_BUTTON_GET_PRIVATE(button);
+ priv->background_colour_fg = style->fg[GTK_STATE_NORMAL];
+ priv->background_colour_bg_dark = style->bg[GTK_STATE_NORMAL];
+ priv->background_colour_bg_light = style->base[GTK_STATE_NORMAL];
+ priv->foreground_colour_fg = style->fg[GTK_STATE_PRELIGHT];
+ priv->foreground_colour_bg = style->bg[GTK_STATE_NORMAL];
+}
+
+static void
+draw_gradient (cairo_t* cr,
+ double x,
+ double y,
+ double w,
+ double r,
+ double* rgba_start,
+ double* rgba_end)
+{
+ cairo_pattern_t* pattern = NULL;
+
+ cairo_move_to (cr, x, y);
+ cairo_line_to (cr, x + w - 2.0f * r, y);
+ cairo_arc (cr,
+ x + w - 2.0f * r,
+ y + r,
+ r,
+ -90.0f * G_PI / 180.0f,
+ 90.0f * G_PI / 180.0f);
+ cairo_line_to (cr, x, y + 2.0f * r);
+ cairo_arc (cr,
+ x,
+ y + r,
+ r,
+ 90.0f * G_PI / 180.0f,
+ 270.0f * G_PI / 180.0f);
+ cairo_close_path (cr);
+
+ pattern = cairo_pattern_create_linear (x, y, x, y + 2.0f * r);
+ cairo_pattern_add_color_stop_rgba (pattern,
+ 0.0f,
+ rgba_start[0],
+ rgba_start[1],
+ rgba_start[2],
+ rgba_start[3]);
+ cairo_pattern_add_color_stop_rgba (pattern,
+ 1.0f,
+ rgba_end[0],
+ rgba_end[1],
+ rgba_end[2],
+ rgba_end[3]);
+ cairo_set_source (cr, pattern);
+ cairo_fill (cr);
+ cairo_pattern_destroy (pattern);
+}
+
+static void
+draw_circle (cairo_t* cr,
+ double x,
+ double y,
+ double r,
+ double* rgba_start,
+ double* rgba_end)
+{
+ cairo_pattern_t* pattern = NULL;
+
+ cairo_move_to (cr, x, y);
+ cairo_arc (cr,
+ x + r,
+ y + r,
+ r,
+ 0.0f * G_PI / 180.0f,
+ 360.0f * G_PI / 180.0f);
+
+ pattern = cairo_pattern_create_linear (x, y, x, y + 2.0f * r);
+ cairo_pattern_add_color_stop_rgba (pattern,
+ 0.0f,
+ rgba_start[0],
+ rgba_start[1],
+ rgba_start[2],
+ rgba_start[3]);
+ cairo_pattern_add_color_stop_rgba (pattern,
+ 1.0f,
+ rgba_end[0],
+ rgba_end[1],
+ rgba_end[2],
+ rgba_end[3]);
+ cairo_set_source (cr, pattern);
+ cairo_fill (cr);
+ cairo_pattern_destroy (pattern);
+}
+
+static void
+_setup (cairo_t** cr,
+ cairo_surface_t** surf,
+ gint width,
+ gint height)
+{
+ if (!cr || !surf)
+ return;
+
+ *surf = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
+ *cr = cairo_create (*surf);
+ cairo_scale (*cr, 1.0f, 1.0f);
+ cairo_set_operator (*cr, CAIRO_OPERATOR_CLEAR);
+ cairo_paint (*cr);
+ cairo_set_operator (*cr, CAIRO_OPERATOR_OVER);
+}
+
+static void
+_mask_prev (cairo_t* cr,
+ double x,
+ double y,
+ double tri_width,
+ double tri_height,
+ double tri_offset)
+{
+ if (!cr)
+ return;
+
+ cairo_move_to (cr, x, y + tri_height / 2.0f);
+ cairo_line_to (cr, x + tri_width, y);
+ cairo_line_to (cr, x + tri_width, y + tri_height);
+ x += tri_offset;
+ cairo_move_to (cr, x, y + tri_height / 2.0f);
+ cairo_line_to (cr, x + tri_width, y);
+ cairo_line_to (cr, x + tri_width, y + tri_height);
+ x -= tri_offset;
+ cairo_rectangle (cr, x, y, 2.5f, tri_height);
+ cairo_close_path (cr);
+}
+
+static void
+_mask_next (cairo_t* cr,
+ double x,
+ double y,
+ double tri_width,
+ double tri_height,
+ double tri_offset)
+{
+ if (!cr)
+ return;
+
+ cairo_move_to (cr, x, y);
+ cairo_line_to (cr, x + tri_width, y + tri_height / 2.0f);
+ cairo_line_to (cr, x, y + tri_height);
+ x += tri_offset;
+ cairo_move_to (cr, x, y);
+ cairo_line_to (cr, x + tri_width, y + tri_height / 2.0f);
+ cairo_line_to (cr, x, y + tri_height);
+ x -= tri_offset;
+ x += 2.0f * tri_width - tri_offset - 1.0f;
+ cairo_rectangle (cr, x, y, 2.5f, tri_height);
+
+ cairo_close_path (cr);
+}
+
+static void
+_mask_pause (cairo_t* cr,
+ double x,
+ double y,
+ double bar_width,
+ double bar_height,
+ double bar_offset)
+{
+ if (!cr)
+ return;
+
+ cairo_set_line_width (cr, bar_width);
+ cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
+
+ x += bar_width;
+ y += bar_width;
+ cairo_move_to (cr, x, y);
+ cairo_line_to (cr, x, y + bar_height);
+ cairo_move_to (cr, x + bar_offset, y);
+ cairo_line_to (cr, x + bar_offset, y + bar_height);
+
+}
+
+static void
+_fill (cairo_t* cr,
+ double x_start,
+ double y_start,
+ double x_end,
+ double y_end,
+ double* rgba_start,
+ double* rgba_end,
+ gboolean stroke)
+{
+ cairo_pattern_t* pattern = NULL;
+
+ if (!cr || !rgba_start || !rgba_end)
+ return;
+
+ pattern = cairo_pattern_create_linear (x_start, y_start, x_end, y_end);
+ cairo_pattern_add_color_stop_rgba (pattern,
+ 0.0f,
+ rgba_start[0],
+ rgba_start[1],
+ rgba_start[2],
+ rgba_start[3]);
+ cairo_pattern_add_color_stop_rgba (pattern,
+ 1.0f,
+ rgba_end[0],
+ rgba_end[1],
+ rgba_end[2],
+ rgba_end[3]);
+ cairo_set_source (cr, pattern);
+ if (stroke)
+ cairo_stroke (cr);
+ else
+ cairo_fill (cr);
+ cairo_pattern_destroy (pattern);
+}
+
+static void
+_finalize (cairo_t* cr,
+ cairo_t** cr_surf,
+ cairo_surface_t** surf,
+ double x,
+ double y)
+{
+ if (!cr || !cr_surf || !surf)
+ return;
+
+ cairo_set_source_surface (cr, *surf, x, y);
+ cairo_paint (cr);
+ cairo_surface_destroy (*surf);
+ cairo_destroy (*cr_surf);
+}
+
+static void
+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_START[] = {61.0f / 255.0f, 60.0f / 255.0f, 57.0f / 255.0f, 1.0f};
+ double MIDDLE_END[] = {94.0f / 255.0f,93.0f / 255.0f, 90.0f / 255.0f,1.0f};
+ double OUTER_START[] = {36.0f / 255.0f, 35.0f / 255.0f, 33.0f / 255.0f, 1.0f};
+ double OUTER_END[] = {123.0f / 255.0f, 123.0f / 255.0f, 120.0f / 255.0f, 1.0f};
+ double BUTTON_START[] = {252.0f / 255.0f, 251.0f / 255.0f, 251.0f / 255.0f,1.0f};
+ double BUTTON_END[] = {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};
+
+
+ // prev/next-background
+ draw_gradient (cr,
+ X,
+ Y,
+ RECT_WIDTH,
+ OUTER_RADIUS,
+ OUTER_START,
+ OUTER_END);
+ draw_gradient (cr,
+ X,
+ Y + 1,
+ RECT_WIDTH - 2,
+ MIDDLE_RADIUS,
+ MIDDLE_START,
+ MIDDLE_END);
+ draw_gradient (cr,
+ X,
+ Y + 2,
+ RECT_WIDTH - 4,
+ INNER_RADIUS,
+ INNER_START,
+ INNER_END);
+
+ // play/pause-background
+ draw_circle (cr,
+ X + RECT_WIDTH / 2.0f - 2.0f * OUTER_RADIUS - 4.5f,
+ Y - ((CIRCLE_RADIUS - OUTER_RADIUS)),
+ CIRCLE_RADIUS,
+ OUTER_START,
+ OUTER_END);
+ draw_circle (cr,
+ X + RECT_WIDTH / 2.0f - 2.0f * OUTER_RADIUS - 4.5f + 1.0f,
+ Y - ((CIRCLE_RADIUS - OUTER_RADIUS)) + 1.0f,
+ CIRCLE_RADIUS - 1,
+ MIDDLE_START,
+ MIDDLE_END);
+ draw_circle (cr,
+ X + RECT_WIDTH / 2.0f - 2.0f * OUTER_RADIUS - 4.5f + 2.0f,
+ Y - ((CIRCLE_RADIUS - OUTER_RADIUS)) + 2.0f,
+ CIRCLE_RADIUS - 2.0f,
+ INNER_START,
+ INNER_END);
+
+ // draw previous-button drop-shadow
+ _setup (&cr_surf, &surf, PREV_WIDTH, PREV_HEIGHT);
+ _mask_prev (cr_surf,
+ (PREV_WIDTH - (2.0f * TRI_WIDTH - TRI_OFFSET)) / 2.0f,
+ (PREV_HEIGHT - TRI_HEIGHT) / 2.0f,
+ TRI_WIDTH,
+ TRI_HEIGHT,
+ TRI_OFFSET);
+ _fill (cr_surf,
+ (PREV_WIDTH - (2.0f * TRI_WIDTH - TRI_OFFSET)) / 2.0f,
+ (PREV_HEIGHT - TRI_HEIGHT) / 2.0f,
+ (PREV_WIDTH - (2.0f * TRI_WIDTH - TRI_OFFSET)) / 2.0f,
+ (double) TRI_HEIGHT,
+ BUTTON_SHADOW,
+ BUTTON_SHADOW,
+ FALSE);
+ _surface_blur (surf, 1);
+ _finalize (cr, &cr_surf, &surf, PREV_X, PREV_Y + 1.0f);
+
+ // draw previous-button
+ _setup (&cr_surf, &surf, PREV_WIDTH, PREV_HEIGHT);
+ _mask_prev (cr_surf,
+ (PREV_WIDTH - (2.0f * TRI_WIDTH - TRI_OFFSET)) / 2.0f,
+ (PREV_HEIGHT - TRI_HEIGHT) / 2.0f,
+ TRI_WIDTH,
+ TRI_HEIGHT,
+ TRI_OFFSET);
+ _fill (cr_surf,
+ (PREV_WIDTH - (2.0f * TRI_WIDTH - TRI_OFFSET)) / 2.0f,
+ (PREV_HEIGHT - TRI_HEIGHT) / 2.0f,
+ (PREV_WIDTH - (2.0f * TRI_WIDTH - TRI_OFFSET)) / 2.0f,
+ (double) TRI_HEIGHT,
+ BUTTON_START,
+ BUTTON_END,
+ FALSE);
+ _finalize (cr, &cr_surf, &surf, PREV_X, PREV_Y);
+
+ // draw next-button drop-shadow
+ _setup (&cr_surf, &surf, NEXT_WIDTH, NEXT_HEIGHT);
+ _mask_next (cr_surf,
+ (NEXT_WIDTH - (2.0f * TRI_WIDTH - TRI_OFFSET)) / 2.0f,
+ (NEXT_HEIGHT - TRI_HEIGHT) / 2.0f,
+ TRI_WIDTH,
+ TRI_HEIGHT,
+ TRI_OFFSET);
+ _fill (cr_surf,
+ (NEXT_WIDTH - (2.0f * TRI_WIDTH - TRI_OFFSET)) / 2.0f,
+ (NEXT_HEIGHT - TRI_HEIGHT) / 2.0f,
+ (NEXT_WIDTH - (2.0f * TRI_WIDTH - TRI_OFFSET)) / 2.0f,
+ (double) TRI_HEIGHT,
+ BUTTON_SHADOW,
+ BUTTON_SHADOW,
+ FALSE);
+ _surface_blur (surf, 1);
+ _finalize (cr, &cr_surf, &surf, NEXT_X, NEXT_Y + 1.0f);
+
+ // draw next-button
+ _setup (&cr_surf, &surf, NEXT_WIDTH, NEXT_HEIGHT);
+ _mask_next (cr_surf,
+ (NEXT_WIDTH - (2.0f * TRI_WIDTH - TRI_OFFSET)) / 2.0f,
+ (NEXT_HEIGHT - TRI_HEIGHT) / 2.0f,
+ TRI_WIDTH,
+ TRI_HEIGHT,
+ TRI_OFFSET);
+ _fill (cr_surf,
+ (NEXT_WIDTH - (2.0f * TRI_WIDTH - TRI_OFFSET)) / 2.0f,
+ (NEXT_HEIGHT - TRI_HEIGHT) / 2.0f,
+ (NEXT_WIDTH - (2.0f * TRI_WIDTH - TRI_OFFSET)) / 2.0f,
+ (double) TRI_HEIGHT,
+ BUTTON_START,
+ BUTTON_END,
+ FALSE);
+ _finalize (cr, &cr_surf, &surf, NEXT_X, NEXT_Y);
+
+ // draw pause-button drop-shadow
+ _setup (&cr_surf, &surf, PAUSE_WIDTH, PAUSE_HEIGHT);
+ _mask_pause (cr_surf,
+ (PAUSE_WIDTH - (2.0f * BAR_WIDTH + BAR_OFFSET)) / 2.0f,
+ (PAUSE_HEIGHT - BAR_HEIGHT) / 2.0f,
+ BAR_WIDTH,
+ BAR_HEIGHT - 2.0f * BAR_WIDTH,
+ BAR_OFFSET);
+ _fill (cr_surf,
+ (PAUSE_WIDTH - (2.0f * BAR_WIDTH + BAR_OFFSET)) / 2.0f,
+ (PAUSE_HEIGHT - BAR_HEIGHT) / 2.0f,
+ (PAUSE_WIDTH - (2.0f * BAR_WIDTH + BAR_OFFSET)) / 2.0f,
+ (double) BAR_HEIGHT,
+ BUTTON_SHADOW,
+ BUTTON_SHADOW,
+ TRUE);
+ _surface_blur (surf, 1);
+ _finalize (cr, &cr_surf, &surf, PAUSE_X, PAUSE_Y + 1.0f);
+
+ // draw pause-button
+ _setup (&cr_surf, &surf, PAUSE_WIDTH, PAUSE_HEIGHT);
+ _mask_pause (cr_surf,
+ (PAUSE_WIDTH - (2.0f * BAR_WIDTH + BAR_OFFSET)) / 2.0f,
+ (PAUSE_HEIGHT - BAR_HEIGHT) / 2.0f,
+ BAR_WIDTH,
+ BAR_HEIGHT - 2.0f * BAR_WIDTH,
+ BAR_OFFSET);
+ _fill (cr_surf,
+ (PAUSE_WIDTH - (2.0f * BAR_WIDTH + BAR_OFFSET)) / 2.0f,
+ (PAUSE_HEIGHT - BAR_HEIGHT) / 2.0f,
+ (PAUSE_WIDTH - (2.0f * BAR_WIDTH + BAR_OFFSET)) / 2.0f,
+ (double) BAR_HEIGHT,
+ BUTTON_START,
+ BUTTON_END,
+ TRUE);
+ _finalize (cr, &cr_surf, &surf, PAUSE_X, PAUSE_Y);
+}
+
+
+/**
+* play_button_new:
+* @returns: a new #PlayButton.
+**/
+GtkWidget*
+play_button_new()
+{
+
+ GtkWidget* widget = g_object_new(PLAY_BUTTON_TYPE, NULL);
+ gtk_widget_set_app_paintable (widget, TRUE);
+ return widget;
+}
+
diff --git a/src/play-button.h b/src/play-button.h
new file mode 100644
index 0000000..6c6aee3
--- /dev/null
+++ b/src/play-button.h
@@ -0,0 +1,51 @@
+/*
+Copyright 2010 Canonical Ltd.
+
+Authors:
+ Conor Curran <conor.curran@canonical.com>
+
+This program is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 3, as published
+by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranties of
+MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
+PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef __PLAY_BUTTON_H__
+#define __PLAY_BUTTON_H__
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define PLAY_BUTTON_TYPE (play_button_get_type ())
+#define PLAY_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PLAY_BUTTON_TYPE, PlayButton))
+#define PLAY_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PLAY_BUTTON_TYPE, PlayButtonClass))
+#define IS_PLAY_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PLAY_BUTTON_TYPE))
+#define IS_PLAY_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PLAY_BUTTON_TYPE))
+#define PLAY_BUTTON_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PLAY_BUTTON_TYPE, PlayButtonClass))
+
+typedef struct _PlayButton PlayButton;
+typedef struct _PlayButtonClass PlayButtonClass;
+
+struct _PlayButtonClass {
+ GtkDrawingAreaClass parent_class;
+};
+
+struct _PlayButton {
+ GtkDrawingArea parent;
+};
+
+GType play_button_get_type (void);
+void play_button_set_style(GtkWidget* button, GtkStyle* style);
+GtkWidget* play_button_new();
+
+G_END_DECLS
+
+#endif
+
diff --git a/src/transport-widget.c b/src/transport-widget.c
index e7b8e4f..6d39a03 100644
--- a/src/transport-widget.c
+++ b/src/transport-widget.c
@@ -25,6 +25,8 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
#include "transport-widget.h"
#include "common-defs.h"
#include <gtk/gtk.h>
+#include "play-button.h"
+
static DbusmenuMenuitem* twin_item;
@@ -36,16 +38,6 @@ struct _TransportWidgetPrivate
GtkWidget* play_button;
};
-enum {
- PLAY,
- PAUSE,
- NEXT,
- PREVIOUS,
- LAST_SIGNAL
-};
-
-static guint signals[LAST_SIGNAL] = { 0 };
-
#define TRANSPORT_WIDGET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TRANSPORT_WIDGET_TYPE, TransportWidgetPrivate))
/* Gobject boiler plate */
@@ -53,26 +45,20 @@ static void transport_widget_class_init (TransportWidgetClass *klass);
static void transport_widget_init (TransportWidget *self);
static void transport_widget_dispose (GObject *object);
static void transport_widget_finalize (GObject *object);
+static gboolean transport_widget_expose_event(GtkWidget* widget, GdkEventExpose* event);
/* UI and dbusmenu callbacks */
static gboolean transport_widget_button_press_event (GtkWidget *menuitem,
GdkEventButton *event);
static gboolean transport_widget_button_release_event (GtkWidget *menuitem,
- GdkEventButton *event);
-static void transport_widget_play_clicked (GtkWidget* button,
- TransportWidget* self);
-
+ GdkEventButton *event);
static void transport_widget_property_update(DbusmenuMenuitem* item,
- gchar * property,
- GValue * value,
- gpointer userdata);
-// utility methods
-static gchar* transport_widget_toggle_play_label(gint state);
+ gchar * property,
+ GValue * value,
+ gpointer userdata);
G_DEFINE_TYPE (TransportWidget, transport_widget, GTK_TYPE_MENU_ITEM);
-
-
static void
transport_widget_class_init (TransportWidgetClass *klass)
{
@@ -82,45 +68,12 @@ transport_widget_class_init (TransportWidgetClass *klass)
menu_item_class->hide_on_activate = FALSE;
widget_class->button_press_event = transport_widget_button_press_event;
- widget_class->button_release_event = transport_widget_button_release_event;
-
+ widget_class->button_release_event = transport_widget_button_release_event;
+ widget_class->expose_event = transport_widget_expose_event;
g_type_class_add_private (klass, sizeof (TransportWidgetPrivate));
gobject_class->dispose = transport_widget_dispose;
gobject_class->finalize = transport_widget_finalize;
-
- signals[PLAY] = g_signal_new ("play",
- G_OBJECT_CLASS_TYPE (gobject_class),
- G_SIGNAL_RUN_FIRST,
- 0,
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
-
- signals[PAUSE] = g_signal_new ("pause",
- G_OBJECT_CLASS_TYPE (gobject_class),
- G_SIGNAL_RUN_FIRST,
- 0,
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
-
-
- signals[NEXT] = g_signal_new ("next",
- G_OBJECT_CLASS_TYPE (gobject_class),
- G_SIGNAL_RUN_FIRST,
- 0,
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
-
- signals[PREVIOUS] = g_signal_new ("previous",
- G_OBJECT_CLASS_TYPE (gobject_class),
- G_SIGNAL_RUN_FIRST,
- 0,
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
}
static void
@@ -129,19 +82,19 @@ transport_widget_init (TransportWidget *self)
g_debug("TransportWidget::transport_widget_init");
TransportWidgetPrivate * priv = TRANSPORT_WIDGET_GET_PRIVATE(self);
- GtkWidget *hbox;
+ GtkWidget* hbox;
hbox = gtk_hbox_new(TRUE, 2);
- gchar* symbol = transport_widget_toggle_play_label(dbusmenu_menuitem_property_get_int(twin_item, DBUSMENU_TRANSPORT_MENUITEM_PLAY_STATE));
- priv->play_button = gtk_button_new_with_label(symbol);
-
- gtk_box_pack_start (GTK_BOX (hbox), priv->play_button, FALSE, TRUE, 0);
+ GtkStyle* style = gtk_rc_get_style(GTK_WIDGET(self));
+
priv->hbox = hbox;
+ priv->play_button = play_button_new();
+ play_button_set_style(priv->play_button, style);
+
+ gtk_box_pack_start (GTK_BOX (priv->hbox), priv->play_button, FALSE, FALSE, 0);
g_signal_connect(G_OBJECT(twin_item), "property-changed", G_CALLBACK(transport_widget_property_update), self);
-
- g_signal_connect(priv->play_button, "clicked", G_CALLBACK(transport_widget_play_clicked), self);
gtk_container_add (GTK_CONTAINER (self), priv->hbox);
@@ -160,6 +113,15 @@ transport_widget_finalize (GObject *object)
G_OBJECT_CLASS (transport_widget_parent_class)->finalize (object);
}
+static gboolean
+transport_widget_expose_event(GtkWidget* widget, GdkEventExpose* event)
+{
+ //TransportWidgetPrivate * priv = TRANSPORT_WIDGET_GET_PRIVATE(widget);
+ //gtk_container_propagate_expose(GTK_CONTAINER(widget),priv->play_button, event);
+ return TRUE;
+}
+
+
/* keyevents */
static gboolean
transport_widget_button_press_event (GtkWidget *menuitem,
@@ -170,28 +132,17 @@ transport_widget_button_press_event (GtkWidget *menuitem,
return FALSE;
}
- TransportWidgetPrivate * priv = TRANSPORT_WIDGET_GET_PRIVATE(TRANSPORT_WIDGET(menuitem));
+ //TransportWidgetPrivate * priv = TRANSPORT_WIDGET_GET_PRIVATE(TRANSPORT_WIDGET(menuitem));
- gtk_widget_event (priv->hbox, (GdkEvent*)event);
- gboolean state = g_ascii_strcasecmp(gtk_button_get_label(GTK_BUTTON(priv->play_button)), ">") == 0;
-
- gtk_button_set_label(GTK_BUTTON(priv->play_button), transport_widget_toggle_play_label((gint)state));
- GValue value = {0};
- g_value_init(&value, G_TYPE_BOOLEAN);
- g_debug("TransportWidget::menu_press_event - going to send value %i", state);
-
- g_value_set_boolean(&value, state);
- dbusmenu_menuitem_handle_event (twin_item, "Transport state change", &value, 0);
+ //GValue value = {0};
+ //g_value_init(&value, G_TYPE_BOOLEAN);
+ //g_debug("TransportWidget::menu_press_event - going to send value %i", state);
+ //g_value_set_boolean(&value, state);
+ //dbusmenu_menuitem_handle_event (twin_item, "Transport state change", &value, 0);
return TRUE;
}
-static void
-transport_widget_play_clicked(GtkWidget* button,
- TransportWidget* self)
-{
- g_debug("Transport_widget_play_clicked");
-}
static gboolean
transport_widget_button_release_event (GtkWidget *menuitem,
@@ -201,9 +152,6 @@ transport_widget_button_release_event (GtkWidget *menuitem,
if(IS_TRANSPORT_WIDGET(menuitem) == FALSE){
return FALSE;
}
-
- TransportWidgetPrivate * priv = TRANSPORT_WIDGET_GET_PRIVATE(TRANSPORT_WIDGET(menuitem));
- gtk_widget_event (priv->hbox, (GdkEvent*)event);
return TRUE;
}
@@ -217,23 +165,12 @@ transport_widget_property_update(DbusmenuMenuitem* item, gchar* property,
GValue* value, gpointer userdata)
{
g_debug("transport_widget_update_state - with property %s", property);
- int update_value = g_value_get_int(value);
- g_debug("transport_widget_update_state - with value %i", update_value);
+ //int update_value = g_value_get_int(value);
+ //g_debug("transport_widget_update_state - with value %i", update_value);
- TransportWidget* bar = (TransportWidget*)userdata;
- TransportWidgetPrivate *priv = TRANSPORT_WIDGET_GET_PRIVATE(bar);
+ //TransportWidget* bar = (TransportWidget*)userdata;
+ //TransportWidgetPrivate *priv = TRANSPORT_WIDGET_GET_PRIVATE(bar);
- gtk_button_set_label(GTK_BUTTON(priv->play_button), transport_widget_toggle_play_label(update_value));
-}
-
-// will be needed for image swapping
-static gchar* transport_widget_toggle_play_label(int play_state)
-{
- gchar* label = ">";
- if(play_state == 1){
- label = "||";
- }
- return label;
}
/**