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