-
-
Notifications
You must be signed in to change notification settings - Fork 68
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Showing
24 changed files
with
334 additions
and
334 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
<UserControl xmlns="https://github.com/avaloniaui" | ||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | ||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" | ||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" | ||
xmlns:avaloniaEdit="https://github.com/avaloniaui/avaloniaedit" | ||
xmlns:mdxaml="https://github.com/whistyun/Markdown.Avalonia.Tight" | ||
xmlns:fa="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia" | ||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" | ||
x:Class="Artemis.UI.Controls.SplitMarkdownEditor"> | ||
<Grid RowDefinitions="Auto,*"> | ||
<Grid Row="0" ColumnDefinitions="Auto,*"> | ||
<Label Grid.Column="0" Name="DescriptionEditorLabel" Target="DescriptionEditor" Margin="0 28 0 0" /> | ||
<StackPanel Grid.Column="1" Orientation="Horizontal" HorizontalAlignment="Right"> | ||
<CheckBox Name="SynchronizedScrolling" IsChecked="True" VerticalAlignment="Bottom">Synchronized scrolling</CheckBox> | ||
<fa:HyperlinkButton | ||
Margin="0 0 0 -20" | ||
Content="Markdown supported" | ||
NavigateUri="https://wiki.artemis-rgb.com/guides/user/markdown?mtm_campaign=artemis&mtm_kwd=markdown-editor" | ||
HorizontalAlignment="Right" /> | ||
</StackPanel> | ||
</Grid> | ||
|
||
<Grid Grid.Row="1" Grid.Column="0" ColumnDefinitions="*,Auto,*"> | ||
<Border Grid.Column="0" BorderThickness="1" | ||
BorderBrush="{DynamicResource TextControlBorderBrush}" | ||
CornerRadius="{DynamicResource ControlCornerRadius}" | ||
Background="{DynamicResource TextControlBackground}" | ||
Padding="{DynamicResource TextControlThemePadding}"> | ||
<avaloniaEdit:TextEditor | ||
FontFamily="{StaticResource RobotoMono}" | ||
FontSize="13" | ||
Name="DescriptionEditor" | ||
TextChanged="DescriptionEditor_OnTextChanged" | ||
WordWrap="True" /> | ||
</Border> | ||
|
||
<GridSplitter Grid.Column="1" Margin="5 0"></GridSplitter> | ||
<Border Grid.Column="2" Classes="card-condensed"> | ||
<mdxaml:MarkdownScrollViewer Margin="5 0" | ||
Name="DescriptionPreview" | ||
Markdown="{CompiledBinding Document.Text, Mode=OneWay, ElementName=DescriptionEditor}" | ||
MarkdownStyleName="FluentAvalonia" | ||
SaveScrollValueWhenContentUpdated="True"> | ||
<mdxaml:MarkdownScrollViewer.Styles> | ||
<StyleInclude Source="/Styles/Markdown.axaml" /> | ||
</mdxaml:MarkdownScrollViewer.Styles> | ||
</mdxaml:MarkdownScrollViewer> | ||
</Border> | ||
</Grid> | ||
</Grid> | ||
</UserControl> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
using System; | ||
using System.Linq; | ||
using System.Threading.Tasks; | ||
using Avalonia; | ||
using Avalonia.Controls; | ||
using Avalonia.Data; | ||
using Avalonia.Media; | ||
using Avalonia.Media.Immutable; | ||
using Avalonia.Threading; | ||
using AvaloniaEdit.TextMate; | ||
using TextMateSharp.Grammars; | ||
using VisualExtensions = Artemis.UI.Shared.Extensions.VisualExtensions; | ||
|
||
namespace Artemis.UI.Controls; | ||
|
||
public partial class SplitMarkdownEditor : UserControl | ||
{ | ||
public static readonly StyledProperty<string> TitleProperty = AvaloniaProperty.Register<SplitMarkdownEditor, string>(nameof(Title), string.Empty); | ||
public static readonly StyledProperty<string> MarkdownProperty = AvaloniaProperty.Register<SplitMarkdownEditor, string>(nameof(Markdown), string.Empty, defaultBindingMode: BindingMode.TwoWay); | ||
|
||
private ScrollViewer? _editorScrollViewer; | ||
private ScrollViewer? _previewScrollViewer; | ||
private bool _scrolling; | ||
private bool _updating; | ||
|
||
public string Title | ||
{ | ||
get => GetValue(TitleProperty); | ||
set => SetValue(TitleProperty, value); | ||
} | ||
|
||
public string Markdown | ||
{ | ||
get => GetValue(MarkdownProperty); | ||
set => SetValue(MarkdownProperty, value); | ||
} | ||
|
||
public SplitMarkdownEditor() | ||
{ | ||
InitializeComponent(); | ||
PropertyChanged += OnPropertyChanged; | ||
|
||
DescriptionEditorLabel.Content = Title; | ||
DescriptionEditor.Options.AllowScrollBelowDocument = false; | ||
} | ||
|
||
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e) | ||
{ | ||
if (this.TryFindResource("SystemAccentColorLight3", out object? resource) && resource is Color color) | ||
DescriptionEditor.TextArea.TextView.LinkTextForegroundBrush = new ImmutableSolidColorBrush(color); | ||
|
||
SetupScrollSync(); | ||
|
||
Dispatcher.UIThread.InvokeAsync(async () => | ||
{ | ||
// Installing is slow, wait for UI to settle | ||
await Task.Delay(300); | ||
RegistryOptions options = new(ThemeName.Dark); | ||
TextMate.Installation? install = DescriptionEditor.InstallTextMate(options); | ||
install.SetGrammar(options.GetScopeByExtension(".md")); | ||
}, DispatcherPriority.ApplicationIdle); | ||
} | ||
|
||
private void SetupScrollSync() | ||
{ | ||
if (_editorScrollViewer != null) | ||
_editorScrollViewer.PropertyChanged -= EditorScrollViewerOnPropertyChanged; | ||
if (_previewScrollViewer != null) | ||
_previewScrollViewer.PropertyChanged -= PreviewScrollViewerOnPropertyChanged; | ||
|
||
_editorScrollViewer = VisualExtensions.GetVisualChildrenOfType<ScrollViewer>(DescriptionEditor).FirstOrDefault(); | ||
_previewScrollViewer = VisualExtensions.GetVisualChildrenOfType<ScrollViewer>(DescriptionPreview).FirstOrDefault(); | ||
|
||
if (_editorScrollViewer != null) | ||
_editorScrollViewer.PropertyChanged += EditorScrollViewerOnPropertyChanged; | ||
if (_previewScrollViewer != null) | ||
_previewScrollViewer.PropertyChanged += PreviewScrollViewerOnPropertyChanged; | ||
} | ||
|
||
private void EditorScrollViewerOnPropertyChanged(object? sender, AvaloniaPropertyChangedEventArgs e) | ||
{ | ||
if (e.Property.Name != nameof(ScrollViewer.Offset) || _scrolling || SynchronizedScrolling.IsChecked != true) | ||
return; | ||
|
||
try | ||
{ | ||
_scrolling = true; | ||
SynchronizeScrollViewers(_editorScrollViewer, _previewScrollViewer); | ||
} | ||
finally | ||
{ | ||
_scrolling = false; | ||
} | ||
} | ||
|
||
private void PreviewScrollViewerOnPropertyChanged(object? sender, AvaloniaPropertyChangedEventArgs e) | ||
{ | ||
if (e.Property.Name != nameof(ScrollViewer.Offset) || _scrolling || SynchronizedScrolling.IsChecked != true) | ||
return; | ||
|
||
try | ||
{ | ||
_scrolling = true; | ||
SynchronizeScrollViewers(_previewScrollViewer, _editorScrollViewer); | ||
} | ||
finally | ||
{ | ||
_scrolling = false; | ||
} | ||
} | ||
|
||
private void SynchronizeScrollViewers(ScrollViewer? source, ScrollViewer? target) | ||
{ | ||
if (source == null || target == null) | ||
return; | ||
|
||
double sourceScrollableHeight = source.Extent.Height - source.Viewport.Height; | ||
double targetScrollableHeight = target.Extent.Height - target.Viewport.Height; | ||
|
||
if (sourceScrollableHeight != 0) | ||
target.Offset = new Vector(target.Offset.X, targetScrollableHeight * (source.Offset.Y / sourceScrollableHeight)); | ||
} | ||
|
||
private void OnPropertyChanged(object? sender, AvaloniaPropertyChangedEventArgs e) | ||
{ | ||
if (e.Property == TitleProperty) | ||
DescriptionEditorLabel.Content = Title; | ||
else if (e.Property == MarkdownProperty && DescriptionEditor.Text != Markdown) | ||
{ | ||
try | ||
{ | ||
_updating = true; | ||
DescriptionEditor.Clear(); | ||
DescriptionEditor.AppendText(Markdown); | ||
} | ||
finally | ||
{ | ||
_updating = false; | ||
} | ||
|
||
} | ||
} | ||
|
||
private void DescriptionEditor_OnTextChanged(object? sender, EventArgs e) | ||
{ | ||
if (!_updating && Markdown != DescriptionEditor.Text) | ||
Markdown = DescriptionEditor.Text; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
89 changes: 0 additions & 89 deletions
89
src/Artemis.UI/Screens/Workshop/Entries/Details/EntrySpecificationsView.axaml.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,100 +1,11 @@ | ||
using System.Linq; | ||
using Avalonia; | ||
using Avalonia.Controls; | ||
using Avalonia.Media; | ||
using Avalonia.Media.Immutable; | ||
using Avalonia.ReactiveUI; | ||
using AvaloniaEdit.TextMate; | ||
using ReactiveUI; | ||
using TextMateSharp.Grammars; | ||
using VisualExtensions = Artemis.UI.Shared.Extensions.VisualExtensions; | ||
|
||
namespace Artemis.UI.Screens.Workshop.Entries.Details; | ||
|
||
public partial class EntrySpecificationsView : ReactiveUserControl<EntrySpecificationsViewModel> | ||
{ | ||
private ScrollViewer? _editorScrollViewer; | ||
private ScrollViewer? _previewScrollViewer; | ||
private bool _updating; | ||
|
||
public EntrySpecificationsView() | ||
{ | ||
InitializeComponent(); | ||
|
||
DescriptionEditor.Options.AllowScrollBelowDocument = false; | ||
RegistryOptions options = new(ThemeName.Dark); | ||
TextMate.Installation? install = TextMate.InstallTextMate(DescriptionEditor, options); | ||
|
||
install.SetGrammar(options.GetScopeByExtension(".md")); | ||
|
||
this.WhenActivated(_ => SetupScrollSync()); | ||
} | ||
|
||
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e) | ||
{ | ||
if (this.TryFindResource("SystemAccentColorLight3", out object? resource) && resource is Color color) | ||
DescriptionEditor.TextArea.TextView.LinkTextForegroundBrush = new ImmutableSolidColorBrush(color); | ||
|
||
base.OnAttachedToVisualTree(e); | ||
} | ||
|
||
private void SetupScrollSync() | ||
{ | ||
if (_editorScrollViewer != null) | ||
_editorScrollViewer.PropertyChanged -= EditorScrollViewerOnPropertyChanged; | ||
if (_previewScrollViewer != null) | ||
_previewScrollViewer.PropertyChanged -= PreviewScrollViewerOnPropertyChanged; | ||
|
||
_editorScrollViewer = VisualExtensions.GetVisualChildrenOfType<ScrollViewer>(DescriptionEditor).FirstOrDefault(); | ||
_previewScrollViewer = VisualExtensions.GetVisualChildrenOfType<ScrollViewer>(DescriptionPreview).FirstOrDefault(); | ||
|
||
if (_editorScrollViewer != null) | ||
_editorScrollViewer.PropertyChanged += EditorScrollViewerOnPropertyChanged; | ||
if (_previewScrollViewer != null) | ||
_previewScrollViewer.PropertyChanged += PreviewScrollViewerOnPropertyChanged; | ||
} | ||
|
||
private void EditorScrollViewerOnPropertyChanged(object? sender, AvaloniaPropertyChangedEventArgs e) | ||
{ | ||
if (e.Property.Name != nameof(ScrollViewer.Offset) || _updating || SynchronizedScrolling.IsChecked != true) | ||
return; | ||
|
||
try | ||
{ | ||
_updating = true; | ||
SynchronizeScrollViewers(_editorScrollViewer, _previewScrollViewer); | ||
} | ||
finally | ||
{ | ||
_updating = false; | ||
} | ||
} | ||
|
||
private void PreviewScrollViewerOnPropertyChanged(object? sender, AvaloniaPropertyChangedEventArgs e) | ||
{ | ||
if (e.Property.Name != nameof(ScrollViewer.Offset) || _updating || SynchronizedScrolling.IsChecked != true) | ||
return; | ||
|
||
try | ||
{ | ||
_updating = true; | ||
SynchronizeScrollViewers(_previewScrollViewer, _editorScrollViewer); | ||
} | ||
finally | ||
{ | ||
_updating = false; | ||
} | ||
} | ||
|
||
private void SynchronizeScrollViewers(ScrollViewer? source, ScrollViewer? target) | ||
{ | ||
if (source == null || target == null) | ||
return; | ||
|
||
double sourceScrollableHeight = source.Extent.Height - source.Viewport.Height; | ||
double targetScrollableHeight = target.Extent.Height - target.Viewport.Height; | ||
|
||
if (sourceScrollableHeight != 0) | ||
target.Offset = new Vector(target.Offset.X, targetScrollableHeight * (source.Offset.Y / sourceScrollableHeight)); | ||
} | ||
} |
Oops, something went wrong.