[gnome-clocks] Use a cell data func for thumb labels



commit e87715f53f2866da0f600a5ef70928beddd1168f
Author: Paolo Borelli <pborelli gnome org>
Date:   Sat Mar 2 10:20:41 2013 +0100

    Use a cell data func for thumb labels
    
    This means that renaming an alarm is automatically reflected in the icon
    view. This also introduces the ContentItem interface and completely
    hides the iconview implementation from Alarm and World.

 src/alarm.vala   |   48 ++++++++++++++++----------------------
 src/widgets.vala |   68 ++++++++++++++++++++++++++++++++++++++++++++---------
 src/world.vala   |   64 ++++++++++++++++++++++++++------------------------
 3 files changed, 109 insertions(+), 71 deletions(-)
---
diff --git a/src/alarm.vala b/src/alarm.vala
index 0532c8f..ab4e308 100644
--- a/src/alarm.vala
+++ b/src/alarm.vala
@@ -19,7 +19,7 @@
 namespace Clocks {
 namespace Alarm {
 
-private class Item : Object {
+private class Item : Object, ContentItem {
     static const int SNOOZE_MINUTES = 9;
     static const int RING_MINUTES = 3;
 
@@ -200,6 +200,19 @@ private class Item : Object {
         return state != last_state;
     }
 
+    public void get_thumb_properties (out string text, out string subtext, out Gdk.Pixbuf? pixbuf, out 
string css_class) {
+        if (state == State.SNOOZING) {
+            text = snooze_time_label;
+            subtext = "(%s)".printf(time_label);
+            css_class = "snoozing";
+        } else {
+            text = time_label;
+            subtext = repeat_label;
+            css_class = active ? "active" : "inactive";
+        }
+        pixbuf = null;
+    }
+
     public void serialize (GLib.VariantBuilder builder) {
         builder.open (new GLib.VariantType ("a{sv}"));
         builder.add ("{sv}", "name", new GLib.Variant.string (name));
@@ -451,7 +464,6 @@ public class MainPanel : Gd.Stack, Clocks.Clock {
 
     private List<Item> alarms;
     private GLib.Settings settings;
-    private IconView icon_view;
     private ContentView content_view;
     private StandalonePanel standalone;
 
@@ -461,24 +473,9 @@ public class MainPanel : Gd.Stack, Clocks.Clock {
         alarms = new List<Item> ();
         settings = new GLib.Settings("org.gnome.clocks");
 
-        icon_view = new IconView ((column, cell, model, iter) => {
-            Item alarm;
-            model.get (iter, IconView.Column.ITEM, out alarm);
-            var renderer = (DigitalClockRenderer) cell;
-            if (alarm.state == Item.State.SNOOZING) {
-                renderer.text = alarm.snooze_time_label;
-                renderer.subtext = "(%s)".printf(alarm.time_label);
-                renderer.css_class = "snoozing";
-            } else {
-                renderer.text = alarm.time_label;
-                renderer.subtext = alarm.repeat_label;
-                renderer.css_class = alarm.active ? "active" : "inactive";
-            }
-        });
-
         var builder = Utils.load_ui ("alarm.ui");
         var empty_view = builder.get_object ("empty_panel") as Gtk.Widget;
-        content_view = new ContentView (empty_view, icon_view, toolbar);
+        content_view = new ContentView (empty_view, toolbar);
         add (content_view);
 
         content_view.item_activated.connect ((item) => {
@@ -494,7 +491,6 @@ public class MainPanel : Gd.Stack, Clocks.Clock {
             foreach (Object i in content_view.get_selected_items ()) {
                 alarms.remove ((Item) i);
             }
-            icon_view.remove_selected ();
             save ();
         });
 
@@ -545,7 +541,7 @@ public class MainPanel : Gd.Stack, Clocks.Clock {
             Item? alarm = Item.deserialize (a);
             if (alarm != null) {
                 alarms.prepend (alarm);
-                icon_view.add_item (alarm.name, alarm);
+                content_view.add_item (alarm);
             }
         }
         alarms.reverse ();
@@ -592,7 +588,7 @@ public class MainPanel : Gd.Stack, Clocks.Clock {
                 var alarm = new Item ();
                 ((SetupDialog) dialog).apply_to_alarm (alarm);
                 alarms.append (alarm);
-                icon_view.add_item (alarm.name, alarm);
+                content_view.add_item (alarm);
                 alarm.reset();
                 save ();
             }
@@ -602,19 +598,15 @@ public class MainPanel : Gd.Stack, Clocks.Clock {
     }
 
     public void activate_select_all () {
-        icon_view.select_all ();
+        content_view.select_all ();
     }
 
     public void activate_select_none () {
-        icon_view.unselect_all ();
+        content_view.unselect_all ();
     }
 
     public bool escape_pressed () {
-        if (icon_view.mode == IconView.Mode.SELECTION) {
-            icon_view.mode = IconView.Mode.NORMAL;
-            return true;
-        }
-        return false;
+        return content_view.escape_pressed ();
     }
 
     public void update_toolbar () {
diff --git a/src/widgets.vala b/src/widgets.vala
index 6f80592..9993e19 100644
--- a/src/widgets.vala
+++ b/src/widgets.vala
@@ -202,7 +202,12 @@ private class DigitalClockRenderer : Gtk.CellRendererPixbuf {
     }
 }
 
-public class IconView : Gtk.IconView {
+public interface ContentItem : GLib.Object {
+    public abstract string name { get; set; }
+    public abstract void get_thumb_properties (out string text, out string subtext, out Gdk.Pixbuf? pixbuf, 
out string css_class);
+}
+
+private class IconView : Gtk.IconView {
     public enum Mode {
         NORMAL,
         SELECTION
@@ -210,7 +215,6 @@ public class IconView : Gtk.IconView {
 
     public enum Column {
         SELECTED,
-        LABEL,
         ITEM,
         COLUMNS
     }
@@ -237,10 +241,10 @@ public class IconView : Gtk.IconView {
     private Mode _mode;
     private DigitalClockRenderer thumb_renderer;
 
-    public IconView (owned Gtk.CellLayoutDataFunc thumb_data_func) {
+    public IconView () {
         Object (selection_mode: Gtk.SelectionMode.NONE, mode: Mode.NORMAL);
 
-        model = new Gtk.ListStore (Column.COLUMNS, typeof (bool), typeof (string), typeof (Object));
+        model = new Gtk.ListStore (Column.COLUMNS, typeof (bool), typeof (ContentItem));
 
         get_style_context ().add_class ("content-view");
         set_item_padding (0);
@@ -254,7 +258,20 @@ public class IconView : Gtk.IconView {
         thumb_renderer.set_fixed_size (tile_width, tile_height);
         pack_start (thumb_renderer, false);
         add_attribute (thumb_renderer, "active", Column.SELECTED);
-        set_cell_data_func (thumb_renderer, (owned) thumb_data_func);
+        set_cell_data_func (thumb_renderer, (column, cell, model, iter) => {
+            ContentItem item;
+            model.get (iter, IconView.Column.ITEM, out item);
+            var renderer = (DigitalClockRenderer) cell;
+            string text;
+            string subtext;
+            Gdk.Pixbuf? pixbuf;
+            string css_class;
+            item.get_thumb_properties (out text, out subtext, out pixbuf, out css_class);
+            renderer.text = text;
+            renderer.subtext = subtext;
+            renderer.pixbuf = pixbuf;
+            renderer.css_class = css_class;
+        });
 
         var text_renderer = new Gtk.CellRendererText ();
         text_renderer.set_alignment (0.5f, 0.5f);
@@ -263,7 +280,12 @@ public class IconView : Gtk.IconView {
         text_renderer.wrap_width = 220;
         text_renderer.wrap_mode = Pango.WrapMode.WORD_CHAR;
         pack_start (text_renderer, true);
-        add_attribute (text_renderer, "markup", Column.LABEL);
+        set_cell_data_func (text_renderer, (column, cell, model, iter) => {
+            ContentItem item;
+            model.get (iter, IconView.Column.ITEM, out item);
+            var renderer = (Gtk.CellRendererText) cell;
+            renderer.markup = GLib.Markup.escape_text (item.name);
+        });
     }
 
     public override bool button_press_event (Gdk.EventButton event) {
@@ -291,12 +313,11 @@ public class IconView : Gtk.IconView {
         return false;
     }
 
-    public void add_item (string name, Object item) {
+    public void add_item (Object item) {
         var store = (Gtk.ListStore) model;
-        var label = GLib.Markup.escape_text (name);
         Gtk.TreeIter i;
         store.append (out i);
-        store.set (i, Column.SELECTED, false, Column.LABEL, label, Column.ITEM, item);
+        store.set (i, Column.SELECTED, false, Column.ITEM, item);
     }
 
     // Redefine selection handling methods since we handle selection manually
@@ -358,11 +379,12 @@ public class ContentView : Gtk.Bin {
     private Gtk.Toolbar selection_toolbar;
     private Gtk.Overlay overlay;
 
-    public ContentView (Gtk.Widget e, IconView iv, Toolbar t) {
+    public ContentView (Gtk.Widget e, Toolbar t) {
         empty_page = e;
-        icon_view = iv;
         main_toolbar = t;
 
+        icon_view = new IconView ();
+
         var builder = Utils.load_ui ("menu.ui");
         selection_menu = builder.get_object ("selection-menu") as GLib.MenuModel;
 
@@ -425,7 +447,9 @@ public class ContentView : Gtk.Bin {
 
     public signal void item_activated (Object item);
 
-    public signal void delete_selected ();
+    public virtual signal void delete_selected () {
+        icon_view.remove_selected ();
+    }
 
     private Gtk.Toolbar create_selection_toolbar () {
         var toolbar = new Gtk.Toolbar ();
@@ -502,6 +526,10 @@ public class ContentView : Gtk.Bin {
         }
     }
 
+    public void add_item (ContentItem item) {
+        icon_view.add_item (item);
+    }
+
     // Note: this is not efficient: we first walk the model to collect
     // a list then the caller has to walk this list and then it has to
     // delete the items from the view, which walks the model again...
@@ -522,6 +550,22 @@ public class ContentView : Gtk.Bin {
         return (owned) items;
     }
 
+    public void select_all () {
+        icon_view.select_all ();
+    }
+
+    public void unselect_all () {
+        icon_view.unselect_all ();
+    }
+
+    public bool escape_pressed () {
+        if (icon_view.mode == IconView.Mode.SELECTION) {
+            icon_view.mode = IconView.Mode.NORMAL;
+            return true;
+        }
+        return false;
+    }
+
     public void update_toolbar () {
         switch (main_toolbar.mode) {
         case Toolbar.Mode.SELECTION:
diff --git a/src/world.vala b/src/world.vala
index f9bdb4a..1a63ad5 100644
--- a/src/world.vala
+++ b/src/world.vala
@@ -28,21 +28,31 @@ private GWeather.Location get_world_location () {
     return gweather_world;
 }
 
-private class Item : Object {
+private class Item : Object, ContentItem {
+    private static Gdk.Pixbuf? day_pixbuf = Utils.load_image ("day.png");
+    private static Gdk.Pixbuf? night_pixbuf = Utils.load_image ("night.png");
+
     public GWeather.Location location { get; set; }
     public string name {
-        owned get {
+        get {
             var nation = location;
 
             while (nation != null && nation.get_level () != GWeather.LocationLevel.COUNTRY) {
                 nation = nation.get_parent ();
             }
 
+            // We store it in a _name member even if we overwrite it every time
+            // since we the abstract name property does not return an owned string
             if (nation != null) {
-                return "%s, %s".printf (location.get_city_name (), nation.get_name ());
+                _name = "%s, %s".printf (location.get_city_name (), nation.get_name ());
             } else {
-                return location.get_city_name ();
+                _name = location.get_city_name ();
             }
+
+            return _name;
+        }
+        set {
+            // ignored
         }
     }
 
@@ -87,6 +97,7 @@ private class Item : Object {
         }
     }
 
+    private string _name;
     private GLib.TimeZone time_zone;
     private GLib.DateTime local_time;
     private GLib.DateTime date_time;
@@ -110,6 +121,18 @@ private class Item : Object {
         weather_info = new GWeather.Info.for_world (get_world_location (), location, 
GWeather.ForecastType.LIST);
     }
 
+    public void get_thumb_properties (out string text, out string subtext, out Gdk.Pixbuf? pixbuf, out 
string css_class) {
+        text = time_label;
+        subtext = day_label;
+        if (is_daytime) {
+            pixbuf = day_pixbuf;
+            css_class = "light";
+        } else {
+            pixbuf = night_pixbuf;
+            css_class = "dark";
+        }
+    }
+
     public void serialize (GLib.VariantBuilder builder) {
         builder.open (new GLib.VariantType ("a{sv}"));
         builder.add ("{sv}", "location", location.serialize ());
@@ -226,7 +249,6 @@ public class MainPanel : Gd.Stack, Clocks.Clock {
     private GLib.Settings settings;
     private Gdk.Pixbuf? day_pixbuf;
     private Gdk.Pixbuf? night_pixbuf;
-    private IconView icon_view;
     private ContentView content_view;
     private StandalonePanel standalone;
 
@@ -239,24 +261,9 @@ public class MainPanel : Gd.Stack, Clocks.Clock {
         day_pixbuf = Utils.load_image ("day.png");
         night_pixbuf = Utils.load_image ("night.png");
 
-        icon_view = new IconView ((column, cell, model, iter) => {
-            Item location;
-            model.get (iter, IconView.Column.ITEM, out location);
-            var renderer = (DigitalClockRenderer) cell;
-            renderer.text = location.time_label;
-            renderer.subtext = location.day_label;
-            if (location.is_daytime) {
-                renderer.pixbuf = day_pixbuf;
-                renderer.css_class = "light";
-            } else {
-                renderer.pixbuf = night_pixbuf;
-                renderer.css_class = "dark";
-            }
-        });
-
         var builder = Utils.load_ui ("world.ui");
         var empty_view = builder.get_object ("empty_panel") as Gtk.Widget;
-        content_view = new ContentView (empty_view, icon_view, toolbar);
+        content_view = new ContentView (empty_view, toolbar);
         add (content_view);
 
         content_view.item_activated.connect ((item) => {
@@ -270,7 +277,6 @@ public class MainPanel : Gd.Stack, Clocks.Clock {
             foreach (Object i in content_view.get_selected_items ()) {
                 locations.remove ((Item) i);
             }
-            icon_view.remove_selected ();
             save ();
         });
 
@@ -300,7 +306,7 @@ public class MainPanel : Gd.Stack, Clocks.Clock {
             Item? location = Item.deserialize (l);
             if (location != null) {
                 locations.prepend (location);
-                icon_view.add_item (location.name, location);
+                content_view.add_item (location);
             }
         }
         locations.reverse ();
@@ -321,7 +327,7 @@ public class MainPanel : Gd.Stack, Clocks.Clock {
             if (response == 1) {
                 var location = ((LocationDialog) dialog).get_location ();
                 locations.append (location);
-                icon_view.add_item (location.name, location);
+                content_view.add_item (location);
                 save ();
             }
             dialog.destroy ();
@@ -330,19 +336,15 @@ public class MainPanel : Gd.Stack, Clocks.Clock {
     }
 
     public void activate_select_all () {
-        icon_view.select_all ();
+        content_view.select_all ();
     }
 
     public void activate_select_none () {
-        icon_view.unselect_all ();
+        content_view.unselect_all ();
     }
 
     public bool escape_pressed () {
-        if (icon_view.mode == IconView.Mode.SELECTION) {
-            icon_view.mode = IconView.Mode.NORMAL;
-            return true;
-        }
-        return false;
+        return content_view.escape_pressed ();
     }
 
     public void update_toolbar () {


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]