1/* 2 * Copyright 2008-2010, Stephan A��mus <superstippi@gmx.de>. 3 * Copyright 1998, Eric Shepherd. 4 * All rights reserved. Distributed under the terms of the Be Sample Code 5 * license. 6 */ 7 8//! Be Newsletter Volume II, Issue 35; September 2, 1998 (Eric Shepherd) 9 10#include "SettingsMessage.h" 11 12#include <new> 13 14#include <Autolock.h> 15#include <Entry.h> 16#include <File.h> 17#include <Messenger.h> 18#include <String.h> 19 20 21SettingsMessage::SettingsMessage(directory_which directory, 22 const char* filename) 23 : 24 BMessage('pref'), 25 fListeners(4) 26{ 27 fStatus = find_directory(directory, &fPath); 28 29 if (fStatus == B_OK) 30 fStatus = fPath.Append(filename); 31 32 if (fStatus == B_OK) 33 fStatus = Load(); 34} 35 36 37SettingsMessage::~SettingsMessage() 38{ 39 Save(); 40 41 for (int32 i = fListeners.CountItems() - 1; i >= 0; i--) 42 delete reinterpret_cast<BMessenger*>(fListeners.ItemAtFast(i)); 43} 44 45 46status_t 47SettingsMessage::InitCheck() const 48{ 49 return fStatus; 50} 51 52 53status_t 54SettingsMessage::Load() 55{ 56 BAutolock _(this); 57 58 BFile file(fPath.Path(), B_READ_ONLY); 59 status_t status = file.InitCheck(); 60 61 if (status == B_OK) 62 status = Unflatten(&file); 63 64 return status; 65} 66 67 68status_t 69SettingsMessage::Save() const 70{ 71 BAutolock _(const_cast<SettingsMessage*>(this)); 72 73 BFile file(fPath.Path(), B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE); 74 status_t status = file.InitCheck(); 75 76 if (status == B_OK) 77 status = Flatten(&file); 78 79 return status; 80} 81 82 83bool 84SettingsMessage::AddListener(const BMessenger& listener) 85{ 86 BAutolock _(this); 87 88 BMessenger* listenerCopy = new(std::nothrow) BMessenger(listener); 89 if (listenerCopy && fListeners.AddItem(listenerCopy)) 90 return true; 91 delete listenerCopy; 92 return false; 93} 94 95 96void 97SettingsMessage::RemoveListener(const BMessenger& listener) 98{ 99 BAutolock _(this); 100 101 for (int32 i = fListeners.CountItems() - 1; i >= 0; i--) { 102 BMessenger* listenerItem = reinterpret_cast<BMessenger*>( 103 fListeners.ItemAtFast(i)); 104 if (*listenerItem == listener) { 105 fListeners.RemoveItem(i); 106 delete listenerItem; 107 return; 108 } 109 } 110} 111 112 113// #pragma mark - 114 115 116status_t 117SettingsMessage::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, int32 value) 154{ 155 status_t ret = ReplaceInt32(name, value); 156 if (ret != B_OK) 157 ret = AddInt32(name, value); 158 if (ret == B_OK) 159 _NotifyValueChanged(name); 160 return ret; 161} 162 163 164status_t 165SettingsMessage::SetValue(const char* name, uint32 value) 166{ 167 status_t ret = ReplaceUInt32(name, value); 168 if (ret != B_OK) 169 ret = AddUInt32(name, value); 170 if (ret == B_OK) 171 _NotifyValueChanged(name); 172 return ret; 173} 174 175 176status_t 177SettingsMessage::SetValue(const char* name, int64 value) 178{ 179 status_t ret = ReplaceInt64(name, value); 180 if (ret != B_OK) 181 ret = AddInt64(name, value); 182 if (ret == B_OK) 183 _NotifyValueChanged(name); 184 return ret; 185} 186 187 188status_t 189SettingsMessage::SetValue(const char* name, float value) 190{ 191 status_t ret = ReplaceFloat(name, value); 192 if (ret != B_OK) 193 ret = AddFloat(name, value); 194 if (ret == B_OK) 195 _NotifyValueChanged(name); 196 return ret; 197} 198 199 200status_t 201SettingsMessage::SetValue(const char* name, double value) 202{ 203 status_t ret = ReplaceDouble(name, value); 204 if (ret != B_OK) 205 ret = AddDouble(name, value); 206 if (ret == B_OK) 207 _NotifyValueChanged(name); 208 return ret; 209} 210 211 212status_t 213SettingsMessage::SetValue(const char* name, const char* value) 214{ 215 status_t ret = ReplaceString(name, value); 216 if (ret != B_OK) 217 ret = AddString(name, value); 218 if (ret == B_OK) 219 _NotifyValueChanged(name); 220 return ret; 221} 222 223 224status_t 225SettingsMessage::SetValue(const char* name, const BString& value) 226{ 227 status_t ret = ReplaceString(name, value); 228 if (ret != B_OK) 229 ret = AddString(name, value); 230 if (ret == B_OK) 231 _NotifyValueChanged(name); 232 return ret; 233} 234 235 236status_t 237SettingsMessage::SetValue(const char* name, const BPoint& value) 238{ 239 status_t ret = ReplacePoint(name, value); 240 if (ret != B_OK) 241 ret = AddPoint(name, value); 242 if (ret == B_OK) 243 _NotifyValueChanged(name); 244 return ret; 245} 246 247 248status_t 249SettingsMessage::SetValue(const char* name, const BRect& value) 250{ 251 status_t ret = ReplaceRect(name, value); 252 if (ret != B_OK) 253 ret = AddRect(name, value); 254 if (ret == B_OK) 255 _NotifyValueChanged(name); 256 return ret; 257} 258 259 260status_t 261SettingsMessage::SetValue(const char* name, const entry_ref& value) 262{ 263 status_t ret = ReplaceRef(name, &value); 264 if (ret != B_OK) 265 ret = AddRef(name, &value); 266 if (ret == B_OK) 267 _NotifyValueChanged(name); 268 return ret; 269} 270 271 272status_t 273SettingsMessage::SetValue(const char* name, const BMessage& value) 274{ 275 status_t ret = ReplaceMessage(name, &value); 276 if (ret != B_OK) 277 ret = AddMessage(name, &value); 278 if (ret == B_OK) 279 _NotifyValueChanged(name); 280 return ret; 281} 282 283 284status_t 285SettingsMessage::SetValue(const char* name, const BFlattenable* value) 286{ 287 status_t ret = ReplaceFlat(name, const_cast<BFlattenable*>(value)); 288 if (ret != B_OK) 289 ret = AddFlat(name, const_cast<BFlattenable*>(value)); 290 if (ret == B_OK) 291 _NotifyValueChanged(name); 292 return ret; 293} 294 295 296status_t 297SettingsMessage::SetValue(const char* name, const BFont& value) 298{ 299 font_family family; 300 font_style style; 301 value.GetFamilyAndStyle(&family, &style); 302 303 BMessage fontMessage; 304 status_t ret = fontMessage.AddString("family", family); 305 if (ret == B_OK) 306 ret = fontMessage.AddString("style", style); 307 if (ret == B_OK) 308 ret = fontMessage.AddFloat("size", value.Size()); 309 310 if (ret == B_OK) { 311 if (ReplaceMessage(name, &fontMessage) != B_OK) 312 ret = AddMessage(name, &fontMessage); 313 } 314 if (ret == B_OK) 315 _NotifyValueChanged(name); 316 return ret; 317} 318 319 320// #pragma mark - 321 322 323bool 324SettingsMessage::GetValue(const char* name, bool defaultValue) const 325{ 326 bool value; 327 if (FindBool(name, &value) != B_OK) 328 return defaultValue; 329 return value; 330} 331 332 333int8 334SettingsMessage::GetValue(const char* name, int8 defaultValue) const 335{ 336 int8 value; 337 if (FindInt8(name, &value) != B_OK) 338 return defaultValue; 339 return value; 340} 341 342 343int16 344SettingsMessage::GetValue(const char* name, int16 defaultValue) const 345{ 346 int16 value; 347 if (FindInt16(name, &value) != B_OK) 348 return defaultValue; 349 return value; 350} 351 352 353int32 354SettingsMessage::GetValue(const char* name, int32 defaultValue) const 355{ 356 int32 value; 357 if (FindInt32(name, &value) != B_OK) 358 return defaultValue; 359 return value; 360} 361 362 363uint32 364SettingsMessage::GetValue(const char* name, uint32 defaultValue) const 365{ 366 uint32 value; 367 if (FindUInt32(name, &value) != B_OK) 368 return defaultValue; 369 return value; 370} 371 372 373int64 374SettingsMessage::GetValue(const char* name, int64 defaultValue) const 375{ 376 int64 value; 377 if (FindInt64(name, &value) != B_OK) 378 return defaultValue; 379 return value; 380} 381 382 383float 384SettingsMessage::GetValue(const char* name, float defaultValue) const 385{ 386 float value; 387 if (FindFloat(name, &value) != B_OK) 388 return defaultValue; 389 return value; 390} 391 392 393double 394SettingsMessage::GetValue(const char* name, double defaultValue) const 395{ 396 double value; 397 if (FindDouble(name, &value) != B_OK) 398 return defaultValue; 399 return value; 400} 401 402 403BString 404SettingsMessage::GetValue(const char* name, const BString& defaultValue) const 405{ 406 BString value; 407 if (FindString(name, &value) != B_OK) 408 return defaultValue; 409 return value; 410} 411 412 413const char* 414SettingsMessage::GetValue(const char* name, const char* defaultValue) const 415{ 416 const char* value; 417 if (FindString(name, &value) != B_OK) 418 return defaultValue; 419 return value; 420} 421 422 423BPoint 424SettingsMessage::GetValue(const char *name, BPoint defaultValue) const 425{ 426 BPoint value; 427 if (FindPoint(name, &value) != B_OK) 428 return defaultValue; 429 return value; 430} 431 432 433BRect 434SettingsMessage::GetValue(const char* name, BRect defaultValue) const 435{ 436 BRect value; 437 if (FindRect(name, &value) != B_OK) 438 return defaultValue; 439 return value; 440} 441 442 443entry_ref 444SettingsMessage::GetValue(const char* name, const entry_ref& defaultValue) const 445{ 446 entry_ref value; 447 if (FindRef(name, &value) != B_OK) 448 return defaultValue; 449 return value; 450} 451 452 453BMessage 454SettingsMessage::GetValue(const char* name, const BMessage& defaultValue) const 455{ 456 BMessage value; 457 if (FindMessage(name, &value) != B_OK) 458 return defaultValue; 459 return value; 460} 461 462 463BFont 464SettingsMessage::GetValue(const char* name, const BFont& defaultValue) const 465{ 466 BMessage fontMessage; 467 if (FindMessage(name, &fontMessage) != B_OK) 468 return defaultValue; 469 470 const char* family; 471 const char* style; 472 float size; 473 if (fontMessage.FindString("family", &family) != B_OK 474 || fontMessage.FindString("style", &style) != B_OK 475 || fontMessage.FindFloat("size", &size) != B_OK) { 476 return defaultValue; 477 } 478 479 BFont value; 480 if (value.SetFamilyAndStyle(family, style) != B_OK) 481 return defaultValue; 482 483 value.SetSize(size); 484 485 return value; 486} 487 488 489// #pragma mark - private 490 491 492void 493SettingsMessage::_NotifyValueChanged(const char* name) const 494{ 495 BMessage message(SETTINGS_VALUE_CHANGED); 496 message.AddString("name", name); 497 498 // Add the value of that name to the notification. 499 type_code type; 500 if (GetInfo(name, &type) == B_OK) { 501 const void* data; 502 ssize_t numBytes; 503 if (FindData(name, type, &data, &numBytes) == B_OK) 504 message.AddData("value", type, data, numBytes); 505 } 506 507 int32 count = fListeners.CountItems(); 508 for (int32 i = 0; i < count; i++) { 509 BMessenger* listener = reinterpret_cast<BMessenger*>( 510 fListeners.ItemAtFast(i)); 511 listener->SendMessage(&message); 512 } 513} 514 515