mirror of
https://gitee.com/akwkevin/aistudio.-wpf.-diagram
synced 2026-03-03 00:00:57 +08:00
216 lines
9.2 KiB
C#
216 lines
9.2 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Threading;
|
|
using System.Windows;
|
|
using System.Windows.Controls;
|
|
using System.Windows.Controls.Primitives;
|
|
using System.Windows.Media;
|
|
using AIStudio.Wpf.DiagramDesigner.Geometrys;
|
|
|
|
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;
|
|
}
|
|
|
|
public IDiagramViewModel DiagramViewModel
|
|
{
|
|
get
|
|
{
|
|
return (this.DataContext as SelectableDesignerItemViewModelBase)?.Root;
|
|
}
|
|
}
|
|
|
|
private List<SelectableDesignerItemViewModelBase> designerItems;
|
|
|
|
private void ResizeThumb_DragStarted(object sender, DragStartedEventArgs e)
|
|
{
|
|
DesignerItemViewModelBase designerItem = this.DataContext as DesignerItemViewModelBase;
|
|
if (designerItem != null && designerItem.IsSelected)
|
|
{
|
|
designerItems = designerItem.Root.SelectedItems.ToList();
|
|
|
|
Interlocked.Increment(ref DiagramViewModel.DoCommandManager.BeginDo);
|
|
foreach (DesignerItemViewModelBase item in designerItems.OfType<DesignerItemViewModelBase>())
|
|
{
|
|
item.SetOldValue(item.Size, nameof(item.Size));
|
|
}
|
|
|
|
e.Handled = true;
|
|
}
|
|
else
|
|
{
|
|
designerItems = null;
|
|
}
|
|
}
|
|
|
|
private void ResizeThumb_DragCompleted(object sender, DragCompletedEventArgs e)
|
|
{
|
|
if (designerItems != null)
|
|
{
|
|
Dictionary<DesignerItemViewModelBase, Tuple<SizeBase, SizeBase>> infos =
|
|
designerItems.OfType<DesignerItemViewModelBase>().ToDictionary(p => p,
|
|
p => new Tuple<SizeBase, SizeBase>(p.GetOldValue<SizeBase>(nameof(p.Size)), p.Size));
|
|
|
|
Interlocked.Decrement(ref DiagramViewModel.DoCommandManager.BeginDo);
|
|
DiagramViewModel.DoCommandManager.DoNewCommand(this.ToString(),
|
|
() => {
|
|
foreach (var info in infos)
|
|
{
|
|
info.Key.Size = info.Value.Item2;
|
|
}
|
|
},
|
|
() => {
|
|
foreach (var info in infos)
|
|
{
|
|
info.Key.Size = info.Value.Item1;
|
|
}
|
|
});
|
|
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)
|
|
{
|
|
switch (base.VerticalAlignment)
|
|
{
|
|
case VerticalAlignment.Bottom:
|
|
dragDeltaVertical = Math.Min(-e.VerticalChange, minDeltaVertical);
|
|
scale = (item.ItemHeight - dragDeltaVertical) / item.ItemHeight;
|
|
DragBottom(scale, item, DiagramViewModel.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, DiagramViewModel.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, DiagramViewModel.SelectionService);
|
|
break;
|
|
case HorizontalAlignment.Right:
|
|
dragDeltaHorizontal = Math.Min(-e.HorizontalChange, minDeltaHorizontal);
|
|
scale = (item.ItemWidth - dragDeltaHorizontal) / item.ItemWidth;
|
|
DragRight(scale, item, DiagramViewModel.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, false).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, false).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, false).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, false).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
|
|
}
|
|
} |