diff --git a/MarkDownEditor/View/MainWindow.xaml b/MarkDownEditor/View/MainWindow.xaml index b920785..a0f2d88 100644 --- a/MarkDownEditor/View/MainWindow.xaml +++ b/MarkDownEditor/View/MainWindow.xaml @@ -90,25 +90,25 @@ + SyntaxHighlighting="MarkDown" + Document="{Binding SourceCode}" + SelectionStart="{Binding SelectionStart,Mode=TwoWay}" + SelectionLength="{Binding SelectionLength,Mode=TwoWay}" + CaretOffset="{Binding CaretOffset,Mode=TwoWay}" + ScrollOffsetRatio="{Binding ScrollOffsetRatio,Mode=OneWayToSource}" + CanUndo="{Binding CanUndo,Mode=OneWayToSource}" + CanRedo="{Binding CanRedo,Mode=OneWayToSource}" + ShowLineNumbers="{Binding SettingsViewModel.ShowLineNumbers}" + WordWrap="{Binding SettingsViewModel.WordWrap}" + ShowTabs="{Binding SettingsViewModel.ShowTabs}" + ShowSpaces="{Binding SettingsViewModel.ShowSpaces}" + ShowEndOfLine="{Binding SettingsViewModel.ShowEndOfLine}" + ShowColumnRuler="{Binding SettingsViewModel.ShowColumnRuler}" + RulerPosition="{Binding SettingsViewModel.RulerPosition}" + HighlightCurrentLine="{Binding SettingsViewModel.HighlightCurrentLine}" + LineNumbersForeground="{DynamicResource AccentColorBrush}" + FontFamily="{Binding SettingsViewModel.EditorFont}" + FontSize="{Binding SettingsViewModel.EditorFontSize}"> @@ -154,7 +154,7 @@ diff --git a/MarkDownEditor/View/MvvmTextEditor.cs b/MarkDownEditor/View/MvvmTextEditor.cs index 60fcfe9..fa711dd 100644 --- a/MarkDownEditor/View/MvvmTextEditor.cs +++ b/MarkDownEditor/View/MvvmTextEditor.cs @@ -116,8 +116,10 @@ public double ScrollOffsetRatio DependencyProperty.Register("SelectionLength", typeof(int), typeof(MvvmTextEditor), new PropertyMetadata((obj, args) => { - MvvmTextEditor target = (MvvmTextEditor)obj; - target.SelectionLength = (int)args.NewValue; + TextEditor editor = (TextEditor)obj; + if (editor.SelectionLength == (int)args.NewValue) + return; + editor.SelectionLength = (int)args.NewValue; })); /// @@ -126,7 +128,12 @@ public double ScrollOffsetRatio public new int SelectionLength { get { return base.SelectionLength; } - set { SetValue(SelectionLengthProperty, value); } + set + { + if ((int)GetValue(SelectionLengthProperty) == value) + return; + SetValue(SelectionLengthProperty, value); + } } /// @@ -136,8 +143,10 @@ public double ScrollOffsetRatio DependencyProperty.Register("SelectionStart", typeof(int), typeof(MvvmTextEditor), new PropertyMetadata((obj, args) => { - MvvmTextEditor target = (MvvmTextEditor)obj; - target.SelectionStart = (int)args.NewValue; + TextEditor editor = (TextEditor)obj; + if (editor.SelectionStart == (int)args.NewValue) + return; + ((TextEditor)obj).SelectionStart = (int)args.NewValue; })); /// @@ -146,7 +155,12 @@ public double ScrollOffsetRatio public new int SelectionStart { get { return base.SelectionStart; } - set { SetValue(SelectionStartProperty, value); } + set + { + if ((int)GetValue(SelectionStartProperty) == value) + return; + SetValue(SelectionStartProperty,value); + } } #endregion // Selection. diff --git a/MarkDownEditor/ViewModel/FindReplaceViewModel.cs b/MarkDownEditor/ViewModel/FindReplaceViewModel.cs index a2bd093..d81c31b 100644 --- a/MarkDownEditor/ViewModel/FindReplaceViewModel.cs +++ b/MarkDownEditor/ViewModel/FindReplaceViewModel.cs @@ -121,6 +121,7 @@ public bool IsMatchCase return; isMatchCase = value; RaisePropertyChanged("IsMatchCase"); + UpdateCommandsState(); } } @@ -134,6 +135,7 @@ public bool IsMatchWholeWord return; isMatchWholeWord = value; RaisePropertyChanged("IsMatchWholeWord"); + UpdateCommandsState(); } } @@ -147,6 +149,7 @@ public bool UseRegExp return; useRegExp = value; RaisePropertyChanged("UseRegExp"); + UpdateCommandsState(); } } @@ -160,6 +163,7 @@ public bool UseWildcards return; useWildcards = value; RaisePropertyChanged("UseWildcards"); + UpdateCommandsState(); } } @@ -190,7 +194,31 @@ public string ReplaceText UpdateCommandsState(); } } + + public MatchCollection MatchedCollection + { + get; set; + } + public int currentMatch = 0; + public int CurrentMatch + { + get { return currentMatch; } + set + { + currentMatch = value; + if (MatchedCollection == null || MatchedCollection.Count == 0) + return; + + IsFindPreviousEnabled = CurrentMatch > 0; + IsFindNextEnabled = CurrentMatch < MatchedCollection.Count - 1; + + var match = MatchedCollection[currentMatch]; + ViewModelLocator.Main.SelectionStart = match.Index; + ViewModelLocator.Main.SelectionLength = match.Length; + } + } + #region Commands public ICommand SwitchFindReplaceCommand => new RelayCommand(() => ShowFindReplaceControl = !ShowFindReplaceControl); public ICommand ShowFindReplaceCommand => new RelayCommand(() => ShowFindReplaceControl = true); @@ -199,12 +227,12 @@ public string ReplaceText public ICommand FindPreviousCommand => new RelayCommand(() => { - + CurrentMatch--; }); public ICommand FindNextCommand => new RelayCommand(() => { - + CurrentMatch++; }); public ICommand ReplaceNextCommand => new RelayCommand(() => @@ -223,30 +251,60 @@ public string ReplaceText private void UpdateCommandsState() { if (string.IsNullOrEmpty(SearchText)) + { + MatchedCollection = null; ClearFindState(); + } else { - var mainVM = ViewModelLocator.Main; - RegexOptions options = RegexOptions.None; - if (!IsMatchCase) - options |= RegexOptions.IgnoreCase; - Regex regex = new Regex(SearchText, options); - var collections = regex.Matches(mainVM.SourceCode.Text); - if (collections.Count == 0)//nothing matched + Regex regex = GetRegEx(SearchText); + MatchedCollection = regex.Matches(ViewModelLocator.Main.SourceCode.Text); + + if (MatchedCollection.Count == 0)//nothing matched { ClearFindState(); + ViewModelLocator.Main.SelectionLength = 0; return; } - + else + { + CurrentMatch = 0; + IsFindPreviousEnabled = false; + IsFindNextEnabled = MatchedCollection.Count > 1; + IsReplaceNextEnabled = !string.IsNullOrEmpty(ReplaceText); + IsReplaceAllEnabled = !string.IsNullOrEmpty(ReplaceText); + } } } - + + private Regex GetRegEx(string textToFind) + { + RegexOptions options = RegexOptions.None; + if (!IsMatchCase) + options |= RegexOptions.IgnoreCase; + + if (UseRegExp) + { + return new Regex(textToFind, options); + } + else + { + string pattern = Regex.Escape(textToFind); + if (UseWildcards) + pattern = pattern.Replace("\\*", ".*").Replace("\\?", "."); + if (IsMatchWholeWord) + pattern = "\\b" + pattern + "\\b"; + return new Regex(pattern, options); + } + } + private void ClearFindState() { IsFindPreviousEnabled = false; IsFindNextEnabled = false; IsReplaceNextEnabled = false; - IsReplaceAllEnabled = false; + IsReplaceAllEnabled = false; + CurrentMatch = 0; } #endregion //Functions }