/* * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. * Distributed under the terms of the MIT License. */ #include "SettingsMenu.h" #include #include #include #include #include "AppMessageCodes.h" #include "SettingsDescription.h" // #pragma mark - SettingsMenu SettingsMenu::SettingsMenu() { } SettingsMenu::~SettingsMenu() { } // #pragma mark - SettingMenuItem SettingMenuItem::SettingMenuItem(Setting* setting, const char* label, BMessage* message, char shortcut, uint32 modifiers) : BMenuItem(label, message, shortcut, modifiers), fSetting(setting) { fSetting->AcquireReference(); } SettingMenuItem::SettingMenuItem(Setting* setting, BMenu* menu, BMessage* message) : BMenuItem(menu, message), fSetting(setting) { fSetting->AcquireReference(); } SettingMenuItem::~SettingMenuItem() { fSetting->ReleaseReference(); } void SettingMenuItem::PrepareToShow(BLooper* parentLooper, BHandler* targetHandler, Settings* settings) { } bool SettingMenuItem::Finish(BLooper* parentLooper, BHandler* targetHandler, bool force) { return false; } void SettingMenuItem::ItemSelected(Settings* settings) { } // #pragma mark - BoolMenuItem class SettingsMenuImpl::MenuItem : public SettingMenuItem { public: MenuItem(Setting* setting, const char* label, BMessage* message, char shortcut = 0, uint32 modifiers = 0) : SettingMenuItem(setting, label, message, shortcut, modifiers) { } MenuItem(Setting* setting, BMenu* menu, BMessage* message = NULL) : SettingMenuItem(setting, menu, message) { } virtual void PrepareToShow(BLooper* parentLooper, BHandler* targetHandler, Settings* settings) { BMessage* message = new BMessage( MSG_SETTINGS_MENU_IMPL_ITEM_SELECTED); if (message == NULL) return; message->AddPointer("setting", fSetting); SetMessage(message); SetTarget(targetHandler); } }; class SettingsMenuImpl::BoolMenuItem : public MenuItem { public: BoolMenuItem(BoolSetting* setting) : MenuItem(setting, setting->Name(), NULL) { } }; // #pragma mark - OptionMenuItem class SettingsMenuImpl::OptionMenuItem : public BMenuItem { public: OptionMenuItem(SettingsOption* option) : BMenuItem(option->Name(), NULL), fOption(option) { } SettingsOption* Option() const { return fOption; } void PrepareToShow(BLooper* parentLooper, BHandler* targetHandler, Settings* settings, OptionsSetting* setting) { BMessage* message = new BMessage( MSG_SETTINGS_MENU_IMPL_OPTION_ITEM_SELECTED); if (message == NULL) return; message->AddPointer("setting", static_cast(setting)); message->AddPointer("option", fOption); SetMessage(message); SetTarget(targetHandler); } private: SettingsOption* fOption; }; // #pragma mark - OptionsMenuItem class SettingsMenuImpl::OptionsMenuItem : public MenuItem { public: OptionsMenuItem(OptionsSetting* setting, BMenu* menu) : MenuItem(setting, menu) { } virtual void PrepareToShow(BLooper* parentLooper, BHandler* targetHandler, Settings* settings) { SettingsOption* selectedOption = settings->OptionValue( dynamic_cast(GetSetting())); for (int32 i = 0; BMenuItem* item = Submenu()->ItemAt(i); i++) { OptionMenuItem* optionItem = dynamic_cast(item); if (optionItem != NULL) optionItem->PrepareToShow(parentLooper, targetHandler, settings, dynamic_cast(GetSetting())); optionItem->SetMarked(optionItem->Option() == selectedOption); } } void OptionItemSelected(Settings* settings, SettingsOption* option) { settings->SetValue(fSetting, BVariant(option->ID(), B_VARIANT_DONT_COPY_DATA)); } }; // #pragma mark - SettingsMenuImpl SettingsMenuImpl::SettingsMenuImpl(Settings* settings) : fSettings(settings), fMenu(NULL) { fSettings->AcquireReference(); } SettingsMenuImpl::~SettingsMenuImpl() { RemoveFromMenu(); fSettings->ReleaseReference(); } bool SettingsMenuImpl::AddItem(SettingMenuItem* item) { return fMenuItems.AddItem(item); } bool SettingsMenuImpl::AddBoolItem(BoolSetting* setting) { SettingMenuItem* item = new(std::nothrow) BoolMenuItem(setting); if (item == NULL || !AddItem(item)) { delete item; return false; } return true; } bool SettingsMenuImpl::AddOptionsItem(OptionsSetting* setting) { // create the submenu BMenu* menu = new(std::nothrow) BMenu(setting->Name()); if (menu == NULL) return false; // create the menu item OptionsMenuItem* item = new(std::nothrow) OptionsMenuItem(setting, menu); if (item == NULL) { delete menu; return false; } ObjectDeleter itemDeleter(item); // create sub menu items for the options int32 count = setting->CountOptions(); for (int32 i = 0; i < count; i++) { SettingsOption* option = setting->OptionAt(i); BMenuItem* optionItem = new(std::nothrow) OptionMenuItem(option); if (optionItem == NULL || !menu->AddItem(optionItem)) { delete optionItem; return false; } } if (!AddItem(item)) return false; itemDeleter.Detach(); return true; } status_t SettingsMenuImpl::AddToMenu(BMenu* menu, int32 index) { if (fMenu != NULL) return B_BAD_VALUE; fMenu = menu; for (int32 i = 0; SettingMenuItem* item = fMenuItems.ItemAt(i); i++) { if (!fMenu->AddItem(item, index + i)) { for (i--; i >= 0; i--) fMenu->RemoveItem(fMenuItems.ItemAt(i)); menu = NULL; return B_NO_MEMORY; } } return B_OK; } void SettingsMenuImpl::RemoveFromMenu() { if (fMenu == NULL) return; for (int32 i = 0; SettingMenuItem* item = fMenuItems.ItemAt(i); i++) fMenu->RemoveItem(item); fMenu = NULL; } void SettingsMenuImpl::PrepareToShow(BLooper* parentLooper) { parentLooper->AddHandler(this); for (int32 i = 0; SettingMenuItem* item = fMenuItems.ItemAt(i); i++) item->PrepareToShow(parentLooper, this, fSettings); } bool SettingsMenuImpl::Finish(BLooper* parentLooper, bool force) { bool stillActive = false; for (int32 i = 0; SettingMenuItem* item = fMenuItems.ItemAt(i); i++) stillActive |= item->Finish(parentLooper, this, force); parentLooper->RemoveHandler(this); return stillActive; } void SettingsMenuImpl::MessageReceived(BMessage* message) { switch (message->what) { case MSG_SETTINGS_MENU_IMPL_ITEM_SELECTED: { Setting* setting; if (message->FindPointer("setting", (void**)&setting) != B_OK) break; if (SettingMenuItem* item = _FindMenuItem(setting)) item->ItemSelected(fSettings); break; } case MSG_SETTINGS_MENU_IMPL_OPTION_ITEM_SELECTED: { Setting* setting; SettingsOption* option; if (message->FindPointer("setting", (void**)&setting) != B_OK || message->FindPointer("option", (void**)&option) != B_OK) { break; } // get the options setting item OptionsMenuItem* optionsItem = dynamic_cast( _FindMenuItem(setting)); if (optionsItem == NULL) break; optionsItem->OptionItemSelected(fSettings, option); break; } default: BHandler::MessageReceived(message); break; } } SettingMenuItem* SettingsMenuImpl::_FindMenuItem(Setting* setting) const { for (int32 i = 0; SettingMenuItem* item = fMenuItems.ItemAt(i); i++) { if (item->GetSetting() == setting) return item; } return NULL; }