UI - Moved exception viewer to its own seperate window

Conditions - Started adding list conditions
This commit is contained in:
Robert committed 2020-08-11 17:27:11 +02:00
1 parent 930a7b4ef7
commit 6803bc5a37
36 files changed
+930 -471

No files matched your search

@@ -19,19 +19,9 @@
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<Button Style="{StaticResource MaterialDesignFlatButton}" IsCancel="True" Margin="0 8 8 0" Command="{s:Action Cancel}">
<Button.CommandParameter>
<system:Boolean xmlns:system="clr-namespace:System;assembly=mscorlib">
False
</system:Boolean>
</Button.CommandParameter>
CANCEL
</Button>
<Button Style="{StaticResource MaterialDesignFlatButton}" IsDefault="True" Margin="0 8 8 0" Command="{s:Action Accept}">
<Button.CommandParameter>
<system:Boolean xmlns:system="clr-namespace:System;assembly=mscorlib">
True
</system:Boolean>
</Button.CommandParameter>
ACCEPT
</Button>
</StackPanel>
@@ -0,0 +1,40 @@
<UserControl x:Class="Artemis.UI.Screens.Module.ProfileEditor.Dialogs.ProfileExportView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Artemis.UI.Screens.Module.ProfileEditor.Dialogs"
xmlns:s="https://github.com/canton7/Stylet"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid Margin="16" Width="500">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock Style="{StaticResource MaterialDesignHeadline6TextBlock}" Grid.Row="0">
Export current profile
</TextBlock>
<TextBlock Margin="0 10" TextAlignment="Justify" TextWrapping="Wrap" Grid.Row="1">
Please note that exporting profiles like this is placeholder functionality. The idea is that this will eventually happen via the workshop.
</TextBlock>
<TextBlock Margin="0 10" TextAlignment="Justify" TextWrapping="Wrap" Grid.Row="2">
The workshop will include tools to make profiles convert easily and look good on different layouts.
That means right now when someone imports this export unless they have the exact same setup as
you, they'll have to select LEDs for each layer in the profile.
</TextBlock>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Grid.Row="3">
<Button Style="{StaticResource MaterialDesignFlatButton}" IsCancel="True" Margin="0 8 8 0" Command="{s:Action Cancel}">
CANCEL
</Button>
<Button Style="{StaticResource MaterialDesignFlatButton}" IsDefault="True" Margin="0 8 0 0" Command="{s:Action Accept}">
I UNDERSTAND, EXPORT
</Button>
</StackPanel>
</Grid>
</UserControl>
@@ -0,0 +1,39 @@
using System.Windows;
using Artemis.Core.Models.Profile;
using Artemis.Core.Services.Storage.Interfaces;
using Artemis.UI.Shared.Services.Dialog;
using MaterialDesignThemes.Wpf;
namespace Artemis.UI.Screens.Module.ProfileEditor.Dialogs
{
public class ProfileExportViewModel : DialogViewModelBase
{
private readonly ISnackbarMessageQueue _mainMessageQueue;
private readonly IProfileService _profileService;
public ProfileExportViewModel(ProfileDescriptor profileDescriptor, IProfileService profileService, ISnackbarMessageQueue mainMessageQueue)
{
ProfileDescriptor = profileDescriptor;
_profileService = profileService;
_mainMessageQueue = mainMessageQueue;
}
public ProfileDescriptor ProfileDescriptor { get; }
public void Accept()
{
var encoded = _profileService.ExportProfile(ProfileDescriptor);
Clipboard.SetText(encoded);
_mainMessageQueue.Enqueue("Profile contents exported to clipboard.");
Session.Close();
}
public void Cancel()
{
Session.Close();
}
}
}
@@ -0,0 +1,51 @@
<UserControl x:Class="Artemis.UI.Screens.Module.ProfileEditor.Dialogs.ProfileImportView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Artemis.UI.Screens.Module.ProfileEditor.Dialogs"
xmlns:s="https://github.com/canton7/Stylet"
xmlns:avalonedit="http://icsharpcode.net/sharpdevelop/avalonedit"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid Margin="16" Width="800">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock Style="{StaticResource MaterialDesignHeadline6TextBlock}" Grid.Row="0">
Import profile to current module
</TextBlock>
<TextBlock Margin="0 10" TextAlignment="Justify" TextWrapping="Wrap" Grid.Row="1">
Please note that importing profiles like this is placeholder functionality. The idea is that this will eventually happen via the workshop.
</TextBlock>
<TextBlock Margin="0 10" TextAlignment="Justify" TextWrapping="Wrap" Grid.Row="2">
The workshop will include tools to make profiles convert easily and look good on different layouts.
That means right now when you import this profile unless you have the exact same setup as
the person who exported it, you'll have to select LEDs for each layer in the profile.
</TextBlock>
<avalonedit:TextEditor Grid.Row="3" SyntaxHighlighting="JavaScript"
FontFamily="pack://application:,,,/Resources/Fonts/#Roboto Mono"
FontSize="10pt"
Document="{Binding Document}"
HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Auto"
Height="500"
Padding="10" />
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Grid.Row="4">
<Button Style="{StaticResource MaterialDesignFlatButton}" IsCancel="True" Margin="0 8 8 0" Command="{s:Action Cancel}">
CANCEL
</Button>
<Button Style="{StaticResource MaterialDesignFlatButton}" IsDefault="True" Margin="0 8 0 0" Command="{s:Action Accept}">
I UNDERSTAND, IMPORT
</Button>
</StackPanel>
</Grid>
</UserControl>
@@ -0,0 +1,47 @@
using System.Windows;
using Artemis.Core.Models.Profile;
using Artemis.Core.Plugins.Abstract;
using Artemis.Core.Services.Storage.Interfaces;
using Artemis.UI.Shared.Services.Dialog;
using ICSharpCode.AvalonEdit.Document;
using MaterialDesignThemes.Wpf;
namespace Artemis.UI.Screens.Module.ProfileEditor.Dialogs
{
public class ProfileImportViewModel : DialogViewModelBase
{
private readonly ISnackbarMessageQueue _mainMessageQueue;
private readonly IProfileService _profileService;
private string _profileJson;
public ProfileImportViewModel(ProfileModule profileModule, IProfileService profileService, ISnackbarMessageQueue mainMessageQueue)
{
ProfileModule = profileModule;
Document = new TextDocument();
_profileService = profileService;
_mainMessageQueue = mainMessageQueue;
}
public ProfileModule ProfileModule { get; }
public TextDocument Document { get; set; }
public string ProfileJson
{
get => _profileJson;
set => SetAndNotify(ref _profileJson, value);
}
public void Accept()
{
_profileService.ImportProfile(Document.Text, ProfileModule);
_mainMessageQueue.Enqueue("Profile imported.");
Session.Close();
}
public void Cancel()
{
Session.Close();
}
}
}
@@ -97,6 +97,14 @@
<materialDesign:PackIcon Kind="InsertLink" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Add list condition"
ToolTip="A condition that evaluates on items in a list"
Command="{s:Action AddCondition}"
CommandParameter="List">
<MenuItem.Icon>
<materialDesign:PackIcon Kind="FormatListBulleted" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Add group" ToolTip="A group can contain conditions and other groups" Command="{s:Action AddGroup}">
<MenuItem.Icon>
<materialDesign:PackIcon Kind="CodeParentheses" />
@@ -66,6 +66,8 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.DisplayConditions
DisplayConditionGroup.AddChild(new DisplayConditionPredicate(DisplayConditionGroup, PredicateType.Static));
else if (type == "Dynamic")
DisplayConditionGroup.AddChild(new DisplayConditionPredicate(DisplayConditionGroup, PredicateType.Dynamic));
else if (type == "List")
DisplayConditionGroup.AddChild(new DisplayConditionListPredicate(DisplayConditionGroup));
Update();
_profileEditorService.UpdateSelectedProfileElement();
@@ -4,10 +4,146 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Artemis.UI.Screens.Module.ProfileEditor.DisplayConditions"
xmlns:converters="clr-namespace:Artemis.UI.Converters"
xmlns:utilities="clr-namespace:Artemis.UI.Utilities"
xmlns:s="https://github.com/canton7/Stylet"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
d:DataContext="{d:DesignInstance Type=local:DisplayConditionListPredicateViewModel, IsDesignTimeCreatable=False}">
<Grid>
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary>
<converters:NullToVisibilityConverter x:Key="NullToVisibilityConverter" />
<utilities:BindingProxy x:Key="DataContextProxy" Data="{Binding}" />
</ResourceDictionary>
<ResourceDictionary Source="pack://application:,,,/Artemis.UI;component/ResourceDictionaries/DisplayConditions.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<Grid Margin="0 3" Visibility="{Binding IsInitialized, Converter={x:Static s:BoolToVisibilityConverter.Instance}, Mode=OneWay}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Button Grid.Row="0"
Grid.Column="0"
Style="{StaticResource MaterialDesignIconForegroundButton}"
HorizontalAlignment="Left"
Foreground="#E74C4C"
Width="25"
Height="25"
Command="{s:Action Delete}">
<materialDesign:PackIcon Kind="Close" Width="18" Height="18" />
</Button>
<!-- Left side, the list this predicate is targeting -->
<Button Grid.Row="0"
Grid.Column="1"
Background="#ab47bc"
BorderBrush="#ab47bc"
Style="{StaticResource DisplayConditionButton}"
ToolTip="{Binding SelectedListProperty.DisplayPropertyPath}"
Click="PropertyButton_OnClick">
<Button.ContextMenu>
<ContextMenu ItemsSource="{Binding TargetDataModel.Children}" IsOpen="{Binding TargetDataModelOpen, Mode=OneWayToSource}">
<ContextMenu.ItemContainerStyle>
<Style TargetType="{x:Type MenuItem}" BasedOn="{StaticResource MaterialDesignMenuItem}">
<Setter Property="ItemsSource" Value="{Binding Children}" />
<Setter Property="Command" Value="{Binding Data.SelectListPropertyCommand, Source={StaticResource DataContextProxy}}" />
<Setter Property="CommandParameter" Value="{Binding}" />
<Setter Property="CommandTarget" Value="{Binding}" />
<Setter Property="IsEnabled" Value="{Binding IsMatchingFilteredTypes}" />
<Setter Property="IsSubmenuOpen" Value="{Binding IsVisualizationExpanded, Mode=TwoWay}" />
<Setter Property="HeaderTemplate" Value="{StaticResource DataModelSelectionTemplate}" />
</Style>
</ContextMenu.ItemContainerStyle>
</ContextMenu>
</Button.ContextMenu>
<Grid>
<TextBlock Text="{Binding SelectedListProperty.PropertyDescription.Name}"
Visibility="{Binding SelectedListProperty, Converter={StaticResource NullToVisibilityConverter}}" />
<TextBlock Text="« Select a list »"
FontStyle="Italic"
Visibility="{Binding SelectedListProperty, Converter={StaticResource NullToVisibilityConverter}, ConverterParameter=Inverted}" />
</Grid>
</Button>
<!-- Operator -->
<Button Grid.Row="0"
Grid.Column="2"
Style="{StaticResource DisplayConditionButtonLeftClickMenu}"
Background="#7B7B7B"
BorderBrush="#7B7B7B"
Content="{Binding SelectedListOperator}"
Click="PropertyButton_OnClick">
<Button.ContextMenu>
<ContextMenu>
<MenuItem Header="Any" Command="{s:Action SelectListOperator}" CommandParameter="Any" />
<MenuItem Header="All" Command="{s:Action SelectListOperator}" CommandParameter="All" />
<MenuItem Header="None" Command="{s:Action SelectListOperator}" CommandParameter="None" />
<MenuItem Header="Count (NYI)" Command="{s:Action SelectListOperator}" CommandParameter="Count" IsEnabled="False"/>
</ContextMenu>
</Button.ContextMenu>
</Button>
<Button x:Name="AddChildButton"
Grid.Row="0"
Grid.Column="3"
HorizontalAlignment="Left"
Foreground="#4CE758"
Width="25"
Height="25">
<Button.Style>
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource MaterialDesignIconForegroundButton}">
<Style.Triggers>
<EventTrigger RoutedEvent="Click">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="ContextMenu.IsOpen">
<DiscreteBooleanKeyFrame KeyTime="0:0:0" Value="True" />
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Style.Triggers>
</Style>
</Button.Style>
<materialDesign:PackIcon Kind="Add" Width="18" Height="18" />
<Button.ContextMenu>
<ContextMenu>
<MenuItem Header="Add static condition"
ToolTip="A condition that compares a data model property to a static input"
Command="{s:Action AddCondition}"
CommandParameter="Static">
<MenuItem.Icon>
<materialDesign:PackIcon Kind="FormTextarea" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Add dynamic condition"
ToolTip="A condition that compares two data model properties"
Command="{s:Action AddCondition}"
CommandParameter="Dynamic">
<MenuItem.Icon>
<materialDesign:PackIcon Kind="InsertLink" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Add group" ToolTip="A group can contain conditions and other groups" Command="{s:Action AddGroup}">
<MenuItem.Icon>
<materialDesign:PackIcon Kind="CodeParentheses" />
</MenuItem.Icon>
</MenuItem>
</ContextMenu>
</Button.ContextMenu>
</Button>
</Grid>
</UserControl>
</UserControl>
@@ -0,0 +1,26 @@
using System.Windows;
using System.Windows.Controls;
namespace Artemis.UI.Screens.Module.ProfileEditor.DisplayConditions
{
/// <summary>
/// Interaction logic for DisplayConditionListPredicateView.xaml
/// </summary>
public partial class DisplayConditionListPredicateView : UserControl
{
public DisplayConditionListPredicateView()
{
InitializeComponent();
}
private void PropertyButton_OnClick(object sender, RoutedEventArgs e)
{
// DataContext is not set when using left button, I don't know why but there it is
if (sender is Button button && button.ContextMenu != null)
{
button.ContextMenu.DataContext = button.DataContext;
button.ContextMenu.IsOpen = true;
}
}
}
}
@@ -1,18 +1,206 @@
using Artemis.Core.Models.Profile.Conditions;
using System;
using System.Collections;
using System.Linq;
using System.Threading.Tasks;
using System.Timers;
using Artemis.Core.Models.Profile.Conditions;
using Artemis.Core.Plugins.Models;
using Artemis.Core.Services;
using Artemis.UI.Ninject.Factories;
using Artemis.UI.Screens.Module.ProfileEditor.DisplayConditions.Abstract;
using Artemis.UI.Shared.DataModelVisualization.Shared;
using Artemis.UI.Shared.Services;
using Artemis.UI.Shared.Services.Interfaces;
using Artemis.UI.Utilities;
using Humanizer;
namespace Artemis.UI.Screens.Module.ProfileEditor.DisplayConditions
{
public class DisplayConditionListPredicateViewModel : DisplayConditionViewModel
{
public DisplayConditionListPredicateViewModel(DisplayConditionListPredicate displayConditionListPredicate, DisplayConditionViewModel parent) : base(displayConditionListPredicate, parent)
private readonly IProfileEditorService _profileEditorService;
private readonly IDataModelVisualizationService _dataModelVisualizationService;
private readonly IDisplayConditionsVmFactory _displayConditionsVmFactory;
private bool _isInitialized;
private DataModelVisualizationViewModel _selectedListProperty;
private DataModelPropertiesViewModel _targetDataModel;
private readonly Timer _updateTimer;
public DisplayConditionListPredicateViewModel(
DisplayConditionListPredicate displayConditionListPredicate,
DisplayConditionViewModel parent,
IProfileEditorService profileEditorService,
IDataModelVisualizationService dataModelVisualizationService,
IDisplayConditionsVmFactory displayConditionsVmFactory,
ISettingsService settingsService) : base(displayConditionListPredicate, parent)
{
_profileEditorService = profileEditorService;
_dataModelVisualizationService = dataModelVisualizationService;
_displayConditionsVmFactory = displayConditionsVmFactory;
_updateTimer = new Timer(500);
SelectListPropertyCommand = new DelegateCommand(ExecuteSelectListProperty);
ShowDataModelValues = settingsService.GetSetting<bool>("ProfileEditor.ShowDataModelValues");
// Initialize async, no need to wait for it
Task.Run(Initialize);
}
public DelegateCommand SelectListPropertyCommand { get; }
public PluginSetting<bool> ShowDataModelValues { get; }
public DisplayConditionListPredicate DisplayConditionListPredicate => (DisplayConditionListPredicate) Model;
public bool IsInitialized
{
get => _isInitialized;
set => SetAndNotify(ref _isInitialized, value);
}
public bool TargetDataModelOpen { get; set; }
public DataModelPropertiesViewModel TargetDataModel
{
get => _targetDataModel;
set => SetAndNotify(ref _targetDataModel, value);
}
public DataModelVisualizationViewModel SelectedListProperty
{
get => _selectedListProperty;
set => SetAndNotify(ref _selectedListProperty, value);
}
public string SelectedListOperator => DisplayConditionListPredicate.ListOperator.Humanize();
public void SelectListOperator(string type)
{
var enumValue = Enum.Parse<ListOperator>(type);
DisplayConditionListPredicate.ListOperator = enumValue;
NotifyOfPropertyChange(nameof(SelectedListOperator));
}
public void AddCondition(string type)
{
if (type == "Static")
DisplayConditionListPredicate.AddChild(new DisplayConditionPredicate(DisplayConditionListPredicate, PredicateType.Static));
else if (type == "Dynamic")
DisplayConditionListPredicate.AddChild(new DisplayConditionPredicate(DisplayConditionListPredicate, PredicateType.Dynamic));
Update();
_profileEditorService.UpdateSelectedProfileElement();
}
public void AddGroup()
{
DisplayConditionListPredicate.AddChild(new DisplayConditionGroup(DisplayConditionListPredicate));
Update();
_profileEditorService.UpdateSelectedProfileElement();
}
public override void Delete()
{
base.Delete();
_profileEditorService.UpdateSelectedProfileElement();
}
public void Initialize()
{
// Get the data models
TargetDataModel = _dataModelVisualizationService.GetMainDataModelVisualization();
if (!_dataModelVisualizationService.GetPluginExtendsDataModel(_profileEditorService.GetCurrentModule()))
TargetDataModel.Children.Add(_dataModelVisualizationService.GetPluginDataModelVisualization(_profileEditorService.GetCurrentModule()));
TargetDataModel.UpdateRequested += TargetDataModelUpdateRequested;
Update();
_updateTimer.Start();
_updateTimer.Elapsed += OnUpdateTimerOnElapsed;
IsInitialized = true;
}
protected override void Dispose(bool disposing)
{
_updateTimer.Stop();
_updateTimer.Elapsed -= OnUpdateTimerOnElapsed;
}
private void OnUpdateTimerOnElapsed(object sender, ElapsedEventArgs e)
{
if (TargetDataModelOpen)
TargetDataModel.Update(_dataModelVisualizationService);
}
private void TargetDataModelUpdateRequested(object sender, EventArgs e)
{
TargetDataModel.ApplyTypeFilter(true, typeof(IEnumerable));
}
public void ApplyList()
{
DisplayConditionListPredicate.UpdateList(SelectedListProperty.DataModel, SelectedListProperty.PropertyPath);
_profileEditorService.UpdateSelectedProfileElement();
Update();
}
public override void Update()
{
if (TargetDataModel == null)
return;
NotifyOfPropertyChange(nameof(SelectedListOperator));
// Update the selected list property
if (DisplayConditionListPredicate.ListDataModel != null && DisplayConditionListPredicate.ListPropertyPath != null)
SelectedListProperty = TargetDataModel.GetChildByPath(DisplayConditionListPredicate.ListDataModel.PluginInfo.Guid, DisplayConditionListPredicate.ListPropertyPath);
// Ensure filtering is applied to include Enumerables only
TargetDataModel.ApplyTypeFilter(true, typeof(IEnumerable));
// Remove VMs of effects no longer applied on the layer
var toRemove = Children.Where(c => !DisplayConditionListPredicate.Children.Contains(c.Model)).ToList();
// Using RemoveRange breaks our lovely animations
foreach (var displayConditionViewModel in toRemove)
{
Children.Remove(displayConditionViewModel);
displayConditionViewModel.Dispose();
}
foreach (var childModel in Model.Children)
{
if (Children.Any(c => c.Model == childModel))
continue;
switch (childModel)
{
case DisplayConditionGroup displayConditionGroup:
Children.Add(_displayConditionsVmFactory.DisplayConditionGroupViewModel(displayConditionGroup, this));
break;
case DisplayConditionListPredicate displayConditionListPredicate:
Children.Add(_displayConditionsVmFactory.DisplayConditionListPredicateViewModel(displayConditionListPredicate, this));
break;
case DisplayConditionPredicate displayConditionPredicate:
Children.Add(_displayConditionsVmFactory.DisplayConditionPredicateViewModel(displayConditionPredicate, this));
break;
}
}
foreach (var childViewModel in Children)
childViewModel.Update();
}
private void ExecuteSelectListProperty(object context)
{
if (!(context is DataModelVisualizationViewModel dataModelVisualizationViewModel))
return;
SelectedListProperty = dataModelVisualizationViewModel;
ApplyList();
}
}
}
@@ -21,47 +21,6 @@
<ResourceDictionary>
<converters:NullToVisibilityConverter x:Key="NullToVisibilityConverter" />
<utilities:BindingProxy x:Key="DataContextProxy" Data="{Binding}" />
<DataTemplate x:Key="DataModelSelectionTemplate">
<StackPanel>
<StackPanel.Resources>
<DataTemplate DataType="{x:Type dataModel:DataModelPropertiesViewModel}">
<TextBlock Text="{Binding PropertyDescription.Name}" ToolTip="{Binding PropertyDescription.Description}" />
</DataTemplate>
<DataTemplate DataType="{x:Type dataModel:DataModelPropertyViewModel}">
<Grid ToolTip="{Binding PropertyDescription.Description}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<!-- Value description -->
<TextBlock Grid.Column="0" Text="{Binding PropertyDescription.Name}" ToolTip="{Binding PropertyDescription.Description}" />
<!-- Value display -->
<StackPanel Grid.Column="1" Visibility="{Binding Data.ShowDataModelValues.Value, Converter={x:Static s:BoolToVisibilityConverter.Instance}, Mode=OneWay, Source={StaticResource DataContextProxy}}">
<TextBlock Text="{Binding DisplayValue, Mode=OneWay}"
FontFamily="Consolas"
HorizontalAlignment="Right"
Visibility="{Binding ShowToString, Converter={x:Static s:BoolToVisibilityConverter.Instance}, Mode=OneWay}"
Margin="15 0.5 0 0" />
<TextBlock Text="null"
FontFamily="Consolas"
HorizontalAlignment="Right"
Foreground="{DynamicResource MaterialDesignCheckBoxDisabled}"
Margin="15 0.5 0 0"
Visibility="{Binding ShowNull, Converter={x:Static s:BoolToVisibilityConverter.Instance}, Mode=OneWay}" />
<ContentControl s:View.Model="{Binding DisplayViewModel}"
FontFamily="Consolas"
Margin="15 0.5 0 0"
Visibility="{Binding ShowViewModel, Converter={x:Static s:BoolToVisibilityConverter.Instance}, Mode=OneWay}" />
</StackPanel>
</Grid>
</DataTemplate>
</StackPanel.Resources>
<ContentPresenter Content="{Binding}" />
</StackPanel>
</DataTemplate>
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
@@ -40,9 +40,14 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.DisplayConditions
private List<Type> _supportedInputTypes;
private readonly Timer _updateTimer;
public DisplayConditionPredicateViewModel(DisplayConditionPredicate displayConditionPredicate, DisplayConditionViewModel parent, IProfileEditorService profileEditorService,
IDataModelVisualizationService dataModelVisualizationService, IDataModelService dataModelService, ISettingsService settingsService, IEventAggregator eventAggregator)
: base(displayConditionPredicate, parent)
public DisplayConditionPredicateViewModel(
DisplayConditionPredicate displayConditionPredicate,
DisplayConditionViewModel parent,
IProfileEditorService profileEditorService,
IDataModelVisualizationService dataModelVisualizationService,
IDataModelService dataModelService,
ISettingsService settingsService,
IEventAggregator eventAggregator) : base(displayConditionPredicate, parent)
{
_profileEditorService = profileEditorService;
_dataModelVisualizationService = dataModelVisualizationService;
@@ -135,9 +135,7 @@
VerticalScrollBarVisibility="Hidden"
ScrollChanged="TimelineScrollChanged">
<Border BorderThickness="0,0,1,0" BorderBrush="{DynamicResource MaterialDesignDivider}">
<Grid>
<ContentControl s:View.Model="{Binding TreeViewModel}" />
</Grid>
<ContentControl s:View.Model="{Binding TreeViewModel}" />
</Border>
</ScrollViewer>
<materialDesign:TransitionerSlide>
@@ -212,7 +210,8 @@
</ScrollViewer>
<!-- Timeline rails -->
<ScrollViewer x:Name="TimelineRailsScrollViewer" Grid.Row="1" Style="{StaticResource SvStyle}" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" ScrollChanged="TimelineScrollChanged">
<ScrollViewer x:Name="TimelineRailsScrollViewer" Grid.Row="1" Style="{StaticResource SvStyle}" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto"
ScrollChanged="TimelineScrollChanged">
<Grid Background="{DynamicResource MaterialDesignToolBarBackground}">
<Canvas Grid.Column="0" Panel.ZIndex="1">
<Line Canvas.Left="{Binding TimeCaretPosition}"
@@ -28,7 +28,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Tree
public LayerPropertyGroupViewModel LayerPropertyGroupViewModel { get; }
public async void OpenBrushSettings()
public void OpenBrushSettings()
{
try
{
@@ -38,12 +38,12 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Tree
}
catch (Exception e)
{
await _dialogService.ShowExceptionDialog("An exception occured while trying to show the brush's settings window", e);
_dialogService.ShowExceptionDialog("An exception occured while trying to show the brush's settings window", e);
throw;
}
}
public async void OpenEffectSettings()
public void OpenEffectSettings()
{
try
{
@@ -53,7 +53,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Tree
}
catch (Exception e)
{
await _dialogService.ShowExceptionDialog("An exception occured while trying to show the effect's settings window", e);
_dialogService.ShowExceptionDialog("An exception occured while trying to show the effect's settings window", e);
throw;
}
}
@@ -131,11 +131,13 @@
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<ComboBox Height="26"
VerticalAlignment="Top"
ItemsSource="{Binding Profiles}"
SelectedItem="{Binding SelectedProfile}"
SelectedItem="{Binding SelectedProfile}"
ItemTemplate="{StaticResource ProfileDescriptorTemplate}">
<ComboBox.ItemsPanel>
<ItemsPanelTemplate>
@@ -144,7 +146,7 @@
</ComboBox.ItemsPanel>
</ComboBox>
<Button Style="{StaticResource MaterialDesignFloatingActionMiniButton}"
Margin="10 0"
Margin="5 0"
Grid.Column="1"
Width="26"
Height="26"
@@ -153,6 +155,7 @@
<materialDesign:PackIcon Kind="Add" Height="14" Width="14" />
</Button>
<Button Style="{StaticResource MaterialDesignFloatingActionMiniDarkButton}"
Margin="5 0"
Grid.Column="2"
Width="26"
Height="26"
@@ -160,6 +163,24 @@
Command="{s:Action DeleteActiveProfile}">
<materialDesign:PackIcon Kind="TrashCanOutline" Height="14" Width="14" />
</Button>
<Button Style="{StaticResource MaterialDesignFloatingActionMiniButton}"
Margin="5 0"
Grid.Column="3"
Width="26"
Height="26"
VerticalAlignment="Top"
Command="{s:Action ExportActiveProfile}">
<materialDesign:PackIcon Kind="Export" Height="14" Width="14" />
</Button>
<Button Style="{StaticResource MaterialDesignFloatingActionMiniButton}"
Margin="5 0 0 0"
Grid.Column="4"
Width="26"
Height="26"
VerticalAlignment="Top"
Command="{s:Action ImportProfile}">
<materialDesign:PackIcon Kind="Import" Height="14" Width="14" />
</Button>
</Grid>
<!-- Profile elements -->
@@ -174,6 +174,22 @@ namespace Artemis.UI.Screens.Module.ProfileEditor
RemoveProfile(SelectedProfile);
}
public async Task ExportActiveProfile()
{
await DialogService.ShowDialog<ProfileExportViewModel>(new Dictionary<string, object>
{
{"profileDescriptor", SelectedProfile}
});
}
public async Task ImportProfile()
{
await DialogService.ShowDialog<ProfileImportViewModel>(new Dictionary<string, object>
{
{"profileModule", Module}
});
}
public void Undo()
{
// Expanded status is also undone because undoing works a bit crude, that's annoying
@@ -292,7 +308,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor
SelectedProfile = lastActiveProfile;
return;
}
// Create a default profile if there is none
var defaultProfile = _profileService.CreateProfileDescriptor(Module, "Default");
Profiles.Add(defaultProfile);
@@ -52,7 +52,7 @@ namespace Artemis.UI.Screens.Settings.Debug
_deviceService.IdentifyDevice(Device);
}
public async void OpenPluginDirectory()
public void OpenPluginDirectory()
{
try
{
@@ -60,11 +60,11 @@ namespace Artemis.UI.Screens.Settings.Debug
}
catch (Exception e)
{
await _dialogService.ShowExceptionDialog("Welp, we couldn't open the device's plugin folder for you", e);
_dialogService.ShowExceptionDialog("Welp, we couldn't open the device's plugin folder for you", e);
}
}
public async void OpenImageDirectory()
public void OpenImageDirectory()
{
if (!CanOpenImageDirectory)
return;
@@ -75,7 +75,7 @@ namespace Artemis.UI.Screens.Settings.Debug
}
catch (Exception e)
{
await _dialogService.ShowExceptionDialog("Welp, we couldn't open the device's image folder for you", e);
_dialogService.ShowExceptionDialog("Welp, we couldn't open the device's image folder for you", e);
}
}
@@ -196,7 +196,7 @@ namespace Artemis.UI.Screens.Settings
_debugService.ShowDebugger();
}
public async Task ShowLogsFolder()
public void ShowLogsFolder()
{
try
{
@@ -204,11 +204,11 @@ namespace Artemis.UI.Screens.Settings
}
catch (Exception e)
{
await _dialogService.ShowExceptionDialog("Welp, we couldn\'t open the logs folder for you", e);
_dialogService.ShowExceptionDialog("Welp, we couldn\'t open the logs folder for you", e);
}
}
public async Task ShowDataFolder()
public void ShowDataFolder()
{
try
{
@@ -216,7 +216,7 @@ namespace Artemis.UI.Screens.Settings
}
catch (Exception e)
{
await _dialogService.ShowExceptionDialog("Welp, we couldn\'t open the data folder for you", e);
_dialogService.ShowExceptionDialog("Welp, we couldn\'t open the data folder for you", e);
}
}
@@ -240,7 +240,7 @@ namespace Artemis.UI.Screens.Settings
base.OnClose();
}
private async Task ApplyAutorun()
private void ApplyAutorun()
{
try
{
@@ -254,7 +254,7 @@ namespace Artemis.UI.Screens.Settings
}
catch (Exception e)
{
await _dialogService.ShowExceptionDialog("An exception occured while trying to apply the auto run setting", e);
_dialogService.ShowExceptionDialog("An exception occured while trying to apply the auto run setting", e);
throw;
}
}
@@ -57,7 +57,7 @@ namespace Artemis.UI.Screens.Settings.Tabs.Devices
_windowManager.ShowWindow(_deviceDebugVmFactory.Create(Device));
}
public async void OpenPluginDirectory()
public void OpenPluginDirectory()
{
try
{
@@ -65,7 +65,7 @@ namespace Artemis.UI.Screens.Settings.Tabs.Devices
}
catch (Exception e)
{
await _dialogService.ShowExceptionDialog("Welp, we couldn't open the device's plugin folder for you", e);
_dialogService.ShowExceptionDialog("Welp, we couldn't open the device's plugin folder for you", e);
}
}
}
@@ -62,7 +62,7 @@ namespace Artemis.UI.Screens.Settings.Tabs.Plugins
set => Task.Run(() => UpdateEnabled(value));
}
public async Task OpenSettings()
public void OpenSettings()
{
try
{
@@ -72,12 +72,12 @@ namespace Artemis.UI.Screens.Settings.Tabs.Plugins
}
catch (Exception e)
{
await _dialogService.ShowExceptionDialog("An exception occured while trying to show the plugin's settings window", e);
_dialogService.ShowExceptionDialog("An exception occured while trying to show the plugin's settings window", e);
throw;
}
}
public async Task ShowLogsFolder()
public void ShowLogsFolder()
{
try
{
@@ -85,16 +85,16 @@ namespace Artemis.UI.Screens.Settings.Tabs.Plugins
}
catch (Exception e)
{
await _dialogService.ShowExceptionDialog("Welp, we couldn\'t open the logs folder for you", e);
_dialogService.ShowExceptionDialog("Welp, we couldn\'t open the logs folder for you", e);
}
}
public async Task ShowLoadException()
public void ShowLoadException()
{
if (PluginInfo.LoadException == null)
return;
await _dialogService.ShowExceptionDialog("The plugin failed to load: " + PluginInfo.LoadException.Message, PluginInfo.LoadException);
_dialogService.ShowExceptionDialog("The plugin failed to load: " + PluginInfo.LoadException.Message, PluginInfo.LoadException);
}
private PackIconKind GetIconKind()
@@ -157,7 +157,7 @@ namespace Artemis.UI.Screens.Settings.Tabs.Plugins
}
catch (Exception e)
{
_snackbarMessageQueue.Enqueue($"Failed to enable plugin {PluginInfo.Name}\r\n{e.Message}", "VIEW LOGS", async () => await ShowLogsFolder());
_snackbarMessageQueue.Enqueue($"Failed to enable plugin {PluginInfo.Name}\r\n{e.Message}", "VIEW LOGS", ShowLogsFolder);
}
finally
{