Add VBox cell renderer to display driver name in lift list
authorPhilipp Zabel <philipp.zabel@gmail.com>
Fri, 2 Jul 2010 16:24:00 +0000 (18:24 +0200)
committerPhilipp Zabel <philipp.zabel@gmail.com>
Fri, 2 Jul 2010 16:24:00 +0000 (18:24 +0200)
Makefile.am
src/cell-renderer-vbox.vala [new file with mode: 0644]
src/lift-list-window.vala

index 5bb0c5e..16c3fcc 100644 (file)
@@ -30,6 +30,7 @@ icon64_DATA = \
 beifahrer_SOURCES = \
        src/beifahrer.c \
        src/adac-mitfahrclub.c \
+       src/cell-renderer-vbox.c \
        src/city-button.c \
        src/orientation.c \
        src/query-window.c \
@@ -43,6 +44,7 @@ beifahrer_SOURCES = \
 beifahrer_VALASOURCES = \
        src/beifahrer.vala \
        src/adac-mitfahrclub.vala \
+       src/cell-renderer-vbox.vala \
        src/city-button.vala \
        src/orientation.vala \
        src/query-window.vala \
diff --git a/src/cell-renderer-vbox.vala b/src/cell-renderer-vbox.vala
new file mode 100644 (file)
index 0000000..659db86
--- /dev/null
@@ -0,0 +1,149 @@
+/* This file is part of Cinaest.
+ *
+ * Copyright (C) 2009 Philipp Zabel
+ *
+ * Cinaest 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Cinaest 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 Cinaest. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+using Gtk;
+
+class CellRendererVBox : CellRenderer {
+       private List<CellRenderer> children;
+
+       public CellRendererVBox () {
+       }
+
+       construct {
+               children = null;
+       }
+
+       public void append (CellRenderer cell, bool expand) {
+               children.append (cell);
+               cell.set_data ("box-expand", (void*) (long) expand);
+       }
+
+       public override void get_size (Widget widget, Gdk.Rectangle? rectangle, out int x_offset, out int y_offset, out int width, out int height) {
+               int calc_width = 0;
+               int calc_height = 0;
+
+               foreach (CellRenderer child in children) {
+                       int renderer_width, renderer_height;
+
+                       child.get_size (widget, null, null, null, out renderer_width, out renderer_height);
+                       if ((renderer_width > 0) && (renderer_height > 0)) {
+                               calc_width = int.max (calc_width, renderer_width);
+                               calc_height += renderer_height;
+                       }
+               }
+
+               int full_width = (int) xpad * 2 + calc_width;
+               int full_height = (int) ypad * 2 + calc_height;
+
+               if ((rectangle != null) && calc_width > 0 && calc_height > 0) {
+                       if (&x_offset != null) {
+                               x_offset = (int) (((widget.get_direction () == TextDirection.RTL) ? (1.0 - xalign) : xalign) * (rectangle.width - full_width));
+                               x_offset = int.max (x_offset, 0);
+                       }
+                       if (&y_offset != null) {
+                               y_offset = (int) (yalign * (rectangle.height - full_height));
+                               y_offset = int.max (y_offset, 0);
+                       }
+               } else {
+                       if (&x_offset != null)
+                               x_offset = 0;
+                       if (&y_offset != null)
+                               y_offset = 0;
+               }
+
+               if (&width != null)
+                       width = full_width;
+               if (&height != null)
+                       height = full_height;
+       }
+
+       public override void render (Gdk.Window window, Widget widget, Gdk.Rectangle background_area, Gdk.Rectangle cell_area, Gdk.Rectangle expose_area, CellRendererState flags) {
+               int nvis_children = 0;
+               int nexpand_children = 0;
+               int height, extra;
+
+               // Counts visible and expandable children cell renderers
+               foreach (CellRenderer child in children) {
+                       bool visible, expand;
+
+                       child.get ("visible", out visible);
+                       expand = child.get_data ("box-expand");
+
+                       if (visible) {
+                               nvis_children += 1;
+                               if (expand)
+                                       nexpand_children += 1;
+                       }
+               }
+
+               if (nvis_children > 0) {
+                       int x_pad, y_pad;
+                       int y;
+                       var child_alloc = Gdk.Rectangle ();
+
+                       if (nexpand_children > 0) {
+                               var req = Requisition ();
+
+                               get_size (widget, null, null, null, out req.width, out req.height);
+                               height = cell_area.height - req.height;
+                               extra = height / nexpand_children;
+                       } else {
+                               height = 0;
+                               extra = 0;
+                       }
+
+                       get ("xpad", out x_pad, "ypad", out y_pad);
+                       y = cell_area.y + y_pad;
+                       child_alloc.x = cell_area.x + x_pad;
+                       child_alloc.width = int.max (1, cell_area.width - x_pad * 2);
+
+                       foreach (CellRenderer child in children) {
+                               bool visible, expand;
+
+                               child.get ("visible", out visible);
+                               expand = child.get_data ("box-expand");
+
+                               if (visible) {
+                                       var child_req = Requisition ();
+                                       int child_xpad, child_ypad;
+                                       var child_expose_area = Gdk.Rectangle ();
+
+                                       child.get_size (widget, null, null, null, out child_req.width, out child_req.height);
+                                       child.get ("xpad", out child_xpad, "ypad", out child_ypad);
+
+                                       if (expand) {
+                                               if (nexpand_children == 1)
+                                                       child_req.height += height;
+                                               else
+                                                       child_req.height += extra;
+                                               nexpand_children -= 1;
+                                               height -= extra;
+                                       }
+
+                                       child_alloc.height = int.max (1, child_req.height);
+                                       child_alloc.y = y;
+
+                                       if (child_alloc.intersect (expose_area, child_expose_area)) {
+                                               child.render (window, widget, background_area, child_alloc, child_expose_area, flags);
+                                       }
+                                       y += child_req.height;
+                               }
+                       }
+               }
+       }
+}
index c1a2611..4c59c5e 100644 (file)
@@ -22,6 +22,16 @@ using Hildon;
 public class LiftListWindow : StackableWindow {
        public const string GCONF_KEY_PRELOAD = "/apps/beifahrer/preload";
 
+       enum Columns {
+               ROUTE,
+               SECONDARY,
+               DATETIME,
+               PLACES,
+               PRICE,
+               SMOKER,
+               LIFT
+       }
+
        AdacMitfahrclub adac;
        ListStore store;
        TreeSortable sortable;
@@ -56,7 +66,7 @@ public class LiftListWindow : StackableWindow {
                set_main_menu (menu);
 
                gconf = GConf.Client.get_default ();
-               store = new ListStore (6, typeof (string), typeof (string), typeof (string), typeof (string), typeof (string), typeof (Lift));
+               store = new ListStore (7, typeof (string), typeof (string), typeof (string), typeof (string), typeof (string), typeof (string), typeof (Lift));
                sortable = new TreeModelSort.with_model (store);
 
                alignment = new Alignment (0.0f, 0.0f, 1.0f, 1.0f);
@@ -74,36 +84,69 @@ public class LiftListWindow : StackableWindow {
                var selection = tree.get_selection ();
                selection.set_mode (SelectionMode.SINGLE);
 
-               // Source and destination column
-               route_column = new TreeViewColumn.with_attributes ("Route", new CellRendererText (), "markup", 0);
+               // Source - destination / driver column
+               var route_column = new TreeViewColumn ();
+               route_column.set_title (_("Route"));
                route_column.set_reorderable (false);
                route_column.set_sizing (TreeViewColumnSizing.AUTOSIZE);
                route_column.set_expand (true);
                tree.append_column (route_column);
 
+               var vbox_renderer = new CellRendererVBox ();
+
+               var renderer = new CellRendererText ();
+               renderer.yalign = 1.0f;
+               renderer.set_fixed_size (-1, 32);
+               vbox_renderer.append (renderer, true);
+               vbox_renderer.set_data ("route-renderer", renderer);
+
+               // Add secondary text to column (driver name, route details)
+               renderer = new CellRendererText ();
+               renderer.yalign = 0;
+               renderer.set_fixed_size (-1, 32);
+               renderer.ellipsize = Pango.EllipsizeMode.END;
+               Pango.AttrList attr_list = new Pango.AttrList ();
+               var style = Gtk.rc_get_style_by_paths (Gtk.Settings.get_default (), "SmallSystemFont", null, typeof (void));
+               if (style != null) {
+                       var attr_font_desc = new Pango.AttrFontDesc (style.font_desc.copy ());
+                       attr_list.insert ((owned) attr_font_desc);
+               }
+               Gdk.Color color;
+               this.ensure_style ();
+               if (this.style.lookup_color ("SecondaryTextColor", out color)) {
+                       Pango.Attribute attr_color = Pango.attr_foreground_new (color.red, color.green, color.blue);
+                       attr_list.insert ((owned) attr_color);
+               }
+               renderer.attributes = attr_list;
+               vbox_renderer.append (renderer, true);
+               vbox_renderer.set_data ("secondary-renderer", renderer);
+
+               route_column.pack_start (vbox_renderer, true);
+               route_column.set_cell_data_func (vbox_renderer, vbox_data_func);
+
                // Date and time column
-               var datetime_column = new TreeViewColumn.with_attributes ("DateTime", new CellRendererText (), "text", 1);
+               var datetime_column = new TreeViewColumn.with_attributes ("DateTime", new CellRendererText (), "text", Columns.DATETIME);
                datetime_column.set_reorderable (false);
                datetime_column.set_sizing (TreeViewColumnSizing.AUTOSIZE);
                datetime_column.set_expand (true);
                tree.append_column (datetime_column);
 
                // Free places column
-               var places_column = new TreeViewColumn.with_attributes ("Places", new CellRendererText (), "text", 2);
+               var places_column = new TreeViewColumn.with_attributes ("Places", new CellRendererText (), "text", Columns.PLACES);
                places_column.set_reorderable (false);
                places_column.set_sizing (TreeViewColumnSizing.AUTOSIZE);
                places_column.set_expand (true);
                tree.append_column (places_column);
 
                // Price column
-               var price_column = new TreeViewColumn.with_attributes ("Price", new CellRendererText (), "text", 3);
+               var price_column = new TreeViewColumn.with_attributes ("Price", new CellRendererText (), "text", Columns.PRICE);
                price_column.set_reorderable (false);
                price_column.set_sizing (TreeViewColumnSizing.AUTOSIZE);
                price_column.set_expand (true);
                tree.append_column (price_column);
 
                // Smoker/Non-smoker column
-               var smoke_column = new TreeViewColumn.with_attributes ("Smoker", new CellRendererPixbuf (), "icon-name", 4);
+               var smoke_column = new TreeViewColumn.with_attributes ("Smoker", new CellRendererPixbuf (), "icon-name", Columns.SMOKER);
                smoke_column.set_reorderable (false);
                smoke_column.set_sizing (TreeViewColumnSizing.AUTOSIZE);
                smoke_column.set_expand (false);
@@ -134,14 +177,27 @@ public class LiftListWindow : StackableWindow {
                goto_website.clicked.connect (on_goto_website_clicked);
                sort_by_time.toggled.connect (button => {
                        if (button.get_active ())
-                               sortable.set_sort_column_id (1, Gtk.SortType.ASCENDING);
+                               sortable.set_sort_column_id (Columns.DATETIME, Gtk.SortType.ASCENDING);
                });
                sort_by_price.toggled.connect (button => {
                        if (button.get_active ())
-                               sortable.set_sort_column_id (3, Gtk.SortType.ASCENDING);
+                               sortable.set_sort_column_id (Columns.PRICE, Gtk.SortType.ASCENDING);
                });
        }
 
+       private void vbox_data_func (CellLayout cell_layout, CellRenderer cell, TreeModel model, TreeIter iter) {
+               unowned string text;
+               CellRendererText renderer;
+
+               model.get (iter, Columns.ROUTE, out text);
+               renderer = cell.get_data ("route-renderer");
+               renderer.text = text;
+
+               model.get (iter, Columns.SECONDARY, out text);
+               renderer = cell.get_data ("secondary-renderer");
+               renderer.text = text;
+       }
+
        public async void find_lifts (string city_from, int radius_from, string city_to, int radius_to, Date date, int tolerance = 0) {
                TreeIter iter;
                set_title ("%s - %s".printf (city_from, city_to));
@@ -161,12 +217,13 @@ public class LiftListWindow : StackableWindow {
                        string datetime = "%02d.%02d.%04d".printf (lift.time.day, lift.time.month, lift.time.year);
                        if (lift.time.hour >= 0)
                                datetime += ", %d:%02d".printf (lift.time.hour, lift.time.minute);
-                       store.insert_with_values (out iter, -1, 0, lift.city_from + " - " + lift.city_to,
-                                                               1, datetime,
-                                                               2, _("%d pl.").printf (lift.places),
-                                                               3, lift.price,
-                                                               4, icon_name,
-                                                               5, lift);
+                       store.insert_with_values (out iter, -1, Columns.ROUTE, lift.city_from + " - " + lift.city_to,
+                                                               Columns.SECONDARY, "",
+                                                               Columns.DATETIME, datetime,
+                                                               Columns.PLACES, _("%d pl.").printf (lift.places),
+                                                               Columns.PRICE, lift.price,
+                                                               Columns.SMOKER, icon_name,
+                                                               Columns.LIFT, lift);
                        // (LiftFlags.WOMEN_ONLY,ADAC_MEMBER in lift.flags)
                }
                if (lift_list.length () > 6)
@@ -182,12 +239,12 @@ public class LiftListWindow : StackableWindow {
                if (preload) {
                        if (store.get_iter_first (out iter)) do {
                                Lift lift2;
-                               store.@get (iter, 5, out lift2);
+                               store.@get (iter, Columns.LIFT, out lift2);
                                if (lift2 == null)
                                        continue;
                                if (lift2.description == null) {
                                        yield adac.update_lift_details (lift2);
-                                       store.@set (iter, 0, lift2.city_from + " - " + lift2.city_to + "\n<small>" + lift2.name + "</small>");
+                                       store.@set (iter, Columns.SECONDARY, lift2.name);
                                }
                        } while (store.iter_next (ref iter));
                }
@@ -205,7 +262,7 @@ public class LiftListWindow : StackableWindow {
                Lift lift;
 
                if (model.get_iter (out iter, path)) {
-                       model.get (iter, 5, out lift);
+                       model.get (iter, Columns.LIFT, out lift);
 
                        var window = new LiftDetailWindow (adac, lift);
                        window.show ();