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 <string.h> 15 16#include <Message.h> 17 18#include "support.h" 19 20using std::nothrow; 21 22// constructor 23Property::Property(uint32 identifier) 24 : fIdentifier(identifier), 25 fEditable(true) 26{ 27} 28 29// constructor 30Property::Property(const Property& other) 31 : fIdentifier(other.fIdentifier), 32 fEditable(other.fEditable) 33{ 34} 35 36// constructor 37Property::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 51Property::~Property() 52{ 53} 54 55// Archive 56status_t 57Property::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 77bool 78Property::InterpolateTo(const Property* other, float scale) 79{ 80 // some properties don't support this 81 return false; 82} 83 84// SetEditable 85void 86Property::SetEditable(bool editable) 87{ 88 fEditable = editable; 89} 90 91// #pragma mark - 92 93// constructor 94IntProperty::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 104IntProperty::IntProperty(const IntProperty& other) 105 : Property(other), 106 fValue(other.fValue), 107 fMin(other.fMin), 108 fMax(other.fMax) 109{ 110} 111 112// constructor 113IntProperty::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 131IntProperty::~IntProperty() 132{ 133} 134 135// Archive 136status_t 137IntProperty::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 156BArchivable* 157IntProperty::Instantiate(BMessage* archive) 158{ 159 if (validate_instantiation(archive, "IntProperty")) 160 return new IntProperty(archive); 161 162 return NULL; 163} 164 165// Clone 166Property* 167IntProperty::Clone() const 168{ 169 return new IntProperty(*this); 170} 171 172// SetValue 173bool 174IntProperty::SetValue(const char* value) 175{ 176 return SetValue(atoi(value)); 177} 178 179// SetValue 180bool 181IntProperty::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 191void 192IntProperty::GetValue(BString& string) 193{ 194 string << fValue; 195} 196 197// InterpolateTo 198bool 199IntProperty::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 210bool 211IntProperty::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 229FloatProperty::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 239FloatProperty::FloatProperty(const FloatProperty& other) 240 : Property(other), 241 fValue(other.fValue), 242 fMin(other.fMin), 243 fMax(other.fMax) 244{ 245} 246 247// constructor 248FloatProperty::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 266FloatProperty::~FloatProperty() 267{ 268} 269 270// Archive 271status_t 272FloatProperty::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 291BArchivable* 292FloatProperty::Instantiate(BMessage* archive) 293{ 294 if (validate_instantiation(archive, "FloatProperty")) 295 return new FloatProperty(archive); 296 297 return NULL; 298} 299 300// Clone 301Property* 302FloatProperty::Clone() const 303{ 304 return new FloatProperty(*this); 305} 306 307// SetValue 308bool 309FloatProperty::SetValue(const char* value) 310{ 311 return SetValue(atof(value)); 312} 313 314// SetValue 315bool 316FloatProperty::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 326void 327FloatProperty::GetValue(BString& string) 328{ 329 append_float(string, fValue, 4); 330} 331 332// InterpolateTo 333bool 334FloatProperty::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 344bool 345FloatProperty::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 363UInt8Property::UInt8Property(uint32 identifier, uint8 value) 364 : Property(identifier), 365 fValue(value) 366{ 367} 368 369// constructor 370UInt8Property::UInt8Property(const UInt8Property& other) 371 : Property(other), 372 fValue(other.fValue) 373{ 374} 375 376// constructor 377UInt8Property::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 389UInt8Property::~UInt8Property() 390{ 391} 392 393// Archive 394status_t 395UInt8Property::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 410BArchivable* 411UInt8Property::Instantiate(BMessage* archive) 412{ 413 if (validate_instantiation(archive, "UInt8Property")) 414 return new UInt8Property(archive); 415 416 return NULL; 417} 418 419// Clone 420Property* 421UInt8Property::Clone() const 422{ 423 return new UInt8Property(*this); 424} 425 426// SetValue 427bool 428UInt8Property::SetValue(const char* value) 429{ 430 return SetValue((uint8)max_c(0, min_c(255, atoi(value)))); 431} 432 433// SetValue 434bool 435UInt8Property::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 445void 446UInt8Property::GetValue(BString& string) 447{ 448 string << fValue; 449} 450 451// InterpolateTo 452bool 453UInt8Property::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 464bool 465UInt8Property::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 477BoolProperty::BoolProperty(uint32 identifier, bool value) 478 : Property(identifier), 479 fValue(value) 480{ 481} 482 483// constructor 484BoolProperty::BoolProperty(const BoolProperty& other) 485 : Property(other), 486 fValue(other.fValue) 487{ 488} 489 490// constructor 491BoolProperty::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 503BoolProperty::~BoolProperty() 504{ 505} 506 507// Archive 508status_t 509BoolProperty::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 524BArchivable* 525BoolProperty::Instantiate(BMessage* archive) 526{ 527 if (validate_instantiation(archive, "BoolProperty")) 528 return new BoolProperty(archive); 529 530 return NULL; 531} 532 533// Clone 534Property* 535BoolProperty::Clone() const 536{ 537 return new BoolProperty(*this); 538} 539 540// SetValue 541bool 542BoolProperty::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 556bool 557BoolProperty::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 567void 568BoolProperty::GetValue(BString& string) 569{ 570 if (fValue) 571 string << "on"; 572 else 573 string << "off"; 574} 575 576// InterpolateTo 577bool 578BoolProperty::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 589bool 590BoolProperty::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 602StringProperty::StringProperty(uint32 identifier, const char* value) 603 : Property(identifier), 604 fValue(value) 605{ 606} 607 608// constructor 609StringProperty::StringProperty(const StringProperty& other) 610 : Property(other), 611 fValue(other.fValue) 612{ 613} 614 615// constructor 616StringProperty::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 628StringProperty::~StringProperty() 629{ 630} 631 632// Archive 633status_t 634StringProperty::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 649BArchivable* 650StringProperty::Instantiate(BMessage* archive) 651{ 652 if (validate_instantiation(archive, "StringProperty")) 653 return new StringProperty(archive); 654 655 return NULL; 656} 657 658// Clone 659Property* 660StringProperty::Clone() const 661{ 662 return new StringProperty(*this); 663} 664 665// SetValue 666bool 667StringProperty::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 678bool 679StringProperty::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 689void 690StringProperty::GetValue(BString& string) 691{ 692 string << fValue; 693} 694 695