1
1
using System ;
2
2
using System . Collections . Generic ;
3
3
using System . Linq ;
4
- using System . Text ;
5
- using System . Threading . Tasks ;
6
4
using System . Windows ;
7
5
using System . Windows . Controls ;
8
- using System . Windows . Data ;
9
- using System . Windows . Documents ;
10
6
using System . Windows . Input ;
11
7
using System . Windows . Media ;
12
- using System . Windows . Media . Imaging ;
13
- using System . Windows . Navigation ;
14
- using System . Windows . Shapes ;
15
8
16
9
namespace MaterialDesignThemes . Wpf
17
10
{
18
- [ TemplateVisualState ( GroupName = "CommonStates" , Name = "Normal" ) ]
19
- [ TemplateVisualState ( GroupName = "CommonStates" , Name = "Pressed" ) ]
11
+ [ TemplateVisualState ( GroupName = "CommonStates" , Name = TemplateStateNormal ) ]
12
+ [ TemplateVisualState ( GroupName = "CommonStates" , Name = TemplateStateMousePressed ) ]
13
+ [ TemplateVisualState ( GroupName = "CommonStates" , Name = TemplateStateMouseOut ) ]
20
14
public class Ripple : ContentControl
21
15
{
16
+ public const string TemplateStateNormal = "Normal" ;
17
+ public const string TemplateStateMousePressed = "MousePressed" ;
18
+ public const string TemplateStateMouseOut = "MouseOut" ;
19
+
20
+ private static readonly HashSet < Ripple > PressedInstances = new HashSet < Ripple > ( ) ;
21
+
22
22
static Ripple ( )
23
- {
23
+ {
24
24
DefaultStyleKeyProperty . OverrideMetadata ( typeof ( Ripple ) , new FrameworkPropertyMetadata ( typeof ( Ripple ) ) ) ;
25
+
26
+ EventManager . RegisterClassHandler ( typeof ( Window ) , Mouse . PreviewMouseUpEvent , new MouseButtonEventHandler ( MouseButtonEventHandler ) , true ) ;
27
+ EventManager . RegisterClassHandler ( typeof ( Window ) , Mouse . MouseMoveEvent , new MouseEventHandler ( MouseMouveEventHandler ) , true ) ;
25
28
}
26
29
27
30
public Ripple ( )
28
- {
29
- SizeChanged += OnSizeChanged ;
30
- }
31
+ {
32
+ SizeChanged += OnSizeChanged ;
33
+ }
31
34
32
- private void OnSizeChanged ( object sender , SizeChangedEventArgs sizeChangedEventArgs )
35
+ private static void MouseButtonEventHandler ( object sender , MouseButtonEventArgs e )
33
36
{
34
- RippleSize = Math . Max ( sizeChangedEventArgs . NewSize . Width , sizeChangedEventArgs . NewSize . Height ) * RippleSizeMultiplier ;
37
+ foreach ( var ripple in PressedInstances )
38
+ VisualStateManager . GoToState ( ripple , TemplateStateNormal , false ) ;
39
+ PressedInstances . Clear ( ) ;
35
40
}
36
41
42
+ private static void MouseMouveEventHandler ( object sender , MouseEventArgs e )
43
+ {
44
+ foreach ( var ripple in PressedInstances . ToList ( ) )
45
+ {
46
+ var relativePosition = Mouse . GetPosition ( ripple ) ;
47
+ if ( relativePosition . X < 0
48
+ || relativePosition . Y < 0
49
+ || relativePosition . X >= ripple . ActualWidth
50
+ || relativePosition . Y >= ripple . ActualHeight )
51
+
52
+ {
53
+ VisualStateManager . GoToState ( ripple , TemplateStateMouseOut , true ) ;
54
+ PressedInstances . Remove ( ripple ) ;
55
+ }
56
+ }
57
+ }
58
+
37
59
public static readonly DependencyProperty FeedbackProperty = DependencyProperty . Register (
38
60
"Feedback" , typeof ( Brush ) , typeof ( Ripple ) , new PropertyMetadata ( default ( Brush ) ) ) ;
39
61
@@ -46,25 +68,38 @@ public Brush Feedback
46
68
protected override void OnPreviewMouseLeftButtonDown ( MouseButtonEventArgs e )
47
69
{
48
70
var point = e . GetPosition ( this ) ;
49
-
50
- RippleX = point . X - RippleSize / 2 ;
51
- RippleY = point . Y - RippleSize / 2 ;
52
-
53
- VisualStateManager . GoToState ( this , "Normal" , true ) ;
54
- VisualStateManager . GoToState ( this , "MousePressed" , true ) ;
71
+
72
+ if ( RippleAssist . GetIsCentered ( this ) )
73
+ {
74
+ var innerContent = ( Content as FrameworkElement ) ;
75
+
76
+ if ( innerContent != null )
77
+ {
78
+ var position = innerContent . TransformToAncestor ( this )
79
+ . Transform ( new Point ( 0 , 0 ) ) ;
80
+
81
+ RippleX = position . X + innerContent . ActualWidth / 2 - RippleSize / 2 ;
82
+ RippleY = position . Y + innerContent . ActualHeight / 2 - RippleSize / 2 ;
83
+ }
84
+ else
85
+ {
86
+ RippleX = ActualWidth / 2 - RippleSize / 2 ;
87
+ RippleY = ActualHeight / 2 - RippleSize / 2 ;
88
+ }
89
+ }
90
+ else
91
+ {
92
+ RippleX = point . X - RippleSize / 2 ;
93
+ RippleY = point . Y - RippleSize / 2 ;
94
+ }
95
+
96
+ VisualStateManager . GoToState ( this , TemplateStateNormal , false ) ;
97
+ VisualStateManager . GoToState ( this , TemplateStateMousePressed , true ) ;
98
+ PressedInstances . Add ( this ) ;
55
99
56
100
base . OnPreviewMouseLeftButtonDown ( e ) ;
57
101
}
58
102
59
- public static readonly DependencyProperty RippleSizeMultiplierProperty = DependencyProperty . Register (
60
- "RippleSizeMultiplier" , typeof ( double ) , typeof ( Ripple ) , new PropertyMetadata ( 1.75 ) ) ;
61
-
62
- public double RippleSizeMultiplier
63
- {
64
- get { return ( double ) GetValue ( RippleSizeMultiplierProperty ) ; }
65
- set { SetValue ( RippleSizeMultiplierProperty , value ) ; }
66
- }
67
-
68
103
private static readonly DependencyPropertyKey RippleSizePropertyKey =
69
104
DependencyProperty . RegisterReadOnly (
70
105
"RippleSize" , typeof ( double ) , typeof ( Ripple ) ,
@@ -81,30 +116,59 @@ public double RippleSize
81
116
82
117
private static readonly DependencyPropertyKey RippleXPropertyKey =
83
118
DependencyProperty . RegisterReadOnly (
84
- "RippleX" , typeof ( double ) , typeof ( Ripple ) ,
119
+ "RippleX" , typeof ( double ) , typeof ( Ripple ) ,
85
120
new PropertyMetadata ( default ( double ) ) ) ;
86
121
87
122
public static readonly DependencyProperty RippleXProperty =
88
123
RippleXPropertyKey . DependencyProperty ;
89
124
90
125
public double RippleX
91
126
{
92
- get { return ( double ) GetValue ( RippleXProperty ) ; }
127
+ get { return ( double ) GetValue ( RippleXProperty ) ; }
93
128
private set { SetValue ( RippleXPropertyKey , value ) ; }
94
129
}
95
130
96
131
private static readonly DependencyPropertyKey RippleYPropertyKey =
97
132
DependencyProperty . RegisterReadOnly (
98
- "RippleY" , typeof ( double ) , typeof ( Ripple ) ,
133
+ "RippleY" , typeof ( double ) , typeof ( Ripple ) ,
99
134
new PropertyMetadata ( default ( double ) ) ) ;
100
135
101
136
public static readonly DependencyProperty RippleYProperty =
102
137
RippleYPropertyKey . DependencyProperty ;
103
138
104
139
public double RippleY
105
140
{
106
- get { return ( double ) GetValue ( RippleYProperty ) ; }
141
+ get { return ( double ) GetValue ( RippleYProperty ) ; }
107
142
private set { SetValue ( RippleYPropertyKey , value ) ; }
108
- }
143
+ }
144
+
145
+ public override void OnApplyTemplate ( )
146
+ {
147
+ base . OnApplyTemplate ( ) ;
148
+
149
+ VisualStateManager . GoToState ( this , TemplateStateNormal , false ) ;
150
+ }
151
+
152
+ private void OnSizeChanged ( object sender , SizeChangedEventArgs sizeChangedEventArgs )
153
+ {
154
+ var innerContent = ( Content as FrameworkElement ) ;
155
+
156
+ double width , height ;
157
+
158
+ if ( RippleAssist . GetIsCentered ( this ) && innerContent != null )
159
+ {
160
+ width = innerContent . ActualWidth ;
161
+ height = innerContent . ActualHeight ;
162
+ }
163
+ else
164
+ {
165
+ width = sizeChangedEventArgs . NewSize . Width ;
166
+ height = sizeChangedEventArgs . NewSize . Height ;
167
+ }
168
+
169
+ var radius = Math . Sqrt ( Math . Pow ( width , 2 ) + Math . Pow ( height , 2 ) ) ;
170
+
171
+ RippleSize = 2 * radius * RippleAssist . GetRippleSizeMultiplier ( this ) ;
172
+ }
109
173
}
110
174
}
0 commit comments