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