xref: /haiku/src/apps/debugger/user_interface/gui/util/SettingsMenu.cpp (revision 10ba334855ad0d7297e23f15dea292f7dbdd231c)
1 /*
2  * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include "SettingsMenu.h"
8 
9 #include <new>
10 
11 #include <Looper.h>
12 #include <Menu.h>
13 
14 #include <AutoDeleter.h>
15 
16 #include "AppMessageCodes.h"
17 #include "SettingsDescription.h"
18 
19 
20 // #pragma mark - SettingsMenu
21 
22 
SettingsMenu()23 SettingsMenu::SettingsMenu()
24 {
25 }
26 
27 
~SettingsMenu()28 SettingsMenu::~SettingsMenu()
29 {
30 }
31 
32 
33 // #pragma mark - SettingMenuItem
34 
35 
SettingMenuItem(Setting * setting,const char * label,BMessage * message,char shortcut,uint32 modifiers)36 SettingMenuItem::SettingMenuItem(Setting* setting, const char* label,
37 	BMessage* message, char shortcut, uint32 modifiers)
38 	:
39 	BMenuItem(label, message, shortcut, modifiers),
40 	fSetting(setting)
41 {
42 	fSetting->AcquireReference();
43 }
44 
45 
SettingMenuItem(Setting * setting,BMenu * menu,BMessage * message)46 SettingMenuItem::SettingMenuItem(Setting* setting, BMenu* menu,
47 	BMessage* message)
48 	:
49 	BMenuItem(menu, message),
50 	fSetting(setting)
51 {
52 	fSetting->AcquireReference();
53 }
54 
55 
~SettingMenuItem()56 SettingMenuItem::~SettingMenuItem()
57 {
58 	fSetting->ReleaseReference();
59 }
60 
61 
62 void
PrepareToShow(BLooper * parentLooper,BHandler * targetHandler,Settings * settings)63 SettingMenuItem::PrepareToShow(BLooper* parentLooper, BHandler* targetHandler,
64 		Settings* settings)
65 {
66 }
67 
68 
69 bool
Finish(BLooper * parentLooper,BHandler * targetHandler,bool force)70 SettingMenuItem::Finish(BLooper* parentLooper, BHandler* targetHandler,
71 	bool force)
72 {
73 	return false;
74 }
75 
76 
77 void
ItemSelected(Settings * settings)78 SettingMenuItem::ItemSelected(Settings* settings)
79 {
80 }
81 
82 
83 // #pragma mark - BoolMenuItem
84 
85 
86 class SettingsMenuImpl::MenuItem : public SettingMenuItem {
87 public:
MenuItem(Setting * setting,const char * label,BMessage * message,char shortcut=0,uint32 modifiers=0)88 	MenuItem(Setting* setting,
89 		const char* label, BMessage* message,
90 		char shortcut = 0, uint32 modifiers = 0)
91 		:
92 		SettingMenuItem(setting, label, message, shortcut, modifiers)
93 	{
94 	}
95 
MenuItem(Setting * setting,BMenu * menu,BMessage * message=NULL)96 	MenuItem(Setting* setting, BMenu* menu, BMessage* message = NULL)
97 		:
98 		SettingMenuItem(setting, menu, message)
99 	{
100 	}
101 
PrepareToShow(BLooper * parentLooper,BHandler * targetHandler,Settings * settings)102 	virtual void PrepareToShow(BLooper* parentLooper, BHandler* targetHandler,
103 		Settings* settings)
104 	{
105 		BMessage* message = new BMessage(
106 			MSG_SETTINGS_MENU_IMPL_ITEM_SELECTED);
107 		if (message == NULL)
108 			return;
109 		message->AddPointer("setting", fSetting);
110 
111 		SetMessage(message);
112 		SetTarget(targetHandler);
113 	}
114 };
115 
116 
117 class SettingsMenuImpl::BoolMenuItem : public MenuItem {
118 public:
BoolMenuItem(BoolSetting * setting)119 	BoolMenuItem(BoolSetting* setting)
120 		:
121 		MenuItem(setting, setting->Name(), NULL)
122 	{
123 	}
124 };
125 
126 
127 // #pragma mark - OptionMenuItem
128 
129 
130 class SettingsMenuImpl::OptionMenuItem : public BMenuItem {
131 public:
OptionMenuItem(SettingsOption * option)132 	OptionMenuItem(SettingsOption* option)
133 		:
134 		BMenuItem(option->Name(), NULL),
135 		fOption(option)
136 	{
137 	}
138 
Option() const139 	SettingsOption* Option() const
140 	{
141 		return fOption;
142 	}
143 
PrepareToShow(BLooper * parentLooper,BHandler * targetHandler,Settings * settings,OptionsSetting * setting)144 	void PrepareToShow(BLooper* parentLooper, BHandler* targetHandler,
145 		Settings* settings, OptionsSetting* setting)
146 	{
147 		BMessage* message = new BMessage(
148 			MSG_SETTINGS_MENU_IMPL_OPTION_ITEM_SELECTED);
149 		if (message == NULL)
150 			return;
151 		message->AddPointer("setting", static_cast<Setting*>(setting));
152 		message->AddPointer("option", fOption);
153 
154 		SetMessage(message);
155 		SetTarget(targetHandler);
156 	}
157 
158 private:
159 	SettingsOption*	fOption;
160 };
161 
162 
163 // #pragma mark - OptionsMenuItem
164 
165 
166 class SettingsMenuImpl::OptionsMenuItem : public MenuItem {
167 public:
OptionsMenuItem(OptionsSetting * setting,BMenu * menu)168 	OptionsMenuItem(OptionsSetting* setting, BMenu* menu)
169 		:
170 		MenuItem(setting, menu)
171 	{
172 	}
173 
PrepareToShow(BLooper * parentLooper,BHandler * targetHandler,Settings * settings)174 	virtual void PrepareToShow(BLooper* parentLooper, BHandler* targetHandler,
175 		Settings* settings)
176 	{
177 		SettingsOption* selectedOption = settings->OptionValue(
178 			dynamic_cast<OptionsSetting*>(GetSetting()));
179 
180 		for (int32 i = 0; BMenuItem* item = Submenu()->ItemAt(i); i++) {
181 			OptionMenuItem* optionItem = dynamic_cast<OptionMenuItem*>(item);
182 			if (optionItem != NULL)
183 				optionItem->PrepareToShow(parentLooper, targetHandler,
184 					settings, dynamic_cast<OptionsSetting*>(GetSetting()));
185 
186 			optionItem->SetMarked(optionItem->Option() == selectedOption);
187 		}
188 	}
189 
OptionItemSelected(Settings * settings,SettingsOption * option)190 	void OptionItemSelected(Settings* settings, SettingsOption* option)
191 	{
192 		settings->SetValue(fSetting,
193 			BVariant(option->ID(), B_VARIANT_DONT_COPY_DATA));
194 	}
195 };
196 
197 
198 // #pragma mark - SettingsMenuImpl
199 
200 
SettingsMenuImpl(Settings * settings)201 SettingsMenuImpl::SettingsMenuImpl(Settings* settings)
202 	:
203 	fSettings(settings),
204 	fMenu(NULL)
205 {
206 	fSettings->AcquireReference();
207 }
208 
209 
~SettingsMenuImpl()210 SettingsMenuImpl::~SettingsMenuImpl()
211 {
212 	RemoveFromMenu();
213 	fSettings->ReleaseReference();
214 }
215 
216 
217 bool
AddItem(SettingMenuItem * item)218 SettingsMenuImpl::AddItem(SettingMenuItem* item)
219 {
220 	return fMenuItems.AddItem(item);
221 }
222 
223 
224 bool
AddBoolItem(BoolSetting * setting)225 SettingsMenuImpl::AddBoolItem(BoolSetting* setting)
226 {
227 	SettingMenuItem* item = new(std::nothrow) BoolMenuItem(setting);
228 	if (item == NULL || !AddItem(item)) {
229 		delete item;
230 		return false;
231 	}
232 
233 	return true;
234 }
235 
236 
237 bool
AddOptionsItem(OptionsSetting * setting)238 SettingsMenuImpl::AddOptionsItem(OptionsSetting* setting)
239 {
240 	// create the submenu
241 	BMenu* menu = new(std::nothrow) BMenu(setting->Name());
242 	if (menu == NULL)
243 		return false;
244 
245 	// create the menu item
246 	OptionsMenuItem* item = new(std::nothrow) OptionsMenuItem(setting, menu);
247 	if (item == NULL) {
248 		delete menu;
249 		return false;
250 	}
251 	ObjectDeleter<OptionsMenuItem> itemDeleter(item);
252 
253 	// create sub menu items for the options
254 	int32 count = setting->CountOptions();
255 	for (int32 i = 0; i < count; i++) {
256 		SettingsOption* option = setting->OptionAt(i);
257 		BMenuItem* optionItem = new(std::nothrow) OptionMenuItem(option);
258 		if (optionItem == NULL || !menu->AddItem(optionItem)) {
259 			delete optionItem;
260 			return false;
261 		}
262 	}
263 
264 	if (!AddItem(item))
265 		return false;
266 
267 	itemDeleter.Detach();
268 	return true;
269 }
270 
271 
272 status_t
AddToMenu(BMenu * menu,int32 index)273 SettingsMenuImpl::AddToMenu(BMenu* menu, int32 index)
274 {
275 	if (fMenu != NULL)
276 		return B_BAD_VALUE;
277 
278 	fMenu = menu;
279 
280 	for (int32 i = 0; SettingMenuItem* item = fMenuItems.ItemAt(i); i++) {
281 		if (!fMenu->AddItem(item, index + i)) {
282 			for (i--; i >= 0; i--)
283 				fMenu->RemoveItem(fMenuItems.ItemAt(i));
284 
285 			menu = NULL;
286 			return B_NO_MEMORY;
287 		}
288 	}
289 
290 	return B_OK;
291 }
292 
293 
294 void
RemoveFromMenu()295 SettingsMenuImpl::RemoveFromMenu()
296 {
297 	if (fMenu == NULL)
298 		return;
299 
300 	for (int32 i = 0; SettingMenuItem* item = fMenuItems.ItemAt(i); i++)
301 		fMenu->RemoveItem(item);
302 
303 	fMenu = NULL;
304 }
305 
306 
307 void
PrepareToShow(BLooper * parentLooper)308 SettingsMenuImpl::PrepareToShow(BLooper* parentLooper)
309 {
310 	parentLooper->AddHandler(this);
311 
312 	for (int32 i = 0; SettingMenuItem* item = fMenuItems.ItemAt(i); i++)
313 		item->PrepareToShow(parentLooper, this, fSettings);
314 }
315 
316 
317 bool
Finish(BLooper * parentLooper,bool force)318 SettingsMenuImpl::Finish(BLooper* parentLooper, bool force)
319 {
320 	bool stillActive = false;
321 
322 	for (int32 i = 0; SettingMenuItem* item = fMenuItems.ItemAt(i); i++)
323 		stillActive |= item->Finish(parentLooper, this, force);
324 
325 	parentLooper->RemoveHandler(this);
326 
327 	return stillActive;
328 }
329 
330 
331 void
MessageReceived(BMessage * message)332 SettingsMenuImpl::MessageReceived(BMessage* message)
333 {
334 	switch (message->what) {
335 		case MSG_SETTINGS_MENU_IMPL_ITEM_SELECTED:
336 		{
337 			Setting* setting;
338 			if (message->FindPointer("setting", (void**)&setting) != B_OK)
339 				break;
340 
341 			if (SettingMenuItem* item = _FindMenuItem(setting))
342 				item->ItemSelected(fSettings);
343 
344 			break;
345 		}
346 
347 		case MSG_SETTINGS_MENU_IMPL_OPTION_ITEM_SELECTED:
348 		{
349 			Setting* setting;
350 			SettingsOption* option;
351 			if (message->FindPointer("setting", (void**)&setting) != B_OK
352 				|| message->FindPointer("option", (void**)&option) != B_OK) {
353 				break;
354 			}
355 
356 			// get the options setting item
357 			OptionsMenuItem* optionsItem = dynamic_cast<OptionsMenuItem*>(
358 				_FindMenuItem(setting));
359 			if (optionsItem == NULL)
360 				break;
361 
362 			optionsItem->OptionItemSelected(fSettings, option);
363 			break;
364 		}
365 
366 		default:
367 			BHandler::MessageReceived(message);
368 			break;
369 	}
370 }
371 
372 
373 SettingMenuItem*
_FindMenuItem(Setting * setting) const374 SettingsMenuImpl::_FindMenuItem(Setting* setting) const
375 {
376 	for (int32 i = 0; SettingMenuItem* item = fMenuItems.ItemAt(i); i++) {
377 		if (item->GetSetting() == setting)
378 			return item;
379 	}
380 
381 	return NULL;
382 }
383