* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#include "OptionProperty.h"
#include <new>
#include <stdio.h>
#include <stdlib.h>
#include <ByteOrder.h>
#include <Message.h>
using std::nothrow;
OptionProperty::OptionProperty(uint32 identifier)
: Property(identifier),
fOptions(4),
fCurrentOptionID(-1)
{
}
OptionProperty::OptionProperty(const OptionProperty& other)
: Property(other),
fOptions(4),
fCurrentOptionID(other.fCurrentOptionID)
{
int32 count = other.fOptions.CountItems();
for (int32 i = 0; i < count; i++) {
option* o = (option*)(other.fOptions.ItemAtFast(i));
option* clone = new (nothrow) option;
if (!clone || !fOptions.AddItem(clone)) {
delete clone;
break;
}
clone->id = o->id;
clone->name = o->name;
}
}
OptionProperty::OptionProperty(BMessage* archive)
: Property(archive),
fOptions(4),
fCurrentOptionID(-1)
{
if (!archive)
return;
if (archive->FindInt32("option", &fCurrentOptionID) < B_OK)
fCurrentOptionID = -1;
}
OptionProperty::~OptionProperty()
{
int32 count = fOptions.CountItems();
for (int32 i = 0; i < count; i++)
delete (option*)fOptions.ItemAtFast(i);
}
status_t
OptionProperty::Archive(BMessage* into, bool deep) const
{
status_t status = Property::Archive(into, deep);
if (status >= B_OK)
status = into->AddInt32("option", fCurrentOptionID);
if (status >= B_OK)
status = into->AddString("class", "OptionProperty");
return status;
}
BArchivable*
OptionProperty::Instantiate(BMessage* archive)
{
if (validate_instantiation(archive, "OptionProperty"))
return new (nothrow) OptionProperty(archive);
return NULL;
}
Property*
OptionProperty::Clone() const
{
return new (nothrow) OptionProperty(*this);
}
type_code
OptionProperty::Type() const
{
return 'optn';
}
bool
OptionProperty::SetValue(const char* value)
{
int32 count = fOptions.CountItems();
for (int32 i = 0; i < count; i++) {
option* o = (option*)fOptions.ItemAtFast(i);
if (strcmp(o->name.String(), value) == 0) {
return SetCurrentOptionID(o->id);
}
}
int32 id = atoi(value);
if (id < 0)
return false;
for (int32 i = 0; i < count; i++) {
option* o = (option*)fOptions.ItemAtFast(i);
if (o->id == id) {
return SetCurrentOptionID(o->id);
}
}
return false;
}
bool
OptionProperty::SetValue(const Property* other)
{
const OptionProperty* optOther = dynamic_cast<const OptionProperty*>(other);
if (optOther) {
return SetCurrentOptionID(optOther->CurrentOptionID());
}
return false;
}
void
OptionProperty::GetValue(BString& string)
{
if (!GetCurrentOption(&string))
string << fCurrentOptionID;
}
bool
OptionProperty::MakeAnimatable(bool animatable)
{
return false;
}
void
OptionProperty::AddOption(int32 id, const char* name)
{
if (!name)
return;
if (option* o = new (nothrow) option) {
o->id = id;
o->name = name;
fOptions.AddItem((void*)o);
}
}
int32
OptionProperty::CurrentOptionID() const
{
return fCurrentOptionID;
}
bool
OptionProperty::SetCurrentOptionID(int32 id)
{
if (fCurrentOptionID != id) {
fCurrentOptionID = id;
return true;
}
return false;
}
bool
OptionProperty::GetOption(int32 index, BString* string, int32* id) const
{
if (option* o = (option*)fOptions.ItemAt(index)) {
*id = o->id;
*string = o->name;
return true;
} else {
*id = -1;
*string = "";
return false;
}
}
bool
OptionProperty::GetCurrentOption(BString* string) const
{
for (int32 i = 0; option* o = (option*)fOptions.ItemAt(i); i++) {
if (o->id == fCurrentOptionID) {
*string = o->name;
return true;
}
}
uint32 current = B_HOST_TO_BENDIAN_INT32(fCurrentOptionID);
printf("OptionProperty::GetCurrentOption() - "
"did not find option %.4s!!\n", (char*)¤t);
return false;
}
bool
OptionProperty::SetOptionAtOffset(int32 indexOffset)
{
if (fOptions.CountItems() > 1) {
int32 index = -1;
for (int32 i = 0; option* o = (option*)fOptions.ItemAt(i); i++) {
if (o->id == fCurrentOptionID) {
index = i;
}
}
if (index >= 0) {
index += indexOffset;
if (index >= fOptions.CountItems())
index = 0;
if (index < 0)
index = fOptions.CountItems() - 1;
if (option* o = (option*)fOptions.ItemAt(index)) {
SetCurrentOptionID(o->id);
return true;
}
}
}
return false;
}