xref: /haiku/src/tests/kits/interface/menu/menuworld/MenuWindow.cpp (revision 3f28966548baf455f231941a6fbc83552119821d)
1 //--------------------------------------------------------------------
2 //
3 //	MenuWindow.cpp
4 //
5 //	Written by: Owen Smith
6 //
7 //--------------------------------------------------------------------
8 
9 /*
10 	Copyright 1999, Be Incorporated.   All Rights Reserved.
11 	This file may be used under the terms of the Be Sample Code License.
12 */
13 
14 #include <Application.h>
15 #include <Box.h>
16 #include <CheckBox.h>
17 #include <Menu.h>
18 #include <MenuBar.h>
19 #include <MenuItem.h>
20 #include <StringView.h>
21 #include <stdio.h>
22 #include <string.h>
23 
24 #include "constants.h"
25 #include "MenuView.h"
26 #include "MenuWindow.h"
27 #include "stddlg.h"
28 
29 //====================================================================
30 //	MenuWindow Implementation
31 
32 #define MAX_TEST_STATUS_CHARS 25
33 
34 
35 //--------------------------------------------------------------------
36 //	MenuWindow constructors, destructors, operators
37 
MenuWindow(const char * name)38 MenuWindow::MenuWindow(const char* name)
39 	: BWindow(BRect(60,60,60,60), name, B_TITLED_WINDOW,
40 		B_NOT_RESIZABLE | B_NOT_ZOOMABLE)
41 {
42 	m_bUsingFullMenuBar = true;
43 
44 	// menu bars
45 	BRect dummyFrame(0, 0, 0, 0);
46 	m_pFullMenuBar = new BMenuBar(dummyFrame, "Full Menu Bar");
47 	m_pHiddenMenuBar = new BMenuBar(dummyFrame, "Menu Bar w. Hidden User Menus");
48 
49 	// File menu
50 	BMenu* pMenu = BuildFileMenu();
51 	if (pMenu) {
52 		m_pFullMenuBar->AddItem(pMenu);
53 	}
54 	pMenu = BuildFileMenu();
55 	if (pMenu) {
56 		m_pHiddenMenuBar->AddItem(pMenu);
57 	}
58 
59 	// Test menu
60 	pMenu = m_testMenuBuilder.BuildTestMenu(B_MINI_ICON);
61 	if (pMenu) {
62 		m_pFullMenuBar->AddItem(pMenu);
63 	}
64 	pMenu = m_testMenuBuilder.BuildTestMenu(B_MINI_ICON);
65 	if (pMenu) {
66 		m_pHiddenMenuBar->AddItem(pMenu);
67 	}
68 
69 	// add child after menus are added so its initially
70 	// calculated app_server bounds take added menus into
71 	// account
72 	AddChild(m_pFullMenuBar);
73 
74 	float menuHeight = m_pFullMenuBar->Bounds().Height();
75 
76 	// Menu view
77 	m_pMenuView = new MenuView(B_FOLLOW_NONE); // don't follow window just yet!
78 	m_pMenuView->MoveBy(0, menuHeight + 1);
79 	AddChild(m_pMenuView);
80 
81 	// Status view
82 	BRect menuViewRect = m_pMenuView->Frame();
83 	float top = menuViewRect.bottom + 1;
84 	font_height plainHeight;
85 	be_plain_font->GetHeight(&plainHeight);
86 
87 	// Simulate a vertical divider by making a BBox where only the top side
88 	// can be seen in the window.
89 	BRect boxFrame;
90 	boxFrame.Set(menuViewRect.left - 2,
91 		top,
92 		menuViewRect.right + 2,
93 		top + plainHeight.ascent + plainHeight.descent + plainHeight.leading + 4);
94 
95 	BBox* pStatusBox = new BBox(boxFrame);
96 	AddChild(pStatusBox);
97 
98 	BRect statusFrame = pStatusBox->Bounds();
99 	statusFrame.InsetBy(2,2);
100 	m_pStatusView = new BStringView(statusFrame, "Status View", STR_STATUS_DEFAULT,
101 		B_FOLLOW_ALL); // don't follow window just yet!
102 	m_pStatusView->SetViewColor(BKG_GREY);
103 	pStatusBox->AddChild(m_pStatusView);
104 
105 	// Resize window dynamically to fit MenuView (and Status View)
106 	float windowWidth = m_pMenuView->Frame().right;
107 	float windowHeight = boxFrame.bottom - 4;
108 	ResizeTo(windowWidth, windowHeight);
109 }
110 
111 
112 
113 //--------------------------------------------------------------------
114 //	MenuWindow virtual function overrides
115 
MenusBeginning(void)116 void MenuWindow::MenusBeginning(void)
117 {
118 	if ((! Valid()) || (! m_bUsingFullMenuBar)) {
119 		return;
120 	}
121 
122 	int32 len = m_pFullMenuBar->CountItems();
123 	for (int32 i = 2; i < len; i++) // skipping File and Test menus
124 	{
125 		BMenu* pMenu = m_pFullMenuBar->SubmenuAt(i);
126 		if (pMenu) {
127 			m_pMenuView->PopulateUserMenu(pMenu, i - 2);
128 		}
129 	}
130 }
131 
MessageReceived(BMessage * message)132 void MenuWindow::MessageReceived(BMessage* message)
133 {
134 	switch (message->what) {
135 	case MSG_WIN_ADD_MENU:
136 		AddMenu(message);
137 		break;
138 	case MSG_WIN_DELETE_MENU:
139 		DeleteMenu(message);
140 		break;
141 	case MSG_TEST_ITEM:
142 		TestMenu(message);
143 		break;
144 	case MSG_USER_ITEM:
145 		UserMenu(message);
146 		break;
147 	case MSG_WIN_HIDE_USER_MENUS:
148 		ToggleUserMenus(message);
149 		break;
150 	case MSG_WIN_LARGE_TEST_ICONS:
151 		ToggleTestIcons(message);
152 		break;
153 	default:
154 		BWindow::MessageReceived(message);
155 		break;
156 	}
157 }
158 
QuitRequested(void)159 bool MenuWindow::QuitRequested(void)
160 {
161 	be_app->PostMessage(B_QUIT_REQUESTED);
162 	return true;
163 }
164 
165 
166 
167 //--------------------------------------------------------------------
168 //	MenuWindow operations
169 
UpdateStatus(const char * str1,const char * str2)170 void MenuWindow::UpdateStatus(const char* str1, const char* str2)
171 {
172 	uint32 lenTotal = 0, len1 = 0, len2 = 0;
173 
174 	if (str1)
175 		len1 = strlen(str1);
176 	if (str2)
177 		len2 = strlen(str2);
178 
179 	lenTotal = len1 + len2;
180 	char* updateText = new char[lenTotal+1];
181 	updateText[0] = '\0'; // in case str1 and str2 are both NULL
182 
183 	if (str1)
184 		strcpy(updateText, str1);
185 	if (str2)
186 		strcpy(updateText + len1, str2);
187 
188 	if (Lock() && Valid()) {
189 		m_pStatusView->SetText(updateText);
190 		Unlock();
191 	}
192 
193 	delete [] updateText;
194 }
195 
196 
197 
198 //--------------------------------------------------------------------
199 //	MenuWindow message handlers
200 
AddMenu(BMessage * message)201 void MenuWindow::AddMenu(BMessage* message)
202 {
203 	if (! Valid()) {
204 		return;
205 	}
206 
207 	const char* menuName;
208 	if (message->FindString("Menu Name", &menuName) == B_OK) {
209 		m_pFullMenuBar->AddItem(new BMenu(menuName));
210 		UpdateStatus(STR_STATUS_ADD_MENU, menuName);
211 	}
212 }
213 
DeleteMenu(BMessage * message)214 void MenuWindow::DeleteMenu(BMessage* message)
215 {
216 	if (! Valid()) {
217 		return;
218 	}
219 
220 	int32 i;
221 	if (message->FindInt32("Menu Index", &i) == B_OK) {
222 		BMenuItem* pItem = m_pFullMenuBar->ItemAt(i+2);
223 		if (pItem) {
224 			// menu index is the above index + 2 (for File and Test menus)
225 			m_pFullMenuBar->RemoveItem(pItem);
226 			UpdateStatus(STR_STATUS_DELETE_MENU, pItem->Label());
227 			delete pItem;
228 		}
229 	}
230 }
231 
TestMenu(BMessage * message)232 void MenuWindow::TestMenu(BMessage* message)
233 {
234 	if (! Valid()) {
235 		return;
236 	}
237 
238 	int32 i;
239 	if (message->FindInt32("Item Index", &i) == B_OK) {
240 		char numText[3];
241 		sprintf(numText, "%ld", i);
242 		UpdateStatus(STR_STATUS_TEST, numText);
243 	}
244 }
245 
UserMenu(BMessage * message)246 void MenuWindow::UserMenu(BMessage* message)
247 {
248 	if (! Valid()) {
249 		return;
250 	}
251 
252 	const char* itemName;
253 	if (message->FindString("Item Name", &itemName) == B_OK) {
254 		UpdateStatus(STR_STATUS_USER, itemName);
255 	}
256 }
257 
ToggleUserMenus(BMessage * message)258 void MenuWindow::ToggleUserMenus(BMessage* message)
259 {
260 	if (! Valid()) {
261 		return;
262 	}
263 
264 	void* pSrc;
265 	bool useFullMenus = false;
266 
267 	if (message->FindPointer("source", &pSrc) == B_OK) {
268 		BCheckBox* pCheckBox = reinterpret_cast<BCheckBox*>(pSrc);
269 		useFullMenus = (pCheckBox->Value() == B_CONTROL_OFF);
270 	}
271 
272 	if ((! useFullMenus) && m_bUsingFullMenuBar) {
273 		RemoveChild(m_pFullMenuBar);
274 		AddChild(m_pHiddenMenuBar);
275 		m_bUsingFullMenuBar = false;
276 	} else if (useFullMenus && (! m_bUsingFullMenuBar)) {
277 		RemoveChild(m_pHiddenMenuBar);
278 		AddChild(m_pFullMenuBar);
279 		m_bUsingFullMenuBar = true;
280 	}
281 }
282 
ToggleTestIcons(BMessage * message)283 void MenuWindow::ToggleTestIcons(BMessage* message)
284 {
285 	if (! Valid()) {
286 		return;
287 	}
288 
289 	void* pSrc;
290 	icon_size size = B_MINI_ICON;
291 
292 	if (message->FindPointer("source", &pSrc) == B_OK) {
293 		BCheckBox* pCheckBox = reinterpret_cast<BCheckBox*>(pSrc);
294 		size = (pCheckBox->Value() == B_CONTROL_ON) ? B_LARGE_ICON : B_MINI_ICON;
295 	}
296 
297 	ReplaceTestMenu(m_pFullMenuBar, size);
298 	ReplaceTestMenu(m_pHiddenMenuBar, size);
299 }
300 
301 
302 
303 //--------------------------------------------------------------------
304 //	MenuWindow implementation member functions
305 
Valid(void) const306 bool MenuWindow::Valid(void) const
307 {
308 	if (! m_pFullMenuBar) {
309 		ierror(STR_NO_FULL_MENU_BAR);
310 		return false;
311 	}
312 	if (! m_pHiddenMenuBar) {
313 		ierror(STR_NO_HIDDEN_MENU_BAR);
314 		return false;
315 	}
316 	if (! m_pMenuView) {
317 		ierror(STR_NO_MENU_VIEW);
318 		return false;
319 	}
320 	if (! m_pStatusView) {
321 		ierror(STR_NO_STATUS_VIEW);
322 		return false;
323 	}
324 	return true;
325 }
326 
BuildFileMenu(void) const327 BMenu* MenuWindow::BuildFileMenu(void) const
328 {
329 	BMenu* pMenu = new BMenu(STR_MNU_FILE);
330 
331 	BMenuItem* pAboutItem = new BMenuItem(STR_MNU_FILE_ABOUT,
332 		new BMessage(B_ABOUT_REQUESTED));
333 	pAboutItem->SetTarget(NULL, be_app);
334 	pMenu->AddItem(pAboutItem);
335 
336 	pMenu->AddSeparatorItem();
337 
338 	pMenu->AddItem(new BMenuItem(STR_MNU_FILE_CLOSE,
339 		new BMessage(B_QUIT_REQUESTED), CMD_FILE_CLOSE));
340 
341 	return pMenu;
342 }
343 
ReplaceTestMenu(BMenuBar * pMenuBar,icon_size size)344 void MenuWindow::ReplaceTestMenu(BMenuBar* pMenuBar, icon_size size)
345 {
346 	if (! pMenuBar) {
347 		return;
348 	}
349 
350 	BMenu* pTestMenu = m_testMenuBuilder.BuildTestMenu(size);
351 	if (pTestMenu) {
352 		BMenuItem* pPrevItem = pMenuBar->RemoveItem(1);
353 		if (pPrevItem) {
354 			delete pPrevItem;
355 		}
356 		pMenuBar->AddItem(pTestMenu, 1);
357 	}
358 }
359