[hyena/canvas: 5/5] [Hyena.Data.Gui] Rebase on Hyena.Gui.Canvas



commit 0e9159ab9e5c125241aacab9b2f10ffe49d7269f
Author: Gabriel Burt <gabriel burt gmail com>
Date:   Thu Oct 21 18:46:04 2010 -0500

    [Hyena.Data.Gui] Rebase on Hyena.Gui.Canvas

 Hyena.Gui/Hyena.Data.Gui/Column.cs                 |    4 +-
 Hyena.Gui/Hyena.Data.Gui/ColumnCell.cs             |   33 +--
 Hyena.Gui/Hyena.Data.Gui/ColumnCellCheckBox.cs     |   18 +-
 Hyena.Gui/Hyena.Data.Gui/ColumnCellRating.cs       |   15 +-
 Hyena.Gui/Hyena.Data.Gui/ColumnCellText.cs         |   32 ++-
 Hyena.Gui/Hyena.Data.Gui/ColumnHeaderCellText.cs   |    6 +-
 Hyena.Gui/Hyena.Data.Gui/DataViewChild.cs          |  254 ------------------
 Hyena.Gui/Hyena.Data.Gui/DataViewChildBox.cs       |  181 -------------
 Hyena.Gui/Hyena.Data.Gui/DataViewLayout.cs         |   46 +++-
 Hyena.Gui/Hyena.Data.Gui/DataViewLayoutGrid.cs     |   13 +-
 Hyena.Gui/Hyena.Data.Gui/ListView/ListViewBase.cs  |   11 +-
 .../ListView/ListView_Interaction.cs               |    6 +-
 .../Hyena.Data.Gui/ListView/ListView_Rendering.cs  |   22 +-
 Hyena.Gui/Hyena.Data.Gui/ListViewTestModule.cs     |  275 +++++++++++++-------
 Hyena.Gui/Makefile.am                              |    2 -
 Hyena/Hyena.Data/ObjectBinder.cs                   |  114 ++++++++
 Hyena/Makefile.am                                  |    1 +
 17 files changed, 419 insertions(+), 614 deletions(-)
---
diff --git a/Hyena.Gui/Hyena.Data.Gui/Column.cs b/Hyena.Gui/Hyena.Data.Gui/Column.cs
index 90e4238..d2e823a 100644
--- a/Hyena.Gui/Hyena.Data.Gui/Column.cs
+++ b/Hyena.Gui/Hyena.Data.Gui/Column.cs
@@ -75,7 +75,7 @@ namespace Hyena.Data.Gui
         }
 
         public Column (ColumnCell headerCell, string title, ColumnCell cell, double width, bool visible, int minWidth, int maxWidth)
-            : base (cell.Property, title, width, visible)
+            : base (cell.ObjectBinder.Property, title, width, visible)
         {
             min_width = minWidth;
             max_width = maxWidth;
@@ -195,7 +195,7 @@ namespace Hyena.Data.Gui
         public string Id {
             get {
                 if (id == null) {
-                    id = GetCell (0).SubProperty ?? GetCell (0).Property;
+                    id = GetCell (0).ObjectBinder.SubProperty ?? GetCell (0).ObjectBinder.Property;
                     id = StringUtil.CamelCaseToUnderCase (id);
                 }
                 return id;
diff --git a/Hyena.Gui/Hyena.Data.Gui/ColumnCell.cs b/Hyena.Gui/Hyena.Data.Gui/ColumnCell.cs
index 89512e0..6c95092 100644
--- a/Hyena.Gui/Hyena.Data.Gui/ColumnCell.cs
+++ b/Hyena.Gui/Hyena.Data.Gui/ColumnCell.cs
@@ -36,7 +36,7 @@ using Hyena.Data.Gui.Accessibility;
 
 namespace Hyena.Data.Gui
 {
-    public abstract class ColumnCell : DataViewChild
+    public abstract class ColumnCell : CanvasItem
     {
         public virtual Atk.Object GetAccessible (ICellAccessibleParent parent)
         {
@@ -50,13 +50,21 @@ namespace Hyena.Data.Gui
 
         public ColumnCell (string property, bool expand)
         {
-            Property = property;
+            Binder = ObjectBinder = new ObjectBinder () { Property = property };
             Expand = expand;
         }
 
+        public ObjectBinder ObjectBinder { get; private set; }
+
+        public object BoundObjectParent {
+            get { return ObjectBinder.BoundObjectParent; }
+        }
+
+        //public string Property { get; private set; }
+
         public void BindListItem (object item)
         {
-            BindDataItem (item);
+            Bind (item);
         }
 
         public virtual void NotifyThemeChange ()
@@ -68,30 +76,17 @@ namespace Hyena.Data.Gui
             return Gdk.Size.Empty;
         }
 
-        protected override void RenderCore (CellContext context)
+        protected override void ClippedRender (CellContext context)
         {
-            Render (context, context.State, Allocation.Width, Allocation.Height);
+            Render (context, ContentAllocation.Width, ContentAllocation.Height);
         }
 
-        public abstract void Render (CellContext context, StateType state, double cellWidth, double cellHeight);
+        public abstract void Render (CellContext context, double cellWidth, double cellHeight);
 
         public bool Expand { get; set; }
 
         public Size? FixedSize { get; set; }
 
-        public override Size Measure (Size available)
-        {
-            // FIXME
-            return FixedSize ?? new Size (0, 0);
-        }
-
-        public override void Invalidate ()
-        {
-            if (ParentLayout != null) {
-                base.Invalidate ();
-            }
-        }
-
         public override void Arrange ()
         {
         }
diff --git a/Hyena.Gui/Hyena.Data.Gui/ColumnCellCheckBox.cs b/Hyena.Gui/Hyena.Data.Gui/ColumnCellCheckBox.cs
index 444083a..28b2161 100644
--- a/Hyena.Gui/Hyena.Data.Gui/ColumnCellCheckBox.cs
+++ b/Hyena.Gui/Hyena.Data.Gui/ColumnCellCheckBox.cs
@@ -43,21 +43,23 @@ namespace Hyena.Data.Gui
 
         public override Size Measure (Size available)
         {
-            return new Size (Size + 2 * Xpad, Size + 2 * Ypad);
+            Width = Size + 2 * Xpad;
+            Height = Size + 2 * Ypad;
+            return DesiredSize = new Size (Width + Margin.X, Height + Margin.Y);
         }
 
-        public override void Render (CellContext context, StateType state, double cellWidth, double cellHeight)
+        public override void Render (CellContext context, double cellWidth, double cellHeight)
         {
             int cell_width = (int)cellWidth - 2 * Xpad;
             int cell_height = (int)cellHeight - 2 * Ypad;
             int x = context.Area.X + xpad + ((cell_width - Size) / 2);
             int y = context.Area.Y + ypad + ((cell_height - Size) / 2);
 
-            if (state == StateType.Normal && last_hover_bound == BoundObjectParent) {
-                state = StateType.Prelight;
+            if (context.State == StateType.Normal && last_hover_bound == BoundObjectParent) {
+                context.State = StateType.Prelight;
             }
 
-            Style.PaintCheck (context.Widget.Style, context.Drawable, state,
+            Style.PaintCheck (context.Widget.Style, context.Drawable, context.State,
                 Value ? ShadowType.In : ShadowType.Out,
                 context.Clip, context.Widget, "cellcheck", x, y, Size, Size);
         }
@@ -81,7 +83,7 @@ namespace Hyena.Data.Gui
                     handler (BoundObjectParent, EventArgs.Empty);
                 }
 
-                Invalidate ();
+                InvalidateRender ();
             }
 
             return true;
@@ -94,7 +96,7 @@ namespace Hyena.Data.Gui
             }
 
             last_hover_bound = BoundObjectParent;
-            Invalidate ();
+            InvalidateRender ();
             return true;
         }
 
@@ -102,7 +104,7 @@ namespace Hyena.Data.Gui
         {
             base.CursorLeaveEvent ();
             last_hover_bound = null;
-            Invalidate ();
+            InvalidateRender ();
             return true;
         }
 
diff --git a/Hyena.Gui/Hyena.Data.Gui/ColumnCellRating.cs b/Hyena.Gui/Hyena.Data.Gui/ColumnCellRating.cs
index 640cd93..0346389 100644
--- a/Hyena.Gui/Hyena.Data.Gui/ColumnCellRating.cs
+++ b/Hyena.Gui/Hyena.Data.Gui/ColumnCellRating.cs
@@ -50,10 +50,12 @@ namespace Hyena.Data.Gui
 
         public override Size Measure (Size available)
         {
-            return new Size (renderer.Width, renderer.Height);
+            Width = renderer.Width;
+            Height = renderer.Height;
+            return DesiredSize = new Size (Width + Margin.X, Height + Margin.Y);
         }
 
-        public override void Render (CellContext context, StateType state, double cellWidth, double cellHeight)
+        public override void Render (CellContext context, double cellWidth, double cellHeight)
         {
             Gdk.Rectangle area = new Gdk.Rectangle (0, 0, (int)cellWidth, (int)cellHeight);
 
@@ -61,7 +63,7 @@ namespace Hyena.Data.Gui
 
             renderer.Value = Value;
             bool is_hovering = hover_bound == BoundObjectParent && hover_bound != null;
-            renderer.Render (context.Context, area, context.Theme.Colors.GetWidgetColor (GtkColorClass.Text, state),
+            renderer.Render (context.Context, area, context.Theme.Colors.GetWidgetColor (GtkColorClass.Text, context.State),
                 is_hovering, is_hovering, hover_value, 0.8, 0.45, 0.35);
 
             // FIXME: Something is hosed in the view when computing cell dimensions
@@ -84,7 +86,7 @@ namespace Hyena.Data.Gui
 
             if (last_pressed_bound == BoundObjectParent && last_pressed_bound != null) {
                 Value = RatingFromPosition (press.X);
-                Invalidate ();
+                InvalidateRender ();
                 last_pressed_bound = null;
             }
 
@@ -98,14 +100,13 @@ namespace Hyena.Data.Gui
             }
 
             int value = RatingFromPosition (motion.X);
-
             if (hover_bound == BoundObjectParent && value == hover_value) {
                 return false;
             }
 
             hover_bound = BoundObjectParent;
             hover_value = value;
-            Invalidate ();
+            InvalidateRender ();
             return true;
         }
 
@@ -114,7 +115,7 @@ namespace Hyena.Data.Gui
             base.CursorLeaveEvent ();
             hover_bound = null;
             hover_value = MinRating - 1;
-            Invalidate ();
+            InvalidateRender ();
             return true;
         }
 
diff --git a/Hyena.Gui/Hyena.Data.Gui/ColumnCellText.cs b/Hyena.Gui/Hyena.Data.Gui/ColumnCellText.cs
index 7662b69..4812a64 100644
--- a/Hyena.Gui/Hyena.Data.Gui/ColumnCellText.cs
+++ b/Hyena.Gui/Hyena.Data.Gui/ColumnCellText.cs
@@ -54,6 +54,7 @@ namespace Hyena.Data.Gui
         public ColumnCellText (string property, bool expand) : base (property, expand)
         {
             Padding = new Thickness (4, 0);
+            SingleParagraphMode = true;
         }
 
         public override Atk.Object GetAccessible (ICellAccessibleParent parent)
@@ -79,13 +80,13 @@ namespace Hyena.Data.Gui
             RestrictSize = true;
         }
 
-        int? height;
-        public override Size Measure (Size available)
-        {
+        //int? height;
+        //public override Size Measure (Size available)
+        //{
             //int min, max;
             //GetWidthRange (ParentLayout.View.PangoLayout, out min, out max);
             //
-            if (height == null) {
+            /*if (height == null) {
                 using (var layout = new Pango.Layout (ParentLayout.View.PangoContext)) {
                     if (layout.FontDescription == null) {
                         layout.FontDescription = new Pango.FontDescription ();
@@ -93,12 +94,12 @@ namespace Hyena.Data.Gui
                     UpdateText (layout, 100, "Woo Mar");
                     height = TextHeight;
                 }
-            }
+            }*/
 
-            return FixedSize ?? new Size (0, (double)height + Padding.Y);
-        }
+            //return FixedSize ?? new Size (0, (double)height + Padding.Y);
+        //}
 
-        public override void Render (CellContext context, StateType state, double cellWidth, double cellHeight)
+        public override void Render (CellContext context, double cellWidth, double cellHeight)
         {
             UpdateText (context, cellWidth);
             if (String.IsNullOrEmpty (last_text)) {
@@ -109,7 +110,7 @@ namespace Hyena.Data.Gui
             //context.Context.Clip ();
             context.Context.MoveTo (Padding.Left, ((int)cellHeight - text_height) / 2);
             Cairo.Color color = context.Theme.Colors.GetWidgetColor (
-                context.TextAsForeground ? GtkColorClass.Foreground : GtkColorClass.Text, state);
+                context.TextAsForeground ? GtkColorClass.Foreground : GtkColorClass.Text, context.State);
             color.A = Alpha ?? (context.Opaque ? 1.0 : 0.5);
             context.Context.Color = color;
 
@@ -133,6 +134,7 @@ namespace Hyena.Data.Gui
             layout.FontDescription.Weight = font_weight;
             layout.Ellipsize = EllipsizeMode;
             layout.Alignment = alignment;
+            layout.SingleParagraphMode = SingleParagraphMode;
             UpdateLayout (layout, text);
             layout.GetPixelSize (out text_width, out text_height);
             is_ellipsized = layout.IsEllipsized;
@@ -142,7 +144,7 @@ namespace Hyena.Data.Gui
         private void UpdateLayout (Pango.Layout layout, string text)
         {
             string final_text = GetFormattedText (text);
-            if (final_text.IndexOfAny (lfcr) >= 0) {
+            if (SingleParagraphMode && final_text.IndexOfAny (lfcr) >= 0) {
                 final_text = final_text.Replace ("\r\n", "\x20").Replace ('\n', '\x20').Replace ('\r', '\x20');
             }
             if (use_markup) {
@@ -158,9 +160,15 @@ namespace Hyena.Data.Gui
             return IsEllipsized ? GLib.Markup.EscapeText (Text) : null;
         }
 
+        public Func<object, string> TextGenerator { get; set; }
+
         protected virtual string GetText (object obj)
         {
-            return obj == null ? String.Empty : obj.ToString ();
+            if (TextGenerator != null) {
+                return TextGenerator (obj);
+            } else {
+                return obj == null ? String.Empty : obj.ToString ();
+            }
         }
 
         private string GetFormattedText (string text)
@@ -203,6 +211,8 @@ namespace Hyena.Data.Gui
             set { font_weight = value; }
         }
 
+        public bool SingleParagraphMode { get; set; }
+
         public virtual Pango.EllipsizeMode EllipsizeMode {
             get { return ellipsize_mode; }
             set { ellipsize_mode = value; }
diff --git a/Hyena.Gui/Hyena.Data.Gui/ColumnHeaderCellText.cs b/Hyena.Gui/Hyena.Data.Gui/ColumnHeaderCellText.cs
index e661627..3110bb0 100644
--- a/Hyena.Gui/Hyena.Data.Gui/ColumnHeaderCellText.cs
+++ b/Hyena.Gui/Hyena.Data.Gui/ColumnHeaderCellText.cs
@@ -52,14 +52,14 @@ namespace Hyena.Data.Gui
             return new  ColumnHeaderCellTextAccessible (BoundObject, this, parent);
         }
 
-        public override void Render (CellContext context, StateType state, double cellWidth, double cellHeight)
+        public override void Render (CellContext context, double cellWidth, double cellHeight)
         {
             if (data_handler == null) {
                 return;
             }
 
             if (!has_sort) {
-                base.Render (context, state, cellWidth, cellHeight);
+                base.Render (context, cellWidth, cellHeight);
                 return;
             }
 
@@ -71,7 +71,7 @@ namespace Hyena.Data.Gui
 
             double textWidth = arrow_alloc.X - Padding.Left;
             if (textWidth > 0) {
-                base.Render (context, state, textWidth, cellHeight);
+                base.Render (context, textWidth, cellHeight);
             }
 
             SortType sort_type = ((ISortableColumn)data_handler ()).SortType;
diff --git a/Hyena.Gui/Hyena.Data.Gui/DataViewLayout.cs b/Hyena.Gui/Hyena.Data.Gui/DataViewLayout.cs
index 6609dfc..6a7cc1a 100644
--- a/Hyena.Gui/Hyena.Data.Gui/DataViewLayout.cs
+++ b/Hyena.Gui/Hyena.Data.Gui/DataViewLayout.cs
@@ -36,13 +36,25 @@ namespace Hyena.Data.Gui
 {
     public abstract class DataViewLayout
     {
-        private List<DataViewChild> children = new List<DataViewChild> ();
-        protected List<DataViewChild> Children {
+        private List<CanvasItem> children = new List<CanvasItem> ();
+        protected List<CanvasItem> Children {
             get { return children; }
         }
 
+        private Dictionary<CanvasItem, int> model_indices = new Dictionary<CanvasItem, int> ();
+
         public IListModel Model { get; set; }
-        public ListViewBase View { get; set; }
+
+        protected CanvasManager CanvasManager;
+
+        private ListViewBase view;
+        public ListViewBase View {
+            get { return view; }
+            set {
+                view = value;
+                CanvasManager = new CanvasManager (view);
+            }
+        }
 
         public Rect ActualAllocation { get; protected set; }
         public Size VirtualSize { get; protected set; }
@@ -54,7 +66,11 @@ namespace Hyena.Data.Gui
             get { return Children.Count; }
         }
 
-        public DataViewChild this[int index] {
+        public DataViewLayout ()
+        {
+        }
+
+        public CanvasItem this[int index] {
             get { return Children[index]; }
         }
 
@@ -81,21 +97,35 @@ namespace Hyena.Data.Gui
             InvalidateChildLayout ();
         }
 
-        public virtual DataViewChild FindChildAtPoint (Point point)
+        public virtual CanvasItem FindChildAtPoint (Point point)
         {
             return Children.Find (child => child.Allocation.Contains (
                 ActualAllocation.X + point.X, ActualAllocation.Y + point.Y));
         }
 
-        public virtual DataViewChild FindChildAtModelRowIndex (int modelRowIndex)
+        public virtual CanvasItem FindChildAtModelRowIndex (int modelRowIndex)
         {
-            return Children.Find (child => child.ModelRowIndex == modelRowIndex);
+            return Children.Find (child => GetModelIndex (child) == modelRowIndex);
         }
 
         protected abstract void InvalidateChildSize ();
         protected abstract void InvalidateVirtualSize ();
         protected abstract void InvalidateChildCollection ();
-        protected abstract void InvalidateChildLayout ();
+        protected virtual void InvalidateChildLayout ()
+        {
+            model_indices.Clear ();
+        }
+
+        protected void SetModelIndex (CanvasItem item, int index)
+        {
+            model_indices[item] = index;
+        }
+
+        public int GetModelIndex (CanvasItem item)
+        {
+            int i;
+            return model_indices.TryGetValue (item, out i) ? i : -1;
+        }
 
         protected Rect GetChildVirtualAllocation (Rect childAllocation)
         {
diff --git a/Hyena.Gui/Hyena.Data.Gui/DataViewLayoutGrid.cs b/Hyena.Gui/Hyena.Data.Gui/DataViewLayoutGrid.cs
index 2828043..a563d48 100644
--- a/Hyena.Gui/Hyena.Data.Gui/DataViewLayoutGrid.cs
+++ b/Hyena.Gui/Hyena.Data.Gui/DataViewLayoutGrid.cs
@@ -38,7 +38,7 @@ namespace Hyena.Data.Gui
         public int Rows { get; private set; }
         public int Columns { get; private set; }
 
-        public Func<DataViewChild> ChildAllocator { get; set; }
+        public Func<CanvasItem> ChildAllocator { get; set; }
         public event EventHandler<EventArgs<int>> ChildCountChanged;
 
         protected override void InvalidateChildSize ()
@@ -78,6 +78,8 @@ namespace Hyena.Data.Gui
 
         protected override void InvalidateChildLayout ()
         {
+            base.InvalidateChildLayout ();
+
             if (ChildSize.Width <= 0 || ChildSize.Height <= 0) {
                 // FIXME: empty/reset all child slots here?
                 return;
@@ -109,9 +111,9 @@ namespace Hyena.Data.Gui
                 var child = Children[layout_child_index];
                 child.Allocation = child_allocation;
                 child.VirtualAllocation = GetChildVirtualAllocation (child_allocation);
-                child.ModelRowIndex = model_row_index;
+                SetModelIndex (child, model_row_index);
                 if (Model != null) {
-                    child.BindDataItem (Model.GetItem (model_row_index));
+                    child.Bind (Model.GetItem (model_row_index));
                 }
                 child.Measure (ChildSize); // FIXME: Should not do this here...
                 child.Arrange ();
@@ -131,14 +133,15 @@ namespace Hyena.Data.Gui
             }
         }
 
-        protected virtual DataViewChild CreateChild ()
+        protected virtual CanvasItem CreateChild ()
         {
             if (ChildAllocator == null) {
                 throw new InvalidOperationException ("ChildAllocator is unset");
             }
 
             var child = ChildAllocator ();
-            child.ParentLayout = this;
+            child.Manager = CanvasManager;
+            //child.ParentLayout = this;
             return child;
         }
 
diff --git a/Hyena.Gui/Hyena.Data.Gui/ListView/ListViewBase.cs b/Hyena.Gui/Hyena.Data.Gui/ListView/ListViewBase.cs
index c9f59b0..60af960 100644
--- a/Hyena.Gui/Hyena.Data.Gui/ListView/ListViewBase.cs
+++ b/Hyena.Gui/Hyena.Data.Gui/ListView/ListViewBase.cs
@@ -29,9 +29,11 @@
 using System;
 using Gtk;
 
+using Hyena.Gui.Canvas;
+
 namespace Hyena.Data.Gui
 {
-    public abstract class ListViewBase : Widget
+    public abstract class ListViewBase : Widget, ICanvasHost
     {
         protected ListViewBase (IntPtr ptr) : base (ptr)
         {
@@ -47,7 +49,7 @@ namespace Hyena.Data.Gui
             QueueDrawArea (region.X, region.Y, region.Width, region.Height);
         }
 
-        public void QueueDirtyRegion (Hyena.Gui.Canvas.Rect region)
+        public void QueueDirtyRegion (Rect region)
         {
             QueueDirtyRegion ((Gdk.Rectangle)region);
         }
@@ -62,6 +64,11 @@ namespace Hyena.Data.Gui
             });
         }
 
+        public void QueueRender (Hyena.Gui.Canvas.CanvasItem item, Rect rect)
+        {
+            QueueDirtyRegion (rect);
+        }
+
         public abstract Pango.Layout PangoLayout { get; }
     }
 }
diff --git a/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Interaction.cs b/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Interaction.cs
index 6b99953..6d6890c 100644
--- a/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Interaction.cs
+++ b/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Interaction.cs
@@ -308,7 +308,7 @@ namespace Hyena.Data.Gui
 
 #region DataViewLayout Interaction Events
 
-        private DataViewChild last_layout_child;
+        private CanvasItem last_layout_child;
 
         private bool LayoutChildHandlesEvent (Gdk.Event evnt, bool press)
         {
@@ -356,7 +356,7 @@ namespace Hyena.Data.Gui
             return handled;
         }
 
-        private DataViewChild GetLayoutChildAt (Point point)
+        private CanvasItem GetLayoutChildAt (Point point)
         {
             point.Offset (-list_interaction_alloc.X, -list_interaction_alloc.Y);
             return ViewLayout.FindChildAtPoint (point);
@@ -864,7 +864,7 @@ namespace Hyena.Data.Gui
         {
             if (ViewLayout != null) {
                 var child = ViewLayout.FindChildAtPoint (new Point (x, y));
-                return child == null ? -1 : child.ModelRowIndex;
+                return child == null ? -1 : ViewLayout.GetModelIndex (child);
             } else {
                 if (y < 0 || ChildSize.Height <= 0) {
                     return -1;
diff --git a/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Rendering.cs b/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Rendering.cs
index b89b3bd..006911c 100644
--- a/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Rendering.cs
+++ b/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Rendering.cs
@@ -238,7 +238,8 @@ namespace Hyena.Data.Gui
                 cairo_context.Save ();
                 cairo_context.Translate (area.X, area.Y);
                 cell_context.Area = area;
-                cell.Render (cell_context, StateType.Normal, area.Width, area.Height);
+                cell_context.State = StateType.Normal;
+                cell.Render (cell_context, area.Width, area.Height);
                 cairo_context.Restore ();
             }
 
@@ -444,7 +445,8 @@ namespace Hyena.Data.Gui
             cairo_context.Translate (area.X, area.Y);
             cell_context.Area = area;
             cell_context.Opaque = opaque;
-            cell.Render (cell_context, dragging ? StateType.Normal : state, area.Width, area.Height);
+            cell_context.State = dragging ? StateType.Normal : state;
+            cell.Render (cell_context, area.Width, area.Height);
             cairo_context.Restore ();
 
             AccessibleCellRedrawn (column_index, row_index);
@@ -501,12 +503,12 @@ namespace Hyena.Data.Gui
                 var layout_child = ViewLayout[layout_index];
                 var child_allocation = layout_child.Allocation;
 
-                if (!child_allocation.IntersectsWith (clip) || layout_child.ModelRowIndex >= Model.Count) {
+                if (!child_allocation.IntersectsWith (clip) || ViewLayout.GetModelIndex (layout_child) >= Model.Count) {
                     continue;
                 }
 
-                if (Selection != null && Selection.Contains (layout_child.ModelRowIndex)) {
-                    selected_rows.Add (layout_child.ModelRowIndex);
+                if (Selection != null && Selection.Contains (ViewLayout.GetModelIndex (layout_child))) {
+                    selected_rows.Add (ViewLayout.GetModelIndex (layout_child));
 
                     var selection_color = Theme.Colors.GetWidgetColor (GtkColorClass.Background, StateType.Selected);
                     if (!HasFocus || HeaderFocused) {
@@ -523,12 +525,12 @@ namespace Hyena.Data.Gui
                     cell_context.State = StateType.Normal;
                 }
 
-                cairo_context.Save ();
-                cairo_context.Translate (child_allocation.X, child_allocation.Y);
-                cairo_context.Rectangle (0, 0, child_allocation.Width, child_allocation.Height);
-                cairo_context.Clip ();
+                //cairo_context.Save ();
+                //cairo_context.Translate (child_allocation.X, child_allocation.Y);
+                //cairo_context.Rectangle (0, 0, child_allocation.Width, child_allocation.Height);
+                //cairo_context.Clip ();
                 layout_child.Render (cell_context);
-                cairo_context.Restore ();
+                //cairo_context.Restore ();
             }
 
             cairo_context.ResetClip ();
diff --git a/Hyena.Gui/Hyena.Data.Gui/ListViewTestModule.cs b/Hyena.Gui/Hyena.Data.Gui/ListViewTestModule.cs
index e79a861..62978b2 100644
--- a/Hyena.Gui/Hyena.Data.Gui/ListViewTestModule.cs
+++ b/Hyena.Gui/Hyena.Data.Gui/ListViewTestModule.cs
@@ -33,10 +33,12 @@ using Gtk;
 using Hyena.Data;
 using Hyena.Collections;
 using Hyena.Gui;
+using Hyena.Gui.Canvas;
+using Hyena.Data.Gui;
 
 using Selection = Hyena.Collections.Selection;
 
-namespace Hyena.Data.Gui
+namespace Hyena.Data.Gui.Tests
 {
     [TestModule ("List View")]
     public class ListViewTestModule : Window
@@ -79,139 +81,214 @@ namespace Hyena.Data.Gui
                 );
             }
         }
+    }
+
+    [TestModule ("Grid View")]
+    public class GridViewTestModule : Window
+    {
+        private View view;
+        private Model model;
 
-        private class Model : IListModel<ModelItem>
+        public GridViewTestModule () : base ("GridView")
         {
-            private List<ModelItem> store = new List<ModelItem> ();
-            private Selection selection = new Selection ();
+            WindowPosition = WindowPosition.Center;
+            SetDefaultSize (800, 600);
 
-            public event EventHandler Cleared;
-            public event EventHandler Reloaded;
+            view = new View ();
+            model = new Model ();
 
-            public Model ()
-            {
-                Random random = new Random (0);
-                for (int i = 0; i < 1000; i++) {
-                    store.Add (new ModelItem (i, random));
-                }
-            }
+            /*var hbox = new HBox () { Spacing = 6 };
 
-            public void Clear ()
-            {
-            }
+            var add_margin_control = new System.Action<string, Func<double>, System.Action<double>> ((type, get, set) => {
+                var spin = new SpinButton (0, 20, 1);
+                spin.Value = get ();
+                spin.ValueChanged += (o, a) => { set (spin.Value); };
+                hbox.PackStart (new Label (type + " Margin:"), false, false, 0);
+                hbox.PackStart (spin, false, false, 0);
+            });
 
-            public void Reload ()
-            {
-            }
+            add_margin_control ("", () => view.Box.Margin.Left, v => view.Box.Margin = new Thickness (v));*/
 
-            public object GetItem (int index)
-            {
-                return this[index];
-            }
+            var scroll = new ScrolledWindow () {
+                HscrollbarPolicy = PolicyType.Automatic,
+                VscrollbarPolicy = PolicyType.Automatic
+            };
+            scroll.Add (view);
 
-            public int Count {
-                get { return store.Count; }
-            }
+            var vbox = new VBox () { Spacing = 12 };
+            //vbox.PackStart (hbox, true, true, 0);
+            vbox.PackStart (scroll, true, true, 0);
 
-            public bool CanReorder {
-                get { return false; }
-            }
+            Add (vbox);
+            ShowAll ();
 
-            public ModelItem this[int index] {
-                get { return store[index]; }
-            }
+            view.SetModel (model);
+        }
 
-            public Selection Selection {
-                get { return selection; }
+        private class View : ListView<ModelItem>
+        {
+            public View ()
+            {
+                ViewLayout = new DataViewLayoutGrid () {
+                    ChildAllocator = () => {
+                        return new StackPanel () {
+                            Orientation = Hyena.Gui.Canvas.Orientation.Vertical,
+                            Width = 400,
+                            Spacing = 15,
+                            //Margin = new Thickness (10),
+                            Theme = Theme,
+                            Children = {
+                                new Slider (),
+                                new ColumnCellCheckBox ("F", true),
+                                new TextBlock () { Binder = new ObjectBinder () { Property = "A" } },
+                                new TextBlock () { Binder = new ObjectBinder () { Property = "B" } },
+                                //new ColumnCellText ("B", true),
+                                //new ColumnCellText ("C", true),
+                                new ColumnCellRating ("G", true),
+                                //new ColumnCellText ("D", true),
+                                new ColumnCellDoodle ("E", true),
+                                //new ColumnCellText ("A", true)
+                            }
+                        };
+                        //return new ColumnCellRating ("G", true);
+                    },
+                    View = this
+                };
             }
         }
+    }
+
+    internal class Model : IListModel<ModelItem>
+    {
+        private List<ModelItem> store = new List<ModelItem> ();
+        private Selection selection = new Selection ();
 
-        private class ModelItem
+        public event EventHandler Cleared;
+        public event EventHandler Reloaded;
+
+        public Model ()
         {
-            public ModelItem (int i, Random rand)
-            {
-                a = Guid.NewGuid ().ToString ();
-                b = rand.Next (0, 255);
-                c = rand.NextDouble ();
-                d = String.Format ("Item {0}", i);
-                e = new List<Gdk.Point> ();
-                f = rand.Next (0, 1) == 1;
-                g = rand.Next (0, 5);
+            Random random = new Random (0);
+            for (int i = 0; i < 1000; i++) {
+                store.Add (new ModelItem (i, random));
             }
+        }
 
-            string a; public string A { get { return a; } }
-            int b;    public int    B { get { return b; } }
-            double c; public double C { get { return c; } }
-            string d; public string D { get { return d; } }
-            List<Gdk.Point> e; public List<Gdk.Point> E { get { return e; } }
-            bool f; public bool F { get { return f; } set { f = value; } }
-            int g; public int G { get { return g; } set { g = value; } }
+        public void Clear ()
+        {
         }
 
-        private class ColumnCellDoodle : ColumnCell, IInteractiveCell
+        public void Reload ()
         {
-            private Random random = new Random ();
-            private bool red = false;
+        }
 
-            public ColumnCellDoodle (string property, bool expand) : base (property, expand)
-            {
-            }
+        public object GetItem (int index)
+        {
+            return this[index];
+        }
 
-            public override void Render (CellContext context, StateType state, double cellWidth, double cellHeight)
-            {
-                red = !red;
-                Cairo.Context cr = context.Context;
-                cr.Rectangle (0, 0, cellWidth, cellHeight);
-                cr.Color = CairoExtensions.RgbaToColor (red ? 0xff000099 : 0x00000099);
-                cr.Fill ();
-
-                List<Gdk.Point> points = Points;
-                for (int i = 0, n = points.Count; i < n; i++) {
-                    if (i == 0) {
-                        cr.MoveTo (points[i].X, points[i].Y);
-                    } else {
-                        cr.LineTo (points[i].X, points[i].Y);
-                    }
-                }
+        public int Count {
+            get { return store.Count; }
+        }
 
-                cr.Color = CairoExtensions.RgbToColor ((uint)random.Next (0xffffff));
-                cr.LineWidth = 1;
-                cr.Stroke ();
-            }
+        public bool CanReorder {
+            get { return false; }
+        }
 
-            private object last_pressed_bound;
+        public ModelItem this[int index] {
+            get { return store[index]; }
+        }
 
-            public bool ButtonEvent (int x, int y, bool pressed, Gdk.EventButton evnt)
-            {
-                if (!pressed) {
-                    last_pressed_bound = null;
-                    return false;
-                }
+        public Selection Selection {
+            get { return selection; }
+        }
+    }
 
-                last_pressed_bound = BoundObject;
-                Points.Add (new Gdk.Point (x, y));
-                return true;
-            }
+    internal class ModelItem
+    {
+        public ModelItem (int i, Random rand)
+        {
+            a = Guid.NewGuid ().ToString ();
+            b = rand.Next (0, 255);
+            c = rand.NextDouble ();
+            d = String.Format ("Item {0}", i);
+            e = new List<Gdk.Point> ();
+            f = rand.Next (0, 1) == 1;
+            g = rand.Next (0, 5);
+        }
 
-            public bool MotionEvent (int x, int y, Gdk.EventMotion evnt)
-            {
-                if (last_pressed_bound == BoundObject) {
-                    Points.Add (new Gdk.Point (x, y));
-                    return true;
+        string a; public string A { get { return a; } }
+        int b;    public int    B { get { return b; } }
+        double c; public double C { get { return c; } }
+        string d; public string D { get { return d; } }
+        List<Gdk.Point> e; public List<Gdk.Point> E { get { return e; } }
+        bool f; public bool F { get { return f; } set { f = value; } }
+        int g; public int G { get { return g; } set { g = value; } }
+    }
+
+    internal class ColumnCellDoodle : ColumnCell, IInteractiveCell
+    {
+        private Random random = new Random ();
+        private bool red = false;
+
+        public ColumnCellDoodle (string property, bool expand) : base (property, expand)
+        {
+        }
+
+        public override void Render (CellContext context, double cellWidth, double cellHeight)
+        {
+            red = !red;
+            Cairo.Context cr = context.Context;
+            cr.Rectangle (0, 0, cellWidth, cellHeight);
+            cr.Color = CairoExtensions.RgbaToColor (red ? 0xff000099 : 0x00000099);
+            cr.Fill ();
+
+            List<Gdk.Point> points = Points;
+            for (int i = 0, n = points.Count; i < n; i++) {
+                if (i == 0) {
+                    cr.MoveTo (points[i].X, points[i].Y);
+                } else {
+                    cr.LineTo (points[i].X, points[i].Y);
                 }
+            }
+
+            cr.Color = CairoExtensions.RgbToColor ((uint)random.Next (0xffffff));
+            cr.LineWidth = 1;
+            cr.Stroke ();
+        }
 
+        private object last_pressed_bound;
+
+        public bool ButtonEvent (int x, int y, bool pressed, Gdk.EventButton evnt)
+        {
+            if (!pressed) {
+                last_pressed_bound = null;
                 return false;
             }
 
-            public bool PointerLeaveEvent ()
-            {
-                last_pressed_bound = null;
+            last_pressed_bound = BoundObject;
+            Points.Add (new Gdk.Point (x, y));
+            return true;
+        }
+
+        public bool MotionEvent (int x, int y, Gdk.EventMotion evnt)
+        {
+            if (last_pressed_bound == BoundObject) {
+                Points.Add (new Gdk.Point (x, y));
                 return true;
             }
 
-            private List<Gdk.Point> Points {
-                get { return (List<Gdk.Point>)BoundObject; }
-            }
+            return false;
+        }
+
+        public bool PointerLeaveEvent ()
+        {
+            last_pressed_bound = null;
+            return true;
+        }
+
+        private List<Gdk.Point> Points {
+            get { return (List<Gdk.Point>)BoundObject; }
         }
     }
 }
diff --git a/Hyena.Gui/Makefile.am b/Hyena.Gui/Makefile.am
index e7b6c8c..5341d0f 100644
--- a/Hyena.Gui/Makefile.am
+++ b/Hyena.Gui/Makefile.am
@@ -20,8 +20,6 @@ SOURCES =  \
 	Hyena.Data.Gui/ColumnCellText.cs \
 	Hyena.Data.Gui/ColumnController.cs \
 	Hyena.Data.Gui/ColumnHeaderCellText.cs \
-	Hyena.Data.Gui/DataViewChild.cs \
-	Hyena.Data.Gui/DataViewChildBox.cs \
 	Hyena.Data.Gui/DataViewLayout.cs \
 	Hyena.Data.Gui/DataViewLayoutGrid.cs \
 	Hyena.Data.Gui/IHeaderCell.cs \
diff --git a/Hyena/Hyena.Data/ObjectBinder.cs b/Hyena/Hyena.Data/ObjectBinder.cs
new file mode 100644
index 0000000..2064a5d
--- /dev/null
+++ b/Hyena/Hyena.Data/ObjectBinder.cs
@@ -0,0 +1,114 @@
+//
+// ObjectBinder.cs
+//
+// Author:
+//   Aaron Bockover <abockover novell com>
+//   Gabriel Burt <gburt novell com>
+//
+// Copyright 2010 Novell, Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Reflection;
+
+namespace Hyena.Data
+{
+    public class ObjectBinder : IDataBinder
+    {
+        private PropertyInfo property_info;
+        private PropertyInfo sub_property_info;
+
+        public void Bind (object item)
+        {
+            BindDataItem (item);
+        }
+
+        public virtual void BindDataItem (object item)
+        {
+            if (item == null) {
+                BoundObjectParent = null;
+                bound_object = null;
+                return;
+            }
+
+            BoundObjectParent = item;
+
+            if (Property != null) {
+                EnsurePropertyInfo (Property, ref property_info, BoundObjectParent);
+                bound_object = property_info.GetValue (BoundObjectParent, null);
+
+                if (SubProperty != null) {
+                    EnsurePropertyInfo (SubProperty, ref sub_property_info, bound_object);
+                    bound_object = sub_property_info.GetValue (bound_object, null);
+                }
+            } else {
+                bound_object = BoundObjectParent;
+            }
+        }
+
+        private void EnsurePropertyInfo (string name, ref PropertyInfo prop, object obj)
+        {
+            if (prop == null || prop.ReflectedType != obj.GetType ()) {
+                prop = obj.GetType ().GetProperty (name);
+                if (prop == null) {
+                    throw new Exception (String.Format (
+                        "In {0}, type {1} does not have property {2}",
+                        this, obj.GetType (), name));
+                }
+            }
+        }
+
+        protected Type BoundType {
+            get { return bound_object.GetType (); }
+        }
+
+        private object bound_object;
+        public object BoundObject {
+            get { return bound_object; }
+            set {
+                if (Property != null) {
+                    EnsurePropertyInfo (Property, ref property_info, BoundObjectParent);
+                    property_info.SetValue (BoundObjectParent, value, null);
+                }
+            }
+        }
+
+        public object BoundObjectParent { get; private set; }
+
+        private string property;
+        public string Property {
+            get { return property; }
+            set {
+                property = value;
+                if (value != null) {
+                    int i = value.IndexOf (".");
+                    if (i != -1) {
+                        property = value.Substring (0, i);
+                        SubProperty = value.Substring (i + 1, value.Length - i - 1);
+                    }
+                }
+            }
+        }
+
+        public string SubProperty { get; set; }
+    }
+}
diff --git a/Hyena/Makefile.am b/Hyena/Makefile.am
index bda0d98..98361f1 100644
--- a/Hyena/Makefile.am
+++ b/Hyena/Makefile.am
@@ -36,6 +36,7 @@ SOURCES =  \
 	Hyena.Data/MemoryListModel.cs \
 	Hyena.Data/ModelCache.cs \
 	Hyena.Data/ModelSelection.cs \
+	Hyena.Data/ObjectBinder.cs \
 	Hyena.Data/PropertyStore.cs \
 	Hyena.Data/SortType.cs \
 	Hyena.Downloader/Buffer.cs \



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