1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2025-12-13 05:48:35 +00:00

Display conditions - Added data model selection

Display conditions - Added static and dynamic condition types
This commit is contained in:
SpoinkyNL 2020-07-05 23:00:23 +02:00
parent 4e1a09308f
commit 0ac6431755
8 changed files with 198 additions and 66 deletions

View File

@ -5,10 +5,20 @@ namespace Artemis.Core.Models.Profile.Conditions
{ {
public class DisplayConditionPredicate : DisplayConditionPart public class DisplayConditionPredicate : DisplayConditionPart
{ {
public Guid DataModelGuid { get; set; } public PredicateType PredicateType { get; set; }
public string PropertyPath { get; set; }
public DisplayConditionOperator Operator { get; set; } public DisplayConditionOperator Operator { get; set; }
public object Value { get; set; }
public Guid LeftDataModelGuid { get; set; }
public string LeftPropertyPath { get; set; }
public Guid RightDataModelGuid { get; set; }
public string RightPropertyPath { get; set; }
public object RightStaticValue { get; set; }
}
public enum PredicateType
{
Static,
Dynamic
} }
} }

View File

@ -19,7 +19,8 @@
<VisualBrush> <VisualBrush>
<VisualBrush.Visual> <VisualBrush.Visual>
<Rectangle x:Name="BorderVisual" <Rectangle x:Name="BorderVisual"
StrokeDashArray="2 2" Stroke="{DynamicResource SecondaryAccentBrush}" StrokeThickness="1" Stroke="{DynamicResource MaterialDesignTextBoxBorder}"
StrokeThickness="1"
Width="{Binding RelativeSource={RelativeSource AncestorType={x:Type Border}}, Path=ActualWidth}" Width="{Binding RelativeSource={RelativeSource AncestorType={x:Type Border}}, Path=ActualWidth}"
Height="{Binding RelativeSource={RelativeSource AncestorType={x:Type Border}}, Path=ActualHeight}" /> Height="{Binding RelativeSource={RelativeSource AncestorType={x:Type Border}}, Path=ActualHeight}" />
</VisualBrush.Visual> </VisualBrush.Visual>
@ -32,7 +33,6 @@
Margin="0 3 0 0" Margin="0 3 0 0"
Text="{Binding Value, StringFormat=N3, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" Text="{Binding Value, StringFormat=N3, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}"
Cursor="/Resources/Cursors/aero_drag_ew.cur" Cursor="/Resources/Cursors/aero_drag_ew.cur"
Foreground="{DynamicResource SecondaryAccentBrush}"
MouseDown="InputMouseDown" MouseDown="InputMouseDown"
MouseUp="InputMouseUp" MouseUp="InputMouseUp"
MouseMove="InputMouseMove" MouseMove="InputMouseMove"

View File

@ -2,24 +2,11 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Artemis.UI.ResourceDictionaries"> xmlns:local="clr-namespace:Artemis.UI.ResourceDictionaries">
<Style x:Key="DisplayConditionButton" TargetType="{x:Type Button}" BasedOn="{StaticResource MaterialDesignFlatAccentBgButton}"> <Style x:Key="DisplayConditionButton" TargetType="{x:Type Button}" BasedOn="{StaticResource MaterialDesignFlatAccentBgButton}">
<Setter Property="Margin" Value="2 0" /> <Setter Property="Margin" Value="3 0" />
<Setter Property="Padding" Value="6 4" /> <Setter Property="Padding" Value="6 4" />
<Setter Property="Height" Value="22" /> <Setter Property="Height" Value="22" />
<Setter Property="Foreground" Value="{DynamicResource PrimaryHueMidForegroundBrush}" /> <Setter Property="Foreground" Value="{DynamicResource PrimaryHueMidForegroundBrush}" />
<Setter Property="FontSize" Value="12" /> <Setter Property="FontSize" Value="12" />
<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> </Style>
<Style x:Key="DisplayConditionButtonLeftClickMenu" TargetType="{x:Type Button}" BasedOn="{StaticResource DisplayConditionButton}"> <Style x:Key="DisplayConditionButtonLeftClickMenu" TargetType="{x:Type Button}" BasedOn="{StaticResource DisplayConditionButton}">

View File

@ -42,10 +42,10 @@
Content="{Binding SelectedBooleanOperator}"> Content="{Binding SelectedBooleanOperator}">
<Button.ContextMenu> <Button.ContextMenu>
<ContextMenu> <ContextMenu>
<MenuItem Header="And" Command="{s:Action SelectBooleanOperator}" CommandParameter="And"/> <MenuItem Header="And" Command="{s:Action SelectBooleanOperator}" CommandParameter="And" />
<MenuItem Header="Or" Command="{s:Action SelectBooleanOperator}" CommandParameter="Or"/> <MenuItem Header="Or" Command="{s:Action SelectBooleanOperator}" CommandParameter="Or" />
<MenuItem Header="And not" Command="{s:Action SelectBooleanOperator}" CommandParameter="AndNot"/> <MenuItem Header="And not" Command="{s:Action SelectBooleanOperator}" CommandParameter="AndNot" />
<MenuItem Header="Or not" Command="{s:Action SelectBooleanOperator}" CommandParameter="OrNot"/> <MenuItem Header="Or not" Command="{s:Action SelectBooleanOperator}" CommandParameter="OrNot" />
</ContextMenu> </ContextMenu>
</Button.ContextMenu> </Button.ContextMenu>
</Button> </Button>
@ -58,25 +58,44 @@
<Button.Style> <Button.Style>
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource MaterialDesignIconForegroundButton}"> <Style TargetType="{x:Type Button}" BasedOn="{StaticResource MaterialDesignIconForegroundButton}">
<Style.Triggers> <Style.Triggers>
<EventTrigger RoutedEvent="Click"> <EventTrigger RoutedEvent="Click">
<EventTrigger.Actions> <EventTrigger.Actions>
<BeginStoryboard> <BeginStoryboard>
<Storyboard> <Storyboard>
<BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="ContextMenu.IsOpen"> <BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="ContextMenu.IsOpen">
<DiscreteBooleanKeyFrame KeyTime="0:0:0" Value="True"/> <DiscreteBooleanKeyFrame KeyTime="0:0:0" Value="True" />
</BooleanAnimationUsingKeyFrames> </BooleanAnimationUsingKeyFrames>
</Storyboard> </Storyboard>
</BeginStoryboard> </BeginStoryboard>
</EventTrigger.Actions> </EventTrigger.Actions>
</EventTrigger> </EventTrigger>
</Style.Triggers> </Style.Triggers>
</Style> </Style>
</Button.Style> </Button.Style>
<materialDesign:PackIcon Kind="Add" Width="18" Height="18" /> <materialDesign:PackIcon Kind="Add" Width="18" Height="18" />
<Button.ContextMenu> <Button.ContextMenu>
<ContextMenu> <ContextMenu>
<MenuItem Header="Add condition" Command="{s:Action AddCondition}" /> <MenuItem Header="Add static condition"
<MenuItem Header="Add group" Command="{s:Action AddGroup}" /> 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> </ContextMenu>
</Button.ContextMenu> </Button.ContextMenu>
</Button> </Button>

View File

@ -12,7 +12,8 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.DisplayConditions
private readonly IDisplayConditionsVmFactory _displayConditionsVmFactory; private readonly IDisplayConditionsVmFactory _displayConditionsVmFactory;
private bool _isRootGroup; private bool _isRootGroup;
public DisplayConditionGroupViewModel(DisplayConditionGroup displayConditionGroup, DisplayConditionViewModel parent, IDisplayConditionsVmFactory displayConditionsVmFactory) : base(displayConditionGroup, parent) public DisplayConditionGroupViewModel(DisplayConditionGroup displayConditionGroup, DisplayConditionViewModel parent, IDisplayConditionsVmFactory displayConditionsVmFactory) : base(
displayConditionGroup, parent)
{ {
_displayConditionsVmFactory = displayConditionsVmFactory; _displayConditionsVmFactory = displayConditionsVmFactory;
} }
@ -34,9 +35,12 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.DisplayConditions
NotifyOfPropertyChange(nameof(SelectedBooleanOperator)); NotifyOfPropertyChange(nameof(SelectedBooleanOperator));
} }
public void AddCondition() public void AddCondition(string type)
{ {
DisplayConditionGroup.AddChild(new DisplayConditionPredicate()); if (type == "Static")
DisplayConditionGroup.AddChild(new DisplayConditionPredicate {PredicateType = PredicateType.Static});
else if (type == "Dynamic")
DisplayConditionGroup.AddChild(new DisplayConditionPredicate {PredicateType = PredicateType.Dynamic});
Update(); Update();
} }

View File

@ -24,7 +24,7 @@
</ResourceDictionary.MergedDictionaries> </ResourceDictionary.MergedDictionaries>
</ResourceDictionary> </ResourceDictionary>
</UserControl.Resources> </UserControl.Resources>
<Grid Margin="0 2"> <Grid Margin="0 3">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />
@ -41,11 +41,14 @@
Command="{s:Action Delete}"> Command="{s:Action Delete}">
<materialDesign:PackIcon Kind="Close" Width="18" Height="18" /> <materialDesign:PackIcon Kind="Close" Width="18" Height="18" />
</Button> </Button>
<!-- Left side, always a property -->
<Button Grid.Row="0" <Button Grid.Row="0"
Grid.Column="1" Grid.Column="1"
Background="{DynamicResource SecondaryAccentBrush}" Background="#ab47bc"
BorderBrush="{DynamicResource SecondaryAccentBrush}" BorderBrush="#ab47bc"
Style="{StaticResource DisplayConditionButtonLeftClickMenu}"> Style="{StaticResource DisplayConditionButton}"
Click="PropertyButton_OnClick">
<Button.ContextMenu> <Button.ContextMenu>
<ContextMenu ItemsSource="{Binding DataModel.Children}"> <ContextMenu ItemsSource="{Binding DataModel.Children}">
<ContextMenu.ItemContainerStyle> <ContextMenu.ItemContainerStyle>
@ -53,10 +56,10 @@
<Setter Property="ItemsSource" Value="{Binding Children}" /> <Setter Property="ItemsSource" Value="{Binding Children}" />
<Setter Property="Header" Value="{Binding PropertyDescription.Name}" /> <Setter Property="Header" Value="{Binding PropertyDescription.Name}" />
<Setter Property="ToolTip" Value="{Binding PropertyDescription.Description}" /> <Setter Property="ToolTip" Value="{Binding PropertyDescription.Description}" />
<Setter Property="Command" Value="{Binding Data.SelectPropertyCommand, Source={StaticResource DataContextProxy}}" /> <Setter Property="Command" Value="{Binding Data.SelectLeftPropertyCommand, Source={StaticResource DataContextProxy}}" />
<Setter Property="CommandParameter" Value="{Binding}" /> <Setter Property="CommandParameter" Value="{Binding}" />
<Setter Property="CommandTarget" Value="{Binding}" /> <Setter Property="CommandTarget" Value="{Binding}" />
</Style> </Style>
</ContextMenu.ItemContainerStyle> </ContextMenu.ItemContainerStyle>
</ContextMenu> </ContextMenu>
@ -71,6 +74,7 @@
</Grid> </Grid>
</Button> </Button>
<!-- Operator -->
<Button Grid.Row="0" <Button Grid.Row="0"
Grid.Column="2" Grid.Column="2"
Style="{StaticResource DisplayConditionButtonLeftClickMenu}" Style="{StaticResource DisplayConditionButtonLeftClickMenu}"
@ -116,10 +120,63 @@
</ContextMenu> </ContextMenu>
</Button.ContextMenu> </Button.ContextMenu>
</Button> </Button>
<!-- Right side property if type is dynamic -->
<Button Grid.Row="0" <Button Grid.Row="0"
Grid.Column="3" Grid.Column="3"
Style="{StaticResource DisplayConditionButton}"
Background="{DynamicResource PrimaryHueMidBrush}" Background="{DynamicResource PrimaryHueMidBrush}"
BorderBrush="{DynamicResource PrimaryHueMidBrush}" Content="PredicateRightSide" /> BorderBrush="{DynamicResource PrimaryHueMidBrush}"
Style="{StaticResource DisplayConditionButton}"
Click="PropertyButton_OnClick"
Visibility="{Binding ShowRightSidePropertySelection, Converter={x:Static s:BoolToVisibilityConverter.Instance}, Mode=OneWay}">
<Button.ContextMenu>
<ContextMenu ItemsSource="{Binding DataModel.Children}">
<ContextMenu.ItemContainerStyle>
<Style TargetType="{x:Type MenuItem}" BasedOn="{StaticResource MaterialDesignMenuItem}">
<Setter Property="ItemsSource" Value="{Binding Children}" />
<Setter Property="Header" Value="{Binding PropertyDescription.Name}" />
<Setter Property="ToolTip" Value="{Binding PropertyDescription.Description}" />
<Setter Property="Command" Value="{Binding Data.SelectRightPropertyCommand, Source={StaticResource DataContextProxy}}" />
<Setter Property="CommandParameter" Value="{Binding}" />
<Setter Property="CommandTarget" Value="{Binding}" />
</Style>
</ContextMenu.ItemContainerStyle>
</ContextMenu>
</Button.ContextMenu>
<Grid>
<TextBlock Text="{Binding SelectedRightSideProperty.PropertyDescription.Name}"
ToolTip="{Binding SelectedRightSideProperty.PropertyDescription.Description}"
Visibility="{Binding SelectedRightSideProperty, Converter={StaticResource NullToVisibilityConverter}}" />
<TextBlock Text="« Select a property »"
FontStyle="Italic"
Visibility="{Binding SelectedRightSideProperty, Converter={StaticResource NullToVisibilityConverter}, ConverterParameter=Inverted}" />
</Grid>
</Button>
<Grid Grid.Row="0"
Grid.Column="3"
Visibility="{Binding ShowRightSidePropertySelection, Converter={x:Static s:BoolToVisibilityConverter.InverseInstance}, Mode=OneWay}">
<materialDesign:Transitioner
SelectedIndex="{Binding RightSideTransitionIndex}"
DefaultTransitionOrigin="0.5, 0.5"
Margin="3 -4">
<Button Style="{StaticResource DisplayConditionButton}"
Background="{DynamicResource PrimaryHueMidBrush}"
BorderBrush="{DynamicResource PrimaryHueMidBrush}"
Margin="0 4"
Content="PredicateRightSide"
Command="{s:Action ActivateRightSideInputViewModel}"
HorizontalAlignment="Left" />
<Border BorderBrush="{DynamicResource PrimaryHueMidBrush}"
BorderThickness="2"
CornerRadius="3"
Padding="3"
Width="140">
<ContentControl s:View.Model="{Binding RightSideInputViewModel}" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" />
</Border>
</materialDesign:Transitioner>
</Grid>
</Grid> </Grid>
</UserControl> </UserControl>

View File

@ -0,0 +1,26 @@
using System.Windows;
using System.Windows.Controls;
namespace Artemis.UI.Screens.Module.ProfileEditor.DisplayConditions
{
/// <summary>
/// Interaction logic for DisplayConditionPredicateView.xaml
/// </summary>
public partial class DisplayConditionPredicateView : UserControl
{
public DisplayConditionPredicateView()
{
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;
}
}
}
}

View File

@ -1,5 +1,6 @@
using Artemis.Core.Models.Profile.Conditions; using Artemis.Core.Models.Profile.Conditions;
using Artemis.UI.Screens.Module.ProfileEditor.DisplayConditions.Abstract; using Artemis.UI.Screens.Module.ProfileEditor.DisplayConditions.Abstract;
using Artemis.UI.Shared.DataModelVisualization;
using Artemis.UI.Shared.DataModelVisualization.Shared; using Artemis.UI.Shared.DataModelVisualization.Shared;
using Artemis.UI.Shared.Services; using Artemis.UI.Shared.Services;
using Artemis.UI.Shared.Services.Interfaces; using Artemis.UI.Shared.Services.Interfaces;
@ -13,7 +14,9 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.DisplayConditions
private readonly IProfileEditorService _profileEditorService; private readonly IProfileEditorService _profileEditorService;
private DataModelPropertiesViewModel _dataModel; private DataModelPropertiesViewModel _dataModel;
private DataModelVisualizationViewModel _selectedLeftSideProperty; private DataModelVisualizationViewModel _selectedLeftSideProperty;
private bool _leftSidePropertySelectionOpen; private DataModelVisualizationViewModel _selectedRightSideProperty;
private int _rightSideTransitionIndex;
private DataModelInputViewModel _rightSideInputViewModel;
public DisplayConditionPredicateViewModel(DisplayConditionPredicate displayConditionPredicate, DisplayConditionViewModel parent, public DisplayConditionPredicateViewModel(DisplayConditionPredicate displayConditionPredicate, DisplayConditionViewModel parent,
IProfileEditorService profileEditorService, IDataModelVisualizationService dataModelVisualizationService) : base(displayConditionPredicate, parent) IProfileEditorService profileEditorService, IDataModelVisualizationService dataModelVisualizationService) : base(displayConditionPredicate, parent)
@ -21,12 +24,16 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.DisplayConditions
_profileEditorService = profileEditorService; _profileEditorService = profileEditorService;
_dataModelVisualizationService = dataModelVisualizationService; _dataModelVisualizationService = dataModelVisualizationService;
SelectPropertyCommand = new DelegateCommand(ExecuteSelectProperty); SelectLeftPropertyCommand = new DelegateCommand(ExecuteSelectLeftProperty);
SelectRightPropertyCommand = new DelegateCommand(ExecuteSelectRightProperty);
GetDataModel(); GetDataModel();
} }
public DelegateCommand SelectPropertyCommand { get; } public DisplayConditionPredicate DisplayConditionPredicate => (DisplayConditionPredicate) Model;
public DelegateCommand SelectLeftPropertyCommand { get; }
public DelegateCommand SelectRightPropertyCommand { get; }
public bool ShowRightSidePropertySelection => DisplayConditionPredicate.PredicateType == PredicateType.Dynamic;
public DataModelPropertiesViewModel DataModel public DataModelPropertiesViewModel DataModel
{ {
@ -40,18 +47,22 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.DisplayConditions
set => SetAndNotify(ref _selectedLeftSideProperty, value); set => SetAndNotify(ref _selectedLeftSideProperty, value);
} }
public bool LeftSidePropertySelectionOpen public DataModelVisualizationViewModel SelectedRightSideProperty
{ {
get => _leftSidePropertySelectionOpen; get => _selectedRightSideProperty;
set => SetAndNotify(ref _leftSidePropertySelectionOpen, value); set => SetAndNotify(ref _selectedRightSideProperty, value);
} }
public int RightSideTransitionIndex
public DisplayConditionPredicate DisplayConditionPredicate => (DisplayConditionPredicate) Model;
public void ToggleLeftSidePropertySelectionOpen()
{ {
LeftSidePropertySelectionOpen = !LeftSidePropertySelectionOpen; get => _rightSideTransitionIndex;
set => SetAndNotify(ref _rightSideTransitionIndex, value);
}
public DataModelInputViewModel RightSideInputViewModel
{
get => _rightSideInputViewModel;
set => SetAndNotify(ref _rightSideInputViewModel, value);
} }
public void GetDataModel() public void GetDataModel()
@ -67,19 +78,37 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.DisplayConditions
public override void Update() public override void Update()
{ {
if (DisplayConditionPredicate.PropertyPath != null) SelectedLeftSideProperty = DisplayConditionPredicate.LeftPropertyPath != null
SelectedLeftSideProperty = DataModel.GetChildByPath(DisplayConditionPredicate.DataModelGuid, DisplayConditionPredicate.PropertyPath); ? DataModel.GetChildByPath(DisplayConditionPredicate.LeftDataModelGuid, DisplayConditionPredicate.LeftPropertyPath)
else : null;
SelectedLeftSideProperty = null;
SelectedRightSideProperty = DisplayConditionPredicate.RightPropertyPath != null
? DataModel.GetChildByPath(DisplayConditionPredicate.RightDataModelGuid, DisplayConditionPredicate.RightPropertyPath)
: null;
} }
private void ExecuteSelectProperty(object context) public void ActivateRightSideInputViewModel()
{
RightSideTransitionIndex = 1;
}
private void ExecuteSelectLeftProperty(object context)
{ {
if (!(context is DataModelVisualizationViewModel vm)) if (!(context is DataModelVisualizationViewModel vm))
return; return;
DisplayConditionPredicate.PropertyPath = vm.GetCurrentPath(); DisplayConditionPredicate.LeftPropertyPath = vm.GetCurrentPath();
DisplayConditionPredicate.DataModelGuid = vm.DataModel.PluginInfo.Guid; DisplayConditionPredicate.LeftDataModelGuid = vm.DataModel.PluginInfo.Guid;
Update();
}
private void ExecuteSelectRightProperty(object context)
{
if (!(context is DataModelVisualizationViewModel vm))
return;
DisplayConditionPredicate.RightPropertyPath = vm.GetCurrentPath();
DisplayConditionPredicate.RightDataModelGuid = vm.DataModel.PluginInfo.Guid;
Update(); Update();
} }
} }