aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/SideChains/Tango.AutoComplete/Editors/AutoCompleteTextBox.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Software/Visual_Studio/SideChains/Tango.AutoComplete/Editors/AutoCompleteTextBox.cs')
-rw-r--r--Software/Visual_Studio/SideChains/Tango.AutoComplete/Editors/AutoCompleteTextBox.cs545
1 files changed, 545 insertions, 0 deletions
diff --git a/Software/Visual_Studio/SideChains/Tango.AutoComplete/Editors/AutoCompleteTextBox.cs b/Software/Visual_Studio/SideChains/Tango.AutoComplete/Editors/AutoCompleteTextBox.cs
new file mode 100644
index 000000000..f350c0b9b
--- /dev/null
+++ b/Software/Visual_Studio/SideChains/Tango.AutoComplete/Editors/AutoCompleteTextBox.cs
@@ -0,0 +1,545 @@
+namespace Tango.AutoComplete.Editors
+{
+
+ using System;
+ using System.Collections;
+ using System.Threading;
+ using System.Windows;
+ using System.Windows.Controls;
+ using System.Windows.Controls.Primitives;
+ using System.Windows.Data;
+ using System.Windows.Input;
+ using System.Windows.Media;
+ using System.Windows.Threading;
+
+ [TemplatePart(Name = AutoCompleteTextBox.PartEditor, Type = typeof(TextBox))]
+ [TemplatePart(Name = AutoCompleteTextBox.PartPopup, Type = typeof(Popup))]
+ [TemplatePart(Name = AutoCompleteTextBox.PartSelector, Type = typeof(Selector))]
+ public class AutoCompleteTextBox : Control
+ {
+
+ #region "Fields"
+
+ public const string PartEditor = "PART_Editor";
+ public const string PartPopup = "PART_Popup";
+
+ public const string PartSelector = "PART_Selector";
+ public static readonly DependencyProperty DelayProperty = DependencyProperty.Register("Delay", typeof(int), typeof(AutoCompleteTextBox), new FrameworkPropertyMetadata(200));
+ public static readonly DependencyProperty DisplayMemberProperty = DependencyProperty.Register("DisplayMember", typeof(string), typeof(AutoCompleteTextBox), new FrameworkPropertyMetadata(string.Empty));
+ public static readonly DependencyProperty IconPlacementProperty = DependencyProperty.Register("IconPlacement", typeof(IconPlacement), typeof(AutoCompleteTextBox), new FrameworkPropertyMetadata(IconPlacement.Left));
+ public static readonly DependencyProperty IconProperty = DependencyProperty.Register("Icon", typeof(object), typeof(AutoCompleteTextBox), new FrameworkPropertyMetadata(null));
+ public static readonly DependencyProperty IconVisibilityProperty = DependencyProperty.Register("IconVisibility", typeof(Visibility), typeof(AutoCompleteTextBox), new FrameworkPropertyMetadata(Visibility.Visible));
+ public static readonly DependencyProperty IsDropDownOpenProperty = DependencyProperty.Register("IsDropDownOpen", typeof(bool), typeof(AutoCompleteTextBox), new FrameworkPropertyMetadata(false));
+ public static readonly DependencyProperty IsLoadingProperty = DependencyProperty.Register("IsLoading", typeof(bool), typeof(AutoCompleteTextBox), new FrameworkPropertyMetadata(false));
+ public static readonly DependencyProperty IsReadOnlyProperty = DependencyProperty.Register("IsReadOnly", typeof(bool), typeof(AutoCompleteTextBox), new FrameworkPropertyMetadata(false));
+ public static readonly DependencyProperty ItemTemplateProperty = DependencyProperty.Register("ItemTemplate", typeof(DataTemplate), typeof(AutoCompleteTextBox), new FrameworkPropertyMetadata(null));
+ public static readonly DependencyProperty ItemTemplateSelectorProperty = DependencyProperty.Register("ItemTemplateSelector", typeof(DataTemplateSelector), typeof(AutoCompleteTextBox));
+ public static readonly DependencyProperty LoadingContentProperty = DependencyProperty.Register("LoadingContent", typeof(object), typeof(AutoCompleteTextBox), new FrameworkPropertyMetadata(null));
+ public static readonly DependencyProperty ProviderProperty = DependencyProperty.Register("Provider", typeof(ISuggestionProvider), typeof(AutoCompleteTextBox), new FrameworkPropertyMetadata(null));
+ public static readonly DependencyProperty SelectedItemProperty = DependencyProperty.Register("SelectedItem", typeof(object), typeof(AutoCompleteTextBox), new FrameworkPropertyMetadata(null, OnSelectedItemChanged));
+ public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(AutoCompleteTextBox), new FrameworkPropertyMetadata(string.Empty));
+ public static readonly DependencyProperty MaxLengthProperty = DependencyProperty.Register("MaxLength", typeof(int), typeof(AutoCompleteTextBox), new FrameworkPropertyMetadata(0));
+ public static readonly DependencyProperty CharacterCasingProperty = DependencyProperty.Register("CharacterCasing", typeof(CharacterCasing), typeof(AutoCompleteTextBox), new FrameworkPropertyMetadata(CharacterCasing.Normal));
+ public static readonly DependencyProperty MaxPopUpHeightProperty = DependencyProperty.Register("MaxPopUpHeight", typeof(int), typeof(AutoCompleteTextBox), new FrameworkPropertyMetadata(600));
+
+ public static readonly DependencyProperty WatermarkProperty = DependencyProperty.Register("Watermark", typeof(string), typeof(AutoCompleteTextBox), new FrameworkPropertyMetadata(string.Empty));
+
+ public static readonly DependencyProperty SuggestionBackgroundProperty = DependencyProperty.Register("SuggestionBackground", typeof(Brush), typeof(AutoCompleteTextBox), new FrameworkPropertyMetadata(Brushes.White));
+ private BindingEvaluator _bindingEvaluator;
+
+ private TextBox _editor;
+
+ private DispatcherTimer _fetchTimer;
+
+ private string _filter;
+
+ private bool _isUpdatingText;
+
+ private Selector _itemsSelector;
+
+ private Popup _popup;
+
+ private SelectionAdapter _selectionAdapter;
+
+ private bool _selectionCancelled;
+
+ private SuggestionsAdapter _suggestionsAdapter;
+
+
+ #endregion
+
+ #region "Constructors"
+
+ static AutoCompleteTextBox()
+ {
+ DefaultStyleKeyProperty.OverrideMetadata(typeof(AutoCompleteTextBox), new FrameworkPropertyMetadata(typeof(AutoCompleteTextBox)));
+ }
+
+ #endregion
+
+ #region "Properties"
+
+
+ public int MaxPopupHeight
+ {
+ get { return (int) GetValue(MaxPopUpHeightProperty); }
+ set { SetValue(MaxPopUpHeightProperty, value);}
+ }
+
+
+ public BindingEvaluator BindingEvaluator
+ {
+ get { return _bindingEvaluator; }
+ set { _bindingEvaluator = value; }
+ }
+
+ public CharacterCasing CharacterCasing
+ {
+ get { return (System.Windows.Controls.CharacterCasing) GetValue(CharacterCasingProperty); }
+ set { SetValue(CharacterCasingProperty, value);}
+ }
+
+ public int MaxLength
+ {
+ get { return (int) GetValue(DelayProperty); }
+ set { SetValue(MaxLengthProperty, value); }
+ }
+
+ public int Delay
+ {
+ get { return (int)GetValue(DelayProperty); }
+
+ set { SetValue(DelayProperty, value); }
+ }
+
+ public string DisplayMember
+ {
+ get { return (string)GetValue(DisplayMemberProperty); }
+
+ set { SetValue(DisplayMemberProperty, value); }
+ }
+
+ public TextBox Editor
+ {
+ get { return _editor; }
+ set { _editor = value; }
+ }
+
+ public DispatcherTimer FetchTimer
+ {
+ get { return _fetchTimer; }
+ set { _fetchTimer = value; }
+ }
+
+ public string Filter
+ {
+ get { return _filter; }
+ set { _filter = value; }
+ }
+
+ public object Icon
+ {
+ get { return GetValue(IconProperty); }
+
+ set { SetValue(IconProperty, value); }
+ }
+
+ public IconPlacement IconPlacement
+ {
+ get { return (IconPlacement)GetValue(IconPlacementProperty); }
+
+ set { SetValue(IconPlacementProperty, value); }
+ }
+
+ public Visibility IconVisibility
+ {
+ get { return (Visibility)GetValue(IconVisibilityProperty); }
+
+ set { SetValue(IconVisibilityProperty, value); }
+ }
+
+ public bool IsDropDownOpen
+ {
+ get { return (bool)GetValue(IsDropDownOpenProperty); }
+
+ set { SetValue(IsDropDownOpenProperty, value); }
+ }
+
+ public bool IsLoading
+ {
+ get { return (bool)GetValue(IsLoadingProperty); }
+
+ set { SetValue(IsLoadingProperty, value); }
+ }
+
+ public bool IsReadOnly
+ {
+ get { return (bool)GetValue(IsReadOnlyProperty); }
+
+ set { SetValue(IsReadOnlyProperty, value); }
+ }
+
+ public Selector ItemsSelector
+ {
+ get { return _itemsSelector; }
+ set { _itemsSelector = value; }
+ }
+
+ public DataTemplate ItemTemplate
+ {
+ get { return (DataTemplate)GetValue(ItemTemplateProperty); }
+
+ set { SetValue(ItemTemplateProperty, value); }
+ }
+
+ public DataTemplateSelector ItemTemplateSelector
+ {
+ get { return ((DataTemplateSelector)(GetValue(AutoCompleteTextBox.ItemTemplateSelectorProperty))); }
+ set { SetValue(AutoCompleteTextBox.ItemTemplateSelectorProperty, value); }
+ }
+
+ public object LoadingContent
+ {
+ get { return GetValue(LoadingContentProperty); }
+
+ set { SetValue(LoadingContentProperty, value); }
+ }
+
+ public Popup Popup
+ {
+ get { return _popup; }
+ set { _popup = value; }
+ }
+
+ public ISuggestionProvider Provider
+ {
+ get { return (ISuggestionProvider)GetValue(ProviderProperty); }
+
+ set { SetValue(ProviderProperty, value); }
+ }
+
+ public object SelectedItem
+ {
+ get { return GetValue(SelectedItemProperty); }
+
+ set { SetValue(SelectedItemProperty, value); }
+ }
+
+ public SelectionAdapter SelectionAdapter
+ {
+ get { return _selectionAdapter; }
+ set { _selectionAdapter = value; }
+ }
+
+ public string Text
+ {
+ get { return (string)GetValue(TextProperty); }
+
+ set { SetValue(TextProperty, value); }
+ }
+
+ public string Watermark
+ {
+ get { return (string)GetValue(WatermarkProperty); }
+
+ set { SetValue(WatermarkProperty, value); }
+ }
+ public Brush SuggestionBackground {
+ get { return (Brush)GetValue(SuggestionBackgroundProperty); }
+
+ set { SetValue(SuggestionBackgroundProperty, value); }
+ }
+
+ #endregion
+
+ #region "Methods"
+
+ public static void OnSelectedItemChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ AutoCompleteTextBox act = null;
+ act = d as AutoCompleteTextBox;
+ if (act != null)
+ {
+ if (act.Editor != null & !act._isUpdatingText)
+ {
+ act._isUpdatingText = true;
+ act.Editor.Text = act.BindingEvaluator.Evaluate(e.NewValue);
+ act._isUpdatingText = false;
+ }
+ }
+ }
+
+ private void ScrollToSelectedItem()
+ {
+ ListBox listBox = ItemsSelector as ListBox;
+ if (listBox != null && listBox.SelectedItem != null)
+ listBox.ScrollIntoView(listBox.SelectedItem);
+ }
+
+
+ public override void OnApplyTemplate()
+ {
+ base.OnApplyTemplate();
+
+ Editor = Template.FindName(PartEditor, this) as TextBox;
+ Popup = Template.FindName(PartPopup, this) as Popup;
+ ItemsSelector = Template.FindName(PartSelector, this) as Selector;
+ BindingEvaluator = new BindingEvaluator(new Binding(DisplayMember));
+
+ if (Editor != null)
+ {
+ Editor.TextChanged += OnEditorTextChanged;
+ Editor.PreviewKeyDown += OnEditorKeyDown;
+ Editor.LostFocus += OnEditorLostFocus;
+
+ if (SelectedItem != null)
+ {
+ Editor.Text = BindingEvaluator.Evaluate(SelectedItem);
+ }
+
+ }
+
+ this.GotFocus += AutoCompleteTextBox_GotFocus;
+
+ if (Popup != null)
+ {
+ Popup.StaysOpen = false;
+ Popup.Opened += OnPopupOpened;
+ Popup.Closed += OnPopupClosed;
+ }
+ if (ItemsSelector != null)
+ {
+ SelectionAdapter = new SelectionAdapter(ItemsSelector);
+ SelectionAdapter.Commit += OnSelectionAdapterCommit;
+ SelectionAdapter.Cancel += OnSelectionAdapterCancel;
+ SelectionAdapter.SelectionChanged += OnSelectionAdapterSelectionChanged;
+ ItemsSelector.PreviewMouseDown += ItemsSelector_PreviewMouseDown;
+ }
+ }
+ private void ItemsSelector_PreviewMouseDown(object sender, MouseButtonEventArgs e)
+ {
+ var pos_item = (e.OriginalSource as FrameworkElement)?.DataContext;
+ if (pos_item == null)
+ return;
+ if (!ItemsSelector.Items.Contains(pos_item))
+ return;
+ ItemsSelector.SelectedItem = pos_item;
+ OnSelectionAdapterCommit();
+ }
+ private void AutoCompleteTextBox_GotFocus(object sender, RoutedEventArgs e)
+ {
+ Editor?.Focus();
+ }
+
+ private string GetDisplayText(object dataItem)
+ {
+ if (BindingEvaluator == null)
+ {
+ BindingEvaluator = new BindingEvaluator(new Binding(DisplayMember));
+ }
+ if (dataItem == null)
+ {
+ return string.Empty;
+ }
+ if (string.IsNullOrEmpty(DisplayMember))
+ {
+ return dataItem.ToString();
+ }
+ return BindingEvaluator.Evaluate(dataItem);
+ }
+
+ private void OnEditorKeyDown(object sender, KeyEventArgs e)
+ {
+ if (SelectionAdapter != null)
+ {
+ if (IsDropDownOpen)
+ SelectionAdapter.HandleKeyDown(e);
+ else
+ IsDropDownOpen = e.Key == Key.Down || e.Key == Key.Up;
+ }
+ }
+
+ private void OnEditorLostFocus(object sender, RoutedEventArgs e)
+ {
+ if (!IsKeyboardFocusWithin)
+ {
+ IsDropDownOpen = false;
+ }
+ }
+
+ private void OnEditorTextChanged(object sender, TextChangedEventArgs e)
+ {
+ if (_isUpdatingText)
+ return;
+ if (FetchTimer == null)
+ {
+ FetchTimer = new DispatcherTimer();
+ FetchTimer.Interval = TimeSpan.FromMilliseconds(Delay);
+ FetchTimer.Tick += OnFetchTimerTick;
+ }
+ FetchTimer.IsEnabled = false;
+ FetchTimer.Stop();
+ SetSelectedItem(null);
+ if (Editor.Text.Length > 0)
+ {
+ IsLoading = true;
+ IsDropDownOpen = true;
+ ItemsSelector.ItemsSource = null;
+ FetchTimer.IsEnabled = true;
+ FetchTimer.Start();
+ }
+ else
+ {
+ IsDropDownOpen = false;
+ }
+ }
+
+ private void OnFetchTimerTick(object sender, EventArgs e)
+ {
+ FetchTimer.IsEnabled = false;
+ FetchTimer.Stop();
+ if (Provider != null && ItemsSelector != null)
+ {
+ Filter = Editor.Text;
+ if (_suggestionsAdapter == null)
+ {
+ _suggestionsAdapter = new SuggestionsAdapter(this);
+ }
+ _suggestionsAdapter.GetSuggestions(Filter);
+ }
+ }
+
+ private void OnPopupClosed(object sender, EventArgs e)
+ {
+ if (!_selectionCancelled)
+ {
+ OnSelectionAdapterCommit();
+ }
+ }
+
+ private void OnPopupOpened(object sender, EventArgs e)
+ {
+ _selectionCancelled = false;
+ ItemsSelector.SelectedItem = SelectedItem;
+ }
+
+ private void OnSelectionAdapterCancel()
+ {
+ _isUpdatingText = true;
+ Editor.Text = SelectedItem == null ? Filter : GetDisplayText(SelectedItem);
+ Editor.SelectionStart = Editor.Text.Length;
+ Editor.SelectionLength = 0;
+ _isUpdatingText = false;
+ IsDropDownOpen = false;
+ _selectionCancelled = true;
+ }
+
+ private void OnSelectionAdapterCommit()
+ {
+ if (ItemsSelector.SelectedItem != null)
+ {
+ SelectedItem = ItemsSelector.SelectedItem;
+ _isUpdatingText = true;
+ Editor.Text = GetDisplayText(ItemsSelector.SelectedItem);
+ SetSelectedItem(ItemsSelector.SelectedItem);
+ _isUpdatingText = false;
+ IsDropDownOpen = false;
+ }
+ }
+
+ private void OnSelectionAdapterSelectionChanged()
+ {
+ _isUpdatingText = true;
+ if (ItemsSelector.SelectedItem == null)
+ {
+ Editor.Text = Filter;
+ }
+ else
+ {
+ Editor.Text = GetDisplayText(ItemsSelector.SelectedItem);
+ }
+ Editor.SelectionStart = Editor.Text.Length;
+ Editor.SelectionLength = 0;
+ ScrollToSelectedItem();
+ _isUpdatingText = false;
+ }
+
+ private void SetSelectedItem(object item)
+ {
+ _isUpdatingText = true;
+ SelectedItem = item;
+ _isUpdatingText = false;
+ }
+ #endregion
+
+ #region "Nested Types"
+
+ private class SuggestionsAdapter
+ {
+
+ #region "Fields"
+
+ private AutoCompleteTextBox _actb;
+
+ private string _filter;
+ #endregion
+
+ #region "Constructors"
+
+ public SuggestionsAdapter(AutoCompleteTextBox actb)
+ {
+ _actb = actb;
+ }
+
+ #endregion
+
+ #region "Methods"
+
+ public void GetSuggestions(string searchText)
+ {
+ _filter = searchText;
+ _actb.IsLoading = true;
+ ParameterizedThreadStart thInfo = new ParameterizedThreadStart(GetSuggestionsAsync);
+ Thread th = new Thread(thInfo);
+ th.Start(new object[] {
+ searchText,
+ _actb.Provider
+ });
+ }
+
+ private void DisplaySuggestions(IEnumerable suggestions, string filter)
+ {
+ if (_filter != filter)
+ {
+ return;
+ }
+ if (_actb.IsDropDownOpen)
+ {
+ _actb.IsLoading = false;
+ _actb.ItemsSelector.ItemsSource = suggestions;
+ _actb.IsDropDownOpen = _actb.ItemsSelector.HasItems;
+ }
+
+ }
+
+ private void GetSuggestionsAsync(object param)
+ {
+ object[] args = param as object[];
+ string searchText = Convert.ToString(args[0]);
+ ISuggestionProvider provider = args[1] as ISuggestionProvider;
+ IEnumerable list = provider.GetSuggestions(searchText);
+ _actb.Dispatcher.BeginInvoke(new Action<IEnumerable, string>(DisplaySuggestions), DispatcherPriority.Background, new object[] {
+ list,
+ searchText
+ });
+ }
+
+ #endregion
+
+ }
+
+ #endregion
+
+ }
+
+}