[Xfce4-commits] <xfce4-weather-plugin:master> Scrollbox: Rewrite scrollbox to make it less confusing.

Harald Judt noreply at xfce.org
Tue Dec 18 17:14:01 CET 2012


Updating branch refs/heads/master
         to 73e199a5005a5a55fede1e83d17976e4cab732f8 (commit)
       from 055ce41675a84f3efb8c896ae17cd3b2dd60a653 (commit)

commit 73e199a5005a5a55fede1e83d17976e4cab732f8
Author: Harald Judt <h.judt at gmx.at>
Date:   Tue Dec 18 17:00:22 2012 +0100

    Scrollbox: Rewrite scrollbox to make it less confusing.
    
    Well, at least it's an attempt to make it more readable by putting
    stuff into an control loop function. The previous modifications
    added some bugs, which should be fixed by this rewrite.

 panel-plugin/weather-scrollbox.c |  220 ++++++++++++++++++--------------------
 panel-plugin/weather-scrollbox.h |    8 +-
 panel-plugin/weather.c           |   15 ++--
 3 files changed, 116 insertions(+), 127 deletions(-)

diff --git a/panel-plugin/weather-scrollbox.c b/panel-plugin/weather-scrollbox.c
index ddd78b2..50b95a2 100644
--- a/panel-plugin/weather-scrollbox.c
+++ b/panel-plugin/weather-scrollbox.c
@@ -28,10 +28,8 @@
 
 #include "weather-scrollbox.h"
 
-#define LABEL_REFRESH (3)
-#define LABEL_REFRESH_NO_ANIMATION (6)
-#define LABEL_REFRESH_NO_ANIM_INIT (1)
-#define LABEL_SPEED (25)
+#define LABEL_SLEEP (3)    /* sleep time in seconds */
+#define LABEL_SPEED (25)   /* animation speed, delay in ms */
 
 
 static void gtk_scrollbox_finalize(GObject *object);
@@ -42,7 +40,7 @@ static void gtk_scrollbox_size_request(GtkWidget *widget,
 static gboolean gtk_scrollbox_expose_event(GtkWidget *widget,
                                            GdkEventExpose *event);
 
-static gboolean gtk_scrollbox_fade_out(gpointer user_data);
+static gboolean gtk_scrollbox_control_loop(gpointer user_data);
 
 G_DEFINE_TYPE(GtkScrollbox, gtk_scrollbox, GTK_TYPE_DRAWING_AREA)
 
@@ -70,8 +68,9 @@ gtk_scrollbox_init(GtkScrollbox *self)
     self->labels = NULL;
     self->labels_new = NULL;
     self->timeout_id = 0;
+    self->labels_len = 0;
     self->offset = 0;
-    self->fade = FADE_NONE;
+    self->fade = FADE_OUT;
     self->active = NULL;
     self->animate = FALSE;
     self->visible = FALSE;
@@ -200,12 +199,14 @@ gtk_scrollbox_expose_event(GtkWidget *widget,
             height = widget->allocation.y
                 + (widget->allocation.height
                    - PANGO_PIXELS(logical_rect.height)) / 2
-                + (self->animate || self->fade == FADE_OUT ? self->offset : 0);
+                + (self->fade == FADE_IN || self->fade == FADE_OUT
+                   ? self->offset : 0);
         } else {
             width = widget->allocation.x
                 + (widget->allocation.width
                    - PANGO_PIXELS(logical_rect.height)) / 2
-                + (self->animate || self->fade == FADE_OUT ? self->offset : 0);
+                + (self->fade == FADE_IN || self->fade == FADE_OUT
+                   ? self->offset : 0);
             height = widget->allocation.y
                 + (widget->allocation.height
                    - PANGO_PIXELS(logical_rect.width)) / 2;
@@ -224,7 +225,7 @@ gtk_scrollbox_expose_event(GtkWidget *widget,
 void
 gtk_scrollbox_add_label(GtkScrollbox *self,
                         const gint position,
-                        gchar *markup)
+                        const gchar *markup)
 {
     PangoLayout *layout;
 
@@ -237,27 +238,33 @@ gtk_scrollbox_add_label(GtkScrollbox *self,
 }
 
 
-void
+/*
+ * Sets new labels active if there are any, or advances the current
+ * label.
+ */
+static void
 gtk_scrollbox_swap_labels(GtkScrollbox *self)
 {
-    guint len;
     gint pos;
 
     g_return_if_fail(GTK_IS_SCROLLBOX(self));
 
-    if (G_LIKELY(self->labels_new == NULL))
+    /* No new label, so simply switch to the next */
+    if (G_LIKELY(self->labels_new == NULL)) {
+        gtk_scrollbox_next_label(self);
         return;
+    }
 
+    /* Keep current list position if possible */
     pos = g_list_position(self->labels, self->active);
-    len = g_list_length(self->labels_new);
-
-    if (pos >= len)
+    self->labels_len = g_list_length(self->labels_new);
+    if (pos >= self->labels_len)
         pos = 0;
-
-    self->active = g_list_nth(self->labels_new, pos);
+    self->active = g_list_nth(self->labels_new, pos + 1);
     if (self->active == NULL)
         self->active = self->labels_new;
 
+    /* clear the existing labels */
     gtk_scrollbox_labels_free(self);
     self->labels = self->labels_new;
     self->labels_new = NULL;
@@ -267,53 +274,6 @@ gtk_scrollbox_swap_labels(GtkScrollbox *self)
 
 
 static gboolean
-gtk_scrollbox_fade_none(gpointer user_data)
-{
-    GtkScrollbox *self = GTK_SCROLLBOX(user_data);
-
-    if (!self->visible)
-        return FALSE;
-
-    /* start fading out if animation has been enabled */
-    if (self->animate) {
-        self->fade = FADE_OUT;
-        self->offset = 0;
-        self->timeout_id = g_timeout_add(LABEL_SPEED,
-                                         gtk_scrollbox_fade_out, self);
-        return FALSE;
-    }
-
-    if (self->timeout_id != 0) {
-        g_source_remove(self->timeout_id);
-        self->timeout_id = 0;
-    }
-
-    if (self->orientation == GTK_ORIENTATION_HORIZONTAL)
-        self->offset = GTK_WIDGET(self)->allocation.height;
-    else
-        self->offset = GTK_WIDGET(self)->allocation.width;
-
-    gtk_scrollbox_swap_labels(self);
-    gtk_scrollbox_next_label(self);
-
-    self->timeout_id = g_timeout_add_seconds(LABEL_REFRESH_NO_ANIMATION,
-                                             gtk_scrollbox_fade_none, self);
-    return FALSE;
-}
-
-
-static gboolean
-gtk_scrollbox_sleep(gpointer user_data)
-{
-    GtkScrollbox *self = GTK_SCROLLBOX(user_data);
-
-    self->timeout_id = g_timeout_add(LABEL_SPEED,
-                                     gtk_scrollbox_fade_out, self);
-    return FALSE;
-}
-
-
-static gboolean
 gtk_scrollbox_fade_in(gpointer user_data)
 {
     GtkScrollbox *self = GTK_SCROLLBOX(user_data);
@@ -330,18 +290,7 @@ gtk_scrollbox_fade_in(gpointer user_data)
         (self->orientation == GTK_ORIENTATION_VERTICAL && self->offset < 0))
         return TRUE;
 
-    if (self->visible)
-        if (self->animate) {
-            self->fade = FADE_OUT;
-            self->timeout_id =
-                g_timeout_add_seconds(LABEL_REFRESH,
-                                      gtk_scrollbox_sleep, self);
-        } else {
-            self->fade = FADE_NONE;
-            self->timeout_id =
-                g_timeout_add_seconds(LABEL_REFRESH_NO_ANIMATION,
-                                      gtk_scrollbox_fade_none, self);
-        }
+    (void) gtk_scrollbox_control_loop(self);
     return FALSE;
 }
 
@@ -365,37 +314,85 @@ gtk_scrollbox_fade_out(gpointer user_data)
          self->offset > 0 - GTK_WIDGET(self)->allocation.width))
         return TRUE;
 
-    gtk_scrollbox_swap_labels(self);
-    gtk_scrollbox_next_label(self);
-    if (self->visible) {
-        self->timeout_id = g_timeout_add(LABEL_SPEED,
-                                         gtk_scrollbox_fade_in, self);
-    }
+    (void) gtk_scrollbox_control_loop(self);
     return FALSE;
 }
 
 
-static void
-gtk_scrollbox_start_fade(GtkScrollbox *self)
+/*
+ * This control loop is called between any animation steps except
+ * sleeps and determines what to do next.
+ */
+static gboolean
+gtk_scrollbox_control_loop(gpointer user_data)
 {
+    GtkScrollbox *self = GTK_SCROLLBOX(user_data);
+
     if (self->timeout_id != 0) {
         g_source_remove(self->timeout_id);
         self->timeout_id = 0;
     }
 
-    gtk_scrollbox_swap_labels(self);
+    /* determine what to do next */
+    switch(self->fade) {
+    case FADE_IN:
+        self->fade = FADE_SLEEP;
+        break;
+    case FADE_OUT:
+        self->fade = FADE_IN;
+        gtk_scrollbox_swap_labels(self);
+        break;
+    case FADE_NONE:
+        if (self->animate && self->labels_len > 1)
+            self->fade = FADE_OUT;
+        else {
+            self->fade = FADE_NONE;
+            gtk_scrollbox_swap_labels(self);
+        }
+        break;
+    case FADE_SLEEP:
+        self->fade = self->animate ? FADE_OUT : FADE_NONE;
+        break;
+    }
 
-    if (self->animate && g_list_length(self->labels) > 1) {
+    /* now perform the next action */
+    switch(self->fade) {
+    case FADE_IN:
+        if (self->labels_len > 1) {
+            if (self->orientation == GTK_ORIENTATION_HORIZONTAL)
+                self->offset = GTK_WIDGET(self)->allocation.height;
+            else
+                self->offset = 0;
+        } else
+            self->offset = 0;
+        self->timeout_id = g_timeout_add(LABEL_SPEED,
+                                         gtk_scrollbox_fade_in,
+                                         self);
+        break;
+    case FADE_OUT:
+        self->offset = 0;
+        self->timeout_id = g_timeout_add(LABEL_SPEED,
+                                         gtk_scrollbox_fade_out,
+                                         self);
+        break;
+    case FADE_SLEEP:
+        self->timeout_id = g_timeout_add_seconds(LABEL_SLEEP,
+                                                 gtk_scrollbox_control_loop,
+                                                 self);
+        break;
+    case FADE_NONE:
         if (self->orientation == GTK_ORIENTATION_HORIZONTAL)
             self->offset = GTK_WIDGET(self)->allocation.height;
         else
-            self->offset = 0;
+            self->offset = GTK_WIDGET(self)->allocation.width;
+        self->timeout_id = g_timeout_add_seconds(LABEL_SLEEP,
+                                                 gtk_scrollbox_control_loop,
+                                                 self);
+        break;
+    }
 
-        self->fade = FADE_IN;
-        self->timeout_id = g_timeout_add(LABEL_SPEED,
-                                         gtk_scrollbox_fade_in, self);
-    } else
-        self->offset = 0;
+    gtk_widget_queue_resize(GTK_WIDGET(self));
+    return FALSE;
 }
 
 
@@ -438,22 +435,14 @@ gtk_scrollbox_reset(GtkScrollbox *self)
         g_source_remove(self->timeout_id);
         self->timeout_id = 0;
     }
-
-    if (self->animate)
-        gtk_scrollbox_start_fade(self);
-    else {
-        self->fade = FADE_NONE;
-        self->timeout_id =
-            g_timeout_add_seconds(LABEL_REFRESH_NO_ANIMATION,
-                                  gtk_scrollbox_fade_none, self);
-    }
-    gtk_widget_queue_resize(GTK_WIDGET(self));
+    self->fade = FADE_OUT;
+    (void) gtk_scrollbox_control_loop(self);
 }
 
 
 void
 gtk_scrollbox_set_animate(GtkScrollbox *self,
-                          gboolean animate)
+                          const gboolean animate)
 {
     g_return_if_fail(GTK_IS_SCROLLBOX(self));
 
@@ -463,23 +452,22 @@ gtk_scrollbox_set_animate(GtkScrollbox *self,
 
 void
 gtk_scrollbox_set_visible(GtkScrollbox *self,
-                          gboolean visible)
+                          const gboolean visible)
 {
     g_return_if_fail(GTK_IS_SCROLLBOX(self));
 
     gtk_widget_set_visible(GTK_WIDGET(self), visible);
     self->visible = visible;
     if (visible) {
-        if (self->timeout_id == 0)
-            if (self->animate)
-                gtk_scrollbox_start_fade(self);
-            else {
-                self->fade = FADE_NONE;
-                self->timeout_id =
-                    g_timeout_add_seconds(LABEL_REFRESH_NO_ANIM_INIT,
-                                          gtk_scrollbox_fade_none,
-                                          self);
-            }
+        if (self->timeout_id == 0) {
+            self->fade = FADE_NONE;
+            (void) gtk_scrollbox_control_loop(self);
+        } else {
+            /* update immediately if there's only one or no label,
+             typically this is the case at startup */
+            if (self->active == NULL || self->labels_len <= 1)
+                (void) gtk_scrollbox_control_loop(self);
+        }
     } else
         if (self->timeout_id != 0) {
             g_source_remove(self->timeout_id);
@@ -493,7 +481,7 @@ gtk_scrollbox_prev_label(GtkScrollbox *self)
 {
     g_return_if_fail(GTK_IS_SCROLLBOX(self));
 
-    if (g_list_length(self->labels) > 1) {
+    if (self->labels_len > 1) {
         if (self->active->prev != NULL)
             self->active = self->active->prev;
         else
@@ -508,7 +496,7 @@ gtk_scrollbox_next_label(GtkScrollbox *self)
 {
     g_return_if_fail(GTK_IS_SCROLLBOX(self));
 
-    if (g_list_length(self->labels) > 1) {
+    if (self->labels_len > 1) {
         if (self->active->next != NULL)
             self->active = self->active->next;
         else
diff --git a/panel-plugin/weather-scrollbox.h b/panel-plugin/weather-scrollbox.h
index 70dc4a7..937e07f 100644
--- a/panel-plugin/weather-scrollbox.h
+++ b/panel-plugin/weather-scrollbox.h
@@ -40,7 +40,8 @@ GType gtk_scrollbox_get_type(void);
 typedef enum {
     FADE_IN,
     FADE_OUT,
-    FADE_NONE
+    FADE_NONE,
+    FADE_SLEEP
 } fade_states;
 
 typedef struct _GtkScrollbox GtkScrollbox;
@@ -52,6 +53,7 @@ struct _GtkScrollbox {
     GList *labels;
     GList *labels_new;
     GList *active;
+    guint labels_len;
     guint timeout_id;
     gint offset;
     gboolean animate;
@@ -69,9 +71,7 @@ struct _GtkScrollboxClass {
 
 void gtk_scrollbox_add_label(GtkScrollbox *self,
                              gint position,
-                             gchar *markup);
-
-void gtk_scrollbox_swap_labels(GtkScrollbox *self);
+                             const gchar *markup);
 
 void gtk_scrollbox_set_orientation(GtkScrollbox *self,
                                    GtkOrientation orientation);
diff --git a/panel-plugin/weather.c b/panel-plugin/weather.c
index ca7f0fb..a555cf7 100644
--- a/panel-plugin/weather.c
+++ b/panel-plugin/weather.c
@@ -280,7 +280,7 @@ void
 update_scrollbox(plugin_data *data)
 {
     GString *out;
-    gchar *single = NULL;
+    gchar *label = NULL;
     data_types type;
     gint i = 0, j = 0;
 
@@ -291,12 +291,12 @@ update_scrollbox(plugin_data *data)
             out = g_string_sized_new(128);
             while ((i + j) < data->labels->len && j < data->scrollbox_lines) {
                 type = g_array_index(data->labels, data_types, i + j);
-                single = make_label(data, type);
-                g_string_append_printf(out, "%s%s", single,
+                label = make_label(data, type);
+                g_string_append_printf(out, "%s%s", label,
                                        (j < (data->scrollbox_lines - 1)
                                         ? "\n"
                                         : ""));
-                g_free(single);
+                g_free(label);
                 j++;
             }
             gtk_scrollbox_add_label(GTK_SCROLLBOX(data->scrollbox),
@@ -306,12 +306,13 @@ update_scrollbox(plugin_data *data)
         }
         weather_debug("Added %u labels to scrollbox.", data->labels->len);
     } else {
-        single = g_strdup(_("No Data"));
-        gtk_scrollbox_add_label(GTK_SCROLLBOX(data->scrollbox), -1, single);
-        g_free(single);
+        gtk_scrollbox_add_label(GTK_SCROLLBOX(data->scrollbox), -1,
+                                _("No Data"));
         weather_debug("No weather data available, set single label '%s'.",
                       _("No Data"));
     }
+    gtk_scrollbox_set_animate(GTK_SCROLLBOX(data->scrollbox),
+                              data->scrollbox_animate);
     scrollbox_set_visible(data);
     weather_debug("Updated scrollbox.");
 }


More information about the Xfce4-commits mailing list