UI - Added routing (#802)

ColorGradient - Fixed GetColor returning the first stop if position was after the last stop
This commit is contained in:
RobertBeekman authored and GitHub committed 2023-07-02 22:15:38 +02:00
1 parent 79309dcee7
commit 962b13c6ed
77 files changed
+2034 -854

No files matched your search

@@ -11,6 +11,7 @@ using Artemis.Core.Services;
using Artemis.UI.Screens.Scripting;
using Artemis.UI.Screens.Sidebar;
using Artemis.UI.Shared;
using Artemis.UI.Shared.Routing;
using Artemis.UI.Shared.Services;
using Artemis.UI.Shared.Services.ProfileEditor;
using Newtonsoft.Json;
@@ -21,7 +22,7 @@ namespace Artemis.UI.Screens.ProfileEditor.MenuBar;
public class MenuBarViewModel : ActivatableViewModelBase
{
private readonly ILogger _logger;
private readonly IRouter _router;
private readonly IProfileEditorService _profileEditorService;
private readonly IProfileService _profileService;
private readonly ISettingsService _settingsService;
@@ -36,9 +37,9 @@ public class MenuBarViewModel : ActivatableViewModelBase
private ObservableAsPropertyHelper<RenderProfileElement?>? _profileElement;
private ObservableAsPropertyHelper<bool>? _suspendedEditing;
public MenuBarViewModel(ILogger logger, IProfileEditorService profileEditorService, IProfileService profileService, ISettingsService settingsService, IWindowService windowService)
public MenuBarViewModel(IRouter router, IProfileEditorService profileEditorService, IProfileService profileService, ISettingsService settingsService, IWindowService windowService)
{
_logger = logger;
_router = router;
_profileEditorService = profileEditorService;
_profileService = profileService;
_settingsService = settingsService;
@@ -182,7 +183,7 @@ public class MenuBarViewModel : ActivatableViewModelBase
return;
if (ProfileConfiguration.IsBeingEdited)
_profileEditorService.ChangeCurrentProfileConfiguration(null);
await _router.Navigate("home");
_profileService.RemoveProfileConfiguration(ProfileConfiguration);
}
@@ -17,6 +17,7 @@ using Artemis.UI.Shared.Services.Builders;
using Artemis.UI.Shared.Services.ProfileEditor;
using Artemis.UI.Shared.Services.ProfileEditor.Commands;
using Avalonia;
using Avalonia.ReactiveUI;
using ReactiveUI;
namespace Artemis.UI.Screens.ProfileEditor.ProfileTree;
@@ -71,7 +72,7 @@ public abstract class TreeItemViewModel : ActivatableViewModelBase
CreateTreeItems();
});
this.WhenAnyValue(vm => vm.IsFlyoutOpen).Subscribe(UpdateCanPaste);
this.WhenAnyValue(vm => vm.IsFlyoutOpen).ObserveOn(AvaloniaScheduler.Instance).Subscribe(UpdateCanPaste);
}
public ReactiveCommand<Unit, bool> AbsorbCommand { get; }
@@ -83,6 +83,7 @@ public class PropertiesViewModel : ActivatableViewModelBase
? Observable.FromEventPattern(x => l.LayerBrushUpdated += x, x => l.LayerBrushUpdated -= x)
: Observable.Never<EventPattern<object>>())
.Switch()
.ObserveOn(Shared.UI.BackgroundScheduler)
.Subscribe(_ => UpdatePropertyGroups())
.DisposeWith(d);
this.WhenAnyValue(vm => vm.ProfileElement)
@@ -90,10 +91,11 @@ public class PropertiesViewModel : ActivatableViewModelBase
? Observable.FromEventPattern(x => p.LayerEffectsUpdated += x, x => p.LayerEffectsUpdated -= x)
: Observable.Never<EventPattern<object>>())
.Switch()
.ObserveOn(Shared.UI.BackgroundScheduler)
.Subscribe(_ => UpdatePropertyGroups())
.DisposeWith(d);
});
this.WhenAnyValue(vm => vm.ProfileElement).Subscribe(_ => UpdatePropertyGroups());
this.WhenAnyValue(vm => vm.ProfileElement).ObserveOn(Shared.UI.BackgroundScheduler).Subscribe(_ => UpdatePropertyGroups());
this.WhenAnyValue(vm => vm.LayerProperty).Subscribe(_ => UpdateTimelineViewModel());
}
@@ -83,7 +83,11 @@
</ItemsControl>
</Grid>
</paz:ZoomBorder>
<Border CornerRadius="0 0 8 0" VerticalAlignment="Top" HorizontalAlignment="Left" Background="{DynamicResource ControlFillColorDefaultBrush}">
<Border CornerRadius="0 0 8 0"
VerticalAlignment="Top"
HorizontalAlignment="Left"
Background="{DynamicResource ControlFillColorDefaultBrush}"
IsVisible="{CompiledBinding ProfileConfiguration, Converter={x:Static ObjectConverters.IsNotNull}}">
<StackPanel Orientation="Horizontal" Margin="8">
<shared:ProfileConfigurationIcon ConfigurationIcon="{CompiledBinding ProfileConfiguration.Icon}" Width="18" Height="18" Margin="0 0 5 0" />
<TextBlock Text="{CompiledBinding ProfileConfiguration.Name}" />
@@ -1,6 +1,7 @@
using System;
using System.Linq;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using Avalonia;
using Avalonia.Controls.PanAndZoom;
using Avalonia.LogicalTree;
@@ -17,7 +18,7 @@ public partial class LayerShapeVisualizerView : ReactiveUserControl<LayerShapeVi
public LayerShapeVisualizerView()
{
InitializeComponent();
this.WhenActivated(d => ViewModel.WhenAnyValue(vm => vm.Selected).Subscribe(_ => UpdateStrokeThickness()).DisposeWith(d));
this.WhenActivated(d => ViewModel.WhenAnyValue(vm => vm.Selected).ObserveOn(AvaloniaScheduler.Instance).Subscribe(_ => UpdateStrokeThickness()).DisposeWith(d));
}
@@ -12,14 +12,6 @@
<UserControl.Resources>
<converters:DoubleToGridLengthConverter x:Key="DoubleToGridLengthConverter" />
</UserControl.Resources>
<UserControl.Styles>
<Style Selector="Border.suspended-editing">
<Setter Property="Margin" Value="-10" />
<Setter Property="Background" Value="{DynamicResource SmokeFillColorDefault}" />
<Setter Property="IsVisible" Value="{CompiledBinding SuspendedEditing}" />
<Setter Property="CornerRadius" Value="{DynamicResource CardCornerRadius}" />
</Style>
</UserControl.Styles>
<UserControl.KeyBindings>
<KeyBinding Command="{CompiledBinding History.Undo}" Gesture="Ctrl+Z" />
<KeyBinding Command="{CompiledBinding History.Redo}" Gesture="Ctrl+Y" />
@@ -30,6 +22,12 @@
<KeyBinding Command="{Binding TitleBarViewModel.MenuBarViewModel.CycleFocusMode}" Gesture="F" />
</UserControl.KeyBindings>
<UserControl.Styles>
<Style Selector="Border.suspended-editing">
<Setter Property="Margin" Value="-10" />
<Setter Property="Background" Value="{DynamicResource SmokeFillColorDefault}" />
<Setter Property="IsVisible" Value="{CompiledBinding SuspendedEditing}" />
<Setter Property="CornerRadius" Value="{DynamicResource CardCornerRadius}" />
</Style>
<Style Selector="GridSplitter.editor-grid-splitter-vertical">
<Setter Property="MinWidth" Value="4" />
<Setter Property="Margin" Value="1 1 1 5" />
@@ -70,7 +68,7 @@
<Border Grid.Row="0" Classes="card" Padding="0" Margin="4 0 4 4" ClipToBounds="True">
<Grid ColumnDefinitions="Auto,*">
<Border Grid.Column="0">
<ItemsControl ItemsSource="{CompiledBinding Tools}">
<ItemsControl ItemsSource="{CompiledBinding Tools}" IsVisible="{CompiledBinding ProfileConfiguration, Converter={x:Static ObjectConverters.IsNotNull}}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="shared:IToolViewModel">
<ToggleButton Classes="icon-button editor-sidebar-button"
@@ -83,14 +81,15 @@
</ItemsControl.ItemTemplate>
</ItemsControl>
</Border>
<ContentControl Grid.Column="1" Content="{CompiledBinding VisualEditorViewModel}" />
<ContentControl Grid.Column="1" Content="{CompiledBinding VisualEditorViewModel}" Classes="fade-in"
IsVisible="{CompiledBinding ProfileConfiguration, Converter={x:Static ObjectConverters.IsNotNull}}" />
</Grid>
</Border>
<GridSplitter Grid.Row="1" Classes="editor-grid-splitter-horizontal" />
<Border Grid.Row="2" Classes="card card-condensed" Margin="4" Padding="0" ClipToBounds="True">
<Panel>
<Panel IsVisible="{CompiledBinding ProfileConfiguration, Converter={x:Static ObjectConverters.IsNotNull}}">
<ContentControl Content="{CompiledBinding PropertiesViewModel}" />
<Border Classes="suspended-editing">
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" Margin="16">
@@ -109,9 +108,9 @@
</Panel>
</Border>
</Grid>
<GridSplitter Grid.Row="0" Grid.Column="1" Classes="editor-grid-splitter-vertical" />
<Grid Grid.Row="0" Grid.Column="2">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
@@ -119,22 +118,25 @@
<RowDefinition Height="{CompiledBinding ConditionsHeight.Value, Mode=TwoWay, Converter={StaticResource DoubleToGridLengthConverter}}" />
</Grid.RowDefinitions>
<Border Grid.Row="0" Classes="card card-condensed" Margin="4 0 4 4">
<Panel>
<Panel IsVisible="{CompiledBinding ProfileConfiguration, Converter={x:Static ObjectConverters.IsNotNull}}">
<ContentControl Content="{CompiledBinding ProfileTreeViewModel}" />
<Border Classes="suspended-editing" />
</Panel>
</Border>
<GridSplitter Grid.Row="1" Classes="editor-grid-splitter-horizontal" />
<Border Grid.Row="2" Classes="card card-condensed" Margin="4">
<Panel>
<Panel IsVisible="{CompiledBinding ProfileConfiguration, Converter={x:Static ObjectConverters.IsNotNull}}">
<ContentControl Content="{CompiledBinding DisplayConditionScriptViewModel}" />
<Border Classes="suspended-editing" />
</Panel>
</Border>
</Grid>
<ContentControl Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="3" Content="{CompiledBinding StatusBarViewModel}" />
<Panel Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="3" Height="23">
<ContentControl Content="{CompiledBinding StatusBarViewModel}" IsVisible="{CompiledBinding ProfileConfiguration, Converter={x:Static ObjectConverters.IsNotNull}}"/>
</Panel>
</Grid>
</UserControl>
@@ -4,6 +4,8 @@ using System.Collections.ObjectModel;
using System.Linq;
using System.Reactive;
using System.Reactive.Disposables;
using System.Threading;
using System.Threading.Tasks;
using Artemis.Core;
using Artemis.Core.Services;
using Artemis.UI.Screens.ProfileEditor.DisplayCondition;
@@ -11,6 +13,8 @@ using Artemis.UI.Screens.ProfileEditor.ProfileTree;
using Artemis.UI.Screens.ProfileEditor.Properties;
using Artemis.UI.Screens.ProfileEditor.StatusBar;
using Artemis.UI.Screens.ProfileEditor.VisualEditor;
using Artemis.UI.Shared;
using Artemis.UI.Shared.Routing;
using Artemis.UI.Shared.Services.MainWindow;
using Artemis.UI.Shared.Services.ProfileEditor;
using Avalonia.Threading;
@@ -20,22 +24,18 @@ using ReactiveUI;
namespace Artemis.UI.Screens.ProfileEditor;
public class ProfileEditorViewModel : MainScreenViewModel
public class ProfileEditorViewModel : RoutableScreen<object, ProfileEditorViewModelParameters>, IMainScreenViewModel
{
private readonly IProfileEditorService _profileEditorService;
private readonly IProfileService _profileService;
private readonly ISettingsService _settingsService;
private readonly SourceList<IToolViewModel> _tools;
private DisplayConditionScriptViewModel? _displayConditionScriptViewModel;
private ObservableAsPropertyHelper<ProfileEditorHistory?>? _history;
private ObservableAsPropertyHelper<ProfileConfiguration?>? _profileConfiguration;
private ProfileTreeViewModel? _profileTreeViewModel;
private PropertiesViewModel? _propertiesViewModel;
private StatusBarViewModel? _statusBarViewModel;
private ProfileConfiguration? _profileConfiguration;
private ObservableAsPropertyHelper<bool>? _suspendedEditing;
private VisualEditorViewModel? _visualEditorViewModel;
/// <inheritdoc />
public ProfileEditorViewModel(IScreen hostScreen,
public ProfileEditorViewModel(IProfileService profileService,
IProfileEditorService profileEditorService,
ISettingsService settingsService,
VisualEditorViewModel visualEditorViewModel,
@@ -46,8 +46,8 @@ public class ProfileEditorViewModel : MainScreenViewModel
StatusBarViewModel statusBarViewModel,
IEnumerable<IToolViewModel> toolViewModels,
IMainWindowService mainWindowService)
: base(hostScreen, "profile-editor")
{
_profileService = profileService;
_profileEditorService = profileEditorService;
_settingsService = settingsService;
@@ -62,9 +62,14 @@ public class ProfileEditorViewModel : MainScreenViewModel
Tools = tools;
visualEditorViewModel.SetTools(_tools);
StatusBarViewModel = statusBarViewModel;
VisualEditorViewModel = visualEditorViewModel;
ProfileTreeViewModel = profileTreeViewModel;
PropertiesViewModel = propertiesViewModel;
DisplayConditionScriptViewModel = displayConditionScriptViewModel;
this.WhenActivated(d =>
{
_profileConfiguration = profileEditorService.ProfileConfiguration.ToProperty(this, vm => vm.ProfileConfiguration).DisposeWith(d);
_history = profileEditorService.History.ToProperty(this, vm => vm.History).DisposeWith(d);
_suspendedEditing = profileEditorService.SuspendedEditing.ToProperty(this, vm => vm.SuspendedEditing).DisposeWith(d);
@@ -78,13 +83,6 @@ public class ProfileEditorViewModel : MainScreenViewModel
foreach (IToolViewModel toolViewModel in _tools.Items)
toolViewModel.Dispose();
}).DisposeWith(d);
// Slow and steady wins the race (and doesn't lock up the entire UI)
Dispatcher.UIThread.Post(() => StatusBarViewModel = statusBarViewModel, DispatcherPriority.Loaded);
Dispatcher.UIThread.Post(() => VisualEditorViewModel = visualEditorViewModel, DispatcherPriority.Loaded);
Dispatcher.UIThread.Post(() => ProfileTreeViewModel = profileTreeViewModel, DispatcherPriority.Loaded);
Dispatcher.UIThread.Post(() => PropertiesViewModel = propertiesViewModel, DispatcherPriority.Loaded);
Dispatcher.UIThread.Post(() => DisplayConditionScriptViewModel = displayConditionScriptViewModel, DispatcherPriority.Loaded);
});
TitleBarViewModel = profileEditorTitleBarViewModel;
@@ -92,38 +90,19 @@ public class ProfileEditorViewModel : MainScreenViewModel
ToggleAutoSuspend = ReactiveCommand.Create(ExecuteToggleAutoSuspend);
}
public VisualEditorViewModel? VisualEditorViewModel
public ProfileConfiguration? ProfileConfiguration
{
get => _visualEditorViewModel;
set => RaiseAndSetIfChanged(ref _visualEditorViewModel, value);
get => _profileConfiguration;
set => RaiseAndSetIfChanged(ref _profileConfiguration, value);
}
public ProfileTreeViewModel? ProfileTreeViewModel
{
get => _profileTreeViewModel;
set => RaiseAndSetIfChanged(ref _profileTreeViewModel, value);
}
public PropertiesViewModel? PropertiesViewModel
{
get => _propertiesViewModel;
set => RaiseAndSetIfChanged(ref _propertiesViewModel, value);
}
public DisplayConditionScriptViewModel? DisplayConditionScriptViewModel
{
get => _displayConditionScriptViewModel;
set => RaiseAndSetIfChanged(ref _displayConditionScriptViewModel, value);
}
public StatusBarViewModel? StatusBarViewModel
{
get => _statusBarViewModel;
set => RaiseAndSetIfChanged(ref _statusBarViewModel, value);
}
public VisualEditorViewModel? VisualEditorViewModel { get; }
public ProfileTreeViewModel? ProfileTreeViewModel { get; }
public PropertiesViewModel? PropertiesViewModel { get; }
public DisplayConditionScriptViewModel? DisplayConditionScriptViewModel { get; }
public StatusBarViewModel? StatusBarViewModel { get; }
public ReadOnlyObservableCollection<IToolViewModel> Tools { get; }
public ProfileConfiguration? ProfileConfiguration => _profileConfiguration?.Value;
public ProfileEditorHistory? History => _history?.Value;
public bool SuspendedEditing => _suspendedEditing?.Value ?? false;
public PluginSetting<double> TreeWidth => _settingsService.GetSetting("ProfileEditor.TreeWidth", 350.0);
@@ -132,11 +111,6 @@ public class ProfileEditorViewModel : MainScreenViewModel
public ReactiveCommand<Unit, Unit> ToggleSuspend { get; }
public ReactiveCommand<Unit, Unit> ToggleAutoSuspend { get; }
public void OpenUrl(string url)
{
Utilities.OpenUrl(url);
}
private void ExecuteToggleSuspend()
{
_profileEditorService.ChangeSuspendedEditing(!SuspendedEditing);
@@ -177,4 +151,41 @@ public class ProfileEditorViewModel : MainScreenViewModel
if (_settingsService.GetSetting("ProfileEditor.AutoSuspend", true).Value)
_profileEditorService.ChangeSuspendedEditing(true);
}
public ViewModelBase? TitleBarViewModel { get; }
#region Overrides of RoutableScreen<object,ProfileEditorViewModelParameters>
/// <inheritdoc />
public override async Task OnNavigating(ProfileEditorViewModelParameters parameters, NavigationArguments args, CancellationToken cancellationToken)
{
ProfileConfiguration? profileConfiguration = _profileService.ProfileConfigurations.FirstOrDefault(c => c.ProfileId == parameters.ProfileId);
// If the profile doesn't exist, navigate home for lack of some kind of 404 :p
if (profileConfiguration == null)
{
await args.Router.Navigate("home");
return;
}
await _profileEditorService.ChangeCurrentProfileConfiguration(profileConfiguration);
ProfileConfiguration = profileConfiguration;
}
/// <inheritdoc />
public override async Task OnClosing(NavigationArguments args)
{
if (!args.Path.StartsWith("profile-editor"))
{
ProfileConfiguration = null;
await _profileEditorService.ChangeCurrentProfileConfiguration(null);
}
}
#endregion
}
public class ProfileEditorViewModelParameters
{
public Guid ProfileId { get; set; }
}