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
OptionProperty(uint32 identifier)21 OptionProperty::OptionProperty(uint32 identifier)
22 : Property(identifier),
23 fOptions(4),
24 fCurrentOptionID(-1)
25 {
26 }
27
28 // copy constructor
OptionProperty(const OptionProperty & other)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
OptionProperty(BMessage * archive)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
~OptionProperty()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
Archive(BMessage * into,bool deep) const73 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*
Instantiate(BMessage * archive)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*
Clone() const100 OptionProperty::Clone() const
101 {
102 return new (nothrow) OptionProperty(*this);
103 }
104
105 // Type
106 type_code
Type() const107 OptionProperty::Type() const
108 {
109 // NOTE: not a Be defined type (those are upper case)
110 return 'optn';
111 }
112
113 // SetValue
114 bool
SetValue(const char * value)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
SetValue(const Property * other)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
GetValue(BString & string)153 OptionProperty::GetValue(BString& string)
154 {
155 if (!GetCurrentOption(&string))
156 string << fCurrentOptionID;
157 }
158
159 // MakeAnimatable
160 bool
MakeAnimatable(bool animatable)161 OptionProperty::MakeAnimatable(bool animatable)
162 {
163 return false;
164 }
165
166 // #pragma mark -
167
168 // AddOption
169 void
AddOption(int32 id,const char * name)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
CurrentOptionID() const184 OptionProperty::CurrentOptionID() const
185 {
186 return fCurrentOptionID;
187 }
188
189 // SetCurrentOptionID
190 bool
SetCurrentOptionID(int32 id)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
GetOption(int32 index,BString * string,int32 * id) const202 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
GetCurrentOption(BString * string) const217 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
SetOptionAtOffset(int32 indexOffset)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