mirror of
https://gitee.com/akwkevin/aistudio.-wpf.-diagram
synced 2026-04-28 12:13:25 +08:00
mind 有点样子了
This commit is contained in:
@@ -5,32 +5,139 @@
|
||||
|
||||
<dd:ColorBrushConverter x:Key="ColorBrushConverter"/>
|
||||
<dd:DoubleToCornerRadius x:Key="DoubleToCornerRadius"/>
|
||||
<dd:IntToVisibilityConverter x:Key="IntToVisibilityConverter"/>
|
||||
|
||||
<!-- Toggle Button -->
|
||||
<Style x:Key="ExpandCollapseToggleStyle" TargetType="ToggleButton">
|
||||
<Setter Property="Focusable" Value="False"/>
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="ToggleButton">
|
||||
<Grid Width="17" Height="17" SnapsToDevicePixels="True">
|
||||
<Rectangle Width="13" Height="13" Stroke="Gray" RadiusX="6" RadiusY="6" SnapsToDevicePixels="true">
|
||||
<Rectangle.Fill>
|
||||
<LinearGradientBrush EndPoint="0.5,2" StartPoint="0.5,0">
|
||||
<GradientStop Color="White" Offset="0"/>
|
||||
<GradientStop Color="Silver" Offset="0.5"/>
|
||||
<GradientStop Color="LightGray" Offset="1"/>
|
||||
</LinearGradientBrush>
|
||||
</Rectangle.Fill>
|
||||
</Rectangle>
|
||||
<Rectangle x:Name="ExpandPath" Width="1" Height="9" Stroke="Gray" SnapsToDevicePixels="true" />
|
||||
<Rectangle Width="9" Height="1" Stroke="Gray" SnapsToDevicePixels="true"/>
|
||||
</Grid>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsChecked" Value="True">
|
||||
<Setter Property="Visibility" TargetName="ExpandPath" Value="Collapsed"/>
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<ControlTemplate x:Key="MindLevel1NodeStyle" TargetType="{x:Type ContentControl}">
|
||||
<Grid >
|
||||
<Grid.ContextMenu>
|
||||
<ContextMenu ItemsSource="{Binding MenuOptions}">
|
||||
<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>
|
||||
<Grid IsHitTestVisible="False">
|
||||
<Border BorderThickness="1"
|
||||
BorderBrush="{Binding ColorViewModel.LineColor,Converter={StaticResource ColorBrushConverter}}"
|
||||
Background="{Binding ColorViewModel.FillColor,Converter={StaticResource ColorBrushConverter}}"
|
||||
CornerRadius="{Binding CornerRadius,Converter={StaticResource DoubleToCornerRadius}}">
|
||||
</Border>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
|
||||
<ControlTemplate x:Key="MindLevel2NodeStyle" TargetType="{x:Type ContentControl}">
|
||||
<Grid>
|
||||
<Grid.ContextMenu>
|
||||
<ContextMenu ItemsSource="{Binding MenuOptions}">
|
||||
<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>
|
||||
<Grid IsHitTestVisible="False">
|
||||
<Border BorderThickness="1"
|
||||
BorderBrush="{Binding ColorViewModel.LineColor,Converter={StaticResource ColorBrushConverter}}"
|
||||
Background="{Binding ColorViewModel.FillColor,Converter={StaticResource ColorBrushConverter}}"
|
||||
CornerRadius="{Binding CornerRadius,Converter={StaticResource DoubleToCornerRadius}}">
|
||||
</Border>
|
||||
</Grid>
|
||||
<ToggleButton IsChecked="{Binding IsExpanded}" Style="{StaticResource ExpandCollapseToggleStyle}" HorizontalAlignment="Left" Margin="-15,0,0,0" Visibility="{Binding Children.Count,Converter={StaticResource IntToVisibilityConverter}}"/>
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
|
||||
<ControlTemplate x:Key="MindLevel3NodeStyle" TargetType="{x:Type ContentControl}">
|
||||
<Grid>
|
||||
<Grid.ContextMenu>
|
||||
<ContextMenu ItemsSource="{Binding MenuOptions}">
|
||||
<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>
|
||||
<Grid IsHitTestVisible="False">
|
||||
<Border BorderThickness="0,0,0,1"
|
||||
BorderBrush="{Binding ColorViewModel.LineColor,Converter={StaticResource ColorBrushConverter}}"
|
||||
Background="{Binding ColorViewModel.FillColor,Converter={StaticResource ColorBrushConverter}}">
|
||||
|
||||
</Border>
|
||||
</Grid>
|
||||
<ToggleButton IsChecked="{Binding IsExpanded}" Style="{StaticResource ExpandCollapseToggleStyle}" HorizontalAlignment="Left" Margin="-15,0,0,0" Visibility="{Binding Children.Count,Converter={StaticResource IntToVisibilityConverter}}"/>
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
|
||||
<Style x:Key="MindNodeStyle" TargetType="{x:Type ContentControl}">
|
||||
<Setter Property="Template" Value="{StaticResource MindLevel1NodeStyle}" />
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding NodeLevel}" Value="Level1">
|
||||
<Setter Property="Template" Value="{StaticResource MindLevel1NodeStyle}" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding NodeLevel}" Value="Level2">
|
||||
<Setter Property="Template" Value="{StaticResource MindLevel2NodeStyle}" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding NodeLevel}" Value="Level3">
|
||||
<Setter Property="Template" Value="{StaticResource MindLevel3NodeStyle}" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
|
||||
<DataTemplate DataType="{x:Type viewmodel:MindNode}">
|
||||
<Grid IsHitTestVisible="False">
|
||||
<Grid>
|
||||
<Border BorderThickness="1"
|
||||
BorderBrush="{Binding ColorViewModel.LineColor,Converter={StaticResource ColorBrushConverter}}"
|
||||
Background="{Binding ColorViewModel.FillColor,Converter={StaticResource ColorBrushConverter}}"
|
||||
CornerRadius="{Binding CornerRadius,Converter={StaticResource DoubleToCornerRadius}}">
|
||||
|
||||
</Border>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
</DataTemplate>
|
||||
<DataTemplate DataType="{x:Type viewmodel:MindLevel1Node}">
|
||||
<Grid IsHitTestVisible="False">
|
||||
<Grid>
|
||||
<Border BorderThickness="1"
|
||||
BorderBrush="{Binding ColorViewModel.LineColor,Converter={StaticResource ColorBrushConverter}}"
|
||||
Background="{Binding ColorViewModel.FillColor,Converter={StaticResource ColorBrushConverter}}"
|
||||
CornerRadius="{Binding CornerRadius,Converter={StaticResource DoubleToCornerRadius}}">
|
||||
|
||||
</Border>
|
||||
</Grid>
|
||||
<ContentControl Style="{StaticResource MindNodeStyle}"/>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
|
||||
|
||||
</ResourceDictionary>
|
||||
@@ -1,9 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Windows.Media;
|
||||
using AIStudio.Wpf.DiagramDesigner;
|
||||
using AIStudio.Wpf.DiagramDesigner.Algorithms;
|
||||
using AIStudio.Wpf.DiagramDesigner.Geometrys;
|
||||
using AIStudio.Wpf.DiagramDesigner.Models;
|
||||
|
||||
@@ -13,12 +17,12 @@ namespace AIStudio.Wpf.Mind.ViewModels
|
||||
{
|
||||
public MindNode(NodeLevel nodeLevel) : this(null, nodeLevel)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public MindNode(IDiagramViewModel root, NodeLevel nodeLevel) : base(root)
|
||||
{
|
||||
NodeLevel = nodeLevel;
|
||||
LevelInit(true);
|
||||
}
|
||||
|
||||
public MindNode(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer)
|
||||
@@ -29,6 +33,90 @@ namespace AIStudio.Wpf.Mind.ViewModels
|
||||
{
|
||||
}
|
||||
|
||||
protected override void Init(IDiagramViewModel root)
|
||||
{
|
||||
base.Init(root);
|
||||
|
||||
EnabledForConnection = false;
|
||||
|
||||
AddChildCommand = new SimpleCommand(Command_Enable, ExecuteAddChildCommand);
|
||||
AddParentCommand = new SimpleCommand(Level_Enable, ExecuteAddParentCommand);
|
||||
AddPeerCommand = new SimpleCommand(Level_Enable, ExecuteAddPeerCommand);
|
||||
DeleteCommand = new SimpleCommand(Command_Enable, ExecuteDeleteCommand);
|
||||
MoveForwardCommand = new SimpleCommand(Command_Enable, ExecuteMoveForwardCommand);
|
||||
MoveBackCommand = new SimpleCommand(Command_Enable, ExecuteMoveBackCommand);
|
||||
BuildMenuOptions();
|
||||
|
||||
this.PropertyChanged += this.Item_PropertyChanged;
|
||||
}
|
||||
|
||||
private void LevelInit(bool init =false)
|
||||
{
|
||||
switch (NodeLevel)
|
||||
{
|
||||
case NodeLevel.Level1:
|
||||
{
|
||||
ItemWidth = 110;
|
||||
ItemHeight = 40;
|
||||
this.ClearConnectors();
|
||||
var port = new FullyCreatedConnectorInfo(Root, this, ConnectorOrientation.None, true) { XRatio = 0.5, YRatio = 0.5 };
|
||||
this.AddConnector(port);
|
||||
IsInnerConnector = true;
|
||||
|
||||
ColorViewModel.FillColor.Color = Color.FromRgb(0x73, 0xa1, 0xbf);
|
||||
ColorViewModel.LineColor.Color = Color.FromRgb(0x73, 0xa1, 0xbf);
|
||||
FontViewModel.FontColor = Colors.White;
|
||||
FontViewModel.FontSize = 15;
|
||||
Spacing = new SizeBase(50, 15);
|
||||
ShapeViewModel.SinkMarker.PathStyle = ArrowPathStyle.Circle;
|
||||
ShapeViewModel.SinkMarker.SizeStyle = ArrowSizeStyle.VerySmall;
|
||||
|
||||
break;
|
||||
}
|
||||
case NodeLevel.Level2:
|
||||
{
|
||||
ItemWidth = 80;
|
||||
ItemHeight = 25;
|
||||
this.ClearConnectors();
|
||||
var port1 = new FullyCreatedConnectorInfo(Root, this, ConnectorOrientation.Left, true) { XRatio = 0, YRatio = 0.5 };
|
||||
this.AddConnector(port1);
|
||||
var port2 = new FullyCreatedConnectorInfo(Root, this, ConnectorOrientation.Right, true) { XRatio = 1, YRatio = 0.5 };
|
||||
this.AddConnector(port2);
|
||||
IsInnerConnector = true;
|
||||
|
||||
ColorViewModel.LineColor.Color = Color.FromRgb(0x73, 0xa1, 0xbf);
|
||||
ShapeViewModel.SinkMarker.PathStyle = ArrowPathStyle.None;
|
||||
ShapeViewModel.SinkMarker.SizeStyle = ArrowSizeStyle.VerySmall;
|
||||
break;
|
||||
}
|
||||
case NodeLevel.Level3:
|
||||
{
|
||||
ItemWidth = 80;
|
||||
ItemHeight = 25;
|
||||
this.ClearConnectors();
|
||||
var port1 = new FullyCreatedConnectorInfo(Root, this, ConnectorOrientation.Left, true) { XRatio = 0, YRatio = 1 };
|
||||
this.AddConnector(port1);
|
||||
var port2 = new FullyCreatedConnectorInfo(Root, this, ConnectorOrientation.Right, true) { XRatio = 1, YRatio = 1 };
|
||||
this.AddConnector(port2);
|
||||
IsInnerConnector = true;
|
||||
|
||||
ColorViewModel.LineColor.Color = Color.FromRgb(0x73, 0xa1, 0xbf);
|
||||
ShapeViewModel.SinkMarker.PathStyle = ArrowPathStyle.None;
|
||||
ShapeViewModel.SinkMarker.SizeStyle = ArrowSizeStyle.VerySmall;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private bool Level_Enable(object obj)
|
||||
{
|
||||
if (Command_Enable(obj) == false) return false;
|
||||
|
||||
return NodeLevel != NodeLevel.Level1;
|
||||
}
|
||||
|
||||
[Browsable(false)]
|
||||
public NodeLevel NodeLevel
|
||||
{
|
||||
@@ -48,10 +136,28 @@ namespace AIStudio.Wpf.Mind.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
public double Spacing
|
||||
private bool _isExpanded = true;
|
||||
public bool IsExpanded
|
||||
{
|
||||
get
|
||||
{
|
||||
return _isExpanded;
|
||||
}
|
||||
set
|
||||
{
|
||||
SetProperty(ref _isExpanded, value);
|
||||
}
|
||||
}
|
||||
|
||||
public bool LayoutUpdating
|
||||
{
|
||||
get; set;
|
||||
} = 20;
|
||||
}
|
||||
|
||||
public SizeBase Spacing
|
||||
{
|
||||
get; set;
|
||||
} = new SizeBase(15, 15);
|
||||
|
||||
public List<MindNode> Children
|
||||
{
|
||||
@@ -62,170 +168,357 @@ namespace AIStudio.Wpf.Mind.ViewModels
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.Size.Add(Spacing * 2);
|
||||
return this.Size.Add(Spacing.Width * 2, Spacing.Height * 2);
|
||||
}
|
||||
}
|
||||
|
||||
public SizeBase DesiredSize
|
||||
{
|
||||
get;set;
|
||||
get; set;
|
||||
}
|
||||
|
||||
public SizeBase MeasureOverride()
|
||||
public PointBase DesiredPosition
|
||||
{
|
||||
var sizewithSpacing = SizeWithSpacing;
|
||||
if (Children?.Count > 0)
|
||||
get; set;
|
||||
}
|
||||
|
||||
public PointBase Offset
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
public SimpleCommand AddParentCommand
|
||||
{
|
||||
get; private set;
|
||||
}
|
||||
|
||||
public SimpleCommand AddChildCommand
|
||||
{
|
||||
get; private set;
|
||||
}
|
||||
|
||||
public SimpleCommand AddPeerCommand
|
||||
{
|
||||
get; private set;
|
||||
}
|
||||
|
||||
public SimpleCommand DeleteCommand
|
||||
{
|
||||
get; private set;
|
||||
}
|
||||
|
||||
public SimpleCommand MoveForwardCommand
|
||||
{
|
||||
get; private set;
|
||||
}
|
||||
|
||||
public SimpleCommand MoveBackCommand
|
||||
{
|
||||
get; private set;
|
||||
}
|
||||
|
||||
private void BuildMenuOptions()
|
||||
{
|
||||
menuOptions = new ObservableCollection<CinchMenuItem>();
|
||||
CinchMenuItem menuItem = new CinchMenuItem();
|
||||
menuItem.Text = "下级";
|
||||
menuItem.Command = AddChildCommand;
|
||||
menuOptions.Add(menuItem);
|
||||
menuItem = new CinchMenuItem();
|
||||
menuItem.Text = "同级";
|
||||
menuItem.Command = AddPeerCommand;
|
||||
menuOptions.Add(menuItem);
|
||||
//menuItem = new CinchMenuItem();
|
||||
//menuItem.Text = "上级";
|
||||
//menuItem.Command = AddParentCommand;
|
||||
//menuOptions.Add(menuItem);
|
||||
menuItem = new CinchMenuItem();
|
||||
menuItem.Text = "前移";
|
||||
menuItem.Command = MoveForwardCommand;
|
||||
menuOptions.Add(menuItem);
|
||||
menuItem = new CinchMenuItem();
|
||||
menuItem.Text = "后移";
|
||||
menuItem.Command = MoveBackCommand;
|
||||
menuOptions.Add(menuItem);
|
||||
menuItem = new CinchMenuItem();
|
||||
menuItem.Text = "删除";
|
||||
menuItem.Command = DeleteCommand;
|
||||
menuOptions.Add(menuItem);
|
||||
}
|
||||
|
||||
public void ExecuteAddChildCommand(object obj)
|
||||
{
|
||||
if (obj is MindNode node)
|
||||
{
|
||||
var childrensizes = Children.Select(p => p.MeasureOverride()).ToArray();
|
||||
sizewithSpacing = new SizeBase(sizewithSpacing.Width + childrensizes.Max(p => p.Width), Math.Max(sizewithSpacing.Height, childrensizes.Sum(p => p.Height)));
|
||||
}
|
||||
DesiredSize = sizewithSpacing;
|
||||
return DesiredSize;
|
||||
else
|
||||
{
|
||||
if (NodeLevel == NodeLevel.Level1)
|
||||
node = new MindNode(Root, NodeLevel.Level2) { Text = "分支主题" };
|
||||
else
|
||||
node = new MindNode(Root, NodeLevel.Level3) { Text = "分支主题" };
|
||||
}
|
||||
AddChild(node);
|
||||
|
||||
LayoutUpdated();
|
||||
}
|
||||
|
||||
public void ExecuteAddParentCommand(object obj)
|
||||
{
|
||||
if (Parent is MindNode parent)
|
||||
{
|
||||
if (obj is MindNode node)
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
if (NodeLevel == NodeLevel.Level1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if (NodeLevel == NodeLevel.Level2)
|
||||
node = new MindNode(Root, NodeLevel.Level2) { Text = "分支主题" };
|
||||
else
|
||||
node = new MindNode(Root, NodeLevel.Level3) { Text = "分支主题" };
|
||||
}
|
||||
|
||||
parent.RemoveChild(this);
|
||||
int index = parent.Children.IndexOf(this);
|
||||
parent.AddChild(node, index + 1);
|
||||
node.AddChild(this);
|
||||
|
||||
LayoutUpdated();
|
||||
}
|
||||
}
|
||||
|
||||
public void ExecuteAddPeerCommand(object obj)
|
||||
{
|
||||
if (Parent is MindNode parent)
|
||||
{
|
||||
if (obj is MindNode node)
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
if (NodeLevel == NodeLevel.Level1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if (NodeLevel == NodeLevel.Level2)
|
||||
node = new MindNode(Root, NodeLevel.Level2) { Text = "分支主题" };
|
||||
else
|
||||
node = new MindNode(Root, NodeLevel.Level3) { Text = "分支主题" };
|
||||
}
|
||||
int index = parent.Children.IndexOf(this);
|
||||
parent.AddChild(node, index + 1);
|
||||
|
||||
LayoutUpdated();
|
||||
}
|
||||
}
|
||||
|
||||
private void ExecuteMoveBackCommand(object obj)
|
||||
{
|
||||
if (Parent is MindNode parent)
|
||||
{
|
||||
int index = parent.Children.IndexOf(this);
|
||||
if (index < parent.Children.Count - 1)
|
||||
{
|
||||
parent.RemoveChild(this);
|
||||
parent.AddChild(this, index + 1);
|
||||
LayoutUpdated();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ExecuteMoveForwardCommand(object obj)
|
||||
{
|
||||
if (Parent is MindNode parent)
|
||||
{
|
||||
int index = parent.Children.IndexOf(this);
|
||||
if (index > 0)
|
||||
{
|
||||
parent.RemoveChild(this);
|
||||
parent.AddChild(this, index - 1);
|
||||
LayoutUpdated();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ExecuteDeleteCommand(object obj)
|
||||
{
|
||||
if (Parent is MindNode parent)
|
||||
{
|
||||
parent.RemoveChild(this);
|
||||
LayoutUpdated();
|
||||
}
|
||||
}
|
||||
|
||||
public void AddChild(MindNode item, int index = -1)
|
||||
{
|
||||
if (index >= 0)
|
||||
{
|
||||
this.Children.Insert(index, item);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.Children.Add(item);
|
||||
}
|
||||
item.Parent = this;
|
||||
//item.ParentId = this.Id;
|
||||
Root?.DirectAddItemCommand.Execute(item);
|
||||
|
||||
ConnectionViewModel connector = new ConnectionViewModel(Root, this.Connectors.FirstOrDefault(), item.Connectors.FirstOrDefault());
|
||||
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;
|
||||
|
||||
Root?.DirectAddItemCommand.Execute(connector);
|
||||
|
||||
Root?.BringForwardCommand.Execute(new DesignerItemViewModelBase[] { item });
|
||||
|
||||
Root?.ClearSelectedItemsCommand.Execute(new SelectableDesignerItemViewModelBase[] { connector });
|
||||
}
|
||||
|
||||
public void RemoveChild(MindNode item)
|
||||
{
|
||||
item.PropertyChanged -= Item_PropertyChanged;
|
||||
|
||||
this.Children.Remove(item);
|
||||
|
||||
var connectors = Root?.Items.OfType<ConnectionViewModel>().Where(p => p.SinkConnectorInfoFully?.DataItem == item).ToList();
|
||||
|
||||
Root?.DirectRemoveItemCommand.Execute(item);
|
||||
Root?.DirectRemoveItemCommand.Execute(connectors);
|
||||
if (item.Children?.Count > 0)
|
||||
{
|
||||
foreach (var child in item.Children.ToList())
|
||||
{
|
||||
item.RemoveChild(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public MindNode GetLevel1Node()
|
||||
{
|
||||
var node = this;
|
||||
while (node.Parent is MindNode mindNode)
|
||||
{
|
||||
node = mindNode;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
private void Item_PropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
switch (e.PropertyName)
|
||||
{
|
||||
case nameof(IsExpanded):
|
||||
GetLevel1Node()?.LayoutUpdated();
|
||||
break;
|
||||
case nameof(NodeLevel):
|
||||
LevelInit();
|
||||
break;
|
||||
case nameof(Left):
|
||||
{
|
||||
|
||||
if (e is ValuePropertyChangedEventArgs valuePropertyChangedEventArgs)
|
||||
{
|
||||
if (NodeLevel == NodeLevel.Level1)
|
||||
{
|
||||
LayoutUpdated();
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateOffsetX((double)valuePropertyChangedEventArgs.OldValue, (double)valuePropertyChangedEventArgs.NewValue);
|
||||
LayoutUpdated();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case nameof(Top):
|
||||
{
|
||||
if (e is ValuePropertyChangedEventArgs valuePropertyChangedEventArgs)
|
||||
{
|
||||
if (NodeLevel == NodeLevel.Level1)
|
||||
{
|
||||
LayoutUpdated();
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateOffsetY((double)valuePropertyChangedEventArgs.OldValue, (double)valuePropertyChangedEventArgs.NewValue);
|
||||
LayoutUpdated();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateOffsetX(double oldvalue, double newvalue)
|
||||
{
|
||||
if (GetLevel1Node()?.LayoutUpdating == true) return;
|
||||
|
||||
Offset += new VectorBase(newvalue - oldvalue, 0);
|
||||
}
|
||||
|
||||
public void UpdateOffsetY(double oldvalue, double newvalue)
|
||||
{
|
||||
if (GetLevel1Node()?.LayoutUpdating == true) return;
|
||||
|
||||
Offset += new VectorBase(0, newvalue - oldvalue);
|
||||
}
|
||||
|
||||
public void LayoutUpdated()
|
||||
{
|
||||
var size = MeasureOverride();
|
||||
ArrangeOverride(size);
|
||||
GetLevel1Node()?.Level1LayoutUpdated();
|
||||
}
|
||||
|
||||
public void ArrangeOverride(SizeBase sizeBase)
|
||||
protected void Level1LayoutUpdated()
|
||||
{
|
||||
double left = MiddlePosition.X + ItemWidth / 2 + Spacing;
|
||||
double top = MiddlePosition.Y - sizeBase.Height / 2;
|
||||
LayoutUpdating = true;
|
||||
var size = MeasureOverride();
|
||||
ArrangeOverride();
|
||||
|
||||
Root.BringToFrontCommand.Execute(new SelectableDesignerItemViewModelBase[] { this });
|
||||
Root?.ReconnectLinksToClosestPorts();
|
||||
|
||||
LayoutUpdating = false;
|
||||
}
|
||||
|
||||
protected SizeBase MeasureOverride(bool isExpanded = true)
|
||||
{
|
||||
var sizewithSpacing = SizeWithSpacing;
|
||||
if (Children?.Count > 0)
|
||||
{
|
||||
var childrensizes = Children.Select(p => p.MeasureOverride(IsExpanded && isExpanded)).ToArray();
|
||||
sizewithSpacing = new SizeBase(sizewithSpacing.Width + childrensizes.Max(p => p.Width), Math.Max(sizewithSpacing.Height, childrensizes.Sum(p => p.Height)));
|
||||
}
|
||||
DesiredSize = isExpanded ? sizewithSpacing : new SizeBase(0, 0);
|
||||
Visible = isExpanded;
|
||||
var connectors = Root?.Items.OfType<ConnectionViewModel>().Where(p => p.SinkConnectorInfoFully?.DataItem == this).ToList();
|
||||
connectors?.ForEach(p => p.Visible = Visible);
|
||||
return DesiredSize;
|
||||
}
|
||||
|
||||
protected void ArrangeOverride()
|
||||
{
|
||||
double left = MiddlePosition.X + ItemWidth / 2 + Spacing.Width;
|
||||
double top = MiddlePosition.Y - DesiredSize.Height / 2;
|
||||
if (Children?.Count > 0)
|
||||
{
|
||||
foreach (var child in Children)
|
||||
{
|
||||
child.Left = left + Spacing;
|
||||
child.Top = top + child.DesiredSize.Height / 2 - child.ItemHeight;
|
||||
|
||||
child.Left = left + child.Spacing.Width + child.Offset.X;
|
||||
child.Top = top + child.DesiredSize.Height / 2 - child.ItemHeight / 2 + child.Offset.Y;
|
||||
child.DesiredPosition = child.Position;
|
||||
top += child.DesiredSize.Height;
|
||||
|
||||
child.ArrangeOverride(child.DesiredSize);
|
||||
child.ArrangeOverride();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class MindLevel1Node : MindNode
|
||||
{
|
||||
public MindLevel1Node() : this(null)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public MindLevel1Node(IDiagramViewModel root) : base(root, NodeLevel.Level1)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public MindLevel1Node(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public MindLevel1Node(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType)
|
||||
{
|
||||
|
||||
}
|
||||
protected override void Init(IDiagramViewModel root)
|
||||
{
|
||||
base.Init(root);
|
||||
|
||||
ItemWidth = 80;
|
||||
ItemHeight = 40;
|
||||
this.ClearConnectors();
|
||||
var port = new FullyCreatedConnectorInfo(root, this, ConnectorOrientation.None, true) { XRatio = 0.5, YRatio = 0.5 };
|
||||
this.AddConnector(port);
|
||||
IsInnerConnector = true;
|
||||
}
|
||||
|
||||
public RectangleBase Rectangle
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class MindLevel2Node : MindNode
|
||||
{
|
||||
public MindLevel2Node() : this(null)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public MindLevel2Node(IDiagramViewModel root) : base(root, NodeLevel.Level2)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public MindLevel2Node(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public MindLevel2Node(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected override void Init(IDiagramViewModel root)
|
||||
{
|
||||
base.Init(root);
|
||||
|
||||
ItemWidth = 80;
|
||||
ItemHeight = 40;
|
||||
this.ClearConnectors();
|
||||
var port1 = new FullyCreatedConnectorInfo(root, this, ConnectorOrientation.None, true) { XRatio = 0, YRatio = 0.5 };
|
||||
this.AddConnector(port1);
|
||||
var port2 = new FullyCreatedConnectorInfo(root, this, ConnectorOrientation.None, true) { XRatio = 1, YRatio = 0.5 };
|
||||
this.AddConnector(port2);
|
||||
IsInnerConnector = true;
|
||||
}
|
||||
|
||||
public PointBase Offset
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
}
|
||||
|
||||
public class MindLevel3Node : MindNode
|
||||
{
|
||||
public MindLevel3Node() : this(null)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public MindLevel3Node(IDiagramViewModel root) : base(root, NodeLevel.Level2)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public MindLevel3Node(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public MindLevel3Node(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType)
|
||||
{
|
||||
|
||||
}
|
||||
protected override void Init(IDiagramViewModel root)
|
||||
{
|
||||
base.Init(root);
|
||||
|
||||
ItemWidth = 80;
|
||||
ItemHeight = 40;
|
||||
this.ClearConnectors();
|
||||
var port1 = new FullyCreatedConnectorInfo(root, this, ConnectorOrientation.None, true) { XRatio = 0, YRatio = 1 };
|
||||
this.AddConnector(port1);
|
||||
var port2 = new FullyCreatedConnectorInfo(root, this, ConnectorOrientation.None, true) { XRatio = 1, YRatio = 1 };
|
||||
this.AddConnector(port2);
|
||||
IsInnerConnector = true;
|
||||
}
|
||||
public PointBase Offset
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user