mirror of
https://github.com/sourcegit-scm/sourcegit.git
synced 2024-12-24 20:57:19 -08:00
refactor: rewrite CommitMessageTextBox
This commit is contained in:
parent
91ba181e02
commit
40cf5608d3
5 changed files with 157 additions and 127 deletions
|
@ -105,8 +105,8 @@
|
||||||
<x:String x:Key="Text.CommitDetail.Info.Parents" xml:space="preserve">PARENTS</x:String>
|
<x:String x:Key="Text.CommitDetail.Info.Parents" xml:space="preserve">PARENTS</x:String>
|
||||||
<x:String x:Key="Text.CommitDetail.Info.Refs" xml:space="preserve">REFS</x:String>
|
<x:String x:Key="Text.CommitDetail.Info.Refs" xml:space="preserve">REFS</x:String>
|
||||||
<x:String x:Key="Text.CommitDetail.Info.SHA" xml:space="preserve">SHA</x:String>
|
<x:String x:Key="Text.CommitDetail.Info.SHA" xml:space="preserve">SHA</x:String>
|
||||||
<x:String x:Key="Text.CommitMessageTextBox.Placeholder" xml:space="preserve">Enter commit subject & message</x:String>
|
<x:String x:Key="Text.CommitMessageTextBox.SubjectPlaceholder" xml:space="preserve">Enter commit subject</x:String>
|
||||||
<x:String x:Key="Text.CommitMessageTextBox.Tip" xml:space="preserve">Git uses an empty line to separate the subject and extra message body.</x:String>
|
<x:String x:Key="Text.CommitMessageTextBox.MessagePlaceholder" xml:space="preserve">Description</x:String>
|
||||||
<x:String x:Key="Text.Configure" xml:space="preserve">Repository Configure</x:String>
|
<x:String x:Key="Text.Configure" xml:space="preserve">Repository Configure</x:String>
|
||||||
<x:String x:Key="Text.Configure.Email" xml:space="preserve">Email Address</x:String>
|
<x:String x:Key="Text.Configure.Email" xml:space="preserve">Email Address</x:String>
|
||||||
<x:String x:Key="Text.Configure.Email.Placeholder" xml:space="preserve">Email address</x:String>
|
<x:String x:Key="Text.Configure.Email.Placeholder" xml:space="preserve">Email address</x:String>
|
||||||
|
|
|
@ -108,8 +108,8 @@
|
||||||
<x:String x:Key="Text.CommitDetail.Info.Parents" xml:space="preserve">父提交</x:String>
|
<x:String x:Key="Text.CommitDetail.Info.Parents" xml:space="preserve">父提交</x:String>
|
||||||
<x:String x:Key="Text.CommitDetail.Info.Refs" xml:space="preserve">相关引用</x:String>
|
<x:String x:Key="Text.CommitDetail.Info.Refs" xml:space="preserve">相关引用</x:String>
|
||||||
<x:String x:Key="Text.CommitDetail.Info.SHA" xml:space="preserve">提交指纹</x:String>
|
<x:String x:Key="Text.CommitDetail.Info.SHA" xml:space="preserve">提交指纹</x:String>
|
||||||
<x:String x:Key="Text.CommitMessageTextBox.Placeholder" xml:space="preserve">填写提交信息</x:String>
|
<x:String x:Key="Text.CommitMessageTextBox.SubjectPlaceholder" xml:space="preserve">填写提交信息主题</x:String>
|
||||||
<x:String x:Key="Text.CommitMessageTextBox.Tip" xml:space="preserve">Git使用空白行来划分提交信息中的主题与内容</x:String>
|
<x:String x:Key="Text.CommitMessageTextBox.MessagePlaceholder" xml:space="preserve">详细描述</x:String>
|
||||||
<x:String x:Key="Text.Configure" xml:space="preserve">仓库配置</x:String>
|
<x:String x:Key="Text.Configure" xml:space="preserve">仓库配置</x:String>
|
||||||
<x:String x:Key="Text.Configure.Email" xml:space="preserve">电子邮箱</x:String>
|
<x:String x:Key="Text.Configure.Email" xml:space="preserve">电子邮箱</x:String>
|
||||||
<x:String x:Key="Text.Configure.Email.Placeholder" xml:space="preserve">邮箱地址</x:String>
|
<x:String x:Key="Text.Configure.Email.Placeholder" xml:space="preserve">邮箱地址</x:String>
|
||||||
|
|
|
@ -108,8 +108,8 @@
|
||||||
<x:String x:Key="Text.CommitDetail.Info.Parents" xml:space="preserve">父提交</x:String>
|
<x:String x:Key="Text.CommitDetail.Info.Parents" xml:space="preserve">父提交</x:String>
|
||||||
<x:String x:Key="Text.CommitDetail.Info.Refs" xml:space="preserve">相關引用</x:String>
|
<x:String x:Key="Text.CommitDetail.Info.Refs" xml:space="preserve">相關引用</x:String>
|
||||||
<x:String x:Key="Text.CommitDetail.Info.SHA" xml:space="preserve">提交指紋</x:String>
|
<x:String x:Key="Text.CommitDetail.Info.SHA" xml:space="preserve">提交指紋</x:String>
|
||||||
<x:String x:Key="Text.CommitMessageTextBox.Placeholder" xml:space="preserve">填寫提交資訊</x:String>
|
<x:String x:Key="Text.CommitMessageTextBox.SubjectPlaceholder" xml:space="preserve">填寫提交信息主題</x:String>
|
||||||
<x:String x:Key="Text.CommitMessageTextBox.Tip" xml:space="preserve">Git使用空白行來劃分提交資訊中的主題與內容</x:String>
|
<x:String x:Key="Text.CommitMessageTextBox.MessagePlaceholder" xml:space="preserve">詳細描述</x:String>
|
||||||
<x:String x:Key="Text.Configure" xml:space="preserve">倉庫配置</x:String>
|
<x:String x:Key="Text.Configure" xml:space="preserve">倉庫配置</x:String>
|
||||||
<x:String x:Key="Text.Configure.Email" xml:space="preserve">電子郵箱</x:String>
|
<x:String x:Key="Text.Configure.Email" xml:space="preserve">電子郵箱</x:String>
|
||||||
<x:String x:Key="Text.Configure.Email.Placeholder" xml:space="preserve">郵箱地址</x:String>
|
<x:String x:Key="Text.Configure.Email.Placeholder" xml:space="preserve">郵箱地址</x:String>
|
||||||
|
|
|
@ -2,9 +2,9 @@
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:ae="using:AvaloniaEdit"
|
|
||||||
xmlns:c="using:SourceGit.Converters"
|
xmlns:c="using:SourceGit.Converters"
|
||||||
xmlns:vm="using:SourceGit.ViewModels"
|
xmlns:vm="using:SourceGit.ViewModels"
|
||||||
|
xmlns:v="using:SourceGit.Views"
|
||||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="SourceGit.Views.CommitMessageTextBox"
|
x:Class="SourceGit.Views.CommitMessageTextBox"
|
||||||
x:Name="ThisControl">
|
x:Name="ThisControl">
|
||||||
|
@ -12,52 +12,67 @@
|
||||||
BorderThickness="1"
|
BorderThickness="1"
|
||||||
BorderBrush="{DynamicResource Brush.Border2}"
|
BorderBrush="{DynamicResource Brush.Border2}"
|
||||||
CornerRadius="4">
|
CornerRadius="4">
|
||||||
<Grid RowDefinitions="*,Auto">
|
<Grid RowDefinitions="Auto,1,*">
|
||||||
<Grid Grid.Row="0">
|
<Grid Grid.Row="0" ColumnDefinitions="*,1,Auto">
|
||||||
<Rectangle x:Name="SubjectGuideLine"
|
<v:EnhancedTextBox Grid.Column="0"
|
||||||
Height="0.8"
|
x:Name="SubjectEditor"
|
||||||
HorizontalAlignment="Stretch"
|
Classes="no_border"
|
||||||
VerticalAlignment="Top"
|
Margin="0"
|
||||||
|
Padding="4"
|
||||||
|
CornerRadius="4,4,0,0"
|
||||||
|
BorderThickness="0"
|
||||||
|
Background="Transparent"
|
||||||
|
AcceptsReturn="False"
|
||||||
|
TextWrapping="Wrap"
|
||||||
|
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
|
||||||
|
ScrollViewer.VerticalScrollBarVisibility="Disabled"
|
||||||
|
Text="{Binding #ThisControl.Subject, Mode=TwoWay}"
|
||||||
|
Watermark="{DynamicResource Text.CommitMessageTextBox.SubjectPlaceholder}"
|
||||||
|
PreviewKeyDown="OnSubjectTextBoxPreviewKeyDown"/>
|
||||||
|
|
||||||
|
<Rectangle Grid.Column="1"
|
||||||
|
Width="1"
|
||||||
|
HorizontalAlignment="Center"
|
||||||
|
VerticalAlignment="Stretch"
|
||||||
IsHitTestVisible="False"
|
IsHitTestVisible="False"
|
||||||
Fill="{DynamicResource Brush.Border2}"/>
|
Fill="{DynamicResource Brush.Border2}"/>
|
||||||
|
|
||||||
<ae:TextEditor x:Name="TextEditor"
|
<StackPanel Grid.Column="2"
|
||||||
Foreground="{DynamicResource Brush.FG1}"
|
Margin="8,0"
|
||||||
Background="Transparent"
|
VerticalAlignment="Center"
|
||||||
Padding="4"
|
Orientation="Horizontal">
|
||||||
BorderThickness="0"
|
<TextBlock Classes="monospace" Margin="2,0,0,0" FontSize="11" Text="{Binding #ThisControl.Subject.Length}" IsVisible="{Binding #ThisControl.Subject.Length, Converter={x:Static c:IntConverters.IsSubjectLengthGood}}"/>
|
||||||
WordWrap="True"
|
<TextBlock Classes="monospace" Margin="2,0,0,0" FontSize="11" Foreground="DarkGoldenrod" Text="{Binding #ThisControl.Subject.Length}" IsVisible="{Binding #ThisControl.Subject.Length, Converter={x:Static c:IntConverters.IsSubjectLengthBad}}"/>
|
||||||
Document="{Binding #ThisControl.Document}"
|
|
||||||
TextChanged="OnTextEditorTextChanged"
|
|
||||||
LayoutUpdated="OnTextEditorLayoutUpdated"/>
|
|
||||||
|
|
||||||
<TextBlock Text="{DynamicResource Text.CommitMessageTextBox.Placeholder}"
|
|
||||||
Foreground="{DynamicResource Brush.FG2}"
|
|
||||||
HorizontalAlignment="Left"
|
|
||||||
VerticalAlignment="Top"
|
|
||||||
Margin="3"
|
|
||||||
IsVisible="{Binding #ThisControl.Text, Converter={x:Static StringConverters.IsNullOrEmpty}}"
|
|
||||||
IsHitTestVisible="False"/>
|
|
||||||
</Grid>
|
|
||||||
|
|
||||||
<Border Grid.Row="1" CornerRadius="0,0,4,4" BorderThickness="0,1,0,0" BorderBrush="{DynamicResource Brush.Border2}" Background="{DynamicResource Brush.Window}" ClipToBounds="True">
|
|
||||||
<Grid ColumnDefinitions="Auto,*,Auto">
|
|
||||||
<Border Grid.Column="0" Background="Transparent" Width="16" Height="16" ToolTip.Tip="{DynamicResource Text.CommitMessageTextBox.Tip}">
|
|
||||||
<Path Height="12" Width="12" Margin="4,0,0,0" Data="{DynamicResource Icons.Info}"/>
|
|
||||||
</Border>
|
|
||||||
|
|
||||||
<StackPanel Grid.Column="2" Orientation="Horizontal" Margin="4,2">
|
|
||||||
<TextBlock Text="Subject:" FontSize="10" Foreground="{DynamicResource Brush.FG2}"/>
|
|
||||||
<TextBlock Classes="monospace" Margin="2,0,0,0" FontSize="11" Text="{Binding #ThisControl.SubjectLength}" IsVisible="{Binding #ThisControl.SubjectLength, Converter={x:Static c:IntConverters.IsSubjectLengthGood}}"/>
|
|
||||||
<TextBlock Classes="monospace" Margin="2,0,0,0" FontSize="11" Foreground="DarkGoldenrod" Text="{Binding #ThisControl.SubjectLength}" IsVisible="{Binding #ThisControl.SubjectLength, Converter={x:Static c:IntConverters.IsSubjectLengthBad}}"/>
|
|
||||||
<TextBlock Classes="monospace" FontSize="11" Text="/"/>
|
<TextBlock Classes="monospace" FontSize="11" Text="/"/>
|
||||||
<TextBlock Classes="monospace" FontSize="11" Text="{Binding Source={x:Static vm:Preference.Instance}, Path=SubjectGuideLength}"/>
|
<TextBlock Classes="monospace" FontSize="11" Text="{Binding Source={x:Static vm:Preference.Instance}, Path=SubjectGuideLength}"/>
|
||||||
<Path Width="10" Height="10" Margin="4,0,0,0" Data="{StaticResource Icons.Error}" Fill="DarkGoldenrod" IsVisible="{Binding #ThisControl.SubjectLength, Converter={x:Static c:IntConverters.IsSubjectLengthBad}}"/>
|
<Path Width="10" Height="10" Margin="4,0,0,0" Data="{StaticResource Icons.Error}" Fill="DarkGoldenrod" IsVisible="{Binding #ThisControl.Subject.Length, Converter={x:Static c:IntConverters.IsSubjectLengthBad}}"/>
|
||||||
<TextBlock Margin="8,0,0,0" Text="Total:" FontSize="11" Foreground="{DynamicResource Brush.FG2}"/>
|
|
||||||
<TextBlock Classes="monospace" Margin="2,0,0,0" FontSize="11" Text="{Binding #ThisControl.TotalLength}"/>
|
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Border>
|
|
||||||
|
<Rectangle Grid.Row="1"
|
||||||
|
Height="1"
|
||||||
|
HorizontalAlignment="Stretch"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
IsHitTestVisible="False"
|
||||||
|
Fill="{DynamicResource Brush.Border2}"/>
|
||||||
|
|
||||||
|
<v:EnhancedTextBox Grid.Row="2"
|
||||||
|
x:Name="DescriptionEditor"
|
||||||
|
Classes="no_border"
|
||||||
|
Margin="0"
|
||||||
|
Padding="4"
|
||||||
|
CornerRadius="0,0,4,4"
|
||||||
|
BorderThickness="0"
|
||||||
|
Background="Transparent"
|
||||||
|
VerticalContentAlignment="Top"
|
||||||
|
AcceptsReturn="True"
|
||||||
|
AcceptsTab="True"
|
||||||
|
TextWrapping="Wrap"
|
||||||
|
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
|
||||||
|
ScrollViewer.VerticalScrollBarVisibility="Auto"
|
||||||
|
Text="{Binding #ThisControl.Description, Mode=TwoWay}"
|
||||||
|
Watermark="{DynamicResource Text.CommitMessageTextBox.MessagePlaceholder}"
|
||||||
|
PreviewKeyDown="OnDescriptionTextBoxPreviewKeyDown"/>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Border>
|
</Border>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
|
|
|
@ -2,22 +2,63 @@ using System;
|
||||||
|
|
||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
|
using Avalonia.Input;
|
||||||
using AvaloniaEdit.Document;
|
using Avalonia.Interactivity;
|
||||||
using AvaloniaEdit.Rendering;
|
|
||||||
|
|
||||||
namespace SourceGit.Views
|
namespace SourceGit.Views
|
||||||
{
|
{
|
||||||
|
public class EnhancedTextBox : TextBox
|
||||||
|
{
|
||||||
|
public static readonly RoutedEvent<KeyEventArgs> PreviewKeyDownEvent =
|
||||||
|
RoutedEvent.Register<ChangeCollectionView, KeyEventArgs>(nameof(KeyEventArgs), RoutingStrategies.Tunnel | RoutingStrategies.Bubble);
|
||||||
|
|
||||||
|
public event EventHandler<KeyEventArgs> PreviewKeyDown
|
||||||
|
{
|
||||||
|
add { AddHandler(PreviewKeyDownEvent, value); }
|
||||||
|
remove { RemoveHandler(PreviewKeyDownEvent, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Type StyleKeyOverride => typeof(TextBox);
|
||||||
|
|
||||||
|
protected override void OnKeyDown(KeyEventArgs e)
|
||||||
|
{
|
||||||
|
var dump = new KeyEventArgs()
|
||||||
|
{
|
||||||
|
RoutedEvent = PreviewKeyDownEvent,
|
||||||
|
Route = RoutingStrategies.Direct,
|
||||||
|
Source = e.Source,
|
||||||
|
Key = e.Key,
|
||||||
|
KeyModifiers = e.KeyModifiers,
|
||||||
|
PhysicalKey = e.PhysicalKey,
|
||||||
|
KeySymbol = e.KeySymbol,
|
||||||
|
};
|
||||||
|
|
||||||
|
RaiseEvent(dump);
|
||||||
|
|
||||||
|
if (dump.Handled)
|
||||||
|
e.Handled = true;
|
||||||
|
else
|
||||||
|
base.OnKeyDown(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public partial class CommitMessageTextBox : UserControl
|
public partial class CommitMessageTextBox : UserControl
|
||||||
{
|
{
|
||||||
|
public enum TextChangeWay
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
FromSource,
|
||||||
|
FromEditor,
|
||||||
|
}
|
||||||
|
|
||||||
public static readonly StyledProperty<string> TextProperty =
|
public static readonly StyledProperty<string> TextProperty =
|
||||||
AvaloniaProperty.Register<CommitMessageTextBox, string>(nameof(Text), string.Empty);
|
AvaloniaProperty.Register<CommitMessageTextBox, string>(nameof(Text), string.Empty);
|
||||||
|
|
||||||
public static readonly DirectProperty<CommitMessageTextBox, int> SubjectLengthProperty =
|
public static readonly StyledProperty<string> SubjectProperty =
|
||||||
AvaloniaProperty.RegisterDirect<CommitMessageTextBox, int>(nameof(SubjectLength), o => o.SubjectLength);
|
AvaloniaProperty.Register<CommitMessageTextBox, string>(nameof(Subject), string.Empty);
|
||||||
|
|
||||||
public static readonly DirectProperty<CommitMessageTextBox, int> TotalLengthProperty =
|
public static readonly StyledProperty<string> DescriptionProperty =
|
||||||
AvaloniaProperty.RegisterDirect<CommitMessageTextBox, int>(nameof(TotalLength), o => o.TotalLength);
|
AvaloniaProperty.Register<CommitMessageTextBox, string>(nameof(Description), string.Empty);
|
||||||
|
|
||||||
public string Text
|
public string Text
|
||||||
{
|
{
|
||||||
|
@ -25,26 +66,20 @@ namespace SourceGit.Views
|
||||||
set => SetValue(TextProperty, value);
|
set => SetValue(TextProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int SubjectLength
|
public string Subject
|
||||||
{
|
{
|
||||||
get => _subjectLength;
|
get => GetValue(SubjectProperty);
|
||||||
private set => SetAndRaise(SubjectLengthProperty, ref _subjectLength, value);
|
set => SetValue(SubjectProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int TotalLength
|
public string Description
|
||||||
{
|
{
|
||||||
get => _totalLength;
|
get => GetValue(DescriptionProperty);
|
||||||
private set => SetAndRaise(TotalLengthProperty, ref _totalLength, value);
|
set => SetValue(DescriptionProperty, value);
|
||||||
}
|
|
||||||
|
|
||||||
public TextDocument Document
|
|
||||||
{
|
|
||||||
get;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public CommitMessageTextBox()
|
public CommitMessageTextBox()
|
||||||
{
|
{
|
||||||
Document = new TextDocument(Text);
|
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,72 +87,52 @@ namespace SourceGit.Views
|
||||||
{
|
{
|
||||||
base.OnPropertyChanged(change);
|
base.OnPropertyChanged(change);
|
||||||
|
|
||||||
if (change.Property == TextProperty && !_isDocumentTextChanging)
|
if (change.Property == TextProperty && _changingWay == TextChangeWay.None)
|
||||||
Document.Text = Text;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnTextEditorLayoutUpdated(object sender, EventArgs e)
|
|
||||||
{
|
{
|
||||||
var view = TextEditor.TextArea?.TextView;
|
_changingWay = TextChangeWay.FromSource;
|
||||||
if (view is { VisualLinesValid: true })
|
var normalized = Text.ReplaceLineEndings("\n").Trim();
|
||||||
|
var subjectEnd = normalized.IndexOf("\n\n", StringComparison.Ordinal);
|
||||||
|
if (subjectEnd == -1)
|
||||||
{
|
{
|
||||||
if (_subjectEndLineNumber == 0)
|
SetCurrentValue(SubjectProperty, normalized.ReplaceLineEndings(" "));
|
||||||
{
|
SetCurrentValue(DescriptionProperty, string.Empty);
|
||||||
SubjectGuideLine.Margin = new Thickness(0, view.DefaultLineHeight + 3, 0, 0);
|
|
||||||
SubjectGuideLine.IsVisible = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var line in view.VisualLines)
|
|
||||||
{
|
|
||||||
var lineNumber = line.FirstDocumentLine.LineNumber;
|
|
||||||
if (lineNumber == _subjectEndLineNumber)
|
|
||||||
{
|
|
||||||
var y = line.GetTextLineVisualYPosition(line.TextLines[^1], VisualYPosition.LineBottom) - view.VerticalOffset + 3;
|
|
||||||
SubjectGuideLine.Margin = new Thickness(0, y, 0, 0);
|
|
||||||
SubjectGuideLine.IsVisible = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SubjectGuideLine.IsVisible = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnTextEditorTextChanged(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
var text = Document.Text;
|
|
||||||
_isDocumentTextChanging = true;
|
|
||||||
SetCurrentValue(TextProperty, text);
|
|
||||||
TotalLength = text.Trim().Length;
|
|
||||||
_isDocumentTextChanging = false;
|
|
||||||
|
|
||||||
var foundData = false;
|
|
||||||
for (var i = 0; i < Document.LineCount; i++)
|
|
||||||
{
|
|
||||||
var line = Document.Lines[i];
|
|
||||||
if (line.Length == 0)
|
|
||||||
{
|
|
||||||
if (foundData)
|
|
||||||
{
|
|
||||||
SubjectLength = text[..line.Offset].ReplaceLineEndings(" ").Trim().Length;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
foundData = true;
|
SetCurrentValue(SubjectProperty, normalized.Substring(0, subjectEnd).ReplaceLineEndings(" "));
|
||||||
|
SetCurrentValue(DescriptionProperty, normalized.Substring(subjectEnd + 2));
|
||||||
|
}
|
||||||
|
_changingWay = TextChangeWay.None;
|
||||||
|
}
|
||||||
|
else if ((change.Property == SubjectProperty || change.Property == DescriptionProperty) && _changingWay == TextChangeWay.None)
|
||||||
|
{
|
||||||
|
_changingWay = TextChangeWay.FromEditor;
|
||||||
|
SetCurrentValue(TextProperty, $"{Subject}\n\n{Description}");
|
||||||
|
_changingWay = TextChangeWay.None;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_subjectEndLineNumber = line.LineNumber;
|
private void OnSubjectTextBoxPreviewKeyDown(object sender, KeyEventArgs e)
|
||||||
|
{
|
||||||
|
if ((e.Key == Key.Enter && e.KeyModifiers == KeyModifiers.None)
|
||||||
|
|| (e.Key == Key.Right && SubjectEditor.CaretIndex == Subject.Length))
|
||||||
|
{
|
||||||
|
DescriptionEditor.Focus();
|
||||||
|
DescriptionEditor.CaretIndex = 0;
|
||||||
|
e.Handled = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SubjectLength = text.ReplaceLineEndings(" ").Trim().Length;
|
private void OnDescriptionTextBoxPreviewKeyDown(object sender, KeyEventArgs e)
|
||||||
|
{
|
||||||
|
if ((e.Key == Key.Back || e.Key == Key.Left) && DescriptionEditor.CaretIndex == 0)
|
||||||
|
{
|
||||||
|
SubjectEditor.Focus();
|
||||||
|
SubjectEditor.CaretIndex = Subject.Length;
|
||||||
|
e.Handled = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool _isDocumentTextChanging = false;
|
private TextChangeWay _changingWay = TextChangeWay.None;
|
||||||
private int _subjectEndLineNumber = 0;
|
|
||||||
private int _totalLength = 0;
|
|
||||||
private int _subjectLength = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue