root / trunk / Pithos.Client.WPF / SelectiveSynch / VirtualToggleButton.cs @ 255f5f86
History | View | Annotate | Download (11.1 kB)
1 |
#region |
---|---|
2 |
/* ----------------------------------------------------------------------- |
3 |
* <copyright file="VirtualToggleButton.cs" company="GRNet"> |
4 |
* |
5 |
* Copyright 2011-2012 GRNET S.A. All rights reserved. |
6 |
* |
7 |
* Redistribution and use in source and binary forms, with or |
8 |
* without modification, are permitted provided that the following |
9 |
* conditions are met: |
10 |
* |
11 |
* 1. Redistributions of source code must retain the above |
12 |
* copyright notice, this list of conditions and the following |
13 |
* disclaimer. |
14 |
* |
15 |
* 2. Redistributions in binary form must reproduce the above |
16 |
* copyright notice, this list of conditions and the following |
17 |
* disclaimer in the documentation and/or other materials |
18 |
* provided with the distribution. |
19 |
* |
20 |
* |
21 |
* THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS |
22 |
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
23 |
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
24 |
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR |
25 |
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
26 |
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
27 |
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
28 |
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
29 |
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
30 |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
31 |
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
32 |
* POSSIBILITY OF SUCH DAMAGE. |
33 |
* |
34 |
* The views and conclusions contained in the software and |
35 |
* documentation are those of the authors and should not be |
36 |
* interpreted as representing official policies, either expressed |
37 |
* or implied, of GRNET S.A. |
38 |
* </copyright> |
39 |
* ----------------------------------------------------------------------- |
40 |
*/ |
41 |
#endregion |
42 |
using System; |
43 |
using System.Collections.Generic; |
44 |
using System.Linq; |
45 |
using System.Text; |
46 |
using System.Windows; |
47 |
using System.Windows.Controls.Primitives; |
48 |
using System.Windows.Input; |
49 |
|
50 |
namespace Pithos.Client.WPF.SelectiveSynch |
51 |
{ |
52 |
public static class VirtualToggleButton |
53 |
{ |
54 |
#region attached properties |
55 |
|
56 |
#region IsChecked |
57 |
|
58 |
/// <summary> |
59 |
/// IsChecked Attached Dependency Property |
60 |
/// </summary> |
61 |
public static readonly DependencyProperty IsCheckedProperty = |
62 |
DependencyProperty.RegisterAttached("IsChecked", typeof(Nullable<bool>), typeof(VirtualToggleButton), |
63 |
new FrameworkPropertyMetadata((Nullable<bool>)false, |
64 |
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault | FrameworkPropertyMetadataOptions.Journal, |
65 |
new PropertyChangedCallback(OnIsCheckedChanged))); |
66 |
|
67 |
/// <summary> |
68 |
/// Gets the IsChecked property. This dependency property |
69 |
/// indicates whether the toggle button is checked. |
70 |
/// </summary> |
71 |
public static Nullable<bool> GetIsChecked(DependencyObject d) |
72 |
{ |
73 |
return (Nullable<bool>)d.GetValue(IsCheckedProperty); |
74 |
} |
75 |
|
76 |
/// <summary> |
77 |
/// Sets the IsChecked property. This dependency property |
78 |
/// indicates whether the toggle button is checked. |
79 |
/// </summary> |
80 |
public static void SetIsChecked(DependencyObject d, Nullable<bool> value) |
81 |
{ |
82 |
d.SetValue(IsCheckedProperty, value); |
83 |
} |
84 |
|
85 |
/// <summary> |
86 |
/// Handles changes to the IsChecked property. |
87 |
/// </summary> |
88 |
private static void OnIsCheckedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) |
89 |
{ |
90 |
UIElement pseudobutton = d as UIElement; |
91 |
if (pseudobutton != null) |
92 |
{ |
93 |
Nullable<bool> newValue = (Nullable<bool>)e.NewValue; |
94 |
if (newValue == true) |
95 |
{ |
96 |
RaiseCheckedEvent(pseudobutton); |
97 |
} |
98 |
else if (newValue == false) |
99 |
{ |
100 |
RaiseUncheckedEvent(pseudobutton); |
101 |
} |
102 |
else |
103 |
{ |
104 |
RaiseIndeterminateEvent(pseudobutton); |
105 |
} |
106 |
} |
107 |
} |
108 |
|
109 |
#endregion |
110 |
|
111 |
#region IsThreeState |
112 |
|
113 |
/// <summary> |
114 |
/// IsThreeState Attached Dependency Property |
115 |
/// </summary> |
116 |
public static readonly DependencyProperty IsThreeStateProperty = |
117 |
DependencyProperty.RegisterAttached("IsThreeState", typeof(bool), typeof(VirtualToggleButton), |
118 |
new FrameworkPropertyMetadata((bool)false)); |
119 |
|
120 |
/// <summary> |
121 |
/// Gets the IsThreeState property. This dependency property |
122 |
/// indicates whether the control supports two or three states. |
123 |
/// IsChecked can be set to null as a third state when IsThreeState is true. |
124 |
/// </summary> |
125 |
public static bool GetIsThreeState(DependencyObject d) |
126 |
{ |
127 |
return (bool)d.GetValue(IsThreeStateProperty); |
128 |
} |
129 |
|
130 |
/// <summary> |
131 |
/// Sets the IsThreeState property. This dependency property |
132 |
/// indicates whether the control supports two or three states. |
133 |
/// IsChecked can be set to null as a third state when IsThreeState is true. |
134 |
/// </summary> |
135 |
public static void SetIsThreeState(DependencyObject d, bool value) |
136 |
{ |
137 |
d.SetValue(IsThreeStateProperty, value); |
138 |
} |
139 |
|
140 |
#endregion |
141 |
|
142 |
#region IsVirtualToggleButton |
143 |
|
144 |
/// <summary> |
145 |
/// IsVirtualToggleButton Attached Dependency Property |
146 |
/// </summary> |
147 |
public static readonly DependencyProperty IsVirtualToggleButtonProperty = |
148 |
DependencyProperty.RegisterAttached("IsVirtualToggleButton", typeof(bool), typeof(VirtualToggleButton), |
149 |
new FrameworkPropertyMetadata((bool)false, |
150 |
new PropertyChangedCallback(OnIsVirtualToggleButtonChanged))); |
151 |
|
152 |
/// <summary> |
153 |
/// Gets the IsVirtualToggleButton property. This dependency property |
154 |
/// indicates whether the object to which the property is attached is treated as a VirtualToggleButton. |
155 |
/// If true, the object will respond to keyboard and mouse input the same way a ToggleButton would. |
156 |
/// </summary> |
157 |
public static bool GetIsVirtualToggleButton(DependencyObject d) |
158 |
{ |
159 |
return (bool)d.GetValue(IsVirtualToggleButtonProperty); |
160 |
} |
161 |
|
162 |
/// <summary> |
163 |
/// Sets the IsVirtualToggleButton property. This dependency property |
164 |
/// indicates whether the object to which the property is attached is treated as a VirtualToggleButton. |
165 |
/// If true, the object will respond to keyboard and mouse input the same way a ToggleButton would. |
166 |
/// </summary> |
167 |
public static void SetIsVirtualToggleButton(DependencyObject d, bool value) |
168 |
{ |
169 |
d.SetValue(IsVirtualToggleButtonProperty, value); |
170 |
} |
171 |
|
172 |
/// <summary> |
173 |
/// Handles changes to the IsVirtualToggleButton property. |
174 |
/// </summary> |
175 |
private static void OnIsVirtualToggleButtonChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) |
176 |
{ |
177 |
IInputElement element = d as IInputElement; |
178 |
if (element != null) |
179 |
{ |
180 |
if ((bool)e.NewValue) |
181 |
{ |
182 |
element.MouseLeftButtonDown += OnMouseLeftButtonDown; |
183 |
element.KeyDown += OnKeyDown; |
184 |
} |
185 |
else |
186 |
{ |
187 |
element.MouseLeftButtonDown -= OnMouseLeftButtonDown; |
188 |
element.KeyDown -= OnKeyDown; |
189 |
} |
190 |
} |
191 |
} |
192 |
|
193 |
#endregion |
194 |
|
195 |
#endregion |
196 |
|
197 |
#region routed events |
198 |
|
199 |
#region Checked |
200 |
|
201 |
/// <summary> |
202 |
/// A static helper method to raise the Checked event on a target element. |
203 |
/// </summary> |
204 |
/// <param name="target">UIElement or ContentElement on which to raise the event</param> |
205 |
internal static RoutedEventArgs RaiseCheckedEvent(UIElement target) |
206 |
{ |
207 |
if (target == null) return null; |
208 |
|
209 |
RoutedEventArgs args = new RoutedEventArgs(); |
210 |
args.RoutedEvent = ToggleButton.CheckedEvent; |
211 |
RaiseEvent(target, args); |
212 |
return args; |
213 |
} |
214 |
|
215 |
#endregion |
216 |
|
217 |
#region Unchecked |
218 |
|
219 |
/// <summary> |
220 |
/// A static helper method to raise the Unchecked event on a target element. |
221 |
/// </summary> |
222 |
/// <param name="target">UIElement or ContentElement on which to raise the event</param> |
223 |
internal static RoutedEventArgs RaiseUncheckedEvent(UIElement target) |
224 |
{ |
225 |
if (target == null) return null; |
226 |
|
227 |
RoutedEventArgs args = new RoutedEventArgs(); |
228 |
args.RoutedEvent = ToggleButton.UncheckedEvent; |
229 |
RaiseEvent(target, args); |
230 |
return args; |
231 |
} |
232 |
|
233 |
#endregion |
234 |
|
235 |
#region Indeterminate |
236 |
|
237 |
/// <summary> |
238 |
/// A static helper method to raise the Indeterminate event on a target element. |
239 |
/// </summary> |
240 |
/// <param name="target">UIElement or ContentElement on which to raise the event</param> |
241 |
internal static RoutedEventArgs RaiseIndeterminateEvent(UIElement target) |
242 |
{ |
243 |
if (target == null) return null; |
244 |
|
245 |
RoutedEventArgs args = new RoutedEventArgs(); |
246 |
args.RoutedEvent = ToggleButton.IndeterminateEvent; |
247 |
RaiseEvent(target, args); |
248 |
return args; |
249 |
} |
250 |
|
251 |
#endregion |
252 |
|
253 |
#endregion |
254 |
|
255 |
#region private methods |
256 |
|
257 |
private static void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e) |
258 |
{ |
259 |
e.Handled = true; |
260 |
UpdateIsChecked(sender as DependencyObject); |
261 |
} |
262 |
|
263 |
private static void OnKeyDown(object sender, KeyEventArgs e) |
264 |
{ |
265 |
if (e.OriginalSource == sender) |
266 |
{ |
267 |
if (e.Key == Key.Space) |
268 |
{ |
269 |
// ignore alt+space which invokes the system menu |
270 |
if ((Keyboard.Modifiers & ModifierKeys.Alt) == ModifierKeys.Alt) return; |
271 |
|
272 |
UpdateIsChecked(sender as DependencyObject); |
273 |
e.Handled = true; |
274 |
|
275 |
} |
276 |
else if (e.Key == Key.Enter && (bool)(sender as DependencyObject).GetValue(KeyboardNavigation.AcceptsReturnProperty)) |
277 |
{ |
278 |
UpdateIsChecked(sender as DependencyObject); |
279 |
e.Handled = true; |
280 |
} |
281 |
} |
282 |
} |
283 |
|
284 |
private static void UpdateIsChecked(DependencyObject d) |
285 |
{ |
286 |
Nullable<bool> isChecked = GetIsChecked(d); |
287 |
if (isChecked == true) |
288 |
{ |
289 |
SetIsChecked(d, GetIsThreeState(d) ? (Nullable<bool>)null : (Nullable<bool>)false); |
290 |
} |
291 |
else |
292 |
{ |
293 |
SetIsChecked(d, isChecked.HasValue); |
294 |
} |
295 |
} |
296 |
|
297 |
private static void RaiseEvent(DependencyObject target, RoutedEventArgs args) |
298 |
{ |
299 |
if (target is UIElement) |
300 |
{ |
301 |
(target as UIElement).RaiseEvent(args); |
302 |
} |
303 |
else if (target is ContentElement) |
304 |
{ |
305 |
(target as ContentElement).RaiseEvent(args); |
306 |
} |
307 |
} |
308 |
|
309 |
#endregion |
310 |
} |
311 |
} |