banshee r3608 - in trunk/banshee: . src/Core/Banshee.ThickClient/Banshee.Collection.Gui src/Libraries/Hyena.Gui/Hyena.Data.Gui src/Libraries/Hyena.Gui/Hyena.Data.Gui/ListView src/Libraries/Hyena/Hyena.Data



Author: scottp
Date: Mon Mar 31 05:35:56 2008
New Revision: 3608
URL: http://svn.gnome.org/viewvc/banshee?rev=3608&view=rev

Log:
* src/Core/Banshee.ThickClient/Banshee.Collection.Gui/PersistentColumnController.cs:
Queue saving of column widths.

* src/Libraries/Hyena/Hyena.Data/ColumnDescription.cs: Added a
WidthChanged event.

* src/Libraries/Hyena.Gui/Hyena.Data.Gui/ColumnHeaderCellText.cs:
Better MinWidth math.

* src/Libraries/Hyena.Gui/Hyena.Data.Gui/Column.cs: Formatting fixes.

* src/Libraries/Hyena.Gui/Hyena.Data.Gui/ColumnController.cs: Seperate
reaction to width changes from visibility changes. Get rid of
QueueUpdate since it is no longer used.

* src/Libraries/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_DragAndDrop.cs:
Abstracted out the drag scroll stuff so that it can be used for
both the hadjustment and vadjustment.

* src/Libraries/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Windowing.cs:
Call new column resize methods when nessisary. Moved canvas
generation into its own method so that it can be done after column
resizing.

* src/Libraries/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Header.cs:
Loads of fun stuff. Columns now never get smaller than their
minimum size. All availible width is used, and when there is no
more room, we have an hadjustment. Lots of math to make sure that
columns maintain their reletive sizes for as long as possible.

* src/Libraries/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Rendering.cs:
Take the hadjustment into account when rendering.

* src/Libraries/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Interaction.cs:
Added horizontal adjustment. Abstracted some of the
OnMotionNotifyEvent stuff so we can send synthetic motion events
when the list is automatically scrolling horizontally, but the
mouse is not moving.

* src/Libraries/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Model.cs:
Use new UpdateAdjustments override.

* src/Libraries/Hyena.Gui/Hyena.Data.Gui/ColumnCellText.cs: Use virtual
property rather than private field for ellipsize mode.

Modified:
   trunk/banshee/ChangeLog
   trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/PersistentColumnController.cs
   trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Data.Gui/Column.cs
   trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Data.Gui/ColumnCellText.cs
   trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Data.Gui/ColumnController.cs
   trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Data.Gui/ColumnHeaderCellText.cs
   trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_DragAndDrop.cs
   trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Header.cs
   trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Interaction.cs
   trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Model.cs
   trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Rendering.cs
   trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Windowing.cs
   trunk/banshee/src/Libraries/Hyena/Hyena.Data/ColumnDescription.cs

Modified: trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/PersistentColumnController.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/PersistentColumnController.cs	(original)
+++ trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/PersistentColumnController.cs	Mon Mar 31 05:35:56 2008
@@ -39,6 +39,8 @@
     {
         private string root_namespace;
         private bool loaded = false;
+        private volatile bool pending_changes;
+        private uint timer_id = 0;
         
         private string source_id;
         private Source source;
@@ -74,7 +76,7 @@
         }
         
         public void Load ()
-        {    
+        {
             lock (this) {
                 if (source == null) {
                     return;
@@ -108,6 +110,28 @@
         
         public void Save ()
         {
+            Console.WriteLine ("Save");
+            if (timer_id == 0) {
+                timer_id = GLib.Timeout.Add (500, OnTimeout);
+            } else {
+                pending_changes = true;
+            }
+        }
+        
+        private bool OnTimeout ()
+        {
+            if (pending_changes) {
+                pending_changes = false;
+                return true;
+            } else {
+                SaveCore ();
+                timer_id = 0;
+                return false;
+            }
+        }
+        
+        private void SaveCore ()
+        {
             lock (this) {
                 if (source == null) {
                     return;
@@ -129,13 +153,13 @@
             ConfigurationClient.Set<double> (@namespace, "width", column.Width);
         }
         
-        protected override void OnUpdated ()
+        protected override void OnWidthsChanged ()
         {
             if (loaded) {
                 Save ();
             }
             
-            base.OnUpdated ();
+            base.OnWidthsChanged ();
         }
         
         private string MakeNamespace (string name)

Modified: trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Data.Gui/Column.cs
==============================================================================
--- trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Data.Gui/Column.cs	(original)
+++ trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Data.Gui/Column.cs	Mon Mar 31 05:35:56 2008
@@ -114,27 +114,24 @@
             set { header_cell = value; }
         }
         
-        public int MinWidth
-        {
-            get { return minWidth; }
-            set { minWidth = value; }
-        }
-
-        internal double MinRelativeWidth
-        {
-            get { return minRelativeWidth; }
+        public int MinWidth {
+            get { return minWidth; }
+            set { minWidth = value; }
+        }
+
+        internal double MinRelativeWidth {
+            get { return minRelativeWidth; }
             set { minRelativeWidth = value; }
         }
         
         public int MaxWidth {
             get { return maxWidth; }
             set { maxWidth = value; }
-        }
-
-        public double RelativeWidth
-        {
-            get { return relativeWidth; }
-            set { relativeWidth = value; }
+        }
+
+        public double RelativeWidth {
+            get { return relativeWidth; }
+            set { relativeWidth = value; }
         }
 
         public string Id {

Modified: trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Data.Gui/ColumnCellText.cs
==============================================================================
--- trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Data.Gui/ColumnCellText.cs	(original)
+++ trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Data.Gui/ColumnCellText.cs	Mon Mar 31 05:35:56 2008
@@ -54,7 +54,7 @@
             context.Layout.Width = (int)((cellWidth - 8) * Pango.Scale.PangoScale);
             context.Layout.FontDescription = context.Widget.PangoContext.FontDescription.Copy ();
             context.Layout.FontDescription.Weight = font_weight;
-            context.Layout.Ellipsize = ellipsize_mode;
+            context.Layout.Ellipsize = EllipsizeMode;
             
             context.Layout.SetText (Text);
             context.Layout.GetPixelSize (out text_width, out text_height);

Modified: trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Data.Gui/ColumnController.cs
==============================================================================
--- trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Data.Gui/ColumnController.cs	(original)
+++ trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Data.Gui/ColumnController.cs	Mon Mar 31 05:35:56 2008
@@ -43,7 +43,16 @@
         
         public event EventHandler Updated;
         
-        protected virtual void OnUpdated ()
+        protected virtual void OnVisibilitiesChanged ()
+        {
+            OnUpdated ();
+        }
+        
+        protected virtual void OnWidthsChanged ()
+        {
+        }
+        
+        protected void OnUpdated ()
         {
             EventHandler handler = Updated;
             if (handler != null) {
@@ -51,16 +60,12 @@
             }
         }
         
-        public virtual void QueueUpdate ()
-        {
-            OnUpdated ();
-        }
-        
         public void Clear ()
         {
             lock (this) {
                 foreach (Column column in columns) {
                     column.VisibilityChanged -= OnColumnVisibilityChanged;
+                    column.WidthChanged -= OnColumnWidthChanged;
                 }
                 columns.Clear ();
             }
@@ -73,6 +78,7 @@
             lock (this) {
                 foreach (Column column in range) {
                     column.VisibilityChanged += OnColumnVisibilityChanged;
+                    column.WidthChanged += OnColumnWidthChanged;
                 }
                 columns.AddRange (range);
             }
@@ -84,6 +90,7 @@
         {
             lock (this) {
                 column.VisibilityChanged += OnColumnVisibilityChanged;
+                column.WidthChanged += OnColumnWidthChanged;
                 columns.Add (column);
             }
             
@@ -94,6 +101,7 @@
         {
             lock (this) {
                 column.VisibilityChanged += OnColumnVisibilityChanged;
+                column.WidthChanged += OnColumnWidthChanged;
                 columns.Insert (index, column);
             }
             
@@ -104,6 +112,7 @@
         {
             lock (this) {
                 column.VisibilityChanged -= OnColumnVisibilityChanged;
+                column.WidthChanged -= OnColumnWidthChanged;
                 columns.Remove (column);
             }
             
@@ -115,6 +124,7 @@
             lock (this) {
                 Column column = columns[index];
                 column.VisibilityChanged -= OnColumnVisibilityChanged;
+                column.WidthChanged -= OnColumnWidthChanged;
                 columns.RemoveAt (index);
             }
             
@@ -156,7 +166,12 @@
         
         private void OnColumnVisibilityChanged (object o, EventArgs args)
         {
-            OnUpdated ();
+            OnVisibilitiesChanged ();
+        }
+        
+        private void OnColumnWidthChanged (object o, EventArgs args)
+        {
+            OnWidthsChanged ();
         }
         
         public Column this[int index] {

Modified: trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Data.Gui/ColumnHeaderCellText.cs
==============================================================================
--- trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Data.Gui/ColumnHeaderCellText.cs	(original)
+++ trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Data.Gui/ColumnHeaderCellText.cs	Mon Mar 31 05:35:56 2008
@@ -77,7 +77,14 @@
         }
         
         public int MinWidth {
-            get { return TextWidth + 25; }
+            get {
+                int min_width = data_handler ().MinWidth + 20;
+                if (HasSort) {
+                    min_width += 20;
+                }
+                return min_width;
+            }
         }
+
     }
 }

Modified: trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_DragAndDrop.cs
==============================================================================
--- trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_DragAndDrop.cs	(original)
+++ trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_DragAndDrop.cs	Mon Mar 31 05:35:56 2008
@@ -117,6 +117,22 @@
             }
         }
         
+        private void OnDragScroll (GLib.TimeoutHandler handler, double threshold, int total, int position)
+        {
+            if (position < threshold) {
+                drag_scroll_velocity = -1.0 + (position / threshold);
+            } else if (position > total - threshold) {
+                drag_scroll_velocity = 1.0 - ((total - position) / threshold);
+            } else {
+                StopDragScroll ();
+                return;
+            }
+            
+            if (drag_scroll_timeout_id == 0) {
+                drag_scroll_timeout_id = GLib.Timeout.Add (drag_scroll_timeout_duration, handler);
+            }
+        }
+        
         protected override bool OnDragMotion (Gdk.DragContext context, int x, int y, uint time)
         {
             if (!Reorderable) {
@@ -130,20 +146,7 @@
             drag_reorder_motion_y = y;
             DragReorderUpdateRow ();
             
-            double scroll_threshold = Allocation.Height * 0.3;
-            
-            if (y < scroll_threshold) {
-                drag_scroll_velocity = -1.0 + (y / scroll_threshold);
-            } else if (y > Allocation.Height - scroll_threshold) {
-                drag_scroll_velocity = 1.0 - ((Allocation.Height - y) / scroll_threshold);
-            } else {
-                StopDragScroll ();
-                return true;
-            }
-            
-            if (drag_scroll_timeout_id == 0) {
-                drag_scroll_timeout_id = GLib.Timeout.Add (drag_scroll_timeout_duration, OnDragScrollTimeout);
-            }
+            OnDragScroll (OnDragVScrollTimeout, Allocation.Height * 0.3, Allocation.Height, y);
             
             return true;
         }
@@ -161,7 +164,7 @@
             InvalidateList ();
         }
         
-        private bool OnDragScrollTimeout ()
+        private bool OnDragVScrollTimeout ()
         {
             ScrollTo (vadjustment.Value + (drag_scroll_velocity * drag_scroll_velocity_max));
             DragReorderUpdateRow ();

Modified: trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Header.cs
==============================================================================
--- trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Header.cs	(original)
+++ trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Header.cs	Mon Mar 31 05:35:56 2008
@@ -27,6 +27,7 @@
 //
 
 using System;
+using System.Collections.Generic;
 using Mono.Unix;
 using Gtk;
 
@@ -46,22 +47,29 @@
             public int ResizeX1;
             public int ResizeX2;
             public int Index;
+            public double ElasticWidth;
+            public double ElasticPercent;
         }
         
         private static Gdk.Cursor resize_x_cursor = new Gdk.Cursor (Gdk.CursorType.SbHDoubleArrow);
         private static Gdk.Cursor drag_cursor = new Gdk.Cursor (Gdk.CursorType.Fleur);
 
+        private bool resizable;
+        private int header_width;
         private int sort_column_index = -1;
         private int resizing_column_index = -1;
         private int pressed_column_index = -1;
+        private int pressed_column_x = -1;
         private int pressed_column_x_start = -1;
         private int pressed_column_x_offset = -1;
         private int pressed_column_x_drag = -1;
+        private int pressed_column_x_start_hadjustment = -1;
         private bool pressed_column_is_dragging = false;
         
         private Pango.Layout column_layout;
         
         private CachedColumn [] column_cache;
+        private List<int> elastic_columns;
         
 #region Columns
         
@@ -75,7 +83,6 @@
             column_cache = new CachedColumn[column_controller.Count];
             
             int i = 0;
-            int min_header_width = 0;
             double total = 0.0;
             
             foreach (Column column in column_controller) {
@@ -83,16 +90,17 @@
                     continue;
                 }
                 
+                if (column.MinWidth == 0) {
+                    int w;
+                    int h;
+                    column_layout.SetText (column.Title);
+                    column_layout.GetPixelSize (out w, out h);
+                    column.MinWidth = w;
+                }
+                
                 column_cache[i] = new CachedColumn ();
                 column_cache[i].Column = column;
-                
-                // TODO can this be done in the constructor? Will the title change?
-                int w;
-                int h;
-                column_layout.SetText (column.Title);
-                column_layout.GetPixelSize (out w, out h);
-                // 10 is arbitrary. Should we have a good way of getting the arrow width?
-                min_header_width += column_cache[i].MinWidth = Math.Max (column.MinWidth, w + 10); 
+                column_cache[i].Index = i;
                 
                 total += column.Width;
                 i++;
@@ -105,6 +113,8 @@
             for (i = 0; i < column_cache.Length; i++) {
                 column_cache[i].Column.Width *= scale_factor;
             }
+            
+            RecalculateColumnSizes ();
         }
         
         private void RegenerateColumnCache ()
@@ -117,17 +127,30 @@
                 GenerateColumnCache ();
             }
             
-            ISortable sortable = Model as ISortable;
-            sort_column_index = -1;
-            
             for (int i = 0; i < column_cache.Length; i++) {
-                column_cache[i].Width = (int)Math.Round (((double)header_interaction_alloc.Width * column_cache[i].Column.Width));
+                column_cache[i].Width = (int)Math.Round (((double)header_width * column_cache[i].Column.Width));
                 column_cache[i].X1 = i == 0 ? 0 : column_cache[i - 1].X2;
                 column_cache[i].X2 = column_cache[i].X1 + column_cache[i].Width;
                 column_cache[i].ResizeX1 = column_cache[i].X2;
                 column_cache[i].ResizeX2 = column_cache[i].ResizeX1 + 2;
-                column_cache[i].Index = i;
-                
+            }
+            
+            // TODO handle max width
+            int index = column_cache.Length - 1;
+            column_cache[index].X2 = header_width;
+            column_cache[index].Width = column_cache[index].X2 - column_cache[index].X1;
+        }
+        
+        private void RecalculateColumnSizes ()
+        {
+            if (column_cache == null) {
+                return;
+            }
+            
+            ISortable sortable = Model as ISortable;
+            sort_column_index = -1;
+            int min_header_width = 0;
+            for (int i = 0; i < column_cache.Length; i++) {
                 if (sortable != null) {
                     ColumnHeaderCellText column_cell = column_cache[i].Column.HeaderCell as ColumnHeaderCellText;
                     if (column_cell != null) {
@@ -138,13 +161,82 @@
                         }
                     }
                 }
+                
+                int min_width = 25;
+                IHeaderCell header_cell = column_cache[i].Column.HeaderCell as IHeaderCell;
+                if (header_cell != null) {
+                    min_width = header_cell.MinWidth;
+                }
+                column_cache[i].MinWidth = min_width;
+                min_header_width += column_cache[i].MinWidth = Math.Max (min_width, column_cache[i].Column.MinWidth);
+            }
+            
+            if (min_header_width >= header_interaction_alloc.Width) {
+                header_width = min_header_width;
+                resizable = false;
+                for (int i = 0; i < column_cache.Length; i++) {
+                    column_cache[i].Column.Width = (double)column_cache[i].MinWidth / (double)header_width;
+                }
+            } else {
+                header_width = header_interaction_alloc.Width;
+                resizable = true;
+                
+                if (elastic_columns == null) {
+                    elastic_columns = new List<int> (column_cache.Length);
+                }
+                elastic_columns.Clear ();
+                for (int i = 0; i < column_cache.Length; i++) {
+                    elastic_columns.Add (i);
+                    column_cache[i].ElasticWidth = 0.0;
+                    column_cache[i].ElasticPercent = column_cache[i].Column.Width * header_width;
+                }
+                
+                double remaining_width = RecalculateColumnSizes (header_width, header_width);
+                
+                while (remaining_width != 0 && elastic_columns.Count > 0) {
+                    double total_elastic_width = 0.0;
+                    foreach (int i in elastic_columns) {
+                        total_elastic_width += column_cache[i].ElasticWidth;
+                    }
+                    remaining_width = RecalculateColumnSizes (remaining_width, total_elastic_width);
+                }
+                
+                for (int i = 0; i < column_cache.Length; i++) {
+                    column_cache[i].Column.Width = column_cache[i].ElasticWidth / (double)header_width;
+                }
+            }
+        }
+        
+        private double RecalculateColumnSizes (double total_width, double total_elastic_width)
+        {
+            double remaining_width = total_width;
+            
+            for (int index = 0; index < elastic_columns.Count; index++) {
+                int i = elastic_columns[index];
+                double percent = column_cache[i].ElasticPercent / total_elastic_width;
+                double delta = total_width * percent;
+                
+                // TODO handle max widths
+                if (column_cache[i].ElasticWidth + delta < column_cache[i].MinWidth) {
+                    delta = column_cache[i].MinWidth - column_cache[i].ElasticWidth;
+                    elastic_columns.RemoveAt (index);
+                    index--;
+                }
+                
+                remaining_width -= delta;
+                column_cache[i].ElasticWidth += delta;
             }
+            
+            remaining_width = Math.Round (remaining_width);
+            return remaining_width;
         }
         
         protected virtual void OnColumnControllerUpdated ()
         {
             InvalidateColumnCache ();
             RegenerateColumnCache ();
+            RegenerateCanvases ();
+            UpdateAdjustments ();
             QueueDraw ();
         }
         
@@ -185,50 +277,58 @@
         private void ResizeColumn (double x)
         {
             CachedColumn resizing_column = column_cache[resizing_column_index];
-
             double resize_delta = x - resizing_column.ResizeX2;
-            double subsequent_columns = column_cache.Length - resizing_column.Index - 1;
-            double even_distribution = 0.0;
             
-            int min_width = 25;
-            IHeaderCell header_cell = resizing_column.Column.HeaderCell as IHeaderCell;
-            if (header_cell != null) {
-                min_width = header_cell.MinWidth;
+            if (resizing_column.Width + resize_delta < resizing_column.MinWidth) {
+                resize_delta = resizing_column.MinWidth - resizing_column.Width;
             }
             
-            if (resizing_column.Width + resize_delta < min_width) {
-                resize_delta = min_width - resizing_column.Width;
-            }
-                        
-            for (int i = 0; i <= resizing_column_index; i++) {
-                even_distribution += column_cache[i].Column.Width * resize_delta;
+            if (resize_delta == 0) {
+                return;
             }
-
-            even_distribution /= subsequent_columns;
-
-            resizing_column.Column.Width = (resizing_column.Width + resize_delta) / (double)list_rendering_alloc.Width;
-
+            
+            int sign = Math.Sign (resize_delta);
+            resize_delta = Math.Abs (resize_delta);
+            double total_elastic_width = 0.0;
+            
             for (int i = resizing_column_index + 1; i < column_cache.Length; i++) {
-                column_cache[i].Column.Width = (column_cache[i].Width - 
-                    (column_cache[i].Column.Width * resize_delta) - 
-                    even_distribution) / (double)list_rendering_alloc.Width;
+                total_elastic_width += column_cache[i].ElasticWidth = sign == 1
+                    ? column_cache[i].Width - column_cache[i].MinWidth
+                    : column_cache[i].Column.MaxWidth - column_cache[i].Width;
             }
             
-            ColumnController.QueueUpdate ();
+            if (total_elastic_width == 0) {
+                return;
+            }
+            
+            if (resize_delta > total_elastic_width) {
+                resize_delta = total_elastic_width;
+            }
             
+            resize_delta = sign * resize_delta / (double)header_width;
+            
+            for (int i = resizing_column_index + 1; i < column_cache.Length; i++) {
+                column_cache[i].Column.Width += -resize_delta * (column_cache[i].ElasticWidth / total_elastic_width);
+            }
+            
+            resizing_column.Column.Width += resize_delta;
+        
             RegenerateColumnCache ();
             QueueDraw ();
         }
         
         private Column GetColumnForResizeHandle (int x)
         {
-            if (column_cache == null) {
+            if (column_cache == null || !resizable) {
                 return null;
             }
             
+            x += (int)hadjustment.Value;
+            
             for (int i = 0; i < column_cache.Length - 1; i++) {
                 if (x >= column_cache[i].ResizeX1 - 2 && 
-                    x <= column_cache[i].ResizeX2 + 2) {
+                    x <= column_cache[i].ResizeX2 + 2 &&
+                    column_cache[i].Column.MaxWidth != column_cache[i].Column.MinWidth) {
                     return column_cache[i].Column;
                 }
             }
@@ -242,6 +342,8 @@
                 return null;
             }
             
+            x += (int)hadjustment.Value;
+            
             foreach (CachedColumn column in column_cache) {
                 if (x >= column.X1 && x <= column.X2) {
                     return column.Column;
@@ -310,6 +412,7 @@
             set { 
                 header_visible = value;
                 MoveResize (Allocation);
+                RegenerateCanvases ();
             }
         }
         

Modified: trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Interaction.cs
==============================================================================
--- trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Interaction.cs	(original)
+++ trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Interaction.cs	Mon Mar 31 05:35:56 2008
@@ -45,6 +45,11 @@
             get { return vadjustment; }
         }
         
+        private Adjustment hadjustment;
+        public Adjustment Hadjustment {
+            get { return hadjustment; }
+        }
+        
         private SelectionProxy selection_proxy = new SelectionProxy ();
         public SelectionProxy SelectionProxy {
             get { return selection_proxy; }
@@ -233,6 +238,7 @@
                     pressed_column_index = column_c.Index;
                     pressed_column_x_start = x;
                     pressed_column_x_offset = pressed_column_x_start - column_c.X1;
+                    pressed_column_x_start_hadjustment = (int)hadjustment.Value;
                 }
             }
             
@@ -309,6 +315,7 @@
         protected override bool OnButtonReleaseEvent (Gdk.EventButton evnt)
         {
             OnDragSourceSet ();
+            StopDragScroll ();
             
             if (resizing_column_index >= 0) {
                 pressed_column_index = -1;
@@ -342,6 +349,7 @@
             if (column != null && Model is ISortable && column is ISortableColumn) {
                 ((ISortable)Model).Sort ((ISortableColumn)column);
                 Model.Reload ();
+                RecalculateColumnSizes ();
                 RegenerateColumnCache ();
                 InvalidateHeader ();
             }
@@ -388,36 +396,9 @@
                 InvalidateList ();
             }
             
-            if (pressed_column_is_dragging) {
-                GdkWindow.Cursor = drag_cursor;
-                
-                Column swap_column = GetColumnAt (x);
-                
-                if (swap_column != null) {
-                    CachedColumn swap_column_c = GetCachedColumnForColumn (swap_column);
-                    bool reorder = false;
-                    
-                    if (swap_column_c.Index < pressed_column_index) {
-                        // Moving from right to left
-                        reorder = pressed_column_x_drag <= swap_column_c.X1 + swap_column_c.Width / 2;
-                    } else if (swap_column_c.Index > pressed_column_index) {
-                        // Moving from left to right
-                        reorder = pressed_column_x_drag + column_cache[pressed_column_index].Width >= 
-                            swap_column_c.X1 + swap_column_c.Width / 2;
-                    }
-                    
-                    if (reorder) {
-                        int actual_pressed_index = ColumnController.IndexOf (column_cache[pressed_column_index].Column);
-                        int actual_swap_index = ColumnController.IndexOf (swap_column_c.Column);
-                        ColumnController.Reorder (actual_pressed_index, actual_swap_index);
-                        pressed_column_index = swap_column_c.Index;
-                        RegenerateColumnCache ();
-                    }
-                }
-                
-                pressed_column_x_drag = x - pressed_column_x_offset;
-                
-                QueueDraw ();
+            pressed_column_x = x;
+            
+            if (OnMotionNotifyEvent (x)) {
                 return true;
             }
             
@@ -427,12 +408,59 @@
                 : null;
             
             if (resizing_column_index >= 0) {
-                ResizeColumn ((double)x);
+                ResizeColumn (x);
             }
             
             return true;
         }
         
+        private bool OnMotionNotifyEvent (int x)
+        {
+            if (!pressed_column_is_dragging) {
+                return false;
+            }
+            
+            OnDragScroll (OnDragHScrollTimeout, header_interaction_alloc.Width * 0.1, header_interaction_alloc.Width, x);
+            
+            GdkWindow.Cursor = drag_cursor;
+            
+            Column swap_column = GetColumnAt (x);
+            
+            if (swap_column != null) {
+                CachedColumn swap_column_c = GetCachedColumnForColumn (swap_column);
+                bool reorder = false;
+                
+                if (swap_column_c.Index < pressed_column_index) {
+                    // Moving from right to left
+                    reorder = pressed_column_x_drag <= swap_column_c.X1 + swap_column_c.Width / 2;
+                } else if (swap_column_c.Index > pressed_column_index) {
+                    // Moving from left to right
+                    reorder = pressed_column_x_drag + column_cache[pressed_column_index].Width >= 
+                        swap_column_c.X1 + swap_column_c.Width / 2;
+                }
+                
+                if (reorder) {
+                    int actual_pressed_index = ColumnController.IndexOf (column_cache[pressed_column_index].Column);
+                    int actual_swap_index = ColumnController.IndexOf (swap_column_c.Column);
+                    ColumnController.Reorder (actual_pressed_index, actual_swap_index);
+                    pressed_column_index = swap_column_c.Index;
+                    RegenerateColumnCache ();
+                }
+            }
+            
+            pressed_column_x_drag = x - pressed_column_x_offset - (pressed_column_x_start_hadjustment - (int)hadjustment.Value);
+            
+            QueueDraw ();
+            return true;
+        }
+        
+        private bool OnDragHScrollTimeout ()
+        {
+            ScrollTo (hadjustment, hadjustment.Value + (drag_scroll_velocity * drag_scroll_velocity_max));
+            OnMotionNotifyEvent (pressed_column_x);
+            return true;
+        }
+        
         protected override bool OnLeaveNotifyEvent (Gdk.EventCrossing evnt)
         {
             GdkWindow.Cursor = null;
@@ -484,28 +512,57 @@
 
 #region Adjustments & Scrolling
         
+        private void UpdateAdjustments ()
+        {
+            UpdateAdjustments (null, null);
+        }
+        
         private void UpdateAdjustments (Adjustment hadj, Adjustment vadj)
         {
+            if (hadj != null) {
+                hadjustment = hadj;
+            }
+            
             if (vadj != null) {
                 vadjustment = vadj;
             }
             
+            if (hadjustment != null) {
+                hadjustment.Upper = header_width;
+                hadjustment.StepIncrement = 10.0;
+                if (hadjustment.Value + hadjustment.PageSize > hadjustment.Upper) {
+                    hadjustment.Value = hadjustment.Upper - hadjustment.PageSize;
+                }
+            }
+            
             if (vadjustment != null && model != null) {
                 vadjustment.Upper = (RowHeight * (model.Count));
                 vadjustment.StepIncrement = RowHeight;
             }
             
+            hadjustment.Change ();
             vadjustment.Change ();
         }
         
-        private void OnAdjustmentChanged (object o, EventArgs args)
+        private void OnHadjustmentChanged (object o, EventArgs args)
         {
+            InvalidateHeader ();
             InvalidateList (false);
         }
         
-        protected void ScrollTo (double val)
+        private void OnVadjustmentChanged (object o, EventArgs args)
+        {
+            InvalidateList (false);
+        }
+        
+        public void ScrollTo (double val)
+        {
+            ScrollTo (vadjustment, val);
+        }
+        
+        private void ScrollTo (Adjustment adjustment, double val)
         {
-            vadjustment.Value = Math.Max (0.0, Math.Min (val, vadjustment.Upper - vadjustment.PageSize));
+            adjustment.Value = Math.Max (0.0, Math.Min (val, adjustment.Upper - adjustment.PageSize));
         }
 
         public void ScrollTo (int index)
@@ -520,12 +577,12 @@
                 
         protected override void OnSetScrollAdjustments (Adjustment hadj, Adjustment vadj)
         {
-            if (vadj == null || hadj == null) {
+            if (hadj == null || vadj == null) {
                 return;
             }
             
-            vadj.ValueChanged += OnAdjustmentChanged;
-            hadj.ValueChanged += OnAdjustmentChanged;
+            hadj.ValueChanged += OnHadjustmentChanged;
+            vadj.ValueChanged += OnVadjustmentChanged;
             
             UpdateAdjustments (hadj, vadj);
         }

Modified: trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Model.cs
==============================================================================
--- trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Model.cs	(original)
+++ trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Model.cs	Mon Mar 31 05:35:56 2008
@@ -69,7 +69,7 @@
 
         private void RefreshViewForModel (double? vpos)
         {
-            UpdateAdjustments (null, null);
+            UpdateAdjustments ();
 
             if (vpos != null) {
                 ScrollTo ((double) vpos);

Modified: trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Rendering.cs
==============================================================================
--- trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Rendering.cs	(original)
+++ trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Rendering.cs	Mon Mar 31 05:35:56 2008
@@ -88,11 +88,13 @@
                 canvas1 = new Pixmap (GdkWindow, canvas_alloc.Width, canvas_alloc.Height);
                 render_everything = true;
             }
-            PaintList (damage);
+            PaintList ();
             
             // Now we blit the offscreen canvas onto the GdkWindow.
-            GdkWindow.DrawDrawable (Style.BaseGC (StateType.Normal), canvas1, 0, (int)vadjustment.Value % RowHeight,
-                list_rendering_alloc.X, list_rendering_alloc.Y, list_rendering_alloc.Width, list_rendering_alloc.Height);
+            GdkWindow.DrawDrawable (Style.BaseGC (StateType.Normal), canvas1,
+                (int)hadjustment.Value, (int)vadjustment.Value % RowHeight,
+                list_rendering_alloc.X, list_rendering_alloc.Y,
+                list_rendering_alloc.Width, list_rendering_alloc.Height);
             
             // Finally, render the dragging box and dispose of the cairo context.
             PaintDraggingColumn (damage);
@@ -124,13 +126,13 @@
                     continue;
                 }
                 
-                cell_area.X = column_cache[ci].X1 + Theme.TotalBorderWidth + header_rendering_alloc.X;
+                cell_area.X = column_cache[ci].X1 + Theme.TotalBorderWidth + header_rendering_alloc.X - (int)hadjustment.Value;
                 cell_area.Width = column_cache[ci].Width;
                 PaintHeaderCell (cell_area, clip, ci, false);
             }
             
             if (pressed_column_is_dragging && pressed_column_index >= 0) {
-                cell_area.X = pressed_column_x_drag + Allocation.X;
+                cell_area.X = pressed_column_x_drag + Allocation.X - (int)hadjustment.Value;
                 cell_area.Width = column_cache[pressed_column_index].Width;
                 PaintHeaderCell (cell_area, clip, pressed_column_index, true);
             }
@@ -171,7 +173,7 @@
             }
         }
 
-        private void PaintList (Rectangle clip)
+        private void PaintList ()
         {
             if (model == null) {
                 return;
@@ -180,7 +182,9 @@
             // Render the sort effect to the GdkWindow.
             if (sort_column_index != -1 && (!pressed_column_is_dragging || pressed_column_index != sort_column_index)) {
                 CachedColumn col = column_cache[sort_column_index];
-                Theme.DrawRowRule (cairo_context, list_rendering_alloc.X + col.X1, header_rendering_alloc.Bottom + Theme.BorderWidth,
+                Theme.DrawRowRule (cairo_context,
+                    list_rendering_alloc.X + col.X1 - (int)hadjustment.Value,
+                    header_rendering_alloc.Bottom + Theme.BorderWidth,
                     col.Width, list_rendering_alloc.Height + Theme.InnerBorderWidth * 2);
             }
 
@@ -231,7 +235,7 @@
                 // render the new stuff in situ at the bottom.
                 int delta = (last_row - canvas_last_row) * RowHeight;
                 canvas1.DrawDrawable (Style.BaseGC (StateType.Normal), canvas2, 0, delta, 0, 0,
-                    list_rendering_alloc.Width, canvas_alloc.Height - delta);
+                    canvas_alloc.Width, canvas_alloc.Height - delta);
                 
                 // If the bottom of the stuff we're shifting up is part of a selection
                 // that continues down into the new stuff, be sure that we render the
@@ -247,7 +251,7 @@
                 // render the new stuff in situ at the top.
                 int delta = (canvas_first_row - first_row) * RowHeight;
                 canvas1.DrawDrawable (Style.BaseGC (StateType.Normal), canvas2, 0, 0, 0, delta,
-                    list_rendering_alloc.Width, canvas_alloc.Height - delta);
+                    canvas_alloc.Width, canvas_alloc.Height - delta);
                 
                 // If the top of the stuff we're shifting down is part of a selection
                 // that continues up into the new stuff, be sure that we render the
@@ -259,7 +263,7 @@
                 last_row = canvas_first_row;
             }
             
-            PaintRows (first_row, Math.Min (model.Count, last_row), first_row_y, clip);
+            PaintRows (first_row, Math.Min (model.Count, last_row), first_row_y);
             
             // Destroy the cairo context.
             ((IDisposable)cairo_context.Target).Dispose ();
@@ -270,7 +274,7 @@
             canvas_last_row = bottom;
         }
         
-        private void PaintRows (int first_row, int last_row, int first_row_y, Rectangle clip)
+        private void PaintRows (int first_row, int last_row, int first_row_y)
         {
             Rectangle selected_focus_alloc = Rectangle.Zero;
             Rectangle single_list_alloc = new Rectangle ();
@@ -334,7 +338,7 @@
                         selection_height = 0;
                     }
                     
-                    PaintRow (ri, clip, single_list_alloc, StateType.Normal);
+                    PaintRow (ri, single_list_alloc, StateType.Normal);
                 }
                 
                 single_list_alloc.Y += single_list_alloc.Height;
@@ -353,11 +357,11 @@
             
             foreach (int ri in selected_rows) {
                 single_list_alloc.Y = (ri - first_row) * single_list_alloc.Height + first_row_y;
-                PaintRow (ri, clip, single_list_alloc, StateType.Selected);
+                PaintRow (ri, single_list_alloc, StateType.Selected);
             }
         }
 
-        private void PaintRow (int row_index, Rectangle clip, Rectangle area, StateType state)
+        private void PaintRow (int row_index, Rectangle area, StateType state)
         {
             if (column_cache == null) {
                 return;
@@ -377,18 +381,18 @@
                 
                 cell_area.Width = column_cache[ci].Width;
                 cell_area.X = column_cache[ci].X1 + area.X;
-                PaintCell (item, ci, row_index, cell_area, clip, sensitive ? state : StateType.Insensitive, false);
+                PaintCell (item, ci, row_index, cell_area, sensitive ? state : StateType.Insensitive, false);
             }
             
             if (pressed_column_is_dragging && pressed_column_index >= 0) {
                 cell_area.Width = column_cache[pressed_column_index].Width;
                 cell_area.X = pressed_column_x_drag - list_interaction_alloc.X;
-                PaintCell (item, pressed_column_index, row_index, cell_area, clip, state, true);
+                PaintCell (item, pressed_column_index, row_index, cell_area, state, true);
             }
         }
         
         private void PaintCell (object item, int column_index, int row_index, Rectangle area, 
-            Rectangle clip, StateType state, bool dragging)
+            StateType state, bool dragging)
         {
             ColumnCell cell = column_cache[column_index].Column.GetCell (0);
             cell.BindListItem (item);
@@ -403,7 +407,7 @@
             
             cairo_context.Save ();
             cairo_context.Translate (area.X, area.Y);
-            cell.Render (new CellContext (cairo_context, list_pango_layout, this, canvas1, theme, area, clip), 
+            cell.Render (new CellContext (cairo_context, list_pango_layout, this, canvas1, theme, area, canvas_alloc), 
                 dragging ? StateType.Normal : state, area.Width, area.Height);
             cairo_context.Restore ();
         }
@@ -416,7 +420,7 @@
             
             CachedColumn column = column_cache[pressed_column_index];
             
-            int x = pressed_column_x_drag + Allocation.X + 1;
+            int x = pressed_column_x_drag + Allocation.X + 1 - (int)hadjustment.Value;
             
             Cairo.Color fill_color = Theme.Colors.GetWidgetColor (GtkColorClass.Base, StateType.Normal);
             fill_color.A = 0.45;

Modified: trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Windowing.cs
==============================================================================
--- trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Windowing.cs	(original)
+++ trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Windowing.cs	Mon Mar 31 05:35:56 2008
@@ -80,6 +80,7 @@
             
             OnDragSourceSet ();
             MoveResize (Allocation);
+            RegenerateCanvases ();
         }
         
         protected override void OnUnrealized ()
@@ -131,7 +132,12 @@
             list_interaction_alloc = list_rendering_alloc;
             list_interaction_alloc.Offset (-allocation.X, -allocation.Y);
             
-            int canvas_width = Math.Max (1, list_rendering_alloc.Width);
+            header_width = header_interaction_alloc.Width;
+        }
+        
+        private void RegenerateCanvases ()
+        {
+            int canvas_width = Math.Max (1, header_width);
             int canvas_height = Math.Max (1, RowsInView * RowHeight);
             
             if (canvas_alloc.Width != canvas_width || canvas_alloc.Height != canvas_height) {
@@ -159,8 +165,8 @@
             if (Theme == null) {
                 return;
             }
-            requisition.Width = Theme.InnerBorderWidth * 2;
-            requisition.Height = HeaderHeight;
+            requisition.Width = Theme.TotalBorderWidth * 2;
+            requisition.Height = HeaderHeight + Theme.TotalBorderWidth * 2;
         }
         
         protected override void OnSizeAllocated (Rectangle allocation)
@@ -172,11 +178,16 @@
             }
             
             MoveResize (allocation);
+            RecalculateColumnSizes ();
+            RegenerateColumnCache ();
+            RegenerateCanvases ();
            
             if (vadjustment != null) {
+                hadjustment.PageSize = header_interaction_alloc.Width;
+                hadjustment.PageIncrement = header_interaction_alloc.Width;
                 vadjustment.PageSize = list_rendering_alloc.Height;
                 vadjustment.PageIncrement = list_rendering_alloc.Height;
-                UpdateAdjustments (null, null);
+                UpdateAdjustments ();
             }
             
             ICareAboutView model = Model as ICareAboutView;
@@ -184,7 +195,6 @@
                 model.RowsInView = RowsInView;
             }
             
-            RegenerateColumnCache ();
             InvalidateList (false);
         }
         

Modified: trunk/banshee/src/Libraries/Hyena/Hyena.Data/ColumnDescription.cs
==============================================================================
--- trunk/banshee/src/Libraries/Hyena/Hyena.Data/ColumnDescription.cs	(original)
+++ trunk/banshee/src/Libraries/Hyena/Hyena.Data/ColumnDescription.cs	Mon Mar 31 05:35:56 2008
@@ -38,6 +38,7 @@
         private string property;
         
         public event EventHandler VisibilityChanged;
+        public event EventHandler WidthChanged;
         
         public ColumnDescription (string property, string title, double width) : this (property, title, width, true)
         {
@@ -59,6 +60,14 @@
             }
         }
         
+        protected virtual void OnWidthChanged ()
+        {
+            EventHandler handler = WidthChanged;
+            if (handler != null) {
+                handler (this, EventArgs.Empty);
+            }
+        }
+        
         public string Title {
             get { return title; }
             set { title = value; }
@@ -66,7 +75,14 @@
         
         public double Width {
             get { return width; }
-            set { width = value; }
+            set {
+                double old = width;
+                width = value;
+                
+                if (value != old) {
+                    OnWidthChanged ();
+                }
+            }
         }
         
         public string Property {
@@ -81,7 +97,7 @@
                 visible = value;
                 
                 if(value != old) {
-                    OnVisibilityChanged();
+                    OnVisibilityChanged ();
                 }
             }
         }



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