btrfs: Attempt to fix GCC2 build.
[haiku.git] / src / kits / tracker / IconMenuItem.cpp
blob03dcee79dc0dbfb706cc296db2cf6ae5ad7a605c
1 /*
2 Open Tracker License
4 Terms and Conditions
6 Copyright (c) 1991-2000, Be Incorporated. All rights reserved.
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:
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.
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.
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.
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.
35 //! Menu items with small icons.
38 #include "IconMenuItem.h"
40 #include <ControlLook.h>
41 #include <Debug.h>
42 #include <Menu.h>
43 #include <MenuField.h>
44 #include <NodeInfo.h>
46 #include "IconCache.h"
49 static void
50 DimmedIconBlitter(BView* view, BPoint where, BBitmap* bitmap, void*)
52 if (bitmap->ColorSpace() == B_RGBA32) {
53 rgb_color oldHighColor = view->HighColor();
54 view->SetHighColor(0, 0, 0, 128);
55 view->SetDrawingMode(B_OP_ALPHA);
56 view->SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_OVERLAY);
57 view->DrawBitmap(bitmap, where);
58 view->SetHighColor(oldHighColor);
59 } else {
60 view->SetDrawingMode(B_OP_BLEND);
61 view->DrawBitmap(bitmap, where);
63 view->SetDrawingMode(B_OP_OVER);
67 // #pragma mark - ModelMenuItem
70 ModelMenuItem::ModelMenuItem(const Model* model, const char* title,
71 BMessage* message, char shortcut, uint32 modifiers,
72 bool drawText, bool extraPad)
74 BMenuItem(title, message, shortcut, modifiers),
75 fModel(*model),
76 fHeightDelta(0),
77 fDrawText(drawText),
78 fExtraPad(extraPad)
80 ThrowOnInitCheckError(&fModel);
81 // The 'fExtraPad' field is used to when this menu item is added to
82 // a menubar instead of a menu. Menus and MenuBars space out items
83 // differently (more space around items in a menu). This class wants
84 // to be able to space item the same, no matter where they are. The
85 // fExtraPad field allows for that.
87 if (model->IsRoot())
88 SetLabel(model->Name());
90 // ModelMenuItem is used in synchronously invoked menus, make sure
91 // we invoke with a timeout
92 SetTimeout(kSynchMenuInvokeTimeout);
96 ModelMenuItem::ModelMenuItem(const Model* model, BMenu* menu, bool drawText,
97 bool extraPad)
99 BMenuItem(menu),
100 fModel(*model),
101 fHeightDelta(0),
102 fDrawText(drawText),
103 fExtraPad(extraPad)
105 ThrowOnInitCheckError(&fModel);
106 // ModelMenuItem is used in synchronously invoked menus, make sure
107 // we invoke with a timeout
108 SetTimeout(kSynchMenuInvokeTimeout);
112 ModelMenuItem::~ModelMenuItem()
117 status_t
118 ModelMenuItem::SetEntry(const BEntry* entry)
120 return fModel.SetTo(entry);
124 void
125 ModelMenuItem::DrawContent()
127 if (fDrawText) {
128 BPoint drawPoint(ContentLocation());
129 drawPoint.x += 20 + (fExtraPad ? 6 : 0);
130 if (fHeightDelta > 0)
131 drawPoint.y += ceil(fHeightDelta / 2);
132 Menu()->MovePenTo(drawPoint);
133 _inherited::DrawContent();
135 DrawIcon();
139 void
140 ModelMenuItem::Highlight(bool hilited)
142 _inherited::Highlight(hilited);
143 DrawIcon();
147 void
148 ModelMenuItem::DrawIcon()
150 Menu()->PushState();
152 BPoint where(ContentLocation());
153 // center icon with text.
155 float deltaHeight = fHeightDelta < 0 ? -fHeightDelta : 0;
156 where.y += ceil(deltaHeight / 2);
158 if (fExtraPad)
159 where.x += 6;
161 Menu()->SetDrawingMode(B_OP_OVER);
162 Menu()->SetLowColor(B_TRANSPARENT_32_BIT);
164 // draw small icon, synchronously
165 if (IsEnabled()) {
166 IconCache::sIconCache->Draw(fModel.ResolveIfLink(), Menu(), where,
167 kNormalIcon, B_MINI_ICON);
168 } else {
169 // dimmed, for now use a special blitter; icon cache should
170 // know how to blit one eventually
171 IconCache::sIconCache->SyncDraw(fModel.ResolveIfLink(), Menu(), where,
172 kNormalIcon, B_MINI_ICON, DimmedIconBlitter);
175 Menu()->PopState();
179 void
180 ModelMenuItem::GetContentSize(float* width, float* height)
182 _inherited::GetContentSize(width, height);
183 fHeightDelta = 16 - *height;
184 if (*height < 16)
185 *height = 16;
186 *width = *width + 20 + (fExtraPad ? 18 : 0);
190 status_t
191 ModelMenuItem::Invoke(BMessage* message)
193 if (Menu() == NULL)
194 return B_ERROR;
196 if (!IsEnabled())
197 return B_ERROR;
199 if (message == NULL)
200 message = Message();
202 if (message == NULL)
203 return B_BAD_VALUE;
205 BMessage clone(*message);
206 clone.AddInt32("index", Menu()->IndexOf(this));
207 clone.AddInt64("when", system_time());
208 clone.AddPointer("source", this);
210 if ((modifiers() & B_OPTION_KEY) == 0) {
211 // if option not held, remove refs to close to prevent closing
212 // parent window
213 clone.RemoveData("nodeRefsToClose");
216 return BInvoker::Invoke(&clone);
220 // #pragma mark - SpecialModelMenuItem
223 /*! A ModelMenuItem subclass that draws its label in italics.
225 It's used for example in the "Copy To" menu to indicate some special
226 folders like the parent folder.
228 SpecialModelMenuItem::SpecialModelMenuItem(const Model* model, BMenu* menu)
229 : ModelMenuItem(model, menu)
234 void
235 SpecialModelMenuItem::DrawContent()
237 Menu()->PushState();
239 BFont font;
240 Menu()->GetFont(&font);
241 font.SetFace(B_ITALIC_FACE);
242 Menu()->SetFont(&font);
244 _inherited::DrawContent();
245 Menu()->PopState();
249 // #pragma mark - IconMenuItem
252 /*! A menu item that draws an icon alongside the label.
254 It's currently used in the mount and new file template menus.
256 IconMenuItem::IconMenuItem(const char* label, BMessage* message, BBitmap* icon,
257 icon_size which)
259 PositionPassingMenuItem(label, message),
260 fDeviceIcon(NULL),
261 fHeightDelta(0),
262 fWhich(which)
264 SetIcon(icon);
266 // IconMenuItem is used in synchronously invoked menus, make sure
267 // we invoke with a timeout
268 SetTimeout(kSynchMenuInvokeTimeout);
272 IconMenuItem::IconMenuItem(const char* label, BMessage* message,
273 const BNodeInfo* nodeInfo, icon_size which)
275 PositionPassingMenuItem(label, message),
276 fDeviceIcon(NULL),
277 fHeightDelta(0),
278 fWhich(which)
280 if (nodeInfo != NULL) {
281 fDeviceIcon = new BBitmap(BRect(0, 0, which - 1, which - 1),
282 kDefaultIconDepth);
284 if (nodeInfo->GetTrackerIcon(fDeviceIcon, B_MINI_ICON) != B_OK) {
285 delete fDeviceIcon;
286 fDeviceIcon = NULL;
290 // IconMenuItem is used in synchronously invoked menus, make sure
291 // we invoke with a timeout
292 SetTimeout(kSynchMenuInvokeTimeout);
296 IconMenuItem::IconMenuItem(const char* label, BMessage* message,
297 const char* iconType, icon_size which)
299 PositionPassingMenuItem(label, message),
300 fDeviceIcon(NULL),
301 fHeightDelta(0),
302 fWhich(which)
304 BMimeType mime(iconType);
305 fDeviceIcon = new BBitmap(BRect(0, 0, which - 1, which - 1),
306 kDefaultIconDepth);
308 if (mime.GetIcon(fDeviceIcon, which) != B_OK) {
309 BMimeType super;
310 mime.GetSupertype(&super);
311 if (super.GetIcon(fDeviceIcon, which) != B_OK) {
312 delete fDeviceIcon;
313 fDeviceIcon = NULL;
317 // IconMenuItem is used in synchronously invoked menus, make sure
318 // we invoke with a timeout
319 SetTimeout(kSynchMenuInvokeTimeout);
323 IconMenuItem::IconMenuItem(BMenu* submenu, BMessage* message,
324 const char* iconType, icon_size which)
326 PositionPassingMenuItem(submenu, message),
327 fDeviceIcon(NULL),
328 fHeightDelta(0),
329 fWhich(which)
331 BMimeType mime(iconType);
332 fDeviceIcon = new BBitmap(BRect(0, 0, which - 1, which - 1),
333 kDefaultIconDepth);
335 if (mime.GetIcon(fDeviceIcon, which) != B_OK) {
336 BMimeType super;
337 mime.GetSupertype(&super);
338 if (super.GetIcon(fDeviceIcon, which) != B_OK) {
339 delete fDeviceIcon;
340 fDeviceIcon = NULL;
344 // IconMenuItem is used in synchronously invoked menus, make sure
345 // we invoke with a timeout
346 SetTimeout(kSynchMenuInvokeTimeout);
350 IconMenuItem::IconMenuItem(BMessage* data)
352 PositionPassingMenuItem(data),
353 fDeviceIcon(NULL),
354 fHeightDelta(0),
355 fWhich(B_MINI_ICON)
357 if (data != NULL) {
358 fWhich = (icon_size)data->GetInt32("_which", B_MINI_ICON);
360 fDeviceIcon = new BBitmap(BRect(0, 0, fWhich - 1, fWhich - 1),
361 kDefaultIconDepth);
363 if (data->HasData("_deviceIconBits", B_RAW_TYPE)) {
364 ssize_t numBytes;
365 const void* bits;
366 if (data->FindData("_deviceIconBits", B_RAW_TYPE, &bits, &numBytes)
367 == B_OK) {
368 fDeviceIcon->SetBits(bits, numBytes, (int32)0,
369 kDefaultIconDepth);
374 // IconMenuItem is used in synchronously invoked menus, make sure
375 // we invoke with a timeout
376 SetTimeout(kSynchMenuInvokeTimeout);
380 BArchivable*
381 IconMenuItem::Instantiate(BMessage* data)
383 //if (validate_instantiation(data, "IconMenuItem"))
384 return new IconMenuItem(data);
386 return NULL;
390 status_t
391 IconMenuItem::Archive(BMessage* data, bool deep) const
393 status_t result = PositionPassingMenuItem::Archive(data, deep);
395 if (result == B_OK)
396 result = data->AddInt32("_which", (int32)fWhich);
398 if (result == B_OK && fDeviceIcon != NULL) {
399 result = data->AddData("_deviceIconBits", B_RAW_TYPE,
400 fDeviceIcon->Bits(), fDeviceIcon->BitsLength());
403 return result;
407 IconMenuItem::~IconMenuItem()
409 delete fDeviceIcon;
413 void
414 IconMenuItem::GetContentSize(float* width, float* height)
416 _inherited::GetContentSize(width, height);
418 fHeightDelta = 16 - *height;
419 if (*height < 16)
420 *height = 16;
422 *width += 20;
426 void
427 IconMenuItem::DrawContent()
429 BPoint drawPoint(ContentLocation());
430 if (fDeviceIcon != NULL)
431 drawPoint.x += (float)fWhich + 4.0f;
433 if (fHeightDelta > 0)
434 drawPoint.y += ceilf(fHeightDelta / 2);
436 Menu()->MovePenTo(drawPoint);
437 _inherited::DrawContent();
439 Menu()->PushState();
441 BPoint where(ContentLocation());
442 float deltaHeight = fHeightDelta < 0 ? -fHeightDelta : 0;
443 where.y += ceilf(deltaHeight / 2);
445 if (fDeviceIcon != NULL) {
446 if (IsEnabled())
447 Menu()->SetDrawingMode(B_OP_ALPHA);
448 else {
449 Menu()->SetDrawingMode(B_OP_ALPHA);
450 Menu()->SetHighColor(0, 0, 0, 64);
451 Menu()->SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_OVERLAY);
453 Menu()->DrawBitmapAsync(fDeviceIcon, where);
456 Menu()->PopState();
460 void
461 IconMenuItem::SetMarked(bool mark)
463 _inherited::SetMarked(mark);
465 if (!mark)
466 return;
468 // we are marking the item
470 BMenu* menu = Menu();
471 if (menu == NULL)
472 return;
474 // we have a parent menu
476 BMenu* _menu = menu;
477 while ((_menu = _menu->Supermenu()) != NULL)
478 menu = _menu;
480 // went up the hierarchy to found the topmost menu
482 if (menu == NULL || menu->Parent() == NULL)
483 return;
485 // our topmost menu has a parent
487 if (dynamic_cast<BMenuField*>(menu->Parent()) == NULL)
488 return;
490 // our topmost menu's parent is a BMenuField
492 BMenuItem* topLevelItem = menu->ItemAt((int32)0);
494 if (topLevelItem == NULL)
495 return;
497 // our topmost menu has a menu item
499 IconMenuItem* topLevelIconMenuItem
500 = dynamic_cast<IconMenuItem*>(topLevelItem);
501 if (topLevelIconMenuItem == NULL)
502 return;
504 // our topmost menu's item is an IconMenuItem
506 // update the icon
507 topLevelIconMenuItem->SetIcon(fDeviceIcon);
508 menu->Invalidate();
512 void
513 IconMenuItem::SetIcon(BBitmap* icon)
515 if (icon != NULL) {
516 if (fDeviceIcon != NULL)
517 delete fDeviceIcon;
519 fDeviceIcon = new BBitmap(BRect(0, 0, fWhich - 1, fWhich - 1),
520 icon->ColorSpace());
521 fDeviceIcon->SetBits(icon->Bits(), icon->BitsLength(), 0,
522 icon->ColorSpace());
523 } else {
524 delete fDeviceIcon;
525 fDeviceIcon = NULL;