Tracker: Draw IconMenuItem in closed state

Add an Icon() and SetIcon() method. Override SetMarked() to set the
parent menu field icon.

Don't move the label right if icon is NULL. Make the first menu item
an IconMenuItem with a NULL icon. This allows the icon to draw in the
closed menu state.

icon gets updated even if you select an item in a submenu
This commit is contained in:
John Scipione
2016-07-31 19:42:39 -07:00
parent 837d7501ef
commit caf0a129d6
5 changed files with 166 additions and 14 deletions
+13 -1
View File
@@ -58,16 +58,28 @@ class IconMenuItem : public PositionPassingMenuItem {
const BNodeInfo* nodeInfo, icon_size which); const BNodeInfo* nodeInfo, icon_size which);
IconMenuItem(BMenu*, BMessage*, const char* iconType, IconMenuItem(BMenu*, BMessage*, const char* iconType,
icon_size which); icon_size which);
IconMenuItem(BMessage* data);
virtual ~IconMenuItem(); virtual ~IconMenuItem();
static BArchivable* Instantiate(BMessage* data);
virtual status_t Archive(BMessage* data, bool deep = true) const;
virtual void GetContentSize(float* width, float* height); virtual void GetContentSize(float* width, float* height);
virtual void DrawContent(); virtual void DrawContent();
virtual void SetMarked(bool mark);
virtual void SetIcon(BBitmap* icon) { fDeviceIcon = icon; };
BBitmap* Icon() const { return fDeviceIcon; };
virtual void SetIconSize(icon_size which) { fWhich = which; };
icon_size IconSize() const { return fWhich; };
private: private:
BBitmap* fDeviceIcon; BBitmap* fDeviceIcon;
float fHeightDelta; float fHeightDelta;
icon_size fWhich;
typedef BMenuItem _inherited; typedef PositionPassingMenuItem _inherited;
}; };
+5 -3
View File
@@ -1839,10 +1839,12 @@ FindPanel::AddMimeTypesToMenu()
{ {
BMessage* itemMessage = new BMessage(kMIMETypeItem); BMessage* itemMessage = new BMessage(kMIMETypeItem);
itemMessage->AddString("mimetype", kAllMimeTypes); itemMessage->AddString("mimetype", kAllMimeTypes);
MimeTypeMenu()->AddItem(
new BMenuItem(B_TRANSLATE("All files and folders"), itemMessage)); IconMenuItem* firstItem = new IconMenuItem(
B_TRANSLATE("All files and folders"), itemMessage, NULL);
MimeTypeMenu()->AddItem(firstItem);
MimeTypeMenu()->AddSeparatorItem(); MimeTypeMenu()->AddSeparatorItem();
MimeTypeMenu()->ItemAt(0)->SetMarked(true); firstItem->SetMarked(true);
// add recent MIME types // add recent MIME types
+128 -9
View File
@@ -35,13 +35,16 @@ All rights reserved.
//! Menu items with small icons. //! Menu items with small icons.
#include "IconCache.h"
#include "IconMenuItem.h" #include "IconMenuItem.h"
#include <ControlLook.h>
#include <Debug.h> #include <Debug.h>
#include <Menu.h> #include <Menu.h>
#include <MenuField.h>
#include <NodeInfo.h> #include <NodeInfo.h>
#include "IconCache.h"
static void static void
DimmedIconBlitter(BView* view, BPoint where, BBitmap* bitmap, void*) DimmedIconBlitter(BView* view, BPoint where, BBitmap* bitmap, void*)
@@ -254,7 +257,8 @@ IconMenuItem::IconMenuItem(const char* label, BMessage* message, BBitmap* icon)
: :
PositionPassingMenuItem(label, message), PositionPassingMenuItem(label, message),
fDeviceIcon(icon), fDeviceIcon(icon),
fHeightDelta(0) fHeightDelta(0),
fWhich(icon ? (icon_size)icon->Bounds().IntegerWidth() : B_MINI_ICON)
{ {
// IconMenuItem is used in synchronously invoked menus, make sure // IconMenuItem is used in synchronously invoked menus, make sure
// we invoke with a timeout // we invoke with a timeout
@@ -267,7 +271,8 @@ IconMenuItem::IconMenuItem(const char* label, BMessage* message,
: :
PositionPassingMenuItem(label, message), PositionPassingMenuItem(label, message),
fDeviceIcon(NULL), fDeviceIcon(NULL),
fHeightDelta(0) fHeightDelta(0),
fWhich(which)
{ {
if (nodeInfo != NULL) { if (nodeInfo != NULL) {
fDeviceIcon = new BBitmap(BRect(0, 0, which - 1, which - 1), fDeviceIcon = new BBitmap(BRect(0, 0, which - 1, which - 1),
@@ -290,7 +295,8 @@ IconMenuItem::IconMenuItem(const char* label, BMessage* message,
: :
PositionPassingMenuItem(label, message), PositionPassingMenuItem(label, message),
fDeviceIcon(NULL), fDeviceIcon(NULL),
fHeightDelta(0) fHeightDelta(0),
fWhich(which)
{ {
BMimeType mime(iconType); BMimeType mime(iconType);
fDeviceIcon = new BBitmap(BRect(0, 0, which - 1, which - 1), fDeviceIcon = new BBitmap(BRect(0, 0, which - 1, which - 1),
@@ -316,7 +322,8 @@ IconMenuItem::IconMenuItem(BMenu* submenu, BMessage* message,
: :
PositionPassingMenuItem(submenu, message), PositionPassingMenuItem(submenu, message),
fDeviceIcon(NULL), fDeviceIcon(NULL),
fHeightDelta(0) fHeightDelta(0),
fWhich(which)
{ {
BMimeType mime(iconType); BMimeType mime(iconType);
fDeviceIcon = new BBitmap(BRect(0, 0, which - 1, which - 1), fDeviceIcon = new BBitmap(BRect(0, 0, which - 1, which - 1),
@@ -337,6 +344,63 @@ IconMenuItem::IconMenuItem(BMenu* submenu, BMessage* message,
} }
IconMenuItem::IconMenuItem(BMessage* data)
:
PositionPassingMenuItem(data),
fDeviceIcon(NULL),
fHeightDelta(0),
fWhich(B_MINI_ICON)
{
if (data != NULL) {
fWhich = (icon_size)data->GetInt32("_which", B_MINI_ICON);
fDeviceIcon = new BBitmap(BRect(0, 0, fWhich - 1, fWhich - 1),
kDefaultIconDepth);
if (data->HasData("_deviceIconBits", B_RAW_TYPE)) {
ssize_t numBytes;
const void* bits;
if (data->FindData("_deviceIconBits", B_RAW_TYPE, &bits, &numBytes)
== B_OK) {
fDeviceIcon->SetBits(bits, numBytes, (int32)0,
kDefaultIconDepth);
}
}
}
// IconMenuItem is used in synchronously invoked menus, make sure
// we invoke with a timeout
SetTimeout(kSynchMenuInvokeTimeout);
}
BArchivable*
IconMenuItem::Instantiate(BMessage* data)
{
//if (validate_instantiation(data, "IconMenuItem"))
return new IconMenuItem(data);
return NULL;
}
status_t
IconMenuItem::Archive(BMessage* data, bool deep) const
{
status_t result = PositionPassingMenuItem::Archive(data, deep);
if (result == B_OK)
result = data->AddInt32("_which", (int32)fWhich);
if (result == B_OK && fDeviceIcon != NULL) {
result = data->AddData("_deviceIconBits", B_RAW_TYPE,
fDeviceIcon->Bits(), fDeviceIcon->BitsLength());
}
return result;
}
IconMenuItem::~IconMenuItem() IconMenuItem::~IconMenuItem()
{ {
delete fDeviceIcon; delete fDeviceIcon;
@@ -360,9 +424,12 @@ void
IconMenuItem::DrawContent() IconMenuItem::DrawContent()
{ {
BPoint drawPoint(ContentLocation()); BPoint drawPoint(ContentLocation());
drawPoint.x += 20; if (fDeviceIcon != NULL)
drawPoint.x += (float)fWhich + 4.0f;
if (fHeightDelta > 0) if (fHeightDelta > 0)
drawPoint.y += ceil(fHeightDelta / 2); drawPoint.y += ceilf(fHeightDelta / 2);
Menu()->MovePenTo(drawPoint); Menu()->MovePenTo(drawPoint);
_inherited::DrawContent(); _inherited::DrawContent();
@@ -370,9 +437,9 @@ IconMenuItem::DrawContent()
BPoint where(ContentLocation()); BPoint where(ContentLocation());
float deltaHeight = fHeightDelta < 0 ? -fHeightDelta : 0; float deltaHeight = fHeightDelta < 0 ? -fHeightDelta : 0;
where.y += ceil(deltaHeight / 2); where.y += ceilf(deltaHeight / 2);
if (fDeviceIcon) { if (fDeviceIcon != NULL) {
if (IsEnabled()) if (IsEnabled())
Menu()->SetDrawingMode(B_OP_ALPHA); Menu()->SetDrawingMode(B_OP_ALPHA);
else { else {
@@ -385,3 +452,55 @@ IconMenuItem::DrawContent()
Menu()->PopState(); Menu()->PopState();
} }
void
IconMenuItem::SetMarked(bool mark)
{
_inherited::SetMarked(mark);
if (!mark)
return;
// we are marking the item
BMenu* menu = Menu();
if (menu == NULL)
return;
// we have a parent menu
BMenu* _menu = menu;
while ((_menu = _menu->Supermenu()) != NULL)
menu = _menu;
// went up the hierarchy to found the topmost menu
if (menu == NULL || menu->Parent() == NULL)
return;
// our topmost menu has a parent
if (dynamic_cast<BMenuField*>(menu->Parent()) == NULL)
return;
// our topmost menu's parent is a BMenuField
BMenuItem* topLevelItem = menu->ItemAt((int32)0);
if (topLevelItem == NULL)
return;
// our topmost menu has a menu item
IconMenuItem* topLevelIconMenuItem
= dynamic_cast<IconMenuItem*>(topLevelItem);
if (topLevelIconMenuItem == NULL)
return;
// our topmost menu's item is an IconMenuItem
// update the icon
topLevelIconMenuItem->SetIcon(fDeviceIcon);
menu->Invalidate();
}
+17
View File
@@ -1545,6 +1545,23 @@ PositionPassingMenuItem::PositionPassingMenuItem(BMenu* menu, BMessage* message)
} }
PositionPassingMenuItem::PositionPassingMenuItem(BMessage* data)
:
BMenuItem(data)
{
}
BArchivable*
PositionPassingMenuItem::Instantiate(BMessage* data)
{
if (validate_instantiation(data, "PositionPassingMenuItem"))
return new PositionPassingMenuItem(data);
return NULL;
}
status_t status_t
PositionPassingMenuItem::Invoke(BMessage* message) PositionPassingMenuItem::Invoke(BMessage* message)
{ {
+3 -1
View File
@@ -271,8 +271,10 @@ class PositionPassingMenuItem : public BMenuItem {
public: public:
PositionPassingMenuItem(const char* title, BMessage*, PositionPassingMenuItem(const char* title, BMessage*,
char shortcut = 0, uint32 modifiers = 0); char shortcut = 0, uint32 modifiers = 0);
PositionPassingMenuItem(BMenu*, BMessage*); PositionPassingMenuItem(BMenu*, BMessage*);
PositionPassingMenuItem(BMessage* data);
static BArchivable* Instantiate(BMessage* data);
protected: protected:
virtual status_t Invoke(BMessage* = 0); virtual status_t Invoke(BMessage* = 0);