1/*
2 * Copyright 2005-2008, Haiku Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		<unknown, please fill in who knows>
7 */
8
9#include "MenuView.h"
10#include <Roster.h>
11#include <Message.h>
12#include <stdio.h>
13#include <malloc.h>
14
15#define TOGGLE_TRIGGERS 'tgtr'
16#define ALT_COMMAND 'acmd'
17#define CTRL_COMMAND 'ccmd'
18#define SET_FONT_SIZE 'sfsz'
19#define SET_DEFAULTS 'sdef'
20#define REVERT_SETTINGS 'rvst'
21
22
23MenuView::MenuView(BRect frame, const char *name, int32 resize, int32 flags)
24	: BView(frame, name, resize, flags)
25{
26	SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
27
28	get_menu_info(&menuinfo);
29	revertinfo = menuinfo;
30	revert = false;
31
32	fontmenu = new FontMenu;
33	fontmenu->SetLabelFromMarked(true);
34	fontmenu->GetFonts();
35	fontmenu->Update();
36
37	fontsizemenu = new BMenu("");
38	fontsizemenu->SetLabelFromMarked(true);
39
40	BMenuItem *item;
41	BMessage *msg;
42
43	msg = new BMessage(SET_FONT_SIZE);
44	msg->AddInt32("size", 10);
45	item = new BMenuItem("10", msg);
46	fontsizemenu->AddItem(item);
47
48	msg = new BMessage(SET_FONT_SIZE);
49	msg->AddInt32("size", 11);
50	item = new BMenuItem("11", msg);
51	fontsizemenu->AddItem(item);
52
53	msg = new BMessage(SET_FONT_SIZE);
54	msg->AddInt32("size", 12);
55	item = new BMenuItem("12", msg);
56	fontsizemenu->AddItem(item);
57
58	msg = new BMessage(SET_FONT_SIZE);
59	msg->AddInt32("size", 14);
60	item = new BMenuItem("14", msg);
61	fontsizemenu->AddItem(item);
62
63	msg = new BMessage(SET_FONT_SIZE);
64	msg->AddInt32("size", 18);
65	item = new BMenuItem("18", msg);
66	fontsizemenu->AddItem(item);
67
68	msg = new BMessage(SET_FONT_SIZE);
69	msg->AddInt32("size", 20);
70	item = new BMenuItem("20", msg);
71	fontsizemenu->AddItem(item);
72
73	msg = new BMessage(SET_FONT_SIZE);
74	msg->AddInt32("size", 22);
75	item = new BMenuItem("22", msg);
76	fontsizemenu->AddItem(item);
77
78	msg = new BMessage(SET_FONT_SIZE);
79	msg->AddInt32("size", 24);
80	item = new BMenuItem("24", msg);
81	fontsizemenu->AddItem(item);
82
83	switch((int32)menuinfo.font_size)
84	{
85		case 10:
86			item = fontsizemenu->FindItem("10");
87			break;
88
89		case 11:
90			item = fontsizemenu->FindItem("11");
91			break;
92
93		case 12:
94			item = fontsizemenu->FindItem("12");
95			break;
96
97		case 14:
98			item = fontsizemenu->FindItem("14");
99			break;
100
101		case 18:
102			item = fontsizemenu->FindItem("18");
103			break;
104
105		case 20:
106			item = fontsizemenu->FindItem("20");
107			break;
108
109		case 22:
110			item = fontsizemenu->FindItem("22");
111			break;
112
113		case 24:
114			item = fontsizemenu->FindItem("24");
115			break;
116
117		default:
118		{
119			char fontsizestr[10];
120			sprintf(fontsizestr, "%ld", (int32)menuinfo.font_size);
121			msg = new BMessage(SET_FONT_SIZE);
122			msg->AddInt32("size", (int32)menuinfo.font_size);
123			item = new BMenuItem(fontsizestr,msg);
124			fontsizemenu->AddItem(item);
125			break;
126		}
127	}
128	item->SetMarked(true);
129
130	BRect r(10, 10, 210, 40);
131	r.OffsetTo((Bounds().Width() - r.Width()) / 2, 10);
132	fontfield=new BMenuField(r, "fontfield", "", fontmenu);
133	fontfield->SetLabel("Font:");
134	fontfield->SetDivider(StringWidth("Font:") + 5);
135	AddChild(fontfield);
136
137	r.OffsetTo((Bounds().Width() - r.Width()) / 2, fontfield->Frame().bottom + 10);
138	fontsizefield=new BMenuField(r, "fontsizefield", "", fontsizemenu);
139	fontsizefield->SetLabel("Font Size:");
140	fontsizefield->SetDivider(StringWidth("Font Size:") + 5);
141	AddChild(fontsizefield);
142
143	r.OffsetTo(10, fontsizefield->Frame().bottom + 10);
144	r.right += 20;
145	showtriggers = new BCheckBox(r, "showtriggers", "Always Show Triggers",
146		new BMessage(TOGGLE_TRIGGERS));
147	showtriggers->ResizeToPreferred();
148	showtriggers->MoveTo((Bounds().Width() - showtriggers->Bounds().Width()) / 2, r.top);
149	AddChild(showtriggers);
150	if (menuinfo.triggers_always_shown)
151		showtriggers->SetValue(B_CONTROL_ON);
152
153	r.bottom = r.top + 75;
154	r.OffsetTo((Bounds().Width() - r.Width()) / 2, showtriggers->Frame().bottom + 10);
155	BBox *radiobox = new BBox(r, "radiobox");
156	radiobox->SetLabel("Shortcut Key");
157	AddChild(radiobox);
158
159	r.Set(10, 20, 50, 30);
160	altcmd = new BRadioButton(r, "altcommand", "Alt", new BMessage(ALT_COMMAND));
161	altcmd->ResizeToPreferred();
162	radiobox->AddChild(altcmd);
163
164	r.OffsetBy(0, 25);
165	ctrlcmd = new BRadioButton(r, "ctrlcommand", "Control", new BMessage(CTRL_COMMAND));
166	ctrlcmd->ResizeToPreferred();
167	radiobox->AddChild(ctrlcmd);
168
169	MarkCommandKey();
170	revertaltcmd = altcommand;
171
172	defaultsbutton = new BButton(r, "defaultsbutton", "Defaults", new BMessage(SET_DEFAULTS));
173	defaultsbutton->ResizeToPreferred();
174
175	revertbutton = new BButton(r, "revertbutton", "Revert", new BMessage(REVERT_SETTINGS));
176	revertbutton->ResizeToPreferred();
177
178	defaultsbutton->MoveTo( (Bounds().Width() -
179			(defaultsbutton->Bounds().Width() + revertbutton->Bounds().Width() + 10)) / 2,
180			radiobox->Frame().bottom + 20);
181	revertbutton->MoveTo(defaultsbutton->Frame().right + 10, radiobox->Frame().bottom + 20);
182
183	AddChild(defaultsbutton);
184	AddChild(revertbutton);
185	revertbutton->SetEnabled(false);
186}
187
188
189MenuView::~MenuView(void)
190{
191}
192
193
194void
195MenuView::AttachedToWindow(void)
196{
197	for(int32 i = 0; i < fontmenu->CountItems(); i++) {
198		BMenu *menu = fontmenu->SubmenuAt(i);
199		if (menu)
200			menu->SetTargetForItems(this);
201	}
202	fontmenu->SetTargetForItems(this);
203	fontsizemenu->SetTargetForItems(this);
204	showtriggers->SetTarget(this);
205	altcmd->SetTarget(this);
206	ctrlcmd->SetTarget(this);
207	defaultsbutton->SetTarget(this);
208	revertbutton->SetTarget(this);
209}
210
211
212void
213MenuView::MessageReceived(BMessage *msg)
214{
215	switch(msg->what) {
216		case B_MODIFIERS_CHANGED:
217			MarkCommandKey();
218			break;
219
220		case MENU_FONT_FAMILY:
221		case MENU_FONT_STYLE:
222		{
223			if (!revert)
224				revertbutton->SetEnabled(true);
225			revert = true;
226			font_family *family;
227			msg->FindPointer("family", (void**)&family);
228			font_style *style;
229			msg->FindPointer("style", (void**)&style);
230			menuinfo.f_family = *family;
231			menuinfo.f_style = *style;
232			set_menu_info(&menuinfo);
233
234			fontmenu->Update();
235			break;
236		}
237		case SET_FONT_SIZE:
238		{
239			if (!revert)
240				revertbutton->SetEnabled(true);
241			revert=true;
242			int32 size;
243			msg->FindInt32("size", &size);
244			menuinfo.font_size = size;
245			set_menu_info(&menuinfo);
246			fontmenu->Update();
247			break;
248		}
249		case ALT_COMMAND:
250			if (!revert)
251				revertbutton->SetEnabled(true);
252			revert = true;
253			altcommand = true;
254			SetCommandKey(altcommand);
255			break;
256
257		case CTRL_COMMAND:
258			if (!revert)
259				revertbutton->SetEnabled(true);
260			revert = true;
261			altcommand = false;
262			SetCommandKey(altcommand);
263			break;
264
265		case TOGGLE_TRIGGERS:
266			if (!revert)
267				revertbutton->SetEnabled(true);
268			revert = true;
269			menuinfo.triggers_always_shown = (showtriggers->Value() == B_CONTROL_ON);
270			set_menu_info(&menuinfo);
271			break;
272
273		case REVERT_SETTINGS:
274			revert = false;
275			revertbutton->SetEnabled(false);
276			SetCommandKey(revertaltcmd);
277			altcommand = revertaltcmd;
278			MarkCommandKey();
279			menuinfo = revertinfo;
280			fontmenu->Update();
281			showtriggers->SetValue(menuinfo.triggers_always_shown ? B_CONTROL_ON : B_CONTROL_OFF);
282			set_menu_info(&revertinfo);
283			break;
284
285		case SET_DEFAULTS:
286			if (!revert)
287				revertbutton->SetEnabled(true);
288			revert = true;
289
290			menuinfo.triggers_always_shown = false;
291			menuinfo.font_size = 12.0;
292			sprintf(menuinfo.f_family, "%s", "Swis721 BT");
293			sprintf(menuinfo.f_style, "%s", "Roman");
294			set_menu_info(&menuinfo);
295
296			fontmenu->Update();
297			altcommand = true;
298			SetCommandKey(altcommand);
299			MarkCommandKey();
300			showtriggers->SetValue(menuinfo.triggers_always_shown ? B_CONTROL_ON : B_CONTROL_OFF);
301			break;
302
303		default:
304			BView::MessageReceived(msg);
305			break;
306	}
307}
308
309
310void
311MenuView::MarkCommandKey(void)
312{
313	key_map *keys;
314	char *chars;
315
316	get_key_map(&keys, &chars);
317
318	bool altAsShortcut = (keys->left_command_key == 0x5d)
319		&& (keys->left_control_key == 0x5c);
320
321	free(chars);
322	free(keys);
323
324	if (altAsShortcut)
325		altcmd->SetValue(B_CONTROL_ON);
326	else
327		ctrlcmd->SetValue(B_CONTROL_ON);
328}
329
330
331void
332MenuView::SetCommandKey(bool useAlt)
333{
334	if (useAlt)	{
335		set_modifier_key(B_LEFT_COMMAND_KEY, 0x5d);
336		set_modifier_key(B_LEFT_CONTROL_KEY, 0x5c);
337	} else {
338		set_modifier_key(B_LEFT_COMMAND_KEY, 0x5c);
339		set_modifier_key(B_LEFT_CONTROL_KEY, 0x5d);
340	}
341	be_roster->Broadcast(new BMessage(B_MODIFIERS_CHANGED));
342}
343