xref: /haiku/src/apps/icon-o-matic/generic/property/specific_properties/OptionProperty.cpp (revision 9ecf9d1c1d4888d341a6eac72112c72d1ae3a4cb)
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*)&current);
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