1/*
2Open Tracker License
3
4Terms and Conditions
5
6Copyright (c) 1991-2000, Be Incorporated. All rights reserved.
7
8Permission is hereby granted, free of charge, to any person obtaining a copy of
9this software and associated documentation files (the "Software"), to deal in
10the Software without restriction, including without limitation the rights to
11use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
12of the Software, and to permit persons to whom the Software is furnished to do
13so, subject to the following conditions:
14
15The above copyright notice and this permission notice applies to all licensees
16and shall be included in all copies or substantial portions of the Software.
17
18THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY,
20FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION
23WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
25Except as contained in this notice, the name of Be Incorporated shall not be
26used in advertising or otherwise to promote the sale, use or other dealings in
27this Software without prior written authorization from Be Incorporated.
28
29Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered
30trademarks of Be Incorporated in the United States and other countries. Other
31brand product names are registered trademarks or trademarks of their respective
32holders.
33All rights reserved.
34*/
35
36
37#include "BarMenuBar.h"
38
39#include <string.h>
40
41#include <Bitmap.h>
42#include <Debug.h>
43#include <NodeInfo.h>
44
45#include "icons.h"
46
47#include "BarWindow.h"
48#include "DeskbarMenu.h"
49#include "DeskbarUtils.h"
50#include "ResourceSet.h"
51#include "TeamMenu.h"
52
53
54const float kSepItemWidth = 5.0f;
55
56TBarMenuBar::TBarMenuBar(TBarView* bar, BRect frame, const char* name)
57	: BMenuBar(frame, name, B_FOLLOW_NONE, B_ITEMS_IN_ROW, false),
58	fBarView(bar),
59	fAppListMenuItem(NULL),
60	fSeparatorItem(NULL)
61{
62	SetItemMargins(0.0f, 0.0f, 0.0f, 0.0f);
63
64	TDeskbarMenu* beMenu = new TDeskbarMenu(bar);
65	TBarWindow::SetDeskbarMenu(beMenu);
66
67	const BBitmap* logoBitmap = AppResSet()->FindBitmap(B_MESSAGE_TYPE,
68		R_LeafLogoBitmap);
69	fDeskbarMenuItem = new TBarMenuTitle(frame.Width(), frame.Height(),
70		logoBitmap, beMenu);
71	AddItem(fDeskbarMenuItem);
72}
73
74
75TBarMenuBar::~TBarMenuBar()
76{
77}
78
79
80void
81TBarMenuBar::SmartResize(float width, float height)
82{
83	if (width == -1.0f && height == -1.0f) {
84		BRect frame = Frame();
85		width = frame.Width();
86		height = frame.Height();
87	} else
88		ResizeTo(width, height);
89
90	width -= 1;
91
92	if (fSeparatorItem != NULL)
93		fDeskbarMenuItem->SetWidthHeight(width - kSepItemWidth, height);
94	else {
95		int32 count = CountItems();
96		if (fDeskbarMenuItem)
97			fDeskbarMenuItem->SetWidthHeight(width / count, height);
98		if (fAppListMenuItem)
99			fAppListMenuItem->SetWidthHeight(width / count, height);
100	}
101
102	InvalidateLayout();
103}
104
105
106bool
107TBarMenuBar::AddTeamMenu()
108{
109	if (CountItems() > 1)
110		return false;
111
112	BRect frame(Frame());
113
114	delete fAppListMenuItem;
115	fAppListMenuItem = new TBarMenuTitle(0.0f, 0.0f,
116		AppResSet()->FindBitmap(B_MESSAGE_TYPE, R_TeamIcon), new TTeamMenu());
117
118	bool added = AddItem(fAppListMenuItem);
119
120	if (added)
121		SmartResize(frame.Width() - 1.0f, frame.Height());
122	else
123		SmartResize(frame.Width(), frame.Height());
124
125	return added;
126}
127
128
129bool
130TBarMenuBar::RemoveTeamMenu()
131{
132	if (CountItems() < 2)
133		return false;
134
135	bool removed = false;
136
137	if (fAppListMenuItem != NULL && RemoveItem(fAppListMenuItem)) {
138		delete fAppListMenuItem;
139		fAppListMenuItem = NULL;
140		SmartResize(-1, -1);
141		removed = true;
142	}
143
144	return removed;
145}
146
147
148bool
149TBarMenuBar::AddSeperatorItem()
150{
151	if (CountItems() > 1)
152		return false;
153
154	BRect frame(Frame());
155
156	delete fSeparatorItem;
157	fSeparatorItem = new TTeamMenuItem(kSepItemWidth,
158		frame.Height() - 2, false);
159	fSeparatorItem->SetEnabled(false);
160
161	bool added = AddItem(fSeparatorItem);
162
163	if (added)
164		SmartResize(frame.Width() - 1.0f, frame.Height());
165	else
166		SmartResize(frame.Width(), frame.Height());
167
168	return added;
169}
170
171
172bool
173TBarMenuBar::RemoveSeperatorItem()
174{
175	if (CountItems() < 2)
176		return false;
177
178	bool removed = false;
179
180	if (fSeparatorItem != NULL && RemoveItem(fSeparatorItem)) {
181		delete fSeparatorItem;
182		fSeparatorItem = NULL;
183		SmartResize(-1, -1);
184		removed = true;
185	}
186
187	return removed;
188}
189
190
191void
192TBarMenuBar::Draw(BRect updateRect)
193{
194	// want to skip the fancy BMenuBar drawing code.
195	BMenu::Draw(updateRect);
196}
197
198
199void
200TBarMenuBar::DrawBackground(BRect updateRect)
201{
202	BMenu::DrawBackground(updateRect);
203}
204
205
206void
207TBarMenuBar::MouseMoved(BPoint where, uint32 code, const BMessage* message)
208{
209	// the following code parallels that in ExpandoMenuBar for DnD tracking
210
211	if (!message) {
212		// force a cleanup
213		fBarView->DragStop(true);
214		BMenuBar::MouseMoved(where, code, message);
215		return;
216	}
217
218	switch (code) {
219		case B_ENTERED_VIEW:
220		{
221			BPoint loc;
222			uint32 buttons;
223			GetMouse(&loc, &buttons);
224			// attempt to start DnD tracking
225			if (message && buttons != 0) {
226				fBarView->CacheDragData(const_cast<BMessage*>(message));
227				MouseDown(loc);
228			}
229			break;
230		}
231	}
232	BMenuBar::MouseMoved(where, code, message);
233}
234
235
236static void
237init_tracking_hook(BMenuItem* item, bool (*hookFunction)(BMenu*, void*),
238	void* state)
239{
240	if (!item)
241		return;
242
243	BMenu* windowMenu = item->Submenu();
244	if (windowMenu) {
245		// have a menu, set the tracking hook
246		windowMenu->SetTrackingHook(hookFunction, state);
247	}
248}
249
250
251void
252TBarMenuBar::InitTrackingHook(bool (*hookFunction)(BMenu*, void*),
253	void* state, bool both)
254{
255	BPoint loc;
256	uint32 buttons;
257	GetMouse(&loc, &buttons);
258	// set the hook functions for the two menus
259	// will always have the deskbar menu
260	// may have the app menu as well (mini mode)
261	if (fDeskbarMenuItem->Frame().Contains(loc) || both)
262		init_tracking_hook(fDeskbarMenuItem, hookFunction, state);
263
264	if (fAppListMenuItem && (fAppListMenuItem->Frame().Contains(loc) || both))
265		init_tracking_hook(fAppListMenuItem, hookFunction, state);
266}
267