aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/Tango.Console/ConsoleTextBox.cs
blob: f6fa40b13153babb232c2db473c67c0e2963e943 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
pre { line-height: 125%; }
td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */
.highlight .vc { color: #336699 } /* Name.Variable.Class */
.highlight .vg { color: #dd7700 } /* Name.Variable.Global */
.highlight .vi { color: #3333bb } /* Name.Variable.Instance */
.highlight .vm { color: #336699 } /* Name.Variable.Magic */
.highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
<%@ ServiceHost Language="C#" Debug="true" Service="Tango.MachineStudio.UpdateService.MachineStudioUpdateService" CodeBehind="MachineStudioUpdateService.svc.cs" %>
' href='#n206'>206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace Tango.Console
{
    public class ConsoleTextBox : TextBox
    {
        private Border _caret;
        private ListBox _listSuggestions;
        private Popup _popup;
        private Popup _suggestionsPopup;

        static ConsoleTextBox()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(ConsoleTextBox), new FrameworkPropertyMetadata(typeof(ConsoleTextBox)));
        }

        public Brush CaretBottomBrush
        {
            get { return (Brush)GetValue(CaretBottomBrushProperty); }
            set { SetValue(CaretBottomBrushProperty, value); }
        }
        public static readonly DependencyProperty CaretBottomBrushProperty =
            DependencyProperty.Register("CaretBottomBrush", typeof(Brush), typeof(ConsoleTextBox), new PropertyMetadata(null));

        public double CaretPosition
        {
            get { return (double)GetValue(CaretPositionProperty); }
            set { SetValue(CaretPositionProperty, value); }
        }
        public static readonly DependencyProperty CaretPositionProperty =
            DependencyProperty.Register("CaretPosition", typeof(double), typeof(ConsoleTextBox), new PropertyMetadata(0.0));

        public bool IsSuggestionsOpened
        {
            get { return (bool)GetValue(IsSuggestionsOpenedProperty); }
            set { SetValue(IsSuggestionsOpenedProperty, value); }
        }
        public static readonly DependencyProperty IsSuggestionsOpenedProperty =
            DependencyProperty.Register("IsSuggestionsOpened", typeof(bool), typeof(ConsoleTextBox), new PropertyMetadata(false));

        public List<ConsoleSuggestion> FilteredSuggestions
        {
            get { return (List<ConsoleSuggestion>)GetValue(FilteredSuggestionsProperty); }
            set { SetValue(FilteredSuggestionsProperty, value); }
        }
        public static readonly DependencyProperty FilteredSuggestionsProperty =
            DependencyProperty.Register("FilteredSuggestions", typeof(List<ConsoleSuggestion>), typeof(ConsoleTextBox), new PropertyMetadata(null));

        public IEnumerable<ConsoleSuggestion> Suggestions
        {
            get { return (IEnumerable<ConsoleSuggestion>)GetValue(SuggestionsProperty); }
            set { SetValue(SuggestionsProperty, value); }
        }
        public static readonly DependencyProperty SuggestionsProperty =
            DependencyProperty.Register("Suggestions", typeof(IEnumerable<ConsoleSuggestion>), typeof(ConsoleTextBox), new PropertyMetadata(null));

        public ConsoleSuggestion SelectedSuggestion
        {
            get { return (ConsoleSuggestion)GetValue(SelectedSuggestionProperty); }
            set { SetValue(SelectedSuggestionProperty, value); }
        }
        public static readonly DependencyProperty SelectedSuggestionProperty =
            DependencyProperty.Register("SelectedSuggestion", typeof(ConsoleSuggestion), typeof(ConsoleTextBox), new PropertyMetadata(null));

        public int MaxSuggestions
        {
            get { return (int)GetValue(MaxSuggestionsProperty); }
            set { SetValue(MaxSuggestionsProperty, value); }
        }
        public static readonly DependencyProperty MaxSuggestionsProperty =
            DependencyProperty.Register("MaxSuggestions", typeof(int), typeof(ConsoleTextBox), new PropertyMetadata(1000));

        public Brush SuggestionsBorderBrush
        {
            get { return (Brush)GetValue(SuggestionsBorderBrushProperty); }
            set { SetValue(SuggestionsBorderBrushProperty, value); }
        }
        public static readonly DependencyProperty SuggestionsBorderBrushProperty =
            DependencyProperty.Register("SuggestionsBorderBrush", typeof(Brush), typeof(ConsoleTextBox), new PropertyMetadata(null));

        public Brush SuggestionsBackground
        {
            get { return (Brush)GetValue(SuggestionsBackgroundProperty); }
            set { SetValue(SuggestionsBackgroundProperty, value); }
        }
        public static readonly DependencyProperty SuggestionsBackgroundProperty =
            DependencyProperty.Register("SuggestionsBackground", typeof(Brush), typeof(ConsoleTextBox), new PropertyMetadata(null));

        public Brush SuggestionsForeground
        {
            get { return (Brush)GetValue(SuggestionsForegroundProperty); }
            set { SetValue(SuggestionsForegroundProperty, value); }
        }
        public static readonly DependencyProperty SuggestionsForegroundProperty =
            DependencyProperty.Register("SuggestionsForeground", typeof(Brush), typeof(ConsoleTextBox), new PropertyMetadata(null));


        public ConsoleTextBox()
        {
            SelectionChanged += (sender, e) => MoveCustomCaret();
            LostFocus += (sender, e) => _caret.Visibility = Visibility.Collapsed;
            GotKeyboardFocus += (sender, e) => _caret.Visibility = Visibility.Visible;
            LostKeyboardFocus += (sender, e) => _caret.Visibility = Visibility.Collapsed;

            Suggestions = ConsoleDictionary.GetKnownCommands().Select(x => new ConsoleSuggestion()
            {
                Name = x.Name,
                Description = x.Description
            }).ToObservableCollection();
        }

        protected override void OnPreviewKeyDown(KeyEventArgs e)
        {
            if (IsSuggestionsOpened)
            {
                if (e.Key == Key.Down)
                {
                    if (_listSuggestions.SelectedIndex < _listSuggestions.Items.Count - 1)
                    {
                        _listSuggestions.SelectedIndex++;
                        _listSuggestions.ScrollIntoView(SelectedSuggestion);

                        _popup.IsOpen = false;

                        if (SelectedSuggestion != null && SelectedSuggestion.Description != null)
                        {
                            _popup.IsOpen = FilteredSuggestions.Count > 0;
                        }
                    }

                    e.Handled = true;
                    return;
                }
                else if (e.Key == Key.Up)
                {
                    if (_listSuggestions.SelectedIndex > 0)
                    {
                        _listSuggestions.SelectedIndex--;
                        _listSuggestions.ScrollIntoView(SelectedSuggestion);

                        _popup.IsOpen = false;
                        if (SelectedSuggestion != null && SelectedSuggestion.Description != null)
                        {
                            _popup.IsOpen = FilteredSuggestions.Count > 0;
                        }
                    }

                    e.Handled = true;
                    return;
                }
                else if (e.Key == Key.Enter)
                {
                    var selectedItem = (_listSuggestions.SelectedItem as ConsoleSuggestion);
                    if (selectedItem != null)
                    {
                        var words = Text.Split(' ').ToList();

                        if (words.Count > 1)
                        {
                            words = words.Take(words.Count - 1).ToList();
                            Text = String.Join(" ", words) + " " + selectedItem.Name;
                        }
                        else
                        {
                            Text = selectedItem.Name;
                        }

                        IsSuggestionsOpened = false;
                        CaretIndex = Text.Length;
                        e.Handled = true;
                        return;
                    }

                    IsSuggestionsOpened = false;
                }
            }

            base.OnPreviewKeyDown(e);
        }

        protected override void OnTextChanged(TextChangedEventArgs e)
        {
            base.OnTextChanged(e);

            try
            {
                if (CaretIndex == Text.Length)
                {
                    String lastWord = Text.Split(' ').LastOrDefault();
                    lastWord?.Trim();

                    if (Suggestions != null)
                    {
                        FilteredSuggestions = Suggestions.Where(x => (lastWord.IsNotNullOrEmpty() && x.Name.ToLower().StartsWith(lastWord.ToLower())) || Text.EndsWith(" ")).OrderBy(x => x.Name).Take(MaxSuggestions).ToList();

                        if (Text.Contains(" "))
                        {
                            FilteredSuggestions = FilteredSuggestions.Where(x => x.Type != ConsoleSuggestionType.Command).ToList();
                        }

                        IsSuggestionsOpened = FilteredSuggestions.Count > 0;
                        _popup.IsOpen = false;
                        _popup.IsOpen = FilteredSuggestions.Count > 0 && SelectedSuggestion != null;
                    }
                }
                else
                {
                    IsSuggestionsOpened = false;
                    _popup.IsOpen = false;
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex);
                Debugger.Break();
            }
        }

        protected override void OnSelectionChanged(RoutedEventArgs e)
        {
            base.OnSelectionChanged(e);

            if (CaretIndex < Text.Length)
            {
                IsSuggestionsOpened = false;
                _popup.IsOpen = false;
            }
        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            _caret = GetTemplateChild("PART_Caret") as Border;
            _listSuggestions = GetTemplateChild("PART_listSuggestions") as ListBox;
            _popup = GetTemplateChild("PART_popup") as Popup;
            _suggestionsPopup = GetTemplateChild("PART_SuggestionsPopup") as Popup;
        }

        private void MoveCustomCaret()
        {
            var caretLocation = GetRectFromCharacterIndex(CaretIndex).Location;

            if (!double.IsInfinity(caretLocation.X))
            {
                Canvas.SetLeft(_caret, caretLocation.X);
                CaretPosition = caretLocation.X;

                _suggestionsPopup.PlacementRectangle = new Rect(CaretPosition + 10, 20, 0, 0);
            }
        }
    }
}