diff --git a/AIStudio.Wpf.DiagramDesigner/AIStudio.Wpf.DiagramDesigner.csproj b/AIStudio.Wpf.DiagramDesigner/AIStudio.Wpf.DiagramDesigner.csproj index 5139c43..0b20917 100644 --- a/AIStudio.Wpf.DiagramDesigner/AIStudio.Wpf.DiagramDesigner.csproj +++ b/AIStudio.Wpf.DiagramDesigner/AIStudio.Wpf.DiagramDesigner.csproj @@ -12,6 +12,10 @@ 一个Wpf的Diagram控件基础库 + + + + @@ -19,6 +23,7 @@ True + diff --git a/AIStudio.Wpf.DiagramDesigner/Enums/RouterMode.cs b/AIStudio.Wpf.DiagramDesigner/Enums/RouterMode.cs index 472afab..74926f9 100644 --- a/AIStudio.Wpf.DiagramDesigner/Enums/RouterMode.cs +++ b/AIStudio.Wpf.DiagramDesigner/Enums/RouterMode.cs @@ -7,6 +7,7 @@ namespace AIStudio.Wpf.DiagramDesigner public enum RouterMode { RouterNormal, - RouterOrthogonal + RouterOrthogonal, + RouterFishBone } } diff --git a/AIStudio.Wpf.DiagramDesigner/PathGenerators/PathGenerators.FishBone.cs b/AIStudio.Wpf.DiagramDesigner/PathGenerators/PathGenerators.FishBone.cs new file mode 100644 index 0000000..7027437 --- /dev/null +++ b/AIStudio.Wpf.DiagramDesigner/PathGenerators/PathGenerators.FishBone.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Text; +using AIStudio.Wpf.DiagramDesigner.Geometrys; + +namespace AIStudio.Wpf.DiagramDesigner +{ + public static partial class PathGenerators + { + public static PathGeneratorResult Straight(IDiagramViewModel _, ConnectionViewModel link, PointBase[] route, PointBase source, PointBase target) + { + route = ConcatRouteAndSourceAndTarget(route, source, target); + + double sourceAngle = SourceMarkerAdjustement(route, link.GetSourceMarkerWidth(), link.GetSourceMarkerHeight()); + double targetAngle = TargetMarkerAdjustement(route, link.GetSinkMarkerWidth(), link.GetSinkMarkerHeight()); + + DoShift(route, link); + + var paths = new string[route.Length - 1]; + for (var i = 0; i < route.Length - 1; i++) + { + paths[i] = FormattableString.Invariant($"M {route[i].X} {route[i].Y} L {route[i + 1].X} {route[i + 1].Y}"); + } + + return new PathGeneratorResult(paths, sourceAngle, route[0], targetAngle, route[route.Length - 1]); + } + } +} diff --git a/AIStudio.Wpf.DiagramDesigner/Routers/RouterFishBone.cs b/AIStudio.Wpf.DiagramDesigner/Routers/RouterFishBone.cs new file mode 100644 index 0000000..1c4427b --- /dev/null +++ b/AIStudio.Wpf.DiagramDesigner/Routers/RouterFishBone.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Text; +using AIStudio.Wpf.DiagramDesigner.Geometrys; + +namespace AIStudio.Wpf.DiagramDesigner +{ + public class RouterFishBone : IRouter + { + public PointBase[] Get(IDiagramViewModel _, ConnectionViewModel link) + { + return Routers.FishBone(_, link); + } + } +} diff --git a/AIStudio.Wpf.DiagramDesigner/Routers/Routers.FishBone.cs b/AIStudio.Wpf.DiagramDesigner/Routers/Routers.FishBone.cs new file mode 100644 index 0000000..c4d0aea --- /dev/null +++ b/AIStudio.Wpf.DiagramDesigner/Routers/Routers.FishBone.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using AIStudio.Wpf.DiagramDesigner.Geometrys; + +// Implementation taken from the JS version: https://gist.github.com/menendezpoo/4a8894c152383b9d7a870c24a04447e4 +// Todo: Make it more c#, Benchmark A* vs Dijkstra, Add more options +namespace AIStudio.Wpf.DiagramDesigner +{ + public static partial class Routers + { + public static PointBase[] FishBone(IDiagramViewModel _, ConnectionViewModel link) + { + if (link.IsPortless) + throw new Exception("Orthogonal router doesn't work with portless links yet"); + + if (link.IsFullConnection == false) + return Normal(_, link); + + double x2 = link.SourceConnectorInfo.MiddlePosition.X < link.SinkConnectorInfoFully.MiddlePosition.X ? + link.SinkConnectorInfoFully.MiddlePosition.X - Math.Abs(link.SourceConnectorInfo.MiddlePosition.Y - link.SinkConnectorInfoFully.MiddlePosition.Y) + : link.SinkConnectorInfoFully.MiddlePosition.X + Math.Abs(link.SourceConnectorInfo.MiddlePosition.Y - link.SinkConnectorInfoFully.MiddlePosition.Y); + double y2 = link.SourceConnectorInfo.MiddlePosition.Y; + + return new PointBase[] { new PointBase(x2, y2) }; + + } + + } + + +} diff --git a/AIStudio.Wpf.DiagramDesigner/Routers/Routers.Orthogonal.cs b/AIStudio.Wpf.DiagramDesigner/Routers/Routers.Orthogonal.cs index bd277e7..ddde2d8 100644 --- a/AIStudio.Wpf.DiagramDesigner/Routers/Routers.Orthogonal.cs +++ b/AIStudio.Wpf.DiagramDesigner/Routers/Routers.Orthogonal.cs @@ -38,6 +38,7 @@ namespace AIStudio.Wpf.DiagramDesigner { shapeMargin = 0; inflatedA = shapeA; + inflatedB = shapeB; } diff --git a/AIStudio.Wpf.DiagramDesigner/UserControls/TextControl.xaml.cs b/AIStudio.Wpf.DiagramDesigner/UserControls/TextControl.xaml.cs index 7adeae5..04157f3 100644 --- a/AIStudio.Wpf.DiagramDesigner/UserControls/TextControl.xaml.cs +++ b/AIStudio.Wpf.DiagramDesigner/UserControls/TextControl.xaml.cs @@ -32,9 +32,9 @@ namespace AIStudio.Wpf.DiagramDesigner { InitializeComponent(); - this.Loaded += TextControl_Loaded; - } - + this.Loaded += TextControl_Loaded; + this.PART_ShowText.IsVisibleChanged += PART_ShowText_IsVisibleChanged; + } private void TextControl_Loaded(object sender, RoutedEventArgs e) { @@ -56,6 +56,14 @@ namespace AIStudio.Wpf.DiagramDesigner TextControl_PropertyChanged(this.DataContext, new System.ComponentModel.PropertyChangedEventArgs("IsSelected")); } + private void PART_ShowText_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e) + { + if (this.DataContext is ISelectable selectable) + { + selectable.IsEditing = PART_ShowText.IsVisible; + } + } + private void TextControl_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) { if (e.PropertyName == "IsSelected") diff --git a/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/ConnectionViewModel.cs b/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/ConnectionViewModel.cs index d9c4800..a374eb2 100644 --- a/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/ConnectionViewModel.cs +++ b/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/ConnectionViewModel.cs @@ -686,6 +686,11 @@ namespace AIStudio.Wpf.DiagramDesigner SinkConnectorInfo = port; } + public void SetVisible(bool visible) + { + Visible = visible; + } + public double GetSourceMarkerWidth() { if (!IsFullConnection || string.IsNullOrEmpty(ShapeViewModel.SourceMarker.Path)) diff --git a/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/DiagramViewModel.cs b/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/DiagramViewModel.cs index 3071bf3..9e00235 100644 --- a/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/DiagramViewModel.cs +++ b/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/DiagramViewModel.cs @@ -3,8 +3,10 @@ using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; +using System.Data.Common; using System.Linq; using System.Reactive.Linq; +using System.Reflection.Metadata; using System.Windows; using System.Windows.Input; using System.Windows.Media; @@ -836,16 +838,44 @@ namespace AIStudio.Wpf.DiagramDesigner private bool _undoing; private void UndoExecuted(object para) { + Undo(para); + } + + private bool Undo(object para) + { + var first = SelectedItems.OfType().FirstOrDefault(); + if (first != null && first.IsEditing == true) + { + return false; + } + _undoing = true; DoCommandManager.UnDo(); _undoing = false; + + return true; } + private void RedoExecuted(object para) { + Redo(para); + } + + private bool Redo(object para) + { + var first = SelectedItems.OfType().FirstOrDefault(); + if (first != null && first.IsEditing == true) + { + return false; + } + _undoing = true; DoCommandManager.ReDo(); _undoing = false; + + return true; } + private bool Undo_Enabled(object para) { return DoCommandManager.CanUnDo; @@ -1684,6 +1714,11 @@ namespace AIStudio.Wpf.DiagramDesigner #region 复制,粘贴 private void ExecuteCopyCommand(object parameter) + { + Copy(parameter); + } + + private bool Copy(object parameter) { List selectedDesignerItems; @@ -1696,6 +1731,15 @@ namespace AIStudio.Wpf.DiagramDesigner } else { + if (SelectedItems.Count == 0) + { + return false; + } + var first = SelectedItems.OfType().FirstOrDefault(); + if (first != null && first.IsEditing == true) + { + return false; + } selectedDesignerItems = SelectedItems.OfType().ToList(); selectedConnections = SelectedItems.OfType().ToList(); } @@ -1732,16 +1776,23 @@ namespace AIStudio.Wpf.DiagramDesigner OffsetY = 10; System.Windows.Clipboard.Clear(); System.Windows.Clipboard.SetData(System.Windows.DataFormats.Serializable, json); + + return true; } private void ExecutePasteCommand(object parameter) + { + Paste(parameter); + } + + private bool Paste(object parameter) { if (System.Windows.Clipboard.ContainsData(System.Windows.DataFormats.Serializable)) { string clipboardData = System.Windows.Clipboard.GetData(System.Windows.DataFormats.Serializable) as String; if (string.IsNullOrEmpty(clipboardData)) - return; + return false; try { List items = new List(); @@ -1816,6 +1867,12 @@ namespace AIStudio.Wpf.DiagramDesigner { System.Windows.MessageBox.Show(e.StackTrace, e.Message, System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error); } + + return true; + } + else + { + return false; } } @@ -1831,13 +1888,27 @@ namespace AIStudio.Wpf.DiagramDesigner private void ExecuteCutCommand(object parameter) { - ExecutePasteCommand(null); + Cut(parameter); + } + + private bool Cut(object parameter) + { + if (Paste(null) == false) + return false; OffsetX = 0; OffsetY = 0; - ExecuteDeleteCommand(null); + if (Delete(null) == false) + return false; + + return true; } private void ExecuteDeleteCommand(object parameter) + { + Delete(parameter); + } + + private bool Delete(object parameter) { List itemsToRemove; @@ -1847,6 +1918,15 @@ namespace AIStudio.Wpf.DiagramDesigner } else { + if (SelectedItems.Count == 0) + { + return false; + } + var first = SelectedItems.OfType().FirstOrDefault(); + if (first != null && first.IsEditing == true) + { + return false; + } itemsToRemove = SelectedItems.OfType().ToList(); } @@ -1868,6 +1948,8 @@ namespace AIStudio.Wpf.DiagramDesigner itemsToRemove.AddRange(connectionsToAlsoRemove); RemoveItemCommand.Execute(itemsToRemove); + + return true; } #endregion @@ -2119,33 +2201,27 @@ namespace AIStudio.Wpf.DiagramDesigner } else if (DiagramOption.ShortcutOption.Copy(e)) { - CopyCommand.Execute(null); - return true; + return Copy(null); } else if (DiagramOption.ShortcutOption.Paste(e)) { - PasteCommand.Execute(null); - return true; + return Paste(null); } else if (DiagramOption.ShortcutOption.Cut(e)) { - CutCommand.Execute(null); - return true; + return Cut(null); } else if (DiagramOption.ShortcutOption.Undo(e)) { - UndoCommand.Execute(null); - return true; + return Undo(null); } else if (DiagramOption.ShortcutOption.Redo(e)) { - RedoCommand.Execute(null); - return true; + return Redo(null); } else if (DiagramOption.ShortcutOption.Delete(e)) { - DeleteCommand.Execute(null); - return true; + return Delete(null); } else if (DiagramOption.ShortcutOption.LeftMove(e)) { diff --git a/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/SelectableViewModelBase.cs b/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/SelectableViewModelBase.cs index 2426bed..112dc36 100644 --- a/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/SelectableViewModelBase.cs +++ b/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/SelectableViewModelBase.cs @@ -166,6 +166,24 @@ namespace AIStudio.Wpf.DiagramDesigner } } + bool IsEditing + { + get; set; + } + + private bool _isEditing = true; + public bool IsEditing + { + get + { + return _isEditing; + } + set + { + SetProperty(ref _isEditing, value); + } + } + private bool _visible = true; public bool Visible { diff --git a/AIStudio.Wpf.DiagramDesigner/ViewModels/ISelectable.cs b/AIStudio.Wpf.DiagramDesigner/ViewModels/ISelectable.cs index f6acb43..e91ead0 100644 --- a/AIStudio.Wpf.DiagramDesigner/ViewModels/ISelectable.cs +++ b/AIStudio.Wpf.DiagramDesigner/ViewModels/ISelectable.cs @@ -18,6 +18,11 @@ namespace AIStudio.Wpf.DiagramDesigner get; } + bool IsEditing + { + get; set; + } + void AddToSelection(bool selected); event PropertyChangedEventHandler PropertyChanged; diff --git a/AIStudio.Wpf.Mind/Helpers/DirectoryLayout.cs b/AIStudio.Wpf.Mind/Helpers/DirectoryLayout.cs index 6cd5768..b74f4d4 100644 --- a/AIStudio.Wpf.Mind/Helpers/DirectoryLayout.cs +++ b/AIStudio.Wpf.Mind/Helpers/DirectoryLayout.cs @@ -75,6 +75,18 @@ namespace AIStudio.Wpf.Mind.Helpers } } + public ConnectionViewModel GetConnectionViewModel(MindNode source, MindNode sink) + { + var connector = new ConnectionViewModel(source.Root, source.Connectors.FirstOrDefault(), sink.Connectors.FirstOrDefault(), DrawMode.ConnectingLineStraight, RouterMode.RouterOrthogonal); + connector.ColorViewModel.LineColor = source.ColorViewModel.LineColor; + connector.SmoothMargin = 20; + connector.SmoothAutoSlope = 0.2; + connector.ShapeViewModel.SinkMarker.PathStyle = source.ShapeViewModel.SinkMarker.PathStyle; + connector.ShapeViewModel.SinkMarker.SizeStyle = source.ShapeViewModel.SinkMarker.SizeStyle; + + return connector; + } + public void LayoutUpdated(MindNode mindNode) { if (mindNode == null) return; @@ -131,7 +143,7 @@ namespace AIStudio.Wpf.Mind.Helpers var connect = mindNode.Root?.Items.OfType().FirstOrDefault(p => p.SourceConnectorInfo?.DataItem == mindNode && p.SinkConnectorInfoFully?.DataItem == child); connect?.SetSourcePort(mindNode.FirstConnector); connect?.SetSinkPort(child.TopConnector); - connect.Visible = child.Visible; + connect?.SetVisible(child.Visible); } } } @@ -153,7 +165,7 @@ namespace AIStudio.Wpf.Mind.Helpers var connect = mindNode.Root?.Items.OfType().FirstOrDefault(p => p.SourceConnectorInfo?.DataItem == mindNode && p.SinkConnectorInfoFully?.DataItem == child); connect?.SetSourcePort(mindNode.BottomConnector); connect?.SetSinkPort(child.LeftConnector); - connect.Visible = child.Visible; + connect?.SetVisible(child.Visible); } } } diff --git a/AIStudio.Wpf.Mind/Helpers/FishBoneLayout.cs b/AIStudio.Wpf.Mind/Helpers/FishBoneLayout.cs index 2b50fce..d5bc62b 100644 --- a/AIStudio.Wpf.Mind/Helpers/FishBoneLayout.cs +++ b/AIStudio.Wpf.Mind/Helpers/FishBoneLayout.cs @@ -49,13 +49,9 @@ namespace AIStudio.Wpf.Mind.Helpers var port1 = new FullyCreatedConnectorInfo(mindNode.Root, mindNode, ConnectorOrientation.BottomLeft, true) { XRatio = 0, YRatio = 1 }; mindNode.AddConnector(port1); - var port2 = new FullyCreatedConnectorInfo(mindNode.Root, mindNode, ConnectorOrientation.Top, true) { XRatio = 0.25, YRatio = 0 }; - mindNode.AddConnector(port2); - var port3 = new FullyCreatedConnectorInfo(mindNode.Root, mindNode, ConnectorOrientation.TopLeft, true) { XRatio = 0, YRatio = 0 }; - mindNode.AddConnector(port3); - var port4 = new FullyCreatedConnectorInfo(mindNode.Root, mindNode, ConnectorOrientation.Bottom, true) { XRatio = 0.25, YRatio = 1 }; - mindNode.AddConnector(port4); + var port2 = new FullyCreatedConnectorInfo(mindNode.Root, mindNode, ConnectorOrientation.TopLeft, true) { XRatio = 0, YRatio = 0 }; + mindNode.AddConnector(port2); mindNode.IsInnerConnector = true; @@ -70,15 +66,25 @@ namespace AIStudio.Wpf.Mind.Helpers mindNode.ItemHeight = 25; mindNode.ClearConnectors(); - var port1 = new FullyCreatedConnectorInfo(mindNode.Root, mindNode, ConnectorOrientation.BottomLeft, true) { XRatio = 0, YRatio = 1 }; + var port1 = new FullyCreatedConnectorInfo(mindNode.Root, mindNode, ConnectorOrientation.Left, true) { XRatio = 0, YRatio = 0.5 }; mindNode.AddConnector(port1); - var port2 = new FullyCreatedConnectorInfo(mindNode.Root, mindNode, ConnectorOrientation.Top, true) { XRatio = 0.25, YRatio = 0 }; - mindNode.AddConnector(port2); - var port3 = new FullyCreatedConnectorInfo(mindNode.Root, mindNode, ConnectorOrientation.TopLeft, true) { XRatio = 0, YRatio = 0 }; - mindNode.AddConnector(port3); - var port4 = new FullyCreatedConnectorInfo(mindNode.Root, mindNode, ConnectorOrientation.Bottom, true) { XRatio = 0.25, YRatio = 1 }; - mindNode.AddConnector(port4); + mindNode.IsInnerConnector = true; + mindNode.ColorViewModel.LineColor.Color = Color.FromRgb(0x73, 0xa1, 0xbf); + mindNode.ShapeViewModel.SinkMarker.PathStyle = ArrowPathStyle.None; + mindNode.ShapeViewModel.SinkMarker.SizeStyle = ArrowSizeStyle.VerySmall; + mindNode.CornerRadius = new System.Windows.CornerRadius(0); + mindNode.BorderThickness = new System.Windows.Thickness(0, 0, 0, 0); + break; + } + case NodeLevel.Level4: + { + mindNode.ItemWidth = 80; + mindNode.ItemHeight = 25; + mindNode.ClearConnectors(); + + var port1 = new FullyCreatedConnectorInfo(mindNode.Root, mindNode, ConnectorOrientation.Left, true) { XRatio = 0, YRatio = 0.5 }; + mindNode.AddConnector(port1); mindNode.IsInnerConnector = true; mindNode.ColorViewModel.LineColor.Color = Color.FromRgb(0x73, 0xa1, 0xbf); @@ -93,6 +99,25 @@ namespace AIStudio.Wpf.Mind.Helpers mindNode.GetLevel1Node().LayoutUpdating = false; } + public ConnectionViewModel GetConnectionViewModel(MindNode source, MindNode sink) + { + DrawMode drawMode = DrawMode.ConnectingLineStraight; + RouterMode routerMode = RouterMode.RouterNormal; + if (source.NodeLevel == NodeLevel.Level1) + { + drawMode = DrawMode.ConnectingLineStraight; + routerMode = RouterMode.RouterFishBone; + } + + var connector = new ConnectionViewModel(source.Root, source.Connectors.FirstOrDefault(), sink.Connectors.FirstOrDefault(), drawMode, routerMode); + connector.ColorViewModel.LineColor = source.ColorViewModel.LineColor; + connector.SmoothMargin = 20; + connector.SmoothAutoSlope = 0.2; + connector.ShapeViewModel.SinkMarker.PathStyle = source.ShapeViewModel.SinkMarker.PathStyle; + connector.ShapeViewModel.SinkMarker.SizeStyle = source.ShapeViewModel.SinkMarker.SizeStyle; + + return connector; + } public void LayoutUpdated(MindNode mindNode) { @@ -126,7 +151,7 @@ namespace AIStudio.Wpf.Mind.Helpers { var childrensizes = mindNode.Children.Select(p => MeasureOverride(p, mindNode.IsExpanded && isExpanded)).ToArray(); var lastchildsize = childrensizes.LastOrDefault(); - sizewithSpacing = new SizeBase(sizewithSpacing.Width + childrensizes.Sum(p => p.Width) + lastchildsize.Height / 2 - lastchildsize.Width, sizewithSpacing.Height + childrensizes.Sum(p => p.Height)); + sizewithSpacing = new SizeBase(sizewithSpacing.Width + childrensizes.Sum(p => p.Height) - lastchildsize.Height / 2 + lastchildsize.Width, sizewithSpacing.Height + childrensizes.Sum(p => p.Height)); } else if (mindNode.NodeLevel == NodeLevel.Level3) { @@ -159,10 +184,10 @@ namespace AIStudio.Wpf.Mind.Helpers ArrangeOverride(child); - //var connect = mindNode.Root?.Items.OfType().FirstOrDefault(p => p.SourceConnectorInfo?.DataItem == mindNode && p.SinkConnectorInfoFully?.DataItem == child); - //connect?.SetSourcePort(mindNode.BottomConnector); - //connect?.SetSinkPort(child.TopConnector); - //connect.Visible = child.Visible; + var connect = mindNode.Root?.Items.OfType().FirstOrDefault(p => p.SourceConnectorInfo?.DataItem == mindNode && p.SinkConnectorInfoFully?.DataItem == child); + connect?.SetSourcePort(mindNode.RightConnector); + connect?.SetSinkPort(child.BottomLeftConnector); + connect?.SetVisible(child.Visible); } } @@ -181,10 +206,10 @@ namespace AIStudio.Wpf.Mind.Helpers ArrangeOverride(child); - //var connect = mindNode.Root?.Items.OfType().FirstOrDefault(p => p.SourceConnectorInfo?.DataItem == mindNode && p.SinkConnectorInfoFully?.DataItem == child); - //connect?.SetSourcePort(mindNode.BottomConnector); - //connect?.SetSinkPort(child.TopConnector); - //connect.Visible = child.Visible; + var connect = mindNode.Root?.Items.OfType().FirstOrDefault(p => p.SourceConnectorInfo?.DataItem == mindNode && p.SinkConnectorInfoFully?.DataItem == child); + connect?.SetSourcePort(mindNode.RightConnector); + connect?.SetSinkPort(child.TopLeftConnector); + connect?.SetVisible(child.Visible); } } } diff --git a/AIStudio.Wpf.Mind/Helpers/IMindLayout.cs b/AIStudio.Wpf.Mind/Helpers/IMindLayout.cs index fe1373b..55acb73 100644 --- a/AIStudio.Wpf.Mind/Helpers/IMindLayout.cs +++ b/AIStudio.Wpf.Mind/Helpers/IMindLayout.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Text; +using AIStudio.Wpf.DiagramDesigner; using AIStudio.Wpf.Mind.ViewModels; namespace AIStudio.Wpf.Mind.Helpers @@ -8,6 +9,7 @@ namespace AIStudio.Wpf.Mind.Helpers public interface IMindLayout { void Appearance(MindNode mindNode); + ConnectionViewModel GetConnectionViewModel(MindNode source, MindNode sink); void LayoutUpdated(MindNode mindNode); } diff --git a/AIStudio.Wpf.Mind/Helpers/LogicalLayout.cs b/AIStudio.Wpf.Mind/Helpers/LogicalLayout.cs index e232eff..a13ba6a 100644 --- a/AIStudio.Wpf.Mind/Helpers/LogicalLayout.cs +++ b/AIStudio.Wpf.Mind/Helpers/LogicalLayout.cs @@ -75,6 +75,17 @@ namespace AIStudio.Wpf.Mind.Helpers } } } + public ConnectionViewModel GetConnectionViewModel(MindNode source, MindNode sink) + { + var connector = new ConnectionViewModel(source.Root, source.Connectors.FirstOrDefault(), sink.Connectors.FirstOrDefault(), DrawMode.ConnectingLineSmooth, RouterMode.RouterNormal); + connector.ColorViewModel.LineColor = source.ColorViewModel.LineColor; + connector.SmoothMargin = 20; + connector.SmoothAutoSlope = 0.2; + connector.ShapeViewModel.SinkMarker.PathStyle = source.ShapeViewModel.SinkMarker.PathStyle; + connector.ShapeViewModel.SinkMarker.SizeStyle = source.ShapeViewModel.SinkMarker.SizeStyle; + + return connector; + } public void LayoutUpdated(MindNode mindNode) { @@ -121,7 +132,7 @@ namespace AIStudio.Wpf.Mind.Helpers var connect = mindNode.Root?.Items.OfType().FirstOrDefault(p => p.SourceConnectorInfo?.DataItem == mindNode && p.SinkConnectorInfoFully?.DataItem == child); connect?.SetSourcePort(mindNode.RightConnector ?? mindNode.FirstConnector); connect?.SetSinkPort(child.LeftConnector); - connect.Visible = child.Visible; + connect?.SetVisible(child.Visible); } } diff --git a/AIStudio.Wpf.Mind/Helpers/MindLayout.cs b/AIStudio.Wpf.Mind/Helpers/MindLayout.cs index c9dbe00..0ea6eb9 100644 --- a/AIStudio.Wpf.Mind/Helpers/MindLayout.cs +++ b/AIStudio.Wpf.Mind/Helpers/MindLayout.cs @@ -76,6 +76,17 @@ namespace AIStudio.Wpf.Mind.Helpers } } + public ConnectionViewModel GetConnectionViewModel(MindNode source, MindNode sink) + { + var connector = new ConnectionViewModel(source.Root, source.Connectors.FirstOrDefault(), sink.Connectors.FirstOrDefault(), DrawMode.ConnectingLineSmooth, RouterMode.RouterNormal); + connector.ColorViewModel.LineColor = source.ColorViewModel.LineColor; + connector.SmoothMargin = 20; + connector.SmoothAutoSlope = 0.2; + connector.ShapeViewModel.SinkMarker.PathStyle = source.ShapeViewModel.SinkMarker.PathStyle; + connector.ShapeViewModel.SinkMarker.SizeStyle = source.ShapeViewModel.SinkMarker.SizeStyle; + + return connector; + } public void LayoutUpdated(MindNode mindNode) { @@ -138,7 +149,7 @@ namespace AIStudio.Wpf.Mind.Helpers var connect = mindNode.Root?.Items.OfType().FirstOrDefault(p => p.SourceConnectorInfo?.DataItem == mindNode && p.SinkConnectorInfoFully?.DataItem == child); connect?.SetSourcePort(mindNode.FirstConnector); connect?.SetSinkPort(child.LeftConnector); - connect.Visible = child.Visible; + connect?.SetVisible(child.Visible); } var lefts = mindNode.Children.Where(p => p.ConnectorOrientation == ConnectorOrientation.Right).ToList(); @@ -156,7 +167,7 @@ namespace AIStudio.Wpf.Mind.Helpers var connect = mindNode.Root?.Items.OfType().FirstOrDefault(p => p.SourceConnectorInfo?.DataItem == mindNode && p.SinkConnectorInfoFully?.DataItem == child); connect?.SetSourcePort(mindNode.FirstConnector); connect?.SetSinkPort(child.RightConnector); - connect.Visible = child.Visible; + connect?.SetVisible(child.Visible); } } } @@ -180,7 +191,7 @@ namespace AIStudio.Wpf.Mind.Helpers var connect = mindNode.Root?.Items.OfType().FirstOrDefault(p => p.SourceConnectorInfo?.DataItem == mindNode && p.SinkConnectorInfoFully?.DataItem == child); connect?.SetSourcePort(mindNode.RightConnector); connect?.SetSinkPort(child.LeftConnector); - connect.Visible = child.Visible; + connect?.SetVisible(child.Visible); } } } @@ -202,7 +213,7 @@ namespace AIStudio.Wpf.Mind.Helpers var connect = mindNode.Root?.Items.OfType().FirstOrDefault(p => p.SourceConnectorInfo?.DataItem == mindNode && p.SinkConnectorInfoFully?.DataItem == child); connect?.SetSourcePort(mindNode.LeftConnector); connect?.SetSinkPort(child.RightConnector); - connect.Visible = child.Visible; + connect?.SetVisible(child.Visible); } } } diff --git a/AIStudio.Wpf.Mind/Helpers/OrganizationalLayout.cs b/AIStudio.Wpf.Mind/Helpers/OrganizationalLayout.cs index 8f77a8e..9d2378a 100644 --- a/AIStudio.Wpf.Mind/Helpers/OrganizationalLayout.cs +++ b/AIStudio.Wpf.Mind/Helpers/OrganizationalLayout.cs @@ -54,6 +54,7 @@ namespace AIStudio.Wpf.Mind.Helpers break; } case NodeLevel.Level3: + case NodeLevel.Level4: { mindNode.ItemWidth = 80; mindNode.ItemHeight = 25; @@ -76,6 +77,18 @@ namespace AIStudio.Wpf.Mind.Helpers } } + public ConnectionViewModel GetConnectionViewModel(MindNode source, MindNode sink) + { + var connector = new ConnectionViewModel(source.Root, source.Connectors.FirstOrDefault(), sink.Connectors.FirstOrDefault(), DrawMode.ConnectingLineStraight, RouterMode.RouterOrthogonal); + connector.ColorViewModel.LineColor = source.ColorViewModel.LineColor; + connector.SmoothMargin = 20; + connector.SmoothAutoSlope = 0.2; + connector.ShapeViewModel.SinkMarker.PathStyle = source.ShapeViewModel.SinkMarker.PathStyle; + connector.ShapeViewModel.SinkMarker.SizeStyle = sink.ShapeViewModel.SinkMarker.SizeStyle; + + return connector; + } + public void LayoutUpdated(MindNode mindNode) { if (mindNode == null) return; @@ -89,7 +102,6 @@ namespace AIStudio.Wpf.Mind.Helpers mindNode.GetLevel1Node().LayoutUpdating = false; } - public SizeBase MeasureOverride(MindNode mindNode, bool isExpanded = true) { var sizewithSpacing = mindNode.SizeWithSpacing; @@ -122,7 +134,7 @@ namespace AIStudio.Wpf.Mind.Helpers var connect = mindNode.Root?.Items.OfType().FirstOrDefault(p => p.SourceConnectorInfo?.DataItem == mindNode && p.SinkConnectorInfoFully?.DataItem == child); connect?.SetSourcePort(mindNode.BottomConnector); connect?.SetSinkPort(child.TopConnector); - connect.Visible = child.Visible; + connect?.SetVisible(child.Visible); } } diff --git a/AIStudio.Wpf.Mind/NodeLevel.cs b/AIStudio.Wpf.Mind/NodeLevel.cs index af1fd22..b2eebf6 100644 --- a/AIStudio.Wpf.Mind/NodeLevel.cs +++ b/AIStudio.Wpf.Mind/NodeLevel.cs @@ -8,6 +8,7 @@ namespace AIStudio.Wpf.Mind { Level1, Level2, - Level3 + Level3, + Level4 } } diff --git a/AIStudio.Wpf.Mind/Themes/MindNode.xaml b/AIStudio.Wpf.Mind/Themes/MindNode.xaml index a347efb..baa6ac2 100644 --- a/AIStudio.Wpf.Mind/Themes/MindNode.xaml +++ b/AIStudio.Wpf.Mind/Themes/MindNode.xaml @@ -154,6 +154,9 @@ + + + diff --git a/AIStudio.Wpf.Mind/ViewModels/MindNode.cs b/AIStudio.Wpf.Mind/ViewModels/MindNode.cs index cd66088..6df6028 100644 --- a/AIStudio.Wpf.Mind/ViewModels/MindNode.cs +++ b/AIStudio.Wpf.Mind/ViewModels/MindNode.cs @@ -356,10 +356,7 @@ namespace AIStudio.Wpf.Mind.ViewModels } else { - if (NodeLevel == NodeLevel.Level1) - node = new MindNode(Root, NodeLevel.Level2, this.MindType) { Text = "分支主题" }; - else - node = new MindNode(Root, NodeLevel.Level3, this.MindType) { Text = "分支主题" }; + node = new MindNode(Root, NodeLevel + 1, this.MindType) { Text = "分支主题" }; } AddChild(node); @@ -478,25 +475,7 @@ namespace AIStudio.Wpf.Mind.ViewModels item.Parent = this; Root?.DirectAddItemCommand.Execute(item); - DrawMode drawMode = DrawMode.ConnectingLineSmooth; - RouterMode routerMode = AIStudio.Wpf.DiagramDesigner.RouterMode.RouterNormal; - switch (MindType) - { - case MindType.Directory: - case MindType.Organizational: - drawMode = DrawMode.ConnectingLineStraight; - routerMode = AIStudio.Wpf.DiagramDesigner.RouterMode.RouterOrthogonal; - break; - - } - - ConnectionViewModel connector = new ConnectionViewModel(Root, this.Connectors.FirstOrDefault(), item.Connectors.FirstOrDefault(), drawMode, routerMode); - connector.ColorViewModel.LineColor = this.ColorViewModel.LineColor; - connector.SmoothMargin = 20; - connector.SmoothAutoSlope = 0.2; - connector.ShapeViewModel.SinkMarker.PathStyle = this.ShapeViewModel.SinkMarker.PathStyle; - connector.ShapeViewModel.SinkMarker.SizeStyle = this.ShapeViewModel.SinkMarker.SizeStyle; - + ConnectionViewModel connector = MindLayout?.GetConnectionViewModel(this, item); Root?.DirectAddItemCommand.Execute(connector); Root?.ClearSelectedItemsCommand.Execute(new SelectableDesignerItemViewModelBase[] { connector }); diff --git a/Directory.Build.Props b/Directory.Build.Props index b3d0e9d..4d652c4 100644 --- a/Directory.Build.Props +++ b/Directory.Build.Props @@ -1,7 +1,7 @@ - net461;netcoreapp3.1;net5.0-windows + netcoreapp3.1;net5.0-windows