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.
35 //! Menu items with small icons.
38 #include "IconMenuItem.h"
40 #include <ControlLook.h>
43 #include <MenuField.h>
46 #include "IconCache.h"
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
);
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
),
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.
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
,
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()
118 ModelMenuItem::SetEntry(const BEntry
* entry
)
120 return fModel
.SetTo(entry
);
125 ModelMenuItem::DrawContent()
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();
140 ModelMenuItem::Highlight(bool hilited
)
142 _inherited::Highlight(hilited
);
148 ModelMenuItem::DrawIcon()
152 BPoint
where(ContentLocation());
153 // center icon with text.
155 float deltaHeight
= fHeightDelta
< 0 ? -fHeightDelta
: 0;
156 where
.y
+= ceil(deltaHeight
/ 2);
161 Menu()->SetDrawingMode(B_OP_OVER
);
162 Menu()->SetLowColor(B_TRANSPARENT_32_BIT
);
164 // draw small icon, synchronously
166 IconCache::sIconCache
->Draw(fModel
.ResolveIfLink(), Menu(), where
,
167 kNormalIcon
, B_MINI_ICON
);
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
);
180 ModelMenuItem::GetContentSize(float* width
, float* height
)
182 _inherited::GetContentSize(width
, height
);
183 fHeightDelta
= 16 - *height
;
186 *width
= *width
+ 20 + (fExtraPad
? 18 : 0);
191 ModelMenuItem::Invoke(BMessage
* message
)
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
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
)
235 SpecialModelMenuItem::DrawContent()
240 Menu()->GetFont(&font
);
241 font
.SetFace(B_ITALIC_FACE
);
242 Menu()->SetFont(&font
);
244 _inherited::DrawContent();
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
,
259 PositionPassingMenuItem(label
, message
),
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
),
280 if (nodeInfo
!= NULL
) {
281 fDeviceIcon
= new BBitmap(BRect(0, 0, which
- 1, which
- 1),
284 if (nodeInfo
->GetTrackerIcon(fDeviceIcon
, B_MINI_ICON
) != B_OK
) {
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
),
304 BMimeType
mime(iconType
);
305 fDeviceIcon
= new BBitmap(BRect(0, 0, which
- 1, which
- 1),
308 if (mime
.GetIcon(fDeviceIcon
, which
) != B_OK
) {
310 mime
.GetSupertype(&super
);
311 if (super
.GetIcon(fDeviceIcon
, which
) != B_OK
) {
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
),
331 BMimeType
mime(iconType
);
332 fDeviceIcon
= new BBitmap(BRect(0, 0, which
- 1, which
- 1),
335 if (mime
.GetIcon(fDeviceIcon
, which
) != B_OK
) {
337 mime
.GetSupertype(&super
);
338 if (super
.GetIcon(fDeviceIcon
, which
) != B_OK
) {
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
),
358 fWhich
= (icon_size
)data
->GetInt32("_which", B_MINI_ICON
);
360 fDeviceIcon
= new BBitmap(BRect(0, 0, fWhich
- 1, fWhich
- 1),
363 if (data
->HasData("_deviceIconBits", B_RAW_TYPE
)) {
366 if (data
->FindData("_deviceIconBits", B_RAW_TYPE
, &bits
, &numBytes
)
368 fDeviceIcon
->SetBits(bits
, numBytes
, (int32
)0,
374 // IconMenuItem is used in synchronously invoked menus, make sure
375 // we invoke with a timeout
376 SetTimeout(kSynchMenuInvokeTimeout
);
381 IconMenuItem::Instantiate(BMessage
* data
)
383 //if (validate_instantiation(data, "IconMenuItem"))
384 return new IconMenuItem(data
);
391 IconMenuItem::Archive(BMessage
* data
, bool deep
) const
393 status_t result
= PositionPassingMenuItem::Archive(data
, deep
);
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());
407 IconMenuItem::~IconMenuItem()
414 IconMenuItem::GetContentSize(float* width
, float* height
)
416 _inherited::GetContentSize(width
, height
);
418 fHeightDelta
= 16 - *height
;
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();
441 BPoint
where(ContentLocation());
442 float deltaHeight
= fHeightDelta
< 0 ? -fHeightDelta
: 0;
443 where
.y
+= ceilf(deltaHeight
/ 2);
445 if (fDeviceIcon
!= NULL
) {
447 Menu()->SetDrawingMode(B_OP_ALPHA
);
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
);
461 IconMenuItem::SetMarked(bool mark
)
463 _inherited::SetMarked(mark
);
468 // we are marking the item
470 BMenu
* menu
= Menu();
474 // we have a parent menu
477 while ((_menu
= _menu
->Supermenu()) != NULL
)
480 // went up the hierarchy to found the topmost menu
482 if (menu
== NULL
|| menu
->Parent() == NULL
)
485 // our topmost menu has a parent
487 if (dynamic_cast<BMenuField
*>(menu
->Parent()) == NULL
)
490 // our topmost menu's parent is a BMenuField
492 BMenuItem
* topLevelItem
= menu
->ItemAt((int32
)0);
494 if (topLevelItem
== NULL
)
497 // our topmost menu has a menu item
499 IconMenuItem
* topLevelIconMenuItem
500 = dynamic_cast<IconMenuItem
*>(topLevelItem
);
501 if (topLevelIconMenuItem
== NULL
)
504 // our topmost menu's item is an IconMenuItem
507 topLevelIconMenuItem
->SetIcon(fDeviceIcon
);
513 IconMenuItem::SetIcon(BBitmap
* icon
)
516 if (fDeviceIcon
!= NULL
)
519 fDeviceIcon
= new BBitmap(BRect(0, 0, fWhich
- 1, fWhich
- 1),
521 fDeviceIcon
->SetBits(icon
->Bits(), icon
->BitsLength(), 0,