UI - Tweaked monospace font sizing

This commit is contained in:
Robert committed 2023-09-05 21:39:43 +02:00
1 parent 2ee170b803
commit fcde1d4ecc
25 files changed
+281 -214

No files matched your search

@@ -12,7 +12,7 @@
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="800"
x:Class="Artemis.UI.Screens.Workshop.Entries.EntrySpecificationsView"
x:DataType="entries:EntrySpecificationsViewModel">
<Grid RowDefinitions="Auto,*,Auto">
<Grid RowDefinitions="Auto,Auto,*,Auto">
<StackPanel>
<StackPanel.Styles>
<Styles>
@@ -25,8 +25,8 @@
</Styles>
</StackPanel.Styles>
<Grid ColumnDefinitions="103,*">
<StackPanel Grid.Column="0" Width="95">
<Grid ColumnDefinitions="105,*">
<StackPanel Grid.Column="0" Width="95" HorizontalAlignment="Left">
<Label Target="Name" Margin="0">Icon</Label>
<Button Width="95"
Height="95"
@@ -92,12 +92,22 @@
<Label>Tags</Label>
<tagsInput:TagsInput Tags="{CompiledBinding Tags}" />
<Label Target="DescriptionEditor" Margin="0 28 0 0">Description</Label>
</StackPanel>
<Grid Row="1" ColumnDefinitions="Auto,*">
<Label Grid.Column="0" Target="DescriptionEditor" Margin="0 28 0 0">Description</Label>
<StackPanel Grid.Column="1" Orientation="Horizontal" HorizontalAlignment="Right">
<CheckBox Name="SynchronizedScrolling" IsChecked="True" VerticalAlignment="Bottom">Synchronized scrolling</CheckBox>
<controls:HyperlinkButton
Margin="0 0 0 -20"
Content="Markdown supported"
NavigateUri="https://wiki.artemis-rgb.com/guides/user/markdown?mtm_campaign=artemis&amp;mtm_kwd=markdown-editor"
HorizontalAlignment="Right"/>
</StackPanel>
</Grid>
<Grid Grid.Row="1" ColumnDefinitions="*,Auto,*">
<Grid Grid.Row="2" ColumnDefinitions="*,Auto,*">
<Border Grid.Column="0" BorderThickness="1"
BorderBrush="{DynamicResource TextControlBorderBrush}"
CornerRadius="{DynamicResource ControlCornerRadius}"
@@ -105,6 +115,7 @@
Padding="{DynamicResource TextControlThemePadding}">
<avaloniaEdit:TextEditor
FontFamily="{StaticResource RobotoMono}"
FontSize="13"
Name="DescriptionEditor"
Document="{CompiledBinding MarkdownDocument}"
WordWrap="True" />
@@ -123,17 +134,12 @@
</mdxaml:MarkdownScrollViewer>
</Border>
</Grid>
<StackPanel Grid.Row="2" Orientation="Horizontal" HorizontalAlignment="Right">
<CheckBox Name="SynchronizedScrolling" IsChecked="True" VerticalAlignment="Bottom">Synchronized scrolling</CheckBox>
<controls:HyperlinkButton
Margin="0 5 0 0"
Content="Learn more about Markdown on the wiki"
NavigateUri="https://wiki.artemis-rgb.com/guides/user/markdown?mtm_campaign=artemis&amp;mtm_kwd=markdown-editor"
HorizontalAlignment="Right"
VerticalAlignment="Top" />
</StackPanel>
<TextBlock Grid.Row="3"
Foreground="{DynamicResource SystemFillColorCriticalBrush}"
Margin="2 8 0 0"
IsVisible="{CompiledBinding !DescriptionValid}">
A description is required
</TextBlock>
</Grid>
</UserControl>
@@ -11,6 +11,7 @@ using Artemis.UI.Screens.Workshop.Categories;
using Artemis.UI.Shared;
using Artemis.UI.Shared.Services;
using Artemis.WebClient.Workshop;
using Avalonia.Media.Imaging;
using AvaloniaEdit.Document;
using DynamicData;
using DynamicData.Aggregation;
@@ -19,32 +20,55 @@ using ReactiveUI;
using ReactiveUI.Validation.Extensions;
using ReactiveUI.Validation.Helpers;
using StrawberryShake;
using Bitmap = Avalonia.Media.Imaging.Bitmap;
namespace Artemis.UI.Screens.Workshop.Entries;
public class EntrySpecificationsViewModel : ValidatableViewModelBase
{
private readonly ObservableAsPropertyHelper<bool> _categoriesValid;
private readonly ObservableAsPropertyHelper<bool> _iconValid;
private readonly ObservableAsPropertyHelper<bool> _descriptionValid;
private readonly IWorkshopClient _workshopClient;
private readonly IWindowService _windowService;
private ObservableAsPropertyHelper<bool>? _categoriesValid;
private ObservableAsPropertyHelper<bool>? _iconValid;
private string _description = string.Empty;
private string _name = string.Empty;
private string _summary = string.Empty;
private Bitmap? _iconBitmap;
private TextDocument? _markdownDocument;
private string _name = string.Empty;
private string _summary = string.Empty;
private bool _iconChanged;
public EntrySpecificationsViewModel(IWorkshopClient workshopClient, IWindowService windowService)
{
_workshopClient = workshopClient;
_windowService = windowService;
SelectIcon = ReactiveCommand.CreateFromTask(ExecuteSelectIcon);
Categories.ToObservableChangeSet()
.AutoRefresh(c => c.IsSelected)
.Filter(c => c.IsSelected)
.Transform(c => c.Id)
.Bind(out ReadOnlyObservableCollection<int> selectedCategories)
.Subscribe();
SelectedCategories = selectedCategories;
this.WhenActivated(d =>
this.ValidationRule(vm => vm.Name, s => !string.IsNullOrWhiteSpace(s), "Name is required");
this.ValidationRule(vm => vm.Summary, s => !string.IsNullOrWhiteSpace(s), "Summary is required");
ValidationHelper descriptionRule = this.ValidationRule(vm => vm.Description, s => !string.IsNullOrWhiteSpace(s), "Description is required");
// These don't use inputs that support validation messages, do so manually
ValidationHelper iconRule = this.ValidationRule(vm => vm.IconBitmap, s => s != null, "Icon required");
ValidationHelper categoriesRule = this.ValidationRule(vm => vm.Categories, Categories.ToObservableChangeSet().AutoRefresh(c => c.IsSelected).Filter(c => c.IsSelected).IsNotEmpty(),
"At least one category must be selected"
);
_iconValid = iconRule.ValidationChanged.Select(c => c.IsValid).ToProperty(this, vm => vm.IconValid);
_categoriesValid = categoriesRule.ValidationChanged.Select(c => c.IsValid).ToProperty(this, vm => vm.CategoriesValid);
_descriptionValid = descriptionRule.ValidationChanged.Select(c => c.IsValid).ToProperty(this, vm => vm.DescriptionValid);
this.WhenActivatedAsync(async d =>
{
// Load categories
Observable.FromAsync(workshopClient.GetCategories.ExecuteAsync).Subscribe(PopulateCategories).DisposeWith(d);
this.ClearValidationRules();
await PopulateCategories();
MarkdownDocument = new TextDocument(new StringTextSource(Description));
MarkdownDocument.TextChanged += MarkdownDocumentOnTextChanged;
@@ -57,17 +81,15 @@ public class EntrySpecificationsViewModel : ValidatableViewModelBase
});
}
private void MarkdownDocumentOnTextChanged(object? sender, EventArgs e)
{
Description = MarkdownDocument?.Text ?? string.Empty;
}
public ReactiveCommand<Unit, Unit> SelectIcon { get; }
public ObservableCollection<CategoryViewModel> Categories { get; } = new();
public ObservableCollection<string> Tags { get; } = new();
public bool CategoriesValid => _categoriesValid?.Value ?? true;
public bool IconValid => _iconValid?.Value ?? true;
public ReadOnlyObservableCollection<int> SelectedCategories { get; }
public bool CategoriesValid => _categoriesValid.Value ;
public bool IconValid => _iconValid.Value;
public bool DescriptionValid => _descriptionValid.Value;
public string Name
{
@@ -99,23 +121,17 @@ public class EntrySpecificationsViewModel : ValidatableViewModelBase
set => RaiseAndSetIfChanged(ref _markdownDocument, value);
}
public List<int> PreselectedCategories { get; set; } = new List<int>();
public void SetupDataValidation()
public bool IconChanged
{
// Hopefully this can be avoided in the future
// https://github.com/reactiveui/ReactiveUI.Validation/discussions/558
this.ValidationRule(vm => vm.Name, s => !string.IsNullOrWhiteSpace(s), "Name is required");
this.ValidationRule(vm => vm.Summary, s => !string.IsNullOrWhiteSpace(s), "Summary is required");
this.ValidationRule(vm => vm.Description, s => !string.IsNullOrWhiteSpace(s), "Description is required");
get => _iconChanged;
private set => RaiseAndSetIfChanged(ref _iconChanged, value);
}
// These don't use inputs that support validation messages, do so manually
ValidationHelper iconRule = this.ValidationRule(vm => vm.IconBitmap, s => s != null, "Icon required");
ValidationHelper categoriesRule = this.ValidationRule(vm => vm.Categories, Categories.ToObservableChangeSet().AutoRefresh(c => c.IsSelected).Filter(c => c.IsSelected).IsNotEmpty(),
"At least one category must be selected"
);
_iconValid = iconRule.ValidationChanged.Select(c => c.IsValid).ToProperty(this, vm => vm.IconValid);
_categoriesValid = categoriesRule.ValidationChanged.Select(c => c.IsValid).ToProperty(this, vm => vm.CategoriesValid);
public List<int> PreselectedCategories { get; set; } = new();
private void MarkdownDocumentOnTextChanged(object? sender, EventArgs e)
{
Description = MarkdownDocument?.Text ?? string.Empty;
}
private async Task ExecuteSelectIcon()
@@ -129,6 +145,7 @@ public class EntrySpecificationsViewModel : ValidatableViewModelBase
IconBitmap?.Dispose();
IconBitmap = BitmapExtensions.LoadAndResize(result[0], 128);
IconChanged = true;
}
private void ClearIcon()
@@ -137,10 +154,11 @@ public class EntrySpecificationsViewModel : ValidatableViewModelBase
IconBitmap = null;
}
private void PopulateCategories(IOperationResult<IGetCategoriesResult> result)
private async Task PopulateCategories()
{
IOperationResult<IGetCategoriesResult> categories = await _workshopClient.GetCategories.ExecuteAsync();
Categories.Clear();
if (result.Data != null)
Categories.AddRange(result.Data.Categories.Select(c => new CategoryViewModel(c) {IsSelected = PreselectedCategories.Contains(c.Id)}));
if (categories.Data != null)
Categories.AddRange(categories.Data.Categories.Select(c => new CategoryViewModel(c) {IsSelected = PreselectedCategories.Contains(c.Id)}));
}
}