mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
UI - Fixed a lot of binding errors
UI - Added most missing DisposeWith calls
This commit is contained in:
parent
8fd18b9565
commit
372991a69b
@ -285,34 +285,43 @@ namespace Artemis.Core.Modules
|
||||
internal bool IsPropertyInUse(string path, bool includeChildren)
|
||||
{
|
||||
path = path.ToUpperInvariant();
|
||||
return includeChildren
|
||||
? _activePathsHashSet.Any(p => p.StartsWith(path, StringComparison.Ordinal))
|
||||
: _activePathsHashSet.Contains(path);
|
||||
lock (_activePaths)
|
||||
{
|
||||
return includeChildren
|
||||
? _activePathsHashSet.Any(p => p.StartsWith(path, StringComparison.Ordinal))
|
||||
: _activePathsHashSet.Contains(path);
|
||||
}
|
||||
}
|
||||
|
||||
internal void AddDataModelPath(DataModelPath path)
|
||||
{
|
||||
if (_activePaths.Contains(path))
|
||||
return;
|
||||
lock (_activePaths)
|
||||
{
|
||||
if (_activePaths.Contains(path))
|
||||
return;
|
||||
|
||||
_activePaths.Add(path);
|
||||
_activePaths.Add(path);
|
||||
|
||||
// Add to the hashset if this is the first path pointing
|
||||
string hashPath = path.Path.ToUpperInvariant();
|
||||
if (!_activePathsHashSet.Contains(hashPath))
|
||||
_activePathsHashSet.Add(hashPath);
|
||||
// Add to the hashset if this is the first path pointing
|
||||
string hashPath = path.Path.ToUpperInvariant();
|
||||
if (!_activePathsHashSet.Contains(hashPath))
|
||||
_activePathsHashSet.Add(hashPath);
|
||||
}
|
||||
|
||||
OnActivePathAdded(new DataModelPathEventArgs(path));
|
||||
}
|
||||
|
||||
internal void RemoveDataModelPath(DataModelPath path)
|
||||
{
|
||||
if (!_activePaths.Remove(path))
|
||||
return;
|
||||
lock (_activePaths)
|
||||
{
|
||||
if (!_activePaths.Remove(path))
|
||||
return;
|
||||
|
||||
// Remove from the hashset if this was the last path pointing there
|
||||
if (_activePaths.All(p => p.Path != path.Path))
|
||||
_activePathsHashSet.Remove(path.Path.ToUpperInvariant());
|
||||
// Remove from the hashset if this was the last path pointing there
|
||||
if (_activePaths.All(p => p.Path != path.Path))
|
||||
_activePathsHashSet.Remove(path.Path.ToUpperInvariant());
|
||||
}
|
||||
|
||||
OnActivePathRemoved(new DataModelPathEventArgs(path));
|
||||
}
|
||||
|
||||
@ -634,7 +634,7 @@ namespace Artemis.Core.Services
|
||||
if (isAutoEnable)
|
||||
{
|
||||
// Schedule a retry based on the amount of attempts
|
||||
if (pluginFeature.AutoEnableAttempts < 4)
|
||||
if (pluginFeature.AutoEnableAttempts < 4 && pluginFeature.Plugin.IsEnabled)
|
||||
{
|
||||
TimeSpan retryDelay = TimeSpan.FromSeconds(pluginFeature.AutoEnableAttempts * 10);
|
||||
_logger.Warning(
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using Artemis.Core.Properties;
|
||||
using Ninject;
|
||||
using Ninject.Parameters;
|
||||
|
||||
|
||||
36
src/Artemis.UI.Shared/NullCommand.cs
Normal file
36
src/Artemis.UI.Shared/NullCommand.cs
Normal file
@ -0,0 +1,36 @@
|
||||
using System;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Artemis.UI.Shared;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a placeholder command that does nothing and can't be executed.
|
||||
/// </summary>
|
||||
public class NullCommand : ICommand
|
||||
{
|
||||
private static readonly Lazy<NullCommand> _instance = new(() => new NullCommand());
|
||||
|
||||
private NullCommand()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the static instance of this command.
|
||||
/// </summary>
|
||||
public static ICommand Instance => _instance.Value;
|
||||
|
||||
/// <inheritdoc />
|
||||
public event EventHandler? CanExecuteChanged;
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Execute(object? parameter)
|
||||
{
|
||||
throw new InvalidOperationException("NullCommand cannot be executed");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool CanExecute(object? parameter)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -1,24 +1,14 @@
|
||||
<Styles xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
<Styles.Resources>
|
||||
<VisualBrush x:Key="CheckerboardBrush" TileMode="Tile" Stretch="Uniform" DestinationRect="0,0,15,15">
|
||||
<VisualBrush x:Key="CheckerboardBrush" TileMode="Tile" Stretch="Uniform" DestinationRect="0,0,12,12">
|
||||
<VisualBrush.Visual>
|
||||
<Grid Width="15" Height="15" RowDefinitions="*,*" ColumnDefinitions="*,*">
|
||||
<Rectangle Grid.Row="0" Grid.Column="0" Fill="Black" Opacity="0.15" />
|
||||
<Rectangle Grid.Row="0" Grid.Column="1" />
|
||||
<Rectangle Grid.Row="1" Grid.Column="0" />
|
||||
<Rectangle Grid.Row="1" Grid.Column="1" Fill="Black" Opacity="0.15" />
|
||||
</Grid>
|
||||
</VisualBrush.Visual>
|
||||
</VisualBrush>
|
||||
<VisualBrush x:Key="LargeCheckerboardBrush" TileMode="Tile" Stretch="Uniform" SourceRect="0,0,25,25">
|
||||
<VisualBrush.Visual>
|
||||
<Grid Width="25" Height="25" RowDefinitions="*,*" ColumnDefinitions="*,*">
|
||||
<Rectangle Grid.Row="0" Grid.Column="0" Fill="Black" Opacity="0.15" />
|
||||
<Rectangle Grid.Row="0" Grid.Column="1" />
|
||||
<Rectangle Grid.Row="1" Grid.Column="0" />
|
||||
<Rectangle Grid.Row="1" Grid.Column="1" Fill="Black" Opacity="0.15" />
|
||||
</Grid>
|
||||
<Canvas Width="12" Height="12">
|
||||
<Rectangle Width="6" Height="6" Fill="Black" Opacity="0.15" />
|
||||
<Rectangle Width="6" Height="6" Canvas.Left="6" />
|
||||
<Rectangle Width="6" Height="6" Canvas.Top="6" />
|
||||
<Rectangle Width="6" Height="6" Canvas.Left="6" Canvas.Top="6" Fill="Black" Opacity="0.15" />
|
||||
</Canvas>
|
||||
</VisualBrush.Visual>
|
||||
</VisualBrush>
|
||||
</Styles.Resources>
|
||||
|
||||
@ -88,9 +88,9 @@
|
||||
Background="{DynamicResource LightCheckerboardBrush}"
|
||||
Margin="5 0">
|
||||
<Border Background="{TemplateBinding LinearGradientBrush}">
|
||||
<ItemsControl Items="{TemplateBinding ColorGradient}" ClipToBounds="False">
|
||||
<ItemsControl Name="GradientStops" Items="{TemplateBinding ColorGradient}" ClipToBounds="False">
|
||||
<ItemsControl.Styles>
|
||||
<Style Selector="ContentPresenter">
|
||||
<Style Selector="ItemsControl#GradientStops > ContentPresenter">
|
||||
<Setter Property="Canvas.Left">
|
||||
<Setter.Value>
|
||||
<MultiBinding Converter="{StaticResource WidthNormalizedConverter}">
|
||||
|
||||
@ -22,7 +22,7 @@ public class MenuBarViewModel : ActivatableViewModelBase
|
||||
this.WhenActivated(d =>
|
||||
{
|
||||
profileEditorService.History.Subscribe(history => History = history).DisposeWith(d);
|
||||
_profileConfiguration = profileEditorService.ProfileConfiguration.ToProperty(this, vm => vm.ProfileConfiguration);
|
||||
_profileConfiguration = profileEditorService.ProfileConfiguration.ToProperty(this, vm => vm.ProfileConfiguration).DisposeWith(d);
|
||||
_isSuspended = profileEditorService.ProfileConfiguration
|
||||
.Select(p => p?.WhenAnyValue(c => c.IsSuspended) ?? Observable.Never<bool>())
|
||||
.Switch()
|
||||
|
||||
@ -10,6 +10,15 @@
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Artemis.UI.Screens.ProfileEditor.ProfileTree.ProfileTreeView"
|
||||
x:DataType="profileTree:ProfileTreeViewModel">
|
||||
<!-- These cause binding errors, not my fault - https://github.com/AvaloniaUI/Avalonia/issues/5762 -->
|
||||
<UserControl.KeyBindings>
|
||||
<KeyBinding Gesture="Escape" Command="{Binding ClearSelection}" />
|
||||
<KeyBinding Gesture="F2" Command="{Binding RenameSelected}" />
|
||||
<KeyBinding Gesture="Delete" Command="{Binding DeleteSelected}" />
|
||||
<KeyBinding Gesture="Ctrl+D" Command="{Binding DuplicateSelected}" />
|
||||
<KeyBinding Gesture="Ctrl+C" Command="{Binding CopySelected}" />
|
||||
<KeyBinding Gesture="Ctrl+V" Command="{Binding PasteSelected}" />
|
||||
</UserControl.KeyBindings>
|
||||
<UserControl.Resources>
|
||||
<converters:ColorOpacityConverter x:Key="ColorOpacityConverter" />
|
||||
</UserControl.Resources>
|
||||
@ -55,7 +64,7 @@
|
||||
<Setter Property="Background">
|
||||
<Setter.Value>
|
||||
<LinearGradientBrush StartPoint="0,0" EndPoint="0,28">
|
||||
<GradientStop Color="{StaticResource SystemAccentColorLight3}" Offset="0.0" />
|
||||
<GradientStop Color="{StaticResource SystemAccentColorLight3}" Offset="0.0" />
|
||||
<GradientStop Color="{StaticResource SystemAccentColorLight3}" Offset="0.05" />
|
||||
<GradientStop Color="{Binding Source={StaticResource SystemAccentColorLight3}, Converter={StaticResource ColorOpacityConverter}, ConverterParameter=0.25}" Offset="0.05" />
|
||||
<GradientStop Color="{Binding Source={StaticResource SystemAccentColorLight3}, Converter={StaticResource ColorOpacityConverter}, ConverterParameter=0}" Offset="0.25" />
|
||||
@ -88,14 +97,6 @@
|
||||
<Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
|
||||
</Style>
|
||||
</TreeView.Styles>
|
||||
<TreeView.KeyBindings>
|
||||
<KeyBinding Gesture="Escape" Command="{CompiledBinding ClearSelection}" />
|
||||
<KeyBinding Gesture="F2" Command="{CompiledBinding SelectedChild.Rename}" />
|
||||
<KeyBinding Gesture="Delete" Command="{CompiledBinding SelectedChild.Delete}" />
|
||||
<KeyBinding Gesture="Ctrl+D" Command="{CompiledBinding SelectedChild.Duplicate}" />
|
||||
<KeyBinding Gesture="Ctrl+C" Command="{CompiledBinding SelectedChild.Copy}" />
|
||||
<KeyBinding Gesture="Ctrl+V" Command="{CompiledBinding SelectedChild.Paste}" />
|
||||
</TreeView.KeyBindings>
|
||||
<TreeView.ItemTemplate>
|
||||
<TreeDataTemplate ItemsSource="{Binding Children}">
|
||||
<ContentControl Content="{Binding}" x:DataType="profileTree:TreeItemViewModel">
|
||||
|
||||
@ -2,7 +2,6 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Reactive;
|
||||
using System.Reactive.Disposables;
|
||||
using Artemis.Core;
|
||||
using Artemis.Core.Services;
|
||||
@ -11,87 +10,114 @@ using Artemis.UI.Shared.Services.Interfaces;
|
||||
using Artemis.UI.Shared.Services.ProfileEditor;
|
||||
using ReactiveUI;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor.ProfileTree
|
||||
namespace Artemis.UI.Screens.ProfileEditor.ProfileTree;
|
||||
|
||||
public class ProfileTreeViewModel : TreeItemViewModel
|
||||
{
|
||||
public class ProfileTreeViewModel : TreeItemViewModel
|
||||
private readonly IProfileEditorService _profileEditorService;
|
||||
private TreeItemViewModel? _selectedChild;
|
||||
|
||||
public ProfileTreeViewModel(IWindowService windowService,
|
||||
IProfileEditorService profileEditorService,
|
||||
ILayerBrushService layerBrushService,
|
||||
IProfileEditorVmFactory profileEditorVmFactory,
|
||||
IRgbService rgbService)
|
||||
: base(null, null, windowService, profileEditorService, rgbService, layerBrushService, profileEditorVmFactory)
|
||||
{
|
||||
private TreeItemViewModel? _selectedChild;
|
||||
|
||||
public ProfileTreeViewModel(IWindowService windowService,
|
||||
IProfileEditorService profileEditorService,
|
||||
ILayerBrushService layerBrushService,
|
||||
IProfileEditorVmFactory profileEditorVmFactory,
|
||||
IRgbService rgbService)
|
||||
: base(null, null, windowService, profileEditorService, rgbService, layerBrushService, profileEditorVmFactory)
|
||||
_profileEditorService = profileEditorService;
|
||||
this.WhenActivated(d =>
|
||||
{
|
||||
this.WhenActivated(d =>
|
||||
profileEditorService.ProfileConfiguration.WhereNotNull().Subscribe(configuration =>
|
||||
{
|
||||
profileEditorService.ProfileConfiguration.WhereNotNull().Subscribe(configuration =>
|
||||
if (configuration.Profile == null)
|
||||
{
|
||||
if (configuration.Profile == null)
|
||||
{
|
||||
windowService.ShowConfirmContentDialog("Failed to load profile", "It appears that this profile is corrupt and cannot be loaded. Please check your logs.", "Confirm", null);
|
||||
return;
|
||||
}
|
||||
windowService.ShowConfirmContentDialog("Failed to load profile", "It appears that this profile is corrupt and cannot be loaded. Please check your logs.", "Confirm", null);
|
||||
return;
|
||||
}
|
||||
|
||||
ProfileElement = configuration.Profile.GetRootFolder();
|
||||
SubscribeToProfileElement(d);
|
||||
CreateTreeItems();
|
||||
}).DisposeWith(d);
|
||||
ProfileElement = configuration.Profile.GetRootFolder();
|
||||
SubscribeToProfileElement(d);
|
||||
CreateTreeItems();
|
||||
}).DisposeWith(d);
|
||||
|
||||
profileEditorService.ProfileElement.Subscribe(SelectCurrentProfileElement).DisposeWith(d);
|
||||
});
|
||||
profileEditorService.ProfileElement.Subscribe(SelectCurrentProfileElement).DisposeWith(d);
|
||||
});
|
||||
|
||||
this.WhenAnyValue(vm => vm.SelectedChild).Subscribe(model =>
|
||||
{
|
||||
if (model?.ProfileElement is RenderProfileElement renderProfileElement)
|
||||
profileEditorService.ChangeCurrentProfileElement(renderProfileElement);
|
||||
});
|
||||
|
||||
ClearSelection = ReactiveCommand.Create(() => profileEditorService.ChangeCurrentProfileElement(null));
|
||||
}
|
||||
|
||||
public ReactiveCommand<Unit, Unit> ClearSelection { get; }
|
||||
|
||||
public TreeItemViewModel? SelectedChild
|
||||
this.WhenAnyValue(vm => vm.SelectedChild).Subscribe(model =>
|
||||
{
|
||||
get => _selectedChild;
|
||||
set => RaiseAndSetIfChanged(ref _selectedChild, value);
|
||||
}
|
||||
if (model?.ProfileElement is RenderProfileElement renderProfileElement)
|
||||
profileEditorService.ChangeCurrentProfileElement(renderProfileElement);
|
||||
});
|
||||
}
|
||||
|
||||
private void SelectCurrentProfileElement(RenderProfileElement? element)
|
||||
public TreeItemViewModel? SelectedChild
|
||||
{
|
||||
get => _selectedChild;
|
||||
set => RaiseAndSetIfChanged(ref _selectedChild, value);
|
||||
}
|
||||
|
||||
public override bool SupportsChildren => true;
|
||||
|
||||
public void ClearSelection()
|
||||
{
|
||||
_profileEditorService.ChangeCurrentProfileElement(null);
|
||||
}
|
||||
|
||||
public void RenameSelected()
|
||||
{
|
||||
SelectedChild?.Rename.Execute().Subscribe();
|
||||
}
|
||||
|
||||
public void DeleteSelected()
|
||||
{
|
||||
SelectedChild?.Delete.Execute().Subscribe();
|
||||
}
|
||||
|
||||
public void DuplicateSelected()
|
||||
{
|
||||
SelectedChild?.Duplicate.Execute().Subscribe();
|
||||
}
|
||||
|
||||
public void CopySelected()
|
||||
{
|
||||
SelectedChild?.Copy.Execute().Subscribe();
|
||||
}
|
||||
|
||||
public void PasteSelected()
|
||||
{
|
||||
SelectedChild?.Paste.Execute().Subscribe();
|
||||
}
|
||||
|
||||
private void SelectCurrentProfileElement(RenderProfileElement? element)
|
||||
{
|
||||
if (SelectedChild?.ProfileElement == element)
|
||||
return;
|
||||
|
||||
// Find the tree item belonging to the selected element
|
||||
List<TreeItemViewModel> treeItems = GetAllTreeItems(Children);
|
||||
TreeItemViewModel? selected = treeItems.FirstOrDefault(e => e.ProfileElement == element);
|
||||
|
||||
// Walk up the tree, expanding parents
|
||||
TreeItemViewModel? currentParent = selected?.Parent;
|
||||
while (currentParent != null)
|
||||
{
|
||||
if (SelectedChild?.ProfileElement == element)
|
||||
return;
|
||||
|
||||
// Find the tree item belonging to the selected element
|
||||
List<TreeItemViewModel> treeItems = GetAllTreeItems(Children);
|
||||
TreeItemViewModel? selected = treeItems.FirstOrDefault(e => e.ProfileElement == element);
|
||||
|
||||
// Walk up the tree, expanding parents
|
||||
TreeItemViewModel? currentParent = selected?.Parent;
|
||||
while (currentParent != null)
|
||||
{
|
||||
currentParent.IsExpanded = true;
|
||||
currentParent = currentParent.Parent;
|
||||
}
|
||||
|
||||
SelectedChild = selected;
|
||||
currentParent.IsExpanded = true;
|
||||
currentParent = currentParent.Parent;
|
||||
}
|
||||
|
||||
private List<TreeItemViewModel> GetAllTreeItems(ObservableCollection<TreeItemViewModel> treeItems)
|
||||
SelectedChild = selected;
|
||||
}
|
||||
|
||||
private List<TreeItemViewModel> GetAllTreeItems(ObservableCollection<TreeItemViewModel> treeItems)
|
||||
{
|
||||
List<TreeItemViewModel> result = new();
|
||||
foreach (TreeItemViewModel treeItemViewModel in treeItems)
|
||||
{
|
||||
List<TreeItemViewModel> result = new();
|
||||
foreach (TreeItemViewModel treeItemViewModel in treeItems)
|
||||
{
|
||||
result.Add(treeItemViewModel);
|
||||
if (treeItemViewModel.Children.Any())
|
||||
result.AddRange(GetAllTreeItems(treeItemViewModel.Children));
|
||||
}
|
||||
|
||||
return result;
|
||||
result.Add(treeItemViewModel);
|
||||
if (treeItemViewModel.Children.Any())
|
||||
result.AddRange(GetAllTreeItems(treeItemViewModel.Children));
|
||||
}
|
||||
|
||||
public override bool SupportsChildren => true;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -57,7 +57,14 @@ public class PropertiesViewModel : ActivatableViewModelBase
|
||||
{
|
||||
_profileElement = profileEditorService.ProfileElement.ToProperty(this, vm => vm.ProfileElement).DisposeWith(d);
|
||||
_pixelsPerSecond = profileEditorService.PixelsPerSecond.ToProperty(this, vm => vm.PixelsPerSecond).DisposeWith(d);
|
||||
Disposable.Create(() => _settingsService.SaveAllSettings()).DisposeWith(d);
|
||||
Disposable.Create(() =>
|
||||
{
|
||||
_settingsService.SaveAllSettings();
|
||||
foreach ((LayerPropertyGroup _, PropertyGroupViewModel value) in _cachedViewModels)
|
||||
value.Dispose();
|
||||
_cachedViewModels.Clear();
|
||||
|
||||
}).DisposeWith(d);
|
||||
});
|
||||
this.WhenAnyValue(vm => vm.ProfileElement).Subscribe(_ => UpdateGroups());
|
||||
}
|
||||
|
||||
@ -23,7 +23,7 @@ public class TimelineGroupViewModel : ActivatableViewModelBase
|
||||
{
|
||||
_pixelsPerSecond = p;
|
||||
UpdateKeyframePositions();
|
||||
});
|
||||
}).DisposeWith(d);
|
||||
this.WhenAnyValue(vm => vm.PropertyGroupViewModel.IsExpanded).Subscribe(_ => UpdateKeyframePositions()).DisposeWith(d);
|
||||
PropertyGroupViewModel.WhenAnyValue(vm => vm.IsExpanded).Subscribe(_ => this.RaisePropertyChanged(nameof(Children))).DisposeWith(d);
|
||||
});
|
||||
|
||||
@ -24,7 +24,7 @@ public class StatusBarViewModel : ActivatableViewModelBase
|
||||
{
|
||||
_profileElement = profileEditorService.ProfileElement.ToProperty(this, vm => vm.ProfileElement).DisposeWith(d);
|
||||
_history = profileEditorService.History.ToProperty(this, vm => vm.History).DisposeWith(d);
|
||||
_pixelsPerSecond = profileEditorService.PixelsPerSecond.ToProperty(this, vm => vm.PixelsPerSecond);
|
||||
_pixelsPerSecond = profileEditorService.PixelsPerSecond.ToProperty(this, vm => vm.PixelsPerSecond).DisposeWith(d);
|
||||
});
|
||||
|
||||
this.WhenAnyValue(vm => vm.History)
|
||||
|
||||
@ -9,6 +9,18 @@
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Artemis.UI.Screens.ProfileEditor.VisualEditor.VisualEditorView"
|
||||
x:DataType="visualEditor:VisualEditorViewModel">
|
||||
<UserControl.Resources>
|
||||
<VisualBrush x:Key="LargeCheckerboardBrush" TileMode="Tile" Stretch="Uniform" SourceRect="0,0,20,20">
|
||||
<VisualBrush.Visual>
|
||||
<Canvas Width="20" Height="20">
|
||||
<Rectangle Width="10" Height="10" Fill="Black" Opacity="0.15" />
|
||||
<Rectangle Width="10" Height="10" Canvas.Left="10" />
|
||||
<Rectangle Width="10" Height="10" Canvas.Top="10" />
|
||||
<Rectangle Width="10" Height="10" Canvas.Left="10" Canvas.Top="10" Fill="Black" Opacity="0.15" />
|
||||
</Canvas>
|
||||
</VisualBrush.Visual>
|
||||
</VisualBrush>
|
||||
</UserControl.Resources>
|
||||
<Grid>
|
||||
<paz:ZoomBorder Name="ZoomBorder"
|
||||
Stretch="None"
|
||||
@ -16,7 +28,7 @@
|
||||
Focusable="True"
|
||||
VerticalAlignment="Stretch"
|
||||
HorizontalAlignment="Stretch"
|
||||
Background="{DynamicResource LargeCheckerboardBrush}"
|
||||
Background="{StaticResource LargeCheckerboardBrush}"
|
||||
ZoomChanged="ZoomBorder_OnZoomChanged">
|
||||
<Grid Name="ContainerGrid"
|
||||
Background="Transparent">
|
||||
|
||||
@ -19,7 +19,6 @@ namespace Artemis.UI.Screens.ProfileEditor
|
||||
|
||||
private void MenuItem_OnSubmenuOpened(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -15,6 +15,7 @@ using Avalonia.Controls;
|
||||
using Avalonia.Controls.ApplicationLifetimes;
|
||||
using Avalonia.Platform;
|
||||
using Avalonia.Threading;
|
||||
using JetBrains.Annotations;
|
||||
using ReactiveUI;
|
||||
|
||||
namespace Artemis.UI.Screens.Root
|
||||
@ -95,6 +96,7 @@ namespace Artemis.UI.Screens.Root
|
||||
{
|
||||
_lifeTime.MainWindow = null;
|
||||
SidebarViewModel = null;
|
||||
Router.NavigateAndReset.Execute(new EmptyViewModel(this, "blank")).Subscribe();
|
||||
|
||||
OnMainWindowClosed();
|
||||
}
|
||||
@ -220,4 +222,12 @@ namespace Artemis.UI.Screens.Root
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
internal class EmptyViewModel : MainScreenViewModel
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public EmptyViewModel(IScreen hostScreen, string urlPathSegment) : base(hostScreen, urlPathSegment)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4,6 +4,7 @@ using System.Collections.ObjectModel;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Reactive;
|
||||
using System.Reactive.Disposables;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Artemis.Core;
|
||||
@ -30,8 +31,8 @@ namespace Artemis.UI.Screens.Settings
|
||||
DisplayName = "General";
|
||||
_settingsService = settingsService;
|
||||
_debugService = debugService;
|
||||
_fluentAvaloniaTheme = AvaloniaLocator.Current.GetService<FluentAvaloniaTheme>(); ;
|
||||
|
||||
_fluentAvaloniaTheme = AvaloniaLocator.Current.GetService<FluentAvaloniaTheme>();
|
||||
|
||||
List<LayerBrushProvider> layerBrushProviders = pluginManagementService.GetFeaturesOfType<LayerBrushProvider>();
|
||||
LayerBrushDescriptors = new ObservableCollection<LayerBrushDescriptor>(layerBrushProviders.SelectMany(l => l.LayerBrushDescriptors));
|
||||
_defaultLayerBrushDescriptor = _settingsService.GetSetting("ProfileEditor.DefaultLayerBrushDescriptor", new LayerBrushReference
|
||||
@ -45,8 +46,12 @@ namespace Artemis.UI.Screens.Settings
|
||||
ShowSetupWizard = ReactiveCommand.Create(ExecuteShowSetupWizard);
|
||||
ShowDebugger = ReactiveCommand.Create(ExecuteShowDebugger);
|
||||
ShowDataFolder = ReactiveCommand.Create(ExecuteShowDataFolder);
|
||||
|
||||
UIColorScheme.SettingChanged += UIColorSchemeOnSettingChanged;
|
||||
|
||||
this.WhenActivated(d =>
|
||||
{
|
||||
UIColorScheme.SettingChanged += UIColorSchemeOnSettingChanged;
|
||||
Disposable.Create(() => UIColorScheme.SettingChanged -= UIColorSchemeOnSettingChanged).DisposeWith(d);
|
||||
});
|
||||
}
|
||||
|
||||
private void UIColorSchemeOnSettingChanged(object? sender, EventArgs e)
|
||||
@ -139,7 +144,7 @@ namespace Artemis.UI.Screens.Settings
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Updating
|
||||
|
||||
private Task ExecuteCheckForUpdate(CancellationToken cancellationToken)
|
||||
|
||||
@ -7,7 +7,18 @@
|
||||
xmlns:controls="clr-namespace:Artemis.UI.Shared.Controls;assembly=Artemis.UI.Shared"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Artemis.UI.Screens.SurfaceEditor.SurfaceEditorView">
|
||||
|
||||
<UserControl.Resources>
|
||||
<VisualBrush x:Key="LargeCheckerboardBrush" TileMode="Tile" Stretch="Uniform" SourceRect="0,0,20,20">
|
||||
<VisualBrush.Visual>
|
||||
<Canvas Width="20" Height="20">
|
||||
<Rectangle Width="10" Height="10" Fill="Black" Opacity="0.15" />
|
||||
<Rectangle Width="10" Height="10" Canvas.Left="10" />
|
||||
<Rectangle Width="10" Height="10" Canvas.Top="10" />
|
||||
<Rectangle Width="10" Height="10" Canvas.Left="10" Canvas.Top="10" Fill="Black" Opacity="0.15" />
|
||||
</Canvas>
|
||||
</VisualBrush.Visual>
|
||||
</VisualBrush>
|
||||
</UserControl.Resources>
|
||||
<Border Classes="router-container">
|
||||
<paz:ZoomBorder Name="ZoomBorder"
|
||||
Stretch="None"
|
||||
@ -15,7 +26,7 @@
|
||||
Focusable="True"
|
||||
VerticalAlignment="Stretch"
|
||||
HorizontalAlignment="Stretch"
|
||||
Background="{DynamicResource LargeCheckerboardBrush}"
|
||||
Background="{StaticResource LargeCheckerboardBrush}"
|
||||
ZoomChanged="ZoomBorder_OnZoomChanged"
|
||||
PointerPressed="ZoomBorder_OnPointerPressed"
|
||||
PointerMoved="ZoomBorder_OnPointerMoved"
|
||||
|
||||
@ -47,7 +47,7 @@
|
||||
Padding="4"
|
||||
Canvas.Left="{CompiledBinding ValuePoint.X}"
|
||||
Canvas.Top="{CompiledBinding ValuePoint.Y}"
|
||||
IsVisible="{CompiledBinding FromViewModel.Pin.PinValue, Converter={x:Static ObjectConverters.IsNotNull}}">
|
||||
IsVisible="{CompiledBinding DisplayValue}">
|
||||
<ContentControl Content="{CompiledBinding FromViewModel.Pin.PinValue}">
|
||||
<ContentControl.DataTemplates>
|
||||
<DataTemplate DataType="skiaSharp:SKColor">
|
||||
|
||||
@ -15,14 +15,15 @@ namespace Artemis.UI.Screens.VisualScripting;
|
||||
|
||||
public class CableViewModel : ActivatableViewModelBase
|
||||
{
|
||||
private readonly ObservableAsPropertyHelper<bool> _connected;
|
||||
private readonly ObservableAsPropertyHelper<Point> _fromPoint;
|
||||
private readonly ObservableAsPropertyHelper<Point> _toPoint;
|
||||
private readonly ObservableAsPropertyHelper<Point> _valuePoint;
|
||||
private ObservableAsPropertyHelper<Color>? _cableColor;
|
||||
private ObservableAsPropertyHelper<Point>? _fromPoint;
|
||||
private ObservableAsPropertyHelper<Point>? _toPoint;
|
||||
private ObservableAsPropertyHelper<Point>? _valuePoint;
|
||||
private ObservableAsPropertyHelper<bool>? _connected;
|
||||
|
||||
private PinViewModel? _fromViewModel;
|
||||
private PinViewModel? _toViewModel;
|
||||
private bool _displayValue;
|
||||
|
||||
public CableViewModel(NodeScriptViewModel nodeScriptViewModel, IPin from, IPin to)
|
||||
{
|
||||
@ -42,25 +43,32 @@ public class CableViewModel : ActivatableViewModelBase
|
||||
.Switch()
|
||||
.ToProperty(this, vm => vm.CableColor)
|
||||
.DisposeWith(d);
|
||||
|
||||
_fromPoint = this.WhenAnyValue(vm => vm.FromViewModel)
|
||||
.Select(p => p != null ? p.WhenAnyValue(pvm => pvm.Position) : Observable.Never<Point>())
|
||||
.Switch()
|
||||
.ToProperty(this, vm => vm.FromPoint)
|
||||
.DisposeWith(d);
|
||||
_toPoint = this.WhenAnyValue(vm => vm.ToViewModel)
|
||||
.Select(p => p != null ? p.WhenAnyValue(pvm => pvm.Position) : Observable.Never<Point>())
|
||||
.Switch()
|
||||
.ToProperty(this, vm => vm.ToPoint)
|
||||
.DisposeWith(d);
|
||||
_valuePoint = this.WhenAnyValue(vm => vm.FromPoint, vm => vm.ToPoint).Select(tuple => new Point(
|
||||
tuple.Item1.X + (tuple.Item2.X - tuple.Item1.X) / 2,
|
||||
tuple.Item1.Y + (tuple.Item2.Y - tuple.Item1.Y) / 2
|
||||
)).ToProperty(this, vm => vm.ValuePoint)
|
||||
.DisposeWith(d);
|
||||
|
||||
// Not a perfect solution but this makes sure the cable never renders at 0,0 (can happen when the cable spawns before the pin ever rendered)
|
||||
_connected = this.WhenAnyValue(vm => vm.FromPoint, vm => vm.ToPoint)
|
||||
.Select(tuple => tuple.Item1 != new Point(0, 0) && tuple.Item2 != new Point(0, 0))
|
||||
.ToProperty(this, vm => vm.Connected)
|
||||
.DisposeWith(d);
|
||||
});
|
||||
|
||||
_fromPoint = this.WhenAnyValue(vm => vm.FromViewModel)
|
||||
.Select(p => p != null ? p.WhenAnyValue(pvm => pvm.Position) : Observable.Never<Point>())
|
||||
.Switch()
|
||||
.ToProperty(this, vm => vm.FromPoint);
|
||||
_toPoint = this.WhenAnyValue(vm => vm.ToViewModel)
|
||||
.Select(p => p != null ? p.WhenAnyValue(pvm => pvm.Position) : Observable.Never<Point>())
|
||||
.Switch()
|
||||
.ToProperty(this, vm => vm.ToPoint);
|
||||
_valuePoint = this.WhenAnyValue(vm => vm.FromPoint, vm => vm.ToPoint).Select(tuple => new Point(
|
||||
tuple.Item1.X + (tuple.Item2.X - tuple.Item1.X) / 2,
|
||||
tuple.Item1.Y + (tuple.Item2.Y - tuple.Item1.Y) / 2
|
||||
)).ToProperty(this, vm => vm.ValuePoint);
|
||||
|
||||
// Not a perfect solution but this makes sure the cable never renders at 0,0 (can happen when the cable spawns before the pin ever rendered)
|
||||
_connected = this.WhenAnyValue(vm => vm.FromPoint, vm => vm.ToPoint)
|
||||
.Select(tuple => tuple.Item1 != new Point(0, 0) && tuple.Item2 != new Point(0, 0))
|
||||
.ToProperty(this, vm => vm.Connected);
|
||||
DisplayValue = !nodeScriptViewModel.IsPreview;
|
||||
}
|
||||
|
||||
public PinViewModel? FromViewModel
|
||||
@ -75,10 +83,16 @@ public class CableViewModel : ActivatableViewModelBase
|
||||
set => RaiseAndSetIfChanged(ref _toViewModel, value);
|
||||
}
|
||||
|
||||
public bool Connected => _connected.Value;
|
||||
public bool DisplayValue
|
||||
{
|
||||
get => _displayValue;
|
||||
set => _displayValue = value;
|
||||
}
|
||||
|
||||
public Point FromPoint => _fromPoint.Value;
|
||||
public Point ToPoint => _toPoint.Value;
|
||||
public Point ValuePoint => _valuePoint.Value;
|
||||
public bool Connected => _connected?.Value ?? false;
|
||||
|
||||
public Point FromPoint => _fromPoint?.Value ?? new Point();
|
||||
public Point ToPoint => _toPoint?.Value ?? new Point();
|
||||
public Point ValuePoint => _valuePoint?.Value ?? new Point();
|
||||
public Color CableColor => _cableColor?.Value ?? new Color(255, 255, 255, 255);
|
||||
}
|
||||
@ -21,7 +21,7 @@
|
||||
FontFamily="{StaticResource SymbolThemeFontFamily}"
|
||||
Classes="AppBarButton"
|
||||
Command="{Binding $parent[TextBox].Clear}"
|
||||
IsVisible="{Binding Text, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type TextBox}}, Converter={x:Static StringConverters.IsNotNullOrEmpty}}" />
|
||||
IsVisible="{Binding $parent[TextBox].Text, Converter={x:Static StringConverters.IsNotNullOrEmpty}}" />
|
||||
<controls:Button Content=""
|
||||
FontFamily="{StaticResource SymbolThemeFontFamily}"
|
||||
Classes="AppBarButton"
|
||||
|
||||
@ -14,63 +14,64 @@
|
||||
<Setter Property="MaxWidth" Value="1000"></Setter>
|
||||
</Style>
|
||||
</UserControl.Styles>
|
||||
<UserControl.KeyBindings>
|
||||
<KeyBinding Command="{CompiledBinding History.Undo}" Gesture="Ctrl+Z"></KeyBinding>
|
||||
<KeyBinding Command="{CompiledBinding History.Redo}" Gesture="Ctrl+Y"></KeyBinding>
|
||||
<KeyBinding Command="{Binding DeleteSelectedNodes}" Gesture="Delete"></KeyBinding>
|
||||
</UserControl.KeyBindings>
|
||||
<UserControl.Resources>
|
||||
<VisualBrush x:Key="LargeCheckerboardBrush" TileMode="Tile" Stretch="Uniform" SourceRect="0,0,20,20">
|
||||
<VisualBrush.Visual>
|
||||
<Canvas Width="20" Height="20">
|
||||
<Rectangle Width="10" Height="10" Fill="Black" Opacity="0.15" />
|
||||
<Rectangle Width="10" Height="10" Canvas.Left="10" />
|
||||
<Rectangle Width="10" Height="10" Canvas.Top="10" />
|
||||
<Rectangle Width="10" Height="10" Canvas.Left="10" Canvas.Top="10" Fill="Black" Opacity="0.15" />
|
||||
</Canvas>
|
||||
</VisualBrush.Visual>
|
||||
</VisualBrush>
|
||||
</UserControl.Resources>
|
||||
<paz:ZoomBorder Name="ZoomBorder"
|
||||
Stretch="None"
|
||||
Focusable="True"
|
||||
VerticalAlignment="Stretch"
|
||||
HorizontalAlignment="Stretch"
|
||||
Background="{DynamicResource LargeCheckerboardBrush}"
|
||||
Background="{StaticResource LargeCheckerboardBrush}"
|
||||
ZoomChanged="ZoomBorder_OnZoomChanged"
|
||||
MaxZoomX="1"
|
||||
MaxZoomY="1"
|
||||
EnableConstrains="True"
|
||||
PointerReleased="ZoomBorder_OnPointerReleased">
|
||||
<Grid Name="ContainerGrid" Background="Transparent" ClipToBounds="False">
|
||||
<Grid.ContextFlyout>
|
||||
<Flyout FlyoutPresenterClasses="node-picker-flyout">
|
||||
<ContentControl Content="{CompiledBinding NodePickerViewModel}" />
|
||||
</Flyout>
|
||||
</Grid.ContextFlyout>
|
||||
<Grid.Transitions>
|
||||
<Transitions>
|
||||
<TransformOperationsTransition Property="RenderTransform" Duration="0:0:0.2" Easing="CubicEaseOut" />
|
||||
</Transitions>
|
||||
</Grid.Transitions>
|
||||
<Grid.ContextFlyout>
|
||||
<Flyout FlyoutPresenterClasses="node-picker-flyout">
|
||||
<ContentControl Content="{CompiledBinding NodePickerViewModel}" />
|
||||
</Flyout>
|
||||
</Grid.ContextFlyout>
|
||||
<Grid.Transitions>
|
||||
<Transitions>
|
||||
<TransformOperationsTransition Property="RenderTransform" Duration="0:0:0.2" Easing="CubicEaseOut" />
|
||||
</Transitions>
|
||||
</Grid.Transitions>
|
||||
|
||||
<!-- Drag cable, if any -->
|
||||
<ContentControl Content="{CompiledBinding DragViewModel}" ClipToBounds="False"/>
|
||||
<!-- Drag cable, if any -->
|
||||
<ContentControl Content="{CompiledBinding DragViewModel}" ClipToBounds="False" />
|
||||
|
||||
<!-- Cables -->
|
||||
<ItemsControl Items="{CompiledBinding CableViewModels}" ClipToBounds="False">
|
||||
<ItemsControl Items="{CompiledBinding CableViewModels}" ClipToBounds="False">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<Canvas />
|
||||
<Canvas />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.Styles>
|
||||
<Style Selector="ItemsControl > ContentPresenter">
|
||||
<Setter Property="Canvas.Left" Value="{Binding Node.X, TargetNullValue=0}" />
|
||||
<Setter Property="Canvas.Top" Value="{Binding Node.Y, TargetNullValue=0}" />
|
||||
</Style>
|
||||
</ItemsControl.Styles>
|
||||
</ItemsControl>
|
||||
|
||||
<!-- Nodes -->
|
||||
<ItemsControl Name="NodesContainer" Items="{CompiledBinding NodeViewModels}" ClipToBounds="False">
|
||||
<ItemsControl Name="NodesContainer" Items="{CompiledBinding NodeViewModels}" ClipToBounds="False">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<Canvas />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.Styles>
|
||||
<Style Selector="ItemsControl > ContentPresenter">
|
||||
<Setter Property="Canvas.Left" Value="{Binding Node.X, TargetNullValue=0}" />
|
||||
<Setter Property="Canvas.Top" Value="{Binding Node.Y, TargetNullValue=0}" />
|
||||
<Style Selector="ItemsControl#NodesContainer > ContentPresenter">
|
||||
<Setter Property="Canvas.Left" Value="{Binding Node.X}" />
|
||||
<Setter Property="Canvas.Top" Value="{Binding Node.Y}" />
|
||||
</Style>
|
||||
</ItemsControl.Styles>
|
||||
</ItemsControl>
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
using System.Reactive.Disposables;
|
||||
using System.Threading.Tasks;
|
||||
using Artemis.Core;
|
||||
using Artemis.Core.Events;
|
||||
using Artemis.UI.Shared.Controls;
|
||||
@ -15,6 +17,8 @@ using Avalonia.Interactivity;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.ReactiveUI;
|
||||
using Avalonia.Threading;
|
||||
using DynamicData.Binding;
|
||||
using ReactiveUI;
|
||||
|
||||
namespace Artemis.UI.Screens.VisualScripting;
|
||||
@ -38,27 +42,17 @@ public class NodeScriptView : ReactiveUserControl<NodeScriptViewModel>
|
||||
UpdateZoomBorderBackground();
|
||||
|
||||
_grid.AddHandler(PointerReleasedEvent, CanvasOnPointerReleased, RoutingStrategies.Direct | RoutingStrategies.Tunnel | RoutingStrategies.Bubble, true);
|
||||
|
||||
this.WhenActivated(d =>
|
||||
{
|
||||
ViewModel!.PickerPositionSubject.Subscribe(p =>
|
||||
{
|
||||
ViewModel.NodePickerViewModel.Position = p;
|
||||
_grid?.ContextFlyout?.ShowAt(_grid, true);
|
||||
}).DisposeWith(d);
|
||||
|
||||
ViewModel!.PickerPositionSubject.Subscribe(ShowPickerAt).DisposeWith(d);
|
||||
if (ViewModel.IsPreview)
|
||||
{
|
||||
BoundsProperty.Changed.Subscribe(BoundsPropertyChanged).DisposeWith(d);
|
||||
ViewModel.NodeScript.NodeAdded += NodesChanged;
|
||||
ViewModel.NodeScript.NodeRemoved += NodesChanged;
|
||||
Disposable.Create(() =>
|
||||
{
|
||||
ViewModel.NodeScript.NodeAdded -= NodesChanged;
|
||||
ViewModel.NodeScript.NodeRemoved -= NodesChanged;
|
||||
}).DisposeWith(d);
|
||||
ViewModel.NodeViewModels.ToObservableChangeSet().Subscribe(_ => AutoFitIfPreview()).DisposeWith(d);
|
||||
}
|
||||
|
||||
AutoFit(true);
|
||||
Dispatcher.UIThread.InvokeAsync(() => AutoFit(true), DispatcherPriority.ContextIdle);
|
||||
});
|
||||
}
|
||||
|
||||
@ -68,17 +62,20 @@ public class NodeScriptView : ReactiveUserControl<NodeScriptViewModel>
|
||||
return base.MeasureOverride(availableSize);
|
||||
}
|
||||
|
||||
private void ShowPickerAt(Point point)
|
||||
{
|
||||
if (ViewModel == null)
|
||||
return;
|
||||
ViewModel.NodePickerViewModel.Position = point;
|
||||
_grid?.ContextFlyout?.ShowAt(_grid, true);
|
||||
}
|
||||
|
||||
private void AutoFitIfPreview()
|
||||
{
|
||||
if (ViewModel != null && ViewModel.IsPreview)
|
||||
AutoFit(true);
|
||||
}
|
||||
|
||||
private void NodesChanged(object? sender, SingleValueEventArgs<INode> e)
|
||||
{
|
||||
AutoFitIfPreview();
|
||||
}
|
||||
|
||||
private void BoundsPropertyChanged(AvaloniaPropertyChangedEventArgs<Rect> obj)
|
||||
{
|
||||
if (_nodesContainer.ItemContainerGenerator.Containers.Select(c => c.ContainerControl).Contains(obj.Sender))
|
||||
@ -102,8 +99,8 @@ public class NodeScriptView : ReactiveUserControl<NodeScriptViewModel>
|
||||
double bottom = _nodesContainer.ItemContainerGenerator.Containers.Select(c => c.ContainerControl.Bounds.Bottom).Max();
|
||||
double right = _nodesContainer.ItemContainerGenerator.Containers.Select(c => c.ContainerControl.Bounds.Right).Max();
|
||||
|
||||
// Add a 5 pixel margin around the rect
|
||||
Rect scriptRect = new(new Point(left - 5, top - 5), new Point(right + 5, bottom + 5));
|
||||
// Add a 10 pixel margin around the rect
|
||||
Rect scriptRect = new(new Point(left - 10, top - 10), new Point(right + 10, bottom + 10));
|
||||
|
||||
// The scale depends on the available space
|
||||
double scale = Math.Min(1, Math.Min(Bounds.Width / scriptRect.Width, Bounds.Height / scriptRect.Height));
|
||||
|
||||
@ -63,7 +63,10 @@
|
||||
<ItemsControl Items="{CompiledBinding InputPinCollectionViewModels}" />
|
||||
</StackPanel>
|
||||
|
||||
<ContentControl Grid.Column="1" Name="CustomViewModelContainer" Content="{CompiledBinding CustomNodeViewModel}" IsVisible="{CompiledBinding CustomNodeViewModel}" />
|
||||
<ContentControl Grid.Column="1"
|
||||
Name="CustomViewModelContainer"
|
||||
Content="{CompiledBinding CustomNodeViewModel}"
|
||||
IsVisible="{CompiledBinding CustomNodeViewModel, Converter={x:Static ObjectConverters.IsNotNull}}" />
|
||||
|
||||
<StackPanel Grid.Column="2" IsVisible="{CompiledBinding HasOutputPins}">
|
||||
<ItemsControl Items="{CompiledBinding OutputPinViewModels}" Margin="4 0" />
|
||||
|
||||
@ -2,7 +2,10 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Mixins;
|
||||
using Avalonia.Controls.Presenters;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.LogicalTree;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.ReactiveUI;
|
||||
using Avalonia.VisualTree;
|
||||
|
||||
@ -35,8 +35,8 @@ public class NodeViewModel : ActivatableViewModelBase
|
||||
|
||||
public NodeViewModel(NodeScriptViewModel nodeScriptViewModel, INode node, INodeVmFactory nodeVmFactory, INodeEditorService nodeEditorService)
|
||||
{
|
||||
NodeScriptViewModel = nodeScriptViewModel;
|
||||
_nodeEditorService = nodeEditorService;
|
||||
NodeScriptViewModel = nodeScriptViewModel;
|
||||
Node = node;
|
||||
|
||||
DeleteNode = ReactiveCommand.Create(ExecuteDeleteNode, this.WhenAnyValue(vm => vm.IsStaticNode).Select(v => !v));
|
||||
|
||||
@ -3,28 +3,22 @@
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:pins="clr-namespace:Artemis.UI.Screens.VisualScripting.Pins"
|
||||
xmlns:converters="clr-namespace:Artemis.UI.Converters"
|
||||
mc:Ignorable="d"
|
||||
d:DesignWidth="200"
|
||||
x:Class="Artemis.UI.Screens.VisualScripting.Pins.InputPinView"
|
||||
x:DataType="pins:PinViewModel">
|
||||
<UserControl.Resources>
|
||||
<converters:ColorToSolidColorBrushConverter x:Key="ColorToSolidColorBrushConverter" />
|
||||
</UserControl.Resources>
|
||||
<UserControl.Styles>
|
||||
<StyleInclude Source="/Screens/VisualScripting/VisualScripting.axaml" />
|
||||
<Style Selector="StackPanel#PinContainer Border#VisualPinPoint">
|
||||
<Setter Property="Background">
|
||||
<Setter.Value>
|
||||
<SolidColorBrush Color="{CompiledBinding DarkenedPinColor}"></SolidColorBrush>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
<Setter Property="BorderBrush">
|
||||
<Setter.Value>
|
||||
<SolidColorBrush Color="{CompiledBinding PinColor}"></SolidColorBrush>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</UserControl.Styles>
|
||||
<StackPanel Name="PinContainer" Orientation="Horizontal" Spacing="6">
|
||||
<Border Name="PinPoint">
|
||||
<Border Name="VisualPinPoint" />
|
||||
<Border Name="VisualPinPoint"
|
||||
BorderBrush="{CompiledBinding PinColor, Converter={StaticResource ColorToSolidColorBrushConverter}}"
|
||||
Background="{CompiledBinding DarkenedPinColor, Converter={StaticResource ColorToSolidColorBrushConverter}}"/>
|
||||
</Border>
|
||||
<TextBlock Name="PinName" VerticalAlignment="Center" Text="{CompiledBinding Pin.Name}" />
|
||||
</StackPanel>
|
||||
|
||||
@ -3,29 +3,23 @@
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:pins="clr-namespace:Artemis.UI.Screens.VisualScripting.Pins"
|
||||
xmlns:converters="clr-namespace:Artemis.UI.Converters"
|
||||
mc:Ignorable="d"
|
||||
d:DesignWidth="200"
|
||||
x:Class="Artemis.UI.Screens.VisualScripting.Pins.OutputPinView"
|
||||
x:DataType="pins:PinViewModel">
|
||||
<UserControl.Resources>
|
||||
<converters:ColorToSolidColorBrushConverter x:Key="ColorToSolidColorBrushConverter" />
|
||||
</UserControl.Resources>
|
||||
<UserControl.Styles>
|
||||
<StyleInclude Source="/Screens/VisualScripting/VisualScripting.axaml" />
|
||||
<Style Selector="StackPanel#PinContainer Border#VisualPinPoint">
|
||||
<Setter Property="Background">
|
||||
<Setter.Value>
|
||||
<SolidColorBrush Color="{CompiledBinding DarkenedPinColor}" />
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
<Setter Property="BorderBrush">
|
||||
<Setter.Value>
|
||||
<SolidColorBrush Color="{CompiledBinding PinColor}" />
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</UserControl.Styles>
|
||||
<StackPanel Name="PinContainer" Orientation="Horizontal" Spacing="6">
|
||||
<TextBlock Name="PinName" VerticalAlignment="Center" Text="{CompiledBinding Pin.Name}" />
|
||||
<Border Name="PinPoint">
|
||||
<Border Name="VisualPinPoint" />
|
||||
<Border Name="VisualPinPoint"
|
||||
BorderBrush="{CompiledBinding PinColor, Converter={StaticResource ColorToSolidColorBrushConverter}}"
|
||||
Background="{CompiledBinding DarkenedPinColor, Converter={StaticResource ColorToSolidColorBrushConverter}}"/>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
@ -23,7 +23,11 @@ public class ViewLocator : IDataTemplate
|
||||
throw new ArtemisUIException($"The views of activatable view models should inherit ReactiveUserControl<T>, in this case ReactiveUserControl<{data.GetType().Name}>.");
|
||||
|
||||
if (type != null)
|
||||
{
|
||||
Debug.WriteLine("[ViewLocator] Creating instance of '{0}'", type);
|
||||
return (Control) Activator.CreateInstance(type)!;
|
||||
}
|
||||
|
||||
return new TextBlock {Text = "Not Found: " + name};
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user