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

Added profile import, profile editor UI polish

This commit is contained in:
SpoinkyNL 2016-05-26 21:03:15 +02:00
parent a596382274
commit 5a19bf9e30
15 changed files with 335 additions and 102 deletions

View File

@ -196,7 +196,7 @@
<Private>True</Private>
</Reference>
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
<HintPath>..\packages\NLog.4.3.3\lib\net45\NLog.dll</HintPath>
<HintPath>..\packages\NLog.4.3.4\lib\net45\NLog.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="SharpDX, Version=3.0.2.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
@ -283,7 +283,7 @@
<Compile Include="ArtemisBootstrapper.cs" />
<Compile Include="DAL\ProfileProvider.cs" />
<Compile Include="DeviceProviders\Corsair\CorsairMice.cs" />
<Compile Include="DeviceProviders\Corsair\CorsiarHeadsets.cs" />
<Compile Include="DeviceProviders\Corsair\CorsairHeadsets.cs" />
<Compile Include="DeviceProviders\DeviceProvider.cs" />
<Compile Include="Events\ActiveKeyboardChanged.cs" />
<Compile Include="Events\ToggleEnabled.cs" />

View File

@ -96,5 +96,24 @@ namespace Artemis.DAL
Directory.CreateDirectory(ProfileFolder);
Debug.WriteLine("Place presets");
}
public static ProfileModel LoadProfileIfValid(string path)
{
try
{
var deserializer = new XmlSerializer(typeof(ProfileModel));
using (var file = new StreamReader(path))
{
var prof = (ProfileModel) deserializer.Deserialize(file);
if (!(prof.GameName?.Length > 1) || !(prof.KeyboardName?.Length > 1) || !(prof.Name?.Length > 1))
return null;
return prof;
}
}
catch (InvalidOperationException)
{
return null;
}
}
}
}

View File

@ -33,7 +33,7 @@ namespace Artemis.DeviceProviders.Corsair
public override void Disable()
{
if (CueSDK.ProtocolDetails != null)
CueSDK.Reinitialize();
CueSDK.Reinitialize(true);
}
public override void UpdateDevice(Brush brush)
@ -72,7 +72,7 @@ namespace Artemis.DeviceProviders.Corsair
try
{
if (CueSDK.ProtocolDetails == null)
CueSDK.Initialize();
CueSDK.Initialize(true);
else
return true;
}
@ -87,7 +87,7 @@ namespace Artemis.DeviceProviders.Corsair
}
catch (WrapperException)
{
CueSDK.Reinitialize();
CueSDK.Reinitialize(true);
return true;
}

View File

@ -33,7 +33,7 @@ namespace Artemis.DeviceProviders.Corsair
public override void Disable()
{
if (CueSDK.ProtocolDetails != null)
CueSDK.Reinitialize();
CueSDK.Reinitialize(true);
}
public override void UpdateDevice(Brush brush)
@ -73,7 +73,7 @@ namespace Artemis.DeviceProviders.Corsair
try
{
if (CueSDK.ProtocolDetails == null)
CueSDK.Initialize();
CueSDK.Initialize(true);
else
return true;
}
@ -88,7 +88,7 @@ namespace Artemis.DeviceProviders.Corsair
}
catch (WrapperException)
{
CueSDK.Reinitialize();
CueSDK.Reinitialize(true);
return true;
}

View File

@ -33,7 +33,7 @@ namespace Artemis.DeviceProviders.Corsair
try
{
if (CueSDK.ProtocolDetails == null)
CueSDK.Initialize();
CueSDK.Initialize(true);
}
catch (CUEException e)
{
@ -46,7 +46,7 @@ namespace Artemis.DeviceProviders.Corsair
}
catch (WrapperException)
{
CueSDK.Reinitialize();
CueSDK.Reinitialize(true);
return true;
}
@ -93,7 +93,7 @@ namespace Artemis.DeviceProviders.Corsair
public override void Disable()
{
if (CueSDK.ProtocolDetails != null)
CueSDK.Reinitialize();
CueSDK.Reinitialize(true);
}
/// <summary>

View File

@ -23,9 +23,13 @@ namespace Artemis.Models.Profiles
// Put the subject in a list, allowing Dynamic Linq to be used.
var subjectList = new List<T> {(T) subject};
var res = Type == "String"
? subjectList.Where($"{Field}.ToLower() {Operator} @0", Value.ToLower()).Any()
: subjectList.Where($"{Field} {Operator} {Value}").Any();
bool res;
if (Type == "String")
res = subjectList.Where($"{Field}.ToLower() {Operator} @0", Value.ToLower()).Any();
else if (Type == "Enum")
res = subjectList.Where($"{Field} {Operator} \"{Value}\"").Any();
else
res = subjectList.Where($"{Field} {Operator} {Value}").Any();
return res;
}
}

View File

@ -166,12 +166,12 @@ namespace Artemis.Models.Profiles
return Enabled && (LayerType == LayerType.Keyboard || LayerType == LayerType.KeyboardGif);
}
public IEnumerable<LayerModel> GetAllLayers()
public IEnumerable<LayerModel> GetAllLayers(bool ignoreEnabled)
{
var layers = new List<LayerModel>();
foreach (var layerModel in Children)
{
if (!layerModel.Enabled)
if (ignoreEnabled && !layerModel.Enabled)
continue;
layers.Add(layerModel);
layers.AddRange(layerModel.Children);

View File

@ -1,5 +1,4 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Windows;
@ -11,6 +10,8 @@ using Artemis.Utilities;
using Artemis.Utilities.ParentChild;
using Brush = System.Windows.Media.Brush;
using Color = System.Windows.Media.Color;
using Point = System.Windows.Point;
using Size = System.Windows.Size;
namespace Artemis.Models.Profiles
{
@ -137,18 +138,38 @@ namespace Artemis.Models.Profiles
/// <summary>
/// Gives all the layers and their children in a flat list
/// </summary>
public List<LayerModel> GetEnabledLayers()
public List<LayerModel> GetLayers(bool ignoreEnabled = true)
{
var layers = new List<LayerModel>();
foreach (var layerModel in Layers)
{
if (!layerModel.Enabled)
if (ignoreEnabled && !layerModel.Enabled)
{
continue;
}
layers.Add(layerModel);
layers.AddRange(layerModel.GetAllLayers());
layers.AddRange(layerModel.GetAllLayers(ignoreEnabled));
}
return layers;
}
public void FixBoundaries(Rect keyboardRectangle)
{
foreach (var layer in GetLayers(false))
{
if (layer.LayerType != LayerType.Keyboard && layer.LayerType != LayerType.KeyboardGif)
continue;
var props = (KeyboardPropertiesModel) layer.Properties;
var layerRect = new Rect(new Point(props.X, props.Y), new Size(props.Width, props.Height));
if (keyboardRectangle.Contains(layerRect))
continue;
props.X = 0;
props.Y = 0;
layer.Properties = props;
}
}
}
}

View File

@ -15,16 +15,17 @@
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="80" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2">
<StackPanel Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Margin="0,0,1,0">
<Label FontSize="20" HorizontalAlignment="Left">
<Label.Content>
<AccessText TextWrapping="Wrap"
Text="Shows lots of things, I should change this." />
Text="Shows verious game states and events on the keyboard." />
</Label.Content>
</Label>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
@ -36,10 +37,11 @@
</StackPanel>
</StackPanel>
<TextBlock Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" VerticalAlignment="Center" Margin="0,8"
<TextBlock Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" Margin="0,0,1,0" VerticalAlignment="Center"
TextWrapping="Wrap" HorizontalAlignment="Left" FontFamily="Segoe UI Semibold"
Foreground="{DynamicResource HighlightBrush}" MaxWidth="510" TextAlignment="Justify">
Note: For this game to work with Artemis, please open up your Division settings, navigate to 3rd Party and set LED keyboard support to Yes. (This only works if you have Artemis running before starting the game)
Note: For this game to work with Artemis, please open up your Division settings, navigate to 3rd Party
and set LED keyboard support to Yes. (This only works if you have Artemis running before starting the game)
</TextBlock>
<!-- Profile editor -->

View File

@ -16,8 +16,8 @@
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition />
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2">
<Label FontSize="20" HorizontalAlignment="Left">
@ -35,18 +35,13 @@
</StackPanel>
</StackPanel>
<TextBlock Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" VerticalAlignment="Center" Margin="0,8"
TextWrapping="Wrap" HorizontalAlignment="Left" FontFamily="Segoe UI Semibold"
MaxWidth="510" TextAlignment="Justify">
TextWrapping="Wrap" HorizontalAlignment="Left" FontFamily="Segoe UI Semibold" TextAlignment="Justify" MaxWidth="820">
Artemis requires the latest Witcher 3 version and mod to be installed in order to work. If you don't use any (conflicting) Witcher 3 mods, the mod can automatically be installed.
</TextBlock>
<TextBlock Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" VerticalAlignment="Center" Margin="0,8"
TextWrapping="Wrap" HorizontalAlignment="Left" FontFamily="Segoe UI Semibold"
Foreground="{DynamicResource HighlightBrush}" MaxWidth="510" TextAlignment="Justify">
Note: If you do use conflicting mods, we'll let you know what to do.
</TextBlock>
<Button Grid.Row="3" Grid.Column="0" x:Name="AutoInstall" Content="Try automatic mod install" Width="160"
Style="{DynamicResource SquareButtonStyle}" HorizontalAlignment="Left" Margin="0,20,0,0" />
<Button Grid.Row="2" Grid.Column="0" x:Name="AutoInstall" Content="Try automatic mod install" Width="160" Style="{DynamicResource SquareButtonStyle}" HorizontalAlignment="Left" />
<!-- Profile editor -->
<ContentControl Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2" x:Name="ProfileEditor" Margin="0,0,-30,0" />
<!-- Buttons -->
<StackPanel Grid.Column="0" Grid.Row="4" Orientation="Horizontal" VerticalAlignment="Bottom">

View File

@ -6,7 +6,7 @@ using Caliburn.Micro;
namespace Artemis.ViewModels.LayerEditor
{
public class LayerConditionViewModel : Screen
public sealed class LayerConditionViewModel : Screen
{
private readonly NamedOperator[] _boolOperators =
{
@ -32,9 +32,10 @@ namespace Artemis.ViewModels.LayerEditor
new NamedOperator("Not equal to", "!=")
};
private bool _enumValueIsVisible;
private bool _preselecting;
private GeneralHelpers.PropertyCollection _selectedDataModelProp;
private string _selectedEnum;
private NamedOperator _selectedOperator;
private string _userValue;
private bool _userValueIsVisible;
@ -48,6 +49,7 @@ namespace Artemis.ViewModels.LayerEditor
LayerConditionModel = layerConditionModel;
DataModelProps = dataModelProps;
Operators = new BindableCollection<NamedOperator>();
Enums = new BindableCollection<string>();
PropertyChanged += UpdateModel;
PropertyChanged += UpdateForm;
@ -55,6 +57,13 @@ namespace Artemis.ViewModels.LayerEditor
PreSelect();
}
public LayerConditionModel LayerConditionModel { get; set; }
public BindableCollection<GeneralHelpers.PropertyCollection> DataModelProps { get; set; }
public BindableCollection<NamedOperator> Operators { get; set; }
public BindableCollection<string> Enums { get; set; }
public string UserValue
{
get { return _userValue; }
@ -66,10 +75,6 @@ namespace Artemis.ViewModels.LayerEditor
}
}
public LayerConditionModel LayerConditionModel { get; set; }
public BindableCollection<GeneralHelpers.PropertyCollection> DataModelProps { get; set; }
public BindableCollection<NamedOperator> Operators { get; set; }
public GeneralHelpers.PropertyCollection SelectedDataModelProp
{
get { return _selectedDataModelProp; }
@ -93,6 +98,17 @@ namespace Artemis.ViewModels.LayerEditor
}
}
public bool EnumValueIsVisible
{
get { return _enumValueIsVisible; }
set
{
if (value == _enumValueIsVisible) return;
_enumValueIsVisible = value;
NotifyOfPropertyChange(() => EnumValueIsVisible);
}
}
public NamedOperator SelectedOperator
{
get { return _selectedOperator; }
@ -104,6 +120,17 @@ namespace Artemis.ViewModels.LayerEditor
}
}
public string SelectedEnum
{
get { return _selectedEnum; }
set
{
if (value == _selectedEnum) return;
_selectedEnum = value;
NotifyOfPropertyChange(() => SelectedEnum);
}
}
/// <summary>
/// Handles updating the form to match the selected data model property
/// </summary>
@ -115,32 +142,35 @@ namespace Artemis.ViewModels.LayerEditor
return;
Operators.Clear();
UserValueIsVisible = false;
EnumValueIsVisible = false;
switch (SelectedDataModelProp.Type)
{
case "Int32":
Operators.AddRange(_int32Operators);
UserValueIsVisible = true;
break;
case "Boolean":
Operators.AddRange(_boolOperators);
break;
default:
Operators.AddRange(_operators);
UserValueIsVisible = true;
break;
}
// Setup Enum selection if needed
if (SelectedDataModelProp.EnumValues != null)
{
Operators.AddRange(
SelectedDataModelProp.EnumValues.Select(val => new NamedOperator(val.SplitCamelCase(), "== " + val)));
UserValueIsVisible = false;
Enums.AddRange(SelectedDataModelProp.EnumValues);
EnumValueIsVisible = true;
}
else
switch (SelectedDataModelProp.Type)
{
case "Int32":
Operators.AddRange(_int32Operators);
UserValueIsVisible = true;
break;
case "Boolean":
Operators.AddRange(_boolOperators);
UserValueIsVisible = false;
break;
default:
Operators.AddRange(_operators);
UserValueIsVisible = true;
break;
}
SelectedOperator = Operators.First();
}
/// <summary>
/// Handles saving user input to the model
/// TODO: Data validation?
@ -156,13 +186,14 @@ namespace Artemis.ViewModels.LayerEditor
// Only care about these fields
if (e.PropertyName != "UserValue" &&
e.PropertyName != "SelectedOperator" &&
e.PropertyName != "SelectedDataModelProp")
e.PropertyName != "SelectedDataModelProp" &&
e.PropertyName != "SelectedEnum")
return;
LayerConditionModel.Field = SelectedDataModelProp.Path;
LayerConditionModel.Operator = SelectedOperator.Value;
LayerConditionModel.Value = UserValue;
LayerConditionModel.Type = SelectedDataModelProp.Type;
LayerConditionModel.Value = SelectedDataModelProp.Type == "Enum" ? SelectedEnum : UserValue;
}
/// <summary>
@ -173,8 +204,12 @@ namespace Artemis.ViewModels.LayerEditor
_preselecting = true;
SelectedDataModelProp = DataModelProps.FirstOrDefault(m => m.Path == LayerConditionModel.Field);
SelectedOperator = Operators.FirstOrDefault(o => o.Value == LayerConditionModel.Operator);
UserValue = LayerConditionModel.Value;
LayerConditionModel.Type = SelectedDataModelProp.Type;
if (LayerConditionModel.Type =="Enum")
SelectedEnum = LayerConditionModel.Value;
else
UserValue = LayerConditionModel.Value;
_preselecting = false;
}

View File

@ -7,6 +7,7 @@ using System.Threading.Tasks;
using System.Timers;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Forms;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Threading;
@ -25,6 +26,13 @@ using Caliburn.Micro;
using GongSolutions.Wpf.DragDrop;
using MahApps.Metro;
using Ninject;
using Application = System.Windows.Application;
using Cursor = System.Windows.Input.Cursor;
using Cursors = System.Windows.Input.Cursors;
using DragDropEffects = System.Windows.DragDropEffects;
using IDropTarget = GongSolutions.Wpf.DragDrop.IDropTarget;
using MouseEventArgs = System.Windows.Input.MouseEventArgs;
using Screen = Caliburn.Micro.Screen;
using Timer = System.Timers.Timer;
namespace Artemis.ViewModels
@ -45,7 +53,8 @@ namespace Artemis.ViewModels
private LayerModel _selectedLayer;
private ProfileModel _selectedProfile;
public ProfileEditorViewModel(IEventAggregator events, MainManager mainManager, GameModel gameModel)
public ProfileEditorViewModel(IEventAggregator events, MainManager mainManager, GameModel gameModel,
MetroDialogService dialogService)
{
_mainManager = mainManager;
_gameModel = gameModel;
@ -53,13 +62,13 @@ namespace Artemis.ViewModels
Profiles = new BindableCollection<ProfileModel>();
Layers = new BindableCollection<LayerModel>();
ActiveKeyboard = _mainManager.DeviceManager.ActiveKeyboard;
DialogService = dialogService;
events.Subscribe(this);
PreviewTimer = new Timer(40);
PreviewTimer.Elapsed += InvokeUpdateKeyboardPreview;
PropertyChanged += PropertyChangeHandler;
LoadProfiles();
}
@ -99,7 +108,7 @@ namespace Artemis.ViewModels
if (Equals(value, _selectedLayer)) return;
_selectedLayer = value;
NotifyOfPropertyChange(() => SelectedLayer);
NotifyOfPropertyChange(() => CanRemoveLayer);
NotifyOfPropertyChange(() => LayerSelected);
}
}
@ -127,8 +136,8 @@ namespace Artemis.ViewModels
Layers.AddRange(SelectedProfile.Layers);
NotifyOfPropertyChange(() => SelectedProfile);
NotifyOfPropertyChange(() => CanAddLayer);
NotifyOfPropertyChange(() => CanRemoveLayer);
NotifyOfPropertyChange(() => ProfileSelected);
NotifyOfPropertyChange(() => LayerSelected);
}
}
@ -147,8 +156,8 @@ namespace Artemis.ViewModels
public PreviewSettings? PreviewSettings => ActiveKeyboard?.PreviewSettings;
public bool CanAddLayer => SelectedProfile != null;
public bool CanRemoveLayer => SelectedProfile != null && _selectedLayer != null;
public bool ProfileSelected => SelectedProfile != null;
public bool LayerSelected => SelectedProfile != null && _selectedLayer != null;
private KeyboardProvider ActiveKeyboard { get; set; }
@ -293,6 +302,14 @@ namespace Artemis.ViewModels
SelectedProfile = profile;
}
public void EditLayer()
{
if (SelectedLayer == null)
return;
LayerEditor(SelectedLayer);
}
/// <summary>
/// Opens a new LayerEditorView for the given layer
/// </summary>
@ -369,6 +386,14 @@ namespace Artemis.ViewModels
SelectedProfile.FixOrder();
}
public void CloneLayer()
{
if (SelectedLayer == null)
return;
CloneLayer(SelectedLayer);
}
/// <summary>
/// Clones the given layer and adds it to the profile, on top of the original
/// </summary>
@ -426,7 +451,7 @@ namespace Artemis.ViewModels
var x = pos.X/((double) ActiveKeyboard.PreviewSettings.Width/ActiveKeyboard.Width);
var y = pos.Y/((double) ActiveKeyboard.PreviewSettings.Height/ActiveKeyboard.Height);
var hoverLayer = SelectedProfile.GetEnabledLayers()
var hoverLayer = SelectedProfile.GetLayers()
.Where(l => l.MustDraw())
.FirstOrDefault(l => ((KeyboardPropertiesModel) l.Properties)
.GetRect(1)
@ -447,7 +472,7 @@ namespace Artemis.ViewModels
var pos = e.GetPosition((Image) e.OriginalSource);
var x = pos.X/((double) ActiveKeyboard.PreviewSettings.Width/ActiveKeyboard.Width);
var y = pos.Y/((double) ActiveKeyboard.PreviewSettings.Height/ActiveKeyboard.Height);
var hoverLayer = SelectedProfile.GetEnabledLayers()
var hoverLayer = SelectedProfile.GetLayers()
.Where(l => l.MustDraw())
.FirstOrDefault(l => ((KeyboardPropertiesModel) l.Properties)
.GetRect(1).Contains(x, y));
@ -594,5 +619,59 @@ namespace Artemis.ViewModels
draggingProps.Y = (int) Math.Round(y - _draggingLayerOffset.Value.Y);
}
}
public async void ImportProfile()
{
var dialog = new OpenFileDialog {Filter = "Artemis profile (*.xml)|*.xml"};
var result = dialog.ShowDialog();
if (result != DialogResult.OK)
return;
var profile = ProfileProvider.LoadProfileIfValid(dialog.FileName);
if (profile == null)
{
DialogService.ShowErrorMessageBox("Oh noes, the profile you provided is invalid. " +
"If this keeps happening, please make an issue on GitHub and provide the profile.");
return;
}
// Verify the game
if (profile.GameName != _gameModel.Name)
{
DialogService.ShowErrorMessageBox(
$"Oh oops! This profile is ment for {profile.GameName}, not {_gameModel.Name} :c");
return;
}
// Verify the keyboard
if (profile.KeyboardName != _mainManager.DeviceManager.ActiveKeyboard.Name)
{
var adjustKeyboard = await DialogService.ShowQuestionMessageBox("Profile not inteded for this keyboard",
$"Watch out, this profile wasn't ment for this keyboard, but for the {profile.KeyboardName}. " +
"You can still import it but you'll probably have to do some adjusting\n\n" +
"Continue?");
if (!adjustKeyboard.Value)
return;
profile.KeyboardName = _mainManager.DeviceManager.ActiveKeyboard.Name;
profile.FixBoundaries(_mainManager.DeviceManager.ActiveKeyboard.KeyboardRectangle(1));
}
// Verify the name
while (ProfileProvider.GetAll().Contains(profile))
{
profile.Name = await DialogService.ShowInputDialog("Rename imported profile",
"A profile with this name already exists for this game. Please enter a new name");
// Null when the user cancelled
if (string.IsNullOrEmpty(profile.Name))
return;
}
ProfileProvider.AddOrUpdate(profile);
LoadProfiles();
SelectedProfile = Profiles.FirstOrDefault(p => p.Name == profile.Name);
}
}
}

View File

@ -54,6 +54,10 @@
<StackPanel Grid.Column="0" x:Name="UserValueIsVisible" HorizontalAlignment="Left" VerticalAlignment="Top">
<TextBox x:Name="UserValue" VerticalAlignment="Center" HorizontalAlignment="Left" Width="110" />
</StackPanel>
<StackPanel Grid.Column="0" x:Name="EnumValueIsVisible" HorizontalAlignment="Left" VerticalAlignment="Top">
<ComboBox x:Name="Enums" Width="110" MaxDropDownHeight="125" HorizontalAlignment="Center"
VerticalAlignment="Top"/>
</StackPanel>
<Button Grid.Column="1" x:Name="Delete" Width="26" Height="26" Style="{DynamicResource SquareButtonStyle}"
VerticalAlignment="Top" HorizontalAlignment="Right">
<Button.Content>

View File

@ -7,9 +7,10 @@
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:itemBehaviours="clr-namespace:Artemis.ItemBehaviours"
xmlns:utilities="clr-namespace:Artemis.Utilities"
xmlns:Controls="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
xmlns:dragDrop="clr-namespace:GongSolutions.Wpf.DragDrop;assembly=GongSolutions.Wpf.DragDrop"
mc:Ignorable="d"
d:DesignHeight="473" Width="1055">
d:DesignHeight="510" Width="1055">
<UserControl.Resources>
<utilities:LayerOrderConverter x:Key="LayerOrderConverter" />
</UserControl.Resources>
@ -64,18 +65,6 @@
</Rectangle>
</Button.Content>
</Button>
<Button x:Name="DuplicateProfile" VerticalAlignment="Top" Style="{DynamicResource SquareButtonStyle}"
Width="26" Height="26" HorizontalAlignment="Right" Margin="10,0,0,0" ToolTip="Duplicate profile">
<Button.Content>
<Rectangle
Fill="{Binding Path=Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}"
Width="12" Height="12">
<Rectangle.OpacityMask>
<VisualBrush Visual="{StaticResource appbar_clipboard_paste}" Stretch="Fill" />
</Rectangle.OpacityMask>
</Rectangle>
</Button.Content>
</Button>
<Button x:Name="EditProfile" VerticalAlignment="Top" Style="{DynamicResource SquareButtonStyle}"
Width="26" Height="26" HorizontalAlignment="Right" Margin="10,0,0,0" ToolTip="Rename profile">
<Button.Content>
@ -88,6 +77,18 @@
</Rectangle>
</Button.Content>
</Button>
<Button x:Name="DuplicateProfile" VerticalAlignment="Top" Style="{DynamicResource SquareButtonStyle}"
Width="26" Height="26" HorizontalAlignment="Right" Margin="10,0,0,0" ToolTip="Duplicate profile">
<Button.Content>
<Rectangle
Fill="{Binding Path=Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}"
Width="12" Height="12">
<Rectangle.OpacityMask>
<VisualBrush Visual="{StaticResource appbar_clipboard_paste}" Stretch="Fill" />
</Rectangle.OpacityMask>
</Rectangle>
</Button.Content>
</Button>
<Button x:Name="RemoveProfile" VerticalAlignment="Top" Style="{DynamicResource SquareButtonStyle}"
Width="26" Height="26" HorizontalAlignment="Right" Margin="10,0,0,0" ToolTip="Delete profile">
<Button.Content>
@ -101,6 +102,38 @@
</Button.Content>
</Button>
</StackPanel>
<StackPanel Grid.Column="0" Grid.Row="2" Orientation="Horizontal" Margin="0,5,0,0" HorizontalAlignment="Right">
<Button x:Name="ImportProfile" VerticalAlignment="Top" Style="{DynamicResource SquareButtonStyle}"
Height="26" HorizontalAlignment="Right" ToolTip="Import profile">
<Button.Content>
<StackPanel Orientation="Horizontal">
<Rectangle
Fill="{Binding Path=Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}"
Width="12" Height="12" Margin="3,0">
<Rectangle.OpacityMask>
<VisualBrush Visual="{StaticResource appbar_cabinet_in}" Stretch="Fill" />
</Rectangle.OpacityMask>
</Rectangle>
<TextBlock Margin="2,0,2,0">import profile</TextBlock>
</StackPanel>
</Button.Content>
</Button>
<Button x:Name="ExportProfile" VerticalAlignment="Top" Style="{DynamicResource SquareButtonStyle}"
Height="26" HorizontalAlignment="Right" Margin="10,0,0,0" IsEnabled="{Binding ProfileSelected}">
<Button.Content>
<StackPanel Orientation="Horizontal">
<Rectangle
Fill="{Binding Path=Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}"
Width="12" Height="12" Margin="3,0">
<Rectangle.OpacityMask>
<VisualBrush Visual="{StaticResource appbar_cabinet_out}" Stretch="Fill" />
</Rectangle.OpacityMask>
</Rectangle>
<TextBlock Margin="2,0,2,0">export profile</TextBlock>
</StackPanel>
</Button.Content>
</Button>
</StackPanel>
<!-- Layer list -->
<Label Grid.Column="1" Grid.Row="0" FontSize="20" HorizontalAlignment="Left" Content="Layers" Margin="10,0,0,0" />
@ -144,18 +177,59 @@
</TreeView.ItemContainerStyle>
</TreeView>
</Border>
<Button Grid.Column="1" Grid.Row="2" Margin="10,5,0,0" x:Name="AddLayer" VerticalAlignment="Top"
Style="{DynamicResource SquareButtonStyle}"
Width="26" Height="26" ToolTip="Add layer" HorizontalAlignment="Right">
<Button.Content>
<Rectangle
Fill="{Binding Path=Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}"
Width="12" Height="12">
<Rectangle.OpacityMask>
<VisualBrush Visual="{StaticResource appbar_add}" Stretch="Fill" />
</Rectangle.OpacityMask>
</Rectangle>
</Button.Content>
</Button>
<StackPanel Grid.Column="1" Grid.Row="2" Orientation="Horizontal" Margin="10,5,0,0" HorizontalAlignment="Right">
<Button x:Name="AddLayer" VerticalAlignment="Top"
Style="{DynamicResource SquareButtonStyle}" IsEnabled="{Binding ProfileSelected}"
Width="26" Height="26" ToolTip="Add layer" HorizontalAlignment="Left">
<Button.Content>
<Rectangle
Fill="{Binding Path=Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}"
Width="12" Height="12">
<Rectangle.OpacityMask>
<VisualBrush Visual="{StaticResource appbar_add}" Stretch="Fill" />
</Rectangle.OpacityMask>
</Rectangle>
</Button.Content>
</Button>
<Button x:Name="EditLayer" VerticalAlignment="Top" Style="{DynamicResource SquareButtonStyle}"
Width="26" Height="26" HorizontalAlignment="Right" Margin="10,0,0,0" ToolTip="Rename layer"
IsEnabled="{Binding Path=LayerSelected}">
<Button.Content>
<Rectangle
Fill="{Binding Path=Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}"
Width="12" Height="12">
<Rectangle.OpacityMask>
<VisualBrush Visual="{StaticResource appbar_edit}" Stretch="Fill" />
</Rectangle.OpacityMask>
</Rectangle>
</Button.Content>
</Button>
<Button x:Name="CloneLayer" VerticalAlignment="Top" Style="{DynamicResource SquareButtonStyle}"
Width="26" Height="26" HorizontalAlignment="Right" Margin="10,0,0,0" ToolTip="Duplicate layer"
IsEnabled="{Binding Path=LayerSelected}">
<Button.Content>
<Rectangle
Fill="{Binding Path=Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}"
Width="12" Height="12">
<Rectangle.OpacityMask>
<VisualBrush Visual="{StaticResource appbar_clipboard_paste}" Stretch="Fill" />
</Rectangle.OpacityMask>
</Rectangle>
</Button.Content>
</Button>
<Button x:Name="RemoveLayer" VerticalAlignment="Top" Style="{DynamicResource SquareButtonStyle}"
Width="26" Height="26" HorizontalAlignment="Right" Margin="10,0,0,0" ToolTip="Delete layer"
IsEnabled="{Binding Path=LayerSelected}">
<Button.Content>
<Rectangle
Fill="{Binding Path=Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}"
Width="12" Height="12">
<Rectangle.OpacityMask>
<VisualBrush Visual="{StaticResource appbar_delete}" Stretch="Fill" />
</Rectangle.OpacityMask>
</Rectangle>
</Button.Content>
</Button>
</StackPanel>
</Grid>
</UserControl>

View File

@ -18,8 +18,8 @@
<package id="Ninject.Extensions.Factory" version="3.2.1.0" targetFramework="net452" />
<package id="Ninject.Extensions.Logging" version="3.2.3.0" targetFramework="net452" />
<package id="Ninject.Extensions.Logging.nlog4" version="3.2.3.0" targetFramework="net452" />
<package id="NLog" version="4.3.3" targetFramework="net452" />
<package id="NLog.Schema" version="4.3.0" targetFramework="net452" />
<package id="NLog" version="4.3.4" targetFramework="net452" />
<package id="NLog.Schema" version="4.3.4" targetFramework="net452" />
<package id="SharpDX" version="3.0.2" targetFramework="net452" />
<package id="SharpDX.Direct3D11" version="3.0.2" targetFramework="net452" />
<package id="SharpDX.DXGI" version="3.0.2" targetFramework="net452" />