mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-31 09:43:46 +00:00
Basic implementation of a few editor tools
This commit is contained in:
parent
580db3185e
commit
8539f05d90
@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Artemis.Core.Models.Profile.LayerShapes;
|
||||||
using Artemis.Core.Models.Surface;
|
using Artemis.Core.Models.Surface;
|
||||||
using Artemis.Storage.Entities.Profile;
|
using Artemis.Storage.Entities.Profile;
|
||||||
using SkiaSharp;
|
using SkiaSharp;
|
||||||
@ -72,6 +73,7 @@ namespace Artemis.Core.Models.Profile
|
|||||||
public Layer AddLayer(string name)
|
public Layer AddLayer(string name)
|
||||||
{
|
{
|
||||||
var layer = new Layer(Profile, this, name) {Order = Children.LastOrDefault()?.Order ?? 1};
|
var layer = new Layer(Profile, this, name) {Order = Children.LastOrDefault()?.Order ?? 1};
|
||||||
|
layer.LayerShape = new Fill(layer);
|
||||||
AddChild(layer);
|
AddChild(layer);
|
||||||
return layer;
|
return layer;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -97,7 +97,8 @@ namespace Artemis.Core.Models.Profile
|
|||||||
set
|
set
|
||||||
{
|
{
|
||||||
_layerShape = value;
|
_layerShape = value;
|
||||||
_layerShape.CalculateRenderProperties();
|
if (Path != null)
|
||||||
|
_layerShape.CalculateRenderProperties();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,15 +147,18 @@ namespace Artemis.Core.Models.Profile
|
|||||||
LayerEntity.Condition.Clear();
|
LayerEntity.Condition.Clear();
|
||||||
|
|
||||||
// Brush
|
// Brush
|
||||||
LayerEntity.BrushEntity = new BrushEntity
|
if (LayerBrush != null)
|
||||||
{
|
{
|
||||||
BrushPluginGuid = LayerBrush.Descriptor.LayerBrushProvider.PluginInfo.Guid,
|
LayerEntity.BrushEntity = new BrushEntity
|
||||||
BrushType = LayerBrush.GetType().Name,
|
{
|
||||||
Configuration = JsonConvert.SerializeObject(LayerBrush.Settings)
|
BrushPluginGuid = LayerBrush.Descriptor.LayerBrushProvider.PluginInfo.Guid,
|
||||||
};
|
BrushType = LayerBrush.GetType().Name,
|
||||||
|
Configuration = JsonConvert.SerializeObject(LayerBrush.Settings)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// Shape
|
// Shape
|
||||||
LayerShape.ApplyToEntity();
|
LayerShape?.ApplyToEntity();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@ -67,6 +67,11 @@ namespace Artemis.Core.Models.Profile
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Folder GetRootFolder()
|
||||||
|
{
|
||||||
|
return (Folder) Children.Single();
|
||||||
|
}
|
||||||
|
|
||||||
internal override void ApplyToEntity()
|
internal override void ApplyToEntity()
|
||||||
{
|
{
|
||||||
ProfileEntity.Id = EntityId;
|
ProfileEntity.Id = EntityId;
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
using AppDomainToolkit;
|
using AppDomainToolkit;
|
||||||
using Artemis.Core.Events;
|
using Artemis.Core.Events;
|
||||||
using Artemis.Core.Exceptions;
|
using Artemis.Core.Exceptions;
|
||||||
@ -215,8 +216,19 @@ namespace Artemis.Core.Services
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get the Plugin implementation from the main assembly and if there is only one, instantiate it
|
// Get the Plugin implementation from the main assembly and if there is only one, instantiate it
|
||||||
var mainAssembly = pluginInfo.Context.Domain.GetAssemblies().First(a => a.Location == mainFile);
|
List<Type> pluginTypes;
|
||||||
var pluginTypes = mainAssembly.GetTypes().Where(t => typeof(Plugin).IsAssignableFrom(t)).ToList();
|
var mainAssembly = pluginInfo.Context.Domain.GetAssemblies().FirstOrDefault(a => a.Location == mainFile);
|
||||||
|
if (mainAssembly == null)
|
||||||
|
throw new ArtemisPluginException(pluginInfo, "Found no supported assembly in the plugins main file");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
pluginTypes = mainAssembly.GetTypes().Where(t => typeof(Plugin).IsAssignableFrom(t)).ToList();
|
||||||
|
}
|
||||||
|
catch (ReflectionTypeLoadException e)
|
||||||
|
{
|
||||||
|
throw new ArtemisPluginException(pluginInfo, "Failed to initialize the plugin assembly", new AggregateException(e.LoaderExceptions));
|
||||||
|
}
|
||||||
|
|
||||||
if (pluginTypes.Count > 1)
|
if (pluginTypes.Count > 1)
|
||||||
throw new ArtemisPluginException(pluginInfo, $"Plugin contains {pluginTypes.Count} implementations of Plugin, only 1 allowed");
|
throw new ArtemisPluginException(pluginInfo, $"Plugin contains {pluginTypes.Count} implementations of Plugin, only 1 allowed");
|
||||||
if (pluginTypes.Count == 0)
|
if (pluginTypes.Count == 0)
|
||||||
|
|||||||
@ -1,10 +1,12 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using Artemis.Core.Events;
|
using Artemis.Core.Events;
|
||||||
using Artemis.Core.Plugins.Models;
|
using Artemis.Core.Plugins.Models;
|
||||||
using Artemis.Core.RGB.NET;
|
using Artemis.Core.RGB.NET;
|
||||||
using Artemis.Core.Services.Interfaces;
|
using Artemis.Core.Services.Interfaces;
|
||||||
using RGB.NET.Brushes;
|
using RGB.NET.Brushes;
|
||||||
|
using RGB.NET.Brushes.Gradients;
|
||||||
using RGB.NET.Core;
|
using RGB.NET.Core;
|
||||||
using RGB.NET.Groups;
|
using RGB.NET.Groups;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
@ -104,7 +106,7 @@ namespace Artemis.Core.Services
|
|||||||
{
|
{
|
||||||
// Apply the application wide brush and decorator
|
// Apply the application wide brush and decorator
|
||||||
BitmapBrush = new BitmapBrush(new Scale(_renderScaleSetting.Value));
|
BitmapBrush = new BitmapBrush(new Scale(_renderScaleSetting.Value));
|
||||||
_surfaceLedGroup = new ListLedGroup(Surface.Leds) { Brush = BitmapBrush };
|
_surfaceLedGroup = new ListLedGroup(Surface.Leds) {Brush = BitmapBrush};
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,11 +117,11 @@ namespace Artemis.Core.Services
|
|||||||
|
|
||||||
// Apply the application wide brush and decorator
|
// Apply the application wide brush and decorator
|
||||||
BitmapBrush.Scale = new Scale(_renderScaleSetting.Value);
|
BitmapBrush.Scale = new Scale(_renderScaleSetting.Value);
|
||||||
_surfaceLedGroup = new ListLedGroup(Surface.Leds) { Brush = BitmapBrush };
|
_surfaceLedGroup = new ListLedGroup(Surface.Leds) {Brush = BitmapBrush};
|
||||||
}
|
}
|
||||||
|
|
||||||
lock (BitmapBrush)
|
lock (BitmapBrush)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -50,14 +50,6 @@
|
|||||||
<Compile Include="WootingDeviceProvider.cs" />
|
<Compile Include="WootingDeviceProvider.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
|
||||||
<Content Include="x64\wooting-rgb-sdk64.dll">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</Content>
|
|
||||||
<Content Include="x86\wooting-rgb-sdk.dll">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</Content>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="plugin.json">
|
<None Include="plugin.json">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
@ -69,6 +61,10 @@
|
|||||||
<Name>Artemis.Core</Name>
|
<Name>Artemis.Core</Name>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Folder Include="x64\" />
|
||||||
|
<Folder Include="x86\" />
|
||||||
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<PostBuildEvent>echo Copying resources to plugin output directory
|
<PostBuildEvent>echo Copying resources to plugin output directory
|
||||||
|
|||||||
@ -172,6 +172,7 @@
|
|||||||
<Compile Include="Converters\NullToImageConverter.cs" />
|
<Compile Include="Converters\NullToImageConverter.cs" />
|
||||||
<Compile Include="Converters\NullToVisibilityConverter.cs" />
|
<Compile Include="Converters\NullToVisibilityConverter.cs" />
|
||||||
<Compile Include="Events\MainWindowFocusChangedEvent.cs" />
|
<Compile Include="Events\MainWindowFocusChangedEvent.cs" />
|
||||||
|
<Compile Include="Events\MainWindowKeyEvent.cs" />
|
||||||
<Compile Include="Events\WindowsThemeEventArgs.cs" />
|
<Compile Include="Events\WindowsThemeEventArgs.cs" />
|
||||||
<Compile Include="Screens\GradientEditor\GradientEditorViewModel.cs" />
|
<Compile Include="Screens\GradientEditor\GradientEditorViewModel.cs" />
|
||||||
<Compile Include="Screens\Module\ProfileEditor\LayerProperties\LayerPropertiesView.xaml.cs">
|
<Compile Include="Screens\Module\ProfileEditor\LayerProperties\LayerPropertiesView.xaml.cs">
|
||||||
@ -222,8 +223,8 @@
|
|||||||
<Compile Include="Screens\Sidebar\SidebarViewModel.cs" />
|
<Compile Include="Screens\Sidebar\SidebarViewModel.cs" />
|
||||||
<Compile Include="Services\Interfaces\IProfileEditorService.cs" />
|
<Compile Include="Services\Interfaces\IProfileEditorService.cs" />
|
||||||
<Compile Include="Services\ProfileEditorService.cs" />
|
<Compile Include="Services\ProfileEditorService.cs" />
|
||||||
<Compile Include="Utilities\BindableSelectedItemBehavior.cs" />
|
|
||||||
<Compile Include="Utilities\ThemeWatcher.cs" />
|
<Compile Include="Utilities\ThemeWatcher.cs" />
|
||||||
|
<Compile Include="Behaviors\TreeViewSelectionBehavior.cs" />
|
||||||
<Compile Include="Utilities\TriggerTracing.cs" />
|
<Compile Include="Utilities\TriggerTracing.cs" />
|
||||||
<Compile Include="Exceptions\ArtemisCoreException.cs" />
|
<Compile Include="Exceptions\ArtemisCoreException.cs" />
|
||||||
<Compile Include="Extensions\RgbColorExtensions.cs" />
|
<Compile Include="Extensions\RgbColorExtensions.cs" />
|
||||||
@ -520,6 +521,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="Resources\aero_fill.cur" />
|
<None Include="Resources\aero_fill.cur" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup />
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<PostBuildEvent>
|
<PostBuildEvent>
|
||||||
|
|||||||
174
src/Artemis.UI/Behaviors/TreeViewSelectionBehavior.cs
Normal file
174
src/Artemis.UI/Behaviors/TreeViewSelectionBehavior.cs
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
using System.Collections.Specialized;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Controls;
|
||||||
|
using System.Windows.Interactivity;
|
||||||
|
|
||||||
|
namespace Artemis.UI.Behaviors
|
||||||
|
{
|
||||||
|
public class TreeViewSelectionBehavior : Behavior<TreeView>
|
||||||
|
{
|
||||||
|
public delegate bool IsChildOfPredicate(object nodeA, object nodeB);
|
||||||
|
|
||||||
|
public static readonly DependencyProperty SelectedItemProperty =
|
||||||
|
DependencyProperty.Register(nameof(SelectedItem), typeof(object),
|
||||||
|
typeof(TreeViewSelectionBehavior),
|
||||||
|
new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
|
||||||
|
OnSelectedItemChanged));
|
||||||
|
|
||||||
|
public static readonly DependencyProperty HierarchyPredicateProperty =
|
||||||
|
DependencyProperty.Register(nameof(HierarchyPredicate), typeof(IsChildOfPredicate),
|
||||||
|
typeof(TreeViewSelectionBehavior),
|
||||||
|
new FrameworkPropertyMetadata(null));
|
||||||
|
|
||||||
|
public static readonly DependencyProperty ExpandSelectedProperty =
|
||||||
|
DependencyProperty.Register(nameof(ExpandSelected), typeof(bool),
|
||||||
|
typeof(TreeViewSelectionBehavior),
|
||||||
|
new FrameworkPropertyMetadata(false));
|
||||||
|
|
||||||
|
private readonly EventSetter _treeViewItemEventSetter;
|
||||||
|
private bool _modelHandled;
|
||||||
|
|
||||||
|
public TreeViewSelectionBehavior()
|
||||||
|
{
|
||||||
|
_treeViewItemEventSetter = new EventSetter(
|
||||||
|
FrameworkElement.LoadedEvent,
|
||||||
|
new RoutedEventHandler(OnTreeViewItemLoaded));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bindable selected item
|
||||||
|
public object SelectedItem
|
||||||
|
{
|
||||||
|
get => GetValue(SelectedItemProperty);
|
||||||
|
set => SetValue(SelectedItemProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Predicate that checks if two items are hierarchically related
|
||||||
|
public IsChildOfPredicate HierarchyPredicate
|
||||||
|
{
|
||||||
|
get => (IsChildOfPredicate) GetValue(HierarchyPredicateProperty);
|
||||||
|
set => SetValue(HierarchyPredicateProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Should expand selected?
|
||||||
|
public bool ExpandSelected
|
||||||
|
{
|
||||||
|
get => (bool) GetValue(ExpandSelectedProperty);
|
||||||
|
set => SetValue(ExpandSelectedProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void OnSelectedItemChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
|
||||||
|
{
|
||||||
|
var behavior = (TreeViewSelectionBehavior) sender;
|
||||||
|
if (behavior._modelHandled) return;
|
||||||
|
|
||||||
|
if (behavior.AssociatedObject == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
behavior._modelHandled = true;
|
||||||
|
behavior.UpdateAllTreeViewItems();
|
||||||
|
behavior._modelHandled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update state of all items starting with given, with optional recursion
|
||||||
|
private void UpdateTreeViewItem(TreeViewItem item, bool recurse)
|
||||||
|
{
|
||||||
|
if (SelectedItem == null) return;
|
||||||
|
var model = item.DataContext;
|
||||||
|
|
||||||
|
// If the selected item is this model and is not yet selected - select and return
|
||||||
|
if (SelectedItem == model && !item.IsSelected)
|
||||||
|
{
|
||||||
|
item.IsSelected = true;
|
||||||
|
if (ExpandSelected)
|
||||||
|
item.IsExpanded = true;
|
||||||
|
}
|
||||||
|
// If the selected item is a parent of this model - expand
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var isParentOfModel = HierarchyPredicate?.Invoke(SelectedItem, model) ?? true;
|
||||||
|
if (isParentOfModel)
|
||||||
|
item.IsExpanded = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recurse into children
|
||||||
|
if (recurse)
|
||||||
|
{
|
||||||
|
foreach (var subitem in item.Items)
|
||||||
|
{
|
||||||
|
var tvi = item.ItemContainerGenerator.ContainerFromItem(subitem) as TreeViewItem;
|
||||||
|
if (tvi != null)
|
||||||
|
UpdateTreeViewItem(tvi, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update state of all items
|
||||||
|
private void UpdateAllTreeViewItems()
|
||||||
|
{
|
||||||
|
var treeView = AssociatedObject;
|
||||||
|
foreach (var item in treeView.Items)
|
||||||
|
{
|
||||||
|
var tvi = treeView.ItemContainerGenerator.ContainerFromItem(item) as TreeViewItem;
|
||||||
|
if (tvi != null)
|
||||||
|
UpdateTreeViewItem(tvi, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inject Loaded event handler into ItemContainerStyle
|
||||||
|
private void UpdateTreeViewItemStyle()
|
||||||
|
{
|
||||||
|
if (AssociatedObject.ItemContainerStyle == null)
|
||||||
|
{
|
||||||
|
AssociatedObject.ItemContainerStyle = new Style(
|
||||||
|
typeof(TreeViewItem),
|
||||||
|
Application.Current.TryFindResource(typeof(TreeViewItem)) as Style);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!AssociatedObject.ItemContainerStyle.Setters.Contains(_treeViewItemEventSetter))
|
||||||
|
AssociatedObject.ItemContainerStyle.Setters.Add(_treeViewItemEventSetter);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnTreeViewItemsChanged(object sender,
|
||||||
|
NotifyCollectionChangedEventArgs args)
|
||||||
|
{
|
||||||
|
UpdateAllTreeViewItems();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnTreeViewSelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> args)
|
||||||
|
{
|
||||||
|
if (_modelHandled) return;
|
||||||
|
if (AssociatedObject.Items.SourceCollection == null) return;
|
||||||
|
SelectedItem = args.NewValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnTreeViewItemLoaded(object sender, RoutedEventArgs args)
|
||||||
|
{
|
||||||
|
UpdateTreeViewItem((TreeViewItem) sender, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnAttached()
|
||||||
|
{
|
||||||
|
base.OnAttached();
|
||||||
|
|
||||||
|
AssociatedObject.SelectedItemChanged += OnTreeViewSelectedItemChanged;
|
||||||
|
((INotifyCollectionChanged) AssociatedObject.Items).CollectionChanged += OnTreeViewItemsChanged;
|
||||||
|
|
||||||
|
UpdateTreeViewItemStyle();
|
||||||
|
_modelHandled = true;
|
||||||
|
UpdateAllTreeViewItems();
|
||||||
|
_modelHandled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnDetaching()
|
||||||
|
{
|
||||||
|
base.OnDetaching();
|
||||||
|
|
||||||
|
if (AssociatedObject != null)
|
||||||
|
{
|
||||||
|
AssociatedObject.ItemContainerStyle?.Setters?.Remove(_treeViewItemEventSetter);
|
||||||
|
AssociatedObject.SelectedItemChanged -= OnTreeViewSelectedItemChanged;
|
||||||
|
((INotifyCollectionChanged) AssociatedObject.Items).CollectionChanged -= OnTreeViewItemsChanged;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
16
src/Artemis.UI/Events/MainWindowKeyEvent.cs
Normal file
16
src/Artemis.UI/Events/MainWindowKeyEvent.cs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
using System.Windows.Input;
|
||||||
|
|
||||||
|
namespace Artemis.UI.Events
|
||||||
|
{
|
||||||
|
public class MainWindowKeyEvent
|
||||||
|
{
|
||||||
|
public bool KeyDown { get; }
|
||||||
|
public KeyEventArgs EventArgs { get; }
|
||||||
|
|
||||||
|
public MainWindowKeyEvent(bool keyDown, KeyEventArgs eventArgs)
|
||||||
|
{
|
||||||
|
KeyDown = keyDown;
|
||||||
|
EventArgs = eventArgs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -7,9 +7,9 @@
|
|||||||
xmlns:s="https://github.com/canton7/Stylet"
|
xmlns:s="https://github.com/canton7/Stylet"
|
||||||
xmlns:dd="urn:gong-wpf-dragdrop"
|
xmlns:dd="urn:gong-wpf-dragdrop"
|
||||||
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
|
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
|
||||||
xmlns:utilities="clr-namespace:Artemis.UI.Utilities"
|
|
||||||
xmlns:profileTree="clr-namespace:Artemis.UI.Screens.Module.ProfileEditor.ProfileTree"
|
xmlns:profileTree="clr-namespace:Artemis.UI.Screens.Module.ProfileEditor.ProfileTree"
|
||||||
xmlns:treeItem="clr-namespace:Artemis.UI.Screens.Module.ProfileEditor.ProfileTree.TreeItem"
|
xmlns:treeItem="clr-namespace:Artemis.UI.Screens.Module.ProfileEditor.ProfileTree.TreeItem"
|
||||||
|
xmlns:behaviors="clr-namespace:Artemis.UI.Behaviors"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
d:DesignHeight="450" d:DesignWidth="800"
|
d:DesignHeight="450" d:DesignWidth="800"
|
||||||
d:DataContext="{d:DesignInstance {x:Type profileTree:ProfileTreeViewModel}}">
|
d:DataContext="{d:DesignInstance {x:Type profileTree:ProfileTreeViewModel}}">
|
||||||
@ -33,7 +33,7 @@
|
|||||||
dd:DragDrop.IsDropTarget="True"
|
dd:DragDrop.IsDropTarget="True"
|
||||||
dd:DragDrop.DropHandler="{Binding}">
|
dd:DragDrop.DropHandler="{Binding}">
|
||||||
<i:Interaction.Behaviors>
|
<i:Interaction.Behaviors>
|
||||||
<utilities:BindableSelectedItemBehavior SelectedItem="{Binding SelectedTreeItem, Mode=TwoWay}" />
|
<behaviors:TreeViewSelectionBehavior ExpandSelected="True" SelectedItem="{Binding SelectedTreeItem}" />
|
||||||
</i:Interaction.Behaviors>
|
</i:Interaction.Behaviors>
|
||||||
<TreeView.Resources>
|
<TreeView.Resources>
|
||||||
<HierarchicalDataTemplate DataType="{x:Type treeItem:FolderViewModel}" ItemsSource="{Binding Children}">
|
<HierarchicalDataTemplate DataType="{x:Type treeItem:FolderViewModel}" ItemsSource="{Binding Children}">
|
||||||
|
|||||||
@ -2,10 +2,12 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using Artemis.Core.Models.Profile;
|
using Artemis.Core.Models.Profile;
|
||||||
|
using Artemis.UI.Behaviors;
|
||||||
using Artemis.UI.Ninject.Factories;
|
using Artemis.UI.Ninject.Factories;
|
||||||
using Artemis.UI.Screens.Module.ProfileEditor.ProfileTree.TreeItem;
|
using Artemis.UI.Screens.Module.ProfileEditor.ProfileTree.TreeItem;
|
||||||
using Artemis.UI.Services.Interfaces;
|
using Artemis.UI.Services.Interfaces;
|
||||||
using GongSolutions.Wpf.DragDrop;
|
using GongSolutions.Wpf.DragDrop;
|
||||||
|
using Stylet;
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree
|
namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree
|
||||||
{
|
{
|
||||||
@ -13,12 +15,16 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree
|
|||||||
{
|
{
|
||||||
private readonly IProfileEditorService _profileEditorService;
|
private readonly IProfileEditorService _profileEditorService;
|
||||||
private readonly IFolderViewModelFactory _folderViewModelFactory;
|
private readonly IFolderViewModelFactory _folderViewModelFactory;
|
||||||
|
private readonly ILayerViewModelFactory _layerViewModelFactory;
|
||||||
private TreeItemViewModel _selectedTreeItem;
|
private TreeItemViewModel _selectedTreeItem;
|
||||||
|
|
||||||
public ProfileTreeViewModel(IProfileEditorService profileEditorService, IFolderViewModelFactory folderViewModelFactory)
|
public ProfileTreeViewModel(IProfileEditorService profileEditorService,
|
||||||
|
IFolderViewModelFactory folderViewModelFactory,
|
||||||
|
ILayerViewModelFactory layerViewModelFactory)
|
||||||
{
|
{
|
||||||
_profileEditorService = profileEditorService;
|
_profileEditorService = profileEditorService;
|
||||||
_folderViewModelFactory = folderViewModelFactory;
|
_folderViewModelFactory = folderViewModelFactory;
|
||||||
|
_layerViewModelFactory = layerViewModelFactory;
|
||||||
|
|
||||||
CreateRootFolderViewModel();
|
CreateRootFolderViewModel();
|
||||||
_profileEditorService.SelectedProfileChanged += OnSelectedProfileChanged;
|
_profileEditorService.SelectedProfileChanged += OnSelectedProfileChanged;
|
||||||
@ -139,6 +145,27 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree
|
|||||||
|
|
||||||
// Don't set it using the setter or that will trigger the event again
|
// Don't set it using the setter or that will trigger the event again
|
||||||
_selectedTreeItem = vms?.FirstOrDefault(vm => vm.ProfileElement == _profileEditorService.SelectedProfileElement);
|
_selectedTreeItem = vms?.FirstOrDefault(vm => vm.ProfileElement == _profileEditorService.SelectedProfileElement);
|
||||||
|
|
||||||
|
if (_selectedTreeItem == null && _profileEditorService.SelectedProfileElement != null)
|
||||||
|
{
|
||||||
|
var parent = vms?.FirstOrDefault(vm => vm.ProfileElement == _profileEditorService.SelectedProfileElement.Parent);
|
||||||
|
if (parent == null)
|
||||||
|
{
|
||||||
|
// Eh.. we did our best.. start over
|
||||||
|
CreateRootFolderViewModel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new TreeItemViewModel for the new ProfileElement
|
||||||
|
TreeItemViewModel treeItemViewModel;
|
||||||
|
if (_profileEditorService.SelectedProfileElement is Folder folder)
|
||||||
|
treeItemViewModel = _folderViewModelFactory.Create(parent, folder);
|
||||||
|
else
|
||||||
|
treeItemViewModel = _layerViewModelFactory.Create(parent, (Layer) _profileEditorService.SelectedProfileElement);
|
||||||
|
parent.AddExistingElement(treeItemViewModel);
|
||||||
|
_selectedTreeItem = treeItemViewModel;
|
||||||
|
}
|
||||||
|
|
||||||
NotifyOfPropertyChange(() => SelectedTreeItem);
|
NotifyOfPropertyChange(() => SelectedTreeItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -49,7 +49,7 @@
|
|||||||
</Path>
|
</Path>
|
||||||
|
|
||||||
<!-- Selection -->
|
<!-- Selection -->
|
||||||
<Path Data="{Binding DisplayGeometry, Mode=OneWay}" ClipToBounds="False" StrokeThickness="2">
|
<Path Data="{Binding DisplayGeometry, Mode=OneWay}" ClipToBounds="False" StrokeThickness="1">
|
||||||
<Path.Style>
|
<Path.Style>
|
||||||
<Style TargetType="{x:Type Path}">
|
<Style TargetType="{x:Type Path}">
|
||||||
<Style.Triggers>
|
<Style.Triggers>
|
||||||
@ -83,10 +83,10 @@
|
|||||||
</Style>
|
</Style>
|
||||||
</Path.Style>
|
</Path.Style>
|
||||||
<Path.Fill>
|
<Path.Fill>
|
||||||
<SolidColorBrush Opacity="0.65" />
|
<SolidColorBrush Opacity="0.25" />
|
||||||
</Path.Fill>
|
</Path.Fill>
|
||||||
<Path.Stroke>
|
<Path.Stroke>
|
||||||
<SolidColorBrush />
|
<SolidColorBrush Opacity="0.5"/>
|
||||||
</Path.Stroke>
|
</Path.Stroke>
|
||||||
</Path>
|
</Path>
|
||||||
</Canvas>
|
</Canvas>
|
||||||
|
|||||||
@ -46,17 +46,17 @@
|
|||||||
<ColumnDefinition Width="*" />
|
<ColumnDefinition Width="*" />
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<ToolBarTray Orientation="Vertical" Width="58">
|
<ToolBarTray Orientation="Vertical" Width="58">
|
||||||
<ToolBar Style="{DynamicResource MaterialDesignToolBar}" ClipToBounds="False" ToolBarTray.IsLocked="True" >
|
<ToolBar Style="{DynamicResource MaterialDesignToolBar}" ClipToBounds="False" ToolBarTray.IsLocked="True">
|
||||||
<ListBox SelectedIndex="{Binding ActiveToolIndex}" ToolBar.OverflowMode="Never">
|
<ListBox SelectedIndex="{Binding ActiveToolIndex}" ToolBar.OverflowMode="Never">
|
||||||
<ListBox.ItemsPanel>
|
<ListBox.ItemsPanel>
|
||||||
<ItemsPanelTemplate>
|
<ItemsPanelTemplate>
|
||||||
<StackPanel Orientation="Vertical"/>
|
<StackPanel Orientation="Vertical" />
|
||||||
</ItemsPanelTemplate>
|
</ItemsPanelTemplate>
|
||||||
</ListBox.ItemsPanel>
|
</ListBox.ItemsPanel>
|
||||||
<ListBoxItem ToolTip="Pan over different parts of the surface" >
|
<ListBoxItem ToolTip="Pan over different parts of the surface">
|
||||||
<materialDesign:PackIcon Kind="HandLeft" />
|
<materialDesign:PackIcon Kind="HandLeft" />
|
||||||
</ListBoxItem>
|
</ListBoxItem>
|
||||||
<ListBoxItem ToolTip="Change layer selection" >
|
<ListBoxItem ToolTip="Change layer selection">
|
||||||
<materialDesign:PackIcon Kind="SelectionDrag" />
|
<materialDesign:PackIcon Kind="SelectionDrag" />
|
||||||
</ListBoxItem>
|
</ListBoxItem>
|
||||||
<ListBoxItem ToolTip="Add to layer selection">
|
<ListBoxItem ToolTip="Add to layer selection">
|
||||||
@ -84,11 +84,9 @@
|
|||||||
</ToolBarTray>
|
</ToolBarTray>
|
||||||
<Grid Grid.Column="1"
|
<Grid Grid.Column="1"
|
||||||
ClipToBounds="True"
|
ClipToBounds="True"
|
||||||
KeyUp="{s:Action CanvasKeyUp}"
|
|
||||||
KeyDown="{s:Action CanvasKeyDown}"
|
|
||||||
MouseWheel="{s:Action CanvasMouseWheel}"
|
MouseWheel="{s:Action CanvasMouseWheel}"
|
||||||
MouseUp="{s:Action CanvasMouseDown}"
|
MouseUp="{s:Action CanvasMouseUp}"
|
||||||
MouseDown="{s:Action CanvasMouseUp}"
|
MouseDown="{s:Action CanvasMouseDown}"
|
||||||
MouseMove="{s:Action CanvasMouseMove}"
|
MouseMove="{s:Action CanvasMouseMove}"
|
||||||
Cursor="{Binding ActiveToolViewModel.Cursor}"
|
Cursor="{Binding ActiveToolViewModel.Cursor}"
|
||||||
utilities:SizeObserver.Observe="True"
|
utilities:SizeObserver.Observe="True"
|
||||||
@ -123,7 +121,7 @@
|
|||||||
<TranslateTransform X="{Binding PanZoomViewModel.PanX}" Y="{Binding PanZoomViewModel.PanY}" />
|
<TranslateTransform X="{Binding PanZoomViewModel.PanX}" Y="{Binding PanZoomViewModel.PanY}" />
|
||||||
</TransformGroup>
|
</TransformGroup>
|
||||||
</Grid.RenderTransform>
|
</Grid.RenderTransform>
|
||||||
<ItemsControl ItemsSource="{Binding Devices}">
|
<ItemsControl ItemsSource="{Binding CanvasViewModels}">
|
||||||
<ItemsControl.ItemsPanel>
|
<ItemsControl.ItemsPanel>
|
||||||
<ItemsPanelTemplate>
|
<ItemsPanelTemplate>
|
||||||
<Canvas />
|
<Canvas />
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using System.Windows.Media;
|
|
||||||
using Artemis.Core.Events;
|
using Artemis.Core.Events;
|
||||||
using Artemis.Core.Models.Profile;
|
using Artemis.Core.Models.Profile;
|
||||||
using Artemis.Core.Models.Surface;
|
using Artemis.Core.Models.Surface;
|
||||||
@ -19,11 +19,14 @@ using Stylet;
|
|||||||
|
|
||||||
namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
|
namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
|
||||||
{
|
{
|
||||||
public class ProfileViewModel : ProfileEditorPanelViewModel, IHandle<MainWindowFocusChangedEvent>
|
public class ProfileViewModel : ProfileEditorPanelViewModel, IHandle<MainWindowFocusChangedEvent>, IHandle<MainWindowKeyEvent>
|
||||||
{
|
{
|
||||||
private readonly IProfileEditorService _profileEditorService;
|
private readonly IProfileEditorService _profileEditorService;
|
||||||
private readonly ISettingsService _settingsService;
|
private readonly ISettingsService _settingsService;
|
||||||
private readonly ISurfaceService _surfaceService;
|
private readonly ISurfaceService _surfaceService;
|
||||||
|
private int _activeToolIndex;
|
||||||
|
private VisualizationToolViewModel _activeToolViewModel;
|
||||||
|
private int _previousTool;
|
||||||
private TimerUpdateTrigger _updateTrigger;
|
private TimerUpdateTrigger _updateTrigger;
|
||||||
|
|
||||||
public ProfileViewModel(IProfileEditorService profileEditorService, ISurfaceService surfaceService, ISettingsService settingsService, IEventAggregator eventAggregator)
|
public ProfileViewModel(IProfileEditorService profileEditorService, ISurfaceService surfaceService, ISettingsService settingsService, IEventAggregator eventAggregator)
|
||||||
@ -66,12 +69,19 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
|
|||||||
{
|
{
|
||||||
// Remove the tool from the canvas
|
// Remove the tool from the canvas
|
||||||
if (_activeToolViewModel != null)
|
if (_activeToolViewModel != null)
|
||||||
|
{
|
||||||
CanvasViewModels.Remove(_activeToolViewModel);
|
CanvasViewModels.Remove(_activeToolViewModel);
|
||||||
|
NotifyOfPropertyChange(() => CanvasViewModels);
|
||||||
|
}
|
||||||
|
|
||||||
// Set the new tool
|
// Set the new tool
|
||||||
_activeToolViewModel = value;
|
_activeToolViewModel = value;
|
||||||
// Add the new tool to the canvas
|
// Add the new tool to the canvas
|
||||||
if (_activeToolViewModel != null)
|
if (_activeToolViewModel != null)
|
||||||
|
{
|
||||||
CanvasViewModels.Add(_activeToolViewModel);
|
CanvasViewModels.Add(_activeToolViewModel);
|
||||||
|
NotifyOfPropertyChange(() => CanvasViewModels);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,8 +90,12 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
|
|||||||
get => _activeToolIndex;
|
get => _activeToolIndex;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
_activeToolIndex = value;
|
if (_activeToolIndex != value)
|
||||||
ActivateToolByIndex(value);
|
{
|
||||||
|
_activeToolIndex = value;
|
||||||
|
ActivateToolByIndex(value);
|
||||||
|
NotifyOfPropertyChange(() => ActiveToolIndex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -215,19 +229,21 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
|
|||||||
case 3:
|
case 3:
|
||||||
ActiveToolViewModel = new SelectionRemoveToolViewModel(this, _profileEditorService);
|
ActiveToolViewModel = new SelectionRemoveToolViewModel(this, _profileEditorService);
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 5:
|
||||||
ActiveToolViewModel = new EllipseToolViewModel(this, _profileEditorService);
|
ActiveToolViewModel = new EllipseToolViewModel(this, _profileEditorService);
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 6:
|
||||||
ActiveToolViewModel = new RectangleToolViewModel(this, _profileEditorService);
|
ActiveToolViewModel = new RectangleToolViewModel(this, _profileEditorService);
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 7:
|
||||||
ActiveToolViewModel = new PolygonToolViewModel(this, _profileEditorService);
|
ActiveToolViewModel = new PolygonToolViewModel(this, _profileEditorService);
|
||||||
break;
|
break;
|
||||||
case 7:
|
case 8:
|
||||||
ActiveToolViewModel = new FillToolViewModel(this, _profileEditorService);
|
ActiveToolViewModel = new FillToolViewModel(this, _profileEditorService);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ActiveToolIndex = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ResetZoomAndPan()
|
public void ResetZoomAndPan()
|
||||||
@ -256,6 +272,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
|
|||||||
|
|
||||||
public void CanvasMouseWheel(object sender, MouseWheelEventArgs e)
|
public void CanvasMouseWheel(object sender, MouseWheelEventArgs e)
|
||||||
{
|
{
|
||||||
|
PanZoomViewModel.ProcessMouseScroll(sender, e);
|
||||||
ActiveToolViewModel?.MouseWheel(sender, e);
|
ActiveToolViewModel?.MouseWheel(sender, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -300,27 +317,6 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Keys
|
|
||||||
|
|
||||||
private int _previousTool;
|
|
||||||
private int _activeToolIndex;
|
|
||||||
private VisualizationToolViewModel _activeToolViewModel;
|
|
||||||
|
|
||||||
public void CanvasKeyDown(object sender, KeyEventArgs e)
|
|
||||||
{
|
|
||||||
_previousTool = ActiveToolIndex;
|
|
||||||
if ((e.Key == Key.LeftCtrl || e.Key == Key.RightCtrl) && e.IsDown)
|
|
||||||
ActiveToolViewModel = new ViewpointMoveToolViewModel(this, _profileEditorService);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void CanvasKeyUp(object sender, KeyEventArgs e)
|
|
||||||
{
|
|
||||||
if ((e.Key == Key.LeftCtrl || e.Key == Key.RightCtrl) && e.IsUp)
|
|
||||||
ActivateToolByIndex(_previousTool);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Event handlers
|
#region Event handlers
|
||||||
|
|
||||||
private void HighlightSelectedLayerOnSettingChanged(object sender, EventArgs e)
|
private void HighlightSelectedLayerOnSettingChanged(object sender, EventArgs e)
|
||||||
@ -352,6 +348,29 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Handle(MainWindowKeyEvent message)
|
||||||
|
{
|
||||||
|
Debug.WriteLine(message.KeyDown);
|
||||||
|
if (message.KeyDown)
|
||||||
|
{
|
||||||
|
if (ActiveToolIndex != 0)
|
||||||
|
{
|
||||||
|
_previousTool = ActiveToolIndex;
|
||||||
|
if ((message.EventArgs.Key == Key.LeftCtrl || message.EventArgs.Key == Key.RightCtrl) && message.EventArgs.IsDown)
|
||||||
|
ActivateToolByIndex(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
ActiveToolViewModel?.KeyDown(message.EventArgs);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((message.EventArgs.Key == Key.LeftCtrl || message.EventArgs.Key == Key.RightCtrl) && message.EventArgs.IsUp)
|
||||||
|
ActivateToolByIndex(_previousTool);
|
||||||
|
|
||||||
|
ActiveToolViewModel?.KeyUp(message.EventArgs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -8,23 +8,30 @@
|
|||||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
d:DesignHeight="450" d:DesignWidth="800">
|
d:DesignHeight="450" d:DesignWidth="800">
|
||||||
<Canvas>
|
<UserControl.Resources>
|
||||||
<Canvas.Triggers>
|
<Style TargetType="Shape" x:Key="ShowIfMouseDown">
|
||||||
<EventTrigger RoutedEvent="Canvas.MouseLeftButtonDown">
|
<Style.Triggers>
|
||||||
<BeginStoryboard>
|
<DataTrigger Binding="{Binding IsMouseDown}" Value="True">
|
||||||
<Storyboard TargetName="Preview" TargetProperty="Opacity">
|
<DataTrigger.EnterActions>
|
||||||
<DoubleAnimation From="0" To="1" Duration="0:0:0.1" />
|
<BeginStoryboard>
|
||||||
</Storyboard>
|
<Storyboard TargetProperty="Opacity">
|
||||||
</BeginStoryboard>
|
<DoubleAnimation From="0" To="1" Duration="0:0:0.1" />
|
||||||
</EventTrigger>
|
</Storyboard>
|
||||||
<EventTrigger RoutedEvent="Canvas.MouseLeftButtonUp">
|
</BeginStoryboard>
|
||||||
<BeginStoryboard>
|
</DataTrigger.EnterActions>
|
||||||
<Storyboard TargetName="Preview" TargetProperty="Opacity">
|
<DataTrigger.ExitActions>
|
||||||
<DoubleAnimation From="1" To="0" Duration="0:0:0.2" />
|
<BeginStoryboard>
|
||||||
</Storyboard>
|
<Storyboard TargetProperty="Opacity">
|
||||||
</BeginStoryboard>
|
<DoubleAnimation From="1" To="0" Duration="0:0:0.2" />
|
||||||
</EventTrigger>
|
</Storyboard>
|
||||||
</Canvas.Triggers>
|
</BeginStoryboard>
|
||||||
|
</DataTrigger.ExitActions>
|
||||||
|
</DataTrigger>
|
||||||
|
</Style.Triggers>
|
||||||
|
</Style>
|
||||||
|
</UserControl.Resources>
|
||||||
|
<Canvas Background="Transparent" Width="50" Height="50">
|
||||||
|
|
||||||
<Canvas.ContextMenu>
|
<Canvas.ContextMenu>
|
||||||
<ContextMenu>
|
<ContextMenu>
|
||||||
<MenuItem Header="Ellipse action 1" Command="{s:Action CreateLayer}" CommandParameter="{Binding}">
|
<MenuItem Header="Ellipse action 1" Command="{s:Action CreateLayer}" CommandParameter="{Binding}">
|
||||||
@ -39,7 +46,14 @@
|
|||||||
</MenuItem>
|
</MenuItem>
|
||||||
</ContextMenu>
|
</ContextMenu>
|
||||||
</Canvas.ContextMenu>
|
</Canvas.ContextMenu>
|
||||||
<Ellipse Stroke="{DynamicResource PrimaryHueLightBrush}" StrokeThickness="1" IsHitTestVisible="False" x:Name="Preview" Opacity="1" Width="100" Height="100">
|
<Ellipse Style="{StaticResource ShowIfMouseDown}"
|
||||||
|
Width="{Binding DragRectangle.Width}"
|
||||||
|
Height="{Binding DragRectangle.Height}"
|
||||||
|
Canvas.Left="{Binding DragRectangle.X}"
|
||||||
|
Canvas.Top="{Binding DragRectangle.Y}"
|
||||||
|
Stroke="{DynamicResource PrimaryHueLightBrush}"
|
||||||
|
StrokeThickness="1"
|
||||||
|
Opacity="0">
|
||||||
<Ellipse.Fill>
|
<Ellipse.Fill>
|
||||||
<SolidColorBrush Color="{DynamicResource Primary400}" Opacity="0.25" />
|
<SolidColorBrush Color="{DynamicResource Primary400}" Opacity="0.25" />
|
||||||
</Ellipse.Fill>
|
</Ellipse.Fill>
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Windows;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using Artemis.UI.Properties;
|
using Artemis.UI.Properties;
|
||||||
using Artemis.UI.Services.Interfaces;
|
using Artemis.UI.Services.Interfaces;
|
||||||
@ -7,6 +8,8 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools
|
|||||||
{
|
{
|
||||||
public class EllipseToolViewModel : VisualizationToolViewModel
|
public class EllipseToolViewModel : VisualizationToolViewModel
|
||||||
{
|
{
|
||||||
|
private bool _shiftDown;
|
||||||
|
|
||||||
public EllipseToolViewModel(ProfileViewModel profileViewModel, IProfileEditorService profileEditorService) : base(profileViewModel, profileEditorService)
|
public EllipseToolViewModel(ProfileViewModel profileViewModel, IProfileEditorService profileEditorService) : base(profileViewModel, profileEditorService)
|
||||||
{
|
{
|
||||||
using (var stream = new MemoryStream(Resources.aero_crosshair))
|
using (var stream = new MemoryStream(Resources.aero_crosshair))
|
||||||
@ -14,5 +17,37 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools
|
|||||||
Cursor = new Cursor(stream);
|
Cursor = new Cursor(stream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Rect DragRectangle { get; set; }
|
||||||
|
|
||||||
|
public override void MouseMove(object sender, MouseEventArgs e)
|
||||||
|
{
|
||||||
|
base.MouseMove(sender, e);
|
||||||
|
|
||||||
|
if (!IsMouseDown)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var position = ProfileViewModel.PanZoomViewModel.GetRelativeMousePosition(sender, e);
|
||||||
|
if (!_shiftDown)
|
||||||
|
DragRectangle = new Rect(MouseDownStartPosition, position);
|
||||||
|
else
|
||||||
|
DragRectangle = GetSquareRectBetweenPoints(MouseDownStartPosition, position);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void KeyUp(KeyEventArgs e)
|
||||||
|
{
|
||||||
|
base.KeyUp(e);
|
||||||
|
|
||||||
|
if (e.Key == Key.LeftShift || e.Key == Key.RightShift)
|
||||||
|
_shiftDown = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void KeyDown(KeyEventArgs e)
|
||||||
|
{
|
||||||
|
base.KeyDown(e);
|
||||||
|
|
||||||
|
if (e.Key == Key.LeftShift || e.Key == Key.RightShift)
|
||||||
|
_shiftDown = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4,9 +4,59 @@
|
|||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:local="clr-namespace:Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools"
|
xmlns:local="clr-namespace:Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools"
|
||||||
|
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||||
|
xmlns:s="https://github.com/canton7/Stylet"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
d:DesignHeight="450" d:DesignWidth="800">
|
d:DesignHeight="450" d:DesignWidth="800">
|
||||||
<Grid>
|
<UserControl.Resources>
|
||||||
|
<Style TargetType="Shape" x:Key="ShowIfMouseDown">
|
||||||
|
<Style.Triggers>
|
||||||
|
<DataTrigger Binding="{Binding IsMouseDown}" Value="True">
|
||||||
|
<DataTrigger.EnterActions>
|
||||||
|
<BeginStoryboard>
|
||||||
|
<Storyboard TargetProperty="Opacity">
|
||||||
|
<DoubleAnimation From="0" To="1" Duration="0:0:0.1" />
|
||||||
|
</Storyboard>
|
||||||
|
</BeginStoryboard>
|
||||||
|
</DataTrigger.EnterActions>
|
||||||
|
<DataTrigger.ExitActions>
|
||||||
|
<BeginStoryboard>
|
||||||
|
<Storyboard TargetProperty="Opacity">
|
||||||
|
<DoubleAnimation From="1" To="0" Duration="0:0:0.2" />
|
||||||
|
</Storyboard>
|
||||||
|
</BeginStoryboard>
|
||||||
|
</DataTrigger.ExitActions>
|
||||||
|
</DataTrigger>
|
||||||
|
</Style.Triggers>
|
||||||
|
</Style>
|
||||||
|
</UserControl.Resources>
|
||||||
|
<Canvas Background="Transparent" Width="50" Height="50">
|
||||||
|
|
||||||
</Grid>
|
<Canvas.ContextMenu>
|
||||||
|
<ContextMenu>
|
||||||
|
<MenuItem Header="Ellipse action 1" Command="{s:Action CreateLayer}" CommandParameter="{Binding}">
|
||||||
|
<MenuItem.Icon>
|
||||||
|
<materialDesign:PackIcon Kind="LayersPlus" />
|
||||||
|
</MenuItem.Icon>
|
||||||
|
</MenuItem>
|
||||||
|
<MenuItem Header="Ellipse action 2" Command="{s:Action ApplyToLayer}" CommandParameter="{Binding}">
|
||||||
|
<MenuItem.Icon>
|
||||||
|
<materialDesign:PackIcon Kind="Selection" />
|
||||||
|
</MenuItem.Icon>
|
||||||
|
</MenuItem>
|
||||||
|
</ContextMenu>
|
||||||
|
</Canvas.ContextMenu>
|
||||||
|
<Rectangle Style="{StaticResource ShowIfMouseDown}"
|
||||||
|
Width="{Binding DragRectangle.Width}"
|
||||||
|
Height="{Binding DragRectangle.Height}"
|
||||||
|
Canvas.Left="{Binding DragRectangle.X}"
|
||||||
|
Canvas.Top="{Binding DragRectangle.Y}"
|
||||||
|
Stroke="{DynamicResource PrimaryHueLightBrush}"
|
||||||
|
StrokeThickness="1"
|
||||||
|
Opacity="0">
|
||||||
|
<Rectangle.Fill>
|
||||||
|
<SolidColorBrush Color="{DynamicResource Primary400}" Opacity="0.25" />
|
||||||
|
</Rectangle.Fill>
|
||||||
|
</Rectangle>
|
||||||
|
</Canvas>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
@ -1,4 +1,5 @@
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Windows;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using Artemis.UI.Properties;
|
using Artemis.UI.Properties;
|
||||||
using Artemis.UI.Services.Interfaces;
|
using Artemis.UI.Services.Interfaces;
|
||||||
@ -7,6 +8,8 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools
|
|||||||
{
|
{
|
||||||
public class RectangleToolViewModel : VisualizationToolViewModel
|
public class RectangleToolViewModel : VisualizationToolViewModel
|
||||||
{
|
{
|
||||||
|
private bool _shiftDown;
|
||||||
|
|
||||||
public RectangleToolViewModel(ProfileViewModel profileViewModel, IProfileEditorService profileEditorService) : base(profileViewModel, profileEditorService)
|
public RectangleToolViewModel(ProfileViewModel profileViewModel, IProfileEditorService profileEditorService) : base(profileViewModel, profileEditorService)
|
||||||
{
|
{
|
||||||
using (var stream = new MemoryStream(Resources.aero_crosshair))
|
using (var stream = new MemoryStream(Resources.aero_crosshair))
|
||||||
@ -14,5 +17,37 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools
|
|||||||
Cursor = new Cursor(stream);
|
Cursor = new Cursor(stream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Rect DragRectangle { get; set; }
|
||||||
|
|
||||||
|
public override void MouseMove(object sender, MouseEventArgs e)
|
||||||
|
{
|
||||||
|
base.MouseMove(sender, e);
|
||||||
|
|
||||||
|
if (!IsMouseDown)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var position = ProfileViewModel.PanZoomViewModel.GetRelativeMousePosition(sender, e);
|
||||||
|
if (!_shiftDown)
|
||||||
|
DragRectangle = new Rect(MouseDownStartPosition, position);
|
||||||
|
else
|
||||||
|
DragRectangle = GetSquareRectBetweenPoints(MouseDownStartPosition, position);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void KeyUp(KeyEventArgs e)
|
||||||
|
{
|
||||||
|
base.KeyUp(e);
|
||||||
|
|
||||||
|
if (e.Key == Key.LeftShift || e.Key == Key.RightShift)
|
||||||
|
_shiftDown = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void KeyDown(KeyEventArgs e)
|
||||||
|
{
|
||||||
|
base.KeyDown(e);
|
||||||
|
|
||||||
|
if (e.Key == Key.LeftShift || e.Key == Key.RightShift)
|
||||||
|
_shiftDown = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4,9 +4,60 @@
|
|||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:local="clr-namespace:Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools"
|
xmlns:local="clr-namespace:Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools"
|
||||||
|
xmlns:s="https://github.com/canton7/Stylet"
|
||||||
|
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
d:DesignHeight="450" d:DesignWidth="800">
|
d:DesignHeight="450" d:DesignWidth="800">
|
||||||
<Grid>
|
<UserControl.Resources>
|
||||||
|
<Style TargetType="Shape" x:Key="ShowIfMouseDown">
|
||||||
|
<Style.Triggers>
|
||||||
|
<DataTrigger Binding="{Binding IsMouseDown}" Value="True">
|
||||||
|
<DataTrigger.EnterActions>
|
||||||
|
<BeginStoryboard>
|
||||||
|
<Storyboard TargetProperty="Opacity">
|
||||||
|
<DoubleAnimation From="0" To="1" Duration="0:0:0.1" />
|
||||||
|
</Storyboard>
|
||||||
|
</BeginStoryboard>
|
||||||
|
</DataTrigger.EnterActions>
|
||||||
|
<DataTrigger.ExitActions>
|
||||||
|
<BeginStoryboard>
|
||||||
|
<Storyboard TargetProperty="Opacity">
|
||||||
|
<DoubleAnimation From="1" To="0" Duration="0:0:0.2" />
|
||||||
|
</Storyboard>
|
||||||
|
</BeginStoryboard>
|
||||||
|
</DataTrigger.ExitActions>
|
||||||
|
</DataTrigger>
|
||||||
|
</Style.Triggers>
|
||||||
|
</Style>
|
||||||
|
</UserControl.Resources>
|
||||||
|
<Canvas Background="Transparent" Width="50" Height="50">
|
||||||
|
|
||||||
</Grid>
|
<Canvas.ContextMenu>
|
||||||
|
<ContextMenu>
|
||||||
|
<MenuItem Header="Ellipse action 1" Command="{s:Action CreateLayer}" CommandParameter="{Binding}">
|
||||||
|
<MenuItem.Icon>
|
||||||
|
<materialDesign:PackIcon Kind="LayersPlus" />
|
||||||
|
</MenuItem.Icon>
|
||||||
|
</MenuItem>
|
||||||
|
<MenuItem Header="Ellipse action 2" Command="{s:Action ApplyToLayer}" CommandParameter="{Binding}">
|
||||||
|
<MenuItem.Icon>
|
||||||
|
<materialDesign:PackIcon Kind="Selection" />
|
||||||
|
</MenuItem.Icon>
|
||||||
|
</MenuItem>
|
||||||
|
</ContextMenu>
|
||||||
|
</Canvas.ContextMenu>
|
||||||
|
<Rectangle Style="{StaticResource ShowIfMouseDown}"
|
||||||
|
Width="{Binding DragRectangle.Width}"
|
||||||
|
Height="{Binding DragRectangle.Height}"
|
||||||
|
Canvas.Left="{Binding DragRectangle.X}"
|
||||||
|
Canvas.Top="{Binding DragRectangle.Y}"
|
||||||
|
Stroke="{DynamicResource PrimaryHueLightBrush}"
|
||||||
|
StrokeDashArray="4 4"
|
||||||
|
StrokeThickness="1"
|
||||||
|
Opacity="0">
|
||||||
|
<Rectangle.Fill>
|
||||||
|
<SolidColorBrush Color="{DynamicResource Primary400}" Opacity="0.25" />
|
||||||
|
</Rectangle.Fill>
|
||||||
|
</Rectangle>
|
||||||
|
</Canvas>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
|
|||||||
@ -1,6 +1,10 @@
|
|||||||
using System.IO;
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
|
using Artemis.Core.Models.Profile;
|
||||||
|
using Artemis.Core.Models.Surface;
|
||||||
|
using Artemis.UI.Extensions;
|
||||||
using Artemis.UI.Properties;
|
using Artemis.UI.Properties;
|
||||||
using Artemis.UI.Services.Interfaces;
|
using Artemis.UI.Services.Interfaces;
|
||||||
|
|
||||||
@ -16,49 +20,79 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void MouseDown(object sender, MouseButtonEventArgs e)
|
public Rect DragRectangle { get; set; }
|
||||||
{
|
|
||||||
base.MouseDown(sender, e);
|
|
||||||
// ProfileViewModel.SelectionRectangle.Rect = new Rect();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void MouseUp(object sender, MouseButtonEventArgs e)
|
public override void MouseUp(object sender, MouseButtonEventArgs e)
|
||||||
{
|
{
|
||||||
base.MouseUp(sender, e);
|
base.MouseUp(sender, e);
|
||||||
|
|
||||||
var position = e.GetPosition((IInputElement) sender);
|
var position = ProfileViewModel.PanZoomViewModel.GetRelativeMousePosition(sender, e);
|
||||||
var selectedRect = new Rect(MouseDownStartPosition, position);
|
var selectedRect = new Rect(MouseDownStartPosition, position);
|
||||||
|
|
||||||
|
// Get selected LEDs
|
||||||
|
var selectedLeds = new List<ArtemisLed>();
|
||||||
foreach (var device in ProfileViewModel.Devices)
|
foreach (var device in ProfileViewModel.Devices)
|
||||||
{
|
{
|
||||||
foreach (var ledViewModel in device.Leds)
|
foreach (var ledViewModel in device.Leds)
|
||||||
{
|
{
|
||||||
if (ProfileViewModel.PanZoomViewModel.TransformContainingRect(ledViewModel.Led.RgbLed.AbsoluteLedRectangle).IntersectsWith(selectedRect))
|
if (ledViewModel.Led.RgbLed.AbsoluteLedRectangle.ToWindowsRect(1).IntersectsWith(selectedRect))
|
||||||
ledViewModel.IsSelected = true;
|
selectedLeds.Add(ledViewModel.Led);
|
||||||
else if (!Keyboard.IsKeyDown(Key.LeftShift) && !Keyboard.IsKeyDown(Key.RightShift))
|
// Unselect everything
|
||||||
ledViewModel.IsSelected = false;
|
ledViewModel.IsSelected = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Apply the selection to the selected layer layer
|
||||||
|
if (ProfileEditorService.SelectedProfileElement is Layer layer)
|
||||||
|
{
|
||||||
|
layer.ClearLeds();
|
||||||
|
layer.AddLeds(selectedLeds);
|
||||||
|
ProfileEditorService.UpdateSelectedProfileElement();
|
||||||
|
}
|
||||||
|
// If no layer selected, apply it to a new layer in the selected folder
|
||||||
|
else if (ProfileEditorService.SelectedProfileElement is Folder folder)
|
||||||
|
{
|
||||||
|
var newLayer = folder.AddLayer("New layer");
|
||||||
|
newLayer.AddLeds(selectedLeds);
|
||||||
|
ProfileEditorService.ChangeSelectedProfileElement(newLayer);
|
||||||
|
ProfileEditorService.UpdateSelectedProfileElement();
|
||||||
|
}
|
||||||
|
// If no folder selected, apply it to a new layer in the root folder
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var rootFolder = ProfileEditorService.SelectedProfile.GetRootFolder();
|
||||||
|
var newLayer = rootFolder.AddLayer("New layer");
|
||||||
|
newLayer.AddLeds(selectedLeds);
|
||||||
|
ProfileEditorService.ChangeSelectedProfileElement(newLayer);
|
||||||
|
ProfileEditorService.UpdateSelectedProfileElement();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void MouseMove(object sender, MouseEventArgs e)
|
public override void MouseMove(object sender, MouseEventArgs e)
|
||||||
{
|
{
|
||||||
base.MouseMove(sender, e);
|
base.MouseMove(sender, e);
|
||||||
|
if (!IsMouseDown)
|
||||||
|
{
|
||||||
|
DragRectangle = new Rect(-1, -1, 0, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var position = e.GetPosition((IInputElement) sender);
|
var position = ProfileViewModel.PanZoomViewModel.GetRelativeMousePosition(sender, e);
|
||||||
var selectedRect = new Rect(MouseDownStartPosition, position);
|
var selectedRect = new Rect(MouseDownStartPosition, position);
|
||||||
// ProfileViewModel.SelectionRectangle.Rect = selectedRect;
|
|
||||||
|
|
||||||
foreach (var device in ProfileViewModel.Devices)
|
foreach (var device in ProfileViewModel.Devices)
|
||||||
{
|
{
|
||||||
foreach (var ledViewModel in device.Leds)
|
foreach (var ledViewModel in device.Leds)
|
||||||
{
|
{
|
||||||
if (ProfileViewModel.PanZoomViewModel.TransformContainingRect(ledViewModel.Led.RgbLed.AbsoluteLedRectangle).IntersectsWith(selectedRect))
|
if (ledViewModel.Led.RgbLed.AbsoluteLedRectangle.ToWindowsRect(1).IntersectsWith(selectedRect))
|
||||||
ledViewModel.IsSelected = true;
|
ledViewModel.IsSelected = true;
|
||||||
else if (!Keyboard.IsKeyDown(Key.LeftShift) && !Keyboard.IsKeyDown(Key.RightShift))
|
else if (!Keyboard.IsKeyDown(Key.LeftShift) && !Keyboard.IsKeyDown(Key.RightShift))
|
||||||
ledViewModel.IsSelected = false;
|
ledViewModel.IsSelected = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DragRectangle = selectedRect;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -8,19 +8,13 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools
|
|||||||
public ViewpointMoveToolViewModel(ProfileViewModel profileViewModel, IProfileEditorService profileEditorService) : base(profileViewModel, profileEditorService)
|
public ViewpointMoveToolViewModel(ProfileViewModel profileViewModel, IProfileEditorService profileEditorService) : base(profileViewModel, profileEditorService)
|
||||||
{
|
{
|
||||||
Cursor = Cursors.Hand;
|
Cursor = Cursors.Hand;
|
||||||
|
ProfileViewModel.PanZoomViewModel.LastPanPosition = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void MouseMove(object sender, MouseEventArgs e)
|
public override void MouseMove(object sender, MouseEventArgs e)
|
||||||
{
|
{
|
||||||
base.MouseMove(sender, e);
|
base.MouseMove(sender, e);
|
||||||
if (IsMouseDown)
|
ProfileViewModel.PanZoomViewModel.ProcessMouseMove(sender, e);
|
||||||
ProfileViewModel.PanZoomViewModel.ProcessMouseMove(sender, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void MouseWheel(object sender, MouseWheelEventArgs e)
|
|
||||||
{
|
|
||||||
base.MouseWheel(sender, e);
|
|
||||||
ProfileViewModel.PanZoomViewModel.ProcessMouseScroll(sender, e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,4 +1,5 @@
|
|||||||
using System.Windows;
|
using System;
|
||||||
|
using System.Windows;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using Artemis.UI.Services.Interfaces;
|
using Artemis.UI.Services.Interfaces;
|
||||||
|
|
||||||
@ -26,7 +27,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools
|
|||||||
public virtual void MouseDown(object sender, MouseButtonEventArgs e)
|
public virtual void MouseDown(object sender, MouseButtonEventArgs e)
|
||||||
{
|
{
|
||||||
IsMouseDown = true;
|
IsMouseDown = true;
|
||||||
MouseDownStartPosition = e.GetPosition((IInputElement) sender);
|
MouseDownStartPosition = ProfileViewModel.PanZoomViewModel.GetRelativeMousePosition(sender, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void MouseUp(object sender, MouseButtonEventArgs e)
|
public virtual void MouseUp(object sender, MouseButtonEventArgs e)
|
||||||
@ -41,5 +42,28 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools
|
|||||||
public virtual void MouseWheel(object sender, MouseWheelEventArgs e)
|
public virtual void MouseWheel(object sender, MouseWheelEventArgs e)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public virtual void KeyUp(KeyEventArgs e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void KeyDown(KeyEventArgs e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Rect GetSquareRectBetweenPoints(Point start, Point end)
|
||||||
|
{
|
||||||
|
// Find the shortest side
|
||||||
|
var size = Math.Min(Math.Abs(start.X - end.X), Math.Abs(start.Y - end.Y));
|
||||||
|
|
||||||
|
// There's probably a very elegant way to do this, and this is not it
|
||||||
|
if (end.X < start.X && end.Y < start.Y)
|
||||||
|
return new Rect(start.X - size, start.Y - size, size, size);
|
||||||
|
if (end.X < start.X)
|
||||||
|
return new Rect(start.X - size, Math.Min(start.Y, end.Y), size, size);
|
||||||
|
if (end.Y < start.Y)
|
||||||
|
return new Rect(Math.Min(start.X, end.X), start.Y - size, size, size);
|
||||||
|
return new Rect(Math.Min(start.X, end.X), Math.Min(start.Y, end.Y), size, size);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -17,6 +17,8 @@
|
|||||||
UseLayoutRounding="True"
|
UseLayoutRounding="True"
|
||||||
Deactivated="{s:Action WindowDeactivated}"
|
Deactivated="{s:Action WindowDeactivated}"
|
||||||
Activated="{s:Action WindowActivated}"
|
Activated="{s:Action WindowActivated}"
|
||||||
|
KeyDown="{s:Action WindowKeyDown}"
|
||||||
|
KeyUp="{s:Action WindowKeyUp}"
|
||||||
d:DesignHeight="640"
|
d:DesignHeight="640"
|
||||||
d:DesignWidth="1200"
|
d:DesignWidth="1200"
|
||||||
d:DataContext="{d:DesignInstance screens:RootViewModel}">
|
d:DataContext="{d:DesignInstance screens:RootViewModel}">
|
||||||
|
|||||||
@ -3,6 +3,7 @@ using System.ComponentModel;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
|
using System.Windows.Input;
|
||||||
using Artemis.UI.Events;
|
using Artemis.UI.Events;
|
||||||
using Artemis.UI.Screens.Sidebar;
|
using Artemis.UI.Screens.Sidebar;
|
||||||
using Artemis.UI.Utilities;
|
using Artemis.UI.Utilities;
|
||||||
@ -80,5 +81,15 @@ namespace Artemis.UI.Screens
|
|||||||
_lostFocus = false;
|
_lostFocus = false;
|
||||||
_eventAggregator.Publish(new MainWindowFocusChangedEvent(true));
|
_eventAggregator.Publish(new MainWindowFocusChangedEvent(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void WindowKeyDown(object sender, KeyEventArgs e)
|
||||||
|
{
|
||||||
|
_eventAggregator.Publish(new MainWindowKeyEvent(true, e));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WindowKeyUp(object sender, KeyEventArgs e)
|
||||||
|
{
|
||||||
|
_eventAggregator.Publish(new MainWindowKeyEvent(false, e));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -12,7 +12,7 @@ namespace Artemis.UI.Screens.Shared
|
|||||||
{
|
{
|
||||||
public class PanZoomViewModel : PropertyChangedBase
|
public class PanZoomViewModel : PropertyChangedBase
|
||||||
{
|
{
|
||||||
private Point? _lastPanPosition;
|
public Point? LastPanPosition { get; set; }
|
||||||
public double Zoom { get; set; } = 1;
|
public double Zoom { get; set; } = 1;
|
||||||
|
|
||||||
public double ZoomPercentage
|
public double ZoomPercentage
|
||||||
@ -51,20 +51,20 @@ namespace Artemis.UI.Screens.Shared
|
|||||||
{
|
{
|
||||||
if (e.LeftButton == MouseButtonState.Released)
|
if (e.LeftButton == MouseButtonState.Released)
|
||||||
{
|
{
|
||||||
_lastPanPosition = null;
|
LastPanPosition = null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_lastPanPosition == null)
|
if (LastPanPosition == null)
|
||||||
_lastPanPosition = e.GetPosition((IInputElement) sender);
|
LastPanPosition = e.GetPosition((IInputElement) sender);
|
||||||
|
|
||||||
var position = e.GetPosition((IInputElement) sender);
|
var position = e.GetPosition((IInputElement) sender);
|
||||||
var delta = _lastPanPosition - position;
|
var delta = LastPanPosition - position;
|
||||||
|
|
||||||
PanX = Math.Min(0, PanX - delta.Value.X);
|
PanX = Math.Min(0, PanX - delta.Value.X);
|
||||||
PanY = Math.Min(0, PanY - delta.Value.Y);
|
PanY = Math.Min(0, PanY - delta.Value.Y);
|
||||||
|
|
||||||
_lastPanPosition = position;
|
LastPanPosition = position;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Reset()
|
public void Reset()
|
||||||
|
|||||||
@ -1,47 +0,0 @@
|
|||||||
using System.Windows;
|
|
||||||
using System.Windows.Controls;
|
|
||||||
using System.Windows.Interactivity;
|
|
||||||
|
|
||||||
namespace Artemis.UI.Utilities
|
|
||||||
{
|
|
||||||
public class BindableSelectedItemBehavior : Behavior<TreeView>
|
|
||||||
{
|
|
||||||
protected override void OnAttached()
|
|
||||||
{
|
|
||||||
base.OnAttached();
|
|
||||||
|
|
||||||
AssociatedObject.SelectedItemChanged += OnTreeViewSelectedItemChanged;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnDetaching()
|
|
||||||
{
|
|
||||||
base.OnDetaching();
|
|
||||||
|
|
||||||
if (AssociatedObject != null) AssociatedObject.SelectedItemChanged -= OnTreeViewSelectedItemChanged;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnTreeViewSelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
|
|
||||||
{
|
|
||||||
SelectedItem = e.NewValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
#region SelectedItem Property
|
|
||||||
|
|
||||||
public object SelectedItem
|
|
||||||
{
|
|
||||||
get => GetValue(SelectedItemProperty);
|
|
||||||
set => SetValue(SelectedItemProperty, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static readonly DependencyProperty SelectedItemProperty =
|
|
||||||
DependencyProperty.Register("SelectedItem", typeof(object), typeof(BindableSelectedItemBehavior), new UIPropertyMetadata(null, OnSelectedItemChanged));
|
|
||||||
|
|
||||||
private static void OnSelectedItemChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
|
|
||||||
{
|
|
||||||
var item = e.NewValue as TreeViewItem;
|
|
||||||
if (item != null) item.SetValue(TreeViewItem.IsSelectedProperty, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
x
Reference in New Issue
Block a user