添加block快,不需要连接线,直接吸附。

This commit is contained in:
艾竹
2023-05-21 22:06:59 +08:00
parent 2fd8321363
commit fde899cfa9
30 changed files with 680 additions and 338 deletions

View File

@@ -109,6 +109,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="AIStudio.Wpf.ColorPicker" Version="1.1.2" />
<PackageReference Include="AIStudio.Wpf.ComeCapture" Version="1.1.0" /> <PackageReference Include="AIStudio.Wpf.ComeCapture" Version="1.1.0" />
<PackageReference Include="Costura.Fody" Version="5.7.0"> <PackageReference Include="Costura.Fody" Version="5.7.0">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>

View File

@@ -727,7 +727,8 @@ namespace AIStudio.Wpf.DiagramApp.ViewModels
private void ColorPickerExecuted() private void ColorPickerExecuted()
{ {
AIStudio.Wpf.ColorPicker.MainWindow window = new AIStudio.Wpf.ColorPicker.MainWindow();
window.Show();
} }
#region #region

View File

@@ -580,7 +580,7 @@ namespace AIStudio.Wpf.DiagramApp.ViewModels
public void AddImageExecuted(object para) public void AddImageExecuted(object para)
{ {
ImageItemViewModel itemBase = new ImageItemViewModel(); ImageItemViewModel itemBase = new ImageItemViewModel();
DiagramViewModel?.AddItemCommand.Execute(itemBase); DiagramViewModel?.AddCommand.Execute(itemBase);
if (itemBase.Root != null) if (itemBase.Root != null)
{ {
_service.DrawModeViewModel.CursorMode = CursorMode.Move; _service.DrawModeViewModel.CursorMode = CursorMode.Move;
@@ -631,7 +631,7 @@ namespace AIStudio.Wpf.DiagramApp.ViewModels
public void AddVideoExectued(object para) public void AddVideoExectued(object para)
{ {
VideoItemViewModel itemBase = new VideoItemViewModel(); VideoItemViewModel itemBase = new VideoItemViewModel();
DiagramViewModel?.AddItemCommand.Execute(itemBase); DiagramViewModel?.AddCommand.Execute(itemBase);
if (itemBase.Root != null) if (itemBase.Root != null)
{ {
_service.DrawModeViewModel.CursorMode = CursorMode.Move; _service.DrawModeViewModel.CursorMode = CursorMode.Move;
@@ -641,7 +641,7 @@ namespace AIStudio.Wpf.DiagramApp.ViewModels
public void AddOutLineTextExecuted(object para) public void AddOutLineTextExecuted(object para)
{ {
OutLineTextDesignerItemViewModel itemBase = new OutLineTextDesignerItemViewModel(); OutLineTextDesignerItemViewModel itemBase = new OutLineTextDesignerItemViewModel();
DiagramViewModel?.AddItemCommand.Execute(itemBase); DiagramViewModel?.AddCommand.Execute(itemBase);
if (itemBase.Root != null) if (itemBase.Root != null)
{ {
_service.DrawModeViewModel.CursorMode = CursorMode.Move; _service.DrawModeViewModel.CursorMode = CursorMode.Move;
@@ -651,7 +651,7 @@ namespace AIStudio.Wpf.DiagramApp.ViewModels
public void AddBarcodeExecuted(object para) public void AddBarcodeExecuted(object para)
{ {
BarcodeDesignerItemViewModel itemBase = new BarcodeDesignerItemViewModel() { Format = (BarcodeFormat)Enum.Parse(typeof(BarcodeFormat), para.ToString()), Text = "AIStudio.Wpf.DiagramApp" }; BarcodeDesignerItemViewModel itemBase = new BarcodeDesignerItemViewModel() { Format = (BarcodeFormat)Enum.Parse(typeof(BarcodeFormat), para.ToString()), Text = "AIStudio.Wpf.DiagramApp" };
DiagramViewModel?.AddItemCommand.Execute(itemBase); DiagramViewModel?.AddCommand.Execute(itemBase);
if (itemBase.Root != null) if (itemBase.Root != null)
{ {
_service.DrawModeViewModel.CursorMode = CursorMode.Move; _service.DrawModeViewModel.CursorMode = CursorMode.Move;

View File

@@ -80,7 +80,7 @@ namespace AIStudio.Wpf.DiagramApp.ViewModels
} }
private ICommand _addItemCommand; private ICommand _addItemCommand;
public ICommand AddItemCommand public ICommand AddCommand
{ {
get get
{ {
@@ -119,7 +119,9 @@ namespace AIStudio.Wpf.DiagramApp.ViewModels
List<ToolBoxData> defaultToolBoxItems = new List<ToolBoxData>(); List<ToolBoxData> defaultToolBoxItems = new List<ToolBoxData>();
defaultToolBoxItems.Add(new TextToolBoxData("", typeof(DefaultDesignerItemViewModel))); defaultToolBoxItems.Add(new TextToolBoxData("", typeof(DefaultDesignerItemViewModel)));
var blockitem = new TextToolBoxData("", typeof(BlockDesignerItemViewModel), 64, 32, new Size(130, 65));
blockitem.ColorViewModel.FillColor.Color = Color.FromRgb(0x00, 0x2F, 0xA7);
defaultToolBoxItems.Add(blockitem);
ToolBoxCategory.Add(new ToolBoxCategory() { Header = "Default", ToolBoxItems = new ObservableCollection<ToolBoxData>(defaultToolBoxItems), IsExpanded = true }); ToolBoxCategory.Add(new ToolBoxCategory() { Header = "Default", ToolBoxItems = new ObservableCollection<ToolBoxData>(defaultToolBoxItems), IsExpanded = true });
ToolBoxCategory.Add(new ToolBoxCategory() { Header = "Svg", ToolBoxItems = new ObservableCollection<ToolBoxData>() }); ToolBoxCategory.Add(new ToolBoxCategory() { Header = "Svg", ToolBoxItems = new ObservableCollection<ToolBoxData>() });

View File

@@ -2556,6 +2556,16 @@
Width="190" /> Width="190" />
</Fluent:Button.ToolTip> </Fluent:Button.ToolTip>
</Fluent:Button> </Fluent:Button>
<Fluent:Button Header="取色器" Width="50" VerticalAlignment="Top" Command="{Binding ColorPickerCommand}">
<Fluent:Button.LargeIcon>
<Path Width="18" Height="18" Stretch="Uniform" Fill="Black" Data="M484.9999999999999 416.5L416.5 485A48.00000000000001 48.00000000000001 0 0 1 350 486.75L300 436.75L267.75 467.75A25 25 0 0 1 232.2500000000001 432.25L263.25 400L125 261.75A50 50 0 0 1 110.75 231.5000000000001L100 127.25A25 25 0 0 1 107.25 107.25A25 25 0 0 1 125 100H127.25L231.5 109.5A50 50 0 0 1 261.75 123.75L401.25 263.25L432.2499999999999 232.25A25 25 0 0 1 467.7499999999998 232.25A25 25 0 0 1 467.7499999999998 267.75L436.7499999999999 298.75L486.7499999999999 348.75A48.00000000000001 48.00000000000001 0 0 1 484.9999999999999 416.5zM160 226.5L300 366L367.25 298.5000000000001L297.5 228.7500000000001"/>
</Fluent:Button.LargeIcon>
<Fluent:Button.ToolTip>
<Fluent:ScreenTip Title="Screen"
Text="取色器"
Width="190" />
</Fluent:Button.ToolTip>
</Fluent:Button>
</Fluent:RibbonGroupBox> </Fluent:RibbonGroupBox>
</Fluent:RibbonTabItem> </Fluent:RibbonTabItem>
<Fluent:RibbonTabItem Header="帮助"> <Fluent:RibbonTabItem Header="帮助">

View File

@@ -363,7 +363,7 @@
<Button Margin="0,5,2,5" ToolTip="导入到我的符号" Command="{Binding DataContext.ImportItemCommand, RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type UserControl}}}" Width="16" Height="16" Foreground="{DynamicResource BlackBrush}" Background="{DynamicResource WhiteBrush}" BorderBrush="Transparent"> <Button Margin="0,5,2,5" ToolTip="导入到我的符号" Command="{Binding DataContext.ImportItemCommand, RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type UserControl}}}" Width="16" Height="16" Foreground="{DynamicResource BlackBrush}" Background="{DynamicResource WhiteBrush}" BorderBrush="Transparent">
<Path Stretch="Fill" Margin="2" Fill="{DynamicResource GrayBrush2}" Data="M14,12L10,8V11H2V13H10V16M20,18V6C20,4.89 19.1,4 18,4H6A2,2 0 0,0 4,6V9H6V6H18V18H6V15H4V18A2,2 0 0,0 6,20H18A2,2 0 0,0 20,18Z" ></Path> <Path Stretch="Fill" Margin="2" Fill="{DynamicResource GrayBrush2}" Data="M14,12L10,8V11H2V13H10V16M20,18V6C20,4.89 19.1,4 18,4H6A2,2 0 0,0 4,6V9H6V6H18V18H6V15H4V18A2,2 0 0,0 6,20H18A2,2 0 0,0 20,18Z" ></Path>
</Button> </Button>
<Button Margin="0,5,2,5" ToolTip="添加到我的符号" Command="{Binding DataContext.AddItemCommand, RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type UserControl}}}" Width="16" Height="16" Foreground="{DynamicResource BlackBrush}" Background="{DynamicResource WhiteBrush}" BorderBrush="Transparent"> <Button Margin="0,5,2,5" ToolTip="添加到我的符号" Command="{Binding DataContext.AddCommand, RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type UserControl}}}" Width="16" Height="16" Foreground="{DynamicResource BlackBrush}" Background="{DynamicResource WhiteBrush}" BorderBrush="Transparent">
<Path Stretch="Fill" Margin="2" Fill="{DynamicResource GrayBrush2}" Data="M938.666667 426.666667h-341.333334V85.333333c0-46.933333-38.4-85.333333-85.333333-85.333333s-85.333333 38.4-85.333333 85.333333v341.333334H85.333333c-46.933333 0-85.333333 38.4-85.333333 85.333333s38.4 85.333333 85.333333 85.333333h341.333334v341.333334c0 46.933333 38.4 85.333333 85.333333 85.333333s85.333333-38.4 85.333333-85.333333v-341.333334h341.333334c46.933333 0 85.333333-38.4 85.333333-85.333333s-38.4-85.333333-85.333333-85.333333z" ></Path> <Path Stretch="Fill" Margin="2" Fill="{DynamicResource GrayBrush2}" Data="M938.666667 426.666667h-341.333334V85.333333c0-46.933333-38.4-85.333333-85.333333-85.333333s-85.333333 38.4-85.333333 85.333333v341.333334H85.333333c-46.933333 0-85.333333 38.4-85.333333 85.333333s38.4 85.333333 85.333333 85.333333h341.333334v341.333334c0 46.933333 38.4 85.333333 85.333333 85.333333s85.333333-38.4 85.333333-85.333333v-341.333334h341.333334c46.933333 0 85.333333-38.4 85.333333-85.333333s-38.4-85.333333-85.333333-85.333333z" ></Path>
</Button> </Button>
<Button Margin="0,5,5,5" ToolTip="移除" Command="{Binding DataContext.DeleteCommand, RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type UserControl}}}" CommandParameter="{Binding .}" Width="16" Height="16" Foreground="{DynamicResource BlackBrush}" Background="{DynamicResource WhiteBrush}" BorderBrush="Transparent"> <Button Margin="0,5,5,5" ToolTip="移除" Command="{Binding DataContext.DeleteCommand, RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type UserControl}}}" CommandParameter="{Binding .}" Width="16" Height="16" Foreground="{DynamicResource BlackBrush}" Background="{DynamicResource WhiteBrush}" BorderBrush="Transparent">

View File

@@ -189,7 +189,7 @@ namespace AIStudio.Wpf.DiagramDesigner
if (_drawingDesignerItem?.IsFinish == true) if (_drawingDesignerItem?.IsFinish == true)
{ {
_viewModel.AddItemCommand.Execute(_drawingDesignerItem); _viewModel.AddCommand.Execute(_drawingDesignerItem);
} }
this._service.DrawModeViewModel.ResetDrawMode(); this._service.DrawModeViewModel.ResetDrawMode();

View File

@@ -90,7 +90,7 @@ namespace AIStudio.Wpf.DiagramDesigner
itemBase.ItemWidth = Math.Abs(this.endPoint.Value.X - this.startPoint.Value.X); itemBase.ItemWidth = Math.Abs(this.endPoint.Value.X - this.startPoint.Value.X);
itemBase.ItemHeight = Math.Abs(this.endPoint.Value.Y - this.startPoint.Value.Y); itemBase.ItemHeight = Math.Abs(this.endPoint.Value.Y - this.startPoint.Value.Y);
_viewModel.AddItemCommand.Execute(itemBase); _viewModel.AddCommand.Execute(itemBase);
} }
} }
this._service.DrawModeViewModel.ResetDrawMode(); this._service.DrawModeViewModel.ResetDrawMode();

View File

@@ -231,9 +231,7 @@ namespace AIStudio.Wpf.DiagramDesigner
public DesignerCanvas() public DesignerCanvas()
{ {
this.Focusable = true; this.Focusable = true;
Mediator.Instance.Register(this);
_service.PropertyChanged += _service_PropertyChanged;
this.Loaded += DesignerCanvas_Loaded; this.Loaded += DesignerCanvas_Loaded;
this.IsVisibleChanged += DesignerCanvas_IsVisibleChanged; this.IsVisibleChanged += DesignerCanvas_IsVisibleChanged;
} }
@@ -248,7 +246,9 @@ namespace AIStudio.Wpf.DiagramDesigner
private void DesignerCanvas_Loaded(object sender, RoutedEventArgs e) private void DesignerCanvas_Loaded(object sender, RoutedEventArgs e)
{ {
Mediator.Instance.Register(this);
this.Focus(); this.Focus();
_service.PropertyChanged += _service_PropertyChanged;
} }
protected override void OnRender(DrawingContext dc) protected override void OnRender(DrawingContext dc)
@@ -394,16 +394,8 @@ namespace AIStudio.Wpf.DiagramDesigner
_viewModel.ClearSelectedItems(); _viewModel.ClearSelectedItems();
} }
if (_service.DrawModeViewModel.LineDrawModeSelected)//画线模式,可以不命中实体 if (_service.DrawModeViewModel.SharpDrawModeSelected ||
{
if (SourceConnector == null)
{
//新建一个Part连接点
SourceConnector = new Connector() { Content = new PartCreatedConnectorInfo(currentPoint.X, currentPoint.Y), Tag = "虚拟的连接点" };
}
}
else if (_service.DrawModeViewModel.SharpDrawModeSelected ||
(_service.DrawModeViewModel.DrawingDrawModeSelected && _service.DrawModeViewModel.DrawingDrawMode != DrawMode.Select)) (_service.DrawModeViewModel.DrawingDrawModeSelected && _service.DrawModeViewModel.DrawingDrawMode != DrawMode.Select))
{ {
// create rubberband adorner // create rubberband adorner
@@ -417,7 +409,14 @@ namespace AIStudio.Wpf.DiagramDesigner
} }
} }
} }
else if (_service.DrawModeViewModel.LineDrawModeSelected)//画线模式,可以不命中实体
{
if (SourceConnector == null)
{
//新建一个Part连接点
SourceConnector = new Connector() { Content = new PartCreatedConnectorInfo(currentPoint.X, currentPoint.Y), Tag = "虚拟的连接点" };
}
}
e.Handled = true; e.Handled = true;
} }
} }
@@ -511,8 +510,8 @@ namespace AIStudio.Wpf.DiagramDesigner
{ {
ConnectorInfoBase sinkDataItem = SinkConnector.Info; ConnectorInfoBase sinkDataItem = SinkConnector.Info;
_viewModel.Remove(partialConnection); _viewModel.Delete(partialConnection);
_viewModel.AddItemCommand.Execute(new ConnectionViewModel(_viewModel, sourceDataItem, sinkDataItem, LineDrawMode, RouterMode)); _viewModel.AddCommand.Execute(new ConnectionViewModel(_viewModel, sourceDataItem, sinkDataItem, LineDrawMode, RouterMode));
} }
else if (partialConnection.IsFullConnection)//自动连接模式 else if (partialConnection.IsFullConnection)//自动连接模式
{ {
@@ -523,13 +522,13 @@ namespace AIStudio.Wpf.DiagramDesigner
Point currentPoint = e.GetPosition(this); Point currentPoint = e.GetPosition(this);
ConnectorInfoBase sinkDataItem = new PartCreatedConnectorInfo(currentPoint.X, currentPoint.Y); ConnectorInfoBase sinkDataItem = new PartCreatedConnectorInfo(currentPoint.X, currentPoint.Y);
_viewModel.Remove(partialConnection); _viewModel.Delete(partialConnection);
_viewModel.AddItemCommand.Execute(new ConnectionViewModel(_viewModel, sourceDataItem, sinkDataItem, LineDrawMode, RouterMode)); _viewModel.AddCommand.Execute(new ConnectionViewModel(_viewModel, sourceDataItem, sinkDataItem, LineDrawMode, RouterMode));
} }
else else
{ {
//Need to remove last item as we did not finish drawing the path //Need to remove last item as we did not finish drawing the path
_viewModel.Remove(partialConnection); _viewModel.Delete(partialConnection);
} }
} }
@@ -635,7 +634,7 @@ namespace AIStudio.Wpf.DiagramDesigner
item.Left += position.X - itemswidth / 2; item.Left += position.X - itemswidth / 2;
item.Top += position.Y - itemsheight / 2; item.Top += position.Y - itemsheight / 2;
} }
_viewModel.AddItemCommand.Execute(designerItems); _viewModel.AddCommand.Execute(designerItems);
} }
else else
{ {
@@ -657,7 +656,7 @@ namespace AIStudio.Wpf.DiagramDesigner
} }
itemBase.Left = Math.Max(0, position.X - itemBase.ItemWidth / 2); itemBase.Left = Math.Max(0, position.X - itemBase.ItemWidth / 2);
itemBase.Top = Math.Max(0, position.Y - itemBase.ItemHeight / 2); itemBase.Top = Math.Max(0, position.Y - itemBase.ItemHeight / 2);
_viewModel.AddItemCommand.Execute(itemBase); _viewModel.AddCommand.Execute(itemBase);
} }
} }
var dragFile = e.Data.GetData(DataFormats.FileDrop); var dragFile = e.Data.GetData(DataFormats.FileDrop);
@@ -675,7 +674,7 @@ namespace AIStudio.Wpf.DiagramDesigner
itemBase.Left = Math.Max(0, position.X - itemBase.ItemWidth / 2); itemBase.Left = Math.Max(0, position.X - itemBase.ItemWidth / 2);
itemBase.Top = Math.Max(0, position.Y - itemBase.ItemHeight / 2); itemBase.Top = Math.Max(0, position.Y - itemBase.ItemHeight / 2);
_viewModel.AddItemCommand.Execute(itemBase); _viewModel.AddCommand.Execute(itemBase);
} }
} }
e.Handled = true; e.Handled = true;

View File

@@ -96,9 +96,53 @@ namespace AIStudio.Wpf.DiagramDesigner.Controls
item.SetCellAlignment(); item.SetCellAlignment();
} }
var blocks = designerItems.OfType<BlockDesignerItemViewModel>().ToList();
if (blocks.Any())
{
foreach (BlockDesignerItemViewModel item in blocks)
{
var portTuple = DiagramViewModel.FindNearPortToAttachTo(item, true);
var portParent = portTuple.Item1;
var portNext = portTuple.Item2;
if (portParent != null)
{
(portParent.DataItem as BlockDesignerItemViewModel).AddNext(item);
portParent.BeAttachTo = false;
portParent.DisableAttachTo = false;
}
else
{
if (item.Parent != null)
{
(item.Parent as BlockDesignerItemViewModel).Next = null;
item.Parent = null;
item.ParentId = new Guid();
}
}
if (portNext != null)
{
item.AddNext(portNext.DataItem as BlockDesignerItemViewModel);
portNext.BeAttachTo = false;
portNext.DisableAttachTo = false;
}
else
{
if (item.Next != null)
{
item.Next.Parent = null;
item.Next.ParentId = new Guid();
item.Next = null;
}
}
}
//-DiagramViewModel.ClearNearPort();
}
Dictionary<DesignerItemViewModelBase, Tuple<PointBase, PointBase>> infos = Dictionary<DesignerItemViewModelBase, Tuple<PointBase, PointBase>> infos =
designerItems.OfType<DesignerItemViewModelBase>().ToDictionary(p => p, designerItems.OfType<DesignerItemViewModelBase>().ToDictionary(p => p,
p => new Tuple<PointBase, PointBase>(p.GetOldValue<PointBase>(nameof(p.TopLeft)), p.TopLeft)); p => new Tuple<PointBase, PointBase>(p.GetOldValue<PointBase>(nameof(p.TopLeft)), p.TopLeft));
//部分连接点可以移动 //部分连接点可以移动
Dictionary<ConnectionViewModel, Tuple<Tuple<PointBase?, PointBase?>, Tuple<PointBase?, PointBase?>>> conncetorinfos = Dictionary<ConnectionViewModel, Tuple<Tuple<PointBase?, PointBase?>, Tuple<PointBase?, PointBase?>>> conncetorinfos =
@@ -162,6 +206,15 @@ namespace AIStudio.Wpf.DiagramDesigner.Controls
item.SetPartPostion(sourcePoint, sinkPoint); item.SetPartPostion(sourcePoint, sinkPoint);
} }
var blocks = designerItems.OfType<BlockDesignerItemViewModel>().ToList();
if (blocks.Any())
{
DiagramViewModel.ClearNearPort();
foreach (BlockDesignerItemViewModel item in blocks)
{
DiagramViewModel.FindNearPortToAttachTo(item, false);
}
}
e.Handled = true; e.Handled = true;
} }
} }

View File

@@ -13,10 +13,17 @@ namespace AIStudio.Wpf.DiagramDesigner
return point; return point;
} }
var connectorWidth = double.IsNaN(connector.ConnectorWidth) ? 0 : connector.ConnectorWidth;
var connectorHeight = double.IsNaN(connector.ConnectorHeight) ? 0 : connector.ConnectorHeight;
var left = connector.DataItem.Left;
var top = connector.DataItem.Top;
var itemWidth = connector.DataItem.ItemWidth;
var itemHeight = connector.DataItem.ItemHeight;
if (connector.IsInnerPoint) if (connector.IsInnerPoint)
{ {
point = new PointBase(connector.DataItem.Left + connector.DataItem.ItemWidth * connector.XRatio - connector.ConnectorWidth / 2, point = new PointBase(left + itemWidth * connector.XRatio - connectorWidth / 2,
connector.DataItem.Top + connector.DataItem.ItemHeight * connector.YRatio - connector.ConnectorHeight / 2); top + itemHeight * connector.YRatio - connectorHeight / 2);
} }
else if (connector.IsPortless) else if (connector.IsPortless)
{ {
@@ -27,39 +34,39 @@ namespace AIStudio.Wpf.DiagramDesigner
switch (connector.Orientation) switch (connector.Orientation)
{ {
case ConnectorOrientation.Left: case ConnectorOrientation.Left:
point = new PointBase(connector.DataItem.Left - connector.ConnectorWidth / 2, connector.DataItem.Top + (connector.DataItem.ItemHeight / 2) - connector.ConnectorHeight / 2); point = new PointBase(left - connectorWidth / 2, top + (itemHeight / 2) - connectorHeight / 2);
break; break;
case ConnectorOrientation.TopLeft: case ConnectorOrientation.TopLeft:
point = new PointBase(connector.DataItem.Left - connector.ConnectorWidth / 2, connector.DataItem.Top - connector.ConnectorHeight / 2); point = new PointBase(left - connectorWidth / 2, top - connectorHeight / 2);
break; break;
case ConnectorOrientation.Top: case ConnectorOrientation.Top:
point = new PointBase(connector.DataItem.Left + (connector.DataItem.ItemWidth / 2) - connector.ConnectorWidth / 2, connector.DataItem.Top - connector.ConnectorHeight / 2); point = new PointBase(left + (itemWidth / 2) - connectorWidth / 2, top - connectorHeight / 2);
break; break;
case ConnectorOrientation.TopRight: case ConnectorOrientation.TopRight:
point = new PointBase(connector.DataItem.Left + connector.DataItem.ItemWidth - connector.ConnectorWidth / 2, connector.DataItem.Top - connector.ConnectorHeight / 2); point = new PointBase(left + itemWidth - connectorWidth / 2, top - connectorHeight / 2);
break; break;
case ConnectorOrientation.Right: case ConnectorOrientation.Right:
point = new PointBase(connector.DataItem.Left + connector.DataItem.ItemWidth - connector.ConnectorWidth / 2, connector.DataItem.Top + (connector.DataItem.ItemHeight / 2) - connector.ConnectorHeight / 2); point = new PointBase(left + itemWidth - connectorWidth / 2, top + (itemHeight / 2) - connectorHeight / 2);
break; break;
case ConnectorOrientation.BottomRight: case ConnectorOrientation.BottomRight:
point = new PointBase(connector.DataItem.Left + connector.DataItem.ItemWidth - connector.ConnectorWidth / 2, connector.DataItem.Top + connector.DataItem.ItemHeight - connector.ConnectorHeight / 2); point = new PointBase(left + itemWidth - connectorWidth / 2, top + itemHeight - connectorHeight / 2);
break; break;
case ConnectorOrientation.Bottom: case ConnectorOrientation.Bottom:
point = new PointBase(connector.DataItem.Left + (connector.DataItem.ItemWidth / 2) - connector.ConnectorWidth / 2, connector.DataItem.Top + connector.DataItem.ItemHeight - connector.ConnectorHeight / 2); point = new PointBase(left + (itemWidth / 2) - connectorWidth / 2, top + itemHeight - connectorHeight / 2);
break; break;
case ConnectorOrientation.BottomLeft: case ConnectorOrientation.BottomLeft:
point = new PointBase(connector.DataItem.Left - connector.ConnectorWidth / 2, connector.DataItem.Top + connector.DataItem.ItemHeight - connector.ConnectorHeight / 2); point = new PointBase(left - connectorWidth / 2, top + itemHeight - connectorHeight / 2);
break; break;
default: default:
point = new PointBase(connector.DataItem.Left + (connector.DataItem.ItemWidth / 2) - connector.ConnectorWidth / 2, connector.DataItem.Top + (connector.DataItem.ItemHeight / 2) - connector.ConnectorHeight / 2); point = new PointBase(left + (itemWidth / 2) - connectorWidth / 2, top + (itemHeight / 2) - connectorHeight / 2);
break; break;
} }
} }
if (middle) if (middle)
{ {
point.X = point.X + connector.ConnectorWidth / 2; point.X = point.X + connectorWidth / 2;
point.Y = point.Y + connector.ConnectorHeight / 2; point.Y = point.Y + connectorHeight / 2;
} }
//旋转后的坐标 //旋转后的坐标
var newX = (point.X - connector.DataItem.MiddlePosition.X) * Math.Cos(connector.DataItem.Angle * Math.PI / 180) - (point.Y - connector.DataItem.MiddlePosition.Y) * Math.Sin(connector.DataItem.Angle * Math.PI / 180) + connector.DataItem.MiddlePosition.X; var newX = (point.X - connector.DataItem.MiddlePosition.X) * Math.Cos(connector.DataItem.Angle * Math.PI / 180) - (point.Y - connector.DataItem.MiddlePosition.Y) * Math.Sin(connector.DataItem.Angle * Math.PI / 180) + connector.DataItem.MiddlePosition.X;

View File

@@ -37,6 +37,11 @@ namespace AIStudio.Wpf.DiagramDesigner
return (Style)itemsControl.FindResource("logicalItemStyle"); return (Style)itemsControl.FindResource("logicalItemStyle");
} }
if (item is BlockDesignerItemViewModel)
{
return (Style)itemsControl.FindResource("blockItemStyle");
}
if (item is DesignerItemViewModelBase) if (item is DesignerItemViewModelBase)
{ {
return (Style)itemsControl.FindResource("designerItemStyle"); return (Style)itemsControl.FindResource("designerItemStyle");

View File

@@ -142,6 +142,22 @@
</DataTemplate.Triggers> </DataTemplate.Triggers>
</DataTemplate> </DataTemplate>
<DataTemplate DataType="{x:Type dd:BlockConnectorInfo}">
<Grid Width="{Binding ConnectorWidth}" Height="{Binding ConnectorHeight}" >
<Rectangle x:Name="innter" Fill="{Binding ColorViewModel.FillColor,Converter={StaticResource ColorBrushConverter}}" StrokeThickness="1" Stroke="{Binding ColorViewModel.LineColor,Converter={StaticResource ColorBrushConverter}}" />
</Grid>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding BeAttachTo}" Value="True">
<Setter TargetName="innter" Property="Fill" Value="#f73438" />
<Setter TargetName="innter" Property="Stroke" Value="#f73438" />
</DataTrigger>
<DataTrigger Binding="{Binding DisableAttachTo}" Value="True">
<Setter TargetName="innter" Property="Fill" Value="Gray" />
<Setter TargetName="innter" Property="Stroke" Value="Gray" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
<!-- DragThumb Default Template --> <!-- DragThumb Default Template -->
<Style TargetType="{x:Type c:DragThumb}"> <Style TargetType="{x:Type c:DragThumb}">
<Setter Property="Template"> <Setter Property="Template">

View File

@@ -97,6 +97,18 @@
</Grid> </Grid>
</DataTemplate> </DataTemplate>
<DataTemplate DataType="{x:Type dd:BlockDesignerItemViewModel}">
<Grid IsHitTestVisible="False">
<Rectangle StrokeThickness="1" Fill="{Binding ColorViewModel.FillColor,Converter={StaticResource ColorBrushConverter}}" Stroke="{Binding ColorViewModel.LineColor,Converter={StaticResource ColorBrushConverter}}" />
<Border x:Name="left" HorizontalAlignment="Left" Width="5" Background="Transparent"/>
</Grid>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding IsSelected}" Value="true">
<Setter TargetName="left" Property="Background" Value="#3399FF"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
<DataTemplate DataType="{x:Type dd:ImageItemViewModel}"> <DataTemplate DataType="{x:Type dd:ImageItemViewModel}">
<Grid ToolTip="{Binding Icon}"> <Grid ToolTip="{Binding Icon}">
<Grid IsHitTestVisible="False" ClipToBounds="True"> <Grid IsHitTestVisible="False" ClipToBounds="True">

View File

@@ -217,7 +217,7 @@
</Border> </Border>
<Rectangle Fill="#7F243859" Opacity="0.5" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Visibility="{Binding ShouldInsertAnchor, Converter={StaticResource BooleanToVisibilityConverter}}"> <Rectangle Fill="#7F243859" Opacity="0.5" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Visibility="{Binding ShouldInsertAnchor, Converter={StaticResource BooleanToVisibilityConverter}}">
<i:Interaction.Behaviors> <i:Interaction.Behaviors>
<dd:ControlMouseLeftButtonDownCommandBehavior Command="{Binding AddItemCommand}" /> <dd:ControlMouseLeftButtonDownCommandBehavior Command="{Binding AddCommand}" />
</i:Interaction.Behaviors> </i:Interaction.Behaviors>
</Rectangle> </Rectangle>
</Grid> </Grid>
@@ -341,6 +341,36 @@
</dd:ConnectorContainer> </dd:ConnectorContainer>
</ControlTemplate> </ControlTemplate>
<ControlTemplate x:Key="BlockConnectorDecoratorTemplate"
TargetType="{x:Type Control}">
<Grid Margin="{Binding ConnectorMargin}">
<dd:Connector
Content="{Binding LeftConnector}"
SnapsToDevicePixels="True"
Orientation="Left"
VerticalAlignment="Stretch"
HorizontalAlignment="Left"/>
<dd:Connector
Content="{Binding TopConnector}"
SnapsToDevicePixels="True"
Orientation="Top"
VerticalAlignment="Top"
HorizontalAlignment="Stretch"/>
<dd:Connector
Content="{Binding RightConnector}"
SnapsToDevicePixels="True"
Orientation="Right"
VerticalAlignment="Stretch"
HorizontalAlignment="Right"/>
<dd:Connector
Content="{Binding BottomConnector}"
SnapsToDevicePixels="True"
Orientation="Bottom"
VerticalAlignment="Bottom"
HorizontalAlignment="Stretch"/>
</Grid>
</ControlTemplate>
<!--基础类型--> <!--基础类型-->
<Style x:Key="designerItemStyle" <Style x:Key="designerItemStyle"
TargetType="{x:Type ContentPresenter}"> TargetType="{x:Type ContentPresenter}">
@@ -773,6 +803,92 @@
</Setter.Value> </Setter.Value>
</Setter> </Setter>
</Style> </Style>
<!--自带的block基础类型-->
<Style x:Key="blockItemStyle"
TargetType="{x:Type ContentPresenter}">
<Setter Property="Canvas.Left"
Value="{Binding Left}" />
<Setter Property="Canvas.Top"
Value="{Binding Top}" />
<Setter Property="Canvas.ZIndex"
Value="{Binding ZIndex}" />
<Setter Property="dd:SelectionProps.EnabledForSelection"
Value="{Binding EnabledForSelection}" />
<Setter Property="Visibility"
Value="{Binding Visible,Converter={StaticResource BooleanToVisibilityConverter}}"/>
<Setter Property="Width"
Value="{Binding ItemWidth}" />
<Setter Property="Height"
Value="{Binding ItemHeight}" />
<Setter Property="MinWidth"
Value="{Binding MinItemWidth}" />
<Setter Property="MinHeight"
Value="{Binding MinItemHeight}" />
<Setter Property="SnapsToDevicePixels"
Value="True" />
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Grid x:Name="selectedGrid" IsHitTestVisible="{Binding IsHitTestVisible}" >
<Grid.ContextMenu>
<ContextMenu ItemsSource="{Binding MenuOptions}" Visibility="{Binding ShowMenuOptions,Converter={StaticResource BooleanToVisibilityConverter}}">
<ContextMenu.ItemContainerStyle>
<Style TargetType="MenuItem">
<Setter Property="MenuItem.Header" Value="{Binding Text}" />
<Setter Property="MenuItem.ItemsSource" Value="{Binding Children}" />
<Setter Property="MenuItem.Command" Value="{Binding Command}" />
<Setter Property="MenuItem.Icon" Value="{Binding Icon}" />
<Setter Property="CommandParameter" Value="{Binding CommandParameter}" />
<Setter Property="MenuItem.IsCheckable" Value="{Binding IsCheckable}" />
<Setter Property="MenuItem.IsChecked" Value="{Binding IsChecked}" />
</Style>
</ContextMenu.ItemContainerStyle>
</ContextMenu>
</Grid.ContextMenu>
<!-- PART_DragThumb -->
<c:DragThumb x:Name="PART_DragThumb"
Cursor="SizeAll" >
<c:DragThumb.InputBindings>
<MouseBinding MouseAction="LeftDoubleClick" Command="{Binding EditCommand}" CommandParameter="{Binding }" />
</c:DragThumb.InputBindings>
</c:DragThumb>
<Grid RenderTransformOrigin="0.5,0.5" >
<!-- PART_ContentPresenter -->
<ContentPresenter x:Name="PART_ContentPresenter"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Content="{TemplateBinding Content}" />
<TextBlock x:Name="PART_Text" Text="{Binding Text}" IsHitTestVisible="False"/>
<!-- PART_ConnectorDecorator -->
<Control x:Name="PART_ConnectorDecorator" Template="{StaticResource BlockConnectorDecoratorTemplate}"/>
</Grid>
</Grid>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Connectors.Count}" Value="0">
<Setter TargetName="PART_ConnectorDecorator" Property="Visibility" Value="Collapsed" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</Setter.Value>
</Setter>
<Setter Property="Effect">
<Setter.Value>
<DropShadowEffect BlurRadius="10" Color="{Binding ColorViewModel.ShadowColor}"/>
</Setter.Value>
</Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding ColorViewModel.ShadowColor}" Value="Transparent">
<Setter Property="Effect" Value="{x:Null}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ResourceDictionary> </ResourceDictionary>
</UserControl.Resources> </UserControl.Resources>
<Grid> <Grid>

View File

@@ -738,7 +738,7 @@ namespace AIStudio.Wpf.DiagramDesigner
if (this.Root is IDiagramViewModel) if (this.Root is IDiagramViewModel)
{ {
var diagramVM = this.Root as IDiagramViewModel; var diagramVM = this.Root as IDiagramViewModel;
diagramVM.RemoveItemCommand.Execute(this); diagramVM.DeleteCommand.Execute(this);
} }
} }

View File

@@ -0,0 +1,47 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media;
using AIStudio.Wpf.DiagramDesigner.Models;
namespace AIStudio.Wpf.DiagramDesigner
{
public class BlockConnectorInfo : FullyCreatedConnectorInfo
{
public BlockConnectorInfo(DesignerItemViewModelBase dataItem, ConnectorOrientation orientation) : this(null, dataItem, orientation)
{
}
public BlockConnectorInfo(IDiagramViewModel root, DesignerItemViewModelBase dataItem, ConnectorOrientation orientation) : base(root, dataItem, orientation)
{
if (Orientation == ConnectorOrientation.Left || Orientation == ConnectorOrientation.Right)
{
ConnectorWidth = 4;
ConnectorHeight = double.NaN;
}
else if (Orientation == ConnectorOrientation.Top || Orientation == ConnectorOrientation.Bottom)
{
ConnectorWidth = double.NaN;
ConnectorHeight = 4;
}
}
public BlockConnectorInfo(IDiagramViewModel root, DesignerItemViewModelBase dataItem, SerializableItem serializableItem, string serializableType) : base(root, dataItem, serializableItem, serializableType)
{
}
public BlockConnectorInfo(IDiagramViewModel root, DesignerItemViewModelBase dataItem, SelectableItemBase designer) : base(root, dataItem, designer)
{
}
protected override void InitNew()
{
base.InitNew();
ColorViewModel.LineColor.Color = Colors.Transparent;
ColorViewModel.FillColor.Color = Colors.Transparent;
}
}
}

View File

@@ -78,7 +78,7 @@ namespace AIStudio.Wpf.DiagramDesigner
{ {
get get
{ {
return connectors?.FirstOrDefault(); return Connectors?.FirstOrDefault();
} }
} }
@@ -86,7 +86,7 @@ namespace AIStudio.Wpf.DiagramDesigner
{ {
get get
{ {
return connectors?.FirstOrDefault(p => p.Orientation == ConnectorOrientation.Top); return Connectors?.FirstOrDefault(p => p.Orientation == ConnectorOrientation.Top);
} }
} }
@@ -94,7 +94,7 @@ namespace AIStudio.Wpf.DiagramDesigner
{ {
get get
{ {
return connectors?.FirstOrDefault(p => p.Orientation == ConnectorOrientation.Bottom); return Connectors?.FirstOrDefault(p => p.Orientation == ConnectorOrientation.Bottom);
} }
} }
@@ -102,7 +102,7 @@ namespace AIStudio.Wpf.DiagramDesigner
{ {
get get
{ {
return connectors?.FirstOrDefault(p => p.Orientation == ConnectorOrientation.Left); return Connectors?.FirstOrDefault(p => p.Orientation == ConnectorOrientation.Left);
} }
} }
@@ -110,7 +110,7 @@ namespace AIStudio.Wpf.DiagramDesigner
{ {
get get
{ {
return connectors?.FirstOrDefault(p => p.Orientation == ConnectorOrientation.Right); return Connectors?.FirstOrDefault(p => p.Orientation == ConnectorOrientation.Right);
} }
} }
@@ -118,7 +118,7 @@ namespace AIStudio.Wpf.DiagramDesigner
{ {
get get
{ {
return connectors?.FirstOrDefault(p => p.Orientation == ConnectorOrientation.TopLeft); return Connectors?.FirstOrDefault(p => p.Orientation == ConnectorOrientation.TopLeft);
} }
} }
@@ -126,7 +126,7 @@ namespace AIStudio.Wpf.DiagramDesigner
{ {
get get
{ {
return connectors?.FirstOrDefault(p => p.Orientation == ConnectorOrientation.TopRight); return Connectors?.FirstOrDefault(p => p.Orientation == ConnectorOrientation.TopRight);
} }
} }
@@ -134,7 +134,7 @@ namespace AIStudio.Wpf.DiagramDesigner
{ {
get get
{ {
return connectors?.FirstOrDefault(p => p.Orientation == ConnectorOrientation.BottomLeft); return Connectors?.FirstOrDefault(p => p.Orientation == ConnectorOrientation.BottomLeft);
} }
} }
@@ -142,7 +142,7 @@ namespace AIStudio.Wpf.DiagramDesigner
{ {
get get
{ {
return connectors?.FirstOrDefault(p => p.Orientation == ConnectorOrientation.BottomRight); return Connectors?.FirstOrDefault(p => p.Orientation == ConnectorOrientation.BottomRight);
} }
} }
@@ -294,7 +294,7 @@ namespace AIStudio.Wpf.DiagramDesigner
{ {
if (SetProperty(ref _showConnectors, value)) if (SetProperty(ref _showConnectors, value))
{ {
foreach (var connector in connectors) foreach (var connector in Connectors)
{ {
connector.ShowConnectors = value; connector.ShowConnectors = value;
} }
@@ -566,7 +566,7 @@ namespace AIStudio.Wpf.DiagramDesigner
} }
protected ObservableCollection<FullyCreatedConnectorInfo> connectors = new ObservableCollection<FullyCreatedConnectorInfo>(); protected ObservableCollection<FullyCreatedConnectorInfo> connectors = new ObservableCollection<FullyCreatedConnectorInfo>();
public IEnumerable<FullyCreatedConnectorInfo> Connectors public ObservableCollection<FullyCreatedConnectorInfo> Connectors
{ {
get get
{ {
@@ -600,8 +600,8 @@ namespace AIStudio.Wpf.DiagramDesigner
{ {
return Observable return Observable
.FromEventPattern<NotifyCollectionChangedEventHandler, NotifyCollectionChangedEventArgs>( .FromEventPattern<NotifyCollectionChangedEventHandler, NotifyCollectionChangedEventArgs>(
h => this.connectors.CollectionChanged += h, h => this.Connectors.CollectionChanged += h,
h => this.connectors.CollectionChanged -= h) h => this.Connectors.CollectionChanged -= h)
.Select(x => x.EventArgs); .Select(x => x.EventArgs);
} }
} }
@@ -611,24 +611,24 @@ namespace AIStudio.Wpf.DiagramDesigner
#region #region
public void AddConnector(FullyCreatedConnectorInfo connector) public void AddConnector(FullyCreatedConnectorInfo connector)
{ {
if (!connectors.Contains(connector)) if (!Connectors.Contains(connector))
{ {
connectors.Add(connector); Connectors.Add(connector);
ConnectorMargin = 0 - connector.ConnectorWidth / 2; ConnectorMargin = 0 - connector.ConnectorWidth / 2;
} }
} }
public void RemoveConnector(FullyCreatedConnectorInfo connector) public void RemoveConnector(FullyCreatedConnectorInfo connector)
{ {
if (connectors.Contains(connector)) if (Connectors.Contains(connector))
{ {
connectors.Remove(connector); Connectors.Remove(connector);
} }
} }
public virtual void ClearConnectors() public virtual void ClearConnectors()
{ {
connectors.Clear(); Connectors.Clear();
} }
public void SetCellAlignment() public void SetCellAlignment()

View File

@@ -204,7 +204,7 @@ namespace AIStudio.Wpf.DiagramDesigner
} }
} }
private bool _isEditName; private bool _isEditName;
[Browsable(false)] [Browsable(false)]
@@ -373,24 +373,6 @@ namespace AIStudio.Wpf.DiagramDesigner
} }
} }
private ICommand _addItemCommand;
public ICommand AddItemCommand
{
get
{
return this._addItemCommand ?? (this._addItemCommand = new SimpleCommand(ExecuteEnable, ExecuteAddItemCommand));
}
}
private ICommand _removeItemCommand;
public ICommand RemoveItemCommand
{
get
{
return this._removeItemCommand ?? (this._removeItemCommand = new SimpleCommand(ExecuteEnable, ExecuteRemoveItemCommand));
}
}
private ICommand _clearSelectedItemsCommand; private ICommand _clearSelectedItemsCommand;
public ICommand ClearSelectedItemsCommand public ICommand ClearSelectedItemsCommand
{ {
@@ -544,6 +526,24 @@ namespace AIStudio.Wpf.DiagramDesigner
} }
} }
private ICommand _addCommand;
public ICommand AddCommand
{
get
{
return this._addCommand ?? (this._addCommand = new SimpleCommand(ExecuteEnable, ExecuteAddCommand));
}
}
private ICommand _deleteCommand;
public virtual ICommand DeleteCommand
{
get
{
return this._deleteCommand ?? (this._deleteCommand = new SimpleCommand(ExecuteEnable, ExecuteDeleteCommand));
}
}
private ICommand _copyCommand; private ICommand _copyCommand;
public ICommand CopyCommand public ICommand CopyCommand
{ {
@@ -571,15 +571,6 @@ namespace AIStudio.Wpf.DiagramDesigner
} }
} }
private ICommand _deleteCommand;
public virtual ICommand DeleteCommand
{
get
{
return this._deleteCommand ?? (this._deleteCommand = new SimpleCommand(ExecuteEnable, ExecuteDeleteCommand));
}
}
private ICommand _leftMoveCommand; private ICommand _leftMoveCommand;
public ICommand LeftMoveCommand public ICommand LeftMoveCommand
{ {
@@ -1004,143 +995,13 @@ namespace AIStudio.Wpf.DiagramDesigner
var items = this.Items.ToList(); var items = this.Items.ToList();
DoCommandManager.DoNewCommand(this.ToString(), DoCommandManager.DoNewCommand(this.ToString(),
() => { () => {
this.Items.Clear(); Delete(items);
}, },
() => { () => {
foreach (var item in items) Add(items);
{
Add(item);
}
}); });
} }
private void ExecuteAddItemCommand(object parameter)
{
List<SelectableDesignerItemViewModelBase> newitems = new List<SelectableDesignerItemViewModelBase>();
if (parameter is SelectableDesignerItemViewModelBase ite)
{
newitems.Add(ite);
}
else if (parameter is IEnumerable<SelectableDesignerItemViewModelBase> items)
{
newitems.AddRange(items);
}
DoCommandManager.DoNewCommand(this.ToString(),
() => {
ClearSelectedItems();
Add(newitems, true);
},
() => {
foreach (var item in newitems)
{
Items.Remove(item);
}
});
}
public bool AddVerify(SelectableDesignerItemViewModelBase item)
{
if (item.Verify() == false)
return false;
return true;
}
//使用程序添加对象比如Demo初始化
public void Add(object parameter, bool? isSelected = false)
{
if (parameter is SelectableDesignerItemViewModelBase ite)
{
if (AddVerify(ite) != true) return;
Add(ite, isSelected);
}
else if (parameter is IEnumerable<SelectableDesignerItemViewModelBase> items)
{
if (items.Select(p => AddVerify(p)).Any() != true) return;
foreach (var item in items)
{
Add(item, isSelected);
}
}
}
private void Add(SelectableDesignerItemViewModelBase item, bool? isSelected = true)
{
item.Root = this;
item.ZIndex = Items.Any() ? Items.Max(p => p.ZIndex) + 1 : 0;
if (item.Id == Guid.Empty)
{
item.Id = Guid.NewGuid();
}
var logical = item as LogicalGateItemViewModelBase;
if (logical != null)
{
logical.OrderNumber = Items.OfType<LogicalGateItemViewModelBase>().Count() + 1;
}
var designerItemViewModelBase = item as DesignerItemViewModelBase;
if (designerItemViewModelBase != null)
{
designerItemViewModelBase.SetCellAlignment();
}
Items.Add(item);
if (isSelected != null)
{
item.IsSelected = isSelected.Value;
}
}
public void Remove(object parameter)
{
if (parameter is SelectableDesignerItemViewModelBase ite)
{
ite.IsSelected = false;
ite.Dispose();
Items.Remove(ite);
}
else if (parameter is IEnumerable<SelectableDesignerItemViewModelBase> items)
{
foreach (var item in items)
{
item.IsSelected = false;
item.Dispose();
Items.Remove(item);
}
}
}
private void ExecuteRemoveItemCommand(object parameter)
{
List<SelectableDesignerItemViewModelBase> olditems = new List<SelectableDesignerItemViewModelBase>();
if (parameter is SelectableDesignerItemViewModelBase node)
{
olditems.Add(node);
}
else if (parameter is IEnumerable<SelectableDesignerItemViewModelBase> para)
{
olditems.AddRange(para);
}
else
{
olditems.AddRange(SelectedItems);
}
if (olditems.Any())
{
DoCommandManager.DoNewCommand(this.ToString(),
() => {
Remove(olditems);
},
() => {
Add(olditems);
});
}
}
private void ExecuteClearSelectedItemsCommand(object parameter) private void ExecuteClearSelectedItemsCommand(object parameter)
{ {
List<SelectableDesignerItemViewModelBase> selectedItems = new List<SelectableDesignerItemViewModelBase>(); List<SelectableDesignerItemViewModelBase> selectedItems = new List<SelectableDesignerItemViewModelBase>();
@@ -1187,7 +1048,7 @@ namespace AIStudio.Wpf.DiagramDesigner
public virtual void ExecuteNextCommand(object parameter) public virtual void ExecuteNextCommand(object parameter)
{ {
} }
private void ExecuteSelectAllCommand(object parameter) private void ExecuteSelectAllCommand(object parameter)
@@ -1284,7 +1145,84 @@ namespace AIStudio.Wpf.DiagramDesigner
} }
#endregion #endregion
#region , #region , ,
private void ExecuteAddCommand(object parameter)
{
List<SelectableDesignerItemViewModelBase> newitems = new List<SelectableDesignerItemViewModelBase>();
if (parameter is SelectableDesignerItemViewModelBase ite)
{
newitems.Add(ite);
}
else if (parameter is IEnumerable<SelectableDesignerItemViewModelBase> items)
{
newitems.AddRange(items);
}
DoCommandManager.DoNewCommand(this.ToString(),
() => {
ClearSelectedItems();
Add(newitems, true);
},
() => {
Delete(newitems);
});
}
public bool AddVerify(SelectableDesignerItemViewModelBase item)
{
if (item.Verify() == false)
return false;
return true;
}
//使用程序添加对象比如Demo初始化
public void Add(object parameter, bool? isSelected = false)
{
if (parameter is SelectableDesignerItemViewModelBase ite)
{
if (AddVerify(ite) != true) return;
Add(ite, isSelected);
}
else if (parameter is IEnumerable<SelectableDesignerItemViewModelBase> items)
{
if (items.Select(p => AddVerify(p)).Any() != true) return;
foreach (var item in items)
{
Add(item, isSelected);
}
}
}
private void Add(SelectableDesignerItemViewModelBase item, bool? isSelected = true)
{
item.Root = this;
item.ZIndex = Items.Any() ? Items.Max(p => p.ZIndex) + 1 : 0;
if (item.Id == Guid.Empty)
{
item.Id = Guid.NewGuid();
}
var logical = item as LogicalGateItemViewModelBase;
if (logical != null)
{
logical.OrderNumber = Items.OfType<LogicalGateItemViewModelBase>().Count() + 1;
}
var designerItemViewModelBase = item as DesignerItemViewModelBase;
if (designerItemViewModelBase != null)
{
designerItemViewModelBase.SetCellAlignment();
}
Items.Add(item);
if (isSelected != null)
{
item.IsSelected = isSelected.Value;
}
}
private void ExecuteCopyCommand(object parameter) private void ExecuteCopyCommand(object parameter)
{ {
Copy(parameter); Copy(parameter);
@@ -1436,10 +1374,7 @@ namespace AIStudio.Wpf.DiagramDesigner
FixOtherInfo(items); FixOtherInfo(items);
}, },
() => { () => {
foreach (var item in items) Delete(items);
{
Items.Remove(item);
}
}); });
} }
} }
@@ -1484,16 +1419,10 @@ namespace AIStudio.Wpf.DiagramDesigner
{ {
DoCommandManager.DoNewCommand(this.ToString(), DoCommandManager.DoNewCommand(this.ToString(),
() => { () => {
foreach (var item in items) Delete(items);
{
Items.Remove(item);
}
}, },
() => { () => {
foreach (var item in items) Add(items);
{
Items.Add(item);
}
}); });
} }
} }
@@ -1508,21 +1437,20 @@ namespace AIStudio.Wpf.DiagramDesigner
{ {
DoCommandManager.DoNewCommand(this.ToString(), DoCommandManager.DoNewCommand(this.ToString(),
() => { () => {
foreach (var item in items) Delete(items);
{
Items.Remove(item);
}
}, },
() => { () => {
foreach (var item in items) Add(items);
{
Items.Add(item);
}
}); });
} }
} }
protected virtual List<SelectableDesignerItemViewModelBase> Delete(object parameter, bool delete = true) public void Delete(object parameter)
{
Delete(parameter, true, true);
}
protected virtual List<SelectableDesignerItemViewModelBase> Delete(object parameter, bool delete = true, bool direct = false)
{ {
List<SelectableDesignerItemViewModelBase> itemsToRemove = new List<SelectableDesignerItemViewModelBase>(); List<SelectableDesignerItemViewModelBase> itemsToRemove = new List<SelectableDesignerItemViewModelBase>();
if (parameter is SelectableDesignerItemViewModelBase node) if (parameter is SelectableDesignerItemViewModelBase node)
@@ -1538,22 +1466,25 @@ namespace AIStudio.Wpf.DiagramDesigner
itemsToRemove.AddRange(SelectedItems); itemsToRemove.AddRange(SelectedItems);
} }
List<SelectableDesignerItemViewModelBase> connectionsToAlsoRemove = new List<SelectableDesignerItemViewModelBase>(); if (direct == false)
foreach (var connector in Items.OfType<ConnectionViewModel>())
{ {
if (ItemsToDeleteHasConnector(itemsToRemove, connector.SourceConnectorInfo)) List<SelectableDesignerItemViewModelBase> connectionsToAlsoRemove = new List<SelectableDesignerItemViewModelBase>();
{
connectionsToAlsoRemove.Add(connector);
}
if (ItemsToDeleteHasConnector(itemsToRemove, connector.SinkConnectorInfo)) foreach (var connector in Items.OfType<ConnectionViewModel>())
{ {
connectionsToAlsoRemove.Add(connector); if (ItemsToDeleteHasConnector(itemsToRemove, connector.SourceConnectorInfo))
} {
connectionsToAlsoRemove.Add(connector);
}
if (ItemsToDeleteHasConnector(itemsToRemove, connector.SinkConnectorInfo))
{
connectionsToAlsoRemove.Add(connector);
}
}
itemsToRemove.AddRange(connectionsToAlsoRemove);
} }
itemsToRemove.AddRange(connectionsToAlsoRemove);
if (itemsToRemove.Any()) if (itemsToRemove.Any())
{ {
@@ -1561,6 +1492,7 @@ namespace AIStudio.Wpf.DiagramDesigner
{ {
foreach (var item in itemsToRemove) foreach (var item in itemsToRemove)
{ {
item.Dispose();
Items.Remove(item); Items.Remove(item);
} }
} }
@@ -2501,7 +2433,7 @@ namespace AIStudio.Wpf.DiagramDesigner
groupItem.AddToSelection(true, true); groupItem.AddToSelection(true, true);
}, },
() => { () => {
Remove(groupItem); Delete(groupItem);
foreach (DesignerItemViewModelBase item in items) foreach (DesignerItemViewModelBase item in items)
{ {
item.IsSelected = true; item.IsSelected = true;
@@ -2533,10 +2465,7 @@ namespace AIStudio.Wpf.DiagramDesigner
DoCommandManager.DoNewCommand(this.ToString(), DoCommandManager.DoNewCommand(this.ToString(),
() => { () => {
foreach (DesignerItemViewModelBase groupRoot in groups) Delete(groups);
{
Remove(groupRoot);
}
foreach (var item in items) foreach (var item in items)
{ {
item.Key.ParentId = Guid.Empty; item.Key.ParentId = Guid.Empty;
@@ -2544,10 +2473,7 @@ namespace AIStudio.Wpf.DiagramDesigner
UpdateZIndex(); UpdateZIndex();
}, },
() => { () => {
foreach (DesignerItemViewModelBase groupRoot in groups) Add(groups);
{
Add(groupRoot);
}
foreach (var item in items) foreach (var item in items)
{ {
item.Key.ParentId = item.Value.Item1; item.Key.ParentId = item.Value.Item1;
@@ -3105,13 +3031,101 @@ namespace AIStudio.Wpf.DiagramDesigner
port.DisableAttachTo = true; port.DisableAttachTo = true;
return null; return null;
} }
} }
} }
return null; return null;
} }
/// <summary>
/// type=0最近且没有依附=1
/// </summary>
/// <param name="blockDesignerItemViewModel"></param>
/// <param name="type"></param>
/// <returns></returns>
public Tuple<FullyCreatedConnectorInfo, FullyCreatedConnectorInfo> FindNearPortToAttachTo(BlockDesignerItemViewModel blockDesignerItemViewModel, bool isExist)
{
if (blockDesignerItemViewModel == null)
return new Tuple<FullyCreatedConnectorInfo, FullyCreatedConnectorInfo>(null, null);
List<BlockDesignerItemViewModel> items;
if (isExist == false)
{
items = Items.OfType<BlockDesignerItemViewModel>().
Where(p => p != blockDesignerItemViewModel && p != blockDesignerItemViewModel.Parent && p != blockDesignerItemViewModel.Next)
.ToList();
}
else
{
items = Items.OfType<BlockDesignerItemViewModel>().
Where(p => p != blockDesignerItemViewModel)
.ToList();
}
FullyCreatedConnectorInfo parent = null;
FullyCreatedConnectorInfo next = null;
foreach (var port in items.SelectMany(n => n.Connectors))
{
foreach (var port2 in blockDesignerItemViewModel.Connectors)
{
//parent
if (parent == null)
{
if ((port.Orientation == ConnectorOrientation.Right && port2.Orientation == ConnectorOrientation.Left)
|| (port.Orientation == ConnectorOrientation.Bottom && port2.Orientation == ConnectorOrientation.Top))
{
if (port.Position.DistanceTo(port2.Position) < DiagramOption.SnappingOption.SnappingRadius)
{
port.DataItem.ShowConnectors = true;
if (port2.CanAttachTo(port) == true)
{
port.BeAttachTo = true;
parent = port;
continue;
}
else
{
port.DisableAttachTo = true;
}
}
}
}
//next
if (next == null)
{
if ((port.Orientation == ConnectorOrientation.Left && port2.Orientation == ConnectorOrientation.Right)
|| (port.Orientation == ConnectorOrientation.Top && port2.Orientation == ConnectorOrientation.Bottom))
{
if (port.Position.DistanceTo(port2.Position) < DiagramOption.SnappingOption.SnappingRadius)
{
port.DataItem.ShowConnectors = true;
if (port2.CanAttachTo(port) == true)
{
port.BeAttachTo = true;
next = port;
continue;
}
else
{
port.DisableAttachTo = true;
}
}
}
}
}
}
return new Tuple<FullyCreatedConnectorInfo, FullyCreatedConnectorInfo>(parent, next);
}
public void ClearNearPort() public void ClearNearPort()
{ {
Items.OfType<DesignerItemViewModelBase>().ToList().SelectMany(n => n.Connectors).Where(p => p.BeAttachTo == true || p.DisableAttachTo == true).ToList() Items.OfType<DesignerItemViewModelBase>().ToList().SelectMany(n => n.Connectors).Where(p => p.BeAttachTo == true || p.DisableAttachTo == true).ToList()

View File

@@ -0,0 +1,68 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using AIStudio.Wpf.DiagramDesigner.Models;
namespace AIStudio.Wpf.DiagramDesigner
{
public class BlockDesignerItemViewModel : DesignerItemViewModelBase
{
public BlockDesignerItemViewModel()
{
}
public BlockDesignerItemViewModel(IDiagramViewModel root) : base(root)
{
}
public BlockDesignerItemViewModel(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer)
{
}
public BlockDesignerItemViewModel(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType)
{
}
protected override void InitNew()
{
AddConnector(new BlockConnectorInfo(this.Root, this, ConnectorOrientation.Top));
AddConnector(new BlockConnectorInfo(this.Root, this, ConnectorOrientation.Bottom));
}
public BlockDesignerItemViewModel Next
{
get;set;
}
public void AddNext(BlockDesignerItemViewModel next)
{
next.Left = this.Left;
next.Top = this.Top + this.ItemHeight;
next.ParentId = this.Id;
next.Parent = this;
this.Next = next;
if (next.Next != null)
{
next.AddNext(next.Next);
}
}
public override void AddToSelection(bool selected, bool clearother)
{
if (clearother)
{
foreach (SelectableDesignerItemViewModelBase item in Root.SelectedItems.ToList())
{
if (item != this)
{
item.RemoveFromSelection();
}
}
}
IsSelected = selected;
}
}
}

View File

@@ -49,7 +49,7 @@ namespace AIStudio.Wpf.DiagramDesigner
//propertyChangedSubscription = WhenPropertyChanged.Where(o => o.ToString() == "Left" || o.ToString() == "Top" || o.ToString() == "ItemWidth" || o.ToString() == "ItemHeight").Subscribe(ChangeImageElement); //propertyChangedSubscription = WhenPropertyChanged.Where(o => o.ToString() == "Left" || o.ToString() == "Top" || o.ToString() == "ItemWidth" || o.ToString() == "ItemHeight").Subscribe(ChangeImageElement);
//connectorsChangedSubscription = WhenConnectorsChanged.Subscribe(OnConnectorsChanged); //connectorsChangedSubscription = WhenConnectorsChanged.Subscribe(OnConnectorsChanged);
AddItemCommand = new SimpleCommand(Command_Enable, ExecuteAddItemCommand); AddCommand = new SimpleCommand(Command_Enable, ExecuteAddItemCommand);
ImageSwitchCommand = new SimpleCommand(Command_Enable, ExecuteImageSwitchCommand); ImageSwitchCommand = new SimpleCommand(Command_Enable, ExecuteImageSwitchCommand);
BuildMenuOptions(); BuildMenuOptions();
} }
@@ -82,7 +82,7 @@ namespace AIStudio.Wpf.DiagramDesigner
} }
} }
public ICommand AddItemCommand public ICommand AddCommand
{ {
get; private set; get; private set;
} }
@@ -143,7 +143,7 @@ namespace AIStudio.Wpf.DiagramDesigner
// } // }
// } // }
// } // }
// else if (args.Action == NotifyCollectionChangedAction.Remove) // else if (args.Action == NotifyCollectionChangedAction.Delete)
// { // {
// if (args.OldItems.Count > 0) // if (args.OldItems.Count > 0)
// { // {

View File

@@ -72,7 +72,9 @@ namespace AIStudio.Wpf.DiagramDesigner
protected override void InitNew() protected override void InitNew()
{ {
base.InitNew(); ExecuteAddInput(null);
ExecuteAddInput(null);
ExecuteAddOutput(null);
} }
private void BuildMenuOptions() private void BuildMenuOptions()
@@ -182,7 +184,7 @@ namespace AIStudio.Wpf.DiagramDesigner
public override void ClearConnectors() public override void ClearConnectors()
{ {
connectors.Clear(); Connectors.Clear();
Input.Clear(); Input.Clear();
Output.Clear(); Output.Clear();
} }

View File

@@ -63,7 +63,7 @@ namespace AIStudio.Wpf.DiagramDesigner
protected override void ClearText() protected override void ClearText()
{ {
Root.RemoveItemCommand.Execute(this); Root.DeleteCommand.Execute(this);
} }
} }
} }

View File

@@ -114,7 +114,7 @@ namespace AIStudio.Wpf.DiagramDesigner
foreach (var g in deleteDrawGeometries) foreach (var g in deleteDrawGeometries)
{ {
this.Root.Remove(g); this.Root.Delete(g);
} }
return empty; return empty;

View File

@@ -104,7 +104,7 @@ namespace AIStudio.Wpf.DiagramDesigner
foreach (var g in deleteDrawGeometries) foreach (var g in deleteDrawGeometries)
{ {
this.Root.Remove(g); this.Root.Delete(g);
} }
return empty; return empty;

View File

@@ -97,7 +97,7 @@ namespace AIStudio.Wpf.DiagramDesigner
if (e.PropertyName == nameof(IsEditing) && _previewTextDesign.IsEditing == false) if (e.PropertyName == nameof(IsEditing) && _previewTextDesign.IsEditing == false)
{ {
_previewTextDesign.PropertyChanged -= _previewTextDesign_PropertyChanged; _previewTextDesign.PropertyChanged -= _previewTextDesign_PropertyChanged;
Root?.Remove(_previewTextDesign); Root?.Delete(_previewTextDesign);
Text = _previewTextDesign?.Text; Text = _previewTextDesign?.Text;
if (!string.IsNullOrEmpty(Text)) if (!string.IsNullOrEmpty(Text))
@@ -118,7 +118,7 @@ namespace AIStudio.Wpf.DiagramDesigner
this.ItemHeight = _previewTextDesign.ItemHeight; this.ItemHeight = _previewTextDesign.ItemHeight;
this.Left = _previewTextDesign.Left + 2 + Geometry.Bounds.Left; this.Left = _previewTextDesign.Left + 2 + Geometry.Bounds.Left;
this.Top = _previewTextDesign.Top + 2 + Geometry.Bounds.Top; this.Top = _previewTextDesign.Top + 2 + Geometry.Bounds.Top;
this.Root?.AddItemCommand.Execute(this); this.Root?.AddCommand.Execute(this);
IsLoaded = true; IsLoaded = true;
} }
} }

View File

@@ -36,14 +36,6 @@ namespace AIStudio.Wpf.DiagramDesigner
{ {
get; get;
} }
ICommand AddItemCommand
{
get;
}
ICommand RemoveItemCommand
{
get;
}
ICommand ClearSelectedItemsCommand ICommand ClearSelectedItemsCommand
{ {
get; get;
@@ -113,6 +105,14 @@ namespace AIStudio.Wpf.DiagramDesigner
{ {
get; get;
} }
ICommand AddCommand
{
get;
}
ICommand DeleteCommand
{
get;
}
ICommand CopyCommand ICommand CopyCommand
{ {
get; get;
@@ -125,10 +125,6 @@ namespace AIStudio.Wpf.DiagramDesigner
{ {
get; get;
} }
ICommand DeleteCommand
{
get;
}
ICommand LeftMoveCommand ICommand LeftMoveCommand
{ {
get; get;
@@ -340,7 +336,7 @@ namespace AIStudio.Wpf.DiagramDesigner
void Add(object parameter, bool? isSelected = false); void Add(object parameter, bool? isSelected = false);
void Remove(object parameter); void Delete(object parameter);
void ClearSelectedItems(); void ClearSelectedItems();
@@ -366,6 +362,7 @@ namespace AIStudio.Wpf.DiagramDesigner
#region #region
FullyCreatedConnectorInfo FindNearPortToAttachTo(ConnectionViewModel partialConnection, ConnectorVertexType connectorVertexType); FullyCreatedConnectorInfo FindNearPortToAttachTo(ConnectionViewModel partialConnection, ConnectorVertexType connectorVertexType);
FullyCreatedConnectorInfo FindNearPortToAttachTo(ConnectionViewModel partialConnection); FullyCreatedConnectorInfo FindNearPortToAttachTo(ConnectionViewModel partialConnection);
Tuple<FullyCreatedConnectorInfo, FullyCreatedConnectorInfo> FindNearPortToAttachTo(BlockDesignerItemViewModel blockDesignerItemViewModel, bool isExist);
void ClearNearPort(); void ClearNearPort();
#endregion #endregion
event PropertyChangedEventHandler PropertyChanged; event PropertyChangedEventHandler PropertyChanged;

View File

@@ -101,16 +101,6 @@ namespace AIStudio.Wpf.Logical.ViewModels
} }
protected override void InitNew()
{
base.InitNew();
ClearConnectors();
ExecuteAddInput(null);
ExecuteAddInput(null);
ExecuteAddOutput(null);
}
public override bool EnableAddInput public override bool EnableAddInput
{ {
get; get;

View File

@@ -471,7 +471,7 @@ namespace AIStudio.Wpf.Mind.ViewModels
() => { () => {
if (rootitem != null) if (rootitem != null)
{ {
Remove(rootitem); Delete(rootitem);
} }
}); });
@@ -785,7 +785,7 @@ namespace AIStudio.Wpf.Mind.ViewModels
items.Select(p => p.RootNode).Distinct().ToList().ForEach(p => p.UpdatedLayout()); items.Select(p => p.RootNode).Distinct().ToList().ForEach(p => p.UpdatedLayout());
} }
protected override List<SelectableDesignerItemViewModelBase> Delete(object parameter, bool delete = true) protected override List<SelectableDesignerItemViewModelBase> Delete(object parameter, bool delete = true, bool direct = true)
{ {
List<MindNode> items = new List<MindNode>(); List<MindNode> items = new List<MindNode>();
List<SelectableDesignerItemViewModelBase> others = new List<SelectableDesignerItemViewModelBase>(); List<SelectableDesignerItemViewModelBase> others = new List<SelectableDesignerItemViewModelBase>();
@@ -815,39 +815,42 @@ namespace AIStudio.Wpf.Mind.ViewModels
//去重 //去重
items = items.Distinct().ToList(); items = items.Distinct().ToList();
Dictionary<MindNode, Tuple<int, MindNode>> indexs = items.ToDictionary(p => p, p => new Tuple<int, MindNode>(p.ParentNode != null ? p.ParentNode.Children.IndexOf(p) : 0, p.ParentNode)); if (delete)
DoCommandManager.DoNewCommand(this.ToString(), {
() => { Dictionary<MindNode, Tuple<int, MindNode>> indexs = items.ToDictionary(p => p, p => new Tuple<int, MindNode>(p.ParentNode != null ? p.ParentNode.Children.IndexOf(p) : 0, p.ParentNode));
DoCommandManager.DoNewCommand(this.ToString(),
() => {
foreach (var item in items.ToList()) foreach (var item in items.ToList())
{
item.RemoveFrom();
}
if (others.Any())
{
base.Delete(others);
}
items.Select(p => p.RootNode).Distinct().ToList().ForEach(p => p.UpdatedLayout());
},
() => {
if (others.Any())
{
base.Add(others);
}
foreach (var item in items)
{
item.AddTo(indexs[item].Item2, indexs[item].Item1, false);
if (item.ParentId == Guid.Empty)
{ {
item.Offset = new PointBase(); item.RemoveFrom();
} }
}
items.Select(p => p.RootNode).Distinct().ToList().ForEach(p => p.UpdatedLayout()); if (others.Any())
}); {
base.Delete(others);
}
items.Select(p => p.RootNode).Distinct().ToList().ForEach(p => p.UpdatedLayout());
},
() => {
if (others.Any())
{
base.Add(others);
}
foreach (var item in items)
{
item.AddTo(indexs[item].Item2, indexs[item].Item1, false);
if (item.ParentId == Guid.Empty)
{
item.Offset = new PointBase();
}
}
items.Select(p => p.RootNode).Distinct().ToList().ForEach(p => p.UpdatedLayout());
});
}
return items.OfType<SelectableDesignerItemViewModelBase>().ToList(); return items.OfType<SelectableDesignerItemViewModelBase>().ToList();
} }
else else

View File

@@ -565,8 +565,8 @@ namespace AIStudio.Wpf.Mind.ViewModels
} }
var connectors = Root?.Items.OfType<ConnectionViewModel>().Where(p => p.SinkConnectorInfoFully?.DataItem == this).ToList(); var connectors = Root?.Items.OfType<ConnectionViewModel>().Where(p => p.SinkConnectorInfoFully?.DataItem == this).ToList();
Root?.Remove(this); Root?.Delete(this);
Root?.Remove(connectors); Root?.Delete(connectors);
} }
#endregion #endregion
@@ -745,12 +745,11 @@ namespace AIStudio.Wpf.Mind.ViewModels
{ {
if (item != this) if (item != this)
{ {
item.IsSelected = false; item.RemoveFromSelection();
} }
} }
} }
Root.SelectedItems.Clear();
IsSelected = selected; IsSelected = selected;
} }