diff --git a/src/apps/debugger/user_interface/gui/util/SettingsMenu.cpp b/src/apps/debugger/user_interface/gui/util/SettingsMenu.cpp new file mode 100644 index 0000000000..6165eef643 --- /dev/null +++ b/src/apps/debugger/user_interface/gui/util/SettingsMenu.cpp @@ -0,0 +1,382 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + + +#include "SettingsMenu.h" + +#include + +#include +#include + +#include + +#include "MessageCodes.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; +} diff --git a/src/apps/debugger/user_interface/gui/util/SettingsMenu.h b/src/apps/debugger/user_interface/gui/util/SettingsMenu.h new file mode 100644 index 0000000000..da3961e69c --- /dev/null +++ b/src/apps/debugger/user_interface/gui/util/SettingsMenu.h @@ -0,0 +1,97 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ +#ifndef SETTINGS_MENU_H +#define SETTINGS_MENU_H + + +#include + +#include + +#include "Settings.h" + + +class BoolSetting; +class OptionsSetting; + + +class SettingsMenu : public BReferenceable { +public: + SettingsMenu(); + virtual ~SettingsMenu(); + + virtual status_t AddToMenu(BMenu* menu, int32 index) = 0; + virtual void RemoveFromMenu() = 0; + + virtual void PrepareToShow(BLooper* parentLooper) = 0; + virtual bool Finish(BLooper* parentLooper, bool force) = 0; +}; + + +class SettingMenuItem : public BMenuItem { +public: + SettingMenuItem(Setting* setting, + const char* label, BMessage* message, + char shortcut = 0, uint32 modifiers = 0); + SettingMenuItem(Setting* setting, BMenu* menu, + BMessage* message = NULL); + virtual ~SettingMenuItem(); + + Setting* GetSetting() const { return fSetting; } + + virtual void PrepareToShow(BLooper* parentLooper, + BHandler* targetHandler, + Settings* settings); + virtual bool Finish(BLooper* parentLooper, + BHandler* targetHandler, bool force); + + virtual void ItemSelected(Settings* settings); + +protected: + Setting* fSetting; +}; + + +class SettingsMenuImpl : public SettingsMenu, private BHandler { +public: + SettingsMenuImpl(Settings* settings); + virtual ~SettingsMenuImpl(); + + bool AddItem(SettingMenuItem* item); + // takes over ownership + bool AddBoolItem(BoolSetting* setting); + bool AddOptionsItem(OptionsSetting* setting); + + BMenu* Menu() const { return fMenu; } + virtual status_t AddToMenu(BMenu* menu, int32 index); + virtual void RemoveFromMenu(); + + virtual void PrepareToShow(BLooper* parentLooper); + virtual bool Finish(BLooper* parentLooper, bool force); + + Settings* GetSettings() const { return fSettings; } + +private: + virtual void MessageReceived(BMessage* message); + +private: + class MenuItem; + class BoolMenuItem; + class OptionMenuItem; + class OptionsMenuItem; + + typedef BObjectList MenuItemList; + +private: + SettingMenuItem* _FindMenuItem(Setting* setting) const; + +private: + Settings* fSettings; + BMenu* fMenu; + MenuItemList fMenuItems; +}; + + +#endif // SETTINGS_MENU_H