Mind Editoe

This commit is contained in:
艾竹
2023-03-05 21:30:53 +08:00
parent 9061146139
commit 79f4896fbd
41 changed files with 2090 additions and 484 deletions

View File

@@ -32,27 +32,18 @@ namespace AIStudio.Wpf.Flowchart
DiagramViewModel.GridCellSize = new Size(100, 100);
DiagramViewModel.ShowGrid= false;
_service.DrawModeViewModel.LineDrawMode = DrawMode.ConnectingLineSmooth;
DiagramViewModel.AllowDrop = false;
}
private MindType _mindType = Mind.MindType.FishBone;
public MindType MindType
{
get
{
return _mindType;
}
set
{
SetProperty(ref _mindType, value);
}
}
protected override void Init()
{
base.Init();
DiagramViewModels = new ObservableCollection<IDiagramViewModel>()
{
new MindDiagramViewModel(){Name= "页-1", DiagramType = DiagramType},
};
DiagramViewModel = DiagramViewModels.FirstOrDefault();
InitDiagramViewModel();
MindNode level1node = new MindNode(DiagramViewModel, Mind.NodeLevel.Level1, MindType) { Text = "思维导图" };
DiagramViewModel.DirectAddItemCommand.Execute(level1node);
@@ -76,12 +67,28 @@ namespace AIStudio.Wpf.Flowchart
MindNode level2node1_3 = new MindNode(DiagramViewModel, Mind.NodeLevel.Level2, MindType) { Text = "分支主题3" };
level1node.AddChild(level2node1_3);
DiagramViewModel.ClearSelectedItemsCommand.Execute(null);
DiagramViewModel.ClearSelectedItemsCommand.Execute(null);
level1node.LayoutUpdated();
}
private MindType _mindType = Mind.MindType.Organizational;
public MindType MindType
{
get
{
return _mindType;
}
set
{
if (SetProperty(ref _mindType, value))
{
//DiagramViewModel as MindDiagramViewModel
}
}
}
public override void Dispose()
{
base.Dispose();

View File

@@ -31,12 +31,6 @@ namespace AIStudio.Wpf.DiagramApp.ViewModels
Status = status;
DiagramType = diagramType;
DiagramViewModels = new ObservableCollection<IDiagramViewModel>()
{
new DiagramViewModel(){Name= "页-1", DiagramType = diagramType},
};
DiagramViewModel = DiagramViewModels.FirstOrDefault();
Init();
}
public PageViewModel(string filename)
@@ -61,6 +55,12 @@ namespace AIStudio.Wpf.DiagramApp.ViewModels
protected virtual void Init()
{
DiagramViewModels = new ObservableCollection<IDiagramViewModel>()
{
new DiagramViewModel(){Name= "页-1", DiagramType = DiagramType},
};
DiagramViewModel = DiagramViewModels.FirstOrDefault();
InitDiagramViewModel();
}

View File

@@ -9,7 +9,7 @@
Icon="A.ico"
Identifier="RootWindow"
Style="{StaticResource AIStudio.Styles.WindowBase}"
Height="450" Width="800">
Height="600" Width="850">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" MinWidth="100" />

View File

@@ -16,10 +16,17 @@
</UserControl.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid>
<dd:FlowchartEditor Data="{Binding Data}"
GetDataFunc="{Binding GetDataFunc,Mode=OneWayToSource}"
Users="{Binding Users}"
Roles="{Binding Roles}">
</dd:FlowchartEditor>
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
@@ -40,11 +47,6 @@
Height="50"/>
</Grid>
<dd:FlowchartEditor Grid.Row="1" Data="{Binding Data}"
GetDataFunc="{Binding GetDataFunc,Mode=OneWayToSource}"
Users="{Binding Users}"
Roles="{Binding Roles}">
</dd:FlowchartEditor>
<controls:TitleControl Grid.RowSpan="2"/>
</Grid>

View File

@@ -16,10 +16,14 @@
</UserControl.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid>
<dd:MindEditor Data="{Binding Data}"
GetDataFunc="{Binding GetDataFunc,Mode=OneWayToSource}">
</dd:MindEditor>
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
@@ -40,10 +44,6 @@
Height="50"/>
</Grid>
<dd:MindEditor Grid.Row="1" Data="{Binding Data}"
GetDataFunc="{Binding GetDataFunc,Mode=OneWayToSource}">
</dd:MindEditor>
<controls:TitleControl Grid.RowSpan="2"/>
</Grid>
</UserControl>

View File

@@ -6,7 +6,7 @@ using System.Threading.Tasks;
namespace AIStudio.Wpf.DiagramDesigner
{
class DoCommandManager
public class DoCommandManager
{
#region Command定义
public class Command
@@ -24,9 +24,18 @@ namespace AIStudio.Wpf.DiagramDesigner
this.clearAction = clearAction;
}
internal void Do() { action(); }
internal void UnDo() { unDoAction(); }
internal void Clear() { if (clearAction != null) clearAction(); }
internal void Do()
{
action();
}
internal void UnDo()
{
unDoAction();
}
internal void Clear()
{
if (clearAction != null) clearAction();
}
public override string ToString()
{
@@ -35,35 +44,57 @@ namespace AIStudio.Wpf.DiagramDesigner
}
#endregion
public Stack<Command> ReDoActionStack { get; private set; }
public Stack<Command> UnDoActionStack { get; private set; }
public Stack<Command> ReDoActionStack
{
get; private set;
}
public Stack<Command> UnDoActionStack
{
get; private set;
}
public int Capacity { get; set; } = 10;
public DoCommandManager()
{
Init();
}
public void Init()
{
ReDoActionStack = new Stack<Command>();
UnDoActionStack = new Stack<Command>();
}
private bool _undoing;
public void DoNewCommand(string name, Action action, Action unDoAction, Action clearAction = null, bool doit = true)
{
if (UnDoActionStack.Count >= Capacity)
{
//清理
var clear = UnDoActionStack.LastOrDefault();
clear.Clear();
UnDoActionStack = new Stack<Command>(UnDoActionStack.Take(Capacity - 1).Reverse());
}
var cmd = new Command(name, action, unDoAction, clearAction);
UnDoActionStack.Push(cmd);
ReDoActionStack.Clear();
if (doit)
if (_undoing == true) return;
try
{
cmd.Do();
_undoing = true;
if (UnDoActionStack.Count >= Capacity)
{
//清理
var clear = UnDoActionStack.LastOrDefault();
clear.Clear();
UnDoActionStack = new Stack<Command>(UnDoActionStack.Take(Capacity - 1).Reverse());
}
var cmd = new Command(name, action, unDoAction, clearAction);
UnDoActionStack.Push(cmd);
ReDoActionStack.Clear();
if (doit)
{
cmd.Do();
}
}
finally
{
_undoing = false;
}
}
@@ -72,9 +103,19 @@ namespace AIStudio.Wpf.DiagramDesigner
if (!CanUnDo)
return;
var cmd = UnDoActionStack.Pop();
ReDoActionStack.Push(cmd);
cmd.UnDo();
if (_undoing == true) return;
try
{
_undoing = true;
var cmd = UnDoActionStack.Pop();
ReDoActionStack.Push(cmd);
cmd.UnDo();
}
finally
{
_undoing = false;
}
}
public void ReDo()
@@ -82,13 +123,34 @@ namespace AIStudio.Wpf.DiagramDesigner
if (!CanReDo)
return;
var cmd = ReDoActionStack.Pop();
UnDoActionStack.Push(cmd);
cmd.Do();
if (_undoing == true) return;
try
{
_undoing = true;
var cmd = ReDoActionStack.Pop();
UnDoActionStack.Push(cmd);
cmd.Do();
}
finally
{
_undoing = false;
}
}
public bool CanUnDo { get { return UnDoActionStack.Count != 0; } }
public bool CanReDo { get { return ReDoActionStack.Count != 0; } }
public bool CanUnDo
{
get
{
return UnDoActionStack.Count != 0;
}
}
public bool CanReDo
{
get
{
return ReDoActionStack.Count != 0;
}
}
//public IEnumerable<Command> Actions { get { return ReDoActionStack.Reverse().Concat(UnDoActionStack); } }
}
}

View File

@@ -0,0 +1,85 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AIStudio.Wpf.DiagramDesigner.Helpers
{
public static class IEnumerableExtensions
{
/// <summary>
/// Invokes a transform function on each element of a sequence and returns the minimum Double value
/// if the sequence is not empty; otherwise returns the specified default value.
/// </summary>
/// <typeparam name="TSource"> The type of the elements of source. </typeparam>
/// <param name="source"> A sequence of values to determine the minimum value of. </param>
/// <param name="selector"> A transform function to apply to each element. </param>
/// <param name="defaultValue"> The default value. </param>
/// <returns> The minimum value in the sequence or default value if sequence is empty. </returns>
public static double MinOrDefault<TSource>(this IEnumerable<TSource> source, Func<TSource, double> selector, double defaultValue=default(double))
{
if (source.Any<TSource>())
return source.Min<TSource>(selector);
return defaultValue;
}
/// <summary>
/// Invokes a transform function on each element of a sequence and returns the maximum Double value
/// if the sequence is not empty; otherwise returns the specified default value.
/// </summary>
/// <typeparam name="TSource"> The type of the elements of source. </typeparam>
/// <param name="source"> A sequence of values to determine the maximum value of. </param>
/// <param name="selector"> A transform function to apply to each element. </param>
/// <param name="defaultValue"> The default value. </param>
/// <returns> The maximum value in the sequence or default value if sequence is empty. </returns>
public static double MaxOrDefault<TSource>(this IEnumerable<TSource> source, Func<TSource, double> selector, double defaultValue=default(double))
{
if (source.Any<TSource>())
return source.Max<TSource>(selector);
return defaultValue;
}
public static TResult MinOrDefault<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector, TResult defaultValue)
{
if (source.Any())
{
return source.Min(selector);
}
return defaultValue;
}
public static TResult MaxOrDefault<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector, TResult defaultValue)
{
if (source.Any())
{
return source.Max(selector);
}
return defaultValue;
}
/// <summary>
/// Invokes a transform function on each element of a sequence and returns the minimum Double value
/// if the sequence is not empty; otherwise returns the specified default value.
/// </summary>
/// <typeparam name="TSource"> The type of the elements of source. </typeparam>
/// <param name="source"> A sequence of values to determine the minimum value of. </param>
/// <param name="selector"> A transform function to apply to each element. </param>
/// <param name="defaultValue"> The default value. </param>
/// <returns> The minimum value in the sequence or default value if sequence is empty. </returns>
public static double SumOrDefault<TSource>(this IEnumerable<TSource> source, Func<TSource, double> selector, double defaultValue=default(double))
{
if (source.Any<TSource>())
return source.Sum<TSource>(selector);
return defaultValue;
}
}
}

View File

@@ -540,9 +540,10 @@ namespace AIStudio.Wpf.DiagramDesigner
var nodeB = Get(b);
if (nodeA == null || nodeB == null)
return;
return;
nodeA.AdjacentNodes.Add(nodeB, a.DistanceTo(b));
if (!nodeA.AdjacentNodes.ContainsKey(nodeB))
nodeA.AdjacentNodes.Add(nodeB, a.DistanceTo(b));
}
public bool Has(PointBase p)

View File

@@ -1,6 +1,6 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:s="clr-namespace:AIStudio.Wpf.DiagramDesigner">
xmlns:dd="clr-namespace:AIStudio.Wpf.DiagramDesigner">
<!--TextBox水印样式-->
<Style TargetType="{x:Type TextBox}" x:Key="WaterTextBox">
<Setter Property="Background" Value="Transparent"/>
@@ -29,7 +29,7 @@
</ScrollViewer>
<!--水印-->
<TextBlock x:Name="Message" Padding="{TemplateBinding Padding}" Visibility="Collapsed"
Text="{TemplateBinding s:ControlAttachProperty.Watermark}" Grid.Column="1"
Text="{TemplateBinding dd:ControlAttachProperty.Watermark}" Grid.Column="1"
Foreground="{TemplateBinding Foreground}" IsHitTestVisible="False" Opacity="0.5"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Margin="5,2,5,2" />
@@ -78,7 +78,7 @@
</ScrollViewer>
<!--水印-->
<TextBlock x:Name="Message" Padding="{TemplateBinding Padding}" Visibility="Collapsed"
Text="{TemplateBinding s:ControlAttachProperty.Watermark}" Grid.Column="1"
Text="{TemplateBinding dd:ControlAttachProperty.Watermark}" Grid.Column="1"
Foreground="{TemplateBinding Foreground}" IsHitTestVisible="False" Opacity="0.5"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Margin="5,2,5,2" />

View File

@@ -1,10 +1,10 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:s="clr-namespace:AIStudio.Wpf.DiagramDesigner">
xmlns:dd="clr-namespace:AIStudio.Wpf.DiagramDesigner">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Shared.xaml" />
</ResourceDictionary.MergedDictionaries>
<Style TargetType="{x:Type s:ZoomBox}">
<Style TargetType="{x:Type dd:ZoomBox}">
<Style.Resources>
@@ -165,7 +165,7 @@
Value="true" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type s:ZoomBox}">
<ControlTemplate TargetType="{x:Type dd:ZoomBox}">
<Border CornerRadius="1"
BorderThickness="1"
Background="#EEE"

View File

@@ -1,12 +1,12 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:s="clr-namespace:AIStudio.Wpf.DiagramDesigner"
xmlns:dd="clr-namespace:AIStudio.Wpf.DiagramDesigner"
xmlns:c="clr-namespace:AIStudio.Wpf.DiagramDesigner.Controls">
<s:ColorBrushConverter x:Key="ColorBrushConverter" />
<s:ConectorOrientationConverter x:Key="ConectorOrientationConverter" />
<s:ConectorValueConverter x:Key="ConectorValueConverter"/>
<dd:ColorBrushConverter x:Key="ColorBrushConverter" />
<dd:ConectorOrientationConverter x:Key="ConectorOrientationConverter" />
<dd:ConectorValueConverter x:Key="ConectorValueConverter"/>
<DataTemplate DataType="{x:Type s:FullyCreatedConnectorInfo}">
<DataTemplate DataType="{x:Type dd:FullyCreatedConnectorInfo}">
<Grid Width="{Binding ConnectorWidth}" Height="{Binding ConnectorHeight}">
<Grid.ContextMenu>
<ContextMenu ItemsSource="{Binding MenuOptions}" >
@@ -29,7 +29,7 @@
</Grid>
</DataTemplate>
<DataTemplate DataType="{x:Type s:LogicalConnectorInfo}">
<DataTemplate DataType="{x:Type dd:LogicalConnectorInfo}">
<Grid>
<Grid Width="{Binding ConnectorWidth}" Height="{Binding ConnectorHeight}" HorizontalAlignment="Left" VerticalAlignment="Top">
<Grid.ContextMenu>

View File

@@ -1,36 +1,36 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:s="clr-namespace:AIStudio.Wpf.DiagramDesigner"
xmlns:dd="clr-namespace:AIStudio.Wpf.DiagramDesigner"
xmlns:c="clr-namespace:AIStudio.Wpf.DiagramDesigner.Controls"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:gif="http://wpfanimatedgif.codeplex.com" >
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
<s:ColorBrushConverter x:Key="ColorBrushConverter" />
<s:ConectorOrientationConverter x:Key="ConectorOrientationConverter" />
<s:ConectorValueConverter x:Key="ConectorValueConverter"/>
<s:ArrowPathConverter x:Key="ArrowPathConverter"/>
<s:ArrowSizeConverter x:Key="ArrowSizeConverter"/>
<s:LineDashConverter x:Key="LineDashConverter"/>
<s:ClipConverter x:Key="ClipConverter"/>
<dd:ColorBrushConverter x:Key="ColorBrushConverter" />
<dd:ConectorOrientationConverter x:Key="ConectorOrientationConverter" />
<dd:ConectorValueConverter x:Key="ConectorValueConverter"/>
<dd:ArrowPathConverter x:Key="ArrowPathConverter"/>
<dd:ArrowSizeConverter x:Key="ArrowSizeConverter"/>
<dd:LineDashConverter x:Key="LineDashConverter"/>
<dd:ClipConverter x:Key="ClipConverter"/>
<DataTemplate DataType="{x:Type s:DefaultDesignerItemViewModel}">
<DataTemplate DataType="{x:Type dd:DefaultDesignerItemViewModel}">
<Grid IsHitTestVisible="False">
<Rectangle StrokeThickness="1" Fill="{Binding ColorViewModel.FillColor,Converter={StaticResource ColorBrushConverter}}" Stroke="{Binding ColorViewModel.LineColor,Converter={StaticResource ColorBrushConverter}}" />
</Grid>
</DataTemplate>
<DataTemplate DataType="{x:Type s:TextDesignerItemViewModel}">
<DataTemplate DataType="{x:Type dd:TextDesignerItemViewModel}">
<Grid >
<Border Background="{Binding ColorViewModel.FillColor,Converter={StaticResource ColorBrushConverter}}" IsHitTestVisible="False"/>
<Grid Margin="5">
<s:TextControl s:ControlAttachProperty.Watermark="{Binding Watermark}" />
<dd:TextControl dd:ControlAttachProperty.Watermark="{Binding Watermark}" />
</Grid>
</Grid>
</DataTemplate>
<DataTemplate DataType="{x:Type s:ShapeDesignerItemViewModel}">
<DataTemplate DataType="{x:Type dd:ShapeDesignerItemViewModel}">
<Grid IsHitTestVisible="False" Background="White">
<Grid.ContextMenu>
<ContextMenu>
@@ -84,7 +84,7 @@
<Setter.Value>
<ControlTemplate>
<Polyline
Points="{Binding ConnectionPoints, Converter={x:Static s:ConnectionPointConverter.Instance}}"
Points="{Binding ConnectionPoints, Converter={x:Static dd:ConnectionPointConverter.Instance}}"
Stroke="{Binding ColorViewModel.LineColor,Converter={StaticResource ColorBrushConverter}}"
StrokeThickness="{Binding ColorViewModel.LineWidth}"
Fill="{Binding ColorViewModel.FillColor,Converter={StaticResource ColorBrushConverter}}"
@@ -99,7 +99,7 @@
<Setter.Value>
<ControlTemplate>
<Polygon
Points="{Binding ConnectionPoints, Converter={x:Static s:ConnectionPointConverter.Instance}}"
Points="{Binding ConnectionPoints, Converter={x:Static dd:ConnectionPointConverter.Instance}}"
Stroke="{Binding ColorViewModel.LineColor,Converter={StaticResource ColorBrushConverter}}"
StrokeThickness="{Binding ColorViewModel.LineWidth}"
Fill="{Binding ColorViewModel.FillColor,Converter={StaticResource ColorBrushConverter}}"
@@ -114,7 +114,7 @@
<Setter.Value>
<ControlTemplate>
<Polyline
Points="{Binding ConnectionPoints, Converter={x:Static s:ConnectionPointConverter.Instance}}"
Points="{Binding ConnectionPoints, Converter={x:Static dd:ConnectionPointConverter.Instance}}"
Stroke="{Binding ColorViewModel.LineColor,Converter={StaticResource ColorBrushConverter}}"
StrokeThickness="{Binding ColorViewModel.LineWidth}"
Fill="{Binding ColorViewModel.FillColor,Converter={StaticResource ColorBrushConverter}}"
@@ -129,13 +129,13 @@
</DataTemplate.Triggers>
</DataTemplate>
<DataTemplate DataType="{x:Type s:GroupDesignerItemViewModel}">
<DataTemplate DataType="{x:Type dd:GroupDesignerItemViewModel}">
<Grid IsHitTestVisible="False">
</Grid>
</DataTemplate>
<DataTemplate DataType="{x:Type s:GifImageItemViewModel}">
<DataTemplate DataType="{x:Type dd:GifImageItemViewModel}">
<Grid IsHitTestVisible="False">
<Image Name="PART_Image_run" gif:ImageBehavior.AnimatedSource="{Binding Icon}" gif:ImageBehavior.AutoStart="True" VerticalAlignment="Center" HorizontalAlignment="Center" Visibility="Visible"/>
<Control x:Name="control" />
@@ -147,13 +147,13 @@
</DataTemplate.Triggers>
</DataTemplate>
<DataTemplate DataType="{x:Type s:VideoItemViewModel}">
<DataTemplate DataType="{x:Type dd:VideoItemViewModel}">
<Grid IsHitTestVisible="False">
<MediaElement x:Name="MediaPlayer" LoadedBehavior="Play" Source="{Binding Icon}" VerticalAlignment="Center" HorizontalAlignment="Center" Visibility="Visible"/>
</Grid>
</DataTemplate>
<DataTemplate DataType="{x:Type s:ImageItemViewModel}">
<DataTemplate DataType="{x:Type dd:ImageItemViewModel}">
<Grid ToolTip="{Binding Icon}">
<Grid IsHitTestVisible="False" ClipToBounds="True">
<Image x:Name="image" Source="{Binding Icon}" Stretch="Fill"

View File

@@ -1,10 +1,5 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:s="clr-namespace:AIStudio.Wpf.DiagramDesigner"
xmlns:c="clr-namespace:AIStudio.Wpf.DiagramDesigner.Controls"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:gif="http://wpfanimatedgif.codeplex.com" >
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/AIStudio.Wpf.DiagramDesigner;component/Themes/DesignerItem.xaml" />

View File

@@ -1,7 +1,6 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/AIStudio.Wpf.DiagramDesigner;component/Styles/Button.xaml" />
<ResourceDictionary Source="pack://application:,,,/AIStudio.Wpf.DiagramDesigner;component/Styles/ScrollBar.xaml" />
<ResourceDictionary Source="pack://application:,,,/AIStudio.Wpf.DiagramDesigner;component/Styles/Expander.xaml" />
<ResourceDictionary Source="pack://application:,,,/AIStudio.Wpf.DiagramDesigner;component/Styles/GroupBox.xaml" />

View File

@@ -3,7 +3,7 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:s="clr-namespace:AIStudio.Wpf.DiagramDesigner"
xmlns:dd="clr-namespace:AIStudio.Wpf.DiagramDesigner"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<ItemsControl.ItemsPanel>

View File

@@ -3,7 +3,7 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:s="clr-namespace:AIStudio.Wpf.DiagramDesigner"
xmlns:dd="clr-namespace:AIStudio.Wpf.DiagramDesigner"
xmlns:c="clr-namespace:AIStudio.Wpf.DiagramDesigner.Controls"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
@@ -15,16 +15,16 @@
<ResourceDictionary Source="/AIStudio.Wpf.DiagramDesigner;component/Themes/Generic.xaml" />
</ResourceDictionary.MergedDictionaries>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
<s:ColorBrushConverter x:Key="ColorBrushConverter" />
<s:ConectorOrientationConverter x:Key="ConectorOrientationConverter" />
<s:ConectorValueConverter x:Key="ConectorValueConverter"/>
<s:ArrowPathConverter x:Key="ArrowPathConverter"/>
<s:ArrowSizeConverter x:Key="ArrowSizeConverter"/>
<s:LineDashConverter x:Key="LineDashConverter"/>
<s:ClipConverter x:Key="ClipConverter"/>
<s:InvertBoolConverter x:Key="InvertBoolConverter"/>
<s:ConectorStyleConverter x:Key="ConectorStyleConverter"/>
<s:NotNullOrEmptyToBoolConverter x:Key="NotNullOrEmptyToBoolConverter"/>
<dd:ColorBrushConverter x:Key="ColorBrushConverter" />
<dd:ConectorOrientationConverter x:Key="ConectorOrientationConverter" />
<dd:ConectorValueConverter x:Key="ConectorValueConverter"/>
<dd:ArrowPathConverter x:Key="ArrowPathConverter"/>
<dd:ArrowSizeConverter x:Key="ArrowSizeConverter"/>
<dd:LineDashConverter x:Key="LineDashConverter"/>
<dd:ClipConverter x:Key="ClipConverter"/>
<dd:InvertBoolConverter x:Key="InvertBoolConverter"/>
<dd:ConectorStyleConverter x:Key="ConectorStyleConverter"/>
<dd:NotNullOrEmptyToBoolConverter x:Key="NotNullOrEmptyToBoolConverter"/>
<!-- ResizeDecorator Default Template -->
<!--
@@ -145,7 +145,7 @@
<ObjectDataProvider x:Key="ConnectorOrientationMenu" MethodName="GetValues" ObjectType="{x:Type sys:Enum}">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="s:ConnectorOrientation" />
<x:Type TypeName="dd:ConnectorOrientation" />
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
@@ -157,11 +157,11 @@
</Style>
<!-- Connector Style -->
<Style x:Key="PointConnectorStyle" TargetType="{x:Type s:PointConnector}">
<Style x:Key="PointConnectorStyle" TargetType="{x:Type dd:PointConnector}">
<Setter Property="SnapsToDevicePixels" Value="true" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type s:PointConnector}">
<ControlTemplate TargetType="{x:Type dd:PointConnector}">
<Grid Width="{Binding ConnectorWidth}" Height="{Binding ConnectorHeight}">
<!-- transparent extra space makes connector easier to hit -->
<Ellipse Fill="Transparent" Margin="-2" />
@@ -172,7 +172,7 @@
</Setter>
</Style>
<Style x:Key="GifImageConnectorContainer" TargetType="{x:Type s:ConnectorContainer}">
<Style x:Key="GifImageConnectorContainer" TargetType="{x:Type dd:ConnectorContainer}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ItemsControl}">
@@ -182,7 +182,7 @@
</Border>
<Rectangle Fill="#7F243859" Opacity="0.5" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Visibility="{Binding ShouldInsertAnchor, Converter={StaticResource BooleanToVisibilityConverter}}">
<i:Interaction.Behaviors>
<s:ControlMouseLeftButtonDownCommandBehavior Command="{Binding AddItemCommand}" />
<dd:ControlMouseLeftButtonDownCommandBehavior Command="{Binding AddItemCommand}" />
</i:Interaction.Behaviors>
</Rectangle>
</Grid>
@@ -208,87 +208,87 @@
<ControlTemplate x:Key="ConnectorDecoratorTemplate"
TargetType="{x:Type Control}">
<Grid Margin="-5">
<s:Connector
<dd:Connector
Content="{Binding LeftConnector}"
Cursor="Cross"
SnapsToDevicePixels="True"
Orientation="Left"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Visibility="{Binding Path=ShowConnectors, Converter={x:Static s:BoolToVisibilityConverter.Instance}}" />
<s:Connector
Visibility="{Binding Path=ShowConnectors, Converter={x:Static dd:BoolToVisibilityConverter.Instance}}" />
<dd:Connector
Content="{Binding TopLeftConnector}"
Cursor="Cross"
SnapsToDevicePixels="True"
Orientation="TopLeft"
VerticalAlignment="Top"
HorizontalAlignment="Left"
Visibility="{Binding Path=ShowConnectors, Converter={x:Static s:BoolToVisibilityConverter.Instance}}" />
<s:Connector
Visibility="{Binding Path=ShowConnectors, Converter={x:Static dd:BoolToVisibilityConverter.Instance}}" />
<dd:Connector
Content="{Binding TopConnector}"
Cursor="Cross"
SnapsToDevicePixels="True"
Orientation="Top"
VerticalAlignment="Top"
HorizontalAlignment="Center"
Visibility="{Binding Path=ShowConnectors, Converter={x:Static s:BoolToVisibilityConverter.Instance}}" />
<s:Connector
Visibility="{Binding Path=ShowConnectors, Converter={x:Static dd:BoolToVisibilityConverter.Instance}}" />
<dd:Connector
Content="{Binding TopRightConnector}"
Cursor="Cross"
SnapsToDevicePixels="True"
Orientation="TopRight"
VerticalAlignment="Top"
HorizontalAlignment="Right"
Visibility="{Binding Path=ShowConnectors, Converter={x:Static s:BoolToVisibilityConverter.Instance}}" />
<s:Connector
Visibility="{Binding Path=ShowConnectors, Converter={x:Static dd:BoolToVisibilityConverter.Instance}}" />
<dd:Connector
Content="{Binding RightConnector}"
Cursor="Cross"
SnapsToDevicePixels="True"
Orientation="Right"
VerticalAlignment="Center"
HorizontalAlignment="Right"
Visibility="{Binding Path=ShowConnectors, Converter={x:Static s:BoolToVisibilityConverter.Instance}}" />
<s:Connector
Visibility="{Binding Path=ShowConnectors, Converter={x:Static dd:BoolToVisibilityConverter.Instance}}" />
<dd:Connector
Content="{Binding BottomRightConnector}"
Cursor="Cross"
SnapsToDevicePixels="True"
Orientation="BottomRight"
VerticalAlignment="Bottom"
HorizontalAlignment="Right"
Visibility="{Binding Path=ShowConnectors, Converter={x:Static s:BoolToVisibilityConverter.Instance}}" />
<s:Connector
Visibility="{Binding Path=ShowConnectors, Converter={x:Static dd:BoolToVisibilityConverter.Instance}}" />
<dd:Connector
Content="{Binding BottomConnector}"
Cursor="Cross"
SnapsToDevicePixels="True"
Orientation="Bottom"
VerticalAlignment="Bottom"
HorizontalAlignment="Center"
Visibility="{Binding Path=ShowConnectors, Converter={x:Static s:BoolToVisibilityConverter.Instance}}" />
<s:Connector
Visibility="{Binding Path=ShowConnectors, Converter={x:Static dd:BoolToVisibilityConverter.Instance}}" />
<dd:Connector
Content="{Binding BottomLeftConnector}"
Cursor="Cross"
SnapsToDevicePixels="True"
Orientation="BottomLeft"
VerticalAlignment="Bottom"
HorizontalAlignment="Left"
Visibility="{Binding Path=ShowConnectors, Converter={x:Static s:BoolToVisibilityConverter.Instance}}" />
Visibility="{Binding Path=ShowConnectors, Converter={x:Static dd:BoolToVisibilityConverter.Instance}}" />
</Grid>
</ControlTemplate>
<ControlTemplate x:Key="InnerConnectorDecoratorTemplate"
TargetType="{x:Type Control}">
<s:ConnectorContainer x:Name="PART_ConnectorContainer" Style="{StaticResource ItemsControlStyle}" ItemsSource="{Binding Connectors}" Visibility="{Binding Path=ShowConnectors, Converter={x:Static s:BoolToVisibilityConverter.Instance}}">
<s:ConnectorContainer.ItemTemplate>
<dd:ConnectorContainer x:Name="PART_ConnectorContainer" Style="{StaticResource ItemsControlStyle}" ItemsSource="{Binding Connectors}" Visibility="{Binding Path=ShowConnectors, Converter={x:Static dd:BoolToVisibilityConverter.Instance}}">
<dd:ConnectorContainer.ItemTemplate>
<DataTemplate>
<Grid>
<s:Connector
<dd:Connector
Content="{Binding .}"
Cursor="Cross"
SnapsToDevicePixels="True"/>
</Grid>
</DataTemplate>
</s:ConnectorContainer.ItemTemplate>
</s:ConnectorContainer>
</dd:ConnectorContainer.ItemTemplate>
</dd:ConnectorContainer>
</ControlTemplate>
<!--基础类型-->
@@ -300,9 +300,9 @@
Value="{Binding Top}" />
<Setter Property="Canvas.ZIndex"
Value="{Binding ZIndex}" />
<Setter Property="s:SelectionProps.EnabledForSelection"
<Setter Property="dd:SelectionProps.EnabledForSelection"
Value="{Binding EnabledForSelection}" />
<Setter Property="s:ItemConnectProps.EnabledForConnection"
<Setter Property="dd:ItemConnectProps.EnabledForConnection"
Value="{Binding EnabledForConnection}" />
<Setter Property="Visibility"
Value="{Binding Visible,Converter={StaticResource BooleanToVisibilityConverter}}"/>
@@ -368,7 +368,7 @@
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<s:TextControl x:Name="PART_Text" />
<dd:TextControl x:Name="PART_Text" />
</ControlTemplate>
</Setter.Value>
</Setter>
@@ -377,7 +377,7 @@
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<s:TextControl x:Name="PART_Text" />
<dd:TextControl x:Name="PART_Text" />
</ControlTemplate>
</Setter.Value>
</Setter>
@@ -459,7 +459,7 @@
Value="{Binding Area.Left}" />
<Setter Property="Canvas.ZIndex"
Value="{Binding ZIndex}" />
<Setter Property="s:SelectionProps.EnabledForSelection"
<Setter Property="dd:SelectionProps.EnabledForSelection"
Value="{Binding EnabledForSelection}" />
<Setter Property="Visibility"
Value="{Binding Visible,Converter={StaticResource BooleanToVisibilityConverter}}"/>
@@ -475,11 +475,11 @@
<ContextMenu>
<MenuItem Header="删除" Command="{Binding DeleteConnectionCommand}" CommandParameter="{Binding}"/>
<MenuItem Header="添加文本" Command="{Binding AddLabelCommand}" CommandParameter="{Binding}"/>
<MenuItem Header="插入点(按住ctrl可一直插入)" IsCheckable="True" IsChecked="{Binding ShouldInsertAnchor}" IsEnabled="{Binding IsReadOnly,Converter={s:InvertBoolConverter}}" />
<MenuItem Header="插入点(按住ctrl可一直插入)" IsCheckable="True" IsChecked="{Binding ShouldInsertAnchor}" IsEnabled="{Binding IsReadOnly,Converter={dd:InvertBoolConverter}}" />
</ContextMenu>
</Grid.ContextMenu>
<s:LineControl x:Name="line"/>
<dd:LineControl x:Name="line"/>
<!-- PART_DragThumb -->
<c:DragThumb x:Name="PART_DragThumb" Margin="8"
@@ -489,8 +489,8 @@
</c:DragThumb.InputBindings>
</c:DragThumb>
<s:PointContainer x:Name="PART_VerticesContainer" Style="{StaticResource ItemsControlStyle}" ItemsSource="{Binding Vertices}" Visibility="Collapsed">
<s:PointContainer.ItemTemplate>
<dd:PointContainer x:Name="PART_VerticesContainer" Style="{StaticResource ItemsControlStyle}" ItemsSource="{Binding Vertices}" Visibility="Collapsed">
<dd:PointContainer.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ContextMenu>
@@ -498,23 +498,23 @@
<MenuItem Header="删除" Command="{Binding DeleteVertexCommand}" CommandParameter="{Binding}"/>
</ContextMenu>
</Grid.ContextMenu>
<s:PointConnector Style="{StaticResource PointConnectorStyle}"/>
<dd:PointConnector Style="{StaticResource PointConnectorStyle}"/>
<c:PointDragThumb Cursor="SizeAll" Opacity="0"/>
</Grid>
</DataTemplate>
</s:PointContainer.ItemTemplate>
<s:PointContainer.Resources>
</dd:PointContainer.ItemTemplate>
<dd:PointContainer.Resources>
<Style TargetType="{x:Type ContentPresenter}">
<Setter Property="Canvas.Left" Value="{Binding Left}" />
<Setter Property="Canvas.Top" Value="{Binding Top}" />
</Style>
</s:PointContainer.Resources>
</s:PointContainer>
</dd:PointContainer.Resources>
</dd:PointContainer>
<s:PointContainer x:Name="PART_LabelsContainer" Style="{StaticResource ItemsControlStyle}" ItemsSource="{Binding Labels}" >
<s:PointContainer.ItemTemplate>
<dd:PointContainer x:Name="PART_LabelsContainer" Style="{StaticResource ItemsControlStyle}" ItemsSource="{Binding Labels}" >
<dd:PointContainer.ItemTemplate>
<DataTemplate>
<Grid s:SelectionProps.EnabledForSelection="True" Background="{Binding ColorViewModel.FillColor,Converter={StaticResource ColorBrushConverter}}">
<Grid dd:SelectionProps.EnabledForSelection="True" Background="{Binding ColorViewModel.FillColor,Converter={StaticResource ColorBrushConverter}}">
<Grid.ContextMenu>
<ContextMenu>
<MenuItem Header="删除" Command="{Binding DeleteLabelCommand}" CommandParameter="{Binding}"/>
@@ -525,21 +525,21 @@
<MouseBinding MouseAction="LeftDoubleClick" Command="{Binding EditCommand}" CommandParameter="{Binding }" />
</c:PointDragThumb.InputBindings>
</c:PointDragThumb>
<s:TextControl Margin="5" />
<dd:TextControl Margin="5" />
</Grid>
</DataTemplate>
</s:PointContainer.ItemTemplate>
<s:PointContainer.Resources>
</dd:PointContainer.ItemTemplate>
<dd:PointContainer.Resources>
<Style TargetType="{x:Type ContentPresenter}">
<Setter Property="Canvas.Left" Value="{Binding Left}" />
<Setter Property="Canvas.Top" Value="{Binding Top}" />
</Style>
</s:PointContainer.Resources>
</s:PointContainer>
</dd:PointContainer.Resources>
</dd:PointContainer>
<Rectangle Fill="#7F243859" Opacity="0.5" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Visibility="{Binding ShouldInsertAnchor, Converter={StaticResource BooleanToVisibilityConverter}}">
<i:Interaction.Behaviors>
<s:ControlMouseLeftButtonDownCommandBehavior Command="{Binding AddVertexCommand}" />
<dd:ControlMouseLeftButtonDownCommandBehavior Command="{Binding AddVertexCommand}" />
</i:Interaction.Behaviors>
</Rectangle>
</Grid>
@@ -572,9 +572,9 @@
Value="{Binding Left}" />
<Setter Property="Canvas.ZIndex"
Value="{Binding ZIndex}" />
<Setter Property="s:SelectionProps.EnabledForSelection"
<Setter Property="dd:SelectionProps.EnabledForSelection"
Value="{Binding EnabledForSelection}" />
<Setter Property="s:ItemConnectProps.EnabledForConnection"
<Setter Property="dd:ItemConnectProps.EnabledForConnection"
Value="{Binding EnabledForConnection}" />
<Setter Property="Visibility"
Value="{Binding Visible,Converter={StaticResource BooleanToVisibilityConverter}}"/>
@@ -608,13 +608,13 @@
VerticalAlignment="Stretch"
Content="{TemplateBinding Content}" />
<!-- PART_ConnectorDecorator -->
<s:ConnectorContainer x:Name="PART_ConnectorContainer" Visibility="Hidden" Style="{StaticResource GifImageConnectorContainer}" ItemsSource="{Binding Connectors}">
<s:ConnectorContainer.ItemTemplate>
<dd:ConnectorContainer x:Name="PART_ConnectorContainer" Visibility="Hidden" Style="{StaticResource GifImageConnectorContainer}" ItemsSource="{Binding Connectors}">
<dd:ConnectorContainer.ItemTemplate>
<DataTemplate>
<s:Connector Content="{Binding .}" Cursor="Cross" SnapsToDevicePixels="True"/>
<dd:Connector Content="{Binding .}" Cursor="Cross" SnapsToDevicePixels="True"/>
</DataTemplate>
</s:ConnectorContainer.ItemTemplate>
</s:ConnectorContainer>
</dd:ConnectorContainer.ItemTemplate>
</dd:ConnectorContainer>
<Grid.RenderTransform>
<TransformGroup>
<RotateTransform Angle="{Binding Angle}" />
@@ -652,9 +652,9 @@
Value="{Binding Left}" />
<Setter Property="Canvas.ZIndex"
Value="{Binding ZIndex}" />
<Setter Property="s:SelectionProps.EnabledForSelection"
<Setter Property="dd:SelectionProps.EnabledForSelection"
Value="{Binding EnabledForSelection}" />
<Setter Property="s:ItemConnectProps.EnabledForConnection"
<Setter Property="dd:ItemConnectProps.EnabledForConnection"
Value="{Binding EnabledForConnection}" />
<Setter Property="Visibility"
Value="{Binding Visible,Converter={StaticResource BooleanToVisibilityConverter}}"/>
@@ -685,15 +685,15 @@
</Grid.ContextMenu>
<!--PART_ConnectorDecorator-->
<s:ConnectorContainer x:Name="PART_ConnectorContainer" Style="{StaticResource ItemsControlStyle}" ItemsSource="{Binding Connectors}" Margin="0,0,0,0">
<s:ConnectorContainer.ItemTemplate>
<dd:ConnectorContainer x:Name="PART_ConnectorContainer" Style="{StaticResource ItemsControlStyle}" ItemsSource="{Binding Connectors}" Margin="0,0,0,0">
<dd:ConnectorContainer.ItemTemplate>
<DataTemplate>
<Grid>
<s:Connector Content="{Binding .}" Cursor="Cross" SnapsToDevicePixels="True"/>
<dd:Connector Content="{Binding .}" Cursor="Cross" SnapsToDevicePixels="True"/>
</Grid>
</DataTemplate>
</s:ConnectorContainer.ItemTemplate>
</s:ConnectorContainer>
</dd:ConnectorContainer.ItemTemplate>
</dd:ConnectorContainer>
<!-- PART_DragThumb -->
<c:DragThumb x:Name="PART_DragThumb"
Cursor="SizeAll" >
@@ -733,7 +733,7 @@
Value="{Binding Left}" />
<Setter Property="Canvas.ZIndex"
Value="{Binding ZIndex}" />
<Setter Property="s:SelectionProps.EnabledForSelection"
<Setter Property="dd:SelectionProps.EnabledForSelection"
Value="{Binding EnabledForSelection}" />
<Setter Property="Visibility"
Value="{Binding Visible,Converter={StaticResource BooleanToVisibilityConverter}}"/>
@@ -746,11 +746,11 @@
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Grid x:Name="selectedGrid" Visibility="{Binding Path=ShowConnectors, Converter={x:Static s:BoolToVisibilityConverter.Instance}}">
<Grid x:Name="selectedGrid" Visibility="{Binding Path=ShowConnectors, Converter={x:Static dd:BoolToVisibilityConverter.Instance}}">
<!-- PART_ConnectorDecorator -->
<Grid Margin="-5"
x:Name="PART_ConnectorDecorator">
<s:PointConnector DataContext="{Binding TopConnector}" Style="{StaticResource PointConnectorStyle}"/>
<dd:PointConnector DataContext="{Binding TopConnector}" Style="{StaticResource PointConnectorStyle}"/>
</Grid>
<!-- PART_DragThumb -->
<c:DragThumb x:Name="PART_DragThumb"
@@ -779,9 +779,9 @@
Value="{Binding Left}" />
<Setter Property="Canvas.ZIndex"
Value="{Binding ZIndex}" />
<Setter Property="s:SelectionProps.EnabledForSelection"
<Setter Property="dd:SelectionProps.EnabledForSelection"
Value="{Binding EnabledForSelection}" />
<Setter Property="s:ItemConnectProps.EnabledForConnection"
<Setter Property="dd:ItemConnectProps.EnabledForConnection"
Value="{Binding EnabledForConnection}" />
<Setter Property="Visibility"
Value="{Binding Visible,Converter={StaticResource BooleanToVisibilityConverter}}"/>
@@ -799,12 +799,12 @@
<!-- PART_ConnectorDecorator -->
<Grid Margin="-5"
x:Name="PART_ConnectorDecorator">
<s:Connector Content="{Binding Connectors[0]}"
<dd:Connector Content="{Binding Connectors[0]}"
Cursor="Cross"
SnapsToDevicePixels="True"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Visibility="{Binding Path=ShowConnectors, Converter={x:Static s:BoolToVisibilityConverter.Instance}}" />
Visibility="{Binding Path=ShowConnectors, Converter={x:Static dd:BoolToVisibilityConverter.Instance}}" />
</Grid>
<!-- PART_DragThumb -->
<c:DragThumb x:Name="PART_DragThumb"
@@ -835,10 +835,10 @@
<ControlTemplate>
<Grid>
<ItemsControl ItemsSource="{Binding Items}"
ItemContainerStyleSelector="{x:Static s:DesignerItemsControlItemStyleSelector.Instance}">
ItemContainerStyleSelector="{x:Static dd:DesignerItemsControlItemStyleSelector.Instance}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<s:DesignerCanvas
<dd:DesignerCanvas
Height="{Binding PageSize.Height}"
Width="{Binding PageSize.Width}"
ShowGrid="{Binding ShowGrid}"
@@ -847,10 +847,10 @@
GridColor="{Binding GridColor}"
Background="{Binding PageBackground,Converter={StaticResource ColorBrushConverter}}"
AllowDrop="{Binding AllowDrop}">
<s:DesignerCanvas.LayoutTransform>
<dd:DesignerCanvas.LayoutTransform>
<ScaleTransform ScaleX="{Binding ZoomValue}" ScaleY="{Binding ZoomValue}" />
</s:DesignerCanvas.LayoutTransform>
</s:DesignerCanvas>
</dd:DesignerCanvas.LayoutTransform>
</dd:DesignerCanvas>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
@@ -870,10 +870,10 @@
HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Auto">
<ItemsControl x:Name="diagram" ItemsSource="{Binding Items}"
ItemContainerStyleSelector="{x:Static s:DesignerItemsControlItemStyleSelector.Instance}">
ItemContainerStyleSelector="{x:Static dd:DesignerItemsControlItemStyleSelector.Instance}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<s:DesignerCanvas
<dd:DesignerCanvas
Height="{Binding PageSize.Height}"
Width="{Binding PageSize.Width}"
ShowGrid="{Binding ShowGrid}"
@@ -882,16 +882,16 @@
GridColor="{Binding GridColor}"
Background="{Binding PageBackground,Converter={StaticResource ColorBrushConverter}}"
AllowDrop="{Binding AllowDrop}">
<s:DesignerCanvas.LayoutTransform>
<dd:DesignerCanvas.LayoutTransform>
<ScaleTransform ScaleX="{Binding ZoomValue}" ScaleY="{Binding ZoomValue}" />
</s:DesignerCanvas.LayoutTransform>
</s:DesignerCanvas>
</dd:DesignerCanvas.LayoutTransform>
</dd:DesignerCanvas>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</ScrollViewer>
<s:ZoomBox x:Name="zoomBox"
<dd:ZoomBox x:Name="zoomBox"
Width="180"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"

View File

@@ -3,15 +3,15 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:s="clr-namespace:AIStudio.Wpf.DiagramDesigner"
xmlns:dd="clr-namespace:AIStudio.Wpf.DiagramDesigner"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.Resources>
<s:ColorBrushConverter x:Key="ColorBrushConverter" />
<s:LineDashConverter x:Key="LineDashConverter"/>
<s:ArrowPathConverter x:Key="ArrowPathConverter"/>
<s:ArrowSizeConverter x:Key="ArrowSizeConverter"/>
<s:MathConverter x:Key="MathAddConverter" Operation="Add" />
<dd:ColorBrushConverter x:Key="ColorBrushConverter" />
<dd:LineDashConverter x:Key="LineDashConverter"/>
<dd:ArrowPathConverter x:Key="ArrowPathConverter"/>
<dd:ArrowSizeConverter x:Key="ArrowSizeConverter"/>
<dd:MathConverter x:Key="MathAddConverter" Operation="Add" />
<Style x:Key="LineStyle" TargetType="Path">
<Setter Property="Stroke" Value="{Binding ColorViewModel.LineColor,Converter={StaticResource ColorBrushConverter}}"/>
<Style.Triggers>
@@ -40,7 +40,7 @@
StrokeStartLineCap="Round"
StrokeEndLineCap="Round">
<Path.Data>
<MultiBinding Converter="{x:Static s:ConnectionPathConverter.Instance}">
<MultiBinding Converter="{x:Static dd:ConnectionPathConverter.Instance}">
<Binding Path="PathGeneratorResult"/>
</MultiBinding>
</Path.Data>

View File

@@ -3,7 +3,7 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:s="clr-namespace:AIStudio.Wpf.DiagramDesigner"
xmlns:dd="clr-namespace:AIStudio.Wpf.DiagramDesigner"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.Resources>
@@ -11,8 +11,8 @@
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/AIStudio.Wpf.DiagramDesigner;component/Styles/TextBox.xaml" />
<ResourceDictionary>
<s:ColorBrushConverter x:Key="ColorBrushConverter" />
<s:TrueToFalseConverter x:Key="TrueToFalseConverter"/>
<dd:ColorBrushConverter x:Key="ColorBrushConverter" />
<dd:TrueToFalseConverter x:Key="TrueToFalseConverter"/>
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
@@ -32,7 +32,7 @@
TextBlock.LineHeight="{Binding FontViewModel.LineHeight}"
AcceptsReturn="True"
IsHitTestVisible="False"
s:ControlAttachProperty.Watermark="{Binding Path=(s:ControlAttachProperty.Watermark),RelativeSource={RelativeSource AncestorType={x:Type s:TextControl}}}"
dd:ControlAttachProperty.Watermark="{Binding Path=(dd:ControlAttachProperty.Watermark),RelativeSource={RelativeSource AncestorType={x:Type dd:TextControl}}}"
Style="{StaticResource WaterTextBoxWithEffect}" IsReadOnly="True">
</TextBox>
@@ -50,7 +50,7 @@
VerticalContentAlignment="{Binding FontViewModel.VerticalAlignment}"
TextBlock.LineHeight="{Binding FontViewModel.LineHeight}"
AcceptsReturn="True"
s:ControlAttachProperty.Watermark="{Binding Path=(s:ControlAttachProperty.Watermark),RelativeSource={RelativeSource AncestorType={x:Type s:TextControl}}}"
dd:ControlAttachProperty.Watermark="{Binding Path=(dd:ControlAttachProperty.Watermark),RelativeSource={RelativeSource AncestorType={x:Type dd:TextControl}}}"
Style="{StaticResource WaterTextBoxWithEffect}" Visibility="Collapsed">
</TextBox>

View File

@@ -40,13 +40,14 @@ namespace AIStudio.Wpf.DiagramDesigner
{
this.Loaded -= TextControl_Loaded;
PART_ShowText.Visibility = Visibility.Visible;
PART_TextBlock.Visibility = Visibility.Collapsed;
PART_ShowText.Focus();
if (!string.IsNullOrEmpty(PART_ShowText.Text))
{
PART_ShowText.SelectionStart = PART_ShowText.Text.Length;
}
//新建后处于编辑状态,暂时关闭
//PART_ShowText.Visibility = Visibility.Visible;
//PART_TextBlock.Visibility = Visibility.Collapsed;
//PART_ShowText.Focus();
//if (!string.IsNullOrEmpty(PART_ShowText.Text))
//{
// PART_ShowText.SelectionStart = PART_ShowText.Text.Length;
//}
if (this.DataContext is ISelectable selectable)
{
@@ -74,6 +75,7 @@ namespace AIStudio.Wpf.DiagramDesigner
{
PART_ShowText.Visibility = Visibility.Collapsed;
PART_TextBlock.Visibility = Visibility.Visible;
selectable.IsEditing = false;
}
}
}

View File

@@ -448,14 +448,20 @@ namespace AIStudio.Wpf.DiagramDesigner
}
break;
case nameof(SourceConnectorInfo):
SourceA = PointHelper.GetPointForConnector(SourceConnectorInfo);
SourceConnectorInfo.DataItem.PropertyChanged += new WeakINPCEventHandler(ConnectorViewModel_PropertyChanged).Handler;
if (SourceConnectorInfo != null)
{
SourceA = PointHelper.GetPointForConnector(SourceConnectorInfo);
SourceConnectorInfo.DataItem.PropertyChanged += new WeakINPCEventHandler(ConnectorViewModel_PropertyChanged).Handler;
}
break;
case nameof(SinkConnectorInfo):
SourceB = SinkConnectorInfo.Position;
if (SinkConnectorInfo is FullyCreatedConnectorInfo)
if (SinkConnectorInfo != null)
{
SinkConnectorInfoFully.DataItem.PropertyChanged += new WeakINPCEventHandler(ConnectorViewModel_PropertyChanged).Handler;
SourceB = SinkConnectorInfo.Position;
if (IsFullConnection)
{
SinkConnectorInfoFully.DataItem.PropertyChanged += new WeakINPCEventHandler(ConnectorViewModel_PropertyChanged).Handler;
}
}
break;
case nameof(IsSelected):

View File

@@ -26,6 +26,14 @@ namespace AIStudio.Wpf.DiagramDesigner
}
}
public SelectableDesignerItemViewModelBase SelectedItem
{
get
{
return SelectedItems.FirstOrDefault();
}
}
private SelectionService selectionService;
public SelectionService SelectionService
{
@@ -646,6 +654,11 @@ namespace AIStudio.Wpf.DiagramDesigner
get; private set;
}
public SimpleCommand SelectItemCommand
{
get; private set;
}
public SimpleCommand CopyCommand
{
get; private set;
@@ -723,6 +736,11 @@ namespace AIStudio.Wpf.DiagramDesigner
get; private set;
}
public SimpleCommand EditCommand
{
get; private set;
}
private SimpleCommand _undoCommand;
public SimpleCommand UndoCommand
{
@@ -742,7 +760,7 @@ namespace AIStudio.Wpf.DiagramDesigner
}
#endregion
private DoCommandManager DoCommandManager = new DoCommandManager();
public DoCommandManager DoCommandManager = new DoCommandManager();
public event DiagramEventHandler Event;
@@ -770,6 +788,7 @@ namespace AIStudio.Wpf.DiagramDesigner
DistributeHorizontalCommand = new SimpleCommand(ExecuteEnable, ExecuteDistributeHorizontalCommand);
DistributeVerticalCommand = new SimpleCommand(ExecuteEnable, ExecuteDistributeVerticalCommand);
SelectAllCommand = new SimpleCommand(ExecuteEnable, ExecuteSelectAllCommand);
SelectItemCommand = new SimpleCommand(ExecuteEnable, ExecuteSelectItemCommand);
CopyCommand = new SimpleCommand(ExecuteEnable, ExecuteCopyCommand);
PasteCommand = new SimpleCommand(ExecuteEnable, ExecutePasteCommand);
CutCommand = new SimpleCommand(ExecuteEnable, ExecuteCutCommand);
@@ -787,6 +806,7 @@ namespace AIStudio.Wpf.DiagramDesigner
UngroupCommand = new SimpleCommand(ExecuteEnable, ExecuteUngroupCommand);
LockCommand = new SimpleCommand(ExecuteEnable, ExecuteLockCommand);
UnlockCommand = new SimpleCommand(ExecuteEnable, ExecuteUnlockCommand);
EditCommand = new SimpleCommand(ExecuteEnable, ExecuteEditCommand);
Mediator.Instance.Register(this);
Items.CollectionChanged += Items_CollectionChanged;
@@ -815,7 +835,7 @@ namespace AIStudio.Wpf.DiagramDesigner
AllowDrop = diagramItem.AllowDrop;
}
public bool ExecuteEnable(object para)
public virtual bool ExecuteEnable(object para)
{
return IsReadOnly == false;
}
@@ -832,7 +852,7 @@ namespace AIStudio.Wpf.DiagramDesigner
sender.SetPropertyValue(propertyName, oldvalue);
}
private bool _undoing;
private void UndoExecuted(object para)
{
Undo(para);
@@ -845,11 +865,9 @@ namespace AIStudio.Wpf.DiagramDesigner
{
return false;
}
_undoing = true;
DoCommandManager.UnDo();
_undoing = false;
return true;
}
@@ -865,10 +883,7 @@ namespace AIStudio.Wpf.DiagramDesigner
{
return false;
}
_undoing = true;
DoCommandManager.ReDo();
_undoing = false;
return true;
}
@@ -909,8 +924,6 @@ namespace AIStudio.Wpf.DiagramDesigner
{
RaisePropertyChanged(sender, e.PropertyName);
if (_undoing == true) return;
//连续改变需要特殊处理不单独触发属性改变ReDo
if (sender is DesignerItemViewModelBase designer)
{
@@ -1121,6 +1134,14 @@ namespace AIStudio.Wpf.DiagramDesigner
item.IsSelected = true;
}
}
public void ExecuteSelectItemCommand(object parameter)
{
if (parameter is ISelectable selectable)
{
selectable.IsSelected = true;
}
}
#endregion
#region
@@ -2259,5 +2280,19 @@ namespace AIStudio.Wpf.DiagramDesigner
{
}
protected virtual void ExecuteEditCommand(object parameter)
{
if (parameter is SelectableDesignerItemViewModelBase designerItem)
{
designerItem.ShowText = true;
}
else
{
if (SelectedItem != null)
SelectedItem.ShowText = true;
}
}
}
}

View File

@@ -18,6 +18,10 @@ namespace AIStudio.Wpf.DiagramDesigner
{
get;
}
SelectableDesignerItemViewModelBase SelectedItem
{
get;
}
ObservableCollection<SelectableDesignerItemViewModelBase> Items
{
get;
@@ -104,6 +108,10 @@ namespace AIStudio.Wpf.DiagramDesigner
{
get;
}
SimpleCommand SelectItemCommand
{
get;
}
SimpleCommand CopyCommand
{
get;

View File

@@ -119,71 +119,7 @@ namespace AIStudio.Wpf.DiagramModels
private static DiagramItemViewModel ToNodelModel(this DiagramNode diagramNode, IDiagramViewModel diagram)
{
DiagramItemViewModel nodeModel = diagramNode.ToNodel();
//if (diagramNode is FlowchartNode flowchartNode)
//{
// FlowNode flowNode = null;
// switch (flowchartNode.Kind)
// {
// case NodeKinds.Start:
// {
// var flowchartNodelModel = new StartFlowNode();
// flowNode = flowchartNodelModel;
// break;
// }
// case NodeKinds.End:
// {
// var flowchartNodelModel = new EndFlowNode();
// flowNode = flowchartNodelModel;
// break;
// }
// case NodeKinds.Decide:
// {
// var flowchartNodelModel = new DecideFlowNode();
// flowNode = flowchartNodelModel;
// break;
// }
// case NodeKinds.COBegin:
// {
// var flowchartNodelModel = new COBeginFlowNode();
// flowNode = flowchartNodelModel;
// break;
// }
// case NodeKinds.COEnd:
// {
// var flowchartNodelModel = new COEndFlowNode();
// flowNode = flowchartNodelModel;
// break;
// }
// case NodeKinds.Middle:
// {
// var flowchartNodelModel = new MiddleFlowNode();
// flowNode = flowchartNodelModel;
// flowchartNodelModel.UserIds = flowchartNode.UserIds?.ToList();
// flowchartNodelModel.RoleIds = flowchartNode.RoleIds?.ToList();
// flowchartNodelModel.ActType = flowchartNode.ActType;
// break;
// }
// default:
// {
// var flowNodelModel = new FlowNode(NodeKinds.Normal);
// flowNode = flowNodelModel;
// break;
// }
// }
// nodeModel = flowNode;
// flowNode.Name = flowchartNode.Name;
// flowNode.Color = flowchartNode.Color;
// flowNode.Kind = flowchartNode.Kind;
//}
//else
//{
// nodeModel = new TextDesignerItemViewModel();
//}
DiagramItemViewModel nodeModel = diagramNode.ToNodel();
nodeModel.Id = new Guid(diagramNode.Id);
if (!string.IsNullOrEmpty(diagramNode.ParentId))

View File

@@ -0,0 +1,171 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:AIStudio.Wpf.Mind.Controls">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/AIStudio.Wpf.Mind;component/Styles/Button.xaml" />
<ResourceDictionary Source="pack://application:,,,/AIStudio.Wpf.Mind;component/Styles/ContextMenu.xaml" />
</ResourceDictionary.MergedDictionaries>
<Style x:Key="AIStudio.Styles.DropDownButton" TargetType="{x:Type controls:DropDownButton}">
<Setter Property="ArrowBrush" Value="Black" />
<Setter Property="ArrowMouseOverBrush"
Value="{Binding Foreground, RelativeSource={RelativeSource Mode=Self},
Converter={StaticResource BrushOpacityConverter}, ConverterParameter=0.16}" />
<Setter Property="ArrowPressedBrush" Value="Black" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderBrush" Value="Transparent" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="ButtonStyle" Value="{StaticResource FlatButtonStyle}" />
<Setter Property="Focusable" Value="False" />
<Setter Property="Foreground" Value="Black" />
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="MenuStyle" Value="{StaticResource ContextMenuStyle}" />
<Setter Property="MinHeight" Value="26" />
<Setter Property="Padding" Value="3" />
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type controls:DropDownButton}">
<Grid>
<Border x:Name="PART_Border"
Background="Transparent"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="3"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
UseLayoutRounding="True">
<Button x:Name="PART_Button"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Stretch"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
FocusVisualStyle="{TemplateBinding FocusVisualStyle}"
Foreground="{TemplateBinding Foreground}"
RenderOptions.ClearTypeHint="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(RenderOptions.ClearTypeHint), Mode=OneWay}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
Style="{TemplateBinding ButtonStyle}">
<DockPanel x:Name="PART_Content"
Focusable="False"
LastChildFill="True">
<!-- Material - ChevronDown -->
<Path x:Name="PART_Arrow"
Width="9"
Height="6"
Margin="0 0 3 0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Data="M7.41,8.58L12,13.17L16.59,8.58L18,10L12,16L6,10L7.41,8.58Z"
DockPanel.Dock="Right"
Stretch="Fill"
Fill="{TemplateBinding ArrowBrush}"
Visibility="{TemplateBinding ArrowVisibility}" />
<StackPanel x:Name="PART_ContentOrientation"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Focusable="False"
Orientation="Horizontal">
<ContentPresenter HorizontalAlignment="Center"
VerticalAlignment="Center"
Content="{TemplateBinding Icon}"
ContentTemplate="{TemplateBinding IconTemplate}"
Focusable="False"
RecognizesAccessKey="True"
UseLayoutRounding="False" />
<ContentControl x:Name="PART_ButtonContent"
Padding="{TemplateBinding Padding}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
Content="{Binding Content, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
ContentStringFormat="{TemplateBinding ContentStringFormat}"
ContentTemplate="{TemplateBinding ContentTemplate}"
ContentTemplateSelector="{TemplateBinding ContentTemplateSelector}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
UseLayoutRounding="False" />
</StackPanel>
</DockPanel>
<Button.ContextMenu>
<ContextMenu x:Name="PART_Menu"
MinWidth="{TemplateBinding ActualWidth}"
DisplayMemberPath="{TemplateBinding DisplayMemberPath}"
GroupStyleSelector="{TemplateBinding GroupStyleSelector}"
IsOpen="{Binding IsExpanded, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
ItemContainerStyle="{TemplateBinding ItemContainerStyle}"
ItemContainerStyleSelector="{TemplateBinding ItemContainerStyleSelector}"
ItemStringFormat="{TemplateBinding ItemStringFormat}"
ItemTemplate="{TemplateBinding ItemTemplate}"
ItemTemplateSelector="{TemplateBinding ItemTemplateSelector}"
ItemsPanel="{TemplateBinding ItemsPanel}"
ItemsSource="{TemplateBinding ItemsSource}"
Placement="Bottom"
StaysOpen="False"
Style="{TemplateBinding MenuStyle}"
UseLayoutRounding="False" />
</Button.ContextMenu>
</Button>
</Border>
<!--<Popup x:Name="PART_Popup"
Placement="Bottom"
IsOpen="{Binding IsExpanded, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
AllowsTransparency="True"
Margin="0,0,-4,0">
<Border>
<ScrollViewer x:Name="PART_ScrollViewer"
IsTabStop="False"
Margin="1"
SnapsToDevicePixels="True"
VerticalScrollBarVisibility="Auto"
HorizontalScrollBarVisibility="Hidden">
<ItemsPresenter KeyboardNavigation.DirectionalNavigation="Local" />
</ScrollViewer>
</Border>
</Popup>-->
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="Content" Value="{x:Null}">
<Setter TargetName="PART_ButtonContent" Property="Margin" Value="0" />
</Trigger>
<Trigger Property="Orientation" Value="Vertical">
<Setter TargetName="PART_Arrow" Property="DockPanel.Dock" Value="Bottom" />
<Setter TargetName="PART_Arrow" Property="Margin" Value="0 0 0 3" />
<Setter TargetName="PART_ContentOrientation" Property="Orientation" Value="Vertical" />
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsMouseOver" Value="True" />
<Condition SourceName="PART_Button" Property="IsEnabled" Value="True" />
</MultiTrigger.Conditions>
<Setter TargetName="PART_Arrow" Property="Fill" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=ArrowMouseOverBrush, Mode=OneWay}" />
</MultiTrigger>
<Trigger SourceName="PART_Button" Property="IsPressed" Value="True">
<Setter TargetName="PART_Arrow" Property="Fill" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=ArrowPressedBrush, Mode=OneWay}" />
</Trigger>
<Trigger SourceName="PART_Button" Property="IsEnabled" Value="False">
<Setter Property="Opacity" Value=".55" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="VerticalContentAlignment" Value="Center" />
<Style.Triggers>
<Trigger Property="IsFocused" Value="True">
<Setter Property="BorderBrush" Value="LightGray" />
</Trigger>
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter Property="BorderBrush" Value="LightGray" />
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Opacity" Value=".55" />
</Trigger>
</Style.Triggers>
</Style>
<Style TargetType="{x:Type controls:DropDownButton}" BasedOn="{StaticResource AIStudio.Styles.DropDownButton}" />
</ResourceDictionary>

View File

@@ -0,0 +1,685 @@
using System;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
using System.Security;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Markup;
using System.Windows.Media;
namespace AIStudio.Wpf.Mind.Controls
{
[ContentProperty(nameof(ItemsSource))]
[TemplatePart(Name = "PART_Button", Type = typeof(Button))]
[TemplatePart(Name = "PART_ButtonContent", Type = typeof(ContentControl))]
[TemplatePart(Name = "PART_Menu", Type = typeof(ContextMenu))]
[StyleTypedProperty(Property = nameof(ButtonStyle), StyleTargetType = typeof(Button))]
[StyleTypedProperty(Property = nameof(MenuStyle), StyleTargetType = typeof(ContextMenu))]
public class DropDownButton : ItemsControl, ICommandSource
{
public static readonly RoutedEvent ClickEvent
= EventManager.RegisterRoutedEvent(nameof(Click),
RoutingStrategy.Bubble,
typeof(RoutedEventHandler),
typeof(DropDownButton));
public event RoutedEventHandler Click
{
add => this.AddHandler(ClickEvent, value);
remove => this.RemoveHandler(ClickEvent, value);
}
/// <summary>Identifies the <see cref="IsExpanded"/> dependency property.</summary>
public static readonly DependencyProperty IsExpandedProperty
= DependencyProperty.Register(nameof(IsExpanded),
typeof(bool),
typeof(DropDownButton),
new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnIsExpandedPropertyChangedCallback));
private static void OnIsExpandedPropertyChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
{
if (dependencyObject is DropDownButton dropDownButton
&& !(dropDownButton.contextMenu == null))
{
dropDownButton.SetContextMenuPlacementTarget(dropDownButton.contextMenu);
}
}
protected virtual void SetContextMenuPlacementTarget(ContextMenu contextMenu)
{
if (this.button != null)
{
contextMenu.PlacementTarget = this.button;
}
}
/// <summary>
/// Whether or not the "popup" menu for this control is currently open
/// </summary>
public bool IsExpanded
{
get => (bool)this.GetValue(IsExpandedProperty);
set => this.SetValue(IsExpandedProperty, (bool)value);
}
/// <summary>Identifies the <see cref="ExtraTag"/> dependency property.</summary>
public static readonly DependencyProperty ExtraTagProperty
= DependencyProperty.Register(nameof(ExtraTag),
typeof(object),
typeof(DropDownButton));
/// <summary>
/// Gets or sets an extra tag.
/// </summary>
public object ExtraTag
{
get => this.GetValue(ExtraTagProperty);
set => this.SetValue(ExtraTagProperty, value);
}
/// <summary>Identifies the <see cref="Orientation"/> dependency property.</summary>
public static readonly DependencyProperty OrientationProperty
= DependencyProperty.Register(nameof(Orientation),
typeof(Orientation),
typeof(DropDownButton),
new FrameworkPropertyMetadata(Orientation.Horizontal, FrameworkPropertyMetadataOptions.AffectsMeasure));
/// <summary>
/// Gets or sets the orientation of children stacking.
/// </summary>
public Orientation Orientation
{
get => (Orientation)this.GetValue(OrientationProperty);
set => this.SetValue(OrientationProperty, value);
}
/// <summary>Identifies the <see cref="Icon"/> dependency property.</summary>
public static readonly DependencyProperty IconProperty
= DependencyProperty.Register(nameof(Icon),
typeof(object),
typeof(DropDownButton));
/// <summary>
/// Gets or sets the content for the icon part.
/// </summary>
[Bindable(true)]
public object Icon
{
get => this.GetValue(IconProperty);
set => this.SetValue(IconProperty, value);
}
/// <summary>Identifies the <see cref="IconTemplate"/> dependency property.</summary>
public static readonly DependencyProperty IconTemplateProperty
= DependencyProperty.Register(nameof(IconTemplate),
typeof(DataTemplate),
typeof(DropDownButton));
/// <summary>
/// Gets or sets the DataTemplate for the icon part.
/// </summary>
[Bindable(true)]
public DataTemplate IconTemplate
{
get => (DataTemplate)this.GetValue(IconTemplateProperty);
set => this.SetValue(IconTemplateProperty, value);
}
/// <summary>Identifies the <see cref="Command"/> dependency property.</summary>
public static readonly DependencyProperty CommandProperty
= DependencyProperty.Register(nameof(Command),
typeof(ICommand),
typeof(DropDownButton),
new PropertyMetadata(null, OnCommandPropertyChangedCallback));
private static void OnCommandPropertyChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
{
(dependencyObject as DropDownButton).OnCommandChanged((ICommand)e.OldValue, (ICommand)e.NewValue);
}
/// <summary>
/// Gets or sets the command to invoke when the content button is pressed.
/// </summary>
public ICommand Command
{
get => (ICommand)this.GetValue(CommandProperty);
set => this.SetValue(CommandProperty, value);
}
/// <summary>Identifies the <see cref="CommandTarget"/> dependency property.</summary>
public static readonly DependencyProperty CommandTargetProperty
= DependencyProperty.Register(nameof(CommandTarget),
typeof(IInputElement),
typeof(DropDownButton),
new PropertyMetadata(null));
/// <summary>
/// Gets or sets the element on which to raise the specified command.
/// </summary>
public IInputElement CommandTarget
{
get => (IInputElement)this.GetValue(CommandTargetProperty);
set => this.SetValue(CommandTargetProperty, value);
}
/// <summary>Identifies the <see cref="CommandParameter"/> dependency property.</summary>
public static readonly DependencyProperty CommandParameterProperty
= DependencyProperty.Register(nameof(CommandParameter),
typeof(object),
typeof(DropDownButton),
new PropertyMetadata(null));
/// <summary>
/// Gets or sets the parameter to pass to the command property.
/// </summary>
public object CommandParameter
{
get => (object)this.GetValue(CommandParameterProperty);
set => this.SetValue(CommandParameterProperty, value);
}
/// <summary>Identifies the <see cref="Content"/> dependency property.</summary>
public static readonly DependencyProperty ContentProperty
= DependencyProperty.Register(nameof(Content),
typeof(object),
typeof(DropDownButton));
/// <summary>
/// Gets or sets the content of this control.
/// </summary>
public object Content
{
get => (object)this.GetValue(ContentProperty);
set => this.SetValue(ContentProperty, value);
}
/// <summary>Identifies the <see cref="ContentTemplate"/> dependency property.</summary>
public static readonly DependencyProperty ContentTemplateProperty
= DependencyProperty.Register(nameof(ContentTemplate),
typeof(DataTemplate),
typeof(DropDownButton),
new FrameworkPropertyMetadata(null));
/// <summary>
/// Gets or sets the data template used to display the content of the DropDownButton.
/// </summary>
[Bindable(true)]
public DataTemplate ContentTemplate
{
get => (DataTemplate)this.GetValue(ContentTemplateProperty);
set => this.SetValue(ContentTemplateProperty, value);
}
/// <summary>Identifies the <see cref="ContentTemplateSelector"/> dependency property.</summary>
public static readonly DependencyProperty ContentTemplateSelectorProperty
= DependencyProperty.Register(nameof(ContentTemplateSelector),
typeof(DataTemplateSelector),
typeof(DropDownButton),
new FrameworkPropertyMetadata(null));
/// <summary>
/// Gets or sets a template selector that enables an application writer to provide custom template-selection logic.
/// </summary>
/// <remarks>
/// This property is ignored if <seealso cref="ContentTemplate"/> is set.
/// </remarks>
[Bindable(true)]
public DataTemplateSelector ContentTemplateSelector
{
get => (DataTemplateSelector)this.GetValue(ContentTemplateSelectorProperty);
set => this.SetValue(ContentTemplateSelectorProperty, value);
}
/// <summary>Identifies the <see cref="ContentStringFormat"/> dependency property.</summary>
public static readonly DependencyProperty ContentStringFormatProperty
= DependencyProperty.Register(nameof(ContentStringFormat),
typeof(string),
typeof(DropDownButton),
new FrameworkPropertyMetadata(null));
/// <summary>
/// Gets or sets a composite string that specifies how to format the content property if it is displayed as a string.
/// </summary>
/// <remarks>
/// This property is ignored if <seealso cref="ContentTemplate"/> is set.
/// </remarks>
[Bindable(true)]
public string ContentStringFormat
{
get => (string)this.GetValue(ContentStringFormatProperty);
set => this.SetValue(ContentStringFormatProperty, value);
}
/// <summary>Identifies the <see cref="ButtonStyle"/> dependency property.</summary>
public static readonly DependencyProperty ButtonStyleProperty
= DependencyProperty.Register(nameof(ButtonStyle),
typeof(Style),
typeof(DropDownButton),
new FrameworkPropertyMetadata(default(Style), FrameworkPropertyMetadataOptions.Inherits | FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsMeasure));
/// <summary>
/// Gets or sets the button content style.
/// </summary>
public Style ButtonStyle
{
get => (Style)this.GetValue(ButtonStyleProperty);
set => this.SetValue(ButtonStyleProperty, value);
}
/// <summary>Identifies the <see cref="MenuStyle"/> dependency property.</summary>
public static readonly DependencyProperty MenuStyleProperty
= DependencyProperty.Register(nameof(MenuStyle),
typeof(Style),
typeof(DropDownButton),
new FrameworkPropertyMetadata(default(Style), FrameworkPropertyMetadataOptions.Inherits | FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsMeasure));
/// <summary>
/// Gets or sets the "popup" menu style.
/// </summary>
public Style MenuStyle
{
get => (Style)this.GetValue(MenuStyleProperty);
set => this.SetValue(MenuStyleProperty, value);
}
/// <summary>Identifies the <see cref="ArrowBrush"/> dependency property.</summary>
public static readonly DependencyProperty ArrowBrushProperty
= DependencyProperty.Register(nameof(ArrowBrush),
typeof(Brush),
typeof(DropDownButton),
new FrameworkPropertyMetadata(default(Brush), FrameworkPropertyMetadataOptions.AffectsRender));
/// <summary>
/// Gets or sets the foreground brush for the button arrow icon.
/// </summary>
public Brush ArrowBrush
{
get => (Brush)this.GetValue(ArrowBrushProperty);
set => this.SetValue(ArrowBrushProperty, value);
}
/// <summary>Identifies the <see cref="ArrowMouseOverBrush"/> dependency property.</summary>
public static readonly DependencyProperty ArrowMouseOverBrushProperty
= DependencyProperty.Register(nameof(ArrowMouseOverBrush),
typeof(Brush),
typeof(DropDownButton),
new FrameworkPropertyMetadata(default(Brush), FrameworkPropertyMetadataOptions.AffectsRender));
/// <summary>
/// Gets or sets the foreground brush of the button arrow icon if the mouse is over the drop down button.
/// </summary>
public Brush ArrowMouseOverBrush
{
get => (Brush)this.GetValue(ArrowMouseOverBrushProperty);
set => this.SetValue(ArrowMouseOverBrushProperty, value);
}
/// <summary>Identifies the <see cref="ArrowPressedBrush"/> dependency property.</summary>
public static readonly DependencyProperty ArrowPressedBrushProperty
= DependencyProperty.Register(nameof(ArrowPressedBrush),
typeof(Brush),
typeof(DropDownButton),
new FrameworkPropertyMetadata(default(Brush), FrameworkPropertyMetadataOptions.AffectsRender));
/// <summary>
/// Gets or sets the foreground brush of the button arrow icon if the arrow button is pressed.
/// </summary>
public Brush ArrowPressedBrush
{
get => (Brush)this.GetValue(ArrowPressedBrushProperty);
set => this.SetValue(ArrowPressedBrushProperty, value);
}
/// <summary>Identifies the <see cref="ArrowVisibility"/> dependency property.</summary>
public static readonly DependencyProperty ArrowVisibilityProperty
= DependencyProperty.Register(nameof(ArrowVisibility),
typeof(Visibility),
typeof(DropDownButton),
new FrameworkPropertyMetadata(Visibility.Visible, FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsMeasure));
/// <summary>
/// Gets or sets the visibility of the button arrow icon.
/// </summary>
public Visibility ArrowVisibility
{
get => (Visibility)this.GetValue(ArrowVisibilityProperty);
set => this.SetValue(ArrowVisibilityProperty, value);
}
static DropDownButton()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(DropDownButton), new FrameworkPropertyMetadata(typeof(DropDownButton)));
}
private void OnCommandChanged(ICommand oldCommand, ICommand newCommand)
{
if (oldCommand != null)
{
this.UnhookCommand(oldCommand);
}
if (newCommand != null)
{
this.HookCommand(newCommand);
}
}
private void UnhookCommand(ICommand command)
{
CanExecuteChangedEventManager.RemoveHandler(command, this.OnCanExecuteChanged);
this.UpdateCanExecute();
}
private void HookCommand(ICommand command)
{
CanExecuteChangedEventManager.AddHandler(command, this.OnCanExecuteChanged);
this.UpdateCanExecute();
}
private void OnCanExecuteChanged(object sender, EventArgs e)
{
this.UpdateCanExecute();
}
private void UpdateCanExecute()
{
this.CanExecute = this.Command == null || CommandHelpers.CanExecuteCommandSource(this);
}
/// <inheritdoc />
protected override bool IsEnabledCore => base.IsEnabledCore && this.CanExecute;
private bool canExecute = true;
private bool CanExecute
{
get => this.canExecute;
set
{
if (value == this.canExecute)
{
return;
}
this.canExecute = value;
this.CoerceValue(IsEnabledProperty);
}
}
private void ButtonClick(object sender, RoutedEventArgs e)
{
CommandHelpers.ExecuteCommandSource(this);
if (this.contextMenu?.HasItems == true)
{
this.SetCurrentValue(IsExpandedProperty, true);
}
e.RoutedEvent = ClickEvent;
this.RaiseEvent(e);
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
if (this.button != null)
{
this.button.Click -= this.ButtonClick;
}
this.button = this.GetTemplateChild("PART_Button") as Button;
if (this.button != null)
{
this.button.Click += this.ButtonClick;
}
this.GroupStyle.CollectionChanged -= this.OnGroupStyleCollectionChanged;
this.contextMenu = this.GetTemplateChild("PART_Menu") as ContextMenu;
if (this.contextMenu != null)
{
foreach (var groupStyle in this.GroupStyle)
{
this.contextMenu.GroupStyle.Add(groupStyle);
}
this.GroupStyle.CollectionChanged += this.OnGroupStyleCollectionChanged;
if (this.Items != null && this.ItemsSource == null)
{
foreach (var newItem in this.Items)
{
this.TryRemoveVisualFromOldTree(newItem);
this.contextMenu.Items.Add(newItem);
}
}
}
}
#if NET5_0_OR_GREATER
private void OnGroupStyleCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
#else
private void OnGroupStyleCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
#endif
{
if (e.OldItems != null)
{
foreach (var groupStyle in e.OldItems.OfType<GroupStyle>())
{
this.contextMenu?.GroupStyle.Remove(groupStyle);
}
}
if (e.NewItems != null)
{
foreach (var groupStyle in e.NewItems.OfType<GroupStyle>())
{
this.contextMenu?.GroupStyle.Add(groupStyle);
}
}
}
/// <inheritdoc />
protected override void OnMouseRightButtonUp(MouseButtonEventArgs e)
{
base.OnMouseRightButtonUp(e);
e.Handled = true;
}
private void TryRemoveVisualFromOldTree(object item)
{
if (item is Visual visual)
{
var parent = LogicalTreeHelper.GetParent(visual) as FrameworkElement ?? VisualTreeHelper.GetParent(visual) as FrameworkElement;
if (Equals(this, parent))
{
this.RemoveLogicalChild(visual);
this.RemoveVisualChild(visual);
}
}
}
/// <summary>Invoked when the <see cref="P:System.Windows.Controls.ItemsControl.Items" /> property changes.</summary>
/// <param name="e">Information about the change.</param>
protected override void OnItemsChanged(NotifyCollectionChangedEventArgs e)
{
base.OnItemsChanged(e);
if (this.contextMenu == null || this.ItemsSource != null || this.contextMenu.ItemsSource != null)
{
return;
}
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
if (e.NewItems != null)
{
foreach (var newItem in e.NewItems)
{
this.TryRemoveVisualFromOldTree(newItem);
this.contextMenu.Items.Add(newItem);
}
}
break;
case NotifyCollectionChangedAction.Remove:
if (e.OldItems != null)
{
foreach (var oldItem in e.OldItems)
{
this.contextMenu.Items.Remove(oldItem);
}
}
break;
case NotifyCollectionChangedAction.Move:
case NotifyCollectionChangedAction.Replace:
if (e.OldItems != null)
{
foreach (var oldItem in e.OldItems)
{
this.contextMenu.Items.Remove(oldItem);
}
}
if (e.NewItems != null)
{
foreach (var newItem in e.NewItems)
{
this.TryRemoveVisualFromOldTree(newItem);
this.contextMenu.Items.Add(newItem);
}
}
break;
case NotifyCollectionChangedAction.Reset:
if (this.Items != null)
{
this.contextMenu.Items.Clear();
foreach (var newItem in this.Items)
{
this.TryRemoveVisualFromOldTree(newItem);
this.contextMenu.Items.Add(newItem);
}
}
break;
default:
throw new ArgumentOutOfRangeException();
}
}
private Button button;
private ContextMenu contextMenu;
}
internal static class CommandHelpers
{
internal static bool CanExecuteCommandSource(ICommandSource commandSource)
{
var command = commandSource.Command;
if (command == null)
{
return false;
}
var commandParameter = commandSource.CommandParameter ?? commandSource;
if (command is RoutedCommand routedCommand)
{
var target = commandSource.CommandTarget ?? commandSource as IInputElement;
return routedCommand.CanExecute(commandParameter, target);
}
return command.CanExecute(commandParameter);
}
[SecurityCritical]
[SecuritySafeCritical]
internal static void ExecuteCommandSource(ICommandSource commandSource)
{
CriticalExecuteCommandSource(commandSource);
}
[SecurityCritical]
internal static void CriticalExecuteCommandSource(ICommandSource commandSource)
{
var command = commandSource.Command;
if (command == null)
{
return;
}
var commandParameter = commandSource.CommandParameter ?? commandSource;
if (command is RoutedCommand routedCommand)
{
var target = commandSource.CommandTarget ?? commandSource as IInputElement;
if (routedCommand.CanExecute(commandParameter, target))
{
routedCommand.Execute(commandParameter, target);
}
}
else
{
if (command.CanExecute(commandParameter))
{
command.Execute(commandParameter);
}
}
}
internal static bool CanExecuteCommandSource(ICommandSource commandSource, ICommand theCommand)
{
var command = theCommand;
if (command == null)
{
return false;
}
var commandParameter = commandSource.CommandParameter ?? commandSource;
if (command is RoutedCommand routedCommand)
{
var target = commandSource.CommandTarget ?? commandSource as IInputElement;
return routedCommand.CanExecute(commandParameter, target);
}
return command.CanExecute(commandParameter);
}
[SecurityCritical]
[SecuritySafeCritical]
internal static void ExecuteCommandSource(ICommandSource commandSource, ICommand theCommand)
{
CriticalExecuteCommandSource(commandSource, theCommand);
}
[SecurityCritical]
internal static void CriticalExecuteCommandSource(ICommandSource commandSource, ICommand theCommand)
{
var command = theCommand;
if (command == null)
{
return;
}
var commandParameter = commandSource.CommandParameter ?? commandSource;
if (command is RoutedCommand routedCommand)
{
var target = commandSource.CommandTarget ?? commandSource as IInputElement;
if (routedCommand.CanExecute(commandParameter, target))
{
routedCommand.Execute(commandParameter, target);
}
}
else
{
if (command.CanExecute(commandParameter))
{
command.Execute(commandParameter);
}
}
}
}
}

View File

@@ -20,7 +20,7 @@
<!-- ToolBox Control -->
<ContentControl Template="{Binding ToolBox,RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}"/>
<ScrollViewer Grid.Column="1">
<ScrollViewer Grid.Row="1">
<!-- Diagram Control -->
<dd:DiagramControl x:Name="PART_DiagramControl" MinWidth="1000" MinHeight="1000" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
</ScrollViewer>

View File

@@ -10,6 +10,7 @@ using System.Windows;
using System.Xml.Linq;
using AIStudio.Wpf.DiagramDesigner;
using AIStudio.Wpf.DiagramDesigner.Geometrys;
using AIStudio.Wpf.Mind.ViewModels;
namespace AIStudio.Wpf.Mind.Controls
{
@@ -22,7 +23,7 @@ namespace AIStudio.Wpf.Mind.Controls
public const string PART_DiagramControl = "PART_DiagramControl";
private DiagramControl _diagramControl;
private IDiagramViewModel _diagramViewModel;
private MindDiagramViewModel _diagramViewModel;
static MindEditor()
{
@@ -31,16 +32,10 @@ namespace AIStudio.Wpf.Mind.Controls
public MindEditor()
{
_diagramViewModel = new DiagramViewModel();
_diagramViewModel.ShowGrid = true;
_diagramViewModel.GridCellSize = new SizeBase(125 / ScreenHelper.ScreenScale, 125 / ScreenHelper.ScreenScale);
_diagramViewModel = new MindDiagramViewModel();
_diagramViewModel.GridMarginSize = new Size(0, 0);
_diagramViewModel.CellHorizontalAlignment = CellHorizontalAlignment.Center;
_diagramViewModel.CellVerticalAlignment = CellVerticalAlignment.Center;
_diagramViewModel.PageSizeType = PageSizeType.Custom;
_diagramViewModel.PageSize = new SizeBase(double.NaN, double.NaN);
_diagramViewModel.ColorViewModel = new ColorViewModel() { LineWidth = 2 };
_diagramViewModel.DrawModeViewModel = new DrawModeViewModel() { LineDrawMode = DrawMode.ConnectingLineSmooth };
_diagramViewModel.PropertyChanged += DiagramViewModel_PropertyChanged;
}
@@ -52,7 +47,7 @@ namespace AIStudio.Wpf.Mind.Controls
_diagramControl = GetTemplateChild(PART_DiagramControl) as DiagramControl;
_diagramControl.HorizontalAlignment = HorizontalAlignment.Stretch;
_diagramControl.VerticalAlignment = VerticalAlignment.Stretch;
_diagramControl.DataContext = _diagramViewModel;
this.DataContext = _diagramViewModel;
GetDataFunc = GetData;
}
@@ -97,7 +92,11 @@ namespace AIStudio.Wpf.Mind.Controls
{
_diagramViewModel.IsLoading = true;
_diagramViewModel.Items.Clear();
//_diagramViewModel.ToObject(json);
MindNode level1node = new MindNode(_diagramViewModel, Mind.NodeLevel.Level1, _diagramViewModel.MindType) { Text = "思维导图" };
_diagramViewModel.DirectAddItemCommand.Execute(level1node);
level1node.Left = 200;
level1node.Top = 200;
_diagramViewModel.DoCommandManager.Init();
_diagramViewModel.IsLoading = false;
}

View File

@@ -3,10 +3,18 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:AIStudio.Wpf.Mind.Controls"
xmlns:dd="https://gitee.com/akwkevin/aistudio.-wpf.-diagram"
xmlns:controls="clr-namespace:AIStudio.Wpf.Mind.Controls"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800" >
<Grid Height="60">
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/AIStudio.Wpf.Mind;component/Styles/Button.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<Grid Height="70">
<TabControl>
<TabItem Header="思路">
<Grid>
@@ -14,6 +22,112 @@
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Button Style="{StaticResource FlatButtonStyle}" Grid.Row="0" Grid.Column="0" Command="{Binding UndoCommand}">
<Path Width="12" Height="12" Stretch="Uniform" Fill="Black" Data="M255.545 8c-66.269.119-126.438 26.233-170.86 68.685L48.971 40.971C33.851 25.851 8 36.559 8 57.941V192c0 13.255 10.745 24 24 24h134.059c21.382 0 32.09-25.851 16.971-40.971l-41.75-41.75c30.864-28.899 70.801-44.907 113.23-45.273 92.398-.798 170.283 73.977 169.484 169.442C423.236 348.009 349.816 424 256 424c-41.127 0-79.997-14.678-110.63-41.556-4.743-4.161-11.906-3.908-16.368.553L89.34 422.659c-4.872 4.872-4.631 12.815.482 17.433C133.798 479.813 192.074 504 256 504c136.966 0 247.999-111.033 248-247.998C504.001 119.193 392.354 7.755 255.545 8z"></Path>
</Button>
<Button Style="{StaticResource FlatButtonStyle}" Grid.Row="1" Grid.Column="0" Command="{Binding RedoCommand}">
<Path Width="12" Height="12" Stretch="Uniform" Fill="Black" Data="M256.455 8c66.269.119 126.437 26.233 170.859 68.685l35.715-35.715C478.149 25.851 504 36.559 504 57.941V192c0 13.255-10.745 24-24 24H345.941c-21.382 0-32.09-25.851-16.971-40.971l41.75-41.75c-30.864-28.899-70.801-44.907-113.23-45.273-92.398-.798-170.283 73.977-169.484 169.442C88.764 348.009 162.184 424 256 424c41.127 0 79.997-14.678 110.629-41.556 4.743-4.161 11.906-3.908 16.368.553l39.662 39.662c4.872 4.872 4.631 12.815-.482 17.433C378.202 479.813 319.926 504 256 504 119.034 504 8.001 392.967 8 256.002 7.999 119.193 119.646 7.755 256.455 8z"></Path>
</Button>
<Button Style="{StaticResource FlatButtonStyle}" Grid.Row="0" Grid.Column="1" Command="{Binding AddChildCommand}">
<StackPanel Orientation="Horizontal">
<Path Width="12" Height="12" Stretch="Uniform" Fill="Black" Data="M992.9 500.1H355c-19.3 0-35 15.7-35 35V660H182V340.8h427.8c32 0 58-26 58-58V58c0-32-25.9-58-58-58H58C26 0 0 26 0 58v224.8c0 32 26 58 58 58h54V689c0 13.3 7.4 24.8 18.2 30.7 6.3 6.3 15.1 10.3 24.8 10.3h165v145.9c0 19.3 15.7 35 35 35h226c19.3 0 35-15.7 35-35s-15.7-35-35-35H390V570.1h567.9V611c0 19.3 15.7 35 35 35s35-15.7 35-35v-75.9c0-19.3-15.7-35-35-35zM70 70h527.8v200.8H70V70zM989 830h-89v-89c0-19.3-15.7-35-35-35s-35 15.7-35 35v89h-89c-19.3 0-35 15.7-35 35s15.7 35 35 35h89v89c0 19.3 15.7 35 35 35s35-15.7 35-35v-89h89c19.3 0 35-15.7 35-35s-15.7-35-35-35z"></Path>
<TextBlock>插入下级主题</TextBlock>
</StackPanel>
</Button>
<Button Style="{StaticResource FlatButtonStyle}" Grid.Row="1" Grid.Column="1" Command="{Binding AddPeerCommand}">
<StackPanel Orientation="Horizontal">
<Path Width="12" Height="12" Stretch="Uniform" Fill="Black" Data="M651.8 775.5h-20.3v-527h178V305c0 19.3 15.7 35 35 35s35-15.7 35-35v-91.5c0-19.3-15.7-35-35-35h-248c-19.3 0-35 15.7-35 35V477H340.8V236.1c0-32-26-58-58-58H58c-32 0-58 26-58 58v551.8c0 32 26 58 58 58h224.8c32 0 58-26 58-58V547h220.7v263.5c0 19.3 15.7 35 35 35h55.3c19.3 0 35-15.7 35-35s-15.7-35-35-35z m-381 0.4H70V248.1h200.8v527.8zM990 651.5h-89v-89c0-19.3-15.7-35-35-35s-35 15.7-35 35v89h-89c-19.3 0-35 15.7-35 35s15.7 35 35 35h89v89c0 19.3 15.7 35 35 35s35-15.7 35-35v-89h89c19.3 0 35-15.7 35-35s-15.7-35-35-35z"></Path>
<TextBlock>插入同级主题</TextBlock>
</StackPanel>
</Button>
<Button Style="{StaticResource FlatButtonStyle}" Grid.Row="0" Grid.Column="2" Command="{Binding AddParentCommand}">
<StackPanel Orientation="Horizontal">
<Path Width="12" Height="12" Stretch="Uniform" Fill="Black" RenderTransformOrigin="0.5,0.5" Data="M992.9 500.1H355c-19.3 0-35 15.7-35 35V660H182V340.8h427.8c32 0 58-26 58-58V58c0-32-25.9-58-58-58H58C26 0 0 26 0 58v224.8c0 32 26 58 58 58h54V689c0 13.3 7.4 24.8 18.2 30.7 6.3 6.3 15.1 10.3 24.8 10.3h165v145.9c0 19.3 15.7 35 35 35h226c19.3 0 35-15.7 35-35s-15.7-35-35-35H390V570.1h567.9V611c0 19.3 15.7 35 35 35s35-15.7 35-35v-75.9c0-19.3-15.7-35-35-35zM70 70h527.8v200.8H70V70zM989 830h-89v-89c0-19.3-15.7-35-35-35s-35 15.7-35 35v89h-89c-19.3 0-35 15.7-35 35s15.7 35 35 35h89v89c0 19.3 15.7 35 35 35s35-15.7 35-35v-89h89c19.3 0 35-15.7 35-35s-15.7-35-35-35z">
<Path.RenderTransform>
<ScaleTransform ScaleX="-1" ScaleY="-1"/>
</Path.RenderTransform>
</Path>
<TextBlock>插入上级主题</TextBlock>
</StackPanel>
</Button>
<Button Style="{StaticResource FlatButtonStyle}" Grid.Row="0" Grid.Column="3" Command="{Binding MoveForwardCommand}">
<StackPanel Orientation="Horizontal">
<Path Width="12" Height="12" Stretch="Uniform" Fill="Black" Data="M62.5 500L312.5 500L312.5 937.5L687.5 937.5L687.5 500L937.5 500L500 62.5Z"></Path>
<TextBlock>上移</TextBlock>
</StackPanel>
</Button>
<Button Style="{StaticResource FlatButtonStyle}" Grid.Row="1" Grid.Column="3" Command="{Binding MoveBackCommand}">
<StackPanel Orientation="Horizontal">
<Path Width="12" Height="12" Stretch="Uniform" Fill="Black" Data="M687.5 62.5L312.5 62.5L312.5 500L62.5 500L500 937.5L937.4 500L687.5 500Z"></Path>
<TextBlock>下移</TextBlock>
</StackPanel>
</Button>
<Button Style="{StaticResource FlatButtonStyle}" Grid.Row="0" Grid.Column="4" Command="{Binding EditCommand}">
<StackPanel Orientation="Horizontal">
<Path Width="12" Height="12" Stretch="Uniform" Fill="Black" Data="M8,12H16V14H8V12M10,20H6V4H13V9H18V12.1L20,10.1V8L14,2H6A2,2 0 0,0 4,4V20A2,2 0 0,0 6,22H10V20M8,18H12.1L13,17.1V16H8V18M20.2,13C20.3,13 20.5,13.1 20.6,13.2L21.9,14.5C22.1,14.7 22.1,15.1 21.9,15.3L20.9,16.3L18.8,14.2L19.8,13.2C19.9,13.1 20,13 20.2,13M20.2,16.9L14.1,23H12V20.9L18.1,14.8L20.2,16.9Z"></Path>
<TextBlock>编辑</TextBlock>
</StackPanel>
</Button>
<Button Style="{StaticResource FlatButtonStyle}" Grid.Column="4" Command="{Binding DeleteSelfCommand}" Height="22" Grid.RowSpan="2" VerticalAlignment="Bottom">
<StackPanel Orientation="Horizontal">
<Path Width="12" Height="12" Stretch="Uniform" Fill="Black" Data="M 25.3333,23.75L 50.6667,23.75C 51.5411,23.75 51.8541,27.3125 51.8541,27.3125L 24.1458,27.3125C 24.1458,27.3125 24.4589,23.75 25.3333,23.75 Z M 35.625,19.7917L 40.375,19.7917C 40.8122,19.7917 41.9583,20.9378 41.9583,21.375C 41.9583,21.8122 40.8122,22.9584 40.375,22.9584L 35.625,22.9584C 35.1878,22.9584 34.0416,21.8122 34.0416,21.375C 34.0416,20.9378 35.1878,19.7917 35.625,19.7917 Z M 27.7083,28.5L 48.2916,28.5C 49.1661,28.5 49.875,29.2089 49.875,30.0834L 48.2916,53.8334C 48.2916,54.7078 47.5828,55.4167 46.7083,55.4167L 29.2917,55.4167C 28.4172,55.4167 27.7083,54.7078 27.7083,53.8334L 26.125,30.0834C 26.125,29.2089 26.8339,28.5 27.7083,28.5 Z M 30.0833,31.6667L 30.4792,52.25L 33.25,52.25L 32.8542,31.6667L 30.0833,31.6667 Z M 36.4167,31.6667L 36.4167,52.25L 39.5833,52.25L 39.5833,31.6667L 36.4167,31.6667 Z M 43.1458,31.6667L 42.75,52.25L 45.5208,52.25L 45.9167,31.6667L 43.1458,31.6667 Z "></Path>
<TextBlock>删除</TextBlock>
</StackPanel>
</Button>
<controls:DropDownButton Grid.RowSpan="2" Grid.Column="5" >
<controls:DropDownButton.Content>
<StackPanel>
<Path Width="18" Height="18" Stretch="Uniform" Fill="Black" Data="M 23.4963,46.1288L 25.0796,48.8712L 29.4053,50.0303L 33.519,47.6553L 34.8902,46.8636L 37.6326,45.2803L 38.4242,46.6515L 37.2652,50.9772L 30.4091,54.9356L 21.7577,52.6174L 18.591,47.1326L 20.9091,38.4811L 27.7652,34.5227L 32.0909,35.6818L 32.8826,37.053L 30.1402,38.6364L 28.769,39.428L 24.6553,41.803L 23.4963,46.1288 Z M 38.7348,28.1895L 45.5908,24.2311L 54.2423,26.5493L 57.409,32.0341L 55.0908,40.6856L 48.2348,44.6439L 43.9091,43.4848L 43.1174,42.1136L 45.8598,40.5303L 47.231,39.7386L 51.3446,37.3636L 52.5037,33.0379L 50.9204,30.2955L 46.5946,29.1364L 42.481,31.5114L 41.1098,32.3031L 38.3674,33.8864L 37.5757,32.5152L 38.7348,28.1895 Z M 33.9006,45.1496L 31.7377,44.5701L 30.5502,42.5133L 31.1298,40.3504L 42.0994,34.0171L 44.2623,34.5966L 45.4498,36.6534L 44.8702,38.8163L 33.9006,45.1496 Z "></Path>
<TextBlock>链接</TextBlock>
</StackPanel>
</controls:DropDownButton.Content>
<controls:DropDownButton.Items>
<MenuItem Header="插入链接"></MenuItem>
<MenuItem Header="移除已有链接"></MenuItem>
</controls:DropDownButton.Items>
</controls:DropDownButton>
<controls:DropDownButton Grid.RowSpan="2" Grid.Column="6" >
<controls:DropDownButton.Content>
<StackPanel>
<Path Width="18" Height="18" Stretch="Uniform" Fill="Black" Data="M250 645L350 745L625 470L800 645L950 495V950H250V645zM250 503.55V250H405L554.3000000000001 399.25L350 603.55L250 503.55zM546.45 250H950V353.5500000000001L800 503.5500000000001L546.45 250zM200 1050H1000A50 50 0 0 0 1050 1000V200A50 50 0 0 0 1000 150H200A50 50 0 0 0 150 200V1000A50 50 0 0 0 200 1050zM775 700A75 75 0 1 0 775 850A75 75 0 0 0 775 700z"></Path>
<TextBlock>图片</TextBlock>
</StackPanel>
</controls:DropDownButton.Content>
<controls:DropDownButton.Items>
<MenuItem Header="插入图片"></MenuItem>
<MenuItem Header="移除已有图片"></MenuItem>
</controls:DropDownButton.Items>
</controls:DropDownButton>
<controls:DropDownButton Grid.RowSpan="2" Grid.Column="7" >
<controls:DropDownButton.Content>
<StackPanel>
<Path Width="18" Height="18" Stretch="Uniform" Fill="Black" Data="M5,3C3.89,3 3,3.89 3,5V19C3,20.11 3.89,21 5,21H19C20.11,21 21,20.11 21,19V5C21,3.89 20.11,3 19,3H5M5,5H19V19H5V5M7,7V9H17V7H7M7,11V13H17V11H7M7,15V17H14V15H7Z"></Path>
<TextBlock>备注</TextBlock>
</StackPanel>
</controls:DropDownButton.Content>
<controls:DropDownButton.Items>
<MenuItem Header="插入备注"></MenuItem>
<MenuItem Header="移除已有备注"></MenuItem>
</controls:DropDownButton.Items>
</controls:DropDownButton>
</Grid>
</TabItem>
<TabItem Header="外观">
@@ -22,6 +136,36 @@
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<controls:DropDownButton Grid.RowSpan="2" Grid.Column="7">
<controls:DropDownButton.Content>
<StackPanel>
<Path Width="18" Height="18" Stretch="Uniform" Fill="Black" Data="M5,3C3.89,3 3,3.89 3,5V19C3,20.11 3.89,21 5,21H19C20.11,21 21,20.11 21,19V5C21,3.89 20.11,3 19,3H5M5,5H19V19H5V5M7,7V9H17V7H7M7,11V13H17V11H7M7,15V17H14V15H7Z"></Path>
<TextBlock>类型</TextBlock>
</StackPanel>
</controls:DropDownButton.Content>
<controls:DropDownButton.Items>
<MenuItem Header="思维导图" IsCheckable="True" IsChecked="{Binding MindType,Converter={dd:ConverterValueMapToBool Parameter='Mind'}, ConverterParameter='Mind'}" />
<MenuItem Header="目录组织图" IsCheckable="True" IsChecked="{Binding MindType,Converter={dd:ConverterValueMapToBool Parameter='Directory'}, ConverterParameter='Directory'}" />
<MenuItem Header="鱼骨头图" IsCheckable="True" IsChecked="{Binding MindType,Converter={dd:ConverterValueMapToBool Parameter='FishBone'}, ConverterParameter='FishBone'}" />
<MenuItem Header="逻辑结构图" IsCheckable="True" IsChecked="{Binding MindType,Converter={dd:ConverterValueMapToBool Parameter='Logical'}, ConverterParameter='Logical'}" />
<MenuItem Header="组织结构图" IsCheckable="True" IsChecked="{Binding MindType,Converter={dd:ConverterValueMapToBool Parameter='Organizational'}, ConverterParameter='Organizational'}" />
<MenuItem Header="天盘图" IsCheckable="True" IsChecked="{Binding MindType,Converter={dd:ConverterValueMapToBool Parameter='Celestial'}, ConverterParameter='Celestial'}" />
</controls:DropDownButton.Items>
</controls:DropDownButton>
</Grid>
</TabItem>
<TabItem Header="视图">

View File

@@ -6,6 +6,7 @@ using System.Windows.Media;
using AIStudio.Wpf.DiagramDesigner;
using AIStudio.Wpf.DiagramDesigner.Algorithms;
using AIStudio.Wpf.DiagramDesigner.Geometrys;
using AIStudio.Wpf.DiagramDesigner.Helpers;
using AIStudio.Wpf.Mind.ViewModels;
namespace AIStudio.Wpf.Mind.Helpers
@@ -34,6 +35,7 @@ namespace AIStudio.Wpf.Mind.Helpers
mindNode.ShapeViewModel.SinkMarker.PathStyle = ArrowPathStyle.None;
mindNode.ShapeViewModel.SinkMarker.SizeStyle = ArrowSizeStyle.VerySmall;
mindNode.ConnectorOrientation = ConnectorOrientation.None;
break;
}
case NodeLevel.Level2:
@@ -109,12 +111,12 @@ namespace AIStudio.Wpf.Mind.Helpers
if (mindNode.NodeLevel == NodeLevel.Level1)
{
var childrensizes = mindNode.Children.Select(p => MeasureOverride(p, mindNode.IsExpanded && isExpanded)).ToArray();
sizewithSpacing = new SizeBase(Math.Max(sizewithSpacing.Width, childrensizes.Sum(p => p.Width)), sizewithSpacing.Height + childrensizes.Max(p => p.Height));
sizewithSpacing = new SizeBase(Math.Max(sizewithSpacing.Width, childrensizes.SumOrDefault(p => p.Width)), sizewithSpacing.Height + childrensizes.MaxOrDefault(p => p.Height));
}
else
{
var childrensizes = mindNode.Children.Select(p => MeasureOverride(p, mindNode.IsExpanded && isExpanded)).ToArray();
sizewithSpacing = new SizeBase(Math.Max(sizewithSpacing.Width, sizewithSpacing.Width * 0.5 + childrensizes.Max(p => p.Width)), sizewithSpacing.Height + childrensizes.Sum(p => p.Height));
sizewithSpacing = new SizeBase(Math.Max(sizewithSpacing.Width, sizewithSpacing.Width * 0.5 + childrensizes.MaxOrDefault(p => p.Width)), sizewithSpacing.Height + childrensizes.SumOrDefault(p => p.Height));
}
}
mindNode.DesiredSize = isExpanded ? sizewithSpacing : new SizeBase(0, 0);
@@ -127,7 +129,7 @@ namespace AIStudio.Wpf.Mind.Helpers
{
if (mindNode.NodeLevel == NodeLevel.Level1)
{
double left = mindNode.MiddlePosition.X - Math.Max(mindNode.DesiredSize.Width, mindNode.Children.Sum(p => p.DesiredSize.Width)) / 2;
double left = mindNode.MiddlePosition.X - Math.Max(mindNode.DesiredSize.Width, mindNode.Children.SumOrDefault(p => p.DesiredSize.Width)) / 2;
double top = mindNode.MiddlePosition.Y + mindNode.ItemHeight / 2 + mindNode.Spacing.Height;
if (mindNode.Children?.Count > 0)
{

View File

@@ -6,6 +6,7 @@ using System.Windows.Media;
using AIStudio.Wpf.DiagramDesigner;
using AIStudio.Wpf.DiagramDesigner.Algorithms;
using AIStudio.Wpf.DiagramDesigner.Geometrys;
using AIStudio.Wpf.DiagramDesigner.Helpers;
using AIStudio.Wpf.Mind.ViewModels;
namespace AIStudio.Wpf.Mind.Helpers
@@ -39,6 +40,7 @@ namespace AIStudio.Wpf.Mind.Helpers
mindNode.ShapeViewModel.SinkMarker.PathStyle = ArrowPathStyle.None;
mindNode.ShapeViewModel.SinkMarker.SizeStyle = ArrowSizeStyle.VerySmall;
mindNode.ConnectorOrientation = ConnectorOrientation.None;
break;
}
case NodeLevel.Level2:
@@ -144,18 +146,18 @@ namespace AIStudio.Wpf.Mind.Helpers
var bottoms = mindNode.Children.Where((p, index) => index % 2 == 1).ToList();
bottoms.ForEach(p => p.ConnectorOrientation = ConnectorOrientation.TopLeft);
var bottomsizes = bottoms.Select(p => MeasureOverride(p, mindNode.IsExpanded && isExpanded)).ToArray();
sizewithSpacing = new SizeBase(sizewithSpacing.Width + bottomoffset + Math.Max(topsizes.Sum(p => p.Width), bottomsizes.Sum(p => p.Width)), sizewithSpacing.Height + topsizes.Max(p => p.Height) + bottomsizes.Max(p => p.Height));
sizewithSpacing = new SizeBase(sizewithSpacing.Width + bottomoffset + Math.Max(topsizes.SumOrDefault(p => p.Width), bottomsizes.SumOrDefault(p => p.Width)), sizewithSpacing.Height + topsizes.MaxOrDefault(p => p.Height) + bottomsizes.MaxOrDefault(p => p.Height));
}
else if (mindNode.NodeLevel == NodeLevel.Level2)
{
var childrensizes = mindNode.Children.Select(p => MeasureOverride(p, mindNode.IsExpanded && isExpanded)).ToArray();
var lastchildsize = childrensizes.LastOrDefault();
sizewithSpacing = new SizeBase(Math.Max(sizewithSpacing.Width, sizewithSpacing.Height + childrensizes.Sum(p => p.Height) - lastchildsize.Height / 2 + lastchildsize.Width), sizewithSpacing.Height + childrensizes.Sum(p => p.Height));
sizewithSpacing = new SizeBase(Math.Max(sizewithSpacing.Width, sizewithSpacing.Height + childrensizes.SumOrDefault(p => p.Height) - lastchildsize.Height / 2 + lastchildsize.Width), sizewithSpacing.Height + childrensizes.SumOrDefault(p => p.Height));
}
else if (mindNode.NodeLevel == NodeLevel.Level3)
{
var childrensizes = mindNode.Children.Select(p => MeasureOverride(p, mindNode.IsExpanded && isExpanded)).ToArray();
sizewithSpacing = new SizeBase(Math.Max(sizewithSpacing.Width, sizewithSpacing.Width * 0.5 + childrensizes.Max(p => p.Width)), sizewithSpacing.Height + childrensizes.Sum(p => p.Height));
sizewithSpacing = new SizeBase(Math.Max(sizewithSpacing.Width, sizewithSpacing.Width * 0.5 + childrensizes.MaxOrDefault(p => p.Width)), sizewithSpacing.Height + childrensizes.SumOrDefault(p => p.Height));
}
}
mindNode.DesiredSize = isExpanded ? sizewithSpacing : new SizeBase(0, 0);

View File

@@ -6,6 +6,7 @@ using System.Windows.Media;
using AIStudio.Wpf.DiagramDesigner;
using AIStudio.Wpf.DiagramDesigner.Algorithms;
using AIStudio.Wpf.DiagramDesigner.Geometrys;
using AIStudio.Wpf.DiagramDesigner.Helpers;
using AIStudio.Wpf.Mind.ViewModels;
namespace AIStudio.Wpf.Mind.Helpers
@@ -35,6 +36,7 @@ namespace AIStudio.Wpf.Mind.Helpers
mindNode.ShapeViewModel.SinkMarker.PathStyle = ArrowPathStyle.Circle;
mindNode.ShapeViewModel.SinkMarker.SizeStyle = ArrowSizeStyle.VerySmall;
mindNode.ConnectorOrientation = ConnectorOrientation.None;
break;
}
case NodeLevel.Level2:
@@ -106,7 +108,7 @@ namespace AIStudio.Wpf.Mind.Helpers
if (mindNode.Children?.Count > 0)
{
var childrensizes = mindNode.Children.Select(p => MeasureOverride(p, mindNode.IsExpanded && isExpanded)).ToArray();
sizewithSpacing = new SizeBase(sizewithSpacing.Width + childrensizes.Max(p => p.Width), Math.Max(sizewithSpacing.Height, childrensizes.Sum(p => p.Height)));
sizewithSpacing = new SizeBase(sizewithSpacing.Width + childrensizes.MaxOrDefault(p => p.Width), Math.Max(sizewithSpacing.Height, childrensizes.SumOrDefault(p => p.Height)));
}
mindNode.DesiredSize = isExpanded ? sizewithSpacing : new SizeBase(0, 0);
mindNode.Visible = isExpanded;
@@ -117,7 +119,7 @@ namespace AIStudio.Wpf.Mind.Helpers
public void ArrangeOverride(MindNode mindNode)
{
double left = mindNode.MiddlePosition.X + mindNode.ItemWidth / 2 + mindNode.Spacing.Width;
double top = mindNode.MiddlePosition.Y - Math.Min(mindNode.DesiredSize.Height, mindNode.Children.Sum(p => p.DesiredSize.Height)) / 2;
double top = mindNode.MiddlePosition.Y - Math.Min(mindNode.DesiredSize.Height, mindNode.Children.SumOrDefault(p => p.DesiredSize.Height)) / 2;
if (mindNode.Children?.Count > 0)
{
foreach (var child in mindNode.Children)

View File

@@ -6,6 +6,7 @@ using System.Windows.Media;
using AIStudio.Wpf.DiagramDesigner;
using AIStudio.Wpf.DiagramDesigner.Algorithms;
using AIStudio.Wpf.DiagramDesigner.Geometrys;
using AIStudio.Wpf.DiagramDesigner.Helpers;
using AIStudio.Wpf.Mind.ViewModels;
namespace AIStudio.Wpf.Mind.Helpers
@@ -35,6 +36,7 @@ namespace AIStudio.Wpf.Mind.Helpers
mindNode.ShapeViewModel.SinkMarker.PathStyle = ArrowPathStyle.Circle;
mindNode.ShapeViewModel.SinkMarker.SizeStyle = ArrowSizeStyle.VerySmall;
mindNode.ConnectorOrientation = ConnectorOrientation.None;
break;
}
case NodeLevel.Level2:
@@ -114,12 +116,12 @@ namespace AIStudio.Wpf.Mind.Helpers
var lefts = mindNode.Children.Where((p, index) => index % 2 == 1).ToList();
lefts.ForEach(p => p.ConnectorOrientation = ConnectorOrientation.Right);
var leftsizes = lefts.Select(p => MeasureOverride(p, mindNode.IsExpanded && isExpanded)).ToArray();
sizewithSpacing = new SizeBase(sizewithSpacing.Width + rightsizes.Max(p => p.Width) + +leftsizes.Max(p => p.Width), Math.Max(sizewithSpacing.Height, Math.Max(rightsizes.Sum(p => p.Height), leftsizes.Sum(p => p.Height))));
sizewithSpacing = new SizeBase(sizewithSpacing.Width + rightsizes.MaxOrDefault(p => p.Width) + +leftsizes.MaxOrDefault(p => p.Width), Math.Max(sizewithSpacing.Height, Math.Max(rightsizes.SumOrDefault(p => p.Height), leftsizes.SumOrDefault(p => p.Height))));
}
else
{
var childrensizes = mindNode.Children.Select(p => MeasureOverride(p, mindNode.IsExpanded && isExpanded)).ToArray();
sizewithSpacing = new SizeBase(sizewithSpacing.Width + childrensizes.Max(p => p.Width), Math.Max(sizewithSpacing.Height, childrensizes.Sum(p => p.Height)));
sizewithSpacing = new SizeBase(sizewithSpacing.Width + childrensizes.MaxOrDefault(p => p.Width), Math.Max(sizewithSpacing.Height, childrensizes.SumOrDefault(p => p.Height)));
}
}
mindNode.DesiredSize = isExpanded ? sizewithSpacing : new SizeBase(0, 0);
@@ -136,7 +138,7 @@ namespace AIStudio.Wpf.Mind.Helpers
{
var rights = mindNode.Children.Where(p => p.ConnectorOrientation == ConnectorOrientation.Left).ToList();
double left = mindNode.MiddlePosition.X + mindNode.ItemWidth / 2 + mindNode.Spacing.Width;
double lefttop = mindNode.MiddlePosition.Y - Math.Min(mindNode.DesiredSize.Height, rights.Sum(p => p.DesiredSize.Height)) / 2;
double lefttop = mindNode.MiddlePosition.Y - Math.Min(mindNode.DesiredSize.Height, rights.SumOrDefault(p => p.DesiredSize.Height)) / 2;
foreach (var child in rights)
{
child.Left = left + child.Spacing.Width + child.Offset.X;
@@ -154,7 +156,7 @@ namespace AIStudio.Wpf.Mind.Helpers
var lefts = mindNode.Children.Where(p => p.ConnectorOrientation == ConnectorOrientation.Right).ToList();
double right = mindNode.MiddlePosition.X - mindNode.ItemWidth / 2 - mindNode.Spacing.Width;
double righttop = mindNode.MiddlePosition.Y - Math.Min(mindNode.DesiredSize.Height, lefts.Sum(p => p.DesiredSize.Height)) / 2;
double righttop = mindNode.MiddlePosition.Y - Math.Min(mindNode.DesiredSize.Height, lefts.SumOrDefault(p => p.DesiredSize.Height)) / 2;
foreach (var child in lefts)
{
child.Left = right - child.Spacing.Width - child.ItemWidth + child.Offset.X;
@@ -176,7 +178,7 @@ namespace AIStudio.Wpf.Mind.Helpers
if (mindNode.GetLevel2Node().ConnectorOrientation == ConnectorOrientation.Left)
{
double left = mindNode.MiddlePosition.X + mindNode.ItemWidth / 2 + mindNode.Spacing.Width;
double top = mindNode.MiddlePosition.Y - Math.Min(mindNode.DesiredSize.Height, mindNode.Children.Sum(p => p.DesiredSize.Height)) / 2;
double top = mindNode.MiddlePosition.Y - Math.Min(mindNode.DesiredSize.Height, mindNode.Children.SumOrDefault(p => p.DesiredSize.Height)) / 2;
if (mindNode.Children?.Count > 0)
{
foreach (var child in mindNode.Children)
@@ -198,7 +200,7 @@ namespace AIStudio.Wpf.Mind.Helpers
else
{
double right = mindNode.MiddlePosition.X - mindNode.ItemWidth / 2 - mindNode.Spacing.Width;
double top = mindNode.MiddlePosition.Y - Math.Min(mindNode.DesiredSize.Height, mindNode.Children.Sum(p => p.DesiredSize.Height)) / 2;
double top = mindNode.MiddlePosition.Y - Math.Min(mindNode.DesiredSize.Height, mindNode.Children.SumOrDefault(p => p.DesiredSize.Height)) / 2;
if (mindNode.Children?.Count > 0)
{
foreach (var child in mindNode.Children)

View File

@@ -6,6 +6,7 @@ using System.Windows.Media;
using AIStudio.Wpf.DiagramDesigner;
using AIStudio.Wpf.DiagramDesigner.Algorithms;
using AIStudio.Wpf.DiagramDesigner.Geometrys;
using AIStudio.Wpf.DiagramDesigner.Helpers;
using AIStudio.Wpf.Mind.ViewModels;
namespace AIStudio.Wpf.Mind.Helpers
@@ -33,6 +34,8 @@ namespace AIStudio.Wpf.Mind.Helpers
mindNode.FontViewModel.FontSize = 15;
mindNode.ShapeViewModel.SinkMarker.PathStyle = ArrowPathStyle.None;
mindNode.ShapeViewModel.SinkMarker.SizeStyle = ArrowSizeStyle.VerySmall;
mindNode.ConnectorOrientation = ConnectorOrientation.None;
break;
}
case NodeLevel.Level2:
@@ -107,7 +110,7 @@ namespace AIStudio.Wpf.Mind.Helpers
if (mindNode.Children?.Count > 0)
{
var childrensizes = mindNode.Children.Select(p => MeasureOverride(p, mindNode.IsExpanded && isExpanded)).ToArray();
sizewithSpacing = new SizeBase(Math.Max(sizewithSpacing.Width, childrensizes.Sum(p => p.Width)), sizewithSpacing.Height + childrensizes.Max(p => p.Height));
sizewithSpacing = new SizeBase(Math.Max(sizewithSpacing.Width, childrensizes.SumOrDefault(p => p.Width)), sizewithSpacing.Height + childrensizes.MaxOrDefault(p => p.Height));
}
mindNode.DesiredSize = isExpanded ? sizewithSpacing : new SizeBase(0, 0);
mindNode.Visible = isExpanded;
@@ -117,7 +120,7 @@ namespace AIStudio.Wpf.Mind.Helpers
public void ArrangeOverride(MindNode mindNode)
{
double left = mindNode.MiddlePosition.X - Math.Max(mindNode.DesiredSize.Width, mindNode.Children.Sum(p => p.DesiredSize.Width)) / 2;
double left = mindNode.MiddlePosition.X - Math.Max(mindNode.DesiredSize.Width, mindNode.Children.SumOrDefault(p => p.DesiredSize.Width)) / 2;
double top = mindNode.MiddlePosition.Y + mindNode.ItemHeight / 2 + mindNode.Spacing.Height;
if (mindNode.Children?.Count > 0)
{

View File

@@ -1,10 +1,10 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:s="clr-namespace:AIStudio.Wpf.DiagramDesigner">
xmlns:dd="https://gitee.com/akwkevin/aistudio.-wpf.-diagram">
<s:BrushOpacityConverter x:Key="BrushOpacityConverter"/>
<Style x:Key="AIStudio.Styles.Button.Flat" TargetType="{x:Type ButtonBase}">
<dd:BrushOpacityConverter x:Key="BrushOpacityConverter"/>
<Style x:Key="FlatButtonStyle" TargetType="{x:Type ButtonBase}">
<Setter Property="Background" Value="Transparent" />
<Setter Property="Foreground" Value="Black" />
<Setter Property="BorderBrush" Value="Transparent"/>

View File

@@ -0,0 +1,61 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:options="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options">
<DropShadowEffect x:Key="DropShadowEffectStyle"
x:Shared="False"
BlurRadius="4"
Direction="315"
Opacity="0.3"
ShadowDepth="2"
Color="Black"
options:Freeze="True" />
<Style x:Key="ContextMenuStyle" TargetType="{x:Type ContextMenu}">
<Setter Property="Background" Value="White" />
<Setter Property="Block.TextAlignment" Value="Left" />
<Setter Property="BorderBrush" Value="LightGray" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="Foreground" Value="Black" />
<Setter Property="Grid.IsSharedSizeScope" Value="True" />
<Setter Property="HasDropShadow" Value="True" />
<Setter Property="HorizontalContentAlignment" Value="Left" />
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="RenderOptions.ClearTypeHint" Value="Enabled" />
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ContextMenu}">
<Border x:Name="Border"
Width="{TemplateBinding Width}"
Height="{TemplateBinding Height}"
Padding="{TemplateBinding Padding}"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="3"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}">
<ScrollViewer x:Name="SubMenuScrollViewer"
CanContentScroll="True">
<ItemsPresenter x:Name="ItemsPresenter"
Margin="0"
Grid.IsSharedSizeScope="True"
KeyboardNavigation.DirectionalNavigation="Cycle"
KeyboardNavigation.TabNavigation="Cycle"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</ScrollViewer>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="HasDropShadow" Value="True">
<Setter TargetName="Border" Property="Effect" Value="{StaticResource DropShadowEffectStyle}" />
<Setter TargetName="Border" Property="Margin" Value="0 0 6 6" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="TextOptions.TextFormattingMode" Value="Ideal" />
<Setter Property="VerticalContentAlignment" Value="Center" />
</Style>
</ResourceDictionary>

View File

@@ -2,6 +2,7 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/AIStudio.Wpf.Mind;component/Controls/DropDownButton.xaml"/>
<ResourceDictionary Source="pack://application:,,,/AIStudio.Wpf.Mind;component/Controls/MindEditor.xaml"/>
</ResourceDictionary.MergedDictionaries>

View File

@@ -37,6 +37,48 @@
</Setter>
</Style>
<ControlTemplate x:Key="MindNodeLevelStyle" 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="{Binding BorderThickness}"
BorderBrush="{Binding ColorViewModel.LineColor,Converter={StaticResource ColorBrushConverter}}"
Background="{Binding ColorViewModel.FillColor,Converter={StaticResource ColorBrushConverter}}"
CornerRadius="{Binding CornerRadius}">
</Border>
</Grid>
<ToggleButton x:Name="toggle" IsChecked="{Binding IsExpanded}" Style="{StaticResource ExpandCollapseToggleStyle}" HorizontalAlignment="Left" Margin="-15,0,0,0" Visibility="{Binding Children.Count,Converter={StaticResource IntToVisibilityConverter}}"/>
</Grid>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding ConnectorOrientation}" Value="None">
<Setter TargetName="toggle" Property="Visibility" Value="Collapsed"/>
</DataTrigger>
<DataTrigger Binding="{Binding ConnectorOrientation}" Value="Right">
<Setter TargetName="toggle" Property="HorizontalAlignment" Value="Right"/>
<Setter TargetName="toggle" Property="Margin" Value="0,0,-15,0"/>
</DataTrigger>
<DataTrigger Binding="{Binding ConnectorOrientation}" Value="Top">
<Setter TargetName="toggle" Property="HorizontalAlignment" Value="Center"/>
<Setter TargetName="toggle" Property="VerticalAlignment" Value="Top"/>
<Setter TargetName="toggle" Property="Margin" Value="0,-15,0,0"/>
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<ControlTemplate x:Key="MindLevel1NodeStyle" TargetType="{x:Type ContentControl}">
<Grid >
<Grid.ContextMenu>
@@ -143,8 +185,8 @@
</ControlTemplate>
<Style x:Key="MindNodeStyle" TargetType="{x:Type ContentControl}">
<Setter Property="Template" Value="{StaticResource MindLevel1NodeStyle}" />
<Style.Triggers>
<Setter Property="Template" Value="{StaticResource MindNodeLevelStyle}" />
<!--<Style.Triggers>
<DataTrigger Binding="{Binding NodeLevel}" Value="Level1">
<Setter Property="Template" Value="{StaticResource MindLevel1NodeStyle}" />
</DataTrigger>
@@ -154,7 +196,7 @@
<DataTrigger Binding="{Binding NodeLevel}" Value="Level3">
<Setter Property="Template" Value="{StaticResource MindLevel3NodeStyle}" />
</DataTrigger>
</Style.Triggers>
</Style.Triggers>-->
</Style>
<DataTemplate DataType="{x:Type viewmodel:MindNode}">

View File

@@ -0,0 +1,57 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using AIStudio.Wpf.DiagramDesigner;
namespace AIStudio.Wpf.Mind.ViewModels
{
public interface IMindDiagramViewModel : IDiagramViewModel
{
MindType MindType
{
get;set;
}
SimpleCommand AddParentCommand
{
get;
}
SimpleCommand AddChildCommand
{
get;
}
SimpleCommand AddPeerCommand
{
get;
}
SimpleCommand DeleteSelfCommand
{
get;
}
SimpleCommand MoveForwardCommand
{
get;
}
SimpleCommand MoveBackCommand
{
get;
}
SimpleCommand ChangeMindTypeCommand
{
get;
}
SimpleCommand ChangeMindThemeCommand
{
get;
}
}
}

View File

@@ -0,0 +1,382 @@
using System;
using System.Collections.Generic;
using System.Linq;
using AIStudio.Wpf.DiagramDesigner;
namespace AIStudio.Wpf.Mind.ViewModels
{
public class MindDiagramViewModel : DiagramViewModel, IMindDiagramViewModel
{
#region
private MindType _mindType = Mind.MindType.Mind;
public MindType MindType
{
get
{
return _mindType;
}
set
{
if (SetProperty(ref _mindType, value))
{
ExecutedChangeMindTypeCommand(value);
}
}
}
#endregion
#region
public SimpleCommand AddParentCommand
{
get; private set;
}
public SimpleCommand AddChildCommand
{
get; private set;
}
public SimpleCommand AddPeerCommand
{
get; private set;
}
public SimpleCommand DeleteSelfCommand
{
get; private set;
}
public SimpleCommand MoveForwardCommand
{
get; private set;
}
public SimpleCommand MoveBackCommand
{
get; private set;
}
private SimpleCommand _changeMindTypeCommand;
public SimpleCommand ChangeMindTypeCommand
{
get
{
return this._changeMindTypeCommand ?? (this._changeMindTypeCommand = new SimpleCommand(MindExecuteEnable, this.ExecutedChangeMindTypeCommand));
}
}
public SimpleCommand ChangeMindThemeCommand
{
get; private set;
}
public SimpleCommand ResetLayout
{
get; private set;
}
public SimpleCommand Expand2Level1
{
get; private set;
}
public SimpleCommand Expand2Level2
{
get; private set;
}
public SimpleCommand Expand2Level3
{
get; private set;
}
public SimpleCommand Expand2Level4
{
get; private set;
}
public SimpleCommand Expand2Level5
{
get; private set;
}
public SimpleCommand Expand2Level6
{
get; private set;
}
#endregion
public MindDiagramViewModel()
{
AddChildCommand = new SimpleCommand(MindExecuteEnable, ExecuteAddChildCommand);
AddParentCommand = new SimpleCommand(MindLevelEnable, ExecuteAddParentCommand);
AddPeerCommand = new SimpleCommand(MindLevelEnable, ExecuteAddPeerCommand);
DeleteSelfCommand = new SimpleCommand(MindLevelEnable, ExecuteDeleteSelfCommand);
MoveForwardCommand = new SimpleCommand(MindExecuteEnable, ExecuteMoveForwardCommand);
MoveBackCommand = new SimpleCommand(MindExecuteEnable, ExecuteMoveBackCommand);
}
public bool MindExecuteEnable(object para)
{
if (ExecuteEnable(para) == false) return false;
if (SelectedItem is MindNode) return true;
return false;
}
private bool MindLevelEnable(object obj)
{
if (MindExecuteEnable(obj) == false) return false;
return (SelectedItem as MindNode).NodeLevel != NodeLevel.Level1;
}
#region
private void ExecutedChangeMindTypeCommand(object obj)
{
if (obj is MindType mindType)
{
Items.OfType<MindNode>().ToList().ForEach(item => { item.MindType = mindType; });
Items.OfType<MindNode>().FirstOrDefault()?.LayoutUpdated();
}
}
public void ExecuteAddChildCommand(object parameter)
{
List<MindNode> items = new List<MindNode>();
if (parameter is MindNode parent)
{
}
else if (parameter is IEnumerable<MindNode> para)
{
parent = para.FirstOrDefault();//第一个固定为父节点
items = para.Skip(1).ToList();
}
else
{
parent = SelectedItem as MindNode;
}
if (items?.Count == 0)
{
var node = new MindNode(this, (NodeLevel)Math.Min((int)parent.NodeLevel + 1, (int)NodeLevel.Level3), this.MindType) { Text = "分支主题" };
items.Add(node);
}
DoCommandManager.DoNewCommand(this.ToString(),
() => {
foreach (var item in items)
{
parent.AddChild(item);
}
parent.LayoutUpdated();
},
() => {
foreach (var item in items)
{
parent.RemoveChild(item);
}
parent.LayoutUpdated();
});
}
public void ExecuteAddParentCommand(object parameter)
{
List<MindNode> items = new List<MindNode>();
if (parameter is MindNode node)
{
}
else if (parameter is IEnumerable<MindNode> para)
{
node = para.FirstOrDefault();//第一个固定为父节点
items = para.Skip(1).ToList();
}
else
{
node = SelectedItem as MindNode;
}
if (items?.Count == 0)
{
items.Add(new MindNode(this, node.NodeLevel, this.MindType) { Text = "分支主题" });
}
if (node.Parent is MindNode parent)
{
DoCommandManager.DoNewCommand(this.ToString(),
() => {
int index = parent.Children.IndexOf(node);
parent.AddChild(items[0], index + 1);
parent.RemoveChild(node);
items[0].AddChild(node);
parent.LayoutUpdated();
},
() => {
int index = parent.Children.IndexOf(items[0]);
items[0].RemoveChild(node);
parent.AddChild(node, index + 1);
parent.LayoutUpdated();
});
}
}
public void ExecuteAddPeerCommand(object parameter)
{
List<MindNode> items = new List<MindNode>();
if (parameter is MindNode pear)
{
}
else if (parameter is IEnumerable<MindNode> para)
{
pear = para.FirstOrDefault();//第一个固定为同级节点
items = para.Skip(1).ToList();
}
else
{
pear = SelectedItem as MindNode;
}
if (items?.Count == 0)
{
var node = new MindNode(this, pear.NodeLevel, this.MindType) { Text = "分支主题" };
items.Add(node);
}
if (pear.Parent is MindNode parent)
{
DoCommandManager.DoNewCommand(this.ToString(),
() => {
int index = parent.Children.IndexOf(pear);
for (int i = 0; i < items.Count; i++)
{
parent.AddChild(items[i], index + i + 1);
}
parent.LayoutUpdated();
},
() => {
for (int i = 0; i < items.Count; i++)
{
parent.RemoveChild(items[i]);
}
parent.LayoutUpdated();
});
}
}
private void ExecuteMoveBackCommand(object parameter)
{
if (parameter is MindNode node)
{
}
else
{
node = SelectedItem as MindNode;
}
if (node.Parent is MindNode parent)
{
DoCommandManager.DoNewCommand(this.ToString(),
() => {
int index = parent.Children.IndexOf(node);
if (index < parent.Children.Count - 1)
{
parent.RemoveChild(node);
parent.AddChild(node, index + 1);
parent.LayoutUpdated();
}
},
() => {
int index = parent.Children.IndexOf(node);
if (index > 0)
{
parent.RemoveChild(node);
parent.AddChild(node, index - 1);
parent.LayoutUpdated();
}
});
}
}
private void ExecuteMoveForwardCommand(object parameter)
{
if (parameter is MindNode node)
{
}
else
{
node = SelectedItem as MindNode;
}
if (node.Parent is MindNode parent)
{
DoCommandManager.DoNewCommand(this.ToString(),
() => {
int index = parent.Children.IndexOf(node);
if (index > 0)
{
parent.RemoveChild(node);
parent.AddChild(node, index - 1);
parent.LayoutUpdated();
}
},
() => {
int index = parent.Children.IndexOf(node);
if (index < parent.Children.Count - 1)
{
parent.RemoveChild(node);
parent.AddChild(node, index + 1);
parent.LayoutUpdated();
}
});
}
}
private void ExecuteDeleteSelfCommand(object parameter)
{
if (parameter is MindNode node)
{
}
else
{
node = SelectedItem as MindNode;
}
if (node.Parent is MindNode parent)
{
int index = parent.Children.IndexOf(node);
DoCommandManager.DoNewCommand(this.ToString(),
() => {
parent.RemoveChild(node, true);
parent.LayoutUpdated();
},
() => {
parent.AddChild(node, index);
parent.LayoutUpdated();
});
}
}
#endregion
}
}

View File

@@ -20,6 +20,7 @@ using AIStudio.Wpf.Flowchart.Models;
using AIStudio.Wpf.Mind.Helpers;
using AIStudio.Wpf.Mind.Models;
namespace AIStudio.Wpf.Mind.ViewModels
{
public class MindNode : DiagramItemViewModel
@@ -31,20 +32,19 @@ namespace AIStudio.Wpf.Mind.ViewModels
public MindNode(IDiagramViewModel root, NodeLevel nodeLevel, MindType mindType = MindType.Mind) : base(root)
{
NodeLevel = nodeLevel;
MindType = mindType;
MindType = mindType;
InitLayout();
MindLayout.Appearance(this);
InitLayout(true);
}
public MindNode(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer)
{
InitLayout();
InitLayout(false);
}
public MindNode(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType)
{
InitLayout();
InitLayout(false);
}
public override SelectableItemBase GetSerializableObject()
@@ -58,21 +58,25 @@ namespace AIStudio.Wpf.Mind.ViewModels
EnabledForConnection = false;
AddChildCommand = new SimpleCommand(Command_Enable, ExecuteAddChildCommand);
AddParentCommand = new SimpleCommand(Level_Enable, ExecuteAddParentCommand);
AddPeerCommand = new SimpleCommand(Level_Enable, ExecuteAddPeerCommand);
DeleteCommand = new SimpleCommand(Level_Enable, ExecuteDeleteCommand);
MoveForwardCommand = new SimpleCommand(Command_Enable, ExecuteMoveForwardCommand);
MoveBackCommand = new SimpleCommand(Command_Enable, ExecuteMoveBackCommand);
AddChildCommand = (Root as IMindDiagramViewModel)?.AddChildCommand;
AddParentCommand = (Root as IMindDiagramViewModel)?.AddParentCommand;
AddPeerCommand = (Root as IMindDiagramViewModel)?.AddPeerCommand;
DeleteSelfCommand = (Root as IMindDiagramViewModel)?.DeleteSelfCommand;
MoveForwardCommand = (Root as IMindDiagramViewModel)?.MoveForwardCommand;
MoveBackCommand = (Root as IMindDiagramViewModel)?.MoveBackCommand;
BuildMenuOptions();
this.PropertyChanged += this.Item_PropertyChanged;
}
protected void InitLayout()
protected void InitLayout(bool initAppearance)
{
var layout = GlobalType.AllTypes.Where(p => typeof(IMindLayout).IsAssignableFrom(p)).FirstOrDefault(p => p.Name == MindType.ToString() + "Layout");
MindLayout = layout != null ? (System.Activator.CreateInstance(layout) as IMindLayout) : new MindLayout();
if (initAppearance)
{
MindLayout.Appearance(this);
}
this.PropertyChanged += this.Item_PropertyChanged;
}
protected override void LoadDesignerItemViewModel(SelectableItemBase designerbase)
@@ -103,8 +107,6 @@ namespace AIStudio.Wpf.Mind.ViewModels
}
private bool Level_Enable(object obj)
{
if (Command_Enable(obj) == false) return false;
@@ -115,7 +117,7 @@ namespace AIStudio.Wpf.Mind.ViewModels
#region
public IMindLayout MindLayout
{
get;set;
get; set;
}
[Browsable(false)]
private NodeLevel _nodeLevel;
@@ -130,6 +132,29 @@ namespace AIStudio.Wpf.Mind.ViewModels
SetProperty(ref _nodeLevel, value);
}
}
//public MindNode ParentNode
//{
// get
// {
// return Parent as MindNode;
// }
//}
//public int NodeLevel
//{
// get
// {
// if (ParentNode == null)
// {
// return 0;
// }
// else
// {
// return ParentNode.NodeLevel + 1;
// }
// }
//}
private MindType _mindType;
public MindType MindType
@@ -142,7 +167,7 @@ namespace AIStudio.Wpf.Mind.ViewModels
{
SetProperty(ref _mindType, value);
}
}
}
private bool _isExpanded = true;
public bool IsExpanded
@@ -214,7 +239,7 @@ namespace AIStudio.Wpf.Mind.ViewModels
public bool LayoutUpdating
{
get;set;
get; set;
}
#endregion
@@ -314,7 +339,7 @@ namespace AIStudio.Wpf.Mind.ViewModels
get; private set;
}
public SimpleCommand DeleteCommand
public SimpleCommand DeleteSelfCommand
{
get; private set;
}
@@ -337,136 +362,37 @@ namespace AIStudio.Wpf.Mind.ViewModels
CinchMenuItem menuItem = new CinchMenuItem();
menuItem.Text = "下级";
menuItem.Command = AddChildCommand;
menuItem.CommandParameter = this;
menuOptions.Add(menuItem);
menuItem = new CinchMenuItem();
menuItem.Text = "同级";
menuItem.Command = AddPeerCommand;
menuItem.CommandParameter = this;
menuOptions.Add(menuItem);
menuItem = new CinchMenuItem();
menuItem.Text = "上级";
menuItem.Command = AddParentCommand;
menuItem.CommandParameter = this;
menuOptions.Add(menuItem);
menuItem = new CinchMenuItem();
menuItem.Text = "前移";
menuItem.Command = MoveForwardCommand;
menuItem.CommandParameter = this;
menuOptions.Add(menuItem);
menuItem = new CinchMenuItem();
menuItem.Text = "后移";
menuItem.Command = MoveBackCommand;
menuItem.CommandParameter = this;
menuOptions.Add(menuItem);
menuItem = new CinchMenuItem();
menuItem.Text = "删除";
menuItem.Command = DeleteCommand;
menuItem.Command = DeleteSelfCommand;
menuItem.CommandParameter = this;
menuOptions.Add(menuItem);
}
#endregion
#region
public void ExecuteAddChildCommand(object obj)
{
if (obj is MindNode node)
{
}
else
{
node = new MindNode(Root, (NodeLevel)Math.Min((int)NodeLevel + 1, (int)NodeLevel.Level3), this.MindType) { 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, this.MindType) { Text = "分支主题" };
else
node = new MindNode(Root, NodeLevel.Level3, this.MindType) { 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, this.MindType) { Text = "分支主题" };
else
node = new MindNode(Root, NodeLevel.Level3, this.MindType) { 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, true);
LayoutUpdated();
}
}
#region
public void AddChild(MindNode item, int index = -1)
{
if (this.NodeLevel == NodeLevel.Level1)
@@ -486,13 +412,10 @@ namespace AIStudio.Wpf.Mind.ViewModels
this.Children.Add(item);
}
item.Parent = this;
Root?.DirectAddItemCommand.Execute(item);
ConnectionViewModel connector = MindLayout?.GetConnectionViewModel(this, item);
Root?.DirectAddItemCommand.Execute(connector);
Root?.ClearSelectedItemsCommand.Execute(new SelectableDesignerItemViewModelBase[] { connector });
Root?.BringForwardCommand.Execute(new DesignerItemViewModelBase[] { item });
Root?.DirectAddItemCommand.Execute(new SelectableDesignerItemViewModelBase[] { item, connector });
connector.ZIndex = -1;
this.IsSelected = true;
}
public void RemoveChild(MindNode item, bool removeall = false)
@@ -535,17 +458,9 @@ namespace AIStudio.Wpf.Mind.ViewModels
case nameof(NodeLevel):
MindLayout?.Appearance(this);
break;
//case nameof(MindType):
// if (NodeLevel == NodeLevel.Level1)
// {
// MindLayout?.Appearance(this);
// LayoutUpdated();
// }
// else
// {
// GetLevel1Node().MindType = MindType;
// }
// break;
case nameof(MindType):
InitLayout(true);
break;
case nameof(Left):
{
if (e is ValuePropertyChangedEventArgs valuePropertyChangedEventArgs)
@@ -625,7 +540,7 @@ namespace AIStudio.Wpf.Mind.ViewModels
#endregion
}
public class LinkInfo : BindableBase
{
private string _url;

View File

@@ -1,7 +1,7 @@
<Project>
<!-- Project properties -->
<PropertyGroup>
<TargetFrameworks>netcoreapp3.1;net5.0-windows</TargetFrameworks>
<TargetFrameworks>net461;netcoreapp3.1;net5.0-windows</TargetFrameworks>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">