[gnome-panel/wip/applets/clock: 4/15] clock: rewrite ClockFace
- From: Alberts Muktupāvels <muktupavels src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-panel/wip/applets/clock: 4/15] clock: rewrite ClockFace
- Date: Tue, 11 Nov 2014 11:37:22 +0000 (UTC)
commit 40dc7e01c1920addf70c79b06e5a4ce983856e8a
Author: Alberts Muktupāvels <alberts muktupavels gmail com>
Date: Sat Nov 8 21:02:23 2014 +0200
clock: rewrite ClockFace
applets/clock/clock-face.c | 782 ++++++++++++++++++-----------------
applets/clock/clock-face.h | 77 ++--
applets/clock/clock-location-tile.c | 47 +--
applets/clock/clock-location-tile.h | 3 +-
applets/clock/clock.c | 2 +-
5 files changed, 449 insertions(+), 462 deletions(-)
---
diff --git a/applets/clock/clock-face.c b/applets/clock/clock-face.c
index 2e95b11..e636f07 100644
--- a/applets/clock/clock-face.c
+++ b/applets/clock/clock-face.c
@@ -1,466 +1,482 @@
-/**
- * clock.c
+/*
+ * Copyright (C) 2007 Peter Teichman
+ * Copyright (C) 2005-2006 Davyd Madeley
+ * Copyright (C) 2014 Alberts Muktupāvels
*
- * A GTK+ widget that implements a clock face
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
*
- * (c) 2007, Peter Teichman
- * (c) 2005-2006, Davyd Madeley
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY 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/>.
*
* Authors:
- * Davyd Madeley <davyd madeley id au>
- * Peter Teichman <peter novell com>
+ * Alberts Muktupāvels <alberts muktupavels gmail com>
+ * Davyd Madeley <davyd madeley id au>
+ * Peter Teichman <peter novell com>
*/
+#include <config.h>
#include <gtk/gtk.h>
#include <math.h>
-#include <time.h>
#include "clock.h"
#include "clock-face.h"
-#include "clock-location.h"
-#include "clock-utils.h"
-
-static GHashTable *pixbuf_cache = NULL;
-
-G_DEFINE_TYPE (ClockFace, clock_face, GTK_TYPE_WIDGET)
-
-static void clock_face_finalize (GObject *);
-static gboolean clock_face_draw (GtkWidget *clock,
- cairo_t *cr);
-static void clock_face_get_preferred_width (GtkWidget *this,
- gint *minimal_width,
- gint *natural_width);
-static void clock_face_get_preferred_height (GtkWidget *this,
- gint *minimal_height,
- gint *natural_height);
-static void clock_face_size_allocate (GtkWidget *clock,
- GtkAllocation *allocation);
-
-static void update_time_and_face (ClockFace *this,
- gboolean force_face_loading);
-static void clock_face_load_face (ClockFace *this,
- gint width, gint height);
-
-typedef enum {
- CLOCK_FACE_MORNING,
- CLOCK_FACE_DAY,
- CLOCK_FACE_EVENING,
- CLOCK_FACE_NIGHT,
- CLOCK_FACE_INVALID
-} ClockFaceTimeOfDay;
+
+typedef enum _ClockFaceType ClockFaceType;
struct _ClockFacePrivate
{
- GDateTime *time; /* the time on the clock face */
- int minute_offset; /* the offset of the minutes hand */
-
- ClockFaceSize size;
- ClockFaceTimeOfDay timeofday;
- ClockLocation *location;
- GdkPixbuf *face_pixbuf;
- GtkWidget *size_widget;
+ ClockLocation *location;
+ ClockTime *time;
+ gboolean show_seconds;
+
+ gint hour;
+ gint minute;
+ gint second;
};
-static void
-clock_face_class_init (ClockFaceClass *class)
+G_DEFINE_TYPE_WITH_PRIVATE (ClockFace,
+ clock_face,
+ GTK_TYPE_IMAGE)
+
+enum
{
- GObjectClass *obj_class;
- GtkWidgetClass *widget_class;
+ PROP_0,
+ PROP_LOCATION,
+ PROP_TIME,
+ PROP_SHOW_SECONDS,
+ N_PROPERTIES
+};
- obj_class = G_OBJECT_CLASS (class);
- widget_class = GTK_WIDGET_CLASS (class);
+static GParamSpec *object_properties[N_PROPERTIES] = { NULL, };
- /* GtkWidget signals */
- widget_class->draw = clock_face_draw;
- widget_class->get_preferred_width = clock_face_get_preferred_width;
- widget_class->get_preferred_height = clock_face_get_preferred_height;
- widget_class->size_allocate = clock_face_size_allocate;
+enum _ClockFaceType
+{
+ CLOCK_FACE_TYPE_MORNING,
+ CLOCK_FACE_TYPE_DAY,
+ CLOCK_FACE_TYPE_EVENING,
+ CLOCK_FACE_TYPE_NIGHT
+};
- /* GObject signals */
- obj_class->finalize = clock_face_finalize;
+static gboolean
+clock_face_draw (GtkWidget *widget,
+ cairo_t *cr)
+{
+ ClockFace *face;
+ gdouble hour_length;
+ gdouble minute_length;
+ gdouble second_length;
+ gdouble x;
+ gdouble y;
+ gdouble radius;
+ gdouble width;
+ gdouble height;
+
+ face = CLOCK_FACE (widget);
+
+ if (GTK_WIDGET_CLASS (clock_face_parent_class)->draw)
+ GTK_WIDGET_CLASS (clock_face_parent_class)->draw (widget, cr);
+
+ x = gtk_widget_get_allocated_width (widget) / 2;
+ y = gtk_widget_get_allocated_height (widget) / 2;
+ radius = MIN (x, y) - 5;
+
+ if (x * 2 >= 50) {
+ hour_length = 0.45;
+ minute_length = 0.6;
+ second_length = 0.65;
+ } else {
+ hour_length = 0.5;
+ minute_length = 0.7;
+ second_length = 0.8;
+ }
+
+ cairo_set_line_width (cr, 1);
+
+ /* hour hand:
+ * the hour hand is rotated 30 degrees (pi/6 r) per hour +
+ * 1/2 a degree (pi/360 r) per minute
+ */
+ width = x + radius * hour_length * sin (M_PI / 6 * face->priv->hour +
+ M_PI / 360 * face->priv->minute);
+ height = y + radius * hour_length * -cos (M_PI / 6 * face->priv->hour +
+ M_PI / 360 * face->priv->minute);
+
+ cairo_save (cr);
+ cairo_move_to (cr, x, y);
+ cairo_line_to (cr, width, height);
+ cairo_stroke (cr);
+ cairo_restore (cr);
+
+ /* minute hand:
+ * the minute hand is rotated 6 degrees (pi/30 r) per minute
+ */
+ width = x + radius * minute_length * sin (M_PI / 30 * face->priv->minute);
+ height = y + radius * minute_length * -cos (M_PI / 30 * face->priv->minute);
+
+ cairo_save (cr);
+ cairo_move_to (cr, x, y);
+ cairo_line_to (cr, width, height);
+ cairo_stroke (cr);
+ cairo_restore (cr);
+
+ /* second hand:
+ * operates identically to the minute hand
+ */
+ if (face->priv->show_seconds) {
+ width = x + radius * second_length * sin (M_PI / 30 * face->priv->second);
+ height = y + radius * second_length * -cos (M_PI / 30 * face->priv->second);
+
+ cairo_save (cr);
+ cairo_set_source_rgb (cr, 0.937, 0.161, 0.161); /* tango red */
+ cairo_move_to (cr, x, y);
+ cairo_line_to (cr, width, height);
+ cairo_stroke (cr);
+ cairo_restore (cr);
+ }
- g_type_class_add_private (obj_class, sizeof (ClockFacePrivate));
+ return FALSE;
}
-static void
-clock_face_init (ClockFace *this)
+/*
+ * FIXME: this should be a gsettings setting,
+ * currently hardcoded values:
+ * 1. morning : 7 - 9
+ * 2. day : 9 - 17
+ * 3. evening : 17 - 22
+ * 4. night : 22 - 7
+ */
+static ClockFaceType
+clock_face_get_type_from_hour (gint hour)
{
- ClockFacePrivate *priv;
-
- priv = this->priv = G_TYPE_INSTANCE_GET_PRIVATE (this, INTL_TYPE_CLOCK_FACE, ClockFacePrivate);
+ ClockFaceType type;
- priv->size = CLOCK_FACE_SMALL;
- priv->timeofday = CLOCK_FACE_INVALID;
- priv->location = NULL;
- priv->size_widget = NULL;
+ if (hour < 7)
+ type = CLOCK_FACE_TYPE_NIGHT;
+ else if (hour < 9)
+ type = CLOCK_FACE_TYPE_MORNING;
+ else if (hour < 17)
+ type = CLOCK_FACE_TYPE_DAY;
+ else if (hour < 22)
+ type = CLOCK_FACE_TYPE_EVENING;
+ else
+ type = CLOCK_FACE_TYPE_NIGHT;
- gtk_widget_set_has_window (GTK_WIDGET (this), FALSE);
+ return type;
}
-static gboolean
-clock_face_draw (GtkWidget *this, cairo_t *cr)
+static gchar *
+clock_face_image_from_type (ClockFaceType type)
{
- ClockFacePrivate *priv = CLOCK_FACE (this)->priv;
- int width, height;
- double x, y;
- double radius;
- int hours, minutes, seconds;
- /* Hand lengths as a multiple of the clock radius */
- double hour_length, min_length, sec_length;
-
- if (GTK_WIDGET_CLASS (clock_face_parent_class)->draw)
- GTK_WIDGET_CLASS (clock_face_parent_class)->draw (this, cr);
-
- if (priv->size == CLOCK_FACE_LARGE) {
- hour_length = 0.45;
- min_length = 0.6;
- sec_length = 0.65;
- } else {
- hour_length = 0.5;
- min_length = 0.7;
- sec_length = 0.8; /* not drawn currently */
- }
-
- width = gtk_widget_get_allocated_width (this);
- height = gtk_widget_get_allocated_width (this);
-
- x = width / 2;
- y = height / 2;
- radius = MIN (width / 2, height / 2) - 5;
-
- /* clock back */
- if (priv->face_pixbuf) {
- cairo_save (cr);
- gdk_cairo_set_source_pixbuf (cr, priv->face_pixbuf, 0, 0);
- cairo_paint (cr);
- cairo_restore (cr);
- }
-
- /* clock hands */
- hours = g_date_time_get_hour (priv->time);
- minutes = g_date_time_get_minute (priv->time) + priv->minute_offset;
- seconds = g_date_time_get_seconds (priv->time);
-
- cairo_set_line_width (cr, 1);
-
- /* hour hand:
- * the hour hand is rotated 30 degrees (pi/6 r) per hour +
- * 1/2 a degree (pi/360 r) per minute
- */
- cairo_save (cr);
- cairo_move_to (cr, x, y);
- cairo_line_to (cr, x + radius * hour_length * sin (M_PI / 6 * hours +
- M_PI / 360 * minutes),
- y + radius * hour_length * -cos (M_PI / 6 * hours +
- M_PI / 360 * minutes));
- cairo_stroke (cr);
- cairo_restore (cr);
- /* minute hand:
- * the minute hand is rotated 6 degrees (pi/30 r) per minute
- */
- cairo_move_to (cr, x, y);
- cairo_line_to (cr, x + radius * min_length * sin (M_PI / 30 * minutes),
- y + radius * min_length * -cos (M_PI / 30 * minutes));
- cairo_stroke (cr);
-
- /* seconds hand:
- * operates identically to the minute hand
- */
- if (priv->size == CLOCK_FACE_LARGE) {
- cairo_save (cr);
- cairo_set_source_rgb (cr, 0.937, 0.161, 0.161); /* tango red */
- cairo_move_to (cr, x, y);
- cairo_line_to (cr, x + radius * sec_length * sin (M_PI / 30 * seconds),
- y + radius * sec_length * -cos (M_PI / 30 * seconds));
- cairo_stroke (cr);
- cairo_restore (cr);
- }
-
- return FALSE;
+ const gchar *faces[4] = {
+ "morning",
+ "day",
+ "evening",
+ "night"
+ };
+
+ return g_strconcat (CLOCK_RESOURCE_PATH "icons/",
+ "clock-face-",
+ faces[(gint) type],
+ ".svg",
+ NULL);
}
-static void
-clock_face_redraw_canvas (ClockFace *this)
+static GdkPixbuf *
+clock_face_get_pixbuf (ClockFace *face)
{
- gtk_widget_queue_draw (GTK_WIDGET (this));
+ ClockFaceType type;
+ gchar *image;
+ gint width;
+ gint height;
+ gint size;
+ GError *error;
+ GdkPixbuf *pixbuf;
+
+ type = clock_face_get_type_from_hour (face->priv->hour);
+ image = clock_face_image_from_type (type);
+
+ width = gtk_widget_get_allocated_width (GTK_WIDGET (face));
+ height = gtk_widget_get_allocated_height (GTK_WIDGET (face));
+
+ size = MIN (width, height);
+
+ error = NULL;
+ pixbuf = gdk_pixbuf_new_from_resource_at_scale (image,
+ size,
+ size,
+ TRUE,
+ &error);
+ g_free (image);
+
+ if (error) {
+ g_warning ("Failed to load clock face: %s", error->message);
+ g_error_free (error);
+ }
+
+ return pixbuf;
}
static void
-clock_face_get_preferred_width (GtkWidget *this,
- gint *minimal_width,
- gint *natural_width)
+clock_face_hour_changed (ClockTime *time,
+ gint hour,
+ gpointer user_data)
{
- ClockFacePrivate *priv = CLOCK_FACE (this)->priv;
-
- if (priv->size_widget != NULL) {
- int child_minimal_height;
- int child_natural_height;
-
- /* Tie our size to the height of the size_widget */
- gtk_widget_get_preferred_height (GTK_WIDGET (priv->size_widget),
- &child_minimal_height,
- &child_natural_height);
-
- /* Pad out our height by a little bit - this improves
- the balance */
- *minimal_width = child_minimal_height + child_minimal_height / 8;
- *natural_width = child_natural_height + child_natural_height / 8;
- } else if (priv->face_pixbuf != NULL) {
- /* Use the size of the current pixbuf */
- *minimal_width = *natural_width = gdk_pixbuf_get_width (GDK_PIXBUF (priv->face_pixbuf));
- } else {
- /* we don't know anything, so use known dimensions for the svg
- * files */
- if (priv->size == CLOCK_FACE_LARGE)
- *minimal_width = *natural_width = 50;
- else
- *minimal_width = *natural_width = 36;
- }
+ ClockFace *face;
+ GdkPixbuf *pixbuf;
+
+ face = CLOCK_FACE (user_data);
+
+ face->priv->hour = hour;
+
+ pixbuf = clock_face_get_pixbuf (face);
+ gtk_image_set_from_pixbuf (GTK_IMAGE (face), pixbuf);
+ g_object_unref (pixbuf);
}
static void
-clock_face_get_preferred_height (GtkWidget *this,
- gint *minimal_height,
- gint *natural_height)
+clock_face_minute_changed (ClockTime *time,
+ gint hour,
+ gint minute,
+ gpointer user_data)
{
- ClockFacePrivate *priv = CLOCK_FACE (this)->priv;
-
- if (priv->size_widget != NULL) {
- int child_minimal_height;
- int child_natural_height;
-
- /* Tie our size to the height of the size_widget */
- gtk_widget_get_preferred_height (GTK_WIDGET (priv->size_widget),
- &child_minimal_height,
- &child_natural_height);
-
- /* Pad out our height by a little bit - this improves
- the balance */
- *minimal_height = child_minimal_height + child_minimal_height / 8;
- *natural_height = child_natural_height + child_natural_height / 8;
- } else if (priv->face_pixbuf != NULL) {
- /* Use the size of the current pixbuf */
- *minimal_height = *natural_height = gdk_pixbuf_get_height (GDK_PIXBUF (priv->face_pixbuf));
- } else {
- /* we don't know anything, so use known dimensions for the svg
- * files */
- if (priv->size == CLOCK_FACE_LARGE)
- *minimal_height = *natural_height = 50;
- else
- *minimal_height = *natural_height = 36;
- }
+ ClockFace *face;
+
+ face = CLOCK_FACE (user_data);
+
+ if (face->priv->show_seconds)
+ return;
+
+ face->priv->hour = hour;
+ face->priv->minute = minute;
+
+ gtk_widget_queue_draw (GTK_WIDGET (face));
}
static void
-clock_face_size_allocate (GtkWidget *this,
- GtkAllocation *allocation)
+clock_face_second_changed (ClockTime *time,
+ gint hour,
+ gint minute,
+ gint second,
+ gpointer user_data)
{
- GtkAllocation this_allocation;
- GtkAllocation old_allocation;
-
- gtk_widget_get_allocation (this, &this_allocation);
+ ClockFace *face;
- old_allocation.width = this_allocation.width;
- old_allocation.height = this_allocation.height;
+ face = CLOCK_FACE (user_data);
- if (GTK_WIDGET_CLASS (clock_face_parent_class)->size_allocate)
- GTK_WIDGET_CLASS (clock_face_parent_class)->size_allocate (this, allocation);
+ if (!face->priv->show_seconds)
+ return;
- if (old_allocation.width == allocation->width &&
- old_allocation.height == allocation->height)
- return;
+ face->priv->hour = hour;
+ face->priv->minute = minute;
+ face->priv->second = second;
- /* Reload the face for the new size */
- update_time_and_face (CLOCK_FACE (this), TRUE);
+ gtk_widget_queue_draw (GTK_WIDGET (face));
}
static void
-update_time_and_face (ClockFace *this,
- gboolean force_face_loading)
+clock_face_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
{
- ClockFacePrivate *priv;
- ClockFaceTimeOfDay timeofday;
- int hour;
-
- priv = this->priv;
+ ClockFace *face;
+ GtkAllocation old_allocation;
+ GdkPixbuf *pixbuf;
- if (priv->time)
- g_date_time_unref (priv->time);
- /* update the time */
- if (priv->location)
- priv->time = clock_location_localtime (priv->location);
- else
- priv->time = g_date_time_new_now_local ();
-
- /* FIXME this should be a gconf setting
- * Or we could use some code from clock-sun.c?
- * currently we hardcode
- * morning 7-9
- * day 9-17
- * evening 17-22
- * night 22-7
- */
- hour = g_date_time_get_hour (priv->time);
- if (hour < 7)
- timeofday = CLOCK_FACE_NIGHT;
- else if (hour < 9)
- timeofday = CLOCK_FACE_MORNING;
- else if (hour < 17)
- timeofday = CLOCK_FACE_DAY;
- else if (hour < 22)
- timeofday = CLOCK_FACE_EVENING;
- else
- timeofday = CLOCK_FACE_NIGHT;
+ gtk_widget_get_allocation (widget, &old_allocation);
- if (priv->timeofday != timeofday || force_face_loading) {
- GtkAllocation allocation;
- gint width, height;
+ GTK_WIDGET_CLASS (clock_face_parent_class)->size_allocate (widget,
+ allocation);
- priv->timeofday = timeofday;
+ if (old_allocation.width == allocation->width &&
+ old_allocation.height == allocation->height)
+ return;
- gtk_widget_get_allocation (GTK_WIDGET (this), &allocation);
+ face = CLOCK_FACE (widget);
- width = allocation.width;
- height = allocation.height;
+ if (face->priv->hour == -1)
+ return;
- /* Only load the pixbuf if we have some space allocated.
- * Note that 1x1 is not really some space... */
- if (width > 1 && height > 1)
- clock_face_load_face (this, width, height);
- }
+ pixbuf = clock_face_get_pixbuf (CLOCK_FACE (widget));
+ gtk_image_set_from_pixbuf (GTK_IMAGE (widget), pixbuf);
+ g_object_unref (pixbuf);
}
-gboolean
-clock_face_refresh (ClockFace *this)
+static void
+clock_face_finalize (GObject *object)
{
- update_time_and_face (this, FALSE);
- clock_face_redraw_canvas (this);
+ ClockFace *face;
- return TRUE; /* keep running this event */
+ face = CLOCK_FACE (object);
+
+ g_clear_object (&face->priv->time);
+ g_clear_object (&face->priv->location);
+
+ G_OBJECT_CLASS (clock_face_parent_class)->finalize (object);
}
-GtkWidget *
-clock_face_new (ClockFaceSize size)
+static void
+clock_face_set_location (ClockFace *face,
+ ClockLocation *location)
{
- GObject *obj = g_object_new (INTL_TYPE_CLOCK_FACE, NULL);
- ClockFacePrivate *priv = CLOCK_FACE (obj)->priv;
+ if (face->priv->location)
+ g_object_unref (face->priv->location);
- priv->size = size;
-
- return GTK_WIDGET (obj);
+ face->priv->location = g_object_ref (location);
}
-GtkWidget *
-clock_face_new_with_location (ClockFaceSize size,
- ClockLocation *loc,
- GtkWidget *size_widget)
+static void
+clock_face_set_time (ClockFace *face,
+ ClockTime *time)
{
- GObject *obj = g_object_new (INTL_TYPE_CLOCK_FACE, NULL);
- ClockFacePrivate *priv = CLOCK_FACE (obj)->priv;
-
- priv->size = size;
- priv->location = g_object_ref (loc);
- priv->size_widget = g_object_ref (size_widget);
+ if (face->priv->time)
+ g_object_unref (face->priv->time);
+
+ face->priv->time = g_object_ref (time);
+
+ g_signal_connect (face->priv->time,
+ "hour-changed",
+ G_CALLBACK (clock_face_hour_changed),
+ face);
+ g_signal_connect (face->priv->time,
+ "minute-changed",
+ G_CALLBACK (clock_face_minute_changed),
+ face);
+ g_signal_connect (face->priv->time,
+ "second-changed",
+ G_CALLBACK (clock_face_second_changed),
+ face);
+}
- return GTK_WIDGET (obj);
+static void
+clock_face_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ ClockFace *face;
+
+ face = CLOCK_FACE (object);
+
+ switch (property_id)
+ {
+ case PROP_LOCATION:
+ clock_face_set_location (face,
+ g_value_get_object (value));
+ break;
+ case PROP_TIME:
+ clock_face_set_time (face,
+ g_value_get_object (value));
+ break;
+ case PROP_SHOW_SECONDS:
+ face->priv->show_seconds = g_value_get_boolean (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object,
+ property_id,
+ pspec);
+ break;
+ }
}
static void
-clock_face_finalize (GObject *obj)
+clock_face_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
{
- ClockFace *face = CLOCK_FACE (obj);
- ClockFacePrivate *priv = face->priv;
-
- if (priv->location) {
- g_object_unref (priv->location);
- priv->location = NULL;
- }
-
- if (priv->face_pixbuf) {
- g_object_unref (priv->face_pixbuf);
- priv->face_pixbuf = NULL;
- }
-
- if (priv->size_widget) {
- g_object_unref (priv->size_widget);
- priv->size_widget = NULL;
- }
-
- G_OBJECT_CLASS (clock_face_parent_class)->finalize (obj);
-
- if (pixbuf_cache && g_hash_table_size (pixbuf_cache) == 0) {
- g_hash_table_destroy (pixbuf_cache);
- pixbuf_cache = NULL;
- }
+ ClockFace *face;
+
+ face = CLOCK_FACE (object);
+
+ switch (property_id)
+ {
+ case PROP_LOCATION:
+ g_value_set_object (value, face->priv->location);
+ break;
+ case PROP_TIME:
+ g_value_set_object (value, face->priv->time);
+ break;
+ case PROP_SHOW_SECONDS:
+ g_value_set_boolean (value, face->priv->show_seconds);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object,
+ property_id,
+ pspec);
+ break;
+ }
}
-/* The pixbuf is being disposed, so remove it from the cache */
static void
-remove_pixbuf_from_cache (const char *key,
- GObject *pixbuf)
+clock_face_class_init (ClockFaceClass *class)
{
- g_hash_table_remove (pixbuf_cache, key);
+ GObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+
+ object_class = G_OBJECT_CLASS (class);
+ widget_class = GTK_WIDGET_CLASS (class);
+
+ object_class->finalize = clock_face_finalize;
+ object_class->set_property = clock_face_set_property;
+ object_class->get_property = clock_face_get_property;
+
+ widget_class->draw = clock_face_draw;
+ widget_class->size_allocate = clock_face_size_allocate;
+
+ object_properties[PROP_LOCATION] =
+ g_param_spec_object ("location",
+ "location",
+ "location",
+ CLOCK_TYPE_LOCATION,
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_READWRITE);
+
+ object_properties[PROP_TIME] =
+ g_param_spec_object ("time",
+ "time",
+ "time",
+ CLOCK_TYPE_TIME,
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_READWRITE);
+
+ object_properties[PROP_SHOW_SECONDS] =
+ g_param_spec_boolean ("show-seconds",
+ "show-seconds",
+ "show-seconds",
+ FALSE,
+ G_PARAM_READWRITE);
+
+ g_object_class_install_properties (object_class,
+ N_PROPERTIES,
+ object_properties);
}
static void
-clock_face_load_face (ClockFace *this, gint width, gint height)
+clock_face_init (ClockFace *face)
+{
+ face->priv = clock_face_get_instance_private (face);
+ face->priv->hour = -1;
+}
+
+GtkWidget *
+clock_face_new (ClockLocation *location,
+ ClockTime *time,
+ gboolean show_seconds)
{
- ClockFacePrivate *priv = this->priv;
- const gchar *size_string[2] = { "small", "large" };
- const gchar *daytime_string[4] = { "morning", "day", "evening", "night" };
- gchar *cache_name;
- gchar *name;
-
- if (!pixbuf_cache)
- pixbuf_cache = g_hash_table_new_full (g_str_hash, g_str_equal,
- g_free, NULL);
-
- if (priv->face_pixbuf != NULL) {
- /* This might empty the cache, but it's useless to destroy
- * it since this object is still alive and might add another
- * pixbuf in the cache later (eg, a few lines below) */
- g_object_unref (priv->face_pixbuf);
- priv->face_pixbuf = NULL;
- }
-
- /* Look for the pixbuf in the process-wide cache first */
- cache_name = g_strdup_printf ("%d-%d-%d-%d",
- priv->size, priv->timeofday,
- width, height);
-
- priv->face_pixbuf = g_hash_table_lookup (pixbuf_cache, cache_name);
- if (priv->face_pixbuf) {
- g_object_ref (priv->face_pixbuf);
- return;
- }
-
- /* The pixbuf is not cached, let's load it */
- name = g_strconcat (CLOCK_RESOURCE_PATH "icons/",
- "clock-face-", size_string[priv->size],
- "-", daytime_string[priv->timeofday], ".svg",
- NULL);
- priv->face_pixbuf = clock_utils_pixbuf_from_svg_resource_at_size (name,
- width, height);
- g_free (name);
-
- if (!priv->face_pixbuf) {
- name = g_strconcat (CLOCK_RESOURCE_PATH "icons/",
- "clock-face-", size_string[priv->size], ".svg",
- NULL);
- priv->face_pixbuf = clock_utils_pixbuf_from_svg_resource_at_size (name,
- width, height);
- g_free (name);
- }
-
- /* Save the found pixbuf in the cache */
- if (priv->face_pixbuf) {
- g_hash_table_replace (pixbuf_cache,
- cache_name, priv->face_pixbuf);
- /* This will handle automatic removal from the cache when
- * the pixbuf isn't needed anymore */
- g_object_weak_ref (G_OBJECT (priv->face_pixbuf),
- (GWeakNotify) remove_pixbuf_from_cache,
- cache_name);
- } else
- g_free (cache_name);
+ GObject *object;
+
+ object = g_object_new (CLOCK_TYPE_FACE,
+ "location", location,
+ "time", time,
+ "show-seconds", show_seconds,
+ NULL);
+
+ return GTK_WIDGET (object);
}
diff --git a/applets/clock/clock-face.h b/applets/clock/clock-face.h
index cd620a6..3748e54 100644
--- a/applets/clock/clock-face.h
+++ b/applets/clock/clock-face.h
@@ -1,61 +1,68 @@
-/**
- * clock.h
+/*
+ * Copyright (C) 2014 Alberts Muktupāvels
*
- * A GTK+ widget that implements a clock face
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
*
- * (c) 2007, Peter Teichman
- * (c) 2005-2006, Davyd Madeley
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY 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/>.
*
* Authors:
- * Davyd Madeley <davyd madeley id au>
- * Peter Teichman <peter novell com>
+ * Alberts Muktupāvels <alberts muktupavels gmail com>
*/
-#ifndef __INTL_CLOCK_FACE_H__
-#define __INTL_CLOCK_FACE_H__
+#ifndef CLOCK_FACE_H
+#define CLOCK_FACE_H
#include <gtk/gtk.h>
+
#include "clock-location.h"
+#include "clock-time.h"
G_BEGIN_DECLS
-#define INTL_TYPE_CLOCK_FACE (clock_face_get_type ())
-#define CLOCK_FACE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), INTL_TYPE_CLOCK_FACE, ClockFace))
-#define CLOCK_FACE_CLASS(obj) (G_TYPE_CHECK_CLASS_CAST ((obj), INTL_CLOCK_FACE, ClockFaceClass))
-#define INTL_IS_CLOCK_FACE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), INTL_TYPE_CLOCK_FACE))
-#define INTL_IS_CLOCK_FACE_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((obj), INTL_TYPE_CLOCK_FACE))
-#define CLOCK_FACE_GET_CLASS (G_TYPE_INSTANCE_GET_CLASS ((obj), INTL_TYPE_CLOCK_FACE,
ClockFaceClass))
+#define CLOCK_TYPE_FACE (clock_face_get_type ())
+#define CLOCK_FACE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), \
+ CLOCK_TYPE_FACE, \
+ ClockFace))
+#define CLOCK_FACE_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), \
+ CLOCK_TYPE_FACE, \
+ ClockFaceClass))
+#define CLOCK_IS_FACE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), \
+ CLOCK_TYPE_FACE))
+#define CLOCK_IS_FACE_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), \
+ CLOCK_TYPE_FACE))
+#define CLOCK_FACE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS((o), \
+ CLOCK_TYPE_FACE, \
+ ClockFaceClass))
-typedef struct _ClockFace ClockFace;
-typedef struct _ClockFacePrivate ClockFacePrivate;
-typedef struct _ClockFaceClass ClockFaceClass;
+typedef struct _ClockFace ClockFace;
+typedef struct _ClockFaceClass ClockFaceClass;
+typedef struct _ClockFacePrivate ClockFacePrivate;
struct _ClockFace
{
- GtkWidget parent;
-
- /* < private > */
- ClockFacePrivate *priv;
+ GtkImage parent;
+ ClockFacePrivate *priv;
};
struct _ClockFaceClass
{
- GtkWidgetClass parent_class;
+ GtkImageClass parent_class;
};
-typedef enum {
- CLOCK_FACE_SMALL,
- CLOCK_FACE_LARGE
-} ClockFaceSize;
-
-GType clock_face_get_type (void);
-
-GtkWidget *clock_face_new (ClockFaceSize size);
-GtkWidget *clock_face_new_with_location (ClockFaceSize size,
- ClockLocation *loc,
- GtkWidget *size_widget);
-gboolean clock_face_refresh (ClockFace *this);
+GType clock_face_get_type (void);
+GtkWidget *clock_face_new (ClockLocation *location,
+ ClockTime *time,
+ gboolean show_seconds);
G_END_DECLS
diff --git a/applets/clock/clock-location-tile.c b/applets/clock/clock-location-tile.c
index e0a426c..fae4be3 100644
--- a/applets/clock/clock-location-tile.c
+++ b/applets/clock/clock-location-tile.c
@@ -11,6 +11,7 @@
#include "clock.h"
#include "clock-face.h"
+#include "clock-time.h"
#include "clock-location-tile.h"
#include "clock-location.h"
#include "clock-utils.h"
@@ -33,7 +34,6 @@ typedef struct {
GDateTime *last_refresh;
long last_offset;
- ClockFaceSize size;
GtkWidget *box;
GtkWidget *clock_face;
@@ -63,8 +63,7 @@ static gboolean weather_tooltip (GtkWidget *widget,
gpointer data);
ClockLocationTile *
-clock_location_tile_new (ClockLocation *loc,
- ClockFaceSize size)
+clock_location_tile_new (ClockLocation *loc)
{
ClockLocationTile *this;
ClockLocationTilePrivate *priv;
@@ -73,7 +72,6 @@ clock_location_tile_new (ClockLocation *loc,
priv = PRIVATE (this);
priv->location = g_object_ref (loc);
- priv->size = size;
clock_location_tile_fill (this);
@@ -125,7 +123,6 @@ clock_location_tile_init (ClockLocationTile *this)
priv->last_refresh = NULL;
priv->last_offset = 0;
- priv->size = CLOCK_FACE_SMALL;
priv->clock_face = NULL;
priv->city_label = NULL;
@@ -340,8 +337,10 @@ clock_location_tile_fill (ClockLocationTile *this)
g_signal_connect (priv->current_button, "clicked",
G_CALLBACK (make_current), this);
- priv->clock_face = clock_face_new_with_location (
- priv->size, priv->location, head_section);
+ ClockTime *time = clock_time_new (priv->location);
+ priv->clock_face = clock_face_new (priv->location, time, FALSE);
+ gtk_widget_set_size_request (priv->clock_face, 52, 52);
+ g_object_unref (time);
gtk_box_pack_start (GTK_BOX (tile), priv->clock_face, FALSE, FALSE, 0);
gtk_box_pack_start (GTK_BOX (tile), head_section, TRUE, TRUE, 0);
@@ -351,36 +350,6 @@ clock_location_tile_fill (ClockLocationTile *this)
}
static gboolean
-clock_needs_face_refresh (ClockLocationTile *this)
-{
- ClockLocationTilePrivate *priv = PRIVATE (this);
- GDateTime *now;
- gboolean retval;
-
- if (!priv->last_refresh)
- return TRUE;
-
- now = clock_location_localtime (priv->location);
-
- retval = FALSE;
- if (g_date_time_get_year (now) > g_date_time_get_year (priv->last_refresh)
- || g_date_time_get_month (now) > g_date_time_get_month (priv->last_refresh)
- || g_date_time_get_day_of_month (now) > g_date_time_get_day_of_month (priv->last_refresh)
- || g_date_time_get_hour (now) > g_date_time_get_hour (priv->last_refresh)
- || g_date_time_get_minute (now) > g_date_time_get_minute (priv->last_refresh)) {
- retval = TRUE;
- }
-
- if ((priv->size == CLOCK_FACE_LARGE)
- && g_date_time_get_second (now) > g_date_time_get_second (priv->last_refresh)) {
- retval = TRUE;
- }
-
- g_date_time_unref (now);
- return retval;
-}
-
-static gboolean
clock_needs_label_refresh (ClockLocationTile *this)
{
ClockLocationTilePrivate *priv = PRIVATE (this);
@@ -540,10 +509,6 @@ clock_location_tile_refresh (ClockLocationTile *this, gboolean force_refresh)
}
}
- if (clock_needs_face_refresh (this)) {
- clock_face_refresh (CLOCK_FACE (priv->clock_face));
- }
-
if (!force_refresh && !clock_needs_label_refresh (this)) {
return;
}
diff --git a/applets/clock/clock-location-tile.h b/applets/clock/clock-location-tile.h
index c9c0497..8eae703 100644
--- a/applets/clock/clock-location-tile.h
+++ b/applets/clock/clock-location-tile.h
@@ -32,8 +32,7 @@ typedef struct
GType clock_location_tile_get_type (void);
-ClockLocationTile *clock_location_tile_new (ClockLocation *loc,
- ClockFaceSize size);
+ClockLocationTile *clock_location_tile_new (ClockLocation *loc);
ClockLocation *clock_location_tile_get_location (ClockLocationTile *this);
diff --git a/applets/clock/clock.c b/applets/clock/clock.c
index edf7610..05d9989 100644
--- a/applets/clock/clock.c
+++ b/applets/clock/clock.c
@@ -689,7 +689,7 @@ create_cities_section (ClockData *cd)
while (node) {
ClockLocation *loc = node->data;
- city = clock_location_tile_new (loc, CLOCK_FACE_SMALL);
+ city = clock_location_tile_new (loc);
g_signal_connect (city, "tile-pressed",
G_CALLBACK (location_tile_pressed_cb), cd);
g_signal_connect (city, "need-clock-format",
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]