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 "OptionProperty.h" 10 11#include <new> 12#include <stdio.h> 13#include <stdlib.h> 14 15#include <ByteOrder.h> 16#include <Message.h> 17 18using std::nothrow; 19 20// constructor 21OptionProperty::OptionProperty(uint32 identifier) 22 : Property(identifier), 23 fOptions(4), 24 fCurrentOptionID(-1) 25{ 26} 27 28// copy constructor 29OptionProperty::OptionProperty(const OptionProperty& other) 30 : Property(other), 31 fOptions(4), 32 fCurrentOptionID(other.fCurrentOptionID) 33{ 34 // clone the actual options 35 int32 count = other.fOptions.CountItems(); 36 for (int32 i = 0; i < count; i++) { 37 option* o = (option*)(other.fOptions.ItemAtFast(i)); 38 option* clone = new (nothrow) option; 39 if (!clone || !fOptions.AddItem(clone)) { 40 delete clone; 41 break; 42 } 43 clone->id = o->id; 44 clone->name = o->name; 45 } 46} 47 48// archive constructor 49OptionProperty::OptionProperty(BMessage* archive) 50 : Property(archive), 51 fOptions(4), 52 fCurrentOptionID(-1) 53{ 54 if (!archive) 55 return; 56 57 if (archive->FindInt32("option", &fCurrentOptionID) < B_OK) 58 fCurrentOptionID = -1; 59} 60 61// destrucor 62OptionProperty::~OptionProperty() 63{ 64 int32 count = fOptions.CountItems(); 65 for (int32 i = 0; i < count; i++) 66 delete (option*)fOptions.ItemAtFast(i); 67} 68 69// #pragma mark - 70 71// Archive 72status_t 73OptionProperty::Archive(BMessage* into, bool deep) const 74{ 75 status_t status = Property::Archive(into, deep); 76 77 if (status >= B_OK) 78 status = into->AddInt32("option", fCurrentOptionID); 79 80 // finish off 81 if (status >= B_OK) 82 status = into->AddString("class", "OptionProperty"); 83 84 return status; 85} 86 87// Instantiate 88BArchivable* 89OptionProperty::Instantiate(BMessage* archive) 90{ 91 if (validate_instantiation(archive, "OptionProperty")) 92 return new (nothrow) OptionProperty(archive); 93 return NULL; 94} 95 96// #pragma mark - 97 98// Clone 99Property* 100OptionProperty::Clone() const 101{ 102 return new (nothrow) OptionProperty(*this); 103} 104 105// Type 106type_code 107OptionProperty::Type() const 108{ 109 // NOTE: not a Be defined type (those are upper case) 110 return 'optn'; 111} 112 113// SetValue 114bool 115OptionProperty::SetValue(const char* value) 116{ 117 // try to find option by name 118 int32 count = fOptions.CountItems(); 119 for (int32 i = 0; i < count; i++) { 120 option* o = (option*)fOptions.ItemAtFast(i); 121 if (strcmp(o->name.String(), value) == 0) { 122 return SetCurrentOptionID(o->id); 123 } 124 } 125 126 // try to find option by id 127 int32 id = atoi(value); 128 if (id < 0) 129 return false; 130 131 for (int32 i = 0; i < count; i++) { 132 option* o = (option*)fOptions.ItemAtFast(i); 133 if (o->id == id) { 134 return SetCurrentOptionID(o->id); 135 } 136 } 137 return false; 138} 139 140// SetValue 141bool 142OptionProperty::SetValue(const Property* other) 143{ 144 const OptionProperty* optOther = dynamic_cast<const OptionProperty*>(other); 145 if (optOther) { 146 return SetCurrentOptionID(optOther->CurrentOptionID()); 147 } 148 return false; 149} 150 151// GetValue 152void 153OptionProperty::GetValue(BString& string) 154{ 155 if (!GetCurrentOption(&string)) 156 string << fCurrentOptionID; 157} 158 159// MakeAnimatable 160bool 161OptionProperty::MakeAnimatable(bool animatable) 162{ 163 return false; 164} 165 166// #pragma mark - 167 168// AddOption 169void 170OptionProperty::AddOption(int32 id, const char* name) 171{ 172 if (!name) 173 return; 174 175 if (option* o = new (nothrow) option) { 176 o->id = id; 177 o->name = name; 178 fOptions.AddItem((void*)o); 179 } 180} 181 182// CurrentOptionID 183int32 184OptionProperty::CurrentOptionID() const 185{ 186 return fCurrentOptionID; 187} 188 189// SetCurrentOptionID 190bool 191OptionProperty::SetCurrentOptionID(int32 id) 192{ 193 if (fCurrentOptionID != id) { 194 fCurrentOptionID = id; 195 return true; 196 } 197 return false; 198} 199 200// GetOption 201bool 202OptionProperty::GetOption(int32 index, BString* string, int32* id) const 203{ 204 if (option* o = (option*)fOptions.ItemAt(index)) { 205 *id = o->id; 206 *string = o->name; 207 return true; 208 } else { 209 *id = -1; 210 *string = ""; 211 return false; 212 } 213} 214 215// GetCurrentOption 216bool 217OptionProperty::GetCurrentOption(BString* string) const 218{ 219 for (int32 i = 0; option* o = (option*)fOptions.ItemAt(i); i++) { 220 if (o->id == fCurrentOptionID) { 221 *string = o->name; 222 return true; 223 } 224 } 225uint32 current = B_HOST_TO_BENDIAN_INT32(fCurrentOptionID); 226printf("OptionProperty::GetCurrentOption() - " 227 "did not find option %.4s!!\n", (char*)¤t); 228 return false; 229} 230 231// SetOptionAtOffset 232bool 233OptionProperty::SetOptionAtOffset(int32 indexOffset) 234{ 235 // NOTE: used by the Property editor GUI 236 if (fOptions.CountItems() > 1) { 237 int32 index = -1; 238 for (int32 i = 0; option* o = (option*)fOptions.ItemAt(i); i++) { 239 if (o->id == fCurrentOptionID) { 240 index = i; 241 } 242 } 243 if (index >= 0) { 244 // offset index 245 index += indexOffset; 246 // keep index in range by wrapping arround 247 if (index >= fOptions.CountItems()) 248 index = 0; 249 if (index < 0) 250 index = fOptions.CountItems() - 1; 251 if (option* o = (option*)fOptions.ItemAt(index)) { 252 SetCurrentOptionID(o->id); 253 return true; 254 } 255 } 256 } 257 return false; 258} 259 260 261 262