diff --git a/src/Artemis.UI.Shared/Services/ProfileEditor/IProfileEditorService.cs b/src/Artemis.UI.Shared/Services/ProfileEditor/IProfileEditorService.cs index ba6caae14..82b091761 100644 --- a/src/Artemis.UI.Shared/Services/ProfileEditor/IProfileEditorService.cs +++ b/src/Artemis.UI.Shared/Services/ProfileEditor/IProfileEditorService.cs @@ -60,12 +60,7 @@ public interface IProfileEditorService : IArtemisSharedUIService /// Gets an observable of the suspended keybindings state. /// IObservable FocusMode { get; } - - /// - /// Gets an observable read only collection of all available editor tools. - /// - ReadOnlyObservableCollection Tools { get; } - + /// /// Gets an observable read only collection of selected keyframes. /// @@ -209,16 +204,4 @@ public interface IProfileEditorService : IArtemisSharedUIService /// Pauses profile preview playback. /// void Pause(); - - /// - /// Adds a profile editor tool by it's view model. - /// - /// The view model of the tool to add. - void AddTool(IToolViewModel toolViewModel); - - /// - /// Removes a profile editor tool by it's view model. - /// - /// The view model of the tool to remove. - void RemoveTool(IToolViewModel toolViewModel); } \ No newline at end of file diff --git a/src/Artemis.UI.Shared/Services/ProfileEditor/ProfileEditorService.cs b/src/Artemis.UI.Shared/Services/ProfileEditor/ProfileEditorService.cs index f2af44d46..235151038 100644 --- a/src/Artemis.UI.Shared/Services/ProfileEditor/ProfileEditorService.cs +++ b/src/Artemis.UI.Shared/Services/ProfileEditor/ProfileEditorService.cs @@ -33,7 +33,6 @@ internal class ProfileEditorService : IProfileEditorService private readonly BehaviorSubject _suspendedKeybindingsSubject = new(false); private readonly BehaviorSubject _focusModeSubject = new(ProfileEditorFocusMode.None); private readonly BehaviorSubject _timeSubject = new(TimeSpan.Zero); - private readonly SourceList _tools; private readonly SourceList _selectedKeyframes; private readonly IWindowService _windowService; private ProfileEditorCommandScope? _profileEditorHistoryScope; @@ -53,10 +52,7 @@ internal class ProfileEditorService : IProfileEditorService _layerBrushService = layerBrushService; _windowService = windowService; - _tools = new SourceList(); _selectedKeyframes = new SourceList(); - _tools.Connect().AutoRefreshOnObservable(t => t.WhenAnyValue(vm => vm.IsSelected)).Subscribe(OnToolSelected); - _tools.Connect().Bind(out ReadOnlyObservableCollection tools).Subscribe(); _selectedKeyframes.Connect().Bind(out ReadOnlyObservableCollection selectedKeyframes).Subscribe(); ProfileConfiguration = _profileConfigurationSubject.AsObservable(); @@ -69,8 +65,6 @@ internal class ProfileEditorService : IProfileEditorService SuspendedKeybindings = _suspendedKeybindingsSubject.AsObservable(); PixelsPerSecond = _pixelsPerSecondSubject.AsObservable(); FocusMode = _focusModeSubject.AsObservable(); - - Tools = tools; SelectedKeyframes = selectedKeyframes; // Observe executing, undoing and redoing commands and run the auto-save after 1 second @@ -100,7 +94,6 @@ internal class ProfileEditorService : IProfileEditorService public IObservable Playing { get; } public IObservable PixelsPerSecond { get; } public IObservable FocusMode { get; } - public ReadOnlyObservableCollection Tools { get; } public ReadOnlyObservableCollection SelectedKeyframes { get; } public void ChangeCurrentProfileConfiguration(ProfileConfiguration? profileConfiguration) @@ -384,19 +377,7 @@ internal class ProfileEditorService : IProfileEditorService if (_playingSubject.Value) _playingSubject.OnNext(false); } - - /// - public void AddTool(IToolViewModel toolViewModel) - { - _tools.Add(toolViewModel); - } - - /// - public void RemoveTool(IToolViewModel toolViewModel) - { - _tools.Remove(toolViewModel); - } - + #region Commands public void ExecuteCommand(IProfileEditorCommand command) @@ -451,22 +432,7 @@ internal class ProfileEditorService : IProfileEditorService } #endregion - - private void OnToolSelected(IChangeSet changeSet) - { - IToolViewModel? changed = changeSet.FirstOrDefault()?.Item.Current; - if (changed == null) - return; - - // Disable all others if the changed one is selected and exclusive - if (changed.IsSelected && changed.IsExclusive) - _tools.Edit(list => - { - foreach (IToolViewModel toolViewModel in list.Where(t => t.IsExclusive && t != changed)) - toolViewModel.IsSelected = false; - }); - } - + private ProfileEditorHistory? GetHistory(ProfileConfiguration? profileConfiguration) { if (profileConfiguration == null) diff --git a/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/TreeItemViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/TreeItemViewModel.cs index da04e073f..2a542fcb5 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/TreeItemViewModel.cs +++ b/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/TreeItemViewModel.cs @@ -62,7 +62,8 @@ public abstract class TreeItemViewModel : ActivatableViewModelBase _isFocused = ProfileEditorService.FocusMode .CombineLatest(ProfileEditorService.ProfileElement) .Select(tuple => GetIsFocused(tuple.First, tuple.Second)) - .ToProperty(this, vm => vm.IsFocused); + .ToProperty(this, vm => vm.IsFocused) + .DisposeWith(d); ProfileEditorService.Time.Subscribe(t => _time = t).DisposeWith(d); ProfileEditorService.ProfileElement.Subscribe(element => _currentProfileElement = element).DisposeWith(d); diff --git a/src/Artemis.UI/Screens/ProfileEditor/Panels/VisualEditor/VisualEditorViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/Panels/VisualEditor/VisualEditorViewModel.cs index aff8d0b2d..c84afbadc 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/Panels/VisualEditor/VisualEditorViewModel.cs +++ b/src/Artemis.UI/Screens/ProfileEditor/Panels/VisualEditor/VisualEditorViewModel.cs @@ -43,15 +43,6 @@ public class VisualEditorViewModel : ActivatableViewModelBase _suspendedEditing = profileEditorService.SuspendedEditing.ToProperty(this, vm => vm.SuspendedEditing).DisposeWith(d); profileEditorService.ProfileConfiguration.Subscribe(CreateVisualizers).DisposeWith(d); - profileEditorService.Tools - .ToObservableChangeSet() - .AutoRefreshOnObservable(t => t.WhenAnyValue(vm => vm.IsSelected)) - .Filter(t => t.IsSelected) - .Bind(out ReadOnlyObservableCollection tools) - .Subscribe() - .DisposeWith(d); - Tools = tools; - this.WhenAnyValue(vm => vm.ProfileConfiguration) .Select(p => p?.Profile) .Select(p => p != null @@ -74,15 +65,15 @@ public class VisualEditorViewModel : ActivatableViewModelBase public ProfileConfiguration? ProfileConfiguration => _profileConfiguration?.Value; public bool SuspendedEditing => _suspendedEditing?.Value ?? false; - public ObservableCollection Devices { get; } - public ReadOnlyObservableCollection Visualizers { get; } - public ReadOnlyObservableCollection? Tools { get => _tools; set => RaiseAndSetIfChanged(ref _tools, value); } + public ReadOnlyObservableCollection Visualizers { get; } + public ObservableCollection Devices { get; } + private void RemoveElement(EventPattern eventPattern) { List visualizers = Visualizers.Where(v => v.ProfileElement == eventPattern.EventArgs.ProfileElement).ToList(); @@ -113,7 +104,17 @@ public class VisualEditorViewModel : ActivatableViewModelBase visualizerViewModels.Add(_vmFactory.LayerShapeVisualizerViewModel(layer)); visualizerViewModels.Add(_vmFactory.LayerVisualizerViewModel(layer)); } - + + public void SetTools(SourceList tools) + { + tools.Connect() + .AutoRefreshOnObservable(t => t.WhenAnyValue(vm => vm.IsSelected)) + .Filter(t => t.IsSelected) + .Bind(out ReadOnlyObservableCollection selectedTools) + .Subscribe(); + Tools = selectedTools; + } + public void RequestAutoFit() { AutoFitRequested?.Invoke(this, EventArgs.Empty); diff --git a/src/Artemis.UI/Screens/ProfileEditor/ProfileEditorViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/ProfileEditorViewModel.cs index b7649d2f7..cb643ba0c 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/ProfileEditorViewModel.cs +++ b/src/Artemis.UI/Screens/ProfileEditor/ProfileEditorViewModel.cs @@ -1,5 +1,7 @@ using System; +using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Linq; using System.Reactive; using System.Reactive.Disposables; using Artemis.Core; @@ -21,10 +23,10 @@ public class ProfileEditorViewModel : MainScreenViewModel { private readonly IProfileEditorService _profileEditorService; private readonly ISettingsService _settingsService; + private readonly SourceList _tools; private ObservableAsPropertyHelper? _history; private ObservableAsPropertyHelper? _profileConfiguration; private ObservableAsPropertyHelper? _suspendedEditing; - private ReadOnlyObservableCollection? _tools; private StatusBarViewModel _statusBarViewModel; private DisplayConditionScriptViewModel _displayConditionScriptViewModel; private PropertiesViewModel _propertiesViewModel; @@ -40,26 +42,30 @@ public class ProfileEditorViewModel : MainScreenViewModel ProfileEditorTitleBarViewModel profileEditorTitleBarViewModel, PropertiesViewModel propertiesViewModel, DisplayConditionScriptViewModel displayConditionScriptViewModel, - StatusBarViewModel statusBarViewModel) + StatusBarViewModel statusBarViewModel, + IEnumerable toolViewModels) : base(hostScreen, "profile-editor") { _profileEditorService = profileEditorService; _settingsService = settingsService; + _tools = new SourceList(); + _tools.AddRange(toolViewModels); + _tools.Connect().AutoRefreshOnObservable(t => t.WhenAnyValue(vm => vm.IsSelected)).Subscribe(OnToolSelected); + _tools.Connect() + .Filter(t => t.ShowInToolbar) + .Sort(SortExpressionComparer.Ascending(vm => vm.Order)) + .Bind(out ReadOnlyObservableCollection tools) + .Subscribe(); + Tools = tools; + visualEditorViewModel.SetTools(_tools); + 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); - profileEditorService.Tools - .ToObservableChangeSet() - .Filter(t => t.ShowInToolbar) - .Sort(SortExpressionComparer.Ascending(vm => vm.Order)) - .Bind(out ReadOnlyObservableCollection tools) - .Subscribe() - .DisposeWith(d); - Tools = tools; - + // 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); @@ -103,12 +109,7 @@ public class ProfileEditorViewModel : MainScreenViewModel set => RaiseAndSetIfChanged(ref _statusBarViewModel, value); } - public ReadOnlyObservableCollection? Tools - { - get => _tools; - set => RaiseAndSetIfChanged(ref _tools, value); - } - + public ReadOnlyObservableCollection Tools { get; } public ProfileConfiguration? ProfileConfiguration => _profileConfiguration?.Value; public ProfileEditorHistory? History => _history?.Value; public bool SuspendedEditing => _suspendedEditing?.Value ?? false; @@ -134,4 +135,21 @@ public class ProfileEditorViewModel : MainScreenViewModel setting.Value = !setting.Value; setting.Save(); } + + private void OnToolSelected(IChangeSet changeSet) + { + IToolViewModel? changed = changeSet.FirstOrDefault()?.Item.Current; + if (changed == null) + return; + + if (!changed.IsSelected || !changed.IsExclusive) + return; + + // Disable all others if the changed one is selected and exclusive + _tools.Edit(list => + { + foreach (IToolViewModel toolViewModel in list.Where(t => t.IsExclusive && t != changed)) + toolViewModel.IsSelected = false; + }); + } } \ No newline at end of file diff --git a/src/Artemis.UI/Services/RegistrationService.cs b/src/Artemis.UI/Services/RegistrationService.cs index b89412e50..de6811cba 100644 --- a/src/Artemis.UI/Services/RegistrationService.cs +++ b/src/Artemis.UI/Services/RegistrationService.cs @@ -27,14 +27,14 @@ public class RegistrationService : IRegistrationService private readonly IDataModelUIService _dataModelUIService; private bool _registeredBuiltInPropertyEditors; - public RegistrationService(IKernel kernel, - IInputService inputService, + public RegistrationService(IKernel kernel, + IInputService inputService, IPropertyInputService propertyInputService, IProfileEditorService profileEditorService, - INodeService nodeService, + INodeService nodeService, IDataModelUIService dataModelUIService, - IDeviceLayoutService deviceLayoutService, // here to make sure it is instantiated - IEnumerable toolViewModels) + IDeviceLayoutService deviceLayoutService // here to make sure it is instantiated + ) { _kernel = kernel; _inputService = inputService; @@ -42,8 +42,6 @@ public class RegistrationService : IRegistrationService _nodeService = nodeService; _dataModelUIService = dataModelUIService; - foreach (IToolViewModel toolViewModel in toolViewModels) - profileEditorService.AddTool(toolViewModel); CreateCursorResources(); } @@ -90,7 +88,7 @@ public class RegistrationService : IRegistrationService public void RegisterControllers() { } - + public void RegisterBuiltInNodeTypes() { _nodeService.RegisterTypeColor(Constants.CorePlugin, typeof(bool), new SKColor(0xFFCD3232));