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