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