1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
6 * Moonlight List (moonlight-list@lists.ximian.com)
8 * Copyright 2008 Novell, Inc. (http://www.novell.com)
10 * See the LICENSE file included with the distribution for details.
17 #include "validators.h"
18 #include "thickness.h"
19 #include "cornerradius.h"
21 #include "frameworkelement.h"
22 #include "animation.h"
23 #include "propertypath.h"
24 #include "namescope.h"
27 Validators::StyleValidator (DependencyObject
* instance
, DependencyProperty
*property
, Value
*value
, MoonError
*error
) {
28 Value
*current
= instance
->GetValue (property
);
29 if (current
&& !current
->GetIsNull ()) {
30 MoonError::FillIn (error
, MoonError::EXCEPTION
, 1001,
31 g_strdup_printf ("Property 'Style' cannot be assigned to more than once\n"));
38 Validators::AudioStreamIndexValidator (DependencyObject
* instance
, DependencyProperty
*property
, Value
*value
, MoonError
*error
)
40 // A value of -1 is converted to null. Any other value is left as-is
41 if (value
&& value
->AsInt32() == -1)
42 value
->SetIsNull (true);
48 Validators::BalanceValidator (DependencyObject
* instance
, DependencyProperty
*property
, Value
*value
, MoonError
*error
)
51 if (value
->AsDouble () > 1.0) {
53 } else if (value
->AsDouble () < -1.0) {
62 Validators::VolumeValidator (DependencyObject
* instance
, DependencyProperty
*property
, Value
*value
, MoonError
*error
)
65 if (value
->AsDouble () > 1.0) {
67 } else if (value
->AsDouble () < 0.0) {
76 Validators::CursorValidator (DependencyObject
* instance
, DependencyProperty
*property
, Value
*value
, MoonError
*error
)
78 // If the value is null, it means the default cursor has been set.
79 if (value
->GetIsNull ())
80 *value
= Value ((int) MouseCursorDefault
);
86 Validators::default_validator (DependencyObject
* instance
, DependencyProperty
*property
, Value
*value
, MoonError
*error
)
92 Validators::PositiveIntValidator (DependencyObject
* instance
, DependencyProperty
*property
, Value
*value
, MoonError
*error
)
94 if (value
->AsInt32() < 0) {
95 MoonError::FillIn (error
, MoonError::ARGUMENT
, 1001, "Value must be greater than or equal to zero");
102 Validators::IntGreaterThanZeroValidator (DependencyObject
* instance
, DependencyProperty
*property
, Value
*value
, MoonError
*error
)
104 if (value
->AsInt32() < 1) {
105 MoonError::FillIn (error
, MoonError::ARGUMENT
, 1001, "Value must be greater than zero");
112 Validators::IsInputMethodEnabledValidator (DependencyObject
* instance
, DependencyProperty
*property
, Value
*value
, MoonError
*error
)
114 if (!instance
->Is (Type::TEXTBOX
)) {
115 MoonError::FillIn (error
, MoonError::ARGUMENT
, 1001, "Target object must be a TextBox");
122 Validators::DoubleGreaterThanZeroValidator (DependencyObject
* instance
, DependencyProperty
*property
, Value
*value
, MoonError
*error
)
124 if (value
->AsDouble () <= 0) {
125 MoonError::FillIn (error
, MoonError::ARGUMENT
, 1001, "Value must be greater than zero");
132 Validators::NonNullValidator (DependencyObject
* instance
, DependencyProperty
*property
, Value
*value
, MoonError
*error
)
134 if (!value
|| value
->GetIsNull ()) {
135 MoonError::FillIn (error
, MoonError::ARGUMENT
, 1001, "Value cannot be null");
143 Validators::NotNullOrEmptyValidator (DependencyObject
* instance
, DependencyProperty
*property
, Value
*value
, MoonError
*error
)
145 if (!value
|| value
->GetIsNull () || strlen (value
->AsString ()) == 0) {
146 MoonError::FillIn (error
, MoonError::EXCEPTION
, 1001, "Value cannot be null");
154 Validators::MediaAttributeCollectionValidator (DependencyObject
* instance
, DependencyProperty
*property
, Value
*value
, MoonError
*error
)
156 if (!value
|| value
->GetIsNull ()) {
157 MoonError::FillIn (error
, MoonError::EXCEPTION
, 1001, "Value cannot be null");
164 Validators::TemplateValidator (DependencyObject
* instance
, DependencyProperty
*property
, Value
*value
, MoonError
*error
)
167 // this causes DRT #438 to throw an exception and subsequently
169 if (!value
|| value
->GetIsNull ()) {
170 MoonError::FillIn (error
, MoonError::EXCEPTION
, 1001, "Value cannot be null");
174 if (instance
->Is(Type::USERCONTROL
)) {
175 MoonError::FillIn (error
, MoonError::INVALID_OPERATION
, 1001, "Cannot set the template property on a UserControl");
182 Validators::NameValidator (DependencyObject
* instance
, DependencyProperty
*property
, Value
*value
, MoonError
*error
)
184 NameScope
*scope
= instance
->FindNameScope ();
185 if (scope
&& value
) {
186 DependencyObject
*o
= scope
->FindName (value
->AsString ());
187 if (o
&& o
!= instance
) {
188 MoonError::FillIn (error
, MoonError::ARGUMENT
, 2028,
189 g_strdup_printf ("The name already exists in the tree: %s (%p %p).",
190 value
->AsString (), o
, instance
));
194 // TODO: Name validation
195 // This doesn't happen in 1.0 or 2.0b according to my tests, but according to the 2.0 docs
196 // names need to start with a '_' or letter. They can't start with a _. Also characters
197 // should be limited to a-z A-Z 0-9 and _. Once a newer beta actually enforces this
198 // I'll implement the validation method.
202 bool RangeCheck (double d
)
204 bool b
= (d
> -(1E300
)) && (d
< (1E300
));
209 Validators::BorderThicknessValidator (DependencyObject
* instance
, DependencyProperty
*property
, Value
*value
, MoonError
*error
)
211 Thickness t
= *value
->AsThickness ();
213 if (!RangeCheck (t
.left
) || !RangeCheck (t
.right
) || !RangeCheck (t
.top
) || !RangeCheck (t
.bottom
)){
214 MoonError::FillIn (error
, MoonError::EXCEPTION
, 1001, "Value is out of range");
218 if (t
.left
< 0 || t
.right
< 0 || t
.top
< 0 || t
.bottom
< 0){
219 MoonError::FillIn (error
, MoonError::ARGUMENT
, 1001, "Value is out of range");
226 Validators::CornerRadiusValidator (DependencyObject
* instance
, DependencyProperty
*property
, Value
*value
, MoonError
*error
)
228 CornerRadius t
= *value
->AsCornerRadius ();
230 if (!RangeCheck (t
.topLeft
) || !RangeCheck (t
.topRight
) || !RangeCheck (t
.bottomLeft
) || !RangeCheck (t
.bottomRight
)){
231 MoonError::FillIn (error
, MoonError::EXCEPTION
, 1001, "Value is out of range");
235 if (t
.topLeft
< 0 || t
.topRight
< 0 || t
.bottomLeft
< 0 || t
.bottomRight
< 0){
236 MoonError::FillIn (error
, MoonError::ARGUMENT
, 1001, "Value is out of range");
243 Validators::BufferingTimeValidator (DependencyObject
* instance
, DependencyProperty
*property
, Value
*value
, MoonError
*error
)
245 if (value
->AsTimeSpan () > 21427200000000000LL) {
246 MoonError::FillIn (error
, MoonError::EXCEPTION
, 1001, "Value is out of range");
254 Validators::IsTimelineValidator (DependencyObject
* instance
, DependencyProperty
*property
, Value
*value
, MoonError
*error
)
256 if (!instance
->Is (Type::TIMELINE
)) {
257 MoonError::FillIn (error
, MoonError::EXCEPTION
, 1001, "Instance is not a Timeline");
265 Validators::StoryboardTargetPropertyValidator (DependencyObject
* instance
, DependencyProperty
*property
, Value
*value
, MoonError
*error
)
267 if (!IsTimelineValidator (instance
, property
, value
, error
))
270 PropertyPath
*existing
= Storyboard::GetTargetProperty (instance
);
272 if (existing
&& existing
->property
!= NULL
) {
273 // it was initialized using a DP, we only allow it to be overriden with another DP.
274 PropertyPath
*new_path
= value
->AsPropertyPath();
275 if (new_path
->property
== NULL
)
283 Validators::IsSetterSealedValidator (DependencyObject
* instance
, DependencyProperty
*property
, Value
*value
, MoonError
*error
)
285 if (instance
->Is (Type::SETTERBASE
)) {
286 if (((SetterBase
*) instance
)->GetIsSealed ()) {
287 MoonError::FillIn (error
, MoonError::UNAUTHORIZED_ACCESS
, "Cannot modify a setter after it is used");
297 Validators::ContentControlContentValidator (DependencyObject
* instance
, DependencyProperty
*property
, Value
*value
, MoonError
*error
)
299 if (value
->Is (Type::FRAMEWORKELEMENT
)) {
300 FrameworkElement
*fwe
= value
->AsFrameworkElement();
302 if (fwe
->GetLogicalParent () && fwe
->GetLogicalParent ()->Is (Type::PANEL
)) {
303 MoonError::FillIn (error
, MoonError::ARGUMENT
, "Content is already a child of another element");
312 Validators::CrossDomainValidator (DependencyObject
* instance
, DependencyProperty
*property
, Value
*value
, MoonError
*error
)
314 if (instance
->GetValueNoDefault (property
)) {
315 MoonError::FillIn (error
, MoonError::ARGUMENT
, 1001,
316 g_strdup_printf ("Property 'ExternalCallersFromCrossDomain' cannot be changed.\n"));
323 Validators::FloatValidator (DependencyObject
*instance
, DependencyProperty
*property
, Value
*value
, MoonError
*error
)
325 double d
= value
->AsDouble ();
327 switch (fpclassify (d
)) {
331 MoonError::FillIn (error
, MoonError::EXCEPTION
, 1001, "Value is out of range");
334 if ((float) d
< -HUGE
|| (float) d
> HUGE
) {
335 MoonError::FillIn (error
, MoonError::EXCEPTION
, 1001, "Value is out of range");