Files
aistudio-wpf-diagram/AIStudio.Wpf.DiagramDesigner/Controls/ResizeThumb.cs

216 lines
9.2 KiB
C#
Raw Normal View History

2021-07-23 09:42:22 +08:00
using System;
using System.Collections.Generic;
using System.Linq;
2023-04-08 21:48:43 +08:00
using System.Threading;
2021-07-23 09:42:22 +08:00
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Media;
2023-03-26 23:23:34 +08:00
using AIStudio.Wpf.DiagramDesigner.Geometrys;
2021-07-23 09:42:22 +08:00
2022-10-28 22:45:39 +08:00
namespace AIStudio.Wpf.DiagramDesigner.Controls
2021-07-23 09:42:22 +08:00
{
public class ResizeThumb : Thumb
{
public ResizeThumb()
{
base.DragDelta += new DragDeltaEventHandler(ResizeThumb_DragDelta);
base.DragStarted += ResizeThumb_DragStarted;
base.DragCompleted += ResizeThumb_DragCompleted;
}
2023-03-26 23:23:34 +08:00
public IDiagramViewModel DiagramViewModel
{
get
{
return (this.DataContext as SelectableDesignerItemViewModelBase)?.Root;
}
}
2023-01-24 09:02:40 +08:00
private List<SelectableDesignerItemViewModelBase> designerItems;
2021-07-23 09:42:22 +08:00
private void ResizeThumb_DragStarted(object sender, DragStartedEventArgs e)
{
DesignerItemViewModelBase designerItem = this.DataContext as DesignerItemViewModelBase;
if (designerItem != null && designerItem.IsSelected)
{
2023-01-24 16:20:39 +08:00
designerItems = designerItem.Root.SelectedItems.ToList();
2023-03-26 23:23:34 +08:00
2023-04-08 21:48:43 +08:00
Interlocked.Increment(ref DiagramViewModel.DoCommandManager.BeginDo);
2021-07-23 09:42:22 +08:00
foreach (DesignerItemViewModelBase item in designerItems.OfType<DesignerItemViewModelBase>())
{
2023-03-26 23:23:34 +08:00
item.SetOldValue(item.Size, nameof(item.Size));
2021-07-23 09:42:22 +08:00
}
e.Handled = true;
}
else
{
designerItems = null;
}
}
private void ResizeThumb_DragCompleted(object sender, DragCompletedEventArgs e)
{
if (designerItems != null)
{
2023-03-26 23:23:34 +08:00
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));
2023-03-28 23:16:56 +08:00
2023-04-08 21:48:43 +08:00
Interlocked.Decrement(ref DiagramViewModel.DoCommandManager.BeginDo);
2023-03-26 23:23:34 +08:00
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;
}
});
2021-07-23 09:42:22 +08:00
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>())
{
2023-04-04 22:42:09 +08:00
if (item != null)
2021-07-23 09:42:22 +08:00
{
switch (base.VerticalAlignment)
{
case VerticalAlignment.Bottom:
dragDeltaVertical = Math.Min(-e.VerticalChange, minDeltaVertical);
scale = (item.GetItemHeight() - dragDeltaVertical) / item.GetItemHeight();
2023-03-28 23:16:56 +08:00
DragBottom(scale, item, DiagramViewModel.SelectionService);
2021-07-23 09:42:22 +08:00
break;
case VerticalAlignment.Top:
double top = item.Top;
dragDeltaVertical = Math.Min(Math.Max(-minTop, e.VerticalChange), minDeltaVertical);
scale = (item.GetItemHeight() - dragDeltaVertical) / item.GetItemHeight();
2023-03-28 23:16:56 +08:00
DragTop(scale, item, DiagramViewModel.SelectionService);
2021-07-23 09:42:22 +08:00
break;
default:
break;
}
switch (base.HorizontalAlignment)
{
case HorizontalAlignment.Left:
double left = item.Left;
dragDeltaHorizontal = Math.Min(Math.Max(-minLeft, e.HorizontalChange), minDeltaHorizontal);
scale = (item.GetItemWidth() - dragDeltaHorizontal) / item.GetItemWidth();
2023-03-28 23:16:56 +08:00
DragLeft(scale, item, DiagramViewModel.SelectionService);
2021-07-23 09:42:22 +08:00
break;
case HorizontalAlignment.Right:
dragDeltaHorizontal = Math.Min(-e.HorizontalChange, minDeltaHorizontal);
scale = (item.GetItemWidth() - dragDeltaHorizontal) / item.GetItemWidth();
2023-03-28 23:16:56 +08:00
DragRight(scale, item, DiagramViewModel.SelectionService);
2021-07-23 09:42:22 +08:00
break;
default:
break;
}
}
}
e.Handled = true;
}
}
#region Helper methods
private void DragLeft(double scale, DesignerItemViewModelBase item, SelectionService selectionService)
{
2023-03-07 22:59:27 +08:00
IEnumerable<DesignerItemViewModelBase> groupItems = selectionService.GetGroupMembers(item, false).Cast<DesignerItemViewModelBase>();
2021-07-23 09:42:22 +08:00
double groupLeft = item.Left + item.GetItemWidth();
2021-07-23 09:42:22 +08:00
foreach (DesignerItemViewModelBase groupItem in groupItems)
{
double groupItemLeft = groupItem.Left;
double delta = (groupLeft - groupItemLeft) * (scale - 1);
groupItem.Left = groupItemLeft - delta;
groupItem.ItemWidth = groupItem.GetItemWidth() * scale;
2021-07-23 09:42:22 +08:00
}
}
private void DragTop(double scale, DesignerItemViewModelBase item, SelectionService selectionService)
{
2023-03-07 22:59:27 +08:00
IEnumerable<DesignerItemViewModelBase> groupItems = selectionService.GetGroupMembers(item, false).Cast<DesignerItemViewModelBase>();
double groupBottom = item.Top + item.GetItemHeight();
2021-07-23 09:42:22 +08:00
foreach (DesignerItemViewModelBase groupItem in groupItems)
{
double groupItemTop = groupItem.Top;
double delta = (groupBottom - groupItemTop) * (scale - 1);
groupItem.Top = groupItemTop - delta;
groupItem.ItemHeight = groupItem.GetItemHeight() * scale;
2021-07-23 09:42:22 +08:00
}
}
private void DragRight(double scale, DesignerItemViewModelBase item, SelectionService selectionService)
{
2023-03-07 22:59:27 +08:00
IEnumerable<DesignerItemViewModelBase> groupItems = selectionService.GetGroupMembers(item, false).Cast<DesignerItemViewModelBase>();
2021-07-23 09:42:22 +08:00
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.GetItemWidth() * scale;
2021-07-23 09:42:22 +08:00
}
}
private void DragBottom(double scale, DesignerItemViewModelBase item, SelectionService selectionService)
{
2023-03-07 22:59:27 +08:00
IEnumerable<DesignerItemViewModelBase> groupItems = selectionService.GetGroupMembers(item, false).Cast<DesignerItemViewModelBase>();
2021-07-23 09:42:22 +08:00
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.GetItemHeight() * scale;
2021-07-23 09:42:22 +08:00
}
}
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
}
}