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::DoubleGreaterThanZeroValidator (DependencyObject
* instance
, DependencyProperty
*property
, Value
*value
, MoonError
*error
)
114 if (value
->AsDouble () <= 0) {
115 MoonError::FillIn (error
, MoonError::ARGUMENT
, 1001, "Value must be greater than zero");
122 Validators::NonNullValidator (DependencyObject
* instance
, DependencyProperty
*property
, Value
*value
, MoonError
*error
)
124 if (!value
|| value
->GetIsNull ()) {
125 MoonError::FillIn (error
, MoonError::ARGUMENT
, 1001, "Value cannot be null");
133 Validators::NotNullOrEmptyValidator (DependencyObject
* instance
, DependencyProperty
*property
, Value
*value
, MoonError
*error
)
135 if (!value
|| value
->GetIsNull () || strlen (value
->AsString ()) == 0) {
136 MoonError::FillIn (error
, MoonError::EXCEPTION
, 1001, "Value cannot be null");
144 Validators::MediaAttributeCollectionValidator (DependencyObject
* instance
, DependencyProperty
*property
, Value
*value
, MoonError
*error
)
146 if (!value
|| value
->GetIsNull ()) {
147 MoonError::FillIn (error
, MoonError::EXCEPTION
, 1001, "Value cannot be null");
154 Validators::TemplateValidator (DependencyObject
* instance
, DependencyProperty
*property
, Value
*value
, MoonError
*error
)
157 // this causes DRT #438 to throw an exception and subsequently
159 if (!value
|| value
->GetIsNull ()) {
160 MoonError::FillIn (error
, MoonError::EXCEPTION
, 1001, "Value cannot be null");
164 if (instance
->Is(Type::USERCONTROL
)) {
165 MoonError::FillIn (error
, MoonError::INVALID_OPERATION
, 1001, "Cannot set the template property on a UserControl");
172 Validators::NameValidator (DependencyObject
* instance
, DependencyProperty
*property
, Value
*value
, MoonError
*error
)
174 NameScope
*scope
= instance
->FindNameScope ();
175 if (scope
&& value
) {
176 DependencyObject
*o
= scope
->FindName (value
->AsString ());
177 if (o
&& o
!= instance
) {
178 MoonError::FillIn (error
, MoonError::ARGUMENT
, 2028,
179 g_strdup_printf ("The name already exists in the tree: %s (%p %p).",
180 value
->AsString (), o
, instance
));
184 // TODO: Name validation
185 // This doesn't happen in 1.0 or 2.0b according to my tests, but according to the 2.0 docs
186 // names need to start with a '_' or letter. They can't start with a _. Also characters
187 // should be limited to a-z A-Z 0-9 and _. Once a newer beta actually enforces this
188 // I'll implement the validation method.
192 bool RangeCheck (double d
)
194 bool b
= (d
> -(1E300
)) && (d
< (1E300
));
199 Validators::BorderThicknessValidator (DependencyObject
* instance
, DependencyProperty
*property
, Value
*value
, MoonError
*error
)
201 Thickness t
= *value
->AsThickness ();
203 if (!RangeCheck (t
.left
) || !RangeCheck (t
.right
) || !RangeCheck (t
.top
) || !RangeCheck (t
.bottom
)){
204 MoonError::FillIn (error
, MoonError::EXCEPTION
, 1001, "Value is out of range");
208 if (t
.left
< 0 || t
.right
< 0 || t
.top
< 0 || t
.bottom
< 0){
209 MoonError::FillIn (error
, MoonError::ARGUMENT
, 1001, "Value is out of range");
216 Validators::CornerRadiusValidator (DependencyObject
* instance
, DependencyProperty
*property
, Value
*value
, MoonError
*error
)
218 CornerRadius t
= *value
->AsCornerRadius ();
220 if (!RangeCheck (t
.topLeft
) || !RangeCheck (t
.topRight
) || !RangeCheck (t
.bottomLeft
) || !RangeCheck (t
.bottomRight
)){
221 MoonError::FillIn (error
, MoonError::EXCEPTION
, 1001, "Value is out of range");
225 if (t
.topLeft
< 0 || t
.topRight
< 0 || t
.bottomLeft
< 0 || t
.bottomRight
< 0){
226 MoonError::FillIn (error
, MoonError::ARGUMENT
, 1001, "Value is out of range");
233 Validators::BufferingTimeValidator (DependencyObject
* instance
, DependencyProperty
*property
, Value
*value
, MoonError
*error
)
235 if (value
->AsTimeSpan () > 21427200000000000LL) {
236 MoonError::FillIn (error
, MoonError::EXCEPTION
, 1001, "Value is out of range");
244 Validators::IsTimelineValidator (DependencyObject
* instance
, DependencyProperty
*property
, Value
*value
, MoonError
*error
)
246 if (!instance
->Is (Type::TIMELINE
)) {
247 MoonError::FillIn (error
, MoonError::EXCEPTION
, 1001, "Instance is not a Timeline");
255 Validators::StoryboardTargetPropertyValidator (DependencyObject
* instance
, DependencyProperty
*property
, Value
*value
, MoonError
*error
)
257 if (!IsTimelineValidator (instance
, property
, value
, error
))
260 PropertyPath
*existing
= Storyboard::GetTargetProperty (instance
);
262 if (existing
&& existing
->property
!= NULL
) {
263 // it was initialized using a DP, we only allow it to be overriden with another DP.
264 PropertyPath
*new_path
= value
->AsPropertyPath();
265 if (new_path
->property
== NULL
)
273 Validators::IsSetterSealedValidator (DependencyObject
* instance
, DependencyProperty
*property
, Value
*value
, MoonError
*error
)
275 if (instance
->Is (Type::SETTERBASE
)) {
276 if (((SetterBase
*) instance
)->GetIsSealed ()) {
277 MoonError::FillIn (error
, MoonError::UNAUTHORIZED_ACCESS
, "Cannot modify a setter after it is used");
287 Validators::ContentControlContentValidator (DependencyObject
* instance
, DependencyProperty
*property
, Value
*value
, MoonError
*error
)
289 if (value
->Is (Type::FRAMEWORKELEMENT
)) {
290 FrameworkElement
*fwe
= value
->AsFrameworkElement();
292 if (fwe
->GetLogicalParent () && fwe
->GetLogicalParent ()->Is (Type::PANEL
)) {
293 MoonError::FillIn (error
, MoonError::ARGUMENT
, "Content is already a child of another element");
302 Validators::CrossDomainValidator (DependencyObject
* instance
, DependencyProperty
*property
, Value
*value
, MoonError
*error
)
304 if (instance
->GetValueNoDefault (property
)) {
305 MoonError::FillIn (error
, MoonError::ARGUMENT
, 1001,
306 g_strdup_printf ("Property 'ExternalCallersFromCrossDomain' cannot be changed.\n"));
313 Validators::FloatValidator (DependencyObject
*instance
, DependencyProperty
*property
, Value
*value
, MoonError
*error
)
315 double d
= value
->AsDouble ();
317 switch (fpclassify (d
)) {
321 MoonError::FillIn (error
, MoonError::EXCEPTION
, 1001, "Value is out of range");
324 if ((float) d
< -HUGE
|| (float) d
> HUGE
) {
325 MoonError::FillIn (error
, MoonError::EXCEPTION
, 1001, "Value is out of range");