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