17 Commits

Author SHA1 Message Date
艾竹
73f393cbf4 一个小bug 2022-12-13 19:48:34 +08:00
艾竹
13f30f23d8 分离出一个小demo 2022-11-30 19:07:40 +08:00
艾竹
513937c1d6 整理一下项目文件 2022-10-28 22:45:39 +08:00
艾竹
334297b074 update README.md. 2022-06-22 12:12:33 +00:00
艾竹
c443603cfd 笔误啊 2022-05-29 16:02:25 +08:00
艾竹
179f8a45cc update LICENSE. 2021-11-02 03:15:17 +00:00
akwkevin
8bec38e040 连接线改成path绘制,方便绘制曲线 2021-08-06 18:12:05 +08:00
akwkevin
e9c043ae3a 连接线修改,为支持改变连接点做准备 2021-08-05 18:20:22 +08:00
akwkevin
b0c9855d05 保存SFC数据到xml,json完成, 2021-08-03 18:19:47 +08:00
艾竹
5a1f869141 Merge branch 'master' of https://gitee.com/akwkevin/aistudio.-wpf.-diagram 2021-08-02 22:05:25 +08:00
艾竹
d11a3ef2fd 阀门优化 2021-08-02 22:04:58 +08:00
艾竹
9063ca5950 update README.md. 2021-08-02 13:50:45 +00:00
akwkevin
831256336f sfc逻辑基本完成 2021-08-02 18:08:43 +08:00
艾竹
0b8258003f sfc界面处理完成,还差顺序逻辑控制过程 2021-08-01 22:30:12 +08:00
akwkevin
9a0e85e1a9 sfc实现中 2021-07-30 18:26:35 +08:00
akwkevin
336249f313 结构调整,便于后续扩展 2021-07-29 13:55:18 +08:00
艾竹
87be7a8021 update README.md. 2021-07-28 01:19:33 +00:00
626 changed files with 5908 additions and 2938 deletions

135
.editorconfig Normal file
View File

@@ -0,0 +1,135 @@
# Rules in this file were initially inferred by Visual Studio IntelliCode from the F:\AIStudio.Wpf.Controls codebase based on best match to current usage at 2022/1/23
# You can modify the rules from these initially generated values to suit your own policies
# You can learn more about editorconfig here: https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-code-style-settings-reference
[*.cs]
#Core editorconfig formatting - indentation
#use soft tabs (spaces) for indentation
indent_style = space
#Formatting - indentation options
#indent switch case contents.
csharp_indent_case_contents = true
#csharp_indent_case_contents_when_block
csharp_indent_case_contents_when_block = true
#indent switch labels
csharp_indent_switch_labels = true
#Formatting - new line options
#place catch statements on a new line
csharp_new_line_before_catch = true
#place else statements on a new line
csharp_new_line_before_else = true
#require finally statements to be on a new line after the closing brace
csharp_new_line_before_finally = true
#require members of object intializers to be on separate lines
csharp_new_line_before_members_in_object_initializers = true
#require braces to be on a new line for types, control_blocks, methods, properties, object_collection_array_initializers, and accessors (also known as "Allman" style)
csharp_new_line_before_open_brace = types, control_blocks, methods, properties, object_collection_array_initializers, accessors
#Formatting - organize using options
#sort System.* using directives alphabetically, and place them before other usings
dotnet_sort_system_directives_first = true
#Formatting - spacing options
#require NO space between a cast and the value
csharp_space_after_cast = false
#require a space before the colon for bases or interfaces in a type declaration
csharp_space_after_colon_in_inheritance_clause = true
#require a space after a keyword in a control flow statement such as a for loop
csharp_space_after_keywords_in_control_flow_statements = true
#require a space before the colon for bases or interfaces in a type declaration
csharp_space_before_colon_in_inheritance_clause = true
#remove space within empty argument list parentheses
csharp_space_between_method_call_empty_parameter_list_parentheses = false
#remove space between method call name and opening parenthesis
csharp_space_between_method_call_name_and_opening_parenthesis = false
#do not place space characters after the opening parenthesis and before the closing parenthesis of a method call
csharp_space_between_method_call_parameter_list_parentheses = false
#remove space within empty parameter list parentheses for a method declaration
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
#place a space character after the opening parenthesis and before the closing parenthesis of a method declaration parameter list.
csharp_space_between_method_declaration_parameter_list_parentheses = false
#Formatting - wrapping options
#leave code block on separate lines
csharp_preserve_single_line_blocks = false
#leave statements and member declarations on the same line
csharp_preserve_single_line_statements = true
#Style - Code block preferences
#prefer curly braces even for one line of code
csharp_prefer_braces = true:suggestion
#Style - expression bodied member options
#prefer block bodies for accessors
csharp_style_expression_bodied_accessors = false:suggestion
#prefer block bodies for constructors
csharp_style_expression_bodied_constructors = false:suggestion
#prefer block bodies for methods
csharp_style_expression_bodied_methods = false:suggestion
#prefer block bodies for properties
csharp_style_expression_bodied_properties = false:suggestion
#Style - expression level options
#prefer out variables to be declared inline in the argument list of a method call when possible
csharp_style_inlined_variable_declaration = true:suggestion
#prefer the language keyword for member access expressions, instead of the type name, for types that have a keyword to represent them
dotnet_style_predefined_type_for_member_access = true:suggestion
#Style - Expression-level preferences
#prefer default(T) over default
csharp_prefer_simple_default_expression = false:suggestion
#prefer objects to be initialized using object initializers when possible
dotnet_style_object_initializer = true:suggestion
#Style - implicit and explicit types
#prefer explicit type over var in all cases, unless overridden by another code style rule
csharp_style_var_elsewhere = false:suggestion
#prefer explicit type over var to declare variables with built-in system types such as int
csharp_style_var_for_built_in_types = false:suggestion
#prefer explicit type over var when the type is already mentioned on the right-hand side of a declaration
csharp_style_var_when_type_is_apparent = false:suggestion
#Style - language keyword and framework type options
#prefer the language keyword for local variables, method parameters, and class members, instead of the type name, for types that have a keyword to represent them
dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
#Style - modifier options
#prefer accessibility modifiers to be declared except for public interface members. This will currently not differ from always and will act as future proofing for if C# adds default interface methods.
dotnet_style_require_accessibility_modifiers = for_non_interface_members:suggestion
#Style - Modifier preferences
#when this rule is set to a list of modifiers, prefer the specified ordering.
csharp_preferred_modifier_order = public,private,protected,internal,static,readonly,override,virtual,new,async:suggestion
#Style - Pattern matching
#prefer is expression with type casts instead of pattern matching
csharp_style_pattern_matching_over_as_with_null_check = false:suggestion
#Style - qualification options
#prefer events to be prefaced with this. in C# or Me. in Visual Basic
dotnet_style_qualification_for_event = true:suggestion
#prefer fields not to be prefaced with this. or Me. in Visual Basic
dotnet_style_qualification_for_field = false:suggestion
#prefer methods not to be prefaced with this. or Me. in Visual Basic
dotnet_style_qualification_for_method = false:suggestion
#prefer properties not to be prefaced with this. or Me. in Visual Basic
dotnet_style_qualification_for_property = false:suggestion

View File

@@ -1,18 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
namespace AIStudio.Wpf.ADiagram.Controls
{
public class CancelRoutedEventArgs : RoutedEventArgs
{
public CancelRoutedEventArgs(RoutedEvent routedEvent, object source) : base(routedEvent, source)
{
}
public bool Cancel { get; set; }
}
}

View File

@@ -1,35 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
namespace AIStudio.Wpf.ADiagram.Controls
{
/// <summary>
/// 带上下文菜单的切换按钮
/// </summary>
public class ContextMenuToggleButton : ToggleButton
{
public ContextMenu Menu { get; set; }
protected override void OnClick()
{
base.OnClick();
if (Menu != null)
{
if (IsChecked == true)
{
Menu.PlacementTarget = this;
Menu.IsOpen = true;
}
else
{
Menu.IsOpen = false;
}
}
}
}
}

View File

@@ -1,58 +0,0 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=System.Runtime"
xmlns:controls="clr-namespace:AIStudio.Wpf.ADiagram.Controls">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/Util.Controls.Handy;component/Style/Themes/ScrollViewer.xaml"/>
</ResourceDictionary.MergedDictionaries>
<ControlTemplate x:Key="ScrollViewerBaseControlTemplate" TargetType="controls:ScrollViewer">
<ControlTemplate.Resources>
<Storyboard x:Key="Storyboard1">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity" Storyboard.TargetName="PART_VerticalScrollBar">
<EasingDoubleKeyFrame KeyTime="0:0:.1" Value=".8"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity" Storyboard.TargetName="PART_HorizontalScrollBar">
<EasingDoubleKeyFrame KeyTime="0:0:.1" Value=".8"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="Storyboard2">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity" Storyboard.TargetName="PART_VerticalScrollBar">
<EasingDoubleKeyFrame KeyTime="0:0:.2" Value="0"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity" Storyboard.TargetName="PART_HorizontalScrollBar">
<EasingDoubleKeyFrame KeyTime="0:0:.2" Value="0"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</ControlTemplate.Resources>
<Grid x:Name="Grid" Background="{TemplateBinding Background}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<ScrollContentPresenter x:Name="PART_ScrollContentPresenter" Grid.RowSpan="2" Grid.ColumnSpan="2" CanContentScroll="{TemplateBinding CanContentScroll}" CanHorizontallyScroll="False" CanVerticallyScroll="False" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" Grid.Column="0" Margin="{TemplateBinding Padding}" Grid.Row="0"/>
<ScrollBar x:Name="PART_VerticalScrollBar" Opacity="0" Style="{StaticResource ScrollBarBaseStyle}" AutomationProperties.AutomationId="VerticalScrollBar" Cursor="Arrow" Grid.Column="1" Maximum="{TemplateBinding ScrollableHeight}" Minimum="0" Grid.Row="0" Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}" Value="{Binding VerticalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" ViewportSize="{TemplateBinding ViewportHeight}"/>
<ScrollBar x:Name="PART_HorizontalScrollBar" Opacity="0" Style="{StaticResource ScrollBarBaseStyle}" AutomationProperties.AutomationId="HorizontalScrollBar" Cursor="Arrow" Grid.Column="0" Maximum="{TemplateBinding ScrollableWidth}" Minimum="0" Orientation="Horizontal" Grid.Row="1" Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}" Value="{Binding HorizontalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" ViewportSize="{TemplateBinding ViewportWidth}"/>
</Grid>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding IsMouseOver,RelativeSource={RelativeSource Self}}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource Storyboard1}"/>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard Storyboard="{StaticResource Storyboard2}"/>
</DataTrigger.ExitActions>
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<Style x:Key="ScrollViewerBaseStyle" TargetType="controls:ScrollViewer">
<Setter Property="VerticalScrollBarVisibility" Value="Auto"/>
<Setter Property="Focusable" Value="False"/>
<Setter Property="Template" Value="{StaticResource ScrollViewerBaseControlTemplate}"/>
</Style>
</ResourceDictionary>

View File

@@ -1,237 +0,0 @@
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
namespace AIStudio.Wpf.ADiagram.Controls
{
public class ScrollViewer : System.Windows.Controls.ScrollViewer
{
private double _totalVerticalOffset;
private double _totalHorizontalOffset;
private bool _isRunning;
/// <summary>
/// 滚动方向
/// </summary>
public static readonly DependencyProperty OrientationProperty = DependencyProperty.Register(
"Orientation", typeof(Orientation), typeof(ScrollViewer), new PropertyMetadata(Orientation.Vertical));
/// <summary>
/// 滚动方向
/// </summary>
public Orientation Orientation
{
get => (Orientation)GetValue(OrientationProperty);
set => SetValue(OrientationProperty, value);
}
/// <summary>
/// 是否响应鼠标滚轮操作
/// </summary>
public static readonly DependencyProperty CanMouseWheelProperty = DependencyProperty.Register(
"CanMouseWheel", typeof(bool), typeof(ScrollViewer), new PropertyMetadata(true));
/// <summary>
/// 是否响应鼠标滚轮操作
/// </summary>
public bool CanMouseWheel
{
get => (bool)GetValue(CanMouseWheelProperty);
set => SetValue(CanMouseWheelProperty, value);
}
protected override void OnMouseWheel(MouseWheelEventArgs e)
{
if (!CanMouseWheel) return;
if (!IsInertiaEnabled)
{
if (Orientation == Orientation.Vertical)
{
base.OnMouseWheel(e);
}
else
{
_totalHorizontalOffset = HorizontalOffset;
CurrentHorizontalOffset = HorizontalOffset;
_totalHorizontalOffset = Math.Min(Math.Max(0, _totalHorizontalOffset - e.Delta), ScrollableWidth);
CurrentHorizontalOffset = _totalHorizontalOffset;
}
return;
}
e.Handled = true;
if (Orientation == Orientation.Vertical)
{
if (!_isRunning)
{
_totalVerticalOffset = VerticalOffset;
CurrentVerticalOffset = VerticalOffset;
}
_totalVerticalOffset = Math.Min(Math.Max(0, _totalVerticalOffset - e.Delta), ScrollableHeight);
ScrollToVerticalOffsetInternal(_totalVerticalOffset);
}
else
{
if (!_isRunning)
{
_totalHorizontalOffset = HorizontalOffset;
CurrentHorizontalOffset = HorizontalOffset;
}
_totalHorizontalOffset = Math.Min(Math.Max(0, _totalHorizontalOffset - e.Delta), ScrollableWidth);
ScrollToHorizontalOffsetInternal(_totalHorizontalOffset);
}
}
internal void ScrollToTopInternal(double milliseconds = 500)
{
if (!_isRunning)
{
_totalVerticalOffset = VerticalOffset;
CurrentVerticalOffset = VerticalOffset;
}
ScrollToVerticalOffsetInternal(0, milliseconds);
}
internal void ScrollToVerticalOffsetInternal(double offset, double milliseconds = 500)
{
var animation = AnimationHelper.CreateAnimation(offset, milliseconds);
animation.EasingFunction = new CubicEase
{
EasingMode = EasingMode.EaseOut
};
animation.FillBehavior = FillBehavior.Stop;
animation.Completed += (s, e1) =>
{
CurrentVerticalOffset = offset;
_isRunning = false;
};
_isRunning = true;
BeginAnimation(CurrentVerticalOffsetProperty, animation, HandoffBehavior.Compose);
}
internal void ScrollToHorizontalOffsetInternal(double offset, double milliseconds = 500)
{
var animation = AnimationHelper.CreateAnimation(offset, milliseconds);
animation.EasingFunction = new CubicEase
{
EasingMode = EasingMode.EaseOut
};
animation.FillBehavior = FillBehavior.Stop;
animation.Completed += (s, e1) =>
{
CurrentHorizontalOffset = offset;
_isRunning = false;
};
_isRunning = true;
BeginAnimation(CurrentHorizontalOffsetProperty, animation, HandoffBehavior.Compose);
}
protected override HitTestResult HitTestCore(PointHitTestParameters hitTestParameters) =>
IsPenetrating ? null : base.HitTestCore(hitTestParameters);
/// <summary>
/// 是否支持惯性
/// </summary>
public static readonly DependencyProperty IsInertiaEnabledProperty = DependencyProperty.RegisterAttached(
"IsInertiaEnabled", typeof(bool), typeof(ScrollViewer), new PropertyMetadata(false));
public static void SetIsInertiaEnabled(DependencyObject element, bool value)
{
element.SetValue(IsInertiaEnabledProperty, value);
}
public static bool GetIsInertiaEnabled(DependencyObject element)
{
return (bool)element.GetValue(IsInertiaEnabledProperty);
}
/// <summary>
/// 是否支持惯性
/// </summary>
public bool IsInertiaEnabled
{
get => (bool)GetValue(IsInertiaEnabledProperty);
set => SetValue(IsInertiaEnabledProperty, value);
}
/// <summary>
/// 控件是否可以穿透点击
/// </summary>
public static readonly DependencyProperty IsPenetratingProperty = DependencyProperty.RegisterAttached(
"IsPenetrating", typeof(bool), typeof(ScrollViewer), new PropertyMetadata(false));
/// <summary>
/// 控件是否可以穿透点击
/// </summary>
public bool IsPenetrating
{
get => (bool)GetValue(IsPenetratingProperty);
set => SetValue(IsPenetratingProperty, value);
}
public static void SetIsPenetrating(DependencyObject element, bool value)
{
element.SetValue(IsPenetratingProperty, value);
}
public static bool GetIsPenetrating(DependencyObject element)
{
return (bool)element.GetValue(IsPenetratingProperty);
}
/// <summary>
/// 当前垂直滚动偏移
/// </summary>
internal static readonly DependencyProperty CurrentVerticalOffsetProperty = DependencyProperty.Register(
"CurrentVerticalOffset", typeof(double), typeof(ScrollViewer), new PropertyMetadata(0d, OnCurrentVerticalOffsetChanged));
private static void OnCurrentVerticalOffsetChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is ScrollViewer ctl && e.NewValue is double v)
{
ctl.ScrollToVerticalOffset(v);
}
}
/// <summary>
/// 当前垂直滚动偏移
/// </summary>
internal double CurrentVerticalOffset
{
// ReSharper disable once UnusedMember.Local
get => (double)GetValue(CurrentVerticalOffsetProperty);
set => SetValue(CurrentVerticalOffsetProperty, value);
}
/// <summary>
/// 当前水平滚动偏移
/// </summary>
internal static readonly DependencyProperty CurrentHorizontalOffsetProperty = DependencyProperty.Register(
"CurrentHorizontalOffset", typeof(double), typeof(ScrollViewer), new PropertyMetadata(0d, OnCurrentHorizontalOffsetChanged));
private static void OnCurrentHorizontalOffsetChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is ScrollViewer ctl && e.NewValue is double v)
{
ctl.ScrollToHorizontalOffset(v);
}
}
/// <summary>
/// 当前水平滚动偏移
/// </summary>
internal double CurrentHorizontalOffset
{
get => (double)GetValue(CurrentHorizontalOffsetProperty);
set => SetValue(CurrentHorizontalOffsetProperty, value);
}
}
}

View File

@@ -1,181 +0,0 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:controls="clr-namespace:AIStudio.Wpf.ADiagram.Controls"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=System.Runtime"
xmlns:interactivity="clr-namespace:Util.Controls.Handy.Interactivity">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/Util.Controls.Handy;component/Style/Basic/Paths.xaml"/>
<ResourceDictionary Source="pack://application:,,,/Util.Controls.Handy;component/Style/Basic/Converters.xaml"/>
<ResourceDictionary Source="pack://application:,,,/Util.Controls.Handy;component/Style/Themes/Button.xaml"/>
<ResourceDictionary Source="pack://application:,,,/Util.Controls.Handy;component/Style/Themes/RepeatButton.xaml"/>
<ResourceDictionary Source="pack://application:,,,/Util.Controls.Handy;component/Style/Themes/ToggleButton.xaml"/>
</ResourceDictionary.MergedDictionaries>
<ContextMenu x:Key="TabItemMenu" x:Shared="False">
<MenuItem Command="interactivity:ControlCommands.Close" Header="Close"/>
<MenuItem Command="interactivity:ControlCommands.CloseAll" Header="CloseAll"/>
<MenuItem Command="interactivity:ControlCommands.CloseOther" Header="CloseOther"/>
</ContextMenu>
<Style TargetType="controls:TabItem">
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="Foreground" Value="{DynamicResource MahApps.Brushes.Text}"/>
<Setter Property="Background" Value="{DynamicResource MahApps.Brushes.ThemeBackground}"/>
<Setter Property="BorderThickness" Value="1,0,1,1"/>
<Setter Property="BorderBrush" Value="{DynamicResource MahApps.Brushes.Control.Border}"/>
<Setter Property="Margin" Value="0"/>
<Setter Property="Padding" Value="10,0,0,0"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="VerticalContentAlignment" Value="Stretch"/>
<Setter Property="Menu" Value="{StaticResource TabItemMenu}"/>
<Setter Property="controls:IconElement.Width" Value="16"/>
<Setter Property="controls:IconElement.Height" Value="16"/>
<Setter Property="HeaderTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock Background="Transparent" Text="{Binding Header,RelativeSource={RelativeSource AncestorType=controls:TabItem}}"/>
</DataTemplate>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="controls:TabItem">
<Grid x:Name="templateRoot" SnapsToDevicePixels="true" ContextMenu="{TemplateBinding Menu}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Border Grid.ColumnSpan="3" BorderThickness="{TemplateBinding BorderThickness}" x:Name="mainBorder" BorderBrush="{TemplateBinding BorderBrush}" Background="{TemplateBinding Background}" Margin="0">
<Border Margin="0,0,0,-1" x:Name="innerBorder" Background="{DynamicResource MahApps.Brushes.Gray8}" Visibility="Collapsed"/>
</Border>
<Path x:Name="PathMain" Margin="10,0,0,0" Grid.Column="0" Width="{TemplateBinding controls:IconElement.Width}" Height="{TemplateBinding controls:IconElement.Height}" Fill="{TemplateBinding Foreground}" SnapsToDevicePixels="True" Stretch="Uniform" Data="{TemplateBinding controls:IconElement.Geometry}"/>
<ContentPresenter Grid.Column="1" x:Name="contentPresenter" ContentSource="Header" Focusable="False" HorizontalAlignment="Stretch" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="Center"/>
<Border Name="BorderMask" Grid.Column="1" HorizontalAlignment="Right" Width="20" Background="{TemplateBinding Background}">
<Border.OpacityMask>
<LinearGradientBrush EndPoint="1,0" StartPoint="0,0">
<GradientStop Color="White" Offset="1"/>
<GradientStop Offset="0"/>
</LinearGradientBrush>
</Border.OpacityMask>
</Border>
<Button Grid.Column="2" Focusable="False" Command="interactivity:ControlCommands.Close" Visibility="{TemplateBinding ShowCloseButton,Converter={StaticResource Boolean2VisibilityConverter}}" Background="Transparent" Style="{StaticResource ButtonCustom}" Width="28">
<Path Fill="{DynamicResource MahApps.Brushes.Text}" Width="8" Height="8" Style="{StaticResource ClosePathStyle}"/>
</Button>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="true">
<Setter Property="Panel.ZIndex" Value="1"/>
<Setter Property="Visibility" TargetName="innerBorder" Value="Visible"/>
<Setter Property="Background" TargetName="BorderMask" Value="{DynamicResource MahApps.Brushes.Gray8}"/>
</Trigger>
<Trigger Property="controls:IconElement.Geometry" Value="{x:Null}">
<Setter Property="Visibility" Value="Collapsed" TargetName="PathMain"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<ControlTemplate x:Key="TabControlPlusTemplate" TargetType="controls:TabControl">
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}">
<Grid x:Name="templateRoot" ClipToBounds="true" SnapsToDevicePixels="true" KeyboardNavigation.TabNavigation="Local">
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="ColumnDefinition0"/>
<ColumnDefinition x:Name="ColumnDefinition1" Width="0"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Border Background="{TemplateBinding Background}" BorderThickness="0,0,0,1" BorderBrush="{DynamicResource MahApps.Brushes.Control.Border}">
<controls:TabPanel MinHeight="{TemplateBinding TabItemHeight}" TabItemHeight="{TemplateBinding TabItemHeight}" TabItemWidth="{TemplateBinding TabItemWidth}" IsTabFillEnabled="{TemplateBinding IsTabFillEnabled}" Margin="0,0,-1,-1" x:Name="PART_HeaderPanel" HorizontalAlignment="Left" Background="{DynamicResource SecondaryTextBrush}" IsItemsHost="true" KeyboardNavigation.TabIndex="1" Panel.ZIndex="1">
<interactivity:Interaction.Behaviors>
<interactivity:FluidMoveBehavior AppliesTo="Children" Duration="{Binding FluidMoveDuration,ElementName=PART_HeaderPanel}">
<interactivity:FluidMoveBehavior.EaseX>
<CubicEase EasingMode="EaseOut"/>
</interactivity:FluidMoveBehavior.EaseX>
</interactivity:FluidMoveBehavior>
</interactivity:Interaction.Behaviors>
</controls:TabPanel>
</Border>
<Border x:Name="contentPanel" Background="{DynamicResource MahApps.Brushes.ThemeBackground}" Grid.Column="0" KeyboardNavigation.DirectionalNavigation="Contained" Grid.Row="1" KeyboardNavigation.TabIndex="2" KeyboardNavigation.TabNavigation="Local">
<ContentPresenter x:Name="PART_SelectedContentHost" ContentSource="SelectedContent" Margin="{TemplateBinding Padding}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Border>
<Border Visibility="{Binding Visibility,ElementName=PART_OverflowButton}" Margin="0,-1,0,0" Grid.Row="0" Grid.Column="0" BorderThickness="1,0,0,1" BorderBrush="{DynamicResource MahApps.Brushes.Control.Border}" Background="{DynamicResource MahApps.Brushes.Gray8}" HorizontalAlignment="Right">
<controls:ContextMenuToggleButton x:Name="PART_OverflowButton" Visibility="Collapsed" Style="{StaticResource ToggleButtonIconTransparent}" controls:IconSwitchElement.Geometry="{StaticResource DownGeometry}" controls:IconSwitchElement.GeometrySelected="{StaticResource UpGeometry}"/>
</Border>
</Grid>
</Border>
</ControlTemplate>
<ControlTemplate x:Key="TabControlPlusScrollableTemplate" TargetType="controls:TabControl">
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}">
<Grid x:Name="templateRoot" ClipToBounds="true" SnapsToDevicePixels="true" KeyboardNavigation.TabNavigation="Local">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Border Visibility="{TemplateBinding ShowScrollButton,Converter={StaticResource Boolean2VisibilityConverter}}" Margin="0,-1,0,0" Grid.Row="0" Grid.Column="0" BorderThickness="0,0,1,1" BorderBrush="{DynamicResource MahApps.Brushes.Control.Border}" Background="{DynamicResource MahApps.Brushes.Gray8}" HorizontalAlignment="Left" Panel.ZIndex="2">
<Border.CacheMode>
<BitmapCache SnapsToDevicePixels="True"/>
</Border.CacheMode>
<RepeatButton Focusable="False" Style="{StaticResource RepeatButtonIcon}" Padding="8" controls:IconElement.Geometry="{StaticResource LeftGeometry}" Foreground="{DynamicResource MahApps.Brushes.Text}" Background="{DynamicResource MahApps.Brushes.ThemeBackground}" x:Name="PART_ScrollButtonLeft"/>
</Border>
<controls:ScrollViewer HorizontalScrollBarVisibility="Hidden" CanMouseWheel="True" Orientation="Horizontal" IsInertiaEnabled="True" Grid.Row="0" Grid.Column="1" IsDeferredScrollingEnabled="True" x:Name="PART_OverflowScrollviewer">
<Border Background="{TemplateBinding Background}" BorderThickness="0,0,0,1" BorderBrush="{DynamicResource MahApps.Brushes.Control.Border}" Name="PART_HeaderBorder">
<controls:TabPanel MinHeight="{TemplateBinding TabItemHeight}" TabItemHeight="{TemplateBinding TabItemHeight}" TabItemWidth="{TemplateBinding TabItemWidth}" IsTabFillEnabled="{TemplateBinding IsTabFillEnabled}" Margin="0,0,-1,-1" x:Name="PART_HeaderPanel" HorizontalAlignment="Left" Background="{DynamicResource SecondaryTextBrush}" IsItemsHost="true" KeyboardNavigation.TabIndex="1" Panel.ZIndex="1">
<interactivity:Interaction.Behaviors>
<interactivity:FluidMoveBehavior AppliesTo="Children" Duration="{Binding FluidMoveDuration,ElementName=PART_HeaderPanel}">
<interactivity:FluidMoveBehavior.EaseX>
<CubicEase EasingMode="EaseOut"/>
</interactivity:FluidMoveBehavior.EaseX>
</interactivity:FluidMoveBehavior>
</interactivity:Interaction.Behaviors>
</controls:TabPanel>
</Border>
</controls:ScrollViewer>
<Border Margin="0,-1,0,0" Grid.Row="0" Grid.Column="2" BorderThickness="1,0,0,1" BorderBrush="{DynamicResource MahApps.Brushes.Control.Border}" Background="{DynamicResource MahApps.Brushes.Gray8}" HorizontalAlignment="Right">
<Border.CacheMode>
<BitmapCache SnapsToDevicePixels="True"/>
</Border.CacheMode>
<StackPanel Orientation="Horizontal">
<RepeatButton Focusable="False" Visibility="{TemplateBinding ShowScrollButton,Converter={StaticResource Boolean2VisibilityConverter}}" Style="{StaticResource RepeatButtonIcon}" BorderBrush="{DynamicResource MahApps.Brushes.Control.Border}" Padding="8" controls:IconElement.Geometry="{StaticResource RightGeometry}" Foreground="{DynamicResource MahApps.Brushes.Text}" Background="{DynamicResource MahApps.Brushes.ThemeBackground}" x:Name="PART_ScrollButtonRight"/>
<Border Visibility="{Binding Visibility,ElementName=PART_OverflowButton}" Width="1" Background="{DynamicResource MahApps.Brushes.Control.Border}"/>
<controls:ContextMenuToggleButton x:Name="PART_OverflowButton" Visibility="Collapsed" Style="{StaticResource ToggleButtonIconTransparent}" controls:IconSwitchElement.Geometry="{StaticResource DownGeometry}" controls:IconSwitchElement.GeometrySelected="{StaticResource UpGeometry}"/>
</StackPanel>
</Border>
<Border x:Name="contentPanel" Background="{DynamicResource MahApps.Brushes.ThemeBackground}" KeyboardNavigation.DirectionalNavigation="Contained" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="3" KeyboardNavigation.TabIndex="2" KeyboardNavigation.TabNavigation="Local">
<ContentPresenter x:Name="PART_SelectedContentHost" ContentSource="SelectedContent" Margin="{TemplateBinding Padding}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Border>
</Grid>
</Border>
</ControlTemplate>
<Style TargetType="controls:TabControl">
<Setter Property="Padding" Value="0"/>
<Setter Property="Background" Value="{DynamicResource MahApps.Brushes.Gray8}"/>
<Setter Property="BorderBrush" Value="{DynamicResource MahApps.Brushes.Control.Border}"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Template" Value="{StaticResource TabControlPlusTemplate}"/>
<Style.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsScrollable" Value="True"/>
<Condition Property="IsTabFillEnabled" Value="False"/>
</MultiTrigger.Conditions>
<Setter Property="Template" Value="{StaticResource TabControlPlusScrollableTemplate}"/>
</MultiTrigger>
</Style.Triggers>
</Style>
</ResourceDictionary>

View File

@@ -1,443 +0,0 @@
using System;
using System.Collections;
using System.Collections.Specialized;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
namespace AIStudio.Wpf.ADiagram.Controls
{
[TemplatePart(Name = OverflowButtonKey, Type = typeof(ContextMenuToggleButton))]
[TemplatePart(Name = HeaderPanelKey, Type = typeof(TabPanel))]
[TemplatePart(Name = OverflowScrollviewer, Type = typeof(ScrollViewer))]
[TemplatePart(Name = ScrollButtonLeft, Type = typeof(ButtonBase))]
[TemplatePart(Name = ScrollButtonRight, Type = typeof(ButtonBase))]
[TemplatePart(Name = HeaderBorder, Type = typeof(System.Windows.Controls.Border))]
public class TabControl : System.Windows.Controls.TabControl
{
private const string OverflowButtonKey = "PART_OverflowButton";
private const string HeaderPanelKey = "PART_HeaderPanel";
private const string OverflowScrollviewer = "PART_OverflowScrollviewer";
private const string ScrollButtonLeft = "PART_ScrollButtonLeft";
private const string ScrollButtonRight = "PART_ScrollButtonRight";
private const string HeaderBorder = "PART_HeaderBorder";
private ContextMenuToggleButton _buttonOverflow;
internal TabPanel HeaderPanel { get; private set; }
private ScrollViewer _scrollViewerOverflow;
private ButtonBase _buttonScrollLeft;
private ButtonBase _buttonScrollRight;
private System.Windows.Controls.Border _headerBorder;
/// <summary>
/// 是否为内部操作
/// </summary>
internal bool IsInternalAction;
/// <summary>
/// 是否启用动画
/// </summary>
public static readonly DependencyProperty IsAnimationEnabledProperty = DependencyProperty.Register(
"IsAnimationEnabled", typeof(bool), typeof(TabControl), new PropertyMetadata(false));
/// <summary>
/// 是否启用动画
/// </summary>
public bool IsAnimationEnabled
{
get => (bool)GetValue(IsAnimationEnabledProperty);
set => SetValue(IsAnimationEnabledProperty, value);
}
/// <summary>
/// 是否可以拖动
/// </summary>
public static readonly DependencyProperty IsDraggableProperty = DependencyProperty.Register(
"IsDraggable", typeof(bool), typeof(TabControl), new PropertyMetadata(false));
/// <summary>
/// 是否可以拖动
/// </summary>
public bool IsDraggable
{
get => (bool)GetValue(IsDraggableProperty);
set => SetValue(IsDraggableProperty, value);
}
/// <summary>
/// 是否显示关闭按钮
/// </summary>
public static readonly DependencyProperty ShowCloseButtonProperty = DependencyProperty.RegisterAttached(
"ShowCloseButton", typeof(bool), typeof(TabControl), new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.Inherits));
public static void SetShowCloseButton(DependencyObject element, bool value)
=> element.SetValue(ShowCloseButtonProperty, value);
public static bool GetShowCloseButton(DependencyObject element)
=> (bool) element.GetValue(ShowCloseButtonProperty);
/// <summary>
/// 是否显示关闭按钮
/// </summary>
public bool ShowCloseButton
{
get => (bool)GetValue(ShowCloseButtonProperty);
set => SetValue(ShowCloseButtonProperty, value);
}
/// <summary>
/// 是否显示上下文菜单
/// </summary>
public static readonly DependencyProperty ShowContextMenuProperty = DependencyProperty.RegisterAttached(
"ShowContextMenu", typeof(bool), typeof(TabControl), new FrameworkPropertyMetadata(true, FrameworkPropertyMetadataOptions.Inherits));
public static void SetShowContextMenu(DependencyObject element, bool value)
=> element.SetValue(ShowContextMenuProperty, value);
public static bool GetShowContextMenu(DependencyObject element)
=> (bool) element.GetValue(ShowContextMenuProperty);
/// <summary>
/// 是否显示上下文菜单
/// </summary>
public bool ShowContextMenu
{
get => (bool)GetValue(ShowContextMenuProperty);
set => SetValue(ShowContextMenuProperty, value);
}
/// <summary>
/// 是否将标签填充
/// </summary>
public static readonly DependencyProperty IsTabFillEnabledProperty = DependencyProperty.Register(
"IsTabFillEnabled", typeof(bool), typeof(TabControl), new PropertyMetadata(false));
/// <summary>
/// 是否将标签填充
/// </summary>
public bool IsTabFillEnabled
{
get => (bool)GetValue(IsTabFillEnabledProperty);
set => SetValue(IsTabFillEnabledProperty, value);
}
/// <summary>
/// 标签宽度
/// </summary>
public static readonly DependencyProperty TabItemWidthProperty = DependencyProperty.Register(
"TabItemWidth", typeof(double), typeof(TabControl), new PropertyMetadata(200.0));
/// <summary>
/// 标签宽度
/// </summary>
public double TabItemWidth
{
get => (double)GetValue(TabItemWidthProperty);
set => SetValue(TabItemWidthProperty, value);
}
/// <summary>
/// 标签高度
/// </summary>
public static readonly DependencyProperty TabItemHeightProperty = DependencyProperty.Register(
"TabItemHeight", typeof(double), typeof(TabControl), new PropertyMetadata(30.0));
/// <summary>
/// 标签高度
/// </summary>
public double TabItemHeight
{
get => (double)GetValue(TabItemHeightProperty);
set => SetValue(TabItemHeightProperty, value);
}
/// <summary>
/// 是否可以滚动
/// </summary>
public static readonly DependencyProperty IsScrollableProperty = DependencyProperty.Register(
"IsScrollable", typeof(bool), typeof(TabControl), new PropertyMetadata(false));
/// <summary>
/// 是否可以滚动
/// </summary>
public bool IsScrollable
{
get => (bool) GetValue(IsScrollableProperty);
set => SetValue(IsScrollableProperty, value);
}
/// <summary>
/// 是否显示溢出按钮
/// </summary>
public static readonly DependencyProperty ShowOverflowButtonProperty = DependencyProperty.Register(
"ShowOverflowButton", typeof(bool), typeof(TabControl), new PropertyMetadata(true));
/// <summary>
/// 是否显示溢出按钮
/// </summary>
public bool ShowOverflowButton
{
get => (bool) GetValue(ShowOverflowButtonProperty);
set => SetValue(ShowOverflowButtonProperty, value);
}
/// <summary>
/// 是否显示滚动按钮
/// </summary>
public static readonly DependencyProperty ShowScrollButtonProperty = DependencyProperty.Register(
"ShowScrollButton", typeof(bool), typeof(TabControl), new PropertyMetadata(false));
/// <summary>
/// 是否显示滚动按钮
/// </summary>
public bool ShowScrollButton
{
get => (bool) GetValue(ShowScrollButtonProperty);
set => SetValue(ShowScrollButtonProperty, value);
}
/// <summary>
/// 可见的标签数量
/// </summary>
private int _itemShowCount;
protected override void OnItemsChanged(NotifyCollectionChangedEventArgs e)
{
base.OnItemsChanged(e);
if (HeaderPanel == null)
{
IsInternalAction = false;
return;
}
UpdateOverflowButton();
if (IsInternalAction)
{
IsInternalAction = false;
return;
}
if (IsAnimationEnabled)
{
HeaderPanel.SetCurrentValue(TabPanel.FluidMoveDurationProperty, new Duration(TimeSpan.FromMilliseconds(200)));
}
else
{
HeaderPanel.FluidMoveDuration = new Duration(TimeSpan.FromSeconds(0));
}
if (e.Action == NotifyCollectionChangedAction.Add)
{
for (var i = 0; i < Items.Count; i++)
{
if (!(ItemContainerGenerator.ContainerFromIndex(i) is TabItem item)) return;
item.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
item.TabPanel = HeaderPanel;
}
}
_headerBorder?.InvalidateMeasure();
IsInternalAction = false;
}
public override void OnApplyTemplate()
{
if (_buttonOverflow != null)
{
if (_buttonOverflow.Menu != null)
{
_buttonOverflow.Menu.Closed -= Menu_Closed;
_buttonOverflow.Menu = null;
}
_buttonOverflow.Click -= ButtonOverflow_Click;
}
if (_buttonScrollLeft != null) _buttonScrollLeft.Click -= ButtonScrollLeft_Click;
if (_buttonScrollRight != null) _buttonScrollRight.Click -= ButtonScrollRight_Click;
base.OnApplyTemplate();
HeaderPanel = GetTemplateChild(HeaderPanelKey) as TabPanel;
if (IsTabFillEnabled) return;
_buttonOverflow = GetTemplateChild(OverflowButtonKey) as ContextMenuToggleButton;
_scrollViewerOverflow = GetTemplateChild(OverflowScrollviewer) as ScrollViewer;
_buttonScrollLeft = GetTemplateChild(ScrollButtonLeft) as ButtonBase;
_buttonScrollRight = GetTemplateChild(ScrollButtonRight) as ButtonBase;
_headerBorder = GetTemplateChild(HeaderBorder) as System.Windows.Controls.Border;
if (_buttonScrollLeft != null) _buttonScrollLeft.Click += ButtonScrollLeft_Click;
if (_buttonScrollRight != null) _buttonScrollRight.Click += ButtonScrollRight_Click;
if (_buttonOverflow != null)
{
var menu = new System.Windows.Controls.ContextMenu
{
Placement = PlacementMode.Bottom,
PlacementTarget = _buttonOverflow
};
menu.Closed += Menu_Closed;
_buttonOverflow.Menu = menu;
_buttonOverflow.Click += ButtonOverflow_Click;
}
}
protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
{
base.OnRenderSizeChanged(sizeInfo);
UpdateOverflowButton();
}
private void UpdateOverflowButton()
{
if (!IsTabFillEnabled)
{
_itemShowCount = (int)(ActualWidth / TabItemWidth);
if (_buttonOverflow != null)
{
_buttonOverflow.Visibility = (ShowOverflowButton && Items.Count > 0 && Items.Count >= _itemShowCount) ? Visibility.Visible : Visibility.Collapsed;
}
}
}
private void Menu_Closed(object sender, RoutedEventArgs e) => _buttonOverflow.IsChecked = false;
private void ButtonScrollRight_Click(object sender, RoutedEventArgs e) =>
_scrollViewerOverflow.ScrollToHorizontalOffsetInternal(Math.Min(
_scrollViewerOverflow.CurrentHorizontalOffset + TabItemWidth, _scrollViewerOverflow.ScrollableWidth));
private void ButtonScrollLeft_Click(object sender, RoutedEventArgs e) =>
_scrollViewerOverflow.ScrollToHorizontalOffsetInternal(Math.Max(
_scrollViewerOverflow.CurrentHorizontalOffset - TabItemWidth, 0));
private void ButtonOverflow_Click(object sender, RoutedEventArgs e)
{
if (_buttonOverflow.IsChecked == true)
{
_buttonOverflow.Menu.Items.Clear();
for (var i = 0; i < Items.Count; i++)
{
if(!(ItemContainerGenerator.ContainerFromIndex(i) is TabItem item)) continue;
var menuItem = new System.Windows.Controls.MenuItem
{
HeaderStringFormat = ItemStringFormat,
HeaderTemplate = ItemTemplate,
HeaderTemplateSelector = ItemTemplateSelector,
Header = item.Header,
Width = TabItemWidth,
IsChecked = item.IsSelected,
IsCheckable = true
};
menuItem.Click += delegate
{
_buttonOverflow.IsChecked = false;
var list = GetActualList();
if (list == null) return;
var actualItem = ItemContainerGenerator.ItemFromContainer(item);
if (actualItem == null) return;
var index = list.IndexOf(actualItem);
if (index >= _itemShowCount)
{
list.Remove(actualItem);
list.Insert(0, actualItem);
if (IsAnimationEnabled)
{
HeaderPanel.SetCurrentValue(TabPanel.FluidMoveDurationProperty, new Duration(TimeSpan.FromMilliseconds(200)));
}
else
{
HeaderPanel.FluidMoveDuration = new Duration(TimeSpan.FromSeconds(0));
}
HeaderPanel.ForceUpdate = true;
HeaderPanel.Measure(new Size(HeaderPanel.DesiredSize.Width, ActualHeight));
HeaderPanel.ForceUpdate = false;
SetCurrentValue(SelectedIndexProperty, 0);
}
item.IsSelected = true;
};
_buttonOverflow.Menu.Items.Add(menuItem);
}
}
}
internal double GetHorizontalOffset() => _scrollViewerOverflow?.CurrentHorizontalOffset ?? 0;
internal void UpdateScroll() => _scrollViewerOverflow?.RaiseEvent(new MouseWheelEventArgs(Mouse.PrimaryDevice, Environment.TickCount, 0)
{
RoutedEvent = MouseWheelEvent
});
internal void CloseAllItems() => CloseOtherItems(null);
internal void CloseOtherItems(TabItem currentItem)
{
var actualItem = currentItem != null ? ItemContainerGenerator.ItemFromContainer(currentItem) : null;
var list = GetActualList();
if (list == null) return;
IsInternalAction = true;
for (var i = 0; i < Items.Count; i++)
{
var item = list[i];
if (!Equals(item, actualItem) && item != null)
{
var argsClosing = new CancelRoutedEventArgs(TabItem.ClosingEvent, item);
if (!(ItemContainerGenerator.ContainerFromItem(item) is TabItem tabItem)) continue;
tabItem.RaiseEvent(argsClosing);
if (argsClosing.Cancel) return;
tabItem.RaiseEvent(new RoutedEventArgs(TabItem.ClosedEvent, item));
list.Remove(item);
i--;
}
}
SetCurrentValue(SelectedIndexProperty, Items.Count == 0 ? -1 : 0);
}
internal IList GetActualList()
{
IList list;
if (ItemsSource != null)
{
list = ItemsSource as IList;
}
else
{
list = Items;
}
return list;
}
protected override bool IsItemItsOwnContainerOverride(object item) => item is TabItem;
protected override DependencyObject GetContainerForItemOverride() => new TabItem();
}
}

View File

@@ -1,467 +0,0 @@
using System;
using System.Windows;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
namespace AIStudio.Wpf.ADiagram.Controls
{
public class TabItem : System.Windows.Controls.TabItem
{
/// <summary>
/// 动画速度
/// </summary>
private const int AnimationSpeed = 150;
/// <summary>
/// 选项卡是否处于拖动状态
/// </summary>
private static bool ItemIsDragging;
/// <summary>
/// 选项卡是否等待被拖动
/// </summary>
private bool _isWaiting;
/// <summary>
/// 拖动中的选项卡坐标
/// </summary>
private Point _dragPoint;
/// <summary>
/// 鼠标按下时选项卡位置
/// </summary>
private int _mouseDownIndex;
/// <summary>
/// 鼠标按下时选项卡横向偏移
/// </summary>
private double _mouseDownOffsetX;
/// <summary>
/// 鼠标按下时的坐标
/// </summary>
private Point _mouseDownPoint;
/// <summary>
/// 右侧可移动的最大值
/// </summary>
private double _maxMoveRight;
/// <summary>
/// 左侧可移动的最大值
/// </summary>
private double _maxMoveLeft;
/// <summary>
/// 选项卡宽度
/// </summary>
public double ItemWidth { get; internal set; }
/// <summary>
/// 选项卡拖动等待距离在鼠标移动了超过20个像素无关单位后选项卡才开始被拖动
/// </summary>
private const double WaitLength = 20;
/// <summary>
/// 选项卡是否处于拖动状态
/// </summary>
private bool _isDragging;
/// <summary>
/// 选项卡是否已经被拖动
/// </summary>
private bool _isDragged;
/// <summary>
/// 目标横向位移
/// </summary>
internal double TargetOffsetX { get; set; }
/// <summary>
/// 当前编号
/// </summary>
private int _currentIndex;
/// <summary>
/// 标签容器横向滚动距离
/// </summary>
private double _scrollHorizontalOffset;
private TabPanel _tabPanel;
/// <summary>
/// 标签容器
/// </summary>
internal TabPanel TabPanel
{
get
{
if (_tabPanel == null && TabControlParent != null)
{
_tabPanel = TabControlParent.HeaderPanel;
}
return _tabPanel;
}
set => _tabPanel = value;
}
/// <summary>
/// 当前编号
/// </summary>
internal int CurrentIndex
{
get => _currentIndex;
set
{
if (_currentIndex == value || value < 0) return;
var oldIndex = _currentIndex;
_currentIndex = value;
UpdateItemOffsetX(oldIndex);
}
}
/// <summary>
/// 是否显示关闭按钮
/// </summary>
public static readonly DependencyProperty ShowCloseButtonProperty =
TabControl.ShowCloseButtonProperty.AddOwner(typeof(TabItem));
/// <summary>
/// 是否显示关闭按钮
/// </summary>
public bool ShowCloseButton
{
get => (bool)GetValue(ShowCloseButtonProperty);
set => SetValue(ShowCloseButtonProperty, value);
}
public static void SetShowCloseButton(DependencyObject element, bool value)
=> element.SetValue(ShowCloseButtonProperty, value);
public static bool GetShowCloseButton(DependencyObject element)
=> (bool)element.GetValue(ShowCloseButtonProperty);
/// <summary>
/// 是否显示上下文菜单
/// </summary>
public static readonly DependencyProperty ShowContextMenuProperty =
TabControl.ShowContextMenuProperty.AddOwner(typeof(TabItem), new FrameworkPropertyMetadata(OnShowContextMenuChanged));
private static void OnShowContextMenuChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var ctl = (TabItem) d;
if (ctl.Menu != null)
{
var show = (bool)e.NewValue;
ctl.Menu.IsEnabled = show;
ctl.Menu.Show(show);
}
}
/// <summary>
/// 是否显示上下文菜单
/// </summary>
public bool ShowContextMenu
{
get => (bool) GetValue(ShowContextMenuProperty);
set => SetValue(ShowContextMenuProperty, value);
}
public static void SetShowContextMenu(DependencyObject element, bool value)
=> element.SetValue(ShowContextMenuProperty, value);
public static bool GetShowContextMenu(DependencyObject element)
=> (bool)element.GetValue(ShowContextMenuProperty);
public static readonly DependencyProperty MenuProperty = DependencyProperty.Register(
"Menu", typeof(System.Windows.Controls.ContextMenu), typeof(TabItem), new PropertyMetadata(default(System.Windows.Controls.ContextMenu), OnMenuChanged));
private static void OnMenuChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var ctl = (TabItem) d;
ctl.OnMenuChanged(e.NewValue as System.Windows.Controls.ContextMenu);
}
private void OnMenuChanged(System.Windows.Controls.ContextMenu menu)
{
if (IsLoaded && menu != null)
{
var parent = TabControlParent;
if (parent == null) return;
var item = parent.ItemContainerGenerator.ItemFromContainer(this);
menu.DataContext = item;
menu.SetBinding(IsEnabledProperty, new Binding(ShowContextMenuProperty.Name)
{
Source = this
});
menu.SetBinding(VisibilityProperty, new Binding(ShowContextMenuProperty.Name)
{
Source = this,
Converter = ResourceHelper.GetResource<IValueConverter>("Boolean2VisibilityConverter")
});
}
}
public System.Windows.Controls.ContextMenu Menu
{
get => (System.Windows.Controls.ContextMenu) GetValue(MenuProperty);
set => SetValue(MenuProperty, value);
}
/// <summary>
/// 更新选项卡横向偏移
/// </summary>
/// <param name="oldIndex"></param>
private void UpdateItemOffsetX(int oldIndex)
{
if (!_isDragging) return;
var moveItem = TabPanel.ItemDic[CurrentIndex];
moveItem.CurrentIndex -= CurrentIndex - oldIndex;
var offsetX = moveItem.TargetOffsetX;
var resultX = offsetX + (oldIndex - CurrentIndex) * ItemWidth;
TabPanel.ItemDic[CurrentIndex] = this;
TabPanel.ItemDic[moveItem.CurrentIndex] = moveItem;
moveItem.CreateAnimation(offsetX, resultX);
}
public TabItem()
{
CommandBindings.Add(new CommandBinding(ControlCommands.Close, (s, e) => Close()));
CommandBindings.Add(new CommandBinding(ControlCommands.CloseAll,
(s, e) => { TabControlParent.CloseAllItems(); }));
CommandBindings.Add(new CommandBinding(ControlCommands.CloseOther,
(s, e) => { TabControlParent.CloseOtherItems(this); }));
Loaded += (s, e) => OnMenuChanged(Menu);
}
private Util.Controls.Handy.TabControls.TabControl TabControlParent => System.Windows.Controls.ItemsControl.ItemsControlFromItemContainer(this) as TabControl;
protected override void OnMouseRightButtonDown(MouseButtonEventArgs e)
{
base.OnMouseRightButtonDown(e);
IsSelected = true;
Focus();
}
protected override void OnHeaderChanged(object oldHeader, object newHeader)
{
base.OnHeaderChanged(oldHeader, newHeader);
if (TabPanel != null)
{
TabPanel.ForceUpdate = true;
InvalidateMeasure();
TabPanel.ForceUpdate = true;
}
}
internal void Close()
{
var parent = TabControlParent;
if (parent == null) return;
var item = parent.ItemContainerGenerator.ItemFromContainer(this);
var argsClosing = new CancelRoutedEventArgs(ClosingEvent, item);
RaiseEvent(argsClosing);
if (argsClosing.Cancel) return;
TabPanel.SetCurrentValue(TabPanel.FluidMoveDurationProperty, parent.IsAnimationEnabled
? new Duration(TimeSpan.FromMilliseconds(200))
: new Duration(TimeSpan.FromMilliseconds(1)));
parent.IsInternalAction = true;
RaiseEvent(new RoutedEventArgs(ClosedEvent, item));
var list = parent.GetActualList();
list?.Remove(item);
}
protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
{
base.OnMouseLeftButtonDown(e);
var parent = TabControlParent;
if (parent == null) return;
if (parent.IsDraggable && !ItemIsDragging && !_isDragging)
{
parent.UpdateScroll();
TabPanel.FluidMoveDuration = new Duration(TimeSpan.FromSeconds(0));
_mouseDownOffsetX = RenderTransform.Value.OffsetX;
_scrollHorizontalOffset = parent.GetHorizontalOffset();
var mx = TranslatePoint(new Point(), parent).X + _scrollHorizontalOffset;
_mouseDownIndex = CalLocationIndex(mx);
var subIndex = _mouseDownIndex - CalLocationIndex(_scrollHorizontalOffset);
_maxMoveLeft = -subIndex * ItemWidth;
_maxMoveRight = parent.ActualWidth - ActualWidth + _maxMoveLeft;
_isDragging = true;
ItemIsDragging = true;
_isWaiting = true;
_dragPoint = e.GetPosition(parent);
_dragPoint = new Point(_dragPoint.X + _scrollHorizontalOffset, _dragPoint.Y);
_mouseDownPoint = _dragPoint;
CaptureMouse();
}
}
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
if (ItemIsDragging && _isDragging)
{
var parent = TabControlParent;
if (parent == null) return;
var subX = TranslatePoint(new Point(), parent).X + _scrollHorizontalOffset;
CurrentIndex = CalLocationIndex(subX);
var p = e.GetPosition(parent);
p = new Point(p.X + _scrollHorizontalOffset, p.Y);
var subLeft = p.X - _dragPoint.X;
var totalLeft = p.X - _mouseDownPoint.X;
if (Math.Abs(subLeft) <= WaitLength && _isWaiting) return;
_isWaiting = false;
_isDragged = true;
var left = subLeft + RenderTransform.Value.OffsetX;
if (totalLeft < _maxMoveLeft)
{
left = _maxMoveLeft + _mouseDownOffsetX;
}
else if (totalLeft > _maxMoveRight)
{
left = _maxMoveRight + _mouseDownOffsetX;
}
var t = new TranslateTransform(left, 0);
RenderTransform = t;
_dragPoint = p;
}
}
protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e)
{
base.OnMouseLeftButtonUp(e);
ReleaseMouseCapture();
if (_isDragged)
{
var parent = TabControlParent;
if (parent == null) return;
var subX = TranslatePoint(new Point(), parent).X + _scrollHorizontalOffset;
var index = CalLocationIndex(subX);
var left = index * ItemWidth;
var offsetX = RenderTransform.Value.OffsetX;
CreateAnimation(offsetX, offsetX - subX + left, index);
}
_isDragging = false;
ItemIsDragging = false;
_isDragged = false;
}
/// <summary>
/// 创建动画
/// </summary>
internal void CreateAnimation(double offsetX, double resultX, int index = -1)
{
var parent = TabControlParent;
void AnimationCompleted()
{
RenderTransform = new TranslateTransform(resultX, 0);
if (index == -1) return;
var list = parent.GetActualList();
if (list == null) return;
var item = parent.ItemContainerGenerator.ItemFromContainer(this);
if (item == null) return;
TabPanel.CanUpdate = false;
parent.IsInternalAction = true;
list.Remove(item);
parent.IsInternalAction = true;
list.Insert(index, item);
TabPanel.CanUpdate = true;
TabPanel.ForceUpdate = true;
TabPanel.Measure(new Size(TabPanel.DesiredSize.Width, ActualHeight));
TabPanel.ForceUpdate = false;
Focus();
IsSelected = true;
if (!IsMouseCaptured)
{
parent.SetCurrentValue(Selector.SelectedIndexProperty, _currentIndex);
}
}
TargetOffsetX = resultX;
if (!parent.IsAnimationEnabled)
{
AnimationCompleted();
return;
}
var animation = AnimationHelper.CreateAnimation(resultX, AnimationSpeed);
animation.FillBehavior = FillBehavior.Stop;
animation.Completed += (s1, e1) => AnimationCompleted();
var f = new TranslateTransform(offsetX, 0);
RenderTransform = f;
f.BeginAnimation(TranslateTransform.XProperty, animation, HandoffBehavior.Compose);
}
/// <summary>
/// 计算选项卡当前合适的位置编号
/// </summary>
/// <param name="left"></param>
/// <returns></returns>
private int CalLocationIndex(double left)
{
if (_isWaiting)
{
return CurrentIndex;
}
var maxIndex = TabControlParent.Items.Count - 1;
var div = (int)(left / ItemWidth);
var rest = left % ItemWidth;
var result = rest / ItemWidth > .5 ? div + 1 : div;
return result > maxIndex ? maxIndex : result;
}
public static readonly RoutedEvent ClosingEvent = EventManager.RegisterRoutedEvent("Closing", RoutingStrategy.Bubble, typeof(EventHandler), typeof(TabItem));
public event EventHandler Closing
{
add => AddHandler(ClosingEvent, value);
remove => RemoveHandler(ClosingEvent, value);
}
public static readonly RoutedEvent ClosedEvent = EventManager.RegisterRoutedEvent("Closed", RoutingStrategy.Bubble, typeof(EventHandler), typeof(TabItem));
public event EventHandler Closed
{
add => AddHandler(ClosedEvent, value);
remove => RemoveHandler(ClosedEvent, value);
}
}
}

View File

@@ -1,172 +0,0 @@
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Media;
namespace AIStudio.Wpf.ADiagram.Controls
{
public class TabPanel : System.Windows.Controls.Panel
{
private int _itemCount;
/// <summary>
/// 是否可以更新
/// </summary>
internal bool CanUpdate = true;
/// <summary>
/// 选项卡字典
/// </summary>
internal Dictionary<int, TabItem> ItemDic = new Dictionary<int, TabItem>();
/// <summary>
/// 流式行为持续时间
/// </summary>
public static readonly DependencyProperty FluidMoveDurationProperty = DependencyProperty.Register(
"FluidMoveDuration", typeof(Duration), typeof(TabPanel), new PropertyMetadata(new Duration(TimeSpan.FromMilliseconds(200))));
/// <summary>
/// 流式行为持续时间
/// </summary>
public Duration FluidMoveDuration
{
get => (Duration)GetValue(FluidMoveDurationProperty);
set => SetValue(FluidMoveDurationProperty, value);
}
/// <summary>
/// 是否将标签填充
/// </summary>
public static readonly DependencyProperty IsTabFillEnabledProperty = DependencyProperty.Register(
"IsTabFillEnabled", typeof(bool), typeof(TabPanel), new PropertyMetadata(ValueBoxes.FalseBox));
/// <summary>
/// 是否将标签填充
/// </summary>
public bool IsTabFillEnabled
{
get => (bool)GetValue(IsTabFillEnabledProperty);
set => SetValue(IsTabFillEnabledProperty, value);
}
/// <summary>
/// 标签宽度
/// </summary>
public static readonly DependencyProperty TabItemWidthProperty = DependencyProperty.Register(
"TabItemWidth", typeof(double), typeof(TabPanel), new PropertyMetadata(200.0));
/// <summary>
/// 标签宽度
/// </summary>
public double TabItemWidth
{
get => (double)GetValue(TabItemWidthProperty);
set => SetValue(TabItemWidthProperty, value);
}
/// <summary>
/// 标签高度
/// </summary>
public static readonly DependencyProperty TabItemHeightProperty = DependencyProperty.Register(
"TabItemHeight", typeof(double), typeof(TabPanel), new PropertyMetadata(30.0));
/// <summary>
/// 标签高度
/// </summary>
public double TabItemHeight
{
get => (double)GetValue(TabItemHeightProperty);
set => SetValue(TabItemHeightProperty, value);
}
/// <summary>
/// 是否可以强制更新
/// </summary>
internal bool ForceUpdate;
private Size _oldSize;
/// <summary>
/// 是否已经加载
/// </summary>
private bool _isLoaded;
protected override Size MeasureOverride(Size constraint)
{
if ((_itemCount == InternalChildren.Count || !CanUpdate) && !ForceUpdate) return _oldSize;
constraint.Height = TabItemHeight;
_itemCount = InternalChildren.Count;
var size = new Size();
ItemDic.Clear();
var count = InternalChildren.Count;
if (count == 0)
{
_oldSize = new Size();
return _oldSize;
}
constraint.Width += InternalChildren.Count;
var itemWidth = .0;
var arr = new int[count];
if (!IsTabFillEnabled)
{
itemWidth = TabItemWidth;
}
else
{
if (TemplatedParent is TabControl tabControl)
{
arr = ArithmeticHelper.DivideInt2Arr((int)tabControl.ActualWidth + InternalChildren.Count, count);
}
}
for (var index = 0; index < count; index++)
{
if (IsTabFillEnabled)
{
itemWidth = arr[index];
}
if (InternalChildren[index] is TabItem tabItem)
{
tabItem.RenderTransform = new TranslateTransform();
tabItem.MaxWidth = itemWidth;
var rect = new Rect
{
X = size.Width - tabItem.BorderThickness.Left,
Width = itemWidth,
Height = TabItemHeight
};
tabItem.Arrange(rect);
tabItem.ItemWidth = itemWidth - tabItem.BorderThickness.Left;
tabItem.CurrentIndex = index;
tabItem.TargetOffsetX = 0;
ItemDic[index] = tabItem;
size.Width += tabItem.ItemWidth;
}
}
size.Height = constraint.Height;
_oldSize = size;
return _oldSize;
}
public TabPanel()
{
Loaded += (s, e) =>
{
if (_isLoaded) return;
ForceUpdate = true;
Measure(new Size(DesiredSize.Width, ActualHeight));
ForceUpdate = false;
foreach (var item in ItemDic.Values)
{
item.TabPanel = this;
}
_isLoaded = true;
};
}
}
}

View File

@@ -1,30 +0,0 @@
<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:,,,/Util.DiagramDesigner;component/Resources/Styles/ScrollBar.xaml" />
<ResourceDictionary Source="pack://application:,,,/Util.DiagramDesigner;component/Resources/Styles/Expander.xaml" />
<ResourceDictionary Source="pack://application:,,,/Util.DiagramDesigner;component/Resources/Styles/GroupBox.xaml" />
<ResourceDictionary Source="pack://application:,,,/Util.DiagramDesigner;component/Resources/Styles/ToolTip.xaml" />
<ResourceDictionary Source="pack://application:,,,/Util.DiagramDesigner;component/Resources/Styles/ScrollViewer.xaml" />
<ResourceDictionary Source="pack://application:,,,/Util.DiagramDesigner;component/Resources/Styles/ZoomBox.xaml" />
<ResourceDictionary Source="pack://application:,,,/Util.DiagramDesigner;component/Resources/Styles/DesignerItems.xaml" />
<ResourceDictionary Source="pack://application:,,,/AIStudio.Wpf.ADiagram;component/Themes/Styles/Fluent.xaml" />
<ResourceDictionary Source="pack://application:,,,/AIStudio.Wpf.ADiagram;component/Themes/Styles/Expander.xaml"/>
<ResourceDictionary Source="pack://application:,,,/AIStudio.Wpf.ADiagram;component/Themes/Styles/ListBox.xaml"/>
<ResourceDictionary Source="pack://application:,,,/AIStudio.Wpf.ADiagram;component/Themes/Styles/Slider.xaml"/>
<ResourceDictionary Source="pack://application:,,,/AIStudio.Wpf.ADiagram;component/Themes/Styles/TabControl.xaml"/>
<ResourceDictionary Source="pack://application:,,,/AIStudio.Wpf.ADiagram;component/Themes/Styles/ToggleButton.xaml"/>
<ResourceDictionary Source="pack://application:,,,/AIStudio.Wpf.ADiagram;component/Demos/Flowchart/ViewModels/FlowNode.xaml"/>
<ResourceDictionary Source="pack://application:,,,/AIStudio.Wpf.ADiagram;component/Demos/Logical/ViewModels/LogicalGateItemViewModel.xaml"/>
<ResourceDictionary Source="pack://application:,,,/AIStudio.Wpf.ADiagram;component/Demos/Others/ViewModels/BarcodeDesignerItemViewModel.xaml"/>
<ResourceDictionary Source="pack://application:,,,/AIStudio.Wpf.ADiagram;component/Demos/Others/ViewModels/OutLineTextDesignerItemViewModel.xaml"/>
<ResourceDictionary Source="pack://application:,,,/AIStudio.Wpf.ADiagram;component/Demos/Others/ViewModels/PathItemViewModel.xaml"/>
<ResourceDictionary Source="pack://application:,,,/AIStudio.Wpf.ADiagram;component/Demos/Others/ViewModels/PersistDesignerItemViewModel.xaml"/>
<ResourceDictionary Source="pack://application:,,,/AIStudio.Wpf.ADiagram;component/Demos/Others/ViewModels/SettingsDesignerItemViewModel.xaml"/>
<ResourceDictionary Source="pack://application:,,,/AIStudio.Wpf.ADiagram;component/Demos/Others/ViewModels/SvgDesignerItemViewModel.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>

View File

@@ -1,11 +1,29 @@
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16 # Visual Studio Version 16
VisualStudioVersion = 16.0.29509.3 VisualStudioVersion = 16.0.31727.386
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.DiagramDesigner", "Util.DiagramDesigner\Util.DiagramDesigner.csproj", "{3FC9F09D-83EA-4914-8980-A6B4C3352836}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AIStudio.Wpf.Flowchart", "AIStudio.Wpf.Flowchart\AIStudio.Wpf.Flowchart.csproj", "{86ED5B40-D185-4AFA-B5BD-BC8E78DB8758}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AIStudio.Wpf.ADiagram", "AIStudio.Wpf.ADiagram\AIStudio.Wpf.ADiagram.csproj", "{9D2DCA7D-9E0C-4E6E-ACD9-2CD18C75FE34}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AIStudio.Wpf.Logical", "AIStudio.Wpf.Logical\AIStudio.Wpf.Logical.csproj", "{CC68D39D-7935-4079-9CEB-FC2FD498D511}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Extensions", "Extensions", "{4959F170-02FB-4B7F-8F53-93DAF22713F9}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AIStudio.Wpf.SFC", "AIStudio.Wpf.SFC\AIStudio.Wpf.SFC.csproj", "{2AB69067-277E-4EE0-9949-8326A145EEE4}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AIStudio.Wpf.DiagramApp", "AIStudio.Wpf.DiagramApp\AIStudio.Wpf.DiagramApp.csproj", "{4408F718-9C14-4404-A63B-9B785F9D4F35}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AIStudio.Wpf.DiagramDesigner", "AIStudio.Wpf.DiagramDesigner\AIStudio.Wpf.DiagramDesigner.csproj", "{EA1D893D-2F50-47AA-80A6-EA297F651CCC}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AIStudio.Wpf.DiagramHelper", "AIStudio.Wpf.DiagramHelper\AIStudio.Wpf.DiagramHelper.csproj", "{1E77B64D-B457-4467-A5DB-BB7BA01806D9}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "解决方案项", "解决方案项", "{425E7DBD-25B9-4019-9C84-C37273A7F5C3}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
Directory.Build.Props = Directory.Build.Props
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AIStudio.Wpf.DiagramDesigner.Test", "AIStudio.Wpf.DiagramDesigner.Test\AIStudio.Wpf.DiagramDesigner.Test.csproj", "{559BBB2C-03DE-4C95-B38F-538F0A275793}"
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -13,18 +31,43 @@ Global
Release|Any CPU = Release|Any CPU Release|Any CPU = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution GlobalSection(ProjectConfigurationPlatforms) = postSolution
{3FC9F09D-83EA-4914-8980-A6B4C3352836}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {86ED5B40-D185-4AFA-B5BD-BC8E78DB8758}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3FC9F09D-83EA-4914-8980-A6B4C3352836}.Debug|Any CPU.Build.0 = Debug|Any CPU {86ED5B40-D185-4AFA-B5BD-BC8E78DB8758}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3FC9F09D-83EA-4914-8980-A6B4C3352836}.Release|Any CPU.ActiveCfg = Release|Any CPU {86ED5B40-D185-4AFA-B5BD-BC8E78DB8758}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3FC9F09D-83EA-4914-8980-A6B4C3352836}.Release|Any CPU.Build.0 = Release|Any CPU {86ED5B40-D185-4AFA-B5BD-BC8E78DB8758}.Release|Any CPU.Build.0 = Release|Any CPU
{9D2DCA7D-9E0C-4E6E-ACD9-2CD18C75FE34}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {CC68D39D-7935-4079-9CEB-FC2FD498D511}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9D2DCA7D-9E0C-4E6E-ACD9-2CD18C75FE34}.Debug|Any CPU.Build.0 = Debug|Any CPU {CC68D39D-7935-4079-9CEB-FC2FD498D511}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9D2DCA7D-9E0C-4E6E-ACD9-2CD18C75FE34}.Release|Any CPU.ActiveCfg = Release|Any CPU {CC68D39D-7935-4079-9CEB-FC2FD498D511}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9D2DCA7D-9E0C-4E6E-ACD9-2CD18C75FE34}.Release|Any CPU.Build.0 = Release|Any CPU {CC68D39D-7935-4079-9CEB-FC2FD498D511}.Release|Any CPU.Build.0 = Release|Any CPU
{2AB69067-277E-4EE0-9949-8326A145EEE4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2AB69067-277E-4EE0-9949-8326A145EEE4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2AB69067-277E-4EE0-9949-8326A145EEE4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2AB69067-277E-4EE0-9949-8326A145EEE4}.Release|Any CPU.Build.0 = Release|Any CPU
{4408F718-9C14-4404-A63B-9B785F9D4F35}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4408F718-9C14-4404-A63B-9B785F9D4F35}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4408F718-9C14-4404-A63B-9B785F9D4F35}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4408F718-9C14-4404-A63B-9B785F9D4F35}.Release|Any CPU.Build.0 = Release|Any CPU
{EA1D893D-2F50-47AA-80A6-EA297F651CCC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EA1D893D-2F50-47AA-80A6-EA297F651CCC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EA1D893D-2F50-47AA-80A6-EA297F651CCC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EA1D893D-2F50-47AA-80A6-EA297F651CCC}.Release|Any CPU.Build.0 = Release|Any CPU
{1E77B64D-B457-4467-A5DB-BB7BA01806D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1E77B64D-B457-4467-A5DB-BB7BA01806D9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1E77B64D-B457-4467-A5DB-BB7BA01806D9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1E77B64D-B457-4467-A5DB-BB7BA01806D9}.Release|Any CPU.Build.0 = Release|Any CPU
{559BBB2C-03DE-4C95-B38F-538F0A275793}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{559BBB2C-03DE-4C95-B38F-538F0A275793}.Debug|Any CPU.Build.0 = Debug|Any CPU
{559BBB2C-03DE-4C95-B38F-538F0A275793}.Release|Any CPU.ActiveCfg = Release|Any CPU
{559BBB2C-03DE-4C95-B38F-538F0A275793}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
EndGlobalSection EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{86ED5B40-D185-4AFA-B5BD-BC8E78DB8758} = {4959F170-02FB-4B7F-8F53-93DAF22713F9}
{CC68D39D-7935-4079-9CEB-FC2FD498D511} = {4959F170-02FB-4B7F-8F53-93DAF22713F9}
{2AB69067-277E-4EE0-9949-8326A145EEE4} = {4959F170-02FB-4B7F-8F53-93DAF22713F9}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {D30FC641-F06C-4E35-AEA5-48A9B6E59CE0} SolutionGuid = {D30FC641-F06C-4E35-AEA5-48A9B6E59CE0}
EndGlobalSection EndGlobalSection

View File

@@ -2,7 +2,6 @@
<PropertyGroup> <PropertyGroup>
<OutputType>WinExe</OutputType> <OutputType>WinExe</OutputType>
<TargetFrameworks>netcoreapp3.1</TargetFrameworks>
<UseWPF>true</UseWPF> <UseWPF>true</UseWPF>
</PropertyGroup> </PropertyGroup>
@@ -13,16 +12,6 @@
<Page Remove="DesignItems\Custom\**" /> <Page Remove="DesignItems\Custom\**" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<Compile Remove="Controls\AnimationHelper.cs" />
<Compile Remove="Controls\CancelRoutedEventArgs.cs" />
<Compile Remove="Controls\ContextMenuToggleButton.cs" />
<Compile Remove="Controls\ScrollViewer.xaml.cs" />
<Compile Remove="Controls\TabControl.xaml.cs" />
<Compile Remove="Controls\TabItem.cs" />
<Compile Remove="Controls\TabPanel.cs" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<None Remove="Icons\App.ico" /> <None Remove="Icons\App.ico" />
<None Remove="Images\AlignObjectsBottom.png" /> <None Remove="Images\AlignObjectsBottom.png" />
@@ -115,8 +104,6 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Page Remove="Controls\ScrollViewer.xaml" />
<Page Remove="Controls\TabControl.xaml" />
<Page Remove="Images\VectorIcons.xaml" /> <Page Remove="Images\VectorIcons.xaml" />
</ItemGroup> </ItemGroup>
@@ -128,19 +115,20 @@
<PackageReference Include="MahApps.Metro.IconPacks" Version="4.8.0" /> <PackageReference Include="MahApps.Metro.IconPacks" Version="4.8.0" />
<PackageReference Include="MahApps.Metro.IconPacks.FontAwesome" Version="4.8.0" /> <PackageReference Include="MahApps.Metro.IconPacks.FontAwesome" Version="4.8.0" />
<PackageReference Include="MahApps.Metro.IconPacks.VaadinIcons" Version="4.8.0" /> <PackageReference Include="MahApps.Metro.IconPacks.VaadinIcons" Version="4.8.0" />
<PackageReference Include="MathParser.org-mXparser" Version="4.4.2" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="Util.Svg2XamlTestExtension" Version="1.2.5" />
<PackageReference Include="WpfAnimatedGif" Version="2.0.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Util.DiagramDesigner\Util.DiagramDesigner.csproj" /> <ProjectReference Include="..\AIStudio.Wpf.DiagramDesigner\AIStudio.Wpf.DiagramDesigner.csproj" />
<ProjectReference Include="..\AIStudio.Wpf.DiagramHelper\AIStudio.Wpf.DiagramHelper.csproj" />
<ProjectReference Include="..\AIStudio.Wpf.Flowchart\AIStudio.Wpf.Flowchart.csproj" />
<ProjectReference Include="..\AIStudio.Wpf.Logical\AIStudio.Wpf.Logical.csproj" />
<ProjectReference Include="..\AIStudio.Wpf.SFC\AIStudio.Wpf.SFC.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Reference Include="zxing.core"> <Reference Include="zxing.core">
<HintPath>zxing.core.dll</HintPath> <HintPath>..\AIStudio.Wpf.DiagramHelper\DLL\zxing.core.dll</HintPath>
</Reference> </Reference>
</ItemGroup> </ItemGroup>
@@ -239,32 +227,6 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Page Update="Controls\PopupWindow.xaml">
<XamlRuntime>$(DefaultXamlRuntime)</XamlRuntime>
</Page>
<Page Update="Demos\Logical\ViewModels\LogicalGateItemViewModel.xaml">
<XamlRuntime>$(DefaultXamlRuntime)</XamlRuntime>
<SubType>Designer</SubType>
</Page>
<Page Update="Demos\Others\ViewModels\BarcodeDesignerItemViewModel.xaml">
<XamlRuntime>$(DefaultXamlRuntime)</XamlRuntime>
<SubType>Designer</SubType>
</Page>
<Page Update="Demos\Others\ViewModels\PersistDesignerItemViewModel.xaml">
<XamlRuntime>$(DefaultXamlRuntime)</XamlRuntime>
<SubType>Designer</SubType>
</Page>
<Page Update="Demos\Others\ViewModels\SettingsDesignerItemViewModel.xaml">
<XamlRuntime>$(DefaultXamlRuntime)</XamlRuntime>
<SubType>Designer</SubType>
</Page>
<Page Update="Demos\Others\ViewModels\OutLineTextDesignerItemViewModel.xaml">
<XamlRuntime>$(DefaultXamlRuntime)</XamlRuntime>
<SubType>Designer</SubType>
</Page>
<Page Update="Demos\Others\ViewModels\PathItemViewModel.xaml">
<XamlRuntime>$(DefaultXamlRuntime)</XamlRuntime>
</Page>
<Page Update="Themes\Generic.xaml"> <Page Update="Themes\Generic.xaml">
<XamlRuntime>$(DefaultXamlRuntime)</XamlRuntime> <XamlRuntime>$(DefaultXamlRuntime)</XamlRuntime>
</Page> </Page>

View File

@@ -1,14 +1,17 @@
<Application x:Class="AIStudio.Wpf.ADiagram.App" <Application x:Class="AIStudio.Wpf.DiagramApp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:AIStudio.Wpf.ADiagram" xmlns:local="clr-namespace:AIStudio.Wpf.DiagramApp"
StartupUri="Views/MainWindow.xaml"> StartupUri="Views/MainWindow.xaml">
<Application.Resources> <Application.Resources>
<ResourceDictionary> <ResourceDictionary>
<ResourceDictionary.MergedDictionaries> <ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/Fluent;component/Themes/Generic.xaml" /> <ResourceDictionary Source="pack://application:,,,/Fluent;component/Themes/Generic.xaml" />
<ResourceDictionary Source="pack://application:,,,/Dragablz;component/Themes/Generic.xaml" /> <ResourceDictionary Source="pack://application:,,,/Dragablz;component/Themes/Generic.xaml" />
<ResourceDictionary Source="/AIStudio.Wpf.ADiagram;component/Themes/Generic.xaml" /> <ResourceDictionary Source="/AIStudio.Wpf.DiagramApp;component/Themes/Generic.xaml" />
<ResourceDictionary Source="pack://application:,,,/AIStudio.Wpf.Flowchart;component/ViewModels/FlowNode.xaml"/>
<ResourceDictionary Source="pack://application:,,,/AIStudio.Wpf.Logical;component/ViewModels/LogicalGateItemViewModel.xaml"/>
<ResourceDictionary Source="pack://application:,,,/AIStudio.Wpf.SFC;component/ViewModels/SFCNode.xaml"/>
</ResourceDictionary.MergedDictionaries> </ResourceDictionary.MergedDictionaries>
</ResourceDictionary> </ResourceDictionary>
</Application.Resources> </Application.Resources>

View File

@@ -10,7 +10,7 @@ using System.Windows;
//如果是WinForm假定程序为MyDemo.exe则需要一个MyDemo.exe.config文件 //如果是WinForm假定程序为MyDemo.exe则需要一个MyDemo.exe.config文件
//如果是WebForm则从web.config中读取相关信息 //如果是WebForm则从web.config中读取相关信息
[assembly: log4net.Config.XmlConfigurator(Watch = true)] [assembly: log4net.Config.XmlConfigurator(Watch = true)]
namespace AIStudio.Wpf.ADiagram namespace AIStudio.Wpf.DiagramApp
{ {
/// <summary> /// <summary>
/// Interaction logic for App.xaml /// Interaction logic for App.xaml

View File

@@ -21,7 +21,7 @@
"ItemWidth": 65.0, "ItemWidth": 65.0,
"ItemHeight": 65.0, "ItemHeight": 65.0,
"Icon": "M 0,0 H 60 V 40 C 30,30 30,50 0,40 Z", "Icon": "M 0,0 H 60 V 40 C 30,30 30,50 0,40 Z",
"ItemTypeName": "AIStudio.Wpf.ADiagram.Demos.Others.PathItemViewModel", "ItemTypeName": "AIStudio.Wpf.DiagramHelper.Extensions.ViewModels.PathItemViewModel",
"Id": "da395032-ad9e-4dab-a035-f59bed5cb4c4", "Id": "da395032-ad9e-4dab-a035-f59bed5cb4c4",
"ZIndex": 0, "ZIndex": 0,
"IsGroup": false, "IsGroup": false,
@@ -93,76 +93,6 @@
], ],
"FlowNodeDesignerItems": [ "FlowNodeDesignerItems": [
], ],
"AllDesignerItems": [
{
"Left": 132.80000000000007,
"Top": 101.26000022888184,
"Margin": 0.0,
"ItemWidth": 65.0,
"ItemHeight": 65.0,
"Icon": "M 0,0 H 60 V 40 C 30,30 30,50 0,40 Z",
"ItemTypeName": "AIStudio.Wpf.ADiagram.Demos.Others.PathItemViewModel",
"Id": "da395032-ad9e-4dab-a035-f59bed5cb4c4",
"ZIndex": 0,
"IsGroup": false,
"ParentId": "00000000-0000-0000-0000-000000000000",
"Text": "欢迎来到AIStudio画板",
"ColorItem": {
"LineColor": {
"BrushType": 1,
"Color": "#FF808080",
"GradientStop": null,
"Offset": null,
"Image": null,
"SubType": 0,
"StartPoint": "0,0",
"EndPoint": "0,0",
"Opacity": 1.0,
"LinearOrientation": 0,
"RadialOrientation": 0,
"Angle": 0
},
"FillColor": {
"BrushType": 1,
"Color": "#FFFFA500",
"GradientStop": null,
"Offset": null,
"Image": null,
"SubType": 0,
"StartPoint": "0,0",
"EndPoint": "0,0",
"Opacity": 1.0,
"LinearOrientation": 0,
"RadialOrientation": 0,
"Angle": 0
},
"ShadowColor": "#00FFFFFF",
"LineWidth": 1.0,
"LeftArrowPathStyle": 0,
"RightArrowPathStyle": 1,
"LeftArrowSizeStyle": 10,
"RightArrowSizeStyle": 10
},
"FontItem": {
"FontWeight": "Normal",
"FontStyle": "Normal",
"FontStretch": "Normal",
"Underline": false,
"Strikethrough": false,
"OverLine": false,
"FontColor": "#FF000000",
"FontFamily": "Arial",
"FontSize": 11.0,
"FontObject": "Arial, 11pt",
"TextEffectColor": "#00FFFFFF",
"HighlightColor": "#00FFFFFF",
"FontCase": 0,
"HorizontalAlignment": 1,
"VerticalAlignment": 1,
"LineHeight": 0.0
}
}
],
"ConnectionIds": [ "ConnectionIds": [
], ],
"Connections": [ "Connections": [

View File

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View File

Before

Width:  |  Height:  |  Size: 405 B

After

Width:  |  Height:  |  Size: 405 B

View File

Before

Width:  |  Height:  |  Size: 353 B

After

Width:  |  Height:  |  Size: 353 B

View File

Before

Width:  |  Height:  |  Size: 365 B

After

Width:  |  Height:  |  Size: 365 B

View File

Before

Width:  |  Height:  |  Size: 425 B

After

Width:  |  Height:  |  Size: 425 B

View File

Before

Width:  |  Height:  |  Size: 454 B

After

Width:  |  Height:  |  Size: 454 B

View File

Before

Width:  |  Height:  |  Size: 413 B

After

Width:  |  Height:  |  Size: 413 B

View File

Before

Width:  |  Height:  |  Size: 185 B

After

Width:  |  Height:  |  Size: 185 B

View File

Before

Width:  |  Height:  |  Size: 230 B

After

Width:  |  Height:  |  Size: 230 B

View File

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

Before

Width:  |  Height:  |  Size: 556 B

After

Width:  |  Height:  |  Size: 556 B

View File

Before

Width:  |  Height:  |  Size: 689 B

After

Width:  |  Height:  |  Size: 689 B

View File

Before

Width:  |  Height:  |  Size: 185 B

After

Width:  |  Height:  |  Size: 185 B

View File

Before

Width:  |  Height:  |  Size: 230 B

After

Width:  |  Height:  |  Size: 230 B

View File

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

Before

Width:  |  Height:  |  Size: 643 B

After

Width:  |  Height:  |  Size: 643 B

View File

Before

Width:  |  Height:  |  Size: 628 B

After

Width:  |  Height:  |  Size: 628 B

View File

Before

Width:  |  Height:  |  Size: 743 B

After

Width:  |  Height:  |  Size: 743 B

View File

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

Before

Width:  |  Height:  |  Size: 435 B

After

Width:  |  Height:  |  Size: 435 B

View File

Before

Width:  |  Height:  |  Size: 334 B

After

Width:  |  Height:  |  Size: 334 B

View File

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

Before

Width:  |  Height:  |  Size: 1022 B

After

Width:  |  Height:  |  Size: 1022 B

View File

Before

Width:  |  Height:  |  Size: 185 B

After

Width:  |  Height:  |  Size: 185 B

View File

Before

Width:  |  Height:  |  Size: 228 B

After

Width:  |  Height:  |  Size: 228 B

View File

Before

Width:  |  Height:  |  Size: 185 B

After

Width:  |  Height:  |  Size: 185 B

View File

Before

Width:  |  Height:  |  Size: 229 B

After

Width:  |  Height:  |  Size: 229 B

View File

Before

Width:  |  Height:  |  Size: 654 B

After

Width:  |  Height:  |  Size: 654 B

View File

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

Before

Width:  |  Height:  |  Size: 743 B

After

Width:  |  Height:  |  Size: 743 B

View File

Before

Width:  |  Height:  |  Size: 185 B

After

Width:  |  Height:  |  Size: 185 B

View File

Before

Width:  |  Height:  |  Size: 231 B

After

Width:  |  Height:  |  Size: 231 B

View File

Before

Width:  |  Height:  |  Size: 730 B

After

Width:  |  Height:  |  Size: 730 B

View File

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

View File

Before

Width:  |  Height:  |  Size: 185 B

After

Width:  |  Height:  |  Size: 185 B

View File

Before

Width:  |  Height:  |  Size: 225 B

After

Width:  |  Height:  |  Size: 225 B

View File

Before

Width:  |  Height:  |  Size: 766 B

After

Width:  |  Height:  |  Size: 766 B

View File

Before

Width:  |  Height:  |  Size: 185 B

After

Width:  |  Height:  |  Size: 185 B

View File

Before

Width:  |  Height:  |  Size: 229 B

After

Width:  |  Height:  |  Size: 229 B

View File

Before

Width:  |  Height:  |  Size: 8.8 KiB

After

Width:  |  Height:  |  Size: 8.8 KiB

View File

Before

Width:  |  Height:  |  Size: 6.7 KiB

After

Width:  |  Height:  |  Size: 6.7 KiB

View File

Before

Width:  |  Height:  |  Size: 595 B

After

Width:  |  Height:  |  Size: 595 B

View File

Before

Width:  |  Height:  |  Size: 559 B

After

Width:  |  Height:  |  Size: 559 B

View File

Before

Width:  |  Height:  |  Size: 586 B

After

Width:  |  Height:  |  Size: 586 B

View File

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

View File

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

Before

Width:  |  Height:  |  Size: 823 B

After

Width:  |  Height:  |  Size: 823 B

View File

Before

Width:  |  Height:  |  Size: 698 B

After

Width:  |  Height:  |  Size: 698 B

View File

Before

Width:  |  Height:  |  Size: 764 B

After

Width:  |  Height:  |  Size: 764 B

View File

Before

Width:  |  Height:  |  Size: 759 B

After

Width:  |  Height:  |  Size: 759 B

View File

Before

Width:  |  Height:  |  Size: 926 B

After

Width:  |  Height:  |  Size: 926 B

View File

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

Before

Width:  |  Height:  |  Size: 899 B

After

Width:  |  Height:  |  Size: 899 B

View File

Before

Width:  |  Height:  |  Size: 616 B

After

Width:  |  Height:  |  Size: 616 B

View File

Before

Width:  |  Height:  |  Size: 542 B

After

Width:  |  Height:  |  Size: 542 B

View File

Before

Width:  |  Height:  |  Size: 547 B

After

Width:  |  Height:  |  Size: 547 B

View File

Before

Width:  |  Height:  |  Size: 374 B

After

Width:  |  Height:  |  Size: 374 B

View File

Before

Width:  |  Height:  |  Size: 416 B

After

Width:  |  Height:  |  Size: 416 B

View File

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

Before

Width:  |  Height:  |  Size: 454 B

After

Width:  |  Height:  |  Size: 454 B

View File

Before

Width:  |  Height:  |  Size: 290 B

After

Width:  |  Height:  |  Size: 290 B

View File

Before

Width:  |  Height:  |  Size: 442 B

After

Width:  |  Height:  |  Size: 442 B

View File

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

Before

Width:  |  Height:  |  Size: 357 B

After

Width:  |  Height:  |  Size: 357 B

View File

Before

Width:  |  Height:  |  Size: 404 B

After

Width:  |  Height:  |  Size: 404 B

Some files were not shown because too many files have changed in this diff Show More