Skip to content

Commit b3454e9

Browse files
committed
ripple mouse out
1 parent 265552c commit b3454e9

File tree

2 files changed

+73
-25
lines changed

2 files changed

+73
-25
lines changed

MaterialDesignThemes.Wpf/Ripple.cs

Lines changed: 45 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -21,55 +21,51 @@ namespace MaterialDesignThemes.Wpf
2121
{
2222
[TemplateVisualState(GroupName = "CommonStates", Name = TemplateStateNormal)]
2323
[TemplateVisualState(GroupName = "CommonStates", Name = TemplateStateMousePressed)]
24+
[TemplateVisualState(GroupName = "CommonStates", Name = TemplateStateMouseOut)]
2425
public class Ripple : ContentControl
2526
{
2627
public const string TemplateStateNormal = "Normal";
2728
public const string TemplateStateMousePressed = "MousePressed";
29+
public const string TemplateStateMouseOut = "MouseOut";
2830

29-
private static readonly HashSet<Ripple> LoadedInstances = new HashSet<Ripple>();
31+
private static readonly HashSet<Ripple> PressedInstances = new HashSet<Ripple>();
3032

3133
static Ripple()
3234
{
3335
DefaultStyleKeyProperty.OverrideMetadata(typeof(Ripple), new FrameworkPropertyMetadata(typeof(Ripple)));
3436

3537
EventManager.RegisterClassHandler(typeof(Window), Mouse.PreviewMouseUpEvent, new MouseButtonEventHandler(MouseButtonEventHandler), true);
38+
EventManager.RegisterClassHandler(typeof (Window), Mouse.MouseMoveEvent, new MouseEventHandler(MouseMouveEventHandler), true);
3639
}
3740

3841
public Ripple()
3942
{
40-
SizeChanged += OnSizeChanged;
41-
42-
Loaded += (sender, args) => LoadedInstances.Add((Ripple) sender);
43-
Unloaded += (sender, args) => LoadedInstances.Remove((Ripple)sender);
43+
SizeChanged += OnSizeChanged;
4444
}
4545

4646
private static void MouseButtonEventHandler(object sender, MouseButtonEventArgs e)
4747
{
48-
foreach (var loadedInstance in LoadedInstances)
49-
VisualStateManager.GoToState(loadedInstance, TemplateStateNormal, false);
48+
foreach (var ripple in PressedInstances)
49+
VisualStateManager.GoToState(ripple, TemplateStateNormal, false);
50+
PressedInstances.Clear();
5051
}
5152

52-
private void OnSizeChanged(object sender, SizeChangedEventArgs sizeChangedEventArgs)
53+
private static void MouseMouveEventHandler(object sender, MouseEventArgs e)
5354
{
54-
var innerContent = (Content as FrameworkElement);
55-
56-
double width, height;
57-
58-
if (RippleAssist.GetIsCentered(this) && innerContent != null)
59-
{
60-
width = innerContent.ActualWidth;
61-
height = innerContent.ActualHeight;
62-
}
63-
else
55+
foreach (var ripple in PressedInstances.ToList())
6456
{
65-
width = sizeChangedEventArgs.NewSize.Width;
66-
height = sizeChangedEventArgs.NewSize.Height;
67-
}
57+
var relativePosition = Mouse.GetPosition(ripple);
58+
if (relativePosition.X < 0
59+
|| relativePosition.Y < 0
60+
|| relativePosition.X >= ripple.ActualWidth
61+
|| relativePosition.Y >= ripple.ActualHeight)
6862

69-
var radius = Math.Sqrt(Math.Pow(width, 2) + Math.Pow(height, 2));
70-
71-
RippleSize = 2 * radius * RippleAssist.GetRippleSizeMultiplier(this);
72-
}
63+
{
64+
VisualStateManager.GoToState(ripple, TemplateStateMouseOut, true);
65+
PressedInstances.Remove(ripple);
66+
}
67+
}
68+
}
7369

7470
public static readonly DependencyProperty FeedbackProperty = DependencyProperty.Register(
7571
"Feedback", typeof(Brush), typeof(Ripple), new PropertyMetadata(default(Brush)));
@@ -108,7 +104,9 @@ protected override void OnPreviewMouseLeftButtonDown(MouseButtonEventArgs e)
108104
RippleY = point.Y - RippleSize / 2;
109105
}
110106

107+
VisualStateManager.GoToState(this, TemplateStateNormal, false);
111108
VisualStateManager.GoToState(this, TemplateStateMousePressed, true);
109+
PressedInstances.Add(this);
112110

113111
base.OnPreviewMouseLeftButtonDown(e);
114112
}
@@ -161,5 +159,27 @@ public override void OnApplyTemplate()
161159

162160
VisualStateManager.GoToState(this, TemplateStateNormal, false);
163161
}
162+
163+
private void OnSizeChanged(object sender, SizeChangedEventArgs sizeChangedEventArgs)
164+
{
165+
var innerContent = (Content as FrameworkElement);
166+
167+
double width, height;
168+
169+
if (RippleAssist.GetIsCentered(this) && innerContent != null)
170+
{
171+
width = innerContent.ActualWidth;
172+
height = innerContent.ActualHeight;
173+
}
174+
else
175+
{
176+
width = sizeChangedEventArgs.NewSize.Width;
177+
height = sizeChangedEventArgs.NewSize.Height;
178+
}
179+
180+
var radius = Math.Sqrt(Math.Pow(width, 2) + Math.Pow(height, 2));
181+
182+
RippleSize = 2 * radius * RippleAssist.GetRippleSizeMultiplier(this);
183+
}
164184
}
165185
}

MaterialDesignThemes.Wpf/Themes/Generic.xaml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,27 @@
6464
</DoubleAnimationUsingKeyFrames>
6565
</Storyboard>
6666
</VisualTransition>
67+
<VisualTransition From="MousePressed" To="MouseOut">
68+
<Storyboard>
69+
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="ScaleX" Storyboard.TargetName="ScaleTransform">
70+
<EasingDoubleKeyFrame KeyTime="0:0:0.12" Value="0">
71+
<EasingDoubleKeyFrame.EasingFunction>
72+
<SineEase EasingMode="EaseIn" />
73+
</EasingDoubleKeyFrame.EasingFunction>
74+
</EasingDoubleKeyFrame>
75+
</DoubleAnimationUsingKeyFrames>
76+
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="ScaleY" Storyboard.TargetName="ScaleTransform">
77+
<EasingDoubleKeyFrame KeyTime="0:0:0.12" Value="0">
78+
<EasingDoubleKeyFrame.EasingFunction>
79+
<SineEase EasingMode="EaseIn" />
80+
</EasingDoubleKeyFrame.EasingFunction>
81+
</EasingDoubleKeyFrame>
82+
</DoubleAnimationUsingKeyFrames>
83+
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity" Storyboard.TargetName="ClickEllipse">
84+
<EasingDoubleKeyFrame KeyTime="0:0:0.12" Value="0"/>
85+
</DoubleAnimationUsingKeyFrames>
86+
</Storyboard>
87+
</VisualTransition>
6788
</VisualStateGroup.Transitions>
6889
<VisualState x:Name="Normal">
6990
<Storyboard>
@@ -79,6 +100,13 @@
79100
<DoubleAnimation Storyboard.TargetProperty="Opacity" Storyboard.TargetName="ClickEllipse" To="0.26"/>
80101
</Storyboard>
81102
</VisualState>
103+
<VisualState x:Name="MouseOut">
104+
<Storyboard>
105+
<DoubleAnimation Storyboard.TargetProperty="ScaleX" Storyboard.TargetName="ScaleTransform" To="0"/>
106+
<DoubleAnimation Storyboard.TargetProperty="ScaleY" Storyboard.TargetName="ScaleTransform" To="0"/>
107+
<DoubleAnimation Storyboard.TargetProperty="Opacity" Storyboard.TargetName="ClickEllipse" To="0"/>
108+
</Storyboard>
109+
</VisualState>
82110
</VisualStateGroup>
83111
</VisualStateManager.VisualStateGroups>
84112
<Canvas IsHitTestVisible="False" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">

0 commit comments

Comments
 (0)