Compare commits

...

13 Commits

Author SHA1 Message Date
zengwenjie
385e932401 优化「Dodo」脚本的调试用例 2025-10-17 10:07:37 +08:00
zengwenjie
55573f6040 完善「Val_Double」方法的运算逻辑 2025-10-16 14:52:19 +08:00
zengwenjie
2efc34846c 已经完成While、Continue、Break指令的调试 2025-10-16 14:44:30 +08:00
zengwenjie
fb3db24b90 已经完成条件指令的调试 2025-10-16 13:21:41 +08:00
zengwenjie
413985e08f 当设置变量值时如果找不到变量则优先在临时变量上下文中声明变量 2025-10-16 12:24:25 +08:00
zengwenjie
7d18b88172 已经完成「Dodo」脚本对自定义方法参数的支持 2025-10-16 12:12:11 +08:00
zengwenjie
fdcef37be3 完成「Dodo」脚本的定义与服务关键逻辑的测试 2025-10-16 10:47:09 +08:00
zengwenjie
d7ff6b3109 为窗口抽屉添加代码注释 2025-10-09 09:48:08 +08:00
zengwenjie
cce2224926 Merge branch 'main' of http://123.56.72.222:3000/IBridge/DeedyDesigner 2025-10-09 09:15:30 +08:00
zengwenjie
23fc6c17e6 清理无用方法 2025-10-09 09:15:11 +08:00
于智纯
c6c1e41cb6 撤销抽屉视图注册附属视图的功能 2025-09-30 21:55:34 +08:00
zengwenjie
f9138ff444 定义注册附属视图需要的方法 2025-09-30 18:42:49 +08:00
zengwenjie
71c55abbcb 除去注册「取消」按钮,其它关于抽屉视图的功能全部完成 2025-09-30 18:30:38 +08:00
6 changed files with 1465 additions and 26 deletions

View File

@@ -1,6 +1,8 @@
using System.Configuration;
using System.Data;
using System.Diagnostics;
using System.Windows;
using Deedy.Testing;
namespace Deedy
{
@@ -9,6 +11,45 @@ namespace Deedy
/// </summary>
public partial class App : Application
{
public App()
{
string script =
@"
VarP var1 111
VarP var2 222
Func Add var1x var2x
LetP AddResult -1
math AddResult @var1x 777 + @var2 - @var2x -
retu AddResult
EndF
//调用自定义方法
Call Add @var1 99
PopV result
ifth true 4 3 <
letp result 248
else
letp result 80
endi
letp var1 1
letp var2 1
whil false @var1 10 <
math var1 @var1 ++
ifth false @var2 4 !=
math var2 @var2 ++
cont
var var3 xxx
else
brea
endi
endw
";
Todo todo = new();
todo.Init("varp var1 111");
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < 1000000; i++)
todo.Redo();
sw.Stop();
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -20,6 +20,10 @@
<Button Content="测试的标题"/>
</UniformGrid>
</deedy:WindowBorder.Header>
<Border BorderBrush="Red" BorderThickness="1"/>
<Border BorderBrush="Red" BorderThickness="1">
<UniformGrid>
<Button Content="打开抽屉" Click="Button_Click"/>
</UniformGrid>
</Border>
</deedy:WindowBorder>
</Window>

View File

@@ -31,7 +31,34 @@ namespace Deedy.Testing
private void WindowBorder_Click_1(object sender, RoutedEventArgs e)
{
drawer?.HideWithAnimation();
}
private DrawerViewer? drawer;
private void Button_Click(object sender, RoutedEventArgs e)
{
if (this.Content is UIElement windowBorder)
{
DrawerViewer? _drawer = null;
_drawer = new DrawerViewer(windowBorder, (s, e) =>
{
_drawer?.HideWithAnimation();
}, Dock.Right, Button.ClickEvent)
{
Content = new Button()
{
Background = Brushes.Red,
Opacity = 0.75,
Visibility = Visibility.Visible,
Content = "测试按钮"
},
Background = Brushes.Green,
Margin = new Thickness(100, 40, 0, 0),
};
var al = AdornerLayer.GetAdornerLayer(this.Content as UIElement);
al.Add(_drawer);
_drawer.ShowWithAnimation();
drawer = _drawer;
}
}
}
}

View File

@@ -0,0 +1,220 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Documents;
using System.Windows.Media;
using System.Windows.Media.Animation;
namespace Deedy
{
/// <summary>
/// 抽屉窗口装饰器
/// </summary>
public class DrawerViewer : Adorner
{
private readonly VisualCollection _visualChildren;
/// <summary>
/// 抽屉外边框
/// </summary>
private readonly Border _border;
public Brush Background { get => (Brush)GetValue(BackgroundProperty); set => SetValue(BackgroundProperty, value); }
public static readonly DependencyProperty BackgroundProperty = Border.BackgroundProperty.AddOwner(typeof(DrawerViewer));
public Brush BorderBrush { get => (Brush)GetValue(BorderBrushProperty); set => SetValue(BorderBrushProperty, value); }
public static readonly DependencyProperty BorderBrushProperty = Border.BorderBrushProperty.AddOwner(typeof(DrawerViewer));
public Thickness BorderThickness { get => (Thickness)GetValue(BorderThicknessProperty); set => SetValue(BorderThicknessProperty, value); }
public static readonly DependencyProperty BorderThicknessProperty = Border.BorderThicknessProperty.AddOwner(typeof(DrawerViewer));
public CornerRadius CornerRadius { get => (CornerRadius)GetValue(CornerRadiusProperty); set => SetValue(CornerRadiusProperty, value); }
public static readonly DependencyProperty CornerRadiusProperty = Border.CornerRadiusProperty.AddOwner(typeof(DrawerViewer));
/// <summary>
/// 抽屉内容容器
/// </summary>
private readonly ContentPresenter _contentPresenter;
public object Content { get => GetValue(ContentProperty); set => SetValue(ContentProperty, value); }
public static readonly DependencyProperty ContentProperty = ContentPresenter.ContentProperty.AddOwner(typeof(DrawerViewer));
public DataTemplate ContentTemplate { get => (DataTemplate)GetValue(ContentTemplateProperty); set => SetValue(ContentTemplateProperty, value); }
public static readonly DependencyProperty ContentTemplateProperty = ContentPresenter.ContentTemplateProperty.AddOwner(typeof(DrawerViewer));
public DataTemplateSelector ContentTemplateSelector { get => (DataTemplateSelector)GetValue(ContentTemplateSelectorProperty); set => SetValue(ContentTemplateSelectorProperty, value); }
public static readonly DependencyProperty ContentTemplateSelectorProperty = ContentPresenter.ContentTemplateSelectorProperty.AddOwner(typeof(DrawerViewer));
/// <summary>
/// 动画方向如果为「null」则使用缩放动画
/// </summary>
private readonly Dock? _direction;
/// <summary>
/// 根据抽屉加载方向创建边距动画所需要的「Thickness」对象
/// </summary>
/// <returns>动画需要的「Thickness」对象</returns>
private Thickness GetMargin4Animation()
{
switch (this._direction)
{
case Dock.Left: return new Thickness(0, 0, this.AdornedElement.RenderSize.Width, 0);
case Dock.Right: return new Thickness(this.AdornedElement.RenderSize.Width, 0, 0, 0);
case Dock.Top: return new Thickness(0, 0, 0, this.AdornedElement.RenderSize.Height);
case Dock.Bottom: return new Thickness(0, AdornedElement.RenderSize.Height, 0, 0);
default:
double horMargin = this.AdornedElement.RenderSize.Width / 2;
double verMargin = this.AdornedElement.RenderSize.Height / 2;
return new Thickness(horMargin, verMargin, horMargin, verMargin);
}
}
/// <summary>
/// 在特定「UIElement」上创建「WindowDrawer」蒙层
/// </summary>
/// <param name="adornedElement">目标「UIElement」元素</param>
/// <param name="direction">抽屉的加载方向,如果不设置则使用缩放动画</param>
public DrawerViewer(UIElement adornedElement, Dock? direction = null) : base(adornedElement)
{
this.Opacity = 0;
this._direction = direction;
_visualChildren = new VisualCollection(this);
// 创建边框并绑定属性
_border = new Border() { };
var backgroundBinding = new System.Windows.Data.Binding(BackgroundProperty.Name) { Source = this };
var borderBrushBinding = new System.Windows.Data.Binding(BorderBrushProperty.Name) { Source = this };
var borderThicknessBinding = new System.Windows.Data.Binding(BorderThicknessProperty.Name) { Source = this };
var cornerRadiusBinding = new System.Windows.Data.Binding(CornerRadiusProperty.Name) { Source = this };
_border.SetBinding(Border.BackgroundProperty, backgroundBinding);
_border.SetBinding(Border.BorderBrushProperty, borderBrushBinding);
_border.SetBinding(Border.BorderThicknessProperty, borderThicknessBinding);
_border.SetBinding(Border.CornerRadiusProperty, cornerRadiusBinding);
_visualChildren.Add(_border);
// 创建内容并绑定属性
_contentPresenter = new ContentPresenter
{
HorizontalAlignment = HorizontalAlignment.Stretch,
VerticalAlignment = VerticalAlignment.Stretch
};
var contentBinding = new System.Windows.Data.Binding(ContentProperty.Name) { Source = this };
var contentTemplateBinding = new System.Windows.Data.Binding(ContentTemplateProperty.Name) { Source = this };
var contentTemplateSelectorBinding = new System.Windows.Data.Binding(ContentTemplateSelectorProperty.Name) { Source = this };
_contentPresenter.SetBinding(ContentPresenter.ContentProperty, contentBinding);
_contentPresenter.SetBinding(ContentPresenter.ContentTemplateProperty, contentTemplateBinding);
_contentPresenter.SetBinding(ContentPresenter.ContentTemplateSelectorProperty, contentTemplateSelectorBinding);
_border.Child = _contentPresenter;
}
/// <summary>
/// 要注册的事件
/// </summary>
[AllowNull]
private readonly RoutedEvent[] _routedEvents;
/// <summary>
/// 事件响应方法
/// </summary>
private readonly RoutedEventHandler? _routedEventHandler;
/// <summary>
/// 在特定「UIElement」上创建「WindowDrawer」蒙层同时绑定特定路由事件
/// </summary>
/// <param name="adornedElement">目标「UIElement」元素</param>
/// <param name="routedEventHandler">路由事件处理程序</param>
/// <param name="direction">抽屉的加载方向,如果不设置则使用缩放动画</param>
/// <param name="routedEvents">要绑定的路由事件</param>
/// <remarks>
/// 如果不设置「routedEvents」参数则注册「ButtonBase.ClickEvent」事件
/// </remarks>
public DrawerViewer(UIElement adornedElement, RoutedEventHandler routedEventHandler, Dock? direction, params RoutedEvent[] routedEvents)
: this(adornedElement, direction)
{
if (routedEvents.Length == 0) routedEvents = [ButtonBase.ClickEvent];
if (routedEventHandler != null)
{
_routedEvents = routedEvents;
_routedEventHandler = routedEventHandler;
foreach (var routedEvent in routedEvents)
this.AddHandler(routedEvent, routedEventHandler);
}
}
/// <summary>
/// 在特定「UIElement」上创建「WindowDrawer」蒙层同时绑定特定路由事件
/// </summary>
/// <param name="adornedElement">目标「UIElement」元素</param>
/// <param name="routedEventHandler">路由事件处理程序</param>
/// <param name="routedEvents">要绑定的路由事件</param>
/// <remarks>
/// <para>如果不设置「routedEvents」参数则注册「ButtonBase.ClickEvent」事件</para>
/// <para>抽屉采用缩放方式加载</para>
/// </remarks>
public DrawerViewer(UIElement adornedElement, RoutedEventHandler routedEventHandler, params RoutedEvent[] routedEvents)
: this(adornedElement, routedEventHandler, null, routedEvents) { }
protected override int VisualChildrenCount => _visualChildren.Count;
protected override Visual GetVisualChild(int index) => _visualChildren[index];
protected override Size MeasureOverride(Size constraint)
{
_border.Measure(constraint);
return base.MeasureOverride(constraint);
}
protected override Size ArrangeOverride(Size finalSize)
{
_border.Arrange(new Rect(0, 0, finalSize.Width, finalSize.Height));
return finalSize;
}
/// <summary>
/// 显示抽屉并播放入场动画
/// </summary>
/// <param name="seconds">动画持续时间</param>
public void ShowWithAnimation(double seconds = 1)
{
var doubleAnimation = new DoubleAnimation
{
From = 0,
To = 1,
Duration = TimeSpan.FromSeconds(seconds),
EasingFunction = new CubicEase { EasingMode = EasingMode.EaseIn }
};
BeginAnimation(OpacityProperty, doubleAnimation);
var marginAnimation = new ThicknessAnimation
{
From = this.GetMargin4Animation(),
To = new Thickness(0),
Duration = TimeSpan.FromSeconds(seconds),
EasingFunction = new CubicEase { EasingMode = EasingMode.EaseIn }
};
_border.BeginAnimation(MarginProperty, marginAnimation);
}
/// <summary>
/// 关闭抽屉并播放出场动画;同时清理事件注册
/// </summary>
/// <param name="seconds">动画持续时间</param>
public void HideWithAnimation(double seconds = 1)
{
var doubleAnimation = new DoubleAnimation
{
From = 1,
To = 0,
Duration = TimeSpan.FromSeconds(seconds),
EasingFunction = new CubicEase { EasingMode = EasingMode.EaseOut }
};
doubleAnimation.Completed += (s, e) =>
{
if (this._routedEventHandler != null)
foreach (var routedEvent in this._routedEvents)
this.RemoveHandler(routedEvent, this._routedEventHandler);
var layer = AdornerLayer.GetAdornerLayer(AdornedElement);
layer?.Remove(this);
};
BeginAnimation(OpacityProperty, doubleAnimation);
var marginAnimation = new ThicknessAnimation
{
From = new Thickness(0),
To = this.GetMargin4Animation(),
Duration = TimeSpan.FromSeconds(seconds),
EasingFunction = new CubicEase { EasingMode = EasingMode.EaseOut }
};
_border.BeginAnimation(MarginProperty, marginAnimation);
}
}
}

View File

@@ -82,32 +82,34 @@
</Style.Triggers>
</Style>
</ControlTemplate.Resources>
<DockPanel Background="{TemplateBinding Background}">
<Border x:Name="TitleBar" Background="{TemplateBinding Headground}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"
<AdornerDecorator>
<DockPanel Background="{TemplateBinding Background}">
<Border x:Name="TitleBar" Background="{TemplateBinding Headground}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"
DockPanel.Dock="Top" MinHeight="32" Height="{TemplateBinding HeaderHeight}">
<DockPanel>
<Image Margin="{TemplateBinding Padding}" Stretch="Uniform" Source="{Binding Icon, RelativeSource={RelativeSource AncestorType=Window}}"/>
<TextBlock VerticalAlignment="Center" Margin="0,0,6,0" Text="{Binding Title, RelativeSource={RelativeSource AncestorType=Window}}"/>
<DockPanel x:Name="Controller" DockPanel.Dock="Right" MinWidth="147" Background="#01FFFFFF" VerticalAlignment="Stretch">
<Button x:Name="CloseWin" DockPanel.Dock="Right" Padding="{TemplateBinding Padding}" Style="{DynamicResource ControlButtonStyle}" Width="{Binding ActualHeight, RelativeSource={RelativeSource Self}}">
<Path Stretch="Uniform" Stroke="Transparent" Fill="{TemplateBinding Foreground}"
Data="M 1 0 L 0 1 L 23 24 L 24 23 Z M 1 24 L 0 23 L 11 12 L 12 13 Z M 12 11 L 23 0 L 24 1 L 13 12 Z"/>
</Button>
<Button x:Name="Maximize" DockPanel.Dock="Right" Padding="{TemplateBinding Padding}" Style="{DynamicResource ControlButtonStyle}" Width="{Binding ActualHeight, RelativeSource={RelativeSource Self}}">
<Path Stretch="Uniform" Stroke="Transparent" Fill="{TemplateBinding Foreground}"
Data="M 0 6 V 24 H 18 V 6 H 16.5 V 22.5 H 1.5 V 7.5 H 16.5 V 6 Z M 6 0 H 24 V 18 H 22.5 V 1.5 H 6 Z"/>
</Button>
<Button x:Name="Minimize" DockPanel.Dock="Right" Padding="{TemplateBinding Padding}" Style="{DynamicResource ControlButtonStyle}" Width="{Binding ActualHeight, RelativeSource={RelativeSource Self}}">
<Path Stretch="Uniform" Stroke="Transparent" Fill="{TemplateBinding Foreground}"
Data="M 0 0 V 24 M 0 11.25 V 12.75 H 24 V 11.25 Z"/>
</Button>
<Menu x:Name="MainMenu" Background="#01FFFFFF" Foreground="{TemplateBinding HoverBrush}"/>
<DockPanel>
<Image Margin="{TemplateBinding Padding}" Stretch="Uniform" Source="{Binding Icon, RelativeSource={RelativeSource AncestorType=Window}}"/>
<TextBlock VerticalAlignment="Center" Margin="0,0,6,0" Text="{Binding Title, RelativeSource={RelativeSource AncestorType=Window}}"/>
<DockPanel x:Name="Controller" DockPanel.Dock="Right" MinWidth="147" Background="#01FFFFFF" VerticalAlignment="Stretch">
<Button x:Name="CloseWin" DockPanel.Dock="Right" Padding="{TemplateBinding Padding}" Style="{DynamicResource ControlButtonStyle}" Width="{Binding ActualHeight, RelativeSource={RelativeSource Self}}">
<Path Stretch="Uniform" Stroke="Transparent" Fill="{TemplateBinding Foreground}"
Data="M 1 0 L 0 1 L 23 24 L 24 23 Z M 1 24 L 0 23 L 11 12 L 12 13 Z M 12 11 L 23 0 L 24 1 L 13 12 Z"/>
</Button>
<Button x:Name="Maximize" DockPanel.Dock="Right" Padding="{TemplateBinding Padding}" Style="{DynamicResource ControlButtonStyle}" Width="{Binding ActualHeight, RelativeSource={RelativeSource Self}}">
<Path Stretch="Uniform" Stroke="Transparent" Fill="{TemplateBinding Foreground}"
Data="M 0 6 V 24 H 18 V 6 H 16.5 V 22.5 H 1.5 V 7.5 H 16.5 V 6 Z M 6 0 H 24 V 18 H 22.5 V 1.5 H 6 Z"/>
</Button>
<Button x:Name="Minimize" DockPanel.Dock="Right" Padding="{TemplateBinding Padding}" Style="{DynamicResource ControlButtonStyle}" Width="{Binding ActualHeight, RelativeSource={RelativeSource Self}}">
<Path Stretch="Uniform" Stroke="Transparent" Fill="{TemplateBinding Foreground}"
Data="M 0 0 V 24 M 0 11.25 V 12.75 H 24 V 11.25 Z"/>
</Button>
<Menu x:Name="MainMenu" Background="#01FFFFFF" Foreground="{TemplateBinding HoverBrush}"/>
</DockPanel>
<Decorator x:Name="Container" VerticalAlignment="Stretch" HorizontalAlignment="Stretch"/>
</DockPanel>
<Decorator x:Name="Container" VerticalAlignment="Stretch" HorizontalAlignment="Stretch"/>
</DockPanel>
</Border>
<ContentPresenter/>
</DockPanel>
</Border>
<ContentPresenter/>
</DockPanel>
</AdornerDecorator>
</ControlTemplate>
</Setter.Value>
</Setter>