Hey,

The attached patch adds support for AutoCompletMode.Append and
AutoCompleteMode.SuggestAppend for TextBox.

Ok to commit?
Carlos.
Index: TextBox.cs
===================================================================
--- TextBox.cs	(revisiĆ³n: 110900)
+++ TextBox.cs	(copia de trabajo)
@@ -60,6 +60,8 @@
 		private AutoCompleteSource auto_complete_source = AutoCompleteSource.None;
 		private AutoCompleteListBox auto_complete_listbox;
 		private string auto_complete_original_text;
+		private int auto_complete_selected_index = -1;
+		private List<string> auto_complete_matches;
 		private ComboBox auto_complete_cb_source;
 #endif
 		#endregion	// Variables
@@ -131,16 +133,15 @@
 			auto_complete_listbox.Scroll (-lines);
 		}
 
-		private void ShowAutoCompleteListBox ()
+		private void ShowAutoCompleteListBox (bool is_backspace)
 		{
 			if (auto_complete_mode == AutoCompleteMode.None || auto_complete_source == AutoCompleteSource.None)
 				return;
 
 			// 
-			// We only support CustomSource *and* Suggest mode by now
+			// We only support CustomSource by now
 			//
-
-			if (auto_complete_mode != AutoCompleteMode.Suggest)
+			if (auto_complete_source != AutoCompleteSource.CustomSource)
 				return;
 
 			IList source;
@@ -149,41 +150,57 @@
 			else
 				source = auto_complete_cb_source.Items;
 
-			if (auto_complete_source != AutoCompleteSource.CustomSource ||
-				source == null || source.Count == 0)
+			if (source == null || source.Count == 0)
 				return;
 
+			bool append = auto_complete_mode == AutoCompleteMode.Append || auto_complete_mode == AutoCompleteMode.SuggestAppend;
+			bool suggest = auto_complete_mode == AutoCompleteMode.Suggest || auto_complete_mode == AutoCompleteMode.SuggestAppend;
+
 			if (Text.Length == 0) {
 				if (auto_complete_listbox != null)
 					auto_complete_listbox.HideListBox (false);
 				return;
 			}
 
-			if (auto_complete_listbox == null)
-				auto_complete_listbox = new AutoCompleteListBox (this);
+			if (auto_complete_matches == null)
+				auto_complete_matches = new List<string> ();
 
 			string text = Text;
-			auto_complete_listbox.Items.Clear ();
+			auto_complete_matches.Clear ();
 
 			for (int i = 0; i < source.Count; i++) {
 				string item_text = auto_complete_cb_source == null ? auto_complete_custom_source [i] :
 					auto_complete_cb_source.GetItemText (auto_complete_cb_source.Items [i]);
 				if (item_text.StartsWith (text, StringComparison.CurrentCultureIgnoreCase))
-					auto_complete_listbox.Items.Add (item_text);
+					auto_complete_matches.Add (item_text);
 			}
 
-			IList<string> matches = auto_complete_listbox.Items;
-			if ((matches.Count == 0) ||
-				(matches.Count == 1 && matches [0].Equals (text, StringComparison.CurrentCultureIgnoreCase))) { // Exact single match
+			auto_complete_matches.Sort ();
 
-				if (auto_complete_listbox.Visible)
+			// Return if we have a single exact match
+			if ((auto_complete_matches.Count == 0) || (auto_complete_matches.Count == 1 && 
+						auto_complete_matches [0].Equals (text, StringComparison.CurrentCultureIgnoreCase))) {
+
+				if (auto_complete_listbox != null && auto_complete_listbox.Visible)
 					auto_complete_listbox.HideListBox (false);
 				return;
 			}
 
-			// Show or update auto complete listbox contents
-			auto_complete_listbox.Location = PointToScreen (new Point (0, Height));
-			auto_complete_listbox.ShowListBox ();
+			auto_complete_selected_index = suggest ? -1 : 0;
+
+			if (suggest) {
+				if (auto_complete_listbox == null)
+					auto_complete_listbox = new AutoCompleteListBox (this);
+
+				// Show or update auto complete listbox contents
+				auto_complete_listbox.Location = PointToScreen (new Point (0, Height));
+				auto_complete_listbox.ShowListBox ();
+			}
+
+			if (append && !is_backspace)
+				AppendAutoCompleteMatch (0);
+
+			document.MoveCaret (CaretDirection.End);
 		}
 
 		internal ComboBox AutoCompleteInternalSource {
@@ -197,24 +214,22 @@
 
 		void NavigateAutoCompleteList (Keys key)
 		{
-			int index = auto_complete_listbox.HighlightedIndex;
-			if (index == -1)
-				auto_complete_original_text = Text;
+			int index = auto_complete_selected_index;
 
 			switch (key) {
 				case Keys.Up:
 					index -= 1;
 					if (index < -1)
-						index = auto_complete_listbox.Items.Count - 1;
+						index = auto_complete_matches.Count - 1;
 					break;
 				case Keys.Down:
 					index += 1;
-					if (index >= auto_complete_listbox.Items.Count)
+					if (index >= auto_complete_matches.Count)
 						index = -1;
 					break;
 				case Keys.PageUp:
 					if (index == -1)
-						index = auto_complete_listbox.Items.Count - 1;
+						index = auto_complete_matches.Count - 1;
 					else if (index == 0)
 						index = -1;
 					else {
@@ -226,21 +241,37 @@
 				case Keys.PageDown:
 					if (index == -1)
 						index = 0;
-					else if (index == auto_complete_listbox.Items.Count - 1)
+					else if (index == auto_complete_matches.Count - 1)
 						index = -1;
 					else {
 						index += auto_complete_listbox.page_size - 1;
-						if (index >= auto_complete_listbox.Items.Count)
-							index = auto_complete_listbox.Items.Count - 1;
+						if (index >= auto_complete_matches.Count)
+							index = auto_complete_matches.Count - 1;
 					}
 					break;
 				default:
 					break;
 			}
 
-			auto_complete_listbox.HighlightedIndex = index;
-			Text = index == -1 ? auto_complete_original_text : auto_complete_listbox.Items [index];
+			bool suggest = auto_complete_mode == AutoCompleteMode.Suggest || auto_complete_mode == AutoCompleteMode.SuggestAppend;
+			if (suggest) {
+				Text = index == -1 ? auto_complete_original_text : auto_complete_matches [index];
+				auto_complete_listbox.HighlightedIndex = index;
+			} else
+				// Append mode-only, not suggest at all
+				AppendAutoCompleteMatch (index < 0 ? 0 : index);
+				
+			auto_complete_selected_index = index;
+			document.MoveCaret (CaretDirection.End);
 		}
+
+		void AppendAutoCompleteMatch (int index)
+		{
+			Text = auto_complete_original_text + auto_complete_matches [index].Substring (auto_complete_original_text.Length);
+			SelectionStart = auto_complete_original_text.Length;
+			SelectionLength = auto_complete_matches [index].Length - auto_complete_original_text.Length;
+		}
+
 #endif
 
 		private void UpdateAlignment ()
@@ -571,7 +602,8 @@
 			switch ((Msg)m.Msg) {
 #if NET_2_0
 				case Msg.WM_KEYDOWN:
-					if (auto_complete_listbox == null || !auto_complete_listbox.Visible)
+					if (auto_complete_mode == AutoCompleteMode.None ||
+						auto_complete_source != AutoCompleteSource.CustomSource)
 						break;
 
 					Keys key_data = (Keys)m.WParam.ToInt32 ();
@@ -583,15 +615,34 @@
 							NavigateAutoCompleteList (key_data);
 							m.Result = IntPtr.Zero;
 							return;
+						case Keys.Enter:
+						case Keys.Escape:
+							if (auto_complete_listbox != null && auto_complete_listbox.Visible)
+								auto_complete_listbox.HideListBox (false);
+							break;
 						default:
 							break;
 					}
 					break;
 				case Msg.WM_CHAR:
+					if (auto_complete_mode == AutoCompleteMode.None ||
+						auto_complete_source != AutoCompleteSource.CustomSource)
+						break;
+
+					bool is_backspace = m.WParam.ToInt32 () == 8;
+					if (!Char.IsLetterOrDigit ((char)m.WParam) && !is_backspace)
+						break;
+					
+					if (!is_backspace)
+						Text = auto_complete_original_text;
+
+					document.MoveCaret (CaretDirection.End);
+
 					// Need to call base.WndProc before to have access to
 					// the updated Text property value
 					base.WndProc (ref m);
-					ShowAutoCompleteListBox ();
+					auto_complete_original_text = Text;
+					ShowAutoCompleteListBox (is_backspace);
 					return;
 #endif
 				case Msg.WM_LBUTTONDOWN:
@@ -715,7 +766,6 @@
 		{
 			TextBox owner;
 			VScrollBar vscroll;
-			List<string> items;
 			int top_item;
 			int last_item;
 			internal int page_size;
@@ -730,7 +780,6 @@
 			public AutoCompleteListBox (TextBox tb)
 			{
 				owner = tb;
-				items = new List<string> ();
 				item_height = FontHeight + 2;
 
 				vscroll = new VScrollBar ();
@@ -753,12 +802,6 @@
 				}
 			}
 
-			public IList<string> Items {
-				get {
-					return items;
-				}
-			}
-
 			public int HighlightedIndex {
 				get {
 					return highlighted_index;
@@ -824,13 +867,13 @@
 			{
 				int top_y = Height;
 
-				for (int i = top_item; i < items.Count; i++) {
+				for (int i = top_item; i < owner.auto_complete_matches.Count; i++) {
 					int pos = i - top_item; // relative to visible area
 					if ((pos * item_height) + item_height >= top_y)
 						return i;
 				}
 
-				return items.Count - 1;
+				return owner.auto_complete_matches.Count - 1;
 			}
 
 			Rectangle GetItemBounds (int index)
@@ -856,13 +899,13 @@
 
 			void LayoutListBox ()
 			{
-				int total_height = items.Count * item_height;
+				int total_height = owner.auto_complete_matches.Count * item_height;
 				page_size = Math.Max (Height / item_height, 1);
 				last_item = GetLastVisibleItem ();
 
 				if (Height < total_height) {
 					vscroll.Visible = true;
-					vscroll.Maximum = items.Count - 1;
+					vscroll.Maximum = owner.auto_complete_matches.Count - 1;
 					vscroll.LargeChange = page_size;
 					vscroll.Location = new Point (Width - vscroll.Width, 0);
 					vscroll.Height = Height - item_height;
@@ -876,7 +919,7 @@
 			public void HideListBox (bool set_text)
 			{
 				if (set_text) {
-					owner.Text = items [HighlightedIndex];
+					owner.Text = owner.auto_complete_matches [HighlightedIndex];
 					owner.SelectAll ();
 				}
 
@@ -888,8 +931,8 @@
 			{
 				if (!user_defined_size) {
 					// This should call the Layout routine for us
-					int height = items.Count > DefaultDropDownItems ? DefaultDropDownItems * item_height : 
-						(items.Count + 1) * item_height;
+					int height = owner.auto_complete_matches.Count > DefaultDropDownItems ? 
+						DefaultDropDownItems * item_height : (owner.auto_complete_matches.Count + 1) * item_height;
 					Size = new Size (owner.Width, height);
 				} else
 					LayoutListBox ();
@@ -974,9 +1017,9 @@
 
 					if (i == highlighted_idx) {
 						g.FillRectangle (SystemBrushes.Highlight, item_bounds);
-						g.DrawString (items [i], Font, SystemBrushes.HighlightText, item_bounds);
+						g.DrawString (owner.auto_complete_matches [i], Font, SystemBrushes.HighlightText, item_bounds);
 					} else 
-						g.DrawString (items [i], Font, brush, item_bounds);
+						g.DrawString (owner.auto_complete_matches [i], Font, brush, item_bounds);
 
 					y += item_height;
 				}
_______________________________________________
Mono-winforms-list maillist  -  Mono-winforms-list@lists.ximian.com
http://lists.ximian.com/mailman/listinfo/mono-winforms-list

Reply via email to