using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; using System.Windows.Input; using System.Windows.Media; using System.Windows.Shapes; namespace Tango.FSE.Diagnostics.Controls { public class DiagnosticsSelectionGrid : DiagnosticsGrid { private List _rects; private Point _mouseDownLocation; private bool _isMouseDown; private List _selectionRects; public Brush RectanglesBackgroundBrush { get { return (Brush)GetValue(RectanglesBackgroundBrushProperty); } set { SetValue(RectanglesBackgroundBrushProperty, value); } } public static readonly DependencyProperty RectanglesBackgroundBrushProperty = DependencyProperty.Register("RectanglesBackgroundBrush", typeof(Brush), typeof(DiagnosticsSelectionGrid), new PropertyMetadata(new SolidColorBrush(Color.FromRgb(25, 25, 25)))); public Brush RectanglesHighlightBrush { get { return (Brush)GetValue(RectanglesHighlightBrushProperty); } set { SetValue(RectanglesHighlightBrushProperty, value); } } public static readonly DependencyProperty RectanglesHighlightBrushProperty = DependencyProperty.Register("RectanglesHighlightBrush", typeof(Brush), typeof(DiagnosticsSelectionGrid), new PropertyMetadata(new SolidColorBrush(Color.FromRgb(30, 30, 30)))); public Rect SelectionRect { get { return (Rect)GetValue(SelectionRectProperty); } set { SetValue(SelectionRectProperty, value); } } public static readonly DependencyProperty SelectionRectProperty = DependencyProperty.Register("SelectionRect", typeof(Rect), typeof(DiagnosticsSelectionGrid), new PropertyMetadata(default(Rect))); public ICommand SelectionCommand { get { return (ICommand)GetValue(SelectionCommandProperty); } set { SetValue(SelectionCommandProperty, value); } } public static readonly DependencyProperty SelectionCommandProperty = DependencyProperty.Register("SelectionCommand", typeof(ICommand), typeof(DiagnosticsSelectionGrid), new PropertyMetadata(null)); public ICommand RightClickCommand { get { return (ICommand)GetValue(RightClickCommandProperty); } set { SetValue(RightClickCommandProperty, value); } } public static readonly DependencyProperty RightClickCommandProperty = DependencyProperty.Register("RightClickCommand", typeof(ICommand), typeof(DiagnosticsSelectionGrid), new PropertyMetadata(null)); public SelectionMode SelectionMode { get { return (SelectionMode)GetValue(SelectionModeProperty); } set { SetValue(SelectionModeProperty, value); } } public static readonly DependencyProperty SelectionModeProperty = DependencyProperty.Register("SelectionMode", typeof(SelectionMode), typeof(DiagnosticsSelectionGrid), new PropertyMetadata(SelectionMode.Multiple)); static DiagnosticsSelectionGrid() { DefaultStyleKeyProperty.OverrideMetadata(typeof(DiagnosticsSelectionGrid), new FrameworkPropertyMetadata(typeof(DiagnosticsSelectionGrid))); } public DiagnosticsSelectionGrid() { _rects = new List(); _selectionRects = new List(); Cursor = Cursors.Cross; Background = Brushes.Transparent; } public void ClearSelection() { _selectionRects.Clear(); foreach (var rect in _rects) { rect.Fill = RectanglesBackgroundBrush; } } protected override void LoadDefinitions() { base.LoadDefinitions(); if (Rows != null && Columns != null) { _rects.Clear(); _selectionRects.Clear(); Children.Clear(); for (int columnIndex = 0; columnIndex < Columns.Count; columnIndex++) { for (int rowIndex = 0; rowIndex < Rows.Count; rowIndex++) { var rect = new Rectangle(); rect.Margin = new Thickness(1); rect.Fill = RectanglesBackgroundBrush; rect.IsHitTestVisible = false; Grid.SetColumn(rect, columnIndex); Grid.SetRow(rect, rowIndex); Children.Add(rect); _rects.Add(rect); } } } } protected override void OnPreviewMouseDown(MouseButtonEventArgs e) { base.OnPreviewMouseDown(e); if (SelectionMode == SelectionMode.Single) return; if (e.ChangedButton == MouseButton.Left) { _mouseDownLocation = e.GetPosition(this); _isMouseDown = true; } } protected override void OnPreviewMouseUp(MouseButtonEventArgs e) { base.OnPreviewMouseUp(e); _isMouseDown = false; if (e.ChangedButton == MouseButton.Right) { RightClickCommand?.Execute(null); return; } if (_selectionRects.Count > 0) { var column = _selectionRects.Min(x => Grid.GetColumn(x)); var row = _selectionRects.Min(x => Grid.GetRow(x)); var columnSpan = Math.Max(_selectionRects.Max(x => Grid.GetColumn(x)) - column + 1, 1); var rowSpan = Math.Max(_selectionRects.Max(x => Grid.GetRow(x)) - row + 1, 1); SelectionRect = new Rect(column, row, columnSpan, rowSpan); SelectionCommand?.Execute(SelectionRect); ClearSelection(); } } protected override void OnPreviewMouseMove(MouseEventArgs e) { base.OnPreviewMouseMove(e); if (SelectionMode == SelectionMode.Single) { var position = e.GetPosition(this); var selection = new Rect(position.X, position.Y, 1, 1); HighlightIntersections(selection); } else if (_isMouseDown) { var position = e.GetPosition(this); var x = Math.Min(position.X, _mouseDownLocation.X); var y = Math.Min(position.Y, _mouseDownLocation.Y); var w = Math.Max(position.X, _mouseDownLocation.X) - Math.Min(_mouseDownLocation.X, position.X); var h = Math.Max(position.Y, _mouseDownLocation.Y) - Math.Min(_mouseDownLocation.Y, position.Y); var selection = new Rect(x, y, w, h); HighlightIntersections(selection); } } private void HighlightIntersections(Rect selection) { _selectionRects.Clear(); foreach (var rect in _rects) { GeneralTransform gt = rect.TransformToAncestor(this); var rectBounds = gt.TransformBounds(new Rect(0, 0, rect.ActualWidth, rect.ActualHeight)); if (selection.IntersectsWith(rectBounds)) { rect.Fill = RectanglesHighlightBrush; _selectionRects.Add(rect); } else { rect.Fill = RectanglesBackgroundBrush; } } } } }