xref: /haiku/src/apps/icon-o-matic/generic/property/Property.cpp (revision a3e794ae459fec76826407f8ba8c94cd3535f128)
1 /*
2  * Copyright 2006, Haiku.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Stephan Aßmus <superstippi@gmx.de>
7  */
8 
9 #include "Property.h"
10 
11 #include <new>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <strings.h>
15 
16 #include <Message.h>
17 
18 #include "support.h"
19 
20 using std::nothrow;
21 
22 // constructor
23 Property::Property(uint32 identifier)
24 	: fIdentifier(identifier),
25 	  fEditable(true)
26 {
27 }
28 
29 // constructor
30 Property::Property(const Property& other)
31 	: fIdentifier(other.fIdentifier),
32 	  fEditable(other.fEditable)
33 {
34 }
35 
36 // constructor
37 Property::Property(BMessage* archive)
38 	: fIdentifier(0),
39 	  fEditable(true)
40 {
41 	if (!archive)
42 		return;
43 
44 	if (archive->FindInt32("id", (int32*)&fIdentifier) < B_OK)
45 		fIdentifier = 0;
46 	if (archive->FindBool("editable", &fEditable) < B_OK)
47 		fEditable = true;
48 }
49 
50 // destructor
51 Property::~Property()
52 {
53 }
54 
55 // Archive
56 status_t
57 Property::Archive(BMessage* into, bool deep) const
58 {
59 	status_t ret = BArchivable::Archive(into, deep);
60 
61 	if (ret == B_OK)
62 		ret = into->AddInt32("id", fIdentifier);
63 
64 	if (ret == B_OK)
65 		ret = into->AddBool("editable", fEditable);
66 
67 	// finish off
68 	if (ret >= B_OK)
69 		ret = into->AddString("class", "Property");
70 
71 	return ret;
72 }
73 
74 // #pragma mark -
75 
76 // InterpolateTo
77 bool
78 Property::InterpolateTo(const Property* other, float scale)
79 {
80 	// some properties don't support this
81 	return false;
82 }
83 
84 // SetEditable
85 void
86 Property::SetEditable(bool editable)
87 {
88 	fEditable = editable;
89 }
90 
91 // #pragma mark -
92 
93 // constructor
94 IntProperty::IntProperty(uint32 identifier, int32 value,
95 						 int32 min, int32 max)
96 	: Property(identifier),
97 	  fValue(value),
98 	  fMin(min),
99 	  fMax(max)
100 {
101 }
102 
103 // constructor
104 IntProperty::IntProperty(const IntProperty& other)
105 	: Property(other),
106 	  fValue(other.fValue),
107 	  fMin(other.fMin),
108 	  fMax(other.fMax)
109 {
110 }
111 
112 // constructor
113 IntProperty::IntProperty(BMessage* archive)
114 	: Property(archive),
115 	  fValue(0),
116 	  fMin(0),
117 	  fMax(0)
118 {
119 	if (!archive)
120 		return;
121 
122 	if (archive->FindInt32("value", &fValue) < B_OK)
123 		fValue = 0;
124 	if (archive->FindInt32("min", &fMin) < B_OK)
125 		fMin = 0;
126 	if (archive->FindInt32("max", &fMax) < B_OK)
127 		fMax = 0;
128 }
129 
130 // destructor
131 IntProperty::~IntProperty()
132 {
133 }
134 
135 // Archive
136 status_t
137 IntProperty::Archive(BMessage* into, bool deep) const
138 {
139 	status_t ret = Property::Archive(into, deep);
140 
141 	if (ret >= B_OK)
142 		ret = into->AddInt32("value", fValue);
143 	if (ret >= B_OK)
144 		ret = into->AddInt32("min", fMin);
145 	if (ret >= B_OK)
146 		ret = into->AddInt32("max", fMax);
147 
148 	// finish off
149 	if (ret >= B_OK)
150 		ret = into->AddString("class", "IntProperty");
151 
152 	return ret;
153 }
154 
155 // Instantiate
156 BArchivable*
157 IntProperty::Instantiate(BMessage* archive)
158 {
159 	if (validate_instantiation(archive, "IntProperty"))
160 		return new IntProperty(archive);
161 
162 	return NULL;
163 }
164 
165 // Clone
166 Property*
167 IntProperty::Clone() const
168 {
169 	return new IntProperty(*this);
170 }
171 
172 // SetValue
173 bool
174 IntProperty::SetValue(const char* value)
175 {
176 	return SetValue(atoi(value));
177 }
178 
179 // SetValue
180 bool
181 IntProperty::SetValue(const Property* other)
182 {
183 	const IntProperty* i = dynamic_cast<const IntProperty*>(other);
184 	if (i) {
185 		return SetValue(i->Value());
186 	}
187 	return false;
188 }
189 
190 // GetValue
191 void
192 IntProperty::GetValue(BString& string)
193 {
194 	string << fValue;
195 }
196 
197 // InterpolateTo
198 bool
199 IntProperty::InterpolateTo(const Property* other, float scale)
200 {
201 	const IntProperty* i = dynamic_cast<const IntProperty*>(other);
202 	if (i) {
203 		return SetValue(fValue + (int32)((float)(i->Value()
204 												 - fValue) * scale + 0.5));
205 	}
206 	return false;
207 }
208 
209 // SetValue
210 bool
211 IntProperty::SetValue(int32 value)
212 {
213 	// truncate
214 	if (value < fMin)
215 		value = fMin;
216 	if (value > fMax)
217 		value = fMax;
218 
219 	if (value != fValue) {
220 		fValue = value;
221 		return true;
222 	}
223 	return false;
224 }
225 
226 // #pragma mark -
227 
228 // constructor
229 FloatProperty::FloatProperty(uint32 identifier, float value,
230 							 float min, float max)
231 	: Property(identifier),
232 	  fValue(value),
233 	  fMin(min),
234 	  fMax(max)
235 {
236 }
237 
238 // constructor
239 FloatProperty::FloatProperty(const FloatProperty& other)
240 	: Property(other),
241 	  fValue(other.fValue),
242 	  fMin(other.fMin),
243 	  fMax(other.fMax)
244 {
245 }
246 
247 // constructor
248 FloatProperty::FloatProperty(BMessage* archive)
249 	: Property(archive),
250 	  fValue(0.0),
251 	  fMin(0.0),
252 	  fMax(0.0)
253 {
254 	if (!archive)
255 		return;
256 
257 	if (archive->FindFloat("value", &fValue) < B_OK)
258 		fValue = 0.0;
259 	if (archive->FindFloat("min", &fMin) < B_OK)
260 		fMin = 0.0;
261 	if (archive->FindFloat("max", &fMax) < B_OK)
262 		fMax = 0.0;
263 }
264 
265 // destructor
266 FloatProperty::~FloatProperty()
267 {
268 }
269 
270 // Archive
271 status_t
272 FloatProperty::Archive(BMessage* into, bool deep) const
273 {
274 	status_t ret = Property::Archive(into, deep);
275 
276 	if (ret >= B_OK)
277 		ret = into->AddFloat("value", fValue);
278 	if (ret >= B_OK)
279 		ret = into->AddFloat("min", fMin);
280 	if (ret >= B_OK)
281 		ret = into->AddFloat("max", fMax);
282 
283 	// finish off
284 	if (ret >= B_OK)
285 		ret = into->AddString("class", "FloatProperty");
286 
287 	return ret;
288 }
289 
290 // Instantiate
291 BArchivable*
292 FloatProperty::Instantiate(BMessage* archive)
293 {
294 	if (validate_instantiation(archive, "FloatProperty"))
295 		return new FloatProperty(archive);
296 
297 	return NULL;
298 }
299 
300 // Clone
301 Property*
302 FloatProperty::Clone() const
303 {
304 	return new FloatProperty(*this);
305 }
306 
307 // SetValue
308 bool
309 FloatProperty::SetValue(const char* value)
310 {
311 	return SetValue(atof(value));
312 }
313 
314 // SetValue
315 bool
316 FloatProperty::SetValue(const Property* other)
317 {
318 	const FloatProperty* f = dynamic_cast<const FloatProperty*>(other);
319 	if (f) {
320 		return SetValue(f->Value());
321 	}
322 	return false;
323 }
324 
325 // GetValue
326 void
327 FloatProperty::GetValue(BString& string)
328 {
329 	append_float(string, fValue, 4);
330 }
331 
332 // InterpolateTo
333 bool
334 FloatProperty::InterpolateTo(const Property* other, float scale)
335 {
336 	const FloatProperty* f = dynamic_cast<const FloatProperty*>(other);
337 	if (f) {
338 		return SetValue(fValue + (f->Value() - fValue) * scale);
339 	}
340 	return false;
341 }
342 
343 // SetValue
344 bool
345 FloatProperty::SetValue(float value)
346 {
347 	// truncate
348 	if (value < fMin)
349 		value = fMin;
350 	if (value > fMax)
351 		value = fMax;
352 
353 	if (value != fValue) {
354 		fValue = value;
355 		return true;
356 	}
357 	return false;
358 }
359 
360 // #pragma mark -
361 
362 // constructor
363 UInt8Property::UInt8Property(uint32 identifier, uint8 value)
364 	: Property(identifier),
365 	  fValue(value)
366 {
367 }
368 
369 // constructor
370 UInt8Property::UInt8Property(const UInt8Property& other)
371 	: Property(other),
372 	  fValue(other.fValue)
373 {
374 }
375 
376 // constructor
377 UInt8Property::UInt8Property(BMessage* archive)
378 	: Property(archive),
379 	  fValue(0)
380 {
381 	if (!archive)
382 		return;
383 
384 	if (archive->FindInt8("value", (int8*)&fValue) < B_OK)
385 		fValue = 0;
386 }
387 
388 // destructor
389 UInt8Property::~UInt8Property()
390 {
391 }
392 
393 // Archive
394 status_t
395 UInt8Property::Archive(BMessage* into, bool deep) const
396 {
397 	status_t ret = Property::Archive(into, deep);
398 
399 	if (ret >= B_OK)
400 		ret = into->AddInt8("value", fValue);
401 
402 	// finish off
403 	if (ret >= B_OK)
404 		ret = into->AddString("class", "UInt8Property");
405 
406 	return ret;
407 }
408 
409 // Instantiate
410 BArchivable*
411 UInt8Property::Instantiate(BMessage* archive)
412 {
413 	if (validate_instantiation(archive, "UInt8Property"))
414 		return new UInt8Property(archive);
415 
416 	return NULL;
417 }
418 
419 // Clone
420 Property*
421 UInt8Property::Clone() const
422 {
423 	return new UInt8Property(*this);
424 }
425 
426 // SetValue
427 bool
428 UInt8Property::SetValue(const char* value)
429 {
430 	return SetValue((uint8)max_c(0, min_c(255, atoi(value))));
431 }
432 
433 // SetValue
434 bool
435 UInt8Property::SetValue(const Property* other)
436 {
437 	const UInt8Property* u = dynamic_cast<const UInt8Property*>(other);
438 	if (u) {
439 		return SetValue(u->Value());
440 	}
441 	return false;
442 }
443 
444 // GetValue
445 void
446 UInt8Property::GetValue(BString& string)
447 {
448 	string << fValue;
449 }
450 
451 // InterpolateTo
452 bool
453 UInt8Property::InterpolateTo(const Property* other, float scale)
454 {
455 	const UInt8Property* u = dynamic_cast<const UInt8Property*>(other);
456 	if (u) {
457 		return SetValue(fValue + (uint8)((float)(u->Value()
458 												 - fValue) * scale + 0.5));
459 	}
460 	return false;
461 }
462 
463 // SetValue
464 bool
465 UInt8Property::SetValue(uint8 value)
466 {
467 	if (value != fValue) {
468 		fValue = value;
469 		return true;
470 	}
471 	return false;
472 }
473 
474 // #pragma mark -
475 
476 // constructor
477 BoolProperty::BoolProperty(uint32 identifier, bool value)
478 	: Property(identifier),
479 	  fValue(value)
480 {
481 }
482 
483 // constructor
484 BoolProperty::BoolProperty(const BoolProperty& other)
485 	: Property(other),
486 	  fValue(other.fValue)
487 {
488 }
489 
490 // constructor
491 BoolProperty::BoolProperty(BMessage* archive)
492 	: Property(archive),
493 	  fValue(false)
494 {
495 	if (!archive)
496 		return;
497 
498 	if (archive->FindBool("value", &fValue) < B_OK)
499 		fValue = false;
500 }
501 
502 // destructor
503 BoolProperty::~BoolProperty()
504 {
505 }
506 
507 // Archive
508 status_t
509 BoolProperty::Archive(BMessage* into, bool deep) const
510 {
511 	status_t ret = Property::Archive(into, deep);
512 
513 	if (ret >= B_OK)
514 		ret = into->AddBool("value", fValue);
515 
516 	// finish off
517 	if (ret >= B_OK)
518 		ret = into->AddString("class", "BoolProperty");
519 
520 	return ret;
521 }
522 
523 // Instantiate
524 BArchivable*
525 BoolProperty::Instantiate(BMessage* archive)
526 {
527 	if (validate_instantiation(archive, "BoolProperty"))
528 		return new BoolProperty(archive);
529 
530 	return NULL;
531 }
532 
533 // Clone
534 Property*
535 BoolProperty::Clone() const
536 {
537 	return new BoolProperty(*this);
538 }
539 
540 // SetValue
541 bool
542 BoolProperty::SetValue(const char* value)
543 {
544 	bool v;
545 	if (strcasecmp(value, "true") == 0)
546 		v = true;
547 	else if (strcasecmp(value, "on") == 0)
548 		v = true;
549 	else
550 		v = (bool)atoi(value);
551 
552 	return SetValue(v);
553 }
554 
555 // SetValue
556 bool
557 BoolProperty::SetValue(const Property* other)
558 {
559 	const BoolProperty* b = dynamic_cast<const BoolProperty*>(other);
560 	if (b) {
561 		return SetValue(b->Value());
562 	}
563 	return false;
564 }
565 
566 // GetValue
567 void
568 BoolProperty::GetValue(BString& string)
569 {
570 	if (fValue)
571 		string << "on";
572 	else
573 		string << "off";
574 }
575 
576 // InterpolateTo
577 bool
578 BoolProperty::InterpolateTo(const Property* other, float scale)
579 {
580 	const BoolProperty* b = dynamic_cast<const BoolProperty*>(other);
581 	if (b) {
582 		if (scale >= 0.5)
583 			return SetValue(b->Value());
584 	}
585 	return false;
586 }
587 
588 // SetValue
589 bool
590 BoolProperty::SetValue(bool value)
591 {
592 	if (value != fValue) {
593 		fValue = value;
594 		return true;
595 	}
596 	return false;
597 }
598 
599 // #pragma mark -
600 
601 // constructor
602 StringProperty::StringProperty(uint32 identifier, const char* value)
603 	: Property(identifier),
604 	  fValue(value)
605 {
606 }
607 
608 // constructor
609 StringProperty::StringProperty(const StringProperty& other)
610 	: Property(other),
611 	  fValue(other.fValue)
612 {
613 }
614 
615 // constructor
616 StringProperty::StringProperty(BMessage* archive)
617 	: Property(archive),
618 	  fValue()
619 {
620 	if (!archive)
621 		return;
622 
623 	if (archive->FindString("value", &fValue) < B_OK)
624 		fValue = "";
625 }
626 
627 // destructor
628 StringProperty::~StringProperty()
629 {
630 }
631 
632 // Archive
633 status_t
634 StringProperty::Archive(BMessage* into, bool deep) const
635 {
636 	status_t ret = Property::Archive(into, deep);
637 
638 	if (ret >= B_OK)
639 		ret = into->AddString("value", fValue);
640 
641 	// finish off
642 	if (ret >= B_OK)
643 		ret = into->AddString("class", "StringProperty");
644 
645 	return ret;
646 }
647 
648 // Instantiate
649 BArchivable*
650 StringProperty::Instantiate(BMessage* archive)
651 {
652 	if (validate_instantiation(archive, "StringProperty"))
653 		return new StringProperty(archive);
654 
655 	return NULL;
656 }
657 
658 // Clone
659 Property*
660 StringProperty::Clone() const
661 {
662 	return new StringProperty(*this);
663 }
664 
665 // SetValue
666 bool
667 StringProperty::SetValue(const char* value)
668 {
669 	BString t(value);
670 	if (fValue != t) {
671 		fValue = t;
672 		return true;
673 	}
674 	return false;
675 }
676 
677 // SetValue
678 bool
679 StringProperty::SetValue(const Property* other)
680 {
681 	const StringProperty* s = dynamic_cast<const StringProperty*>(other);
682 	if (s) {
683 		return SetValue(s->Value());
684 	}
685 	return false;
686 }
687 
688 // GetValue
689 void
690 StringProperty::GetValue(BString& string)
691 {
692 	string << fValue;
693 }
694 
695