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 - [email protected]
http://lists.ximian.com/mailman/listinfo/mono-winforms-list