mirror of
https://github.com/Artemis-RGB/Artemis
synced 2026-11-12 11:56:30 +00:00
Basic implementation of a few editor tools
This commit is contained in:
1 parent
ddce69e8f0
commit
dda3cf442d
26 files changed
+634
-174
No files matched your search
+32
-18
@@ -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>
|
||||
|
||||
+35
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
+57
-7
@@ -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>
|
||||
+35
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
+54
-3
@@ -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>
|
||||
+48
-14
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-8
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
+26
-2
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user