11541Srgrimes/*
21541Srgrimes * Copyright 2008-2010, Stephan A��mus <superstippi@gmx.de>.
31541Srgrimes * Copyright 1998, Eric Shepherd.
41541Srgrimes * All rights reserved. Distributed under the terms of the Be Sample Code
51541Srgrimes * license.
61541Srgrimes */
71541Srgrimes
81541Srgrimes//! Be Newsletter Volume II, Issue 35; September 2, 1998 (Eric Shepherd)
91541Srgrimes
101541Srgrimes#include "SettingsMessage.h"
111541Srgrimes
121541Srgrimes#include <new>
131541Srgrimes
141541Srgrimes#include <Autolock.h>
151541Srgrimes#include <Entry.h>
161541Srgrimes#include <File.h>
171541Srgrimes#include <Messenger.h>
181541Srgrimes#include <String.h>
191541Srgrimes
201541Srgrimes
211541SrgrimesSettingsMessage::SettingsMessage(directory_which directory,
221541Srgrimes		const char* filename)
231541Srgrimes	:
241541Srgrimes	BMessage('pref'),
251541Srgrimes	fListeners(0)
261541Srgrimes{
271541Srgrimes	fStatus = find_directory(directory, &fPath);
281541Srgrimes
291541Srgrimes	if (fStatus == B_OK)
301541Srgrimes		fStatus = fPath.Append(filename);
311541Srgrimes
321541Srgrimes	if (fStatus == B_OK)
331541Srgrimes		fStatus = Load();
341541Srgrimes}
351541Srgrimes
361541Srgrimes
371541SrgrimesSettingsMessage::~SettingsMessage()
3850477Speter{
391541Srgrimes	Save();
401541Srgrimes
411541Srgrimes	for (int32 i = fListeners.CountItems() - 1; i >= 0; i--)
421541Srgrimes		delete reinterpret_cast<BMessenger*>(fListeners.ItemAtFast(i));
431541Srgrimes}
441541Srgrimes
451541Srgrimes
461541Srgrimesstatus_t
471541SrgrimesSettingsMessage::InitCheck() const
481541Srgrimes{
491541Srgrimes	return fStatus;
501541Srgrimes}
511541Srgrimes
521541Srgrimes
531541Srgrimesstatus_t
541541SrgrimesSettingsMessage::Load()
551541Srgrimes{
561541Srgrimes	BAutolock _(this);
5715311Sbde
581541Srgrimes	BFile file(fPath.Path(), B_READ_ONLY);
591541Srgrimes	status_t status = file.InitCheck();
601541Srgrimes
611541Srgrimes	if (status == B_OK)
621541Srgrimes		status = Unflatten(&file);
631541Srgrimes
641541Srgrimes	return status;
651541Srgrimes}
661541Srgrimes
671541Srgrimes
681541Srgrimesstatus_t
691541SrgrimesSettingsMessage::Save() const
701541Srgrimes{
711541Srgrimes	BAutolock _(const_cast<SettingsMessage*>(this));
721541Srgrimes
731541Srgrimes	BFile file(fPath.Path(), B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE);
741541Srgrimes	status_t status = file.InitCheck();
751541Srgrimes
761541Srgrimes	if (status == B_OK)
771541Srgrimes		status = Flatten(&file);
781541Srgrimes
791541Srgrimes	return status;
801541Srgrimes}
811541Srgrimes
821541Srgrimes
831541Srgrimesbool
841541SrgrimesSettingsMessage::AddListener(const BMessenger& listener)
851541Srgrimes{
861541Srgrimes	BAutolock _(this);
871541Srgrimes
881541Srgrimes	BMessenger* listenerCopy = new(std::nothrow) BMessenger(listener);
891541Srgrimes	if (listenerCopy && fListeners.AddItem(listenerCopy))
901541Srgrimes		return true;
911541Srgrimes	delete listenerCopy;
921541Srgrimes	return false;
931541Srgrimes}
941541Srgrimes
951541Srgrimes
961541Srgrimesvoid
971541SrgrimesSettingsMessage::RemoveListener(const BMessenger& listener)
981541Srgrimes{
991541Srgrimes	BAutolock _(this);
10013030Sbde
10113030Sbde	for (int32 i = fListeners.CountItems() - 1; i >= 0; i--) {
10213030Sbde		BMessenger* listenerItem = reinterpret_cast<BMessenger*>(
10313030Sbde			fListeners.ItemAtFast(i));
10413030Sbde		if (*listenerItem == listener) {
10569727Sphk			fListeners.RemoveItem(i);
1061541Srgrimes			delete listenerItem;
1071541Srgrimes			return;
1081541Srgrimes		}
1091541Srgrimes	}
1101541Srgrimes}
1111541Srgrimes
1121541Srgrimes
1131541Srgrimes// #pragma mark -
1141541Srgrimes
1151541Srgrimes
1161541Srgrimesstatus_t
1171541SrgrimesSettingsMessage::SetValue(const char* name, bool value)
118{
119	status_t ret = ReplaceBool(name, value);
120	if (ret != B_OK)
121		ret = AddBool(name, value);
122	if (ret == B_OK)
123		_NotifyValueChanged(name);
124	return ret;
125}
126
127
128status_t
129SettingsMessage::SetValue(const char* name, int8 value)
130{
131	status_t ret = ReplaceInt8(name, value);
132	if (ret != B_OK)
133		ret = AddInt8(name, value);
134	if (ret == B_OK)
135		_NotifyValueChanged(name);
136	return ret;
137}
138
139
140status_t
141SettingsMessage::SetValue(const char* name, int16 value)
142{
143	status_t ret = ReplaceInt16(name, value);
144	if (ret != B_OK)
145		ret = AddInt16(name, value);
146	if (ret == B_OK)
147		_NotifyValueChanged(name);
148	return ret;
149}
150
151
152status_t
153SettingsMessage::SetValue(const char* name, uint16 value)
154{
155	status_t ret = ReplaceUInt16(name, value);
156	if (ret != B_OK)
157		ret = AddUInt16(name, value);
158	if (ret == B_OK)
159		_NotifyValueChanged(name);
160	return ret;
161}
162
163
164status_t
165SettingsMessage::SetValue(const char* name, int32 value)
166{
167	status_t ret = ReplaceInt32(name, value);
168	if (ret != B_OK)
169		ret = AddInt32(name, value);
170	if (ret == B_OK)
171		_NotifyValueChanged(name);
172	return ret;
173}
174
175
176status_t
177SettingsMessage::SetValue(const char* name, uint32 value)
178{
179	status_t ret = ReplaceUInt32(name, value);
180	if (ret != B_OK)
181		ret = AddUInt32(name, value);
182	if (ret == B_BAD_TYPE && HasData(name, B_INT32_TYPE)) {
183		// For compatibility with older versions of this class, replace an int32
184		RemoveData(name);
185		ret = AddUInt32(name, value);
186	}
187	if (ret == B_OK)
188		_NotifyValueChanged(name);
189	return ret;
190}
191
192
193status_t
194SettingsMessage::SetValue(const char* name, int64 value)
195{
196	status_t ret = ReplaceInt64(name, value);
197	if (ret != B_OK)
198		ret = AddInt64(name, value);
199	if (ret == B_OK)
200		_NotifyValueChanged(name);
201	return ret;
202}
203
204
205status_t
206SettingsMessage::SetValue(const char* name, uint64 value)
207{
208	status_t ret = ReplaceUInt64(name, value);
209	if (ret != B_OK)
210		ret = AddUInt64(name, value);
211	if (ret == B_OK)
212		_NotifyValueChanged(name);
213	return ret;
214}
215
216
217status_t
218SettingsMessage::SetValue(const char* name, float value)
219{
220	status_t ret = ReplaceFloat(name, value);
221	if (ret != B_OK)
222		ret = AddFloat(name, value);
223	if (ret == B_OK)
224		_NotifyValueChanged(name);
225	return ret;
226}
227
228
229status_t
230SettingsMessage::SetValue(const char* name, double value)
231{
232	status_t ret = ReplaceDouble(name, value);
233	if (ret != B_OK)
234		ret = AddDouble(name, value);
235	if (ret == B_OK)
236		_NotifyValueChanged(name);
237	return ret;
238}
239
240
241status_t
242SettingsMessage::SetValue(const char* name, const char* value)
243{
244	status_t ret = ReplaceString(name, value);
245	if (ret != B_OK)
246		ret = AddString(name, value);
247	if (ret == B_OK)
248		_NotifyValueChanged(name);
249	return ret;
250}
251
252
253status_t
254SettingsMessage::SetValue(const char* name, const BString& value)
255{
256	status_t ret = ReplaceString(name, value);
257	if (ret != B_OK)
258		ret = AddString(name, value);
259	if (ret == B_OK)
260		_NotifyValueChanged(name);
261	return ret;
262}
263
264
265status_t
266SettingsMessage::SetValue(const char* name, const BPoint& value)
267{
268	status_t ret = ReplacePoint(name, value);
269	if (ret != B_OK)
270		ret = AddPoint(name, value);
271	if (ret == B_OK)
272		_NotifyValueChanged(name);
273	return ret;
274}
275
276
277status_t
278SettingsMessage::SetValue(const char* name, const BRect& value)
279{
280	status_t ret = ReplaceRect(name, value);
281	if (ret != B_OK)
282		ret = AddRect(name, value);
283	if (ret == B_OK)
284		_NotifyValueChanged(name);
285	return ret;
286}
287
288
289status_t
290SettingsMessage::SetValue(const char* name, const entry_ref& value)
291{
292	status_t ret = ReplaceRef(name, &value);
293	if (ret != B_OK)
294		ret = AddRef(name, &value);
295	if (ret == B_OK)
296		_NotifyValueChanged(name);
297	return ret;
298}
299
300
301status_t
302SettingsMessage::SetValue(const char* name, const BMessage& value)
303{
304	status_t ret = ReplaceMessage(name, &value);
305	if (ret != B_OK)
306		ret = AddMessage(name, &value);
307	if (ret == B_OK)
308		_NotifyValueChanged(name);
309	return ret;
310}
311
312
313status_t
314SettingsMessage::SetValue(const char* name, const BFlattenable* value)
315{
316	status_t ret = ReplaceFlat(name, const_cast<BFlattenable*>(value));
317	if (ret != B_OK)
318		ret = AddFlat(name, const_cast<BFlattenable*>(value));
319	if (ret == B_OK)
320		_NotifyValueChanged(name);
321	return ret;
322}
323
324
325status_t
326SettingsMessage::SetValue(const char* name, type_code type, const void* data,
327	ssize_t numBytes)
328{
329	status_t ret = ReplaceData(name, type, data, numBytes);
330	if (ret != B_OK)
331		ret = AddData(name, type, data, numBytes);
332	if (ret == B_OK)
333		_NotifyValueChanged(name);
334	return ret;
335}
336
337
338status_t
339SettingsMessage::SetValue(const char* name, const BFont& value)
340{
341	font_family family;
342	font_style style;
343	value.GetFamilyAndStyle(&family, &style);
344
345	BMessage fontMessage;
346	status_t ret = fontMessage.AddString("family", family);
347	if (ret == B_OK)
348		ret = fontMessage.AddString("style", style);
349	if (ret == B_OK)
350		ret = fontMessage.AddFloat("size", value.Size());
351
352	if (ret == B_OK) {
353		if (ReplaceMessage(name, &fontMessage) != B_OK)
354			ret = AddMessage(name, &fontMessage);
355	}
356	if (ret == B_OK)
357		_NotifyValueChanged(name);
358	return ret;
359}
360
361
362// #pragma mark -
363
364
365bool
366SettingsMessage::GetValue(const char* name, bool defaultValue) const
367{
368	bool value;
369	if (FindBool(name, &value) != B_OK)
370		return defaultValue;
371	return value;
372}
373
374
375int8
376SettingsMessage::GetValue(const char* name, int8 defaultValue) const
377{
378	int8 value;
379	if (FindInt8(name, &value) != B_OK)
380		return defaultValue;
381	return value;
382}
383
384
385int16
386SettingsMessage::GetValue(const char* name, int16 defaultValue) const
387{
388	int16 value;
389	if (FindInt16(name, &value) != B_OK)
390		return defaultValue;
391	return value;
392}
393
394
395uint16
396SettingsMessage::GetValue(const char* name, uint16 defaultValue) const
397{
398	uint16 value;
399	if (FindUInt16(name, &value) != B_OK)
400		return defaultValue;
401	return value;
402}
403
404
405int32
406SettingsMessage::GetValue(const char* name, int32 defaultValue) const
407{
408	int32 value;
409	if (FindInt32(name, &value) != B_OK)
410		return defaultValue;
411	return value;
412}
413
414
415uint32
416SettingsMessage::GetValue(const char* name, uint32 defaultValue) const
417{
418	uint32 value;
419	if (FindUInt32(name, &value) == B_OK)
420		return value;
421	// For compatibility with older versions of this class, also accept an int32
422	int32 signedValue;
423	if (FindInt32(name, &signedValue) == B_OK && signedValue >= 0)
424		return signedValue;
425	return defaultValue;
426}
427
428
429int64
430SettingsMessage::GetValue(const char* name, int64 defaultValue) const
431{
432	int64 value;
433	if (FindInt64(name, &value) != B_OK)
434		return defaultValue;
435	return value;
436}
437
438
439uint64
440SettingsMessage::GetValue(const char* name, uint64 defaultValue) const
441{
442	uint64 value;
443	if (FindUInt64(name, &value) != B_OK)
444		return defaultValue;
445	return value;
446}
447
448
449float
450SettingsMessage::GetValue(const char* name, float defaultValue) const
451{
452	float value;
453	if (FindFloat(name, &value) != B_OK)
454		return defaultValue;
455	return value;
456}
457
458
459double
460SettingsMessage::GetValue(const char* name, double defaultValue) const
461{
462	double value;
463	if (FindDouble(name, &value) != B_OK)
464		return defaultValue;
465	return value;
466}
467
468
469BString
470SettingsMessage::GetValue(const char* name, const BString& defaultValue) const
471{
472	BString value;
473	if (FindString(name, &value) != B_OK)
474		return defaultValue;
475	return value;
476}
477
478
479const char*
480SettingsMessage::GetValue(const char* name, const char* defaultValue) const
481{
482	const char* value;
483	if (FindString(name, &value) != B_OK)
484		return defaultValue;
485	return value;
486}
487
488
489BPoint
490SettingsMessage::GetValue(const char *name, BPoint defaultValue) const
491{
492	BPoint value;
493	if (FindPoint(name, &value) != B_OK)
494		return defaultValue;
495	return value;
496}
497
498
499BRect
500SettingsMessage::GetValue(const char* name, BRect defaultValue) const
501{
502	BRect value;
503	if (FindRect(name, &value) != B_OK)
504		return defaultValue;
505	return value;
506}
507
508
509entry_ref
510SettingsMessage::GetValue(const char* name, const entry_ref& defaultValue) const
511{
512	entry_ref value;
513	if (FindRef(name, &value) != B_OK)
514		return defaultValue;
515	return value;
516}
517
518
519BMessage
520SettingsMessage::GetValue(const char* name, const BMessage& defaultValue) const
521{
522	BMessage value;
523	if (FindMessage(name, &value) != B_OK)
524		return defaultValue;
525	return value;
526}
527
528
529BFont
530SettingsMessage::GetValue(const char* name, const BFont& defaultValue) const
531{
532	BMessage fontMessage;
533	if (FindMessage(name, &fontMessage) != B_OK)
534		return defaultValue;
535
536	const char* family;
537	const char* style;
538	float size;
539	if (fontMessage.FindString("family", &family) != B_OK
540		|| fontMessage.FindString("style", &style) != B_OK
541		|| fontMessage.FindFloat("size", &size) != B_OK) {
542		return defaultValue;
543	}
544
545	BFont value;
546	if (value.SetFamilyAndStyle(family, style) != B_OK)
547		return defaultValue;
548
549	value.SetSize(size);
550
551	return value;
552}
553
554
555void*
556SettingsMessage::GetValue(const char* name, type_code type, ssize_t numBytes,
557		const void** defaultValue) const
558{
559	void* value;
560	if (FindData(name, type, (const void**)&value, &numBytes) != B_OK)
561		return defaultValue;
562	return value;
563}
564
565
566// #pragma mark - private
567
568void
569SettingsMessage::_NotifyValueChanged(const char* name) const
570{
571	BMessage message(SETTINGS_VALUE_CHANGED);
572	message.AddString("name", name);
573
574	// Add the value of that name to the notification.
575	type_code type;
576	if (GetInfo(name, &type) == B_OK) {
577		const void* data;
578		ssize_t numBytes;
579		if (FindData(name, type, &data, &numBytes) == B_OK)
580			message.AddData("value", type, data, numBytes);
581	}
582
583	int32 count = fListeners.CountItems();
584	for (int32 i = 0; i < count; i++) {
585		BMessenger* listener = reinterpret_cast<BMessenger*>(
586			fListeners.ItemAtFast(i));
587		listener->SendMessage(&message);
588	}
589}
590