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