just kick off another build
[moon.git] / src / validators.cpp
blob60cdfb8271b716ad8227cb05c7252d2a469cc781
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3 * validators.cpp:
5 * Contact:
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.
13 #include <config.h>
15 #include <math.h>
17 #include "validators.h"
18 #include "thickness.h"
19 #include "cornerradius.h"
20 #include "style.h"
21 #include "frameworkelement.h"
22 #include "animation.h"
23 #include "propertypath.h"
24 #include "namescope.h"
26 bool
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"));
32 return false;
34 return true;
37 bool
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);
44 return true;
47 bool
48 Validators::BalanceValidator (DependencyObject* instance, DependencyProperty *property, Value *value, MoonError *error)
50 if (value) {
51 if (value->AsDouble () > 1.0) {
52 *value = Value(1.0);
53 } else if (value->AsDouble () < -1.0) {
54 *value = Value(-1.0);
58 return true;
61 bool
62 Validators::VolumeValidator (DependencyObject* instance, DependencyProperty *property, Value *value, MoonError *error)
64 if (value) {
65 if (value->AsDouble () > 1.0) {
66 *value = Value (1.0);
67 } else if (value->AsDouble () < 0.0) {
68 *value = Value (0.0);
72 return true;
75 bool
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);
82 return true;
85 bool
86 Validators::default_validator (DependencyObject* instance, DependencyProperty *property, Value *value, MoonError *error)
88 return true;
91 bool
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");
96 return false;
98 return true;
101 bool
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");
106 return false;
108 return true;
111 bool
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");
116 return false;
118 return true;
121 bool
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");
126 return false;
129 return true;
132 bool
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");
137 return false;
140 return true;
143 bool
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");
148 return false;
150 return true;
153 bool
154 Validators::TemplateValidator (DependencyObject* instance, DependencyProperty *property, Value *value, MoonError *error)
156 #if false
157 // this causes DRT #438 to throw an exception and subsequently
158 // timeout.
159 if (!value || value->GetIsNull ()) {
160 MoonError::FillIn (error, MoonError::EXCEPTION, 1001, "Value cannot be null");
161 return false;
163 #endif
164 if (instance->Is(Type::USERCONTROL)) {
165 MoonError::FillIn (error, MoonError::INVALID_OPERATION, 1001, "Cannot set the template property on a UserControl");
166 return false;
168 return true;
171 bool
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));
181 return false;
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.
189 return true;
192 bool RangeCheck (double d)
194 bool b = (d > -(1E300)) && (d < (1E300));
195 return b;
198 bool
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");
205 return false;
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");
210 return false;
212 return true;
215 bool
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");
222 return false;
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");
227 return false;
229 return true;
232 bool
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");
237 return false;
240 return true;
243 bool
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");
248 return false;
251 return true;
254 bool
255 Validators::StoryboardTargetPropertyValidator (DependencyObject* instance, DependencyProperty *property, Value *value, MoonError *error)
257 if (!IsTimelineValidator (instance, property, value, error))
258 return false;
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)
266 return false;
269 return true;
272 bool
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");
278 return false;
282 return true;
286 bool
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");
294 return false;
298 return true;
301 bool
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"));
307 return false;
309 return true;
312 bool
313 Validators::FloatValidator (DependencyObject *instance, DependencyProperty *property, Value *value, MoonError *error)
315 double d = value->AsDouble ();
317 switch (fpclassify (d)) {
318 case FP_SUBNORMAL:
319 case FP_INFINITE:
320 case FP_NAN:
321 MoonError::FillIn (error, MoonError::EXCEPTION, 1001, "Value is out of range");
322 return false;
323 default:
324 if ((float) d < -HUGE || (float) d > HUGE) {
325 MoonError::FillIn (error, MoonError::EXCEPTION, 1001, "Value is out of range");
326 return false;
330 return true;