using System; using System.Collections.Generic; using System.Linq; using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; using System.Windows.Media; namespace AIStudio.Wpf.DiagramDesigner.Controls { public class ResizeThumb : Thumb { public ResizeThumb() { base.DragDelta += new DragDeltaEventHandler(ResizeThumb_DragDelta); base.DragStarted += ResizeThumb_DragStarted; base.DragCompleted += ResizeThumb_DragCompleted; } private List<SelectableDesignerItemViewModelBase> designerItems; IDiagramViewModel diagarmViewModel; private void ResizeThumb_DragStarted(object sender, DragStartedEventArgs e) { DesignerItemViewModelBase designerItem = this.DataContext as DesignerItemViewModelBase; diagarmViewModel = designerItem.Root; if (designerItem != null && designerItem.IsSelected) { designerItems = designerItem.Root.SelectedItems.ToList(); foreach (DesignerItemViewModelBase item in designerItems.OfType<DesignerItemViewModelBase>()) { item.BeginDo = true; item.SetOldValue(item.ItemWidth, nameof(item.ItemWidth)); item.SetOldValue(item.ItemHeight, nameof(item.ItemHeight)); } e.Handled = true; } else { designerItems = null; } } private void ResizeThumb_DragCompleted(object sender, DragCompletedEventArgs e) { if (designerItems != null) { foreach (DesignerItemViewModelBase item in designerItems.OfType<DesignerItemViewModelBase>()) { item.BeginDo = false; item.RaiseItemWidthHeight(); } e.Handled = true; } } void ResizeThumb_DragDelta(object sender, DragDeltaEventArgs e) { if (designerItems != null) { double minLeft, minTop, minDeltaHorizontal, minDeltaVertical; double dragDeltaVertical, dragDeltaHorizontal, scale; CalculateDragLimits(designerItems.OfType<DesignerItemViewModelBase>(), out minLeft, out minTop, out minDeltaHorizontal, out minDeltaVertical); foreach (DesignerItemViewModelBase item in designerItems.OfType<DesignerItemViewModelBase>()) { if (item != null && item.ParentId == Guid.Empty) { switch (base.VerticalAlignment) { case VerticalAlignment.Bottom: dragDeltaVertical = Math.Min(-e.VerticalChange, minDeltaVertical); scale = (item.ItemHeight - dragDeltaVertical) / item.ItemHeight; DragBottom(scale, item, diagarmViewModel.SelectionService); break; case VerticalAlignment.Top: double top = item.Top; dragDeltaVertical = Math.Min(Math.Max(-minTop, e.VerticalChange), minDeltaVertical); scale = (item.ItemHeight - dragDeltaVertical) / item.ItemHeight; DragTop(scale, item, diagarmViewModel.SelectionService); break; default: break; } switch (base.HorizontalAlignment) { case HorizontalAlignment.Left: double left = item.Left; dragDeltaHorizontal = Math.Min(Math.Max(-minLeft, e.HorizontalChange), minDeltaHorizontal); scale = (item.ItemWidth - dragDeltaHorizontal) / item.ItemWidth; DragLeft(scale, item, diagarmViewModel.SelectionService); break; case HorizontalAlignment.Right: dragDeltaHorizontal = Math.Min(-e.HorizontalChange, minDeltaHorizontal); scale = (item.ItemWidth - dragDeltaHorizontal) / item.ItemWidth; DragRight(scale, item, diagarmViewModel.SelectionService); break; default: break; } } } e.Handled = true; } } #region Helper methods private void DragLeft(double scale, DesignerItemViewModelBase item, SelectionService selectionService) { IEnumerable<DesignerItemViewModelBase> groupItems = selectionService.GetGroupMembers(item).Cast<DesignerItemViewModelBase>(); double groupLeft = item.Left + item.ItemWidth; foreach (DesignerItemViewModelBase groupItem in groupItems) { double groupItemLeft = groupItem.Left; double delta = (groupLeft - groupItemLeft) * (scale - 1); groupItem.Left = groupItemLeft - delta; groupItem.ItemWidth = groupItem.ItemWidth * scale; } } private void DragTop(double scale, DesignerItemViewModelBase item, SelectionService selectionService) { IEnumerable<DesignerItemViewModelBase> groupItems = selectionService.GetGroupMembers(item).Cast<DesignerItemViewModelBase>(); double groupBottom = item.Top + item.ItemHeight; foreach (DesignerItemViewModelBase groupItem in groupItems) { double groupItemTop = groupItem.Top; double delta = (groupBottom - groupItemTop) * (scale - 1); groupItem.Top = groupItemTop - delta; groupItem.ItemHeight = groupItem.ItemHeight * scale; } } private void DragRight(double scale, DesignerItemViewModelBase item, SelectionService selectionService) { IEnumerable<DesignerItemViewModelBase> groupItems = selectionService.GetGroupMembers(item).Cast<DesignerItemViewModelBase>(); double groupLeft = item.Left; foreach (DesignerItemViewModelBase groupItem in groupItems) { double groupItemLeft = groupItem.Left; double delta = (groupItemLeft - groupLeft) * (scale - 1); groupItem.Left = groupItemLeft + delta; groupItem.ItemWidth = groupItem.ItemWidth * scale; } } private void DragBottom(double scale, DesignerItemViewModelBase item, SelectionService selectionService) { IEnumerable<DesignerItemViewModelBase> groupItems = selectionService.GetGroupMembers(item).Cast<DesignerItemViewModelBase>(); double groupTop = item.Top; foreach (DesignerItemViewModelBase groupItem in groupItems) { double groupItemTop = groupItem.Top; double delta = (groupItemTop - groupTop) * (scale - 1); groupItem.Top = groupItemTop + delta; groupItem.ItemHeight = groupItem.ItemHeight * scale; } } private void CalculateDragLimits(IEnumerable<DesignerItemViewModelBase> selectedItems, out double minLeft, out double minTop, out double minDeltaHorizontal, out double minDeltaVertical) { minLeft = double.MaxValue; minTop = double.MaxValue; minDeltaHorizontal = double.MaxValue; minDeltaVertical = double.MaxValue; // drag limits are set by these parameters: canvas top, canvas left, minHeight, minWidth // calculate min value for each parameter for each item foreach (DesignerItemViewModelBase item in selectedItems) { double left = item.Left; double top = item.Top; minLeft = double.IsNaN(left) ? 0 : Math.Min(left, minLeft); minTop = double.IsNaN(top) ? 0 : Math.Min(top, minTop); minDeltaVertical = Math.Min(minDeltaVertical, 10); minDeltaHorizontal = Math.Min(minDeltaHorizontal, 10); } } #endregion } }