enhance: add TransitionMode prop for GrowlWindow.

This commit is contained in:
NaBian committed 2025-09-13 14:35:27 +08:00
1 parent 83fc434e7d
commit faf2ba4412
8 files changed
+164 -55

No files matched your search

@@ -12694,6 +12694,14 @@
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="hc:Growl.TransitionMode" Value="Bottom2Top">
<Setter Property="Margin" Value="10,0,10,10" />
</Trigger>
<Trigger Property="hc:Growl.TransitionMode" Value="Bottom2TopWithFade">
<Setter Property="Margin" Value="10,0,10,10" />
</Trigger>
</Style.Triggers>
</Style>
<Style BasedOn="{StaticResource ImageSelectorBaseStyle}" TargetType="hc:ImageSelector" />
<Style TargetType="hc:ImageViewer">
@@ -291,7 +291,7 @@ public class Growl : Control
{
foreach (var item in panel.Children.OfType<Growl>())
{
item.Close(false);
item.Close(invokeParam: false, isClear: true);
}
};
panel.ContextMenu = new ContextMenu
@@ -354,9 +354,9 @@ public class Growl : Control
GrowlWindow = new GrowlWindow();
GrowlWindow.Show();
InitGrowlPanel(GrowlWindow.GrowlPanel);
GrowlWindow.Init();
}
GrowlWindow.UpdatePosition(Growl.GetTransitionMode(Application.Current.MainWindow));
GrowlWindow.Show(true);
var ctl = new Growl
@@ -408,7 +408,7 @@ public class Growl : Control
ConfirmStr = growlInfo.ConfirmStr,
CancelStr = growlInfo.CancelStr,
Type = growlInfo.Type,
_waitTime = Math.Max(growlInfo.WaitTime, MinWaitTime)
_waitTime = Math.Max(growlInfo.WaitTime, MinWaitTime),
};
if (!string.IsNullOrEmpty(growlInfo.Token))
@@ -424,9 +424,11 @@ public class Growl : Control
GrowlPanel ??= CreateDefaultPanel();
ShowInternal(GrowlPanel, ctl);
var transitionMode = GetTransitionMode(ctl);
var transitionMode = GetTransitionMode(GrowlPanel);
GrowlPanel.VerticalAlignment = GetPanelVerticalAlignment(transitionMode);
GrowlPanel.HorizontalAlignment = GetPanelHorizontalAlignment(transitionMode);
GrowlPanel.SetValue(InverseStackPanel.IsInverseEnabledProperty,
transitionMode is TransitionMode.Bottom2Top or TransitionMode.Bottom2TopWithFade);
}
}
#if NET40
@@ -446,7 +448,7 @@ public class Growl : Control
return null;
}
var panel = new SimpleStackPanel();
var panel = new InverseStackPanel();
InitGrowlPanel(panel);
SetIsCreatedAutomatically(panel, true);
@@ -830,14 +832,15 @@ public class Growl : Control
/// <summary>
/// 关闭
/// </summary>
private void Close(bool invokeParam)
private void Close(bool invokeParam, bool isClear = false)
{
if (ActionBeforeClose?.Invoke(invokeParam) == false)
if (!isClear && ActionBeforeClose?.Invoke(invokeParam) == false)
{
return;
}
_timerClose?.Stop();
Panel.SetZIndex(this, int.MinValue);
StartTransition(true, OnStoryboardCompleted);
return;
@@ -942,16 +945,19 @@ public class Growl : Control
{
var transformLength = GetTransformLength(isClose, transitionMode);
var transformAnimation = CreateTransformAnimation(isClose, transitionMode, transformLength);
_gridMain.RenderTransform = CreateRenderTransform(isClose, transitionMode, transformLength);
var storyboard = new Storyboard
{
Duration = transformAnimation.Duration
};
Storyboard.SetTarget(transformAnimation, _gridMain);
storyboard.Children.Add(transformAnimation);
if (CreateFadeAnimation(transitionMode) is not { } fadeAnimation)
if (transitionMode is not TransitionMode.Fade)
{
_gridMain.RenderTransform = CreateRenderTransform(isClose, transitionMode, transformLength);
Storyboard.SetTarget(transformAnimation, _gridMain);
storyboard.Children.Add(transformAnimation);
}
if (CreateFadeAnimation(isClose, transitionMode) is not { } fadeAnimation)
{
return storyboard;
}
@@ -970,7 +976,7 @@ public class Growl : Control
TransitionMode.Left2Right or TransitionMode.Left2RightWithFade => -ActualWidth,
TransitionMode.Bottom2Top or TransitionMode.Bottom2TopWithFade => ActualHeight,
TransitionMode.Top2Bottom or TransitionMode.Top2BottomWithFade => -ActualHeight,
_ => 0
_ => ActualWidth
};
@@ -1007,6 +1013,9 @@ public class Growl : Control
case Orientation.Vertical:
((TranslateTransform) transformGroup.Children[TranslateTransformIndex]).Y = transformLength;
break;
default:
((TranslateTransform) transformGroup.Children[TranslateTransformIndex]).X = transformLength;
break;
}
return transformGroup;
@@ -1029,23 +1038,29 @@ public class Growl : Control
new PropertyPath(
$"(UIElement.RenderTransform).(TransformGroup.Children)[{TranslateTransformIndex}].(TranslateTransform.Y)"));
break;
default:
Storyboard.SetTargetProperty(animation,
new PropertyPath(
$"(UIElement.RenderTransform).(TransformGroup.Children)[{TranslateTransformIndex}].(TranslateTransform.X)"));
break;
}
return animation;
}
private static DoubleAnimation CreateFadeAnimation(TransitionMode transitionMode)
private static DoubleAnimation CreateFadeAnimation(bool isClose, TransitionMode transitionMode)
{
if (transitionMode is TransitionMode.Right2Left or
TransitionMode.Left2Right or
TransitionMode.Bottom2Top or
TransitionMode.Top2Bottom)
TransitionMode.Top2Bottom or
TransitionMode.Custom)
{
return null;
}
}
var animation = AnimationHelper.CreateAnimation(1);
animation.From = 0;
var animation = AnimationHelper.CreateAnimation(isClose ? 0 : 1);
animation.From = isClose ? 1 : 0;
Storyboard.SetTargetProperty(animation, new PropertyPath("(UIElement.Opacity)"));
return animation;
@@ -1059,23 +1074,16 @@ public class Growl : Control
or TransitionMode.Left2RightWithFade => Orientation.Horizontal,
TransitionMode.Bottom2Top or TransitionMode.Bottom2TopWithFade or TransitionMode.Top2Bottom
or TransitionMode.Top2BottomWithFade => Orientation.Vertical,
_ => null
_ => Orientation.Horizontal
};
}
private static VerticalAlignment GetPanelVerticalAlignment(TransitionMode transitionMode)
internal static VerticalAlignment GetPanelVerticalAlignment(TransitionMode transitionMode)
{
return transitionMode switch
{
TransitionMode.Right2Left or TransitionMode.Right2LeftWithFade or TransitionMode.Left2Right
or TransitionMode.Left2RightWithFade => VerticalAlignment.Top,
TransitionMode.Bottom2Top or TransitionMode.Bottom2TopWithFade => VerticalAlignment.Bottom,
TransitionMode.Top2Bottom or TransitionMode.Top2BottomWithFade => VerticalAlignment.Top,
_ => VerticalAlignment.Stretch
};
return VerticalAlignment.Stretch;
}
private static HorizontalAlignment GetPanelHorizontalAlignment(TransitionMode transitionMode)
internal static HorizontalAlignment GetPanelHorizontalAlignment(TransitionMode transitionMode)
{
return transitionMode switch
{
@@ -1083,7 +1091,7 @@ public class Growl : Control
TransitionMode.Left2Right or TransitionMode.Left2RightWithFade => HorizontalAlignment.Left,
TransitionMode.Bottom2Top or TransitionMode.Bottom2TopWithFade or TransitionMode.Top2Bottom
or TransitionMode.Top2BottomWithFade => HorizontalAlignment.Center,
_ => HorizontalAlignment.Stretch
_ => HorizontalAlignment.Right
};
}
}
@@ -1,6 +1,7 @@
using System;
using System.Windows;
using System.Windows.Controls;
using HandyControl.Data;
using HandyControl.Tools;
using HandyControl.Tools.Interop;
@@ -15,11 +16,8 @@ public sealed class GrowlWindow : Window
WindowStyle = WindowStyle.None;
AllowsTransparency = true;
GrowlPanel = new StackPanel
{
VerticalAlignment = VerticalAlignment.Top
};
Growl.SetTransitionStoryboard(this, Growl.GetTransitionStoryboard(Application.Current.MainWindow));
GrowlPanel = new InverseStackPanel();
Content = new ScrollViewer
{
VerticalScrollBarVisibility = ScrollBarVisibility.Hidden,
@@ -28,12 +26,24 @@ public sealed class GrowlWindow : Window
};
}
internal void Init()
internal void UpdatePosition(TransitionMode transitionMode)
{
var desktopWorkingArea = SystemParameters.WorkArea;
Height = desktopWorkingArea.Height;
Left = desktopWorkingArea.Right - Width;
Top = 0;
var panelHorizontalAlignment = Growl.GetPanelHorizontalAlignment(transitionMode);
Left = panelHorizontalAlignment switch
{
HorizontalAlignment.Right => desktopWorkingArea.Right - Width,
HorizontalAlignment.Left => desktopWorkingArea.Left,
HorizontalAlignment.Center => desktopWorkingArea.Left + (desktopWorkingArea.Width - Width) * 0.5,
_ => desktopWorkingArea.Right - Width
};
Growl.SetTransitionMode(this, transitionMode);
GrowlPanel.SetValue(InverseStackPanel.IsInverseEnabledProperty,
transitionMode is TransitionMode.Bottom2Top or TransitionMode.Bottom2TopWithFade);
}
protected override void OnSourceInitialized(EventArgs e)
@@ -0,0 +1,60 @@
using System;
using System.Windows;
using HandyControl.Data;
namespace HandyControl.Controls;
public class InverseStackPanel : SimpleStackPanel
{
public static readonly DependencyProperty IsInverseEnabledProperty = DependencyProperty.Register(
nameof(IsInversed), typeof(bool), typeof(InverseStackPanel),
new FrameworkPropertyMetadata(ValueBoxes.TrueBox, FrameworkPropertyMetadataOptions.AffectsMeasure));
public bool IsInversed
{
get => (bool) GetValue(IsInverseEnabledProperty);
set => SetValue(IsInverseEnabledProperty, ValueBoxes.BooleanBox(value));
}
protected override Size ArrangeOverride(Size arrangeSize)
{
if (!IsInversed)
{
return base.ArrangeOverride(arrangeSize);
}
var rcChild = new Rect(arrangeSize);
double previousChildSize;
if (Orientation == System.Windows.Controls.Orientation.Horizontal)
{
rcChild.X = arrangeSize.Width;
foreach (var child in GetVisibleChildren())
{
previousChildSize = child.DesiredSize.Width;
rcChild.X -= previousChildSize;
rcChild.Width = previousChildSize;
rcChild.Height = Math.Max(arrangeSize.Height, child.DesiredSize.Height);
child.Arrange(rcChild);
}
}
else
{
rcChild.Y = arrangeSize.Height;
foreach (var child in GetVisibleChildren())
{
previousChildSize = child.DesiredSize.Height;
rcChild.Y -= previousChildSize;
rcChild.Height = previousChildSize;
rcChild.Width = Math.Max(arrangeSize.Width, child.DesiredSize.Width);
child.Arrange(rcChild);
}
}
return arrangeSize;
}
}
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
@@ -19,18 +20,14 @@ public class SimpleStackPanel : Panel
protected override Size MeasureOverride(Size constraint)
{
var stackDesiredSize = new Size();
var children = InternalChildren;
var layoutSlotSize = constraint;
if (Orientation == Orientation.Horizontal)
{
layoutSlotSize.Width = double.PositiveInfinity;
for (int i = 0, count = children.Count; i < count; ++i)
foreach (var child in GetVisibleChildren())
{
var child = children[i];
if (child == null) continue;
child.Measure(layoutSlotSize);
var childDesiredSize = child.DesiredSize;
@@ -42,11 +39,8 @@ public class SimpleStackPanel : Panel
{
layoutSlotSize.Height = double.PositiveInfinity;
for (int i = 0, count = children.Count; i < count; ++i)
foreach (var child in GetVisibleChildren())
{
var child = children[i];
if (child == null) continue;
child.Measure(layoutSlotSize);
var childDesiredSize = child.DesiredSize;
@@ -60,17 +54,13 @@ public class SimpleStackPanel : Panel
protected override Size ArrangeOverride(Size arrangeSize)
{
var children = InternalChildren;
var rcChild = new Rect(arrangeSize);
var previousChildSize = 0.0;
if (Orientation == Orientation.Horizontal)
{
for (int i = 0, count = children.Count; i < count; ++i)
foreach (var child in GetVisibleChildren())
{
var child = children[i];
if (child == null) continue;
rcChild.X += previousChildSize;
previousChildSize = child.DesiredSize.Width;
rcChild.Width = previousChildSize;
@@ -81,11 +71,8 @@ public class SimpleStackPanel : Panel
}
else
{
for (int i = 0, count = children.Count; i < count; ++i)
foreach (var child in GetVisibleChildren())
{
var child = children[i];
if (child == null) continue;
rcChild.Y += previousChildSize;
previousChildSize = child.DesiredSize.Height;
rcChild.Height = previousChildSize;
@@ -97,4 +84,23 @@ public class SimpleStackPanel : Panel
return arrangeSize;
}
public virtual IEnumerable<UIElement> GetVisibleChildren()
{
var children = InternalChildren;
for (int i = 0, count = children.Count; i < count; ++i)
{
var child = children[i];
if (child == null)
{
continue;
}
if (child.Visibility != Visibility.Collapsed)
{
yield return child;
}
}
}
}
@@ -64,6 +64,7 @@
<Compile Include="$(MSBuildThisFileDirectory)Controls\Panel\ClipGrid.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Controls\Panel\FlexPanel.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Controls\Panel\ElementGroup.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Controls\Panel\InverseStackPanel.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Controls\Panel\SimpleStackPanel.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Controls\Panel\UniformSpacingPanel.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Controls\PropertyGrid\Editors\ImagePropertyEditor.cs" />
@@ -60,6 +60,14 @@
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="hc:Growl.TransitionMode" Value="Bottom2Top">
<Setter Property="Margin" Value="10,0,10,10"/>
</Trigger>
<Trigger Property="hc:Growl.TransitionMode" Value="Bottom2TopWithFade">
<Setter Property="Margin" Value="10,0,10,10"/>
</Trigger>
</Style.Triggers>
</Style>
</ResourceDictionary>
@@ -12839,6 +12839,14 @@
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="hc:Growl.TransitionMode" Value="Bottom2Top">
<Setter Property="Margin" Value="10,0,10,10" />
</Trigger>
<Trigger Property="hc:Growl.TransitionMode" Value="Bottom2TopWithFade">
<Setter Property="Margin" Value="10,0,10,10" />
</Trigger>
</Style.Triggers>
</Style>
<Style BasedOn="{StaticResource ImageSelectorBaseStyle}" TargetType="hc:ImageSelector" />
<Style TargetType="hc:ImageViewer">