diff --git a/Shared/Shared.projitems b/Shared/Shared.projitems
index a4787dd..176eaee 100644
--- a/Shared/Shared.projitems
+++ b/Shared/Shared.projitems
@@ -16,6 +16,7 @@
+
diff --git a/Shared/Util/BindableSelectionTextBox.cs b/Shared/Util/BindableSelectionTextBox.cs
new file mode 100644
index 0000000..a4f317c
--- /dev/null
+++ b/Shared/Util/BindableSelectionTextBox.cs
@@ -0,0 +1,68 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using static ParseTreeVisualizer.Util.Functions;
+
+namespace ParseTreeVisualizer {
+ public class BindableSelectionTextBox : TextBox {
+ public static readonly DependencyProperty BindableSelectionStartProperty =
+ DPRegister(0, OnBindableSelectionStartChanged);
+
+ public static readonly DependencyProperty BindableSelectionLengthProperty =
+ DPRegister(0, OnBindableSelectionStartChanged);
+
+ private bool changeFromUI;
+
+ public BindableSelectionTextBox() : base() {
+ SelectionChanged += OnSelectionChanged;
+ }
+
+ public int BindableSelectionStart {
+ get => (int)GetValue(BindableSelectionStartProperty);
+ set => SetValue(BindableSelectionStartProperty, value);
+ }
+
+ public int BindableSelectionLength {
+ get => (int)GetValue(BindableSelectionLengthProperty);
+ set => SetValue(BindableSelectionLengthProperty, value);
+ }
+
+ private static void OnBindableSelectionStartChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs args) {
+ var textBox = dependencyObject as BindableSelectionTextBox;
+
+ if (!textBox.changeFromUI) {
+ int newValue = (int)args.NewValue;
+ textBox.SelectionStart = newValue;
+ } else {
+ textBox.changeFromUI = false;
+ }
+ }
+
+ private static void OnBindableSelectionLengthChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs args) {
+ var textBox = dependencyObject as BindableSelectionTextBox;
+
+ if (!textBox.changeFromUI) {
+ int newValue = (int)args.NewValue;
+ textBox.SelectionLength = newValue;
+ } else {
+ textBox.changeFromUI = false;
+ }
+ }
+
+ private void OnSelectionChanged(object sender, RoutedEventArgs e) {
+ if (BindableSelectionStart != SelectionStart) {
+ changeFromUI = true;
+ BindableSelectionStart = SelectionStart;
+ }
+
+ if (BindableSelectionLength != SelectionLength) {
+ changeFromUI = true;
+ BindableSelectionLength = SelectionLength;
+ }
+ }
+ }
+}
diff --git a/Shared/Util/DebugTraceListener.cs b/Shared/Util/DebugTraceListener.cs
index 0e2384a..bbc4a89 100644
--- a/Shared/Util/DebugTraceListener.cs
+++ b/Shared/Util/DebugTraceListener.cs
@@ -5,7 +5,8 @@
namespace ParseTreeVisualizer.Util {
public class DebugTraceListener : TraceListener {
private readonly static List ignoreMessages = new List {
- "Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Controls.DataGrid', AncestorLevel='1''. BindingExpression:Path=AreRowDetailsFrozen; DataItem=null; target element is 'DataGridDetailsPresenter' (Name=''); target property is 'SelectiveScrollingOrientation' (type 'SelectiveScrollingOrientation')"
+ "Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Controls.DataGrid', AncestorLevel='1''. BindingExpression:Path=AreRowDetailsFrozen; DataItem=null; target element is 'DataGridDetailsPresenter' (Name=''); target property is 'SelectiveScrollingOrientation' (type 'SelectiveScrollingOrientation')",
+ "Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Controls.DataGrid', AncestorLevel='1''. BindingExpression:Path=HeadersVisibility; DataItem=null; target element is 'DataGridRowHeader' (Name=''); target property is 'Visibility' (type 'Visibility')"
};
public override void Write(string message) { }
public override void WriteLine(string message) {
diff --git a/Shared/ViewModels/VisualizerDataViewModel.cs b/Shared/ViewModels/VisualizerDataViewModel.cs
index 82a6593..d793b08 100644
--- a/Shared/ViewModels/VisualizerDataViewModel.cs
+++ b/Shared/ViewModels/VisualizerDataViewModel.cs
@@ -21,7 +21,10 @@ public int SourceSelectionLength {
set => NotifyChanged(ref sourceSelectionLength, value);
}
- private int sourceSelectionEnd => sourceSelectionStart + sourceSelectionLength - 1;
+ private int sourceSelectionEnd =>
+ sourceSelectionLength == 0 ?
+ sourceSelectionStart :
+ sourceSelectionStart + sourceSelectionLength - 1;
public ParseTreeNodeViewModel Root { get; }
public ReadOnlyCollection Tokens { get; }
diff --git a/Shared/VisualizerControl.xaml.cs b/Shared/VisualizerControl.xaml.cs
index edd8973..08f0e8f 100644
--- a/Shared/VisualizerControl.xaml.cs
+++ b/Shared/VisualizerControl.xaml.cs
@@ -26,7 +26,6 @@ public VisualizerControl() {
tvi.BringIntoView();
}));
-
Loaded += (s, e) => {
// https://stackoverflow.com/a/21436273/111794
configPopup.CustomPopupPlacementCallback += (popupSize, targetSize, offset) =>