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 18 using std::nothrow; 19 20 // constructor 21 OptionProperty::OptionProperty(uint32 identifier) 22 : Property(identifier), 23 fOptions(4), 24 fCurrentOptionID(-1) 25 { 26 } 27 28 // copy constructor 29 OptionProperty::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 49 OptionProperty::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 62 OptionProperty::~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 72 status_t 73 OptionProperty::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 88 BArchivable* 89 OptionProperty::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 99 Property* 100 OptionProperty::Clone() const 101 { 102 return new (nothrow) OptionProperty(*this); 103 } 104 105 // Type 106 type_code 107 OptionProperty::Type() const 108 { 109 // NOTE: not a Be defined type (those are upper case) 110 return 'optn'; 111 } 112 113 // SetValue 114 bool 115 OptionProperty::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 141 bool 142 OptionProperty::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 152 void 153 OptionProperty::GetValue(BString& string) 154 { 155 if (!GetCurrentOption(&string)) 156 string << fCurrentOptionID; 157 } 158 159 // MakeAnimatable 160 bool 161 OptionProperty::MakeAnimatable(bool animatable) 162 { 163 return false; 164 } 165 166 // #pragma mark - 167 168 // AddOption 169 void 170 OptionProperty::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 183 int32 184 OptionProperty::CurrentOptionID() const 185 { 186 return fCurrentOptionID; 187 } 188 189 // SetCurrentOptionID 190 bool 191 OptionProperty::SetCurrentOptionID(int32 id) 192 { 193 if (fCurrentOptionID != id) { 194 fCurrentOptionID = id; 195 return true; 196 } 197 return false; 198 } 199 200 // GetOption 201 bool 202 OptionProperty::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 216 bool 217 OptionProperty::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 } 225 uint32 current = B_HOST_TO_BENDIAN_INT32(fCurrentOptionID); 226 printf("OptionProperty::GetCurrentOption() - " 227 "did not find option %.4s!!\n", (char*)¤t); 228 return false; 229 } 230 231 // SetOptionAtOffset 232 bool 233 OptionProperty::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