using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using Artemis.UI.Adorners;
using RGB.NET.Core;
using RGB.NET.Groups;
using Point = System.Windows.Point;
namespace Artemis.UI.Controls.Visualizers
{
///
///
/// Visualizes the in an wpf-application.
///
[TemplatePart(Name = PART_CANVAS, Type = typeof(Canvas))]
public class RGBSurfaceVisualizer : Control
{
#region Constants
private const string PART_CANVAS = "PART_Canvas";
#endregion
#region Properties & Fields
private RGBSurface _surface;
private Canvas _canvas;
private BoundingBoxAdorner _boundingBox;
private Point _startingPoint;
//TODO DarthAffe 17.06.2017: This is ugly - redesign how device connect/disconnect is generally handled!
private readonly List _newDevices = new List();
#endregion
#region Constructors
///
///
/// Initializes a new instance of the class.
///
public RGBSurfaceVisualizer()
{
this.Loaded += OnLoaded;
this.Unloaded += OnUnloaded;
}
private void OnLoaded(object sender, RoutedEventArgs routedEventArgs)
{
_surface = RGBSurface.Instance;
_surface.SurfaceLayoutChanged += RGBSurfaceOnSurfaceLayoutChanged;
foreach (IRGBDevice device in _surface.Devices)
_newDevices.Add(device);
UpdateSurface();
}
private void OnUnloaded(object sender, RoutedEventArgs routedEventArgs)
{
_surface.SurfaceLayoutChanged -= RGBSurfaceOnSurfaceLayoutChanged;
_canvas?.Children.Clear();
_newDevices.Clear();
}
private void RGBSurfaceOnSurfaceLayoutChanged(SurfaceLayoutChangedEventArgs args)
{
if (args.DeviceAdded)
foreach (IRGBDevice device in args.Devices)
_newDevices.Add(device);
UpdateSurface();
}
#endregion
#region Methods
///
public override void OnApplyTemplate()
{
// Detach any existing event handlers
if (_canvas != null)
{
_canvas.MouseLeftButtonDown -= ScrollViewerOnMouseLeftButtonDown;
_canvas.MouseLeftButtonUp -= ScrollViewerOnMouseLeftButtonUp;
}
_canvas?.Children.Clear();
_canvas = (Canvas) GetTemplateChild(PART_CANVAS);
UpdateSurface();
if (_canvas == null) return;
_canvas.MouseLeftButtonDown += ScrollViewerOnMouseLeftButtonDown;
_canvas.MouseLeftButtonUp += ScrollViewerOnMouseLeftButtonUp;
_canvas.MouseMove += ScrollViewerOnMouseMove;
}
private void ScrollViewerOnMouseLeftButtonDown(object sender, MouseButtonEventArgs mouseButtonEventArgs)
{
_canvas.CaptureMouse();
_startingPoint = mouseButtonEventArgs.GetPosition(_canvas);
_boundingBox = new BoundingBoxAdorner(_canvas, Colors.RoyalBlue);
var adornerLayer = AdornerLayer.GetAdornerLayer(_canvas);
adornerLayer.Add(_boundingBox);
}
private void ScrollViewerOnMouseLeftButtonUp(object sender, MouseButtonEventArgs mouseButtonEventArgs)
{
_canvas.ReleaseMouseCapture();
var adornerLayer = AdornerLayer.GetAdornerLayer(_canvas);
var adorners = adornerLayer.GetAdorners(_canvas);
if (adorners == null) return;
foreach (var adorner in adorners)
adornerLayer.Remove(adorner);
_boundingBox = null;
}
private void ScrollViewerOnMouseMove(object sender, MouseEventArgs mouseEventArgs)
{
if (_boundingBox == null) return;
var currentPoint = mouseEventArgs.GetPosition(_canvas);
_boundingBox.Update(_startingPoint, currentPoint);
var ledStart = new RGB.NET.Core.Point(_startingPoint.X, _startingPoint.Y);
var ledEnd = new RGB.NET.Core.Point(currentPoint.X, currentPoint.Y);
var selection = new RectangleLedGroup(ledStart, ledEnd, 0.1);
// Deselect all LED of each device
var deviceLeds = new List();
foreach (var rgbDeviceVisualizer in _canvas.Children.Cast())
deviceLeds.AddRange(rgbDeviceVisualizer.Canvas.Children.Cast());
foreach (var ledVisualizer in deviceLeds)
ledVisualizer?.Deselect();
// Select all LEDs in the bounding box
foreach (var led in selection.GetLeds())
{
var ledVisualizer = deviceLeds.FirstOrDefault(l => l.Led == led);
ledVisualizer?.Select();
}
}
private void UpdateSurface()
{
if ((_canvas == null) || (_surface == null)) return;
if (_newDevices.Count > 0)
{
foreach (IRGBDevice device in _newDevices)
_canvas.Children.Add(new RGBDeviceVisualizer {Device = device});
_newDevices.Clear();
}
_canvas.Width = _surface.SurfaceRectangle.Size.Width;
_canvas.Height = _surface.SurfaceRectangle.Size.Height;
}
#endregion
}
}