[beagle] Grow/shrink the number beagle-search results based on window size



commit 7cfcb26cd31f43ad93d32d3354787e6c2915b5e3
Author: Chris Rivera <crivera novell com>
Date:   Tue May 26 17:07:24 2009 -0400

    Grow/shrink the number beagle-search results based on window size
    
    Rework the size requsitioning to always take all available window
    space for results, and to dynamically grow and shrink based on the
    size of the window.  Fixes bgo #582354 and #328440.
---
 beagle/search/Beagle.Search/Category.cs  |  127 +++++++++++++++---------------
 beagle/search/Beagle.Search/GroupView.cs |   63 +++++++++++++++
 beagle/search/Beagle.Search/Panes.cs     |    4 +
 3 files changed, 129 insertions(+), 65 deletions(-)

diff --git a/beagle/search/Beagle.Search/Category.cs b/beagle/search/Beagle.Search/Category.cs
index 3a920ab..06e8724 100644
--- a/beagle/search/Beagle.Search/Category.cs
+++ b/beagle/search/Beagle.Search/Category.cs
@@ -18,17 +18,14 @@ namespace Beagle.Search {
 
 	public abstract class Category : Container {
 
-		private SortedTileList tiles = null;
-		private int page = 0;
-
 		protected Gtk.HBox header;
+		private SortedTileList tiles;
 		private Gtk.Label position;
 		private Gtk.Button prev, next;
 		private Gtk.Expander headerExpander;
-		private int fewRows, manyRows, columns;
-		private int few, many;
 		private bool extended, expanded;
 		private ScopeType scope;
+		private int columns, tileIndex, tileHeight;
 
 		public Category (Tiles.TileGroupInfo info, int columns)
 		{
@@ -60,14 +57,9 @@ namespace Beagle.Search {
 			header.SizeRequested += HeaderSizeRequested;
 
 			tiles = new SortedTileList (Beagle.Search.SortType.Relevance);
-			page = 0;
-
-			fewRows = info.Rows;
-			manyRows = info.Rows * 2;
 			Columns = columns;
 
 			UpdateButtons ();
-			//headerExpander.Expanded = true;
 			Expanded = true;	
 		}
 
@@ -91,7 +83,7 @@ namespace Beagle.Search {
 				expanded = value;
 
 				if (expanded)
-					ShowTiles (false);
+					ShowTiles ();
 				else
 					HideTiles ();
 
@@ -103,12 +95,10 @@ namespace Beagle.Search {
 			get { return columns; }
 			set {
 				HideTiles ();
-
 				columns = value;
-				few = fewRows * columns;
-				many = manyRows * columns;
 
-				ShowTiles (true);
+				if (Expanded)
+					ShowTiles ();
 			}
 		}
 
@@ -127,14 +117,9 @@ namespace Beagle.Search {
 			args.Requisition = req;
 		}
 
-		void UpdateButtons ()
+		private void UpdateButtons ()
 		{
-			if (tiles.Count <= FirstVisible && page > 0) {
-				// The page we were viewing disappeared
-				page--;
-			}
-
-			prev.Sensitive = (page != 0);
+			prev.Sensitive = tileIndex != 0;
 			next.Sensitive = (tiles.Count > LastVisible + 1);
 
 			if (tiles.Count > 0) {
@@ -156,7 +141,7 @@ namespace Beagle.Search {
 			tiles.Add ((Tiles.Tile)widget);
 
 			if (Expanded)
-				ShowTiles (true);
+				ShowTiles ();
 		}
 
 		protected override void OnRemoved (Gtk.Widget widget)
@@ -168,41 +153,31 @@ namespace Beagle.Search {
 			tiles.Remove ((Tiles.Tile)widget);
 
 			if (Expanded)
-				ShowTiles (true);
+				ShowTiles ();
 		}
 
 		private Tiles.Tile lastTarget;
 		private bool hadFocus;
 
-		void HideTiles ()
+		private void HideTiles ()
 		{
 			lastTarget = null;
-			foreach (Tiles.Tile tile in VisibleTiles) {
+			foreach (Tiles.Tile tile in AllTiles) {
 				if (tile.HasFocus || lastTarget == null) {
 					lastTarget = tile;
 					hadFocus = tile.HasFocus;
 				}
 				tile.ChildVisible = false;
 			}
+
 			QueueResize ();
 		}
 
-		void ShowTiles (bool recenter)
+		private void ShowTiles ()
 		{
-			if (recenter && lastTarget != null) {
-				int index = tiles.IndexOf (lastTarget);
-				if (hadFocus || page > 0) {
-					if (index < few)
-						page = 0;
-					else if (extended)
-						page = index / (manyRows * columns);
-					else
-						page = ((index - few) / (manyRows * columns)) + 1;
-				}
-			}
-
 			foreach (Tiles.Tile tile in VisibleTiles) {
 				tile.ChildVisible = true;
+
 				if (tile == lastTarget && hadFocus && !tile.HasFocus)
 					tile.GrabFocus ();
 			}
@@ -211,33 +186,26 @@ namespace Beagle.Search {
 			QueueResize ();
 		}
 
-		private bool showingMany {
-			get {
-				// Show extra tiles on every page after the first, unless
-				// there are only two pages and the second one only has
-				// enough tiles to fit the "fewer" size.
-				return (page > 0 && tiles.Count > 2 * few) || extended;
-			}
-		}
-
-		void OnPrev (object obj, EventArgs args)
+		private void OnPrev (object obj, EventArgs args)
 		{
 			HideTiles ();
-			page--;
+			tileIndex = Math.Max (0, tileIndex - PageSize);
+			
 			if (!Expanded)
 				OnActivated (obj, args);
 			else
-				ShowTiles (false);
+				ShowTiles ();
 		}
 
-		void OnNext (object obj, EventArgs args)
+		private void OnNext (object obj, EventArgs args)
 		{
 			HideTiles ();
-			page++;
+			tileIndex = Math.Min (tiles.Count - 1, tileIndex + PageSize);
+			
 			if (!Expanded)
 				OnActivated (obj, args);
 			else
-				ShowTiles (false);
+				ShowTiles ();
 		}
 
 		protected void OnActivated (object obj, EventArgs args)
@@ -246,27 +214,56 @@ namespace Beagle.Search {
 			CategoryToggle (scope);
 		}
 
+		public void SetMaxDisplayHeight (int height)
+		{
+			if (tileHeight != height) {
+				tileHeight = height;
+				HideTiles ();
+
+				if (Expanded)
+					ShowTiles ();
+			}
+		}
+
+		public int GetPotentialDisplayHeight ()
+		{
+			if (tiles.Count == 0)
+				return 0;
+
+			Requisition headerReq = header.SizeRequest ();
+			Requisition tileReq = tiles[0].SizeRequest ();
+			return headerReq.Height + (tiles.Count / Columns) * tileReq.Height;
+		}
+		
 		public delegate void CategoryToggleDelegate (ScopeType scope);
 		public event CategoryToggleDelegate CategoryToggle;
 
 		protected int PageSize {
 			get {
-				return Math.Min (showingMany ? many : few, tiles.Count);
+				if (tiles.Count == 0)
+					return 0;
+
+				if (tileHeight == 0)
+					return Math.Min (2 * Columns, tiles.Count);
+
+				Requisition sizeReq = tiles[0].SizeRequest ();
+				int ps = Math.Min (tileHeight / sizeReq.Height * Columns, tiles.Count);
+				
+				// Display at least two rows if we have the hits for it.
+				if (ps < 2 * Columns)
+					ps = Math.Min (2 * Columns, tiles.Count);
+                
+				return ps;
 			}
 		}
 
-		protected int FirstVisible {
+		private int FirstVisible {
 			get {
-				if (page == 0)
-					return 0;
-				else if (extended)
-					return page * many;
-				else
-					return few + (page - 1) * many;
+				return tileIndex;
 			}
 		}
 
-		protected int LastVisible {
+		private int LastVisible {
 			get {
 				return Math.Min (FirstVisible + PageSize, tiles.Count) - 1;
 			}
@@ -337,7 +334,7 @@ namespace Beagle.Search {
 			set {
 				HideTiles ();
 				tiles.SortType = value;
-				ShowTiles (true);
+				ShowTiles ();
 			}
 		}
 
@@ -346,7 +343,7 @@ namespace Beagle.Search {
 			if (extended) {
 				HideTiles ();
 				this.extended = extended;
-				ShowTiles (false);
+				ShowTiles ();
 			}
 			if (focus && !Empty)
 				((Gtk.Widget)VisibleTiles[0]).GrabFocus ();
diff --git a/beagle/search/Beagle.Search/GroupView.cs b/beagle/search/Beagle.Search/GroupView.cs
index d9d6319..e0620da 100644
--- a/beagle/search/Beagle.Search/GroupView.cs
+++ b/beagle/search/Beagle.Search/GroupView.cs
@@ -25,6 +25,9 @@ namespace Beagle.Search {
 		private Gtk.SizeGroup tileSizeGroup;
 		private Gtk.Widget selection;
 
+		private int[] maxHeight;
+		private int[] displayHeight;
+
 		public event CategoryToggledDelegate CategoryToggled;
 		public event TileHandler TileSelected;
 
@@ -47,8 +50,68 @@ namespace Beagle.Search {
 
 				categories [info.Group] = box;
 			}
+
+			maxHeight = new int[Children.Length];
+			displayHeight = new int[Children.Length];
 		}
 		
+        public void AdjustCategories (int height)
+        {
+			Category last = null;
+			int visible = 0, totalHeight = height, childLen = Children.Length;
+			ulong mask = ~0UL;
+
+			for (int i = 0; i < childLen; i++) {
+				displayHeight[i] = maxHeight[i] = 0;
+				Category c = (Category) Children[i];
+				if (!c.Expanded || c.Count == 0) {
+					mask ^= 1UL << i;
+					continue;
+				}
+                
+				last = c;
+				visible++;
+				maxHeight[i] = c.GetPotentialDisplayHeight ();
+			}
+
+			if (visible == 0) {
+				return;
+			} else if (visible == 1) {
+				last.SetMaxDisplayHeight (height);
+				return;
+			}
+
+			// Split the available height among the visible categories
+			for (int active = visible; active > 0 && totalHeight > active;) {
+				int avg_height = totalHeight / active;
+
+				for (int i = 0; i < childLen; i++) {
+					if ((mask & 1UL << i) == 0)
+						continue;
+
+					int diff = maxHeight[i] - displayHeight[i];
+					if (diff <= avg_height) {
+						displayHeight[i] += diff;
+						totalHeight -= diff;
+						mask ^= 1UL << i;
+					} else {
+						displayHeight[i] += avg_height;
+						totalHeight -= avg_height;
+					}
+				}
+
+				for (int j = active = 0; j < childLen; j++)
+					if ((mask & 1UL << j) != 0)
+						active++;
+			}
+
+			// Tell each category how much height it has to work with
+			for (int i = 0; i < childLen; i++) {
+				Category c = (Category) Children[i];
+				c.SetMaxDisplayHeight (displayHeight[i]);
+			}
+		}
+
 		public void AddHit (Tile tile)
 		{
 			tile.Show ();
diff --git a/beagle/search/Beagle.Search/Panes.cs b/beagle/search/Beagle.Search/Panes.cs
index 3ae5b7e..4b6a554 100644
--- a/beagle/search/Beagle.Search/Panes.cs
+++ b/beagle/search/Beagle.Search/Panes.cs
@@ -92,6 +92,10 @@ namespace Beagle.Search {
 				Gtk.Widget focusChild = mainChild.FocusChild;
 				mainChild.FocusChild = null;
 				mainChild.FocusChild = focusChild;
+
+				GroupView gv = mainChild as GroupView;
+				if (gv != null)
+					gv.AdjustCategories (args.Allocation.Height);
 			}
 		}
 



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