[gnome-contacts/new-design] Separate out the common row stuff into rowgroup



commit 416a6fc9f4d7415f2aa14a108e4e1433a3cdf315
Author: Alexander Larsson <alexl redhat com>
Date:   Mon Dec 12 11:11:01 2011 +0100

    Separate out the common row stuff into rowgroup

 src/contacts-contact-pane.vala |   29 ++--
 src/contacts-row.vala          |  354 +++++++++++++++++++++-------------------
 2 files changed, 204 insertions(+), 179 deletions(-)
---
diff --git a/src/contacts-contact-pane.vala b/src/contacts-contact-pane.vala
index 5417e74..47d8836 100644
--- a/src/contacts-contact-pane.vala
+++ b/src/contacts-contact-pane.vala
@@ -416,17 +416,10 @@ public class Contacts.AvatarMenu : Menu {
 public class Contacts.FieldRow : Contacts.Row {
   int start;
 
-  public FieldRow(ContactPane pane) {
-    base (3);
+  public FieldRow(RowGroup group) {
+    base (group);
 
     start = 0;
-
-    set_column_min_width (0, 32);
-    set_column_min_width (1, 400);
-    set_column_max_width (1, 450);
-    set_column_min_width (2, 32);
-    set_column_spacing (0, 8);
-    set_column_spacing (1, 8);
   }
 
   public void pack (Widget w) {
@@ -514,7 +507,7 @@ public class Contacts.PersonaSheet : Grid {
     construct {
       this.set_orientation (Orientation.VERTICAL);
 
-      label_row = new FieldRow (sheet.pane);
+      label_row = new FieldRow (sheet.pane.row_group);
       this.add (label_row);
       label_row.label (label_name);
     }
@@ -536,7 +529,7 @@ public class Contacts.PersonaSheet : Grid {
     }
 
     public FieldRow new_row () {
-      var row = new FieldRow (sheet.pane);
+      var row = new FieldRow (sheet.pane.row_group);
       this.add (row);
       return row;
     }
@@ -733,7 +726,7 @@ public class Contacts.PersonaSheet : Grid {
       Contact.persona_has_writable_property (persona, "postal-addresses");
 
     if (!persona.store.is_primary_store) {
-      header = new FieldRow (pane);
+      header = new FieldRow (pane.row_group);
       this.attach (header, 0, row_nr++, 1, 1);
 
       header.header (Contact.format_persona_store_name (persona.store));
@@ -756,7 +749,7 @@ public class Contacts.PersonaSheet : Grid {
     }
 
     if (editable) {
-      footer = new FieldRow (pane);
+      footer = new FieldRow (pane.row_group);
       this.attach (footer, 0, row_nr++, 1, 1);
 
       var b = new Button.with_label ("Add detail...");
@@ -774,6 +767,7 @@ public class Contacts.ContactPane : ScrolledWindow {
   private Grid top_grid;
   private Grid card_grid;
   private Grid personas_grid;
+  public RowGroup row_group;
 
   private Contact? contact;
 
@@ -912,6 +906,13 @@ public class Contacts.ContactPane : ScrolledWindow {
 
   public ContactPane (Store contacts_store) {
     this.contacts_store = contacts_store;
+    row_group = new RowGroup(3);
+    row_group.set_column_min_width (0, 32);
+    row_group.set_column_min_width (1, 400);
+    row_group.set_column_max_width (1, 450);
+    row_group.set_column_min_width (2, 32);
+    row_group.set_column_spacing (0, 8);
+    row_group.set_column_spacing (1, 8);
 
     this.set_hexpand (true);
     this.set_vexpand (true);
@@ -927,7 +928,7 @@ public class Contacts.ContactPane : ScrolledWindow {
 
     this.get_child().get_style_context ().add_class ("contact-pane");
 
-    var top_row = new FieldRow (this);
+    var top_row = new FieldRow (row_group);
     top_grid.add (top_row);
     card_grid = new Grid ();
     card_grid.set_vexpand (false);
diff --git a/src/contacts-row.vala b/src/contacts-row.vala
index 3361105..4851606 100644
--- a/src/contacts-row.vala
+++ b/src/contacts-row.vala
@@ -18,49 +18,53 @@
 
 using Gtk;
 
-public class Contacts.Row : Container {
-  struct RowInfo {
-    int min_height;
-    int nat_height;
-    bool expand;
-  }
-
-  struct ColumnInfo {
+public class Contacts.RowGroup : Object {
+  public struct ColumnInfo {
     int min_width;
     int nat_width;
     int max_width;
     int prio;
     int spacing;
   }
-  struct Child {
-    Widget? widget;
-  }
 
-  int n_columns;
-  int n_rows;
-  ColumnInfo[] column_info;
-  Child[,] row_children;
+  public int n_columns;
+  private ColumnInfo[] column_info;
 
   int[] cached_widths;
   int cached_widths_for_width;
 
-  public Row (int n_columns) {
-    int i;
-
-    set_has_window (false);
-    set_redraw_on_allocate (false);
-    set_hexpand (true);
+  Gee.ArrayList<unowned Row> rows;
 
+  public RowGroup (int n_columns) {
     this.n_columns = n_columns;
-    n_rows = 1;
-    row_children = new Child[n_columns, n_rows];
+
     column_info = new ColumnInfo[n_columns];
-    for (i = 0; i < n_columns; i++) {
+    for (int i = 0; i < n_columns; i++) {
       column_info[i].min_width = 0;
       column_info[i].nat_width = -1;
       column_info[i].max_width = -1;
       column_info[i].prio = 0;
     }
+
+    rows = new Gee.ArrayList<Row>();
+  }
+
+  public unowned ColumnInfo? get_column_info (int col) {
+    return column_info[col];
+  }
+
+  public void add (Row row) {
+    rows.add (row);
+    row.destroy.connect ( (widget) => {
+	rows.remove (row);
+      });
+  }
+
+  private void queue_resize () {
+    foreach (unowned Row row in rows) {
+      if (row.get_visible ())
+	row.queue_resize ();
+    }
   }
 
   public void set_column_priority (int column, int priority) {
@@ -70,8 +74,7 @@ public class Contacts.Row : Container {
     column_info[column].prio = priority;
 
     cached_widths = null;
-    if (this.get_visible ())
-      this.queue_resize ();
+    queue_resize ();
   }
 
   public void set_column_min_width (int column, int min_width) {
@@ -80,8 +83,7 @@ public class Contacts.Row : Container {
 
     column_info[column].min_width = min_width;
     cached_widths = null;
-    if (this.get_visible ())
-      this.queue_resize ();
+    queue_resize ();
   }
 
   public void set_column_max_width (int column, int max_width) {
@@ -90,8 +92,7 @@ public class Contacts.Row : Container {
 
     column_info[column].max_width = max_width;
     cached_widths = null;
-    if (this.get_visible ())
-      this.queue_resize ();
+    queue_resize ();
   }
 
   public void set_column_spacing (int column, int spacing) {
@@ -100,43 +101,167 @@ public class Contacts.Row : Container {
 
     column_info[column].spacing = spacing;
     cached_widths = null;
-    if (this.get_visible ())
-      this.queue_resize ();
+    queue_resize ();
   }
 
-  public void attach (Widget widget, int attach_col, int attach_row) {
-    if (attach_col >= n_columns || attach_row >= n_rows) {
-      int old_n_columns = n_columns;
-      int old_n_rows = n_rows;
+  public int[] distribute_widths (int width) {
+    if (cached_widths != null &&
+	cached_widths_for_width == width)
+      return cached_widths;
+
+    int max_prio = 0;
+    var widths = new int[n_columns];
+
+    /* First distribute the min widths */
+    for (int i = 0; i < n_columns; i++) {
+      var info = &column_info[i];
+
+      if (info->prio > max_prio)
+	max_prio = info->prio;
+
+      if (width > info.min_width) {
+	widths[i] = info.min_width;
+	width -= info.min_width;
+      } else if (width > 0) {
+	widths[i] = width;
+	width = 0;
+      } else {
+	widths[i] = 0;
+      }
+      width -= info.spacing;
+    }
 
-      if (attach_col >= n_columns) {
-	n_columns = attach_col + 1;
+    /* Distribute remaining width equally among
+       children with same priority, up to max */
+    for (int prio = max_prio; width > 0 && prio >= 0; prio--) {
+      int n_children;
 
-	var old_column_info = (owned)column_info;
-	column_info = new ColumnInfo[n_columns];
+      while (width > 0) {
+	n_children = 0;
+	int max_extra = width;
 
 	for (int i = 0; i < n_columns; i++) {
-	  if (i < old_n_columns)
-	    column_info[i] = old_column_info[i];
-	  else {
-	    column_info[i].min_width = 0;
-	    column_info[i].nat_width = -1;
-	    column_info[i].max_width = -1;
-	    column_info[i].prio = 0;
+	  var info = &column_info[i];
+
+	  if (info.prio == prio &&
+	      (info.max_width < 0 ||
+	       widths[i] < info.max_width)) {
+	    n_children++;
+
+	    if (info.max_width >= 0 &&
+		info.max_width - widths[i] < max_extra)
+	      max_extra = info.max_width - widths[i];
+	  }
+	}
+
+	if (n_children == 0)
+	  break; // No more unsatisfied children on this prio
+
+	int distribute = int.min (width, max_extra * n_children);
+	width -= distribute;
+
+	int per_child = distribute / n_children;
+	int per_child_extra = distribute % n_children;
+	int per_child_extra_sum = 0;
+
+	for (int i = 0; i < n_columns; i++) {
+	  var info = &column_info[i];
+
+	  if (info.prio == prio &&
+	      (info.max_width < 0 ||
+	       widths[i] < info.max_width)) {
+	    widths[i] += per_child;
+	    per_child_extra_sum += per_child_extra;
+	    if (per_child_extra_sum > distribute) {
+	      widths[i] += 1;
+	      per_child_extra_sum -= distribute;
+	    }
 	  }
 	}
       }
+    }
+
+    cached_widths = widths;
+    cached_widths_for_width = width;
+    return widths;
+  }
+
+  public void get_width (out int minimum_width, out int natural_width) {
+    minimum_width = 0;
+    natural_width = 0;
+
+    for (int i = 0; i < n_columns; i++) {
+      minimum_width += column_info[i].min_width;
+      if (column_info[i].nat_width >= 0)
+	natural_width += column_info[i].nat_width;
+      else if (column_info[i].max_width >= 0)
+	natural_width += column_info[i].max_width;
+      else
+	natural_width += column_info[i].min_width;
+      minimum_width += column_info[i].spacing;
+      natural_width += column_info[i].spacing;
+    }
+  }
+
+  public bool is_expanding () {
+    for (int i = 0; i < n_columns; i++) {
+      var info = &column_info[i];
+      if (info.max_width == -1 &&
+	  info.max_width !=  info.min_width) {
+	return true;
+      }
+    }
+    return false;
+  }
+}
+
+public class Contacts.Row : Container {
+  struct RowInfo {
+    int min_height;
+    int nat_height;
+    bool expand;
+  }
+
+  struct Child {
+    Widget? widget;
+  }
+
+  RowGroup group;
+  int n_rows;
+  Child[,] row_children;
+
+  public Row (RowGroup group) {
+    int i;
+
+    this.group = group;
+    group.add (this);
 
-      if (attach_row >= n_rows)
-	n_rows = attach_row + 1;
+    set_has_window (false);
+    set_redraw_on_allocate (false);
+    set_hexpand (true);
+
+    n_rows = 1;
+    row_children = new Child[group.n_columns, n_rows];
+  }
+
+  public void attach (Widget widget, int attach_col, int attach_row) {
+    if (attach_col >= group.n_columns) {
+      warning ("Tryint to attach widget to non-existing column");
+      return;
+    }
+
+    if (attach_row >= n_rows) {
+      int old_n_rows = n_rows;
+
+      n_rows = attach_row + 1;
 
       var old_row_children = (owned)row_children;
-      row_children = new Child[n_columns, n_rows];
+      row_children = new Child[group.n_columns, n_rows];
 
       for (int row = 0; row < n_rows; row++) {
-	for (int col = 0; col < n_columns; col++) {
+	for (int col = 0; col < group.n_columns; col++) {
 	  if (row < old_n_rows &&
-	      col < old_n_columns) {
+	      col < group.n_columns) {
 	    row_children[col, row] = (owned)old_row_children[col, row];
 	  }
 	}
@@ -154,7 +279,7 @@ public class Contacts.Row : Container {
 
   public override void add (Widget widget) {
     for (int row = 0; row < n_rows; row++) {
-      for (int col = 0; col < n_columns; col++) {
+      for (int col = 0; col < group.n_columns; col++) {
 	Child *child_info = &row_children[col, row];
 	if (child_info.widget == null) {
 	  attach (widget, col, row);
@@ -167,7 +292,7 @@ public class Contacts.Row : Container {
 
   public override void remove (Widget widget) {
     for (int row = 0; row < n_rows; row++) {
-      for (int col = 0; col < n_columns; col++) {
+      for (int col = 0; col < group.n_columns; col++) {
 	Child *child_info = &row_children[col, row];
 	if (child_info.widget == widget) {
           bool was_visible = widget.get_visible ();
@@ -188,7 +313,7 @@ public class Contacts.Row : Container {
   public override void forall_internal (bool include_internals,
 					Gtk.Callback callback) {
     for (int row = 0; row < n_rows; row++) {
-      for (int col = 0; col < n_columns; col++) {
+      for (int col = 0; col < group.n_columns; col++) {
 	Child *child_info = &row_children[col, row];
 	if (child_info.widget != null) {
 	  callback (child_info.widget);
@@ -198,19 +323,11 @@ public class Contacts.Row : Container {
   }
 
   public override void compute_expand_internal (out bool hexpand, out bool vexpand) {
-    hexpand = false;
-    for (int i = 0; i < n_columns; i++) {
-      var info = &column_info[i];
-      if (info.max_width == -1 &&
-	  info.max_width !=  info.min_width) {
-	hexpand = true;
-	break;
-      }
-    }
+    hexpand = group.is_expanding ();
 
     vexpand = false;
     for (int row = 0; row < n_rows; row++) {
-      for (int col = 0; col < n_columns; col++) {
+      for (int col = 0; col < group.n_columns; col++) {
 	Child *child_info = &row_children[col, row];
 	if (child_info.widget != null) {
 	  vexpand |= child_info.widget.compute_expand (Orientation.VERTICAL);
@@ -233,87 +350,6 @@ public class Contacts.Row : Container {
     get_preferred_height_for_width (natural_width, out minimum_height, out natural_height);
   }
 
-  int[] distribute_widths (int width) {
-    if (cached_widths != null &&
-	cached_widths_for_width == width)
-      return cached_widths;
-
-    int max_prio = 0;
-    var widths = new int[n_columns];
-
-    /* First distribute the min widths */
-    for (int i = 0; i < n_columns; i++) {
-      ColumnInfo *info = &column_info[i];
-
-      if (info->prio > max_prio)
-	max_prio = info->prio;
-
-      if (width > info.min_width) {
-	widths[i] = info.min_width;
-	width -= info.min_width;
-      } else if (width > 0) {
-	widths[i] = width;
-	width = 0;
-      } else {
-	widths[i] = 0;
-      }
-      width -= info.spacing;
-    }
-
-    /* Distribute remaining width equally among
-       children with same priority, up to max */
-    for (int prio = max_prio; width > 0 && prio >= 0; prio--) {
-      int n_children;
-
-      while (width > 0) {
-	n_children = 0;
-	int max_extra = width;
-
-	for (int i = 0; i < n_columns; i++) {
-	  ColumnInfo *info = &column_info[i];
-
-	  if (info.prio == prio &&
-	      (info.max_width < 0 ||
-	       widths[i] < info.max_width)) {
-	    n_children++;
-
-	    if (info.max_width >= 0 &&
-		info.max_width - widths[i] < max_extra)
-	      max_extra = info.max_width - widths[i];
-	  }
-	}
-
-	if (n_children == 0)
-	  break; // No more unsatisfied children on this prio
-
-	int distribute = int.min (width, max_extra * n_children);
-	width -= distribute;
-
-	int per_child = distribute / n_children;
-	int per_child_extra = distribute % n_children;
-	int per_child_extra_sum = 0;
-
-	for (int i = 0; i < n_columns; i++) {
-	  ColumnInfo *info = &column_info[i];
-
-	  if (info.prio == prio &&
-	      (info.max_width < 0 ||
-	       widths[i] < info.max_width)) {
-	    widths[i] += per_child;
-	    per_child_extra_sum += per_child_extra;
-	    if (per_child_extra_sum > distribute) {
-	      widths[i] += 1;
-	      per_child_extra_sum -= distribute;
-	    }
-	  }
-	}
-      }
-    }
-
-    cached_widths = widths;
-    cached_widths_for_width = width;
-    return widths;
-  }
 
   int[] distribute_heights (int height, RowInfo[] row_info) {
     var heights = new int[n_rows];
@@ -389,7 +425,7 @@ public class Contacts.Row : Container {
       bool first = true;
       bool expand = false;
 
-      for (int col = 0; col < n_columns; col++) {
+      for (int col = 0; col < group.n_columns; col++) {
 	Child *child_info = &row_children[col, row];
 	if (child_info.widget != null) {
 	  int child_min, child_nat;
@@ -416,8 +452,8 @@ public class Contacts.Row : Container {
   }
 
   public override void get_preferred_height_for_width (int width, out int minimum_height, out int natural_height) {
-    var widths = distribute_widths (width);
-    var row_info =  get_row_heights_for_widths (widths);
+    var widths = group.distribute_widths (width);
+    var row_info = get_row_heights_for_widths (widths);
 
     minimum_height = 0;
     natural_height = 0;
@@ -429,19 +465,7 @@ public class Contacts.Row : Container {
   }
 
   public override void get_preferred_width (out int minimum_width, out int natural_width) {
-    minimum_width = 0;
-    natural_width = 0;
-    for (int i = 0; i < n_columns; i++) {
-      minimum_width += column_info[i].min_width;
-      if (column_info[i].nat_width >= 0)
-	natural_width += column_info[i].nat_width;
-      else if (column_info[i].max_width >= 0)
-	natural_width += column_info[i].max_width;
-      else
-	natural_width += column_info[i].min_width;
-      minimum_width += column_info[i].spacing;
-      natural_width += column_info[i].spacing;
-    }
+    group.get_width (out minimum_width, out natural_width);
   }
 
   public override void get_preferred_width_for_height (int height, out int minimum_width, out int natural_width) {
@@ -449,7 +473,7 @@ public class Contacts.Row : Container {
   }
 
   public override void size_allocate (Gtk.Allocation allocation) {
-    var widths = distribute_widths (allocation.width);
+    var widths = group.distribute_widths (allocation.width);
     var row_info = get_row_heights_for_widths (widths);
     var heights = distribute_heights (allocation.height, row_info);
 
@@ -458,7 +482,7 @@ public class Contacts.Row : Container {
     int y = 0;
     for (int row = 0; row < n_rows; row ++) {
       int x = 0;
-      for (int col = 0; col < n_columns; col++) {
+      for (int col = 0; col < group.n_columns; col++) {
 	Child *child_info = &row_children[col, row];
 	if (child_info.widget != null) {
 	  Allocation child_allocation = { 0, 0, 0, 0};
@@ -473,7 +497,7 @@ public class Contacts.Row : Container {
 	  child_allocation.y = allocation.y + y;
 	  child_info.widget.size_allocate (child_allocation);
 	}
-	x += widths[col] + column_info[col].spacing;
+	x += widths[col] + group.get_column_info (col).spacing;
       }
       y += heights[row];
     }



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