From b5577ed423c6110919b13526aead2cf98a6651a2 Mon Sep 17 00:00:00 2001
From: MaxED <j.maxed@gmail.com>
Date: Tue, 23 Feb 2016 13:55:53 +0000
Subject: [PATCH] Changed the way filtering in the Edit Things, Browse Action
 and Browse Effect windows work: items, which names start with filter text are
 now displayed first. Cosmetic tweaks to the way thing bounding boxes are
 rendered in Things mode when "Fixed Things Scale" option is enabled (bounding
 boxes of highlighted/selected things are now more opaque than the ones of
 unselected things). Changed, Preferences form: action selected in the actions
 list is now stays selected when applying the filtering (unless it's no longer
 valid).

---
 Source/Core/Controls/ThingBrowserControl.cs | 13 ++-
 Source/Core/Rendering/Renderer2D.cs         |  3 +-
 Source/Core/Windows/ActionBrowserForm.cs    | 28 ++++--
 Source/Core/Windows/EffectBrowserForm.cs    | 28 ++++--
 Source/Core/Windows/PreferencesForm.cs      | 94 ++++++++++++---------
 5 files changed, 113 insertions(+), 53 deletions(-)

diff --git a/Source/Core/Controls/ThingBrowserControl.cs b/Source/Core/Controls/ThingBrowserControl.cs
index 30937207b..70d70321d 100644
--- a/Source/Core/Controls/ThingBrowserControl.cs
+++ b/Source/Core/Controls/ThingBrowserControl.cs
@@ -455,14 +455,25 @@ namespace CodeImp.DoomBuilder.Controls
 				validnodes.Clear();
 
 				string match = tbFilter.Text.ToUpperInvariant();
+				HashSet<string> added = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
+				
+				// First add nodes, which titles start with given text
 				foreach(TreeNode node in nodes)
 				{
-					if(node.Text.ToUpperInvariant().Contains(match)) 
+					if(node.Text.ToUpperInvariant().StartsWith(match))
 					{
 						typelist.Nodes.Add(node);
+						added.Add(node.Text);
 					}
 				}
 
+				// Then add nodes, which titles contain given text
+				foreach(TreeNode node in nodes)
+				{
+					if(!added.Contains(node.Text) && node.Text.ToUpperInvariant().Contains(match)) 
+						typelist.Nodes.Add(node);
+				}
+
 				doupdatenode = true;
 				doupdatetextbox = true;
 			}
diff --git a/Source/Core/Rendering/Renderer2D.cs b/Source/Core/Rendering/Renderer2D.cs
index fd10e2818..82ae9c9c7 100644
--- a/Source/Core/Rendering/Renderer2D.cs
+++ b/Source/Core/Rendering/Renderer2D.cs
@@ -1111,7 +1111,7 @@ namespace CodeImp.DoomBuilder.Rendering
 				
 				// Make alpha color
 				Color4 alphacolor = new Color4(alpha, 1.0f, 1.0f, 1.0f);
-				byte bboxalpha = (byte)(alpha * (General.Editing.Mode.GetType().Name == "ThingsMode" ? 128 : 255));
+				bool isthingsmode = (General.Editing.Mode.GetType().Name == "ThingsMode");
 				
 				// Set renderstates for things rendering
 				graphics.Device.SetRenderState(RenderState.CullMode, Cull.None);
@@ -1160,6 +1160,7 @@ namespace CodeImp.DoomBuilder.Rendering
 					
 					// Create vertices
 					PixelColor tc = fixedcolor ? c : DetermineThingColor(t);
+					byte bboxalpha = (byte)(alpha * ((!fixedcolor && !t.Selected && isthingsmode) ? 128 : 255));
 					if(CreateThingBoxVerts(t, ref verts, ref bboxes, thingsByPosition, buffercount * 6, tc, bboxalpha))
 					{
 						buffercount++;
diff --git a/Source/Core/Windows/ActionBrowserForm.cs b/Source/Core/Windows/ActionBrowserForm.cs
index 12f2cbd97..85e0c4640 100644
--- a/Source/Core/Windows/ActionBrowserForm.cs
+++ b/Source/Core/Windows/ActionBrowserForm.cs
@@ -192,24 +192,40 @@ namespace CodeImp.DoomBuilder.Windows
 		}
 
 		//mxd
-		private void FilterActions(string p) 
+		private void FilterActions(string text) 
 		{
-			List<TreeNode> filteredNodes = new List<TreeNode>();
+			List<TreeNode> filterednodes = new List<TreeNode>();
+			HashSet<string> added = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
 
+			// First add nodes, which titles start with given text
 			foreach(TreeNode n in allNodes) 
 			{
 				foreach(TreeNode cn in n.Nodes) 
 				{
 					LinedefActionInfo ai = cn.Tag as LinedefActionInfo;
-					if(ai.Title.ToLowerInvariant().IndexOf(p) != -1)
-						filteredNodes.Add(cn);
+					if(ai != null && ai.Title.ToUpperInvariant().StartsWith(text))
+					{
+						filterednodes.Add(cn);
+						added.Add(ai.Title);
+					}
+				}
+			}
+
+			// Then add nodes, which titles contain given text
+			foreach(TreeNode n in allNodes)
+			{
+				foreach(TreeNode cn in n.Nodes)
+				{
+					LinedefActionInfo ai = cn.Tag as LinedefActionInfo;
+					if(ai != null && !added.Contains(ai.Title) && ai.Title.ToUpperInvariant().Contains(text))
+						filterednodes.Add(cn);
 				}
 			}
 
 			actions.BeginUpdate();
 			actions.Nodes.Clear();
 			actions.ShowLines = false;
-			actions.Nodes.AddRange(filteredNodes.ToArray());
+			actions.Nodes.AddRange(filterednodes.ToArray());
 			actions.EndUpdate();
 		}
 		
@@ -322,7 +338,7 @@ namespace CodeImp.DoomBuilder.Windows
 		{
 			if(!string.IsNullOrEmpty(tbFilter.Text.Trim()))
 			{
-				FilterActions(tbFilter.Text);
+				FilterActions(tbFilter.Text.ToUpperInvariant());
 			} 
 			else
 			{
diff --git a/Source/Core/Windows/EffectBrowserForm.cs b/Source/Core/Windows/EffectBrowserForm.cs
index 89d20e54c..00bc70683 100644
--- a/Source/Core/Windows/EffectBrowserForm.cs
+++ b/Source/Core/Windows/EffectBrowserForm.cs
@@ -155,20 +155,36 @@ namespace CodeImp.DoomBuilder.Windows
 		}
 
 		//mxd
-		private void FilterEffects(string p) 
+		private void FilterEffects(string text) 
 		{
-			List<ListViewItem> filteredItems = new List<ListViewItem>();
+			List<ListViewItem> filtereditems = new List<ListViewItem>();
+			HashSet<string> added = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
 
+			// First add nodes, which titles start with given text
 			foreach(ListViewItem i in allitems) 
 			{
 				SectorEffectInfo si = i.Tag as SectorEffectInfo;
-				if(si.Title.ToLowerInvariant().IndexOf(p) != -1)
-					filteredItems.Add(i);
+				if(si != null && si.Title.ToUpperInvariant().StartsWith(text))
+				{
+					filtereditems.Add(i);
+					added.Add(si.Title);
+				}
+			}
+
+			// Then add nodes, which titles contain given text
+			foreach(ListViewItem i in allitems)
+			{
+				SectorEffectInfo si = i.Tag as SectorEffectInfo;
+				if(si != null && !added.Contains(si.Title) && si.Title.ToUpperInvariant().Contains(text))
+				{
+					filtereditems.Add(i);
+					added.Add(si.Title);
+				}
 			}
 
 			effects.BeginUpdate();
 			effects.Items.Clear();
-			effects.Items.AddRange(filteredItems.ToArray());
+			effects.Items.AddRange(filtereditems.ToArray());
 			effects.EndUpdate();
 		}
 		
@@ -236,7 +252,7 @@ namespace CodeImp.DoomBuilder.Windows
 		{
 			if(!string.IsNullOrEmpty(tbFilter.Text.Trim()))
 			{
-				FilterEffects(tbFilter.Text);
+				FilterEffects(tbFilter.Text.ToUpperInvariant());
 			} 
 			else
 			{
diff --git a/Source/Core/Windows/PreferencesForm.cs b/Source/Core/Windows/PreferencesForm.cs
index 11203799a..78a53fb67 100644
--- a/Source/Core/Windows/PreferencesForm.cs
+++ b/Source/Core/Windows/PreferencesForm.cs
@@ -39,8 +39,8 @@ namespace CodeImp.DoomBuilder.Windows
 		private bool allowapplycontrol;
 		private bool disregardshift;
 		private bool disregardcontrol;
-		private readonly List<ListViewItem> actionListItems; //mxd
-		private readonly List<int> actionListItemsGroupIndices; //mxd
+		private readonly List<ListViewItem> allactionitems; //mxd
+		private readonly List<int> allactionitemsgroups; //mxd
 
 		private bool reloadresources;
 		
@@ -148,8 +148,10 @@ namespace CodeImp.DoomBuilder.Windows
 			
 			// Fill list of actions
 			Action[] actions = General.Actions.GetAllActions();
-			actionListItems = new List<ListViewItem>(); //mxd
-			actionListItemsGroupIndices = new List<int>(); //mxd
+			allactionitems = new List<ListViewItem>(); //mxd
+			allactionitemsgroups = new List<int>(); //mxd
+
+			listactions.BeginUpdate(); //mxd
 			foreach(Action a in actions)
 			{
 				// Create item
@@ -161,15 +163,16 @@ namespace CodeImp.DoomBuilder.Windows
 				if(General.Actions.Categories.ContainsKey(a.Category)) 
 				{
 					item.Group = listactions.Groups[a.Category];
-					actionListItemsGroupIndices.Add(listactions.Groups.IndexOf(item.Group));
+					allactionitemsgroups.Add(listactions.Groups.IndexOf(item.Group)); //mxd
 				}
 				else //mxd
 				{ 
-					actionListItemsGroupIndices.Add(-1);
+					allactionitemsgroups.Add(-1);
 				}
 
-				actionListItems.Add(item); //mxd
+				allactionitems.Add(item); //mxd
 			}
+			listactions.EndUpdate(); //mxd
 
 			// Set the colors
 			// TODO: Make this automated by using the collection
@@ -304,7 +307,7 @@ namespace CodeImp.DoomBuilder.Windows
 			General.Settings.ScriptFontSize = fontsize;
 			
 			// Apply control keys to actions
-			foreach(ListViewItem item in actionListItems) //mxd
+			foreach(ListViewItem item in allactionitems) //mxd
 				General.Actions[item.Name].SetShortcutKey((int)item.SubItems[1].Tag);
 
 			// Apply the colors
@@ -503,7 +506,7 @@ namespace CodeImp.DoomBuilder.Windows
 				if(thiskey != 0)
 				{
 					// Find actions with same key
-					foreach(ListViewItem item in actionListItems)
+					foreach(ListViewItem item in allactionitems)
 					{
 						// Don't count the selected action
 						if(item != listactions.SelectedItems[0])
@@ -665,6 +668,9 @@ namespace CodeImp.DoomBuilder.Windows
 		// Item selected
 		private void listactions_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e)
 		{
+			//mxd. Leave when not allowed to update
+			if(!allowapplycontrol) return;
+
 			string disregardkeys = "";
 
 			// Anything selected?
@@ -849,51 +855,61 @@ namespace CodeImp.DoomBuilder.Windows
 		}
 
 		//mxd
-		private void tbFilterActions_TextChanged(object sender, EventArgs e) 
+		private void tbFilterActions_TextChanged(object sender, EventArgs e)
 		{
+			ListViewItem curselection = (listactions.SelectedItems.Count > 0 ? listactions.SelectedItems[0] : null);
+			ListViewItem toselect = null;
+
+			allowapplycontrol = false;
 			listactions.BeginUpdate();
+			listactions.Items.Clear();
 			
-			//restore everything
-			if(string.IsNullOrEmpty(tbFilterActions.Text)) 
+			// Restore everything
+			if(string.IsNullOrEmpty(tbFilterActions.Text))
 			{
-				//restore items
-				listactions.Items.Clear();
-				listactions.Items.AddRange(actionListItems.ToArray());
-
-				//restore groups
-				for(int i = 0; i < actionListItems.Count; i++) 
+				// Restore items and groups
+				for(int i = 0; i < allactionitems.Count; i++)
 				{
-					if(actionListItemsGroupIndices[i] != -1)
-						actionListItems[i].Group = listactions.Groups[actionListItemsGroupIndices[i]];
+					if(allactionitemsgroups[i] != -1)
+						allactionitems[i].Group = listactions.Groups[allactionitemsgroups[i]];
+
+					// Item sould be added AFTER restoring it's group, otherwise item sorting will be screwed!
+					listactions.Items.Add(allactionitems[i]);
+
+					// Restore selection?
+					if(allactionitems[i] == curselection) toselect = curselection;
 				}
-			} 
-			else //apply filtering
-			{ 
+			}
+			// Apply filtering
+			else
+			{
 				string match = tbFilterActions.Text.ToUpperInvariant();
-				for(int i = 0; i < actionListItems.Count; i++) 
+				for(int i = 0; i < allactionitems.Count; i++) 
 				{
-					if(actionListItems[i].Text.ToUpperInvariant().Contains(match)) 
+					if(allactionitems[i].Text.ToUpperInvariant().Contains(match))
 					{
-						//ensure visible
-						if(!listactions.Items.Contains(actionListItems[i])) 
-						{
-							listactions.Items.Add(actionListItems[i]);
+						// Restore group
+						if(allactionitemsgroups[i] != -1)
+							allactionitems[i].Group = listactions.Groups[allactionitemsgroups[i]];
 
-							//restore group
-							if(actionListItemsGroupIndices[i] != -1)
-								actionListItems[i].Group = listactions.Groups[actionListItemsGroupIndices[i]];
-						}
+						// Add item
+						listactions.Items.Add(allactionitems[i]);
+
+						// Restore selection?
+						if(allactionitems[i] == curselection) toselect = curselection;
 					} 
-					else if(listactions.Items.Contains(actionListItems[i])) 
-					{
-						//ensure invisible
-						listactions.Items.Remove(actionListItems[i]);
-					}
 				}
 			}
 
-			listactions.Sort();
+			// Restore selection?
+			if(toselect != null)
+			{
+				toselect.Selected = true;
+				listactions.EnsureVisible(toselect.Index);
+			}
+
 			listactions.EndUpdate();
+			allowapplycontrol = true;
 		}
 
 		#endregion
-- 
GitLab