xref: /haiku/src/kits/tracker/IconMenuItem.cpp (revision 4f00613311d0bd6b70fa82ce19931c41f071ea4e)
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 trademarks
30 of Be Incorporated in the United States and other countries. Other brand product
31 names are registered trademarks or trademarks of their respective holders.
32 All rights reserved.
33 */
34 
35 // menu items with small icons.
36 
37 #include <Debug.h>
38 #include <Menu.h>
39 #include <NodeInfo.h>
40 
41 #include "IconCache.h"
42 #include "IconMenuItem.h"
43 
44 
45 ModelMenuItem::ModelMenuItem(const Model *model, const char *title,
46 	BMessage *message, char shortcut, uint32 modifiers,
47 	bool drawText, bool extraPad)
48 	:	BMenuItem(title, message, shortcut, modifiers),
49 		fModel(*model),
50 		fHeightDelta(0),
51 		fDrawText(drawText),
52 		fExtraPad(extraPad)
53 {
54 	ThrowOnInitCheckError(&fModel);
55 	//	The 'fExtraPad' field is used to when this menu item is added to
56 	//	a menubar instead of a menu. Menus and MenuBars space out items
57 	//	differently (more space around items in a menu). This class wants
58 	//	to be able to space item the same, no matter where they are. The
59 	//	fExtraPad field allows for that.
60 
61 	if (model->IsRoot())
62 		SetLabel(model->Name());
63 
64 	// ModelMenuItem is used in synchronously invoked menus, make sure
65 	// we invoke with a timeout
66 	SetTimeout(kSynchMenuInvokeTimeout);
67 }
68 
69 
70 ModelMenuItem::ModelMenuItem(const Model *model, BMenu *menu, bool drawText,
71 	bool extraPad)
72 	:	BMenuItem(menu),
73 		fModel(*model),
74 		fHeightDelta(0),
75 		fDrawText(drawText),
76 		fExtraPad(extraPad)
77 {
78 	ThrowOnInitCheckError(&fModel);
79 	// ModelMenuItem is used in synchronously invoked menus, make sure
80 	// we invoke with a timeout
81 	SetTimeout(kSynchMenuInvokeTimeout);
82 }
83 
84 
85 ModelMenuItem::~ModelMenuItem()
86 {
87 }
88 
89 
90 status_t
91 ModelMenuItem::SetEntry(const BEntry *entry)
92 {
93 	return fModel.SetTo(entry);
94 }
95 
96 
97 void
98 ModelMenuItem::DrawContent()
99 {
100 	if (fDrawText) {
101 		BPoint drawPoint(ContentLocation());
102 		drawPoint.x += 20 + (fExtraPad ? 6 : 0);
103 		if (fHeightDelta > 0)
104 			drawPoint.y += ceil(fHeightDelta / 2);
105 		Menu()->MovePenTo(drawPoint);
106 		_inherited::DrawContent();
107 	}
108 	DrawIcon();
109 }
110 
111 
112 void
113 ModelMenuItem::Highlight(bool hilited)
114 {
115 	_inherited::Highlight(hilited);
116 	DrawIcon();
117 }
118 
119 
120 static void
121 DimmedIconBlitter(BView *view, BPoint where, BBitmap *bitmap, void *)
122 {
123 	view->SetDrawingMode(B_OP_BLEND);
124 	view->DrawBitmap(bitmap, where);
125 	view->SetDrawingMode(B_OP_OVER);
126 }
127 
128 
129 void
130 ModelMenuItem::DrawIcon()
131 {
132 	Menu()->PushState();
133 
134 	BPoint where(ContentLocation());
135 	// center icon with text.
136 
137 	float deltaHeight = fHeightDelta < 0 ? -fHeightDelta : 0;
138 	where.y += ceil( deltaHeight/2 );
139 
140 	if (fExtraPad)
141 		where.x += 6;
142 
143 	Menu()->SetDrawingMode(B_OP_OVER);
144 	Menu()->SetLowColor(B_TRANSPARENT_32_BIT);
145 
146 	// draw small icon, synchronously
147 	if (IsEnabled())
148 		IconCache::sIconCache->Draw(fModel.ResolveIfLink(), Menu(), where,
149 			kNormalIcon, B_MINI_ICON);
150 	else {
151 		// dimmed, for now use a special blitter; icon cache should
152 		// know how to blit one eventually
153 		IconCache::sIconCache->SyncDraw(fModel.ResolveIfLink(), Menu(), where,
154 			kNormalIcon, B_MINI_ICON, DimmedIconBlitter);
155 	}
156 
157 	Menu()->PopState();
158 }
159 
160 
161 void
162 ModelMenuItem::GetContentSize(float *width, float *height)
163 {
164 	_inherited::GetContentSize(width, height);
165 	fHeightDelta = 16 - *height;
166 	if (*height < 16)
167 		*height = 16;
168 	*width = *width + 20 + (fExtraPad ? 18 : 0);
169 }
170 
171 
172 status_t
173 ModelMenuItem::Invoke(BMessage *message)
174 {
175 	if (!Menu())
176 		return B_ERROR;
177 
178 	if (!IsEnabled())
179 		return B_ERROR;
180 
181 	if (!message)
182 		message = Message();
183 
184 	if (!message)
185 		return B_BAD_VALUE;
186 
187 	BMessage clone(*message);
188 	clone.AddInt32("index", Menu()->IndexOf(this));
189 	clone.AddInt64("when", system_time());
190 	clone.AddPointer("source", this);
191 
192 	if ((modifiers() & B_OPTION_KEY) == 0)
193 		// if option not held, remove refs to close to prevent closing
194 		// parent window
195 		clone.RemoveData("nodeRefsToClose");
196 
197 	return BInvoker::Invoke(&clone);
198 }
199 
200 
201 //	#pragma mark -
202 
203 
204 SpecialModelMenuItem::SpecialModelMenuItem(const Model *model,BMenu *menu)
205 	: ModelMenuItem(model,menu)
206 {
207 }
208 
209 
210 void
211 SpecialModelMenuItem::DrawContent()
212 {
213 	Menu()->PushState();
214 
215 	BFont font;
216 	Menu()->GetFont(&font);
217 	font.SetFace(B_ITALIC_FACE);
218 	Menu()->SetFont(&font);
219 
220 	_inherited::DrawContent();
221 	Menu()->PopState();
222 }
223 
224 
225 //	#pragma mark -
226 
227 
228 IconMenuItem::IconMenuItem(const char *label, BMessage *message, BBitmap *icon)
229 	:	PositionPassingMenuItem(label, message),
230 		fDeviceIcon(icon)
231 {
232 	// IconMenuItem is used in synchronously invoked menus, make sure
233 	// we invoke with a timeout
234 	SetTimeout(kSynchMenuInvokeTimeout);
235 }
236 
237 
238 IconMenuItem::IconMenuItem(const char *label, BMessage *message,
239 	const BNodeInfo *nodeInfo, icon_size which)
240 	:	PositionPassingMenuItem(label, message),
241 		fDeviceIcon(NULL)
242 {
243 	if (nodeInfo) {
244 		fDeviceIcon = new BBitmap(BRect(0, 0, which - 1, which - 1), B_COLOR_8_BIT);
245 		if (nodeInfo->GetTrackerIcon(fDeviceIcon, B_MINI_ICON)) {
246 			delete fDeviceIcon;
247 			fDeviceIcon = NULL;
248 		}
249 	}
250 
251 	// IconMenuItem is used in synchronously invoked menus, make sure
252 	// we invoke with a timeout
253 	SetTimeout(kSynchMenuInvokeTimeout);
254 }
255 
256 
257 IconMenuItem::IconMenuItem(const char *label, BMessage *message,
258 	const char *iconType, icon_size which)
259 	:	PositionPassingMenuItem(label, message),
260 		fDeviceIcon(NULL)
261 {
262 	BMimeType mime(iconType);
263 	fDeviceIcon = new BBitmap(BRect(0, 0, which - 1, which - 1), B_COLOR_8_BIT);
264 
265 	if (mime.GetIcon(fDeviceIcon, which) != B_OK) {
266 		delete fDeviceIcon;
267 		fDeviceIcon = NULL;
268 	}
269 
270 	// IconMenuItem is used in synchronously invoked menus, make sure
271 	// we invoke with a timeout
272 	SetTimeout(kSynchMenuInvokeTimeout);
273 }
274 
275 
276 IconMenuItem::IconMenuItem(BMenu *submenu, BMessage *message,
277 	const char *iconType, icon_size which)
278 	:	PositionPassingMenuItem(submenu, message),
279 		fDeviceIcon(NULL)
280 {
281 	BMimeType mime(iconType);
282 	fDeviceIcon = new BBitmap(BRect(0, 0, which - 1, which - 1), B_COLOR_8_BIT);
283 
284 	if (mime.GetIcon(fDeviceIcon, which) != B_OK) {
285 		delete fDeviceIcon;
286 		fDeviceIcon = NULL;
287 	}
288 
289 	// IconMenuItem is used in synchronously invoked menus, make sure
290 	// we invoke with a timeout
291 	SetTimeout(kSynchMenuInvokeTimeout);
292 }
293 
294 
295 IconMenuItem::~IconMenuItem()
296 {
297 	delete fDeviceIcon;
298 }
299 
300 
301 void
302 IconMenuItem::GetContentSize(float *width, float *height)
303 {
304 	_inherited::GetContentSize(width, height);
305 	*width += 20;
306 	*height += 3;
307 }
308 
309 
310 void
311 IconMenuItem::DrawContent()
312 {
313 	BPoint drawPoint(ContentLocation());
314 	drawPoint.x += 20;
315 	Menu()->MovePenTo(drawPoint);
316 	_inherited::DrawContent();
317 
318 	BPoint where(ContentLocation());
319 	where.y = Frame().top;
320 
321 	if (fDeviceIcon) {
322 		if (IsEnabled())
323 			Menu()->SetDrawingMode(B_OP_OVER);
324 		else
325 			Menu()->SetDrawingMode(B_OP_BLEND);
326 
327 		Menu()->DrawBitmapAsync(fDeviceIcon, where);
328 	}
329 }
330 
331