Basic implementation of a few editor tools

This commit is contained in:
Robert committed 2019-12-16 17:40:08 +01:00
1 parent ddce69e8f0
commit dda3cf442d
26 files changed
+634 -174

No files matched your search

@@ -7,9 +7,9 @@
xmlns:s="https://github.com/canton7/Stylet"
xmlns:dd="urn:gong-wpf-dragdrop"
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:treeItem="clr-namespace:Artemis.UI.Screens.Module.ProfileEditor.ProfileTree.TreeItem"
xmlns:behaviors="clr-namespace:Artemis.UI.Behaviors"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
d:DataContext="{d:DesignInstance {x:Type profileTree:ProfileTreeViewModel}}">
@@ -33,7 +33,7 @@
dd:DragDrop.IsDropTarget="True"
dd:DragDrop.DropHandler="{Binding}">
<i:Interaction.Behaviors>
<utilities:BindableSelectedItemBehavior SelectedItem="{Binding SelectedTreeItem, Mode=TwoWay}" />
<behaviors:TreeViewSelectionBehavior ExpandSelected="True" SelectedItem="{Binding SelectedTreeItem}" />
</i:Interaction.Behaviors>
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type treeItem:FolderViewModel}" ItemsSource="{Binding Children}">
@@ -2,10 +2,12 @@
using System.Linq;
using System.Windows;
using Artemis.Core.Models.Profile;
using Artemis.UI.Behaviors;
using Artemis.UI.Ninject.Factories;
using Artemis.UI.Screens.Module.ProfileEditor.ProfileTree.TreeItem;
using Artemis.UI.Services.Interfaces;
using GongSolutions.Wpf.DragDrop;
using Stylet;
namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree
{
@@ -13,12 +15,16 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree
{
private readonly IProfileEditorService _profileEditorService;
private readonly IFolderViewModelFactory _folderViewModelFactory;
private readonly ILayerViewModelFactory _layerViewModelFactory;
private TreeItemViewModel _selectedTreeItem;
public ProfileTreeViewModel(IProfileEditorService profileEditorService, IFolderViewModelFactory folderViewModelFactory)
public ProfileTreeViewModel(IProfileEditorService profileEditorService,
IFolderViewModelFactory folderViewModelFactory,
ILayerViewModelFactory layerViewModelFactory)
{
_profileEditorService = profileEditorService;
_folderViewModelFactory = folderViewModelFactory;
_layerViewModelFactory = layerViewModelFactory;
CreateRootFolderViewModel();
_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
_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);
}
@@ -49,7 +49,7 @@
</Path>
<!-- Selection -->
<Path Data="{Binding DisplayGeometry, Mode=OneWay}" ClipToBounds="False" StrokeThickness="2">
<Path Data="{Binding DisplayGeometry, Mode=OneWay}" ClipToBounds="False" StrokeThickness="1">
<Path.Style>
<Style TargetType="{x:Type Path}">
<Style.Triggers>
@@ -83,10 +83,10 @@
</Style>
</Path.Style>
<Path.Fill>
<SolidColorBrush Opacity="0.65" />
<SolidColorBrush Opacity="0.25" />
</Path.Fill>
<Path.Stroke>
<SolidColorBrush />
<SolidColorBrush Opacity="0.5"/>
</Path.Stroke>
</Path>
</Canvas>
@@ -46,17 +46,17 @@
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<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.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical"/>
<StackPanel Orientation="Vertical" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBoxItem ToolTip="Pan over different parts of the surface" >
<ListBoxItem ToolTip="Pan over different parts of the surface">
<materialDesign:PackIcon Kind="HandLeft" />
</ListBoxItem>
<ListBoxItem ToolTip="Change layer selection" >
<ListBoxItem ToolTip="Change layer selection">
<materialDesign:PackIcon Kind="SelectionDrag" />
</ListBoxItem>
<ListBoxItem ToolTip="Add to layer selection">
@@ -79,16 +79,14 @@
<materialDesign:PackIcon Kind="FormatColourFill" />
</ListBoxItem>
</ListBox>
</ToolBar>
</ToolBarTray>
<Grid Grid.Column="1"
ClipToBounds="True"
KeyUp="{s:Action CanvasKeyUp}"
KeyDown="{s:Action CanvasKeyDown}"
MouseWheel="{s:Action CanvasMouseWheel}"
MouseUp="{s:Action CanvasMouseDown}"
MouseDown="{s:Action CanvasMouseUp}"
MouseUp="{s:Action CanvasMouseUp}"
MouseDown="{s:Action CanvasMouseDown}"
MouseMove="{s:Action CanvasMouseMove}"
Cursor="{Binding ActiveToolViewModel.Cursor}"
utilities:SizeObserver.Observe="True"
@@ -115,7 +113,7 @@
</VisualBrush.Visual>
</VisualBrush>
</Grid.Background>
<Grid Name="EditorDisplayGrid">
<Grid.RenderTransform>
<TransformGroup>
@@ -123,7 +121,7 @@
<TranslateTransform X="{Binding PanZoomViewModel.PanX}" Y="{Binding PanZoomViewModel.PanY}" />
</TransformGroup>
</Grid.RenderTransform>
<ItemsControl ItemsSource="{Binding Devices}">
<ItemsControl ItemsSource="{Binding CanvasViewModels}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
@@ -142,7 +140,7 @@
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
<StackPanel ZIndex="1" VerticalAlignment="Bottom" HorizontalAlignment="Left" Margin="10">
<materialDesign:Card Padding="8">
<StackPanel Orientation="Horizontal">
@@ -1,9 +1,9 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Windows.Input;
using System.Windows.Media;
using Artemis.Core.Events;
using Artemis.Core.Models.Profile;
using Artemis.Core.Models.Surface;
@@ -19,11 +19,14 @@ using Stylet;
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 ISettingsService _settingsService;
private readonly ISurfaceService _surfaceService;
private int _activeToolIndex;
private VisualizationToolViewModel _activeToolViewModel;
private int _previousTool;
private TimerUpdateTrigger _updateTrigger;
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
if (_activeToolViewModel != null)
{
CanvasViewModels.Remove(_activeToolViewModel);
NotifyOfPropertyChange(() => CanvasViewModels);
}
// Set the new tool
_activeToolViewModel = value;
// Add the new tool to the canvas
if (_activeToolViewModel != null)
{
CanvasViewModels.Add(_activeToolViewModel);
NotifyOfPropertyChange(() => CanvasViewModels);
}
}
}
@@ -80,8 +90,12 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
get => _activeToolIndex;
set
{
_activeToolIndex = value;
ActivateToolByIndex(value);
if (_activeToolIndex != value)
{
_activeToolIndex = value;
ActivateToolByIndex(value);
NotifyOfPropertyChange(() => ActiveToolIndex);
}
}
}
@@ -215,19 +229,21 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
case 3:
ActiveToolViewModel = new SelectionRemoveToolViewModel(this, _profileEditorService);
break;
case 4:
case 5:
ActiveToolViewModel = new EllipseToolViewModel(this, _profileEditorService);
break;
case 5:
case 6:
ActiveToolViewModel = new RectangleToolViewModel(this, _profileEditorService);
break;
case 6:
case 7:
ActiveToolViewModel = new PolygonToolViewModel(this, _profileEditorService);
break;
case 7:
case 8:
ActiveToolViewModel = new FillToolViewModel(this, _profileEditorService);
break;
}
ActiveToolIndex = value;
}
public void ResetZoomAndPan()
@@ -256,6 +272,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
public void CanvasMouseWheel(object sender, MouseWheelEventArgs e)
{
PanZoomViewModel.ProcessMouseScroll(sender, e);
ActiveToolViewModel?.MouseWheel(sender, e);
}
@@ -300,27 +317,6 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
#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
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
}
}
@@ -8,23 +8,30 @@
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Canvas>
<Canvas.Triggers>
<EventTrigger RoutedEvent="Canvas.MouseLeftButtonDown">
<BeginStoryboard>
<Storyboard TargetName="Preview" TargetProperty="Opacity">
<DoubleAnimation From="0" To="1" Duration="0:0:0.1" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="Canvas.MouseLeftButtonUp">
<BeginStoryboard>
<Storyboard TargetName="Preview" TargetProperty="Opacity">
<DoubleAnimation From="1" To="0" Duration="0:0:0.2" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Canvas.Triggers>
<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">
<Canvas.ContextMenu>
<ContextMenu>
<MenuItem Header="Ellipse action 1" Command="{s:Action CreateLayer}" CommandParameter="{Binding}">
@@ -39,7 +46,14 @@
</MenuItem>
</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>
<SolidColorBrush Color="{DynamicResource Primary400}" Opacity="0.25" />
</Ellipse.Fill>
@@ -1,4 +1,5 @@
using System.IO;
using System.Windows;
using System.Windows.Input;
using Artemis.UI.Properties;
using Artemis.UI.Services.Interfaces;
@@ -7,6 +8,8 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools
{
public class EllipseToolViewModel : VisualizationToolViewModel
{
private bool _shiftDown;
public EllipseToolViewModel(ProfileViewModel profileViewModel, IProfileEditorService profileEditorService) : base(profileViewModel, profileEditorService)
{
using (var stream = new MemoryStream(Resources.aero_crosshair))
@@ -14,5 +17,37 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools
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;
}
}
}
@@ -1,12 +1,62 @@
<UserControl x:Class="Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools.RectangleToolView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools"
mc:Ignorable="d"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:s="https://github.com/canton7/Stylet"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
</Grid>
</UserControl>
<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">
<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>
@@ -1,4 +1,5 @@
using System.IO;
using System.Windows;
using System.Windows.Input;
using Artemis.UI.Properties;
using Artemis.UI.Services.Interfaces;
@@ -7,6 +8,8 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools
{
public class RectangleToolViewModel : VisualizationToolViewModel
{
private bool _shiftDown;
public RectangleToolViewModel(ProfileViewModel profileViewModel, IProfileEditorService profileEditorService) : base(profileViewModel, profileEditorService)
{
using (var stream = new MemoryStream(Resources.aero_crosshair))
@@ -14,5 +17,37 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools
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:d="http://schemas.microsoft.com/expression/blend/2008"
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"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
</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">
<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>
@@ -1,6 +1,10 @@
using System.IO;
using System.Collections.Generic;
using System.IO;
using System.Windows;
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.Services.Interfaces;
@@ -16,49 +20,79 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools
}
}
public override void MouseDown(object sender, MouseButtonEventArgs e)
{
base.MouseDown(sender, e);
// ProfileViewModel.SelectionRectangle.Rect = new Rect();
}
public Rect DragRectangle { get; set; }
public override void MouseUp(object sender, MouseButtonEventArgs e)
{
base.MouseUp(sender, e);
var position = e.GetPosition((IInputElement) sender);
var position = ProfileViewModel.PanZoomViewModel.GetRelativeMousePosition(sender, e);
var selectedRect = new Rect(MouseDownStartPosition, position);
// Get selected LEDs
var selectedLeds = new List<ArtemisLed>();
foreach (var device in ProfileViewModel.Devices)
{
foreach (var ledViewModel in device.Leds)
{
if (ProfileViewModel.PanZoomViewModel.TransformContainingRect(ledViewModel.Led.RgbLed.AbsoluteLedRectangle).IntersectsWith(selectedRect))
ledViewModel.IsSelected = true;
else if (!Keyboard.IsKeyDown(Key.LeftShift) && !Keyboard.IsKeyDown(Key.RightShift))
ledViewModel.IsSelected = false;
if (ledViewModel.Led.RgbLed.AbsoluteLedRectangle.ToWindowsRect(1).IntersectsWith(selectedRect))
selectedLeds.Add(ledViewModel.Led);
// Unselect everything
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)
{
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);
// ProfileViewModel.SelectionRectangle.Rect = selectedRect;
foreach (var device in ProfileViewModel.Devices)
{
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;
else if (!Keyboard.IsKeyDown(Key.LeftShift) && !Keyboard.IsKeyDown(Key.RightShift))
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)
{
Cursor = Cursors.Hand;
ProfileViewModel.PanZoomViewModel.LastPanPosition = null;
}
public override void MouseMove(object sender, MouseEventArgs e)
{
base.MouseMove(sender, e);
if (IsMouseDown)
ProfileViewModel.PanZoomViewModel.ProcessMouseMove(sender, e);
}
public override void MouseWheel(object sender, MouseWheelEventArgs e)
{
base.MouseWheel(sender, e);
ProfileViewModel.PanZoomViewModel.ProcessMouseScroll(sender, e);
ProfileViewModel.PanZoomViewModel.ProcessMouseMove(sender, e);
}
}
}
@@ -1,4 +1,5 @@
using System.Windows;
using System;
using System.Windows;
using System.Windows.Input;
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)
{
IsMouseDown = true;
MouseDownStartPosition = e.GetPosition((IInputElement) sender);
MouseDownStartPosition = ProfileViewModel.PanZoomViewModel.GetRelativeMousePosition(sender, 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 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);
}
}
}
+2
View File
@@ -17,6 +17,8 @@
UseLayoutRounding="True"
Deactivated="{s:Action WindowDeactivated}"
Activated="{s:Action WindowActivated}"
KeyDown="{s:Action WindowKeyDown}"
KeyUp="{s:Action WindowKeyUp}"
d:DesignHeight="640"
d:DesignWidth="1200"
d:DataContext="{d:DesignInstance screens:RootViewModel}">
+11
View File
@@ -3,6 +3,7 @@ using System.ComponentModel;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using Artemis.UI.Events;
using Artemis.UI.Screens.Sidebar;
using Artemis.UI.Utilities;
@@ -80,5 +81,15 @@ namespace Artemis.UI.Screens
_lostFocus = false;
_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
{
private Point? _lastPanPosition;
public Point? LastPanPosition { get; set; }
public double Zoom { get; set; } = 1;
public double ZoomPercentage
@@ -51,20 +51,20 @@ namespace Artemis.UI.Screens.Shared
{
if (e.LeftButton == MouseButtonState.Released)
{
_lastPanPosition = null;
LastPanPosition = null;
return;
}
if (_lastPanPosition == null)
_lastPanPosition = e.GetPosition((IInputElement) sender);
if (LastPanPosition == null)
LastPanPosition = 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);
PanY = Math.Min(0, PanY - delta.Value.Y);
_lastPanPosition = position;
LastPanPosition = position;
}
public void Reset()