public async Task OnPreviewKeyUp(KeyEventArgs e)
        {
            string fullSource = OwnerEditor.FullSource;

            SourceText currentSourceText = SourceText.From(fullSource);

            if (MethodOverloadList.IsVisible)
            {
                Document newDocument = MethodOverloadsOpenDocument.WithText(currentSourceText);

                IEnumerable <TextChange> changes = await newDocument.GetTextChangesAsync(MethodOverloadsOpenDocument);

                foreach (TextChange c in changes)
                {
                    if (c.Span.Contains(MethodOverloadsOpenPosition) || (c.Span.End == MethodOverloadsOpenPosition && c.Span.Length > 0))
                    {
                        MethodOverloadList.IsVisible = false;
                    }
                }
            }

            if (CompletionWindow.IsVisible)
            {
                Document newDocument = CompletionOpenDocument.WithText(currentSourceText);
                foreach (TextChange c in await newDocument.GetTextChangesAsync(CompletionOpenDocument))
                {
                    if (c.Span.Contains(CompletionOpenPosition - 2))
                    {
                        CompletionWindow.IsVisible = false;
                    }
                }
            }

            if (e.Key == Key.LeftCtrl || e.Key == Key.RightCtrl)
            {
                IsCtrlPressed = false;
            }
            else if (e.Key == Key.Back && CompletionWindow.IsVisible)
            {
                _ = UpdateCompletion();
            }

            if (EditorControl.ShowLineChanges)
            {
                DiffResult        diffResultFromLastSaved = OwnerEditor.Differ.CreateLineDiffs(OwnerEditor.PreSource + "\n" + OwnerEditor.LastSavedText + "\n" + OwnerEditor.PostSource, fullSource, false);
                IEnumerable <int> changesFromLastSaved    = (from el in diffResultFromLastSaved.DiffBlocks select Enumerable.Range(el.InsertStartB - OwnerEditor.PreSourceText.Lines.Count, Math.Max(1, el.InsertCountB))).Aggregate(Enumerable.Empty <int>(), (a, b) => a.Concat(b));

                DiffResult        diffResultFromOriginal = OwnerEditor.Differ.CreateLineDiffs(OwnerEditor.PreSource + "\n" + OwnerEditor.OriginalText + "\n" + OwnerEditor.PostSource, fullSource, false);
                IEnumerable <int> changesFromOriginal    = (from el in diffResultFromOriginal.DiffBlocks select Enumerable.Range(el.InsertStartB - OwnerEditor.PreSourceText.Lines.Count, Math.Max(1, el.InsertCountB))).Aggregate(Enumerable.Empty <int>(), (a, b) => a.Concat(b));

                OwnerEditor.SetLineDiff(changesFromLastSaved, changesFromOriginal);
            }
        }
Esempio n. 2
0
        public SettingsContainer(Shortcut[] additionalShortcuts)
        {
            this.InitializeComponent();

            this.AttachedToVisualTree += (s, e) =>
            {
                Editor = this.FindAncestorOfType <Editor>();

                string autosaveDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), Assembly.GetEntryAssembly().GetName().Name, Editor.Guid);

                this.FindControl <TextBox>("SaveDirectoryBox").Text = autosaveDirectory;

                this.FindControl <NumericUpDown>("AutosaveIntervalBox").Value = Editor.AutoSaver.MillisecondsInterval / 1000;

                this.FindControl <NumericUpDown>("CompilationTimeoutBox").Value = Editor.CompilationErrorChecker.MillisecondsInterval;

                this.Editor.LoadSettings();
            };

            this.FindControl <Button>("CopySaveDirectoryButton").Click += async(s, e) =>
            {
                await Application.Current.Clipboard.SetTextAsync(this.FindControl <TextBox>("SaveDirectoryBox").Text);
            };

            this.FindControl <NumericUpDown>("AutosaveIntervalBox").ValueChanged += (s, e) =>
            {
                int newInterval = (int)Math.Round(this.FindControl <NumericUpDown>("AutosaveIntervalBox").Value) * 1000;

                if (newInterval > 0 && Editor.AutoSaver.IsRunning)
                {
                    Editor.AutoSaver.Stop();
                    Editor.AutoSaver.MillisecondsInterval = newInterval;
                    Editor.AutoSaver.Resume();
                }
                else if (newInterval > 0 && !Editor.AutoSaver.IsRunning)
                {
                    Editor.AutoSaver.Stop();
                    Editor.AutoSaver.MillisecondsInterval = newInterval;
                    Editor.AutoSaver.Resume();
                }
                else if (newInterval == 0 && Editor.AutoSaver.IsRunning)
                {
                    Editor.AutoSaver.Stop();
                    Editor.AutoSaver.MillisecondsInterval = newInterval;
                }
            };

            this.FindControl <CheckBox>("KeepSaveHistoryBox").PropertyChanged += (s, e) =>
            {
                if (e.Property == CheckBox.IsCheckedProperty)
                {
                    Editor.KeepSaveHistory = this.FindControl <CheckBox>("KeepSaveHistoryBox").IsChecked == true;
                }
            };

            this.FindControl <Button>("DeleteSaveHistoryButton").Click += (s, e) =>
            {
                string autosaveDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), Assembly.GetEntryAssembly().GetName().Name, Editor.Guid);
                try
                {
                    foreach (string file in Directory.EnumerateFiles(autosaveDirectory, "*.cs"))
                    {
                        try
                        {
                            File.Delete(file);
                        }
                        catch { }
                    }
                }
                catch { }
            };

            this.FindControl <ComboBox>("SyntaxHighlightingModeBox").SelectionChanged += (s, e) =>
            {
                Editor.EditorControl.SyntaxHighlightingMode = (SyntaxHighlightingModes)this.FindControl <ComboBox>("SyntaxHighlightingModeBox").SelectedIndex;
            };

            this.FindControl <CheckBox>("OpenSuggestionsBox").PropertyChanged += (s, e) =>
            {
                if (e.Property == CheckBox.IsCheckedProperty)
                {
                    Editor.AutoOpenSuggestions = this.FindControl <CheckBox>("OpenSuggestionsBox").IsChecked == true;
                }
            };

            this.FindControl <CheckBox>("OpenParametersBox").PropertyChanged += (s, e) =>
            {
                if (e.Property == CheckBox.IsCheckedProperty)
                {
                    Editor.AutoOpenParameters = this.FindControl <CheckBox>("OpenParametersBox").IsChecked == true;
                }
            };

            this.FindControl <CheckBox>("AutoFormatBox").PropertyChanged += (s, e) =>
            {
                if (e.Property == CheckBox.IsCheckedProperty)
                {
                    Editor.AutoFormat = this.FindControl <CheckBox>("AutoFormatBox").IsChecked == true;
                }
            };

            this.FindControl <NumericUpDown>("CompilationTimeoutBox").ValueChanged += (s, e) =>
            {
                int newInterval = (int)Math.Round(this.FindControl <NumericUpDown>("CompilationTimeoutBox").Value);

                if (newInterval > 0 && Editor.CompilationErrorChecker.IsRunning)
                {
                    Editor.CompilationErrorChecker.Stop();
                    Editor.CompilationErrorChecker.MillisecondsInterval = newInterval;
                    Editor.CompilationErrorChecker.Resume();
                }
                else if (newInterval > 0 && !Editor.CompilationErrorChecker.IsRunning)
                {
                    Editor.CompilationErrorChecker.Stop();
                    Editor.CompilationErrorChecker.MillisecondsInterval = newInterval;
                    Editor.CompilationErrorChecker.Resume();
                }
                else if (newInterval == 0 && Editor.CompilationErrorChecker.IsRunning)
                {
                    Editor.CompilationErrorChecker.Stop();
                    Editor.CompilationErrorChecker.MillisecondsInterval = newInterval;
                }
            };

            this.FindControl <CheckBox>("ShowChangedLinesBox").PropertyChanged += (s, e) =>
            {
                if (e.Property == CheckBox.IsCheckedProperty)
                {
                    Editor.EditorControl.ShowLineChanges = this.FindControl <CheckBox>("ShowChangedLinesBox").IsChecked == true;

                    if (Editor.EditorControl.ShowLineChanges)
                    {
                        DiffResult        diffResultFromLastSaved = Editor.Differ.CreateLineDiffs(Editor.PreSource + "\n" + Editor.LastSavedText + "\n" + Editor.PostSource, Editor.FullSource, false);
                        IEnumerable <int> changesFromLastSaved    = (from el in diffResultFromLastSaved.DiffBlocks select Enumerable.Range(el.InsertStartB - Editor.PreSourceText.Lines.Count, Math.Max(1, el.InsertCountB))).Aggregate(Enumerable.Empty <int>(), (a, b) => a.Concat(b));

                        DiffResult        diffResultFromOriginal = Editor.Differ.CreateLineDiffs(Editor.PreSource + "\n" + Editor.OriginalText + "\n" + Editor.PostSource, Editor.FullSource, false);
                        IEnumerable <int> changesFromOriginal    = (from el in diffResultFromOriginal.DiffBlocks select Enumerable.Range(el.InsertStartB - Editor.PreSourceText.Lines.Count, Math.Max(1, el.InsertCountB))).Aggregate(Enumerable.Empty <int>(), (a, b) => a.Concat(b));

                        Editor.SetLineDiff(changesFromLastSaved, changesFromOriginal);
                    }
                }
            };

            this.FindControl <CheckBox>("ShowScrollbarOverviewBox").PropertyChanged += (s, e) =>
            {
                if (e.Property == CheckBox.IsCheckedProperty)
                {
                    Editor.EditorControl.ShowScrollbarOverview = this.FindControl <CheckBox>("ShowScrollbarOverviewBox").IsChecked == true;
                }
            };

            this.FindControl <Button>("SaveSettingsButton").Click += (s, e) =>
            {
                this.Editor.SaveSettings();
            };

            this.FindControl <Button>("LoadSettingsButton").Click += (s, e) =>
            {
                this.Editor.LoadSettings();
            };

            if (additionalShortcuts.Length > 0)
            {
                int additionalShortcutColumns = (int)Math.Ceiling((double)additionalShortcuts.Length / 11);

                ColumnDefinitions definitions = this.FindControl <Grid>("ShortcutGridContainer").ColumnDefinitions;

                for (int i = 0; i < additionalShortcutColumns; i++)
                {
                    this.FindControl <Grid>("ShortcutGridContainer").ColumnDefinitions.Insert(this.FindControl <Grid>("ShortcutGridContainer").ColumnDefinitions.Count - 1, new ColumnDefinition(30, GridUnitType.Pixel));
                    this.FindControl <Grid>("ShortcutGridContainer").ColumnDefinitions.Insert(this.FindControl <Grid>("ShortcutGridContainer").ColumnDefinitions.Count - 1, new ColumnDefinition(0, GridUnitType.Auto));
                }

                int itemsPerColumn = (int)Math.Ceiling((double)additionalShortcuts.Length / additionalShortcutColumns);

                int column = 0;
                int row    = 0;

                Grid currentColumn = new Grid()
                {
                    VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center
                };
                Grid.SetColumn(currentColumn, 5 + 2 * column);
                currentColumn.ColumnDefinitions.Add(new ColumnDefinition(0, GridUnitType.Auto));
                currentColumn.ColumnDefinitions.Add(new ColumnDefinition(10, GridUnitType.Pixel));
                currentColumn.ColumnDefinitions.Add(new ColumnDefinition(1, GridUnitType.Star));
                this.FindControl <Grid>("ShortcutGridContainer").Children.Add(currentColumn);

                for (int i = 0; i < additionalShortcuts.Length; i++)
                {
                    currentColumn.RowDefinitions.Add(new RowDefinition(0, GridUnitType.Auto));

                    TextBlock descriptionBlock = new TextBlock()
                    {
                        VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center, HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Right, Text = additionalShortcuts[i].Name
                    };
                    Grid.SetRow(descriptionBlock, row);
                    currentColumn.Children.Add(descriptionBlock);

                    StackPanel keyPanel = new StackPanel()
                    {
                        Orientation = Avalonia.Layout.Orientation.Horizontal, Margin = new Thickness(5)
                    };
                    Grid.SetColumn(keyPanel, 2);
                    Grid.SetRow(keyPanel, row);

                    for (int j = 0; j < additionalShortcuts[i].Shortcuts.Length; j++)
                    {
                        for (int k = 0; k < additionalShortcuts[i].Shortcuts[j].Length; k++)
                        {
                            keyPanel.Children.Add(new DiagnosticIcons.KeyIcon()
                            {
                                KeyText = additionalShortcuts[i].Shortcuts[j][k], Margin = k > 0 ? new Thickness(5, 0, 0, 0) : new Thickness(0)
                            });
                        }

                        if (j < additionalShortcuts[i].Shortcuts.Length - 1)
                        {
                            keyPanel.Children.Add(new TextBlock()
                            {
                                VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center, Text = "or", Margin = new Thickness(10, 0, 10, 0)
                            });
                        }
                    }

                    currentColumn.Children.Add(keyPanel);

                    row++;

                    if (row == itemsPerColumn)
                    {
                        row = 0;
                        column++;
                        currentColumn = new Grid()
                        {
                            VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center
                        };
                        Grid.SetColumn(currentColumn, 5 + 2 * column);
                        currentColumn.ColumnDefinitions.Add(new ColumnDefinition(0, GridUnitType.Auto));
                        currentColumn.ColumnDefinitions.Add(new ColumnDefinition(10, GridUnitType.Pixel));
                        currentColumn.ColumnDefinitions.Add(new ColumnDefinition(1, GridUnitType.Star));
                        this.FindControl <Grid>("ShortcutGridContainer").Children.Add(currentColumn);
                    }
                }
            }
        }
        public void Refresh()
        {
            this.FindControl <StackPanel>("FileContainer").Children.Clear();
            Editor editor = this.FindAncestorOfType <Editor>();

            string autosaveDirectory = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), Assembly.GetEntryAssembly().GetName().Name);
            string savePath          = System.IO.Path.Combine(autosaveDirectory, editor.Guid);

            string[] files;

            try
            {
                files = System.IO.Directory.GetFiles(savePath, "*.cs");
            }
            catch
            {
                files = new string[0];
            }


            long result = -1;

            List <(long, string)> sortedFiles = (from el in files let filename = System.IO.Path.GetFileNameWithoutExtension(el) where filename.StartsWith("autosave") || long.TryParse(filename, out result) let result2 = result orderby !filename.StartsWith("autosave") ? result2 : ((DateTimeOffset) new System.IO.FileInfo(el).LastWriteTimeUtc).ToUnixTimeSeconds() descending select !filename.StartsWith("autosave") ? (result2, el) : (((DateTimeOffset) new System.IO.FileInfo(el).LastWriteTimeUtc).ToUnixTimeSeconds(), el)).ToList();

            sortedFiles.Add((editor.OriginalTimeStamp, "original"));
            sortedFiles.Sort((a, b) => Math.Sign(b.Item1 - a.Item1));

            int diffWidth = (int)Math.Max(10, Math.Floor(this.Bounds.Width - 32 - 150 - 32 - 32 - 22));

            string currentText = null;
            int    lineCount   = -1;
            Differ differ      = new Differ();

            if (sortedFiles.Any())
            {
                currentText = editor.EditorControl.Text.ToString();
                lineCount   = editor.EditorControl.Text.Lines.Count;
            }

            foreach ((long timestamp, string file)file in sortedFiles)
            {
                Grid itemGrid = new Grid();

                itemGrid.ColumnDefinitions.Add(new ColumnDefinition(32, GridUnitType.Pixel));
                itemGrid.ColumnDefinitions.Add(new ColumnDefinition(1, GridUnitType.Pixel));
                itemGrid.ColumnDefinitions.Add(new ColumnDefinition(150, GridUnitType.Pixel));
                itemGrid.ColumnDefinitions.Add(new ColumnDefinition(1, GridUnitType.Pixel));
                itemGrid.ColumnDefinitions.Add(new ColumnDefinition(1, GridUnitType.Star));
                itemGrid.ColumnDefinitions.Add(new ColumnDefinition(1, GridUnitType.Pixel));
                itemGrid.ColumnDefinitions.Add(new ColumnDefinition(36, GridUnitType.Pixel));
                itemGrid.ColumnDefinitions.Add(new ColumnDefinition(1, GridUnitType.Pixel));
                itemGrid.ColumnDefinitions.Add(new ColumnDefinition(36, GridUnitType.Pixel));
                itemGrid.ColumnDefinitions.Add(new ColumnDefinition(18, GridUnitType.Pixel));

                if (System.IO.Path.GetFileNameWithoutExtension(file.file).StartsWith("autosave"))
                {
                    AutosaveIcon icon = new DiagnosticIcons.AutosaveIcon();
                    ToolTip.SetTip(icon, "Autosave");
                    itemGrid.Children.Add(icon);
                }
                else if (file.file == "original")
                {
                    StartingIcon icon = new DiagnosticIcons.StartingIcon();
                    ToolTip.SetTip(icon, "Original file");
                    itemGrid.Children.Add(icon);
                }
                else
                {
                    SaveIcon icon = new DiagnosticIcons.SaveIcon();
                    ToolTip.SetTip(icon, "Manual save");
                    itemGrid.Children.Add(icon);
                }

                TextBlock timeBlock = new TextBlock()
                {
                    Text = DateTimeOffset.FromUnixTimeSeconds(file.timestamp).DateTime.ToLocalTime().ToString("HH:mm:ss \\(dd MMM\\)", System.Globalization.CultureInfo.InvariantCulture), Margin = new Thickness(5, 2, 5, 2), VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center
                };
                Grid.SetColumn(timeBlock, 2);
                itemGrid.Children.Add(timeBlock);

                DiffResult diffResult;

                if (file.file != "original")
                {
                    diffResult = differ.CreateLineDiffs(currentText, System.IO.File.ReadAllText(file.file), false);
                }
                else
                {
                    diffResult = differ.CreateLineDiffs(currentText, editor.OriginalText, false);
                }


                List <(int pos, int count, Colour colour)> diffLines = new List <(int pos, int count, Colour colour)>(from el in diffResult.DiffBlocks let pos = el.DeleteCountA > 0 ? el.DeleteStartA : el.InsertStartB orderby pos ascending select(pos, el.DeleteCountA > 0 ? el.DeleteCountA : el.InsertCountB, el.DeleteCountA > 0 ? RedColour : GreenColour));

                int currPos = 0;

                List <(double width, Colour colour)> diffBlocks = new List <(double width, Colour colour)>();

                for (int i = 0; i < diffLines.Count; i++)
                {
                    if (diffLines[i].pos > currPos)
                    {
                        diffBlocks.Add((diffLines[i].pos - currPos, GreyColour));
                        currPos = diffLines[i].pos;
                    }

                    diffBlocks.Add((diffLines[i].count, diffLines[i].colour));
                    currPos += diffLines[i].count;
                }

                if (currPos < lineCount)
                {
                    diffBlocks.Add((lineCount - currPos, GreyColour));
                    currPos = lineCount;
                }

                Page     diff = new Page(diffWidth, 20);
                Graphics gpr  = diff.Graphics;

                double currX = 0;

                for (int i = 0; i < diffBlocks.Count; i++)
                {
                    double w = diffBlocks[i].width * diffWidth / currPos;
                    gpr.FillRectangle(currX, 0, w, 20, diffBlocks[i].colour);
                    currX += w;
                }

                Viewbox diffBox = new Viewbox()
                {
                    Child = diff.PaintToCanvas(false), VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center, Height = 20, Stretch = Stretch.Fill
                };
                Grid.SetColumn(diffBox, 4);
                itemGrid.Children.Add(diffBox);

                if (file.file != "original")
                {
                    Button restoreButton = new Button()
                    {
                        Content = new DiagnosticIcons.RestoreIcon(), Margin = new Thickness(3)
                    };
                    Grid.SetColumn(restoreButton, 6);
                    ToolTip.SetTip(restoreButton, "Restore");
                    itemGrid.Children.Add(restoreButton);

                    Button deleteButton = new Button()
                    {
                        Content = new DiagnosticIcons.DeleteIcon(), Margin = new Thickness(3)
                    };
                    Grid.SetColumn(deleteButton, 8);
                    ToolTip.SetTip(deleteButton, "Delete");
                    itemGrid.Children.Add(deleteButton);

                    restoreButton.Click += async(s, e) =>
                    {
                        try
                        {
                            string newText = System.IO.File.ReadAllText(file.file);
                            await editor.EditorControl.SetText(newText);

                            if (editor.EditorControl.ShowLineChanges)
                            {
                                DiffResult        diffResultFromLastSaved = editor.Differ.CreateLineDiffs(editor.PreSource + "\n" + editor.LastSavedText + "\n" + editor.PostSource, editor.PreSource + "\n" + newText + "\n" + editor.PostSource, false);
                                IEnumerable <int> changesFromLastSaved    = (from el in diffResultFromLastSaved.DiffBlocks select Enumerable.Range(el.InsertStartB - editor.PreSourceText.Lines.Count, Math.Max(1, el.InsertCountB))).Aggregate(Enumerable.Empty <int>(), (a, b) => a.Concat(b));

                                DiffResult        diffResultFromOriginal = editor.Differ.CreateLineDiffs(editor.PreSource + "\n" + editor.OriginalText + "\n" + editor.PostSource, editor.PreSource + "\n" + newText + "\n" + editor.PostSource, false);
                                IEnumerable <int> changesFromOriginal    = (from el in diffResultFromOriginal.DiffBlocks select Enumerable.Range(el.InsertStartB - editor.PreSourceText.Lines.Count, Math.Max(1, el.InsertCountB))).Aggregate(Enumerable.Empty <int>(), (a, b) => a.Concat(b));

                                editor.SetLineDiff(changesFromLastSaved, changesFromOriginal);
                            }
                        }
                        catch { }

                        Refresh();
                    };

                    deleteButton.Click += (s, e) =>
                    {
                        try
                        {
                            System.IO.File.Delete(file.file);
                        }
                        catch { }

                        Refresh();
                    };
                }
                else
                {
                    Button restoreButton = new Button()
                    {
                        Content = new DiagnosticIcons.RestoreIcon(), Margin = new Thickness(3)
                    };
                    Grid.SetColumn(restoreButton, 6);
                    ToolTip.SetTip(restoreButton, "Restore");
                    itemGrid.Children.Add(restoreButton);

                    restoreButton.Click += async(s, e) =>
                    {
                        string newText = editor.OriginalText;
                        await editor.EditorControl.SetText(newText);

                        if (editor.EditorControl.ShowLineChanges)
                        {
                            DiffResult        diffResultFromLastSaved = editor.Differ.CreateLineDiffs(editor.PreSource + "\n" + editor.LastSavedText + "\n" + editor.PostSource, editor.PreSource + "\n" + newText + "\n" + editor.PostSource, false);
                            IEnumerable <int> changesFromLastSaved    = (from el in diffResultFromLastSaved.DiffBlocks select Enumerable.Range(el.InsertStartB - editor.PreSourceText.Lines.Count, Math.Max(1, el.InsertCountB))).Aggregate(Enumerable.Empty <int>(), (a, b) => a.Concat(b));

                            DiffResult        diffResultFromOriginal = editor.Differ.CreateLineDiffs(editor.PreSource + "\n" + editor.OriginalText + "\n" + editor.PostSource, editor.PreSource + "\n" + newText + "\n" + editor.PostSource, false);
                            IEnumerable <int> changesFromOriginal    = (from el in diffResultFromOriginal.DiffBlocks select Enumerable.Range(el.InsertStartB - editor.PreSourceText.Lines.Count, Math.Max(1, el.InsertCountB))).Aggregate(Enumerable.Empty <int>(), (a, b) => a.Concat(b));

                            editor.SetLineDiff(changesFromLastSaved, changesFromOriginal);
                        }

                        Refresh();
                    };
                }

                this.FindControl <StackPanel>("FileContainer").Children.Add(itemGrid);
            }
        }