using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System; using System.Collections.Generic; using System.Linq; namespace AIStudio.Wpf.DiagramDesigner { public class RubberbandAdorner : Adorner { private Point? startPoint; private Point? endPoint; private List<Point> pointList = new List<Point>(); private List<PointDesignerItemViewModel> pointDesignerItemViewModelList = new List<PointDesignerItemViewModel>(); private Pen rubberbandPen; private DesignerCanvas _designerCanvas; private IDiagramViewModel _viewModel { get { return _designerCanvas.DataContext as IDiagramViewModel; } } private IDiagramServiceProvider _service { get { return DiagramServicesProvider.Instance.Provider; } } public RubberbandAdorner(DesignerCanvas designerCanvas, Point? dragStartPoint) : base(designerCanvas) { this._designerCanvas = designerCanvas; this.startPoint = dragStartPoint; rubberbandPen = new Pen(Brushes.LightSlateGray, 1); rubberbandPen.DashStyle = new DashStyle(new double[] { 2 }, 1); } protected override void OnMouseMove(System.Windows.Input.MouseEventArgs e) { if (e.LeftButton == MouseButtonState.Pressed) { if (!this.IsMouseCaptured) this.CaptureMouse(); endPoint = e.GetPosition(this); if (this._service.DrawModeViewModel.GetDrawMode() == DrawMode.Polyline) { if (pointList.Count == 0 && this.startPoint.HasValue) { pointList.Add(this.startPoint.Value); } pointList.Add(endPoint.Value); } UpdateSelection(); this.InvalidateVisual(); } else if (this._service.DrawModeViewModel.GetDrawMode() == DrawMode.DirectLine) { if (pointList.Count == 0 && this.startPoint.HasValue) { pointList.Add(this.startPoint.Value); var item = new PointDesignerItemViewModel(startPoint.Value); item.ShowConnectors = true; _viewModel.DirectAddItemCommand.Execute(item); pointDesignerItemViewModelList.Add(item); } } else { if (this.IsMouseCaptured) this.ReleaseMouseCapture(); } e.Handled = true; } protected override void OnMouseUp(System.Windows.Input.MouseButtonEventArgs e) { if (this._service.DrawModeViewModel.GetDrawMode() == DrawMode.DirectLine && e.ChangedButton == MouseButton.Left ) { endPoint = e.GetPosition(this); bool isend = false; var connector = ControlExtession.TryFindFromPoint<PointConnector>(this._designerCanvas, endPoint.Value); if (connector != null) { if (object.Equals(connector.DataContext, pointDesignerItemViewModelList[0].TopConnector)) { isend = true; } } if (isend == false) { pointList.Add(endPoint.Value); var item = new PointDesignerItemViewModel(endPoint.Value); item.ShowConnectors = true; _viewModel.DirectAddItemCommand.Execute(item); pointDesignerItemViewModelList.Add(item); UpdateSelection(); this.InvalidateVisual(); return; } else { this._service.DrawModeViewModel.SetDrawMode(DrawMode.Polygon); } } // release mouse capture if (this.IsMouseCaptured) this.ReleaseMouseCapture(); // remove this adorner from adorner layer AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(this._designerCanvas); if (adornerLayer != null) adornerLayer.Remove(this); if (this._service.DrawModeViewModel.GetDrawMode() == DrawMode.Line || this._service.DrawModeViewModel.GetDrawMode() == DrawMode.Rectangle || this._service.DrawModeViewModel.GetDrawMode() == DrawMode.Ellipse || this._service.DrawModeViewModel.GetDrawMode() == DrawMode.Polyline || this._service.DrawModeViewModel.GetDrawMode() == DrawMode.Polygon || this._service.DrawModeViewModel.GetDrawMode() == DrawMode.DirectLine || this._service.DrawModeViewModel.GetDrawMode() == DrawMode.Text) { if (this.startPoint.HasValue && this.endPoint.HasValue) { if (this._service.DrawModeViewModel.GetDrawMode() == DrawMode.Polyline || this._service.DrawModeViewModel.GetDrawMode() == DrawMode.Polygon || this._service.DrawModeViewModel.GetDrawMode() == DrawMode.DirectLine) { ShapeDesignerItemViewModel itemBase = new ShapeDesignerItemViewModel(this._service.DrawModeViewModel.GetDrawMode(), pointList); _viewModel.AddItemCommand.Execute(itemBase); itemBase.PointDesignerItemViewModels.ForEach(p => { p.ParentId = itemBase.Id; _viewModel.DirectAddItemCommand.Execute(p); }); } else if (this._service.DrawModeViewModel.GetDrawMode() == DrawMode.Text) { TextDesignerItemViewModel itemBase = new TextDesignerItemViewModel(); Point position = e.GetPosition(this); itemBase.Left = Math.Min(this.startPoint.Value.X, this.endPoint.Value.X); itemBase.Top = Math.Min(this.startPoint.Value.Y, this.endPoint.Value.Y); itemBase.ItemWidth = Math.Abs(this.endPoint.Value.X - this.startPoint.Value.X); itemBase.ItemHeight = Math.Abs(this.endPoint.Value.Y - this.startPoint.Value.Y); _viewModel.AddItemCommand.Execute(itemBase); } else { ShapeDesignerItemViewModel itemBase = new ShapeDesignerItemViewModel(this._service.DrawModeViewModel.GetDrawMode(), new List<Point> { this.startPoint.Value, this.endPoint.Value }); _viewModel.AddItemCommand.Execute(itemBase); itemBase.PointDesignerItemViewModels.ForEach(p => { p.ParentId = itemBase.Id; _viewModel.DirectAddItemCommand.Execute(p); }); } } this._service.DrawModeViewModel.ResetDrawMode(); } pointDesignerItemViewModelList.ForEach(p => _viewModel.DirectRemoveItemCommand.Execute(p)); e.Handled = true; } protected override void OnRender(DrawingContext dc) { base.OnRender(dc); // without a background the OnMouseMove event would not be fired ! // Alternative: implement a Canvas as a child of this adorner, like // the ConnectionAdorner does. dc.DrawRectangle(Brushes.Transparent, null, new Rect(RenderSize)); if (this.startPoint.HasValue && this.endPoint.HasValue) { if (this._service.DrawModeViewModel.GetDrawMode() == DrawMode.Line) { dc.DrawLine(rubberbandPen, this.startPoint.Value, this.endPoint.Value); } else if (this._service.DrawModeViewModel.GetDrawMode() == DrawMode.Ellipse) { var centerPoint = new Point((this.startPoint.Value.X + this.endPoint.Value.X) / 2, (this.startPoint.Value.Y + this.endPoint.Value.Y) / 2); dc.DrawEllipse(Brushes.Transparent, rubberbandPen, centerPoint, Math.Abs(this.startPoint.Value.X - this.endPoint.Value.X) / 2, Math.Abs(this.startPoint.Value.Y - this.endPoint.Value.Y) / 2); } else if (_service.DrawModeViewModel.GetDrawMode() == DrawMode.Polyline) { var disList = pointList.ToList(); for (int i = 1; i < pointList.Count; i++) { dc.DrawLine(rubberbandPen, disList[i - 1], disList[i]); } } else if (_service.DrawModeViewModel.GetDrawMode() == DrawMode.DirectLine) { var disList = pointList.ToList(); for (int i = 1; i < pointList.Count; i++) { dc.DrawLine(rubberbandPen, disList[i - 1], disList[i]); } } else { dc.DrawRectangle(Brushes.Transparent, rubberbandPen, new Rect(this.startPoint.Value, this.endPoint.Value)); } } } private T GetParent<T>(Type parentType, DependencyObject dependencyObject) where T : DependencyObject { DependencyObject parent = VisualTreeHelper.GetParent(dependencyObject); if (parent.GetType() == parentType) return (T)parent; return GetParent<T>(parentType, parent); } private void UpdateSelection() { IDiagramViewModel vm = (_designerCanvas.DataContext as IDiagramViewModel); Rect rubberBand = new Rect(startPoint.Value, endPoint.Value); ItemsControl itemsControl = GetParent<ItemsControl>(typeof(ItemsControl), _designerCanvas); foreach (SelectableDesignerItemViewModelBase item in vm.Items) { if (item is SelectableDesignerItemViewModelBase) { DependencyObject container = itemsControl.ItemContainerGenerator.ContainerFromItem(item); Rect itemRect = VisualTreeHelper.GetDescendantBounds((Visual)container); Rect itemBounds = ((Visual)container).TransformToAncestor(_designerCanvas).TransformBounds(itemRect); if (rubberBand.Contains(itemBounds)) { //item.IsSelected = true; vm.SelectionService.AddToSelection(item); } else { if (!(Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl))) { //item.IsSelected = false; vm.SelectionService.RemoveFromSelection(item); } } } } } } }