From caf0a129d6be25e0fa439accc39a4879458e4ac2 Mon Sep 17 00:00:00 2001 From: John Scipione Date: Mon, 11 Apr 2016 11:56:45 -0700 Subject: [PATCH] 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 --- headers/private/tracker/IconMenuItem.h | 14 ++- src/kits/tracker/FindPanel.cpp | 8 +- src/kits/tracker/IconMenuItem.cpp | 137 +++++++++++++++++++++++-- src/kits/tracker/Utilities.cpp | 17 +++ src/kits/tracker/Utilities.h | 4 +- 5 files changed, 166 insertions(+), 14 deletions(-) diff --git a/headers/private/tracker/IconMenuItem.h b/headers/private/tracker/IconMenuItem.h index 3ac0b3e1de..af1a872137 100644 --- a/headers/private/tracker/IconMenuItem.h +++ b/headers/private/tracker/IconMenuItem.h @@ -58,16 +58,28 @@ class IconMenuItem : public PositionPassingMenuItem { const BNodeInfo* nodeInfo, icon_size which); IconMenuItem(BMenu*, BMessage*, const char* iconType, icon_size which); + IconMenuItem(BMessage* data); 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 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: BBitmap* fDeviceIcon; float fHeightDelta; + icon_size fWhich; - typedef BMenuItem _inherited; + typedef PositionPassingMenuItem _inherited; }; diff --git a/src/kits/tracker/FindPanel.cpp b/src/kits/tracker/FindPanel.cpp index 0f9fbf5576..0a29f3ca52 100644 --- a/src/kits/tracker/FindPanel.cpp +++ b/src/kits/tracker/FindPanel.cpp @@ -1839,10 +1839,12 @@ FindPanel::AddMimeTypesToMenu() { BMessage* itemMessage = new BMessage(kMIMETypeItem); 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()->ItemAt(0)->SetMarked(true); + firstItem->SetMarked(true); // add recent MIME types diff --git a/src/kits/tracker/IconMenuItem.cpp b/src/kits/tracker/IconMenuItem.cpp index 09c423f9d9..1d6475c22b 100644 --- a/src/kits/tracker/IconMenuItem.cpp +++ b/src/kits/tracker/IconMenuItem.cpp @@ -35,13 +35,16 @@ All rights reserved. //! Menu items with small icons. -#include "IconCache.h" #include "IconMenuItem.h" +#include #include #include +#include #include +#include "IconCache.h" + static 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), 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 // we invoke with a timeout @@ -267,7 +271,8 @@ IconMenuItem::IconMenuItem(const char* label, BMessage* message, : PositionPassingMenuItem(label, message), fDeviceIcon(NULL), - fHeightDelta(0) + fHeightDelta(0), + fWhich(which) { if (nodeInfo != NULL) { fDeviceIcon = new BBitmap(BRect(0, 0, which - 1, which - 1), @@ -290,7 +295,8 @@ IconMenuItem::IconMenuItem(const char* label, BMessage* message, : PositionPassingMenuItem(label, message), fDeviceIcon(NULL), - fHeightDelta(0) + fHeightDelta(0), + fWhich(which) { BMimeType mime(iconType); fDeviceIcon = new BBitmap(BRect(0, 0, which - 1, which - 1), @@ -316,7 +322,8 @@ IconMenuItem::IconMenuItem(BMenu* submenu, BMessage* message, : PositionPassingMenuItem(submenu, message), fDeviceIcon(NULL), - fHeightDelta(0) + fHeightDelta(0), + fWhich(which) { BMimeType mime(iconType); 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() { delete fDeviceIcon; @@ -360,9 +424,12 @@ void IconMenuItem::DrawContent() { BPoint drawPoint(ContentLocation()); - drawPoint.x += 20; + if (fDeviceIcon != NULL) + drawPoint.x += (float)fWhich + 4.0f; + if (fHeightDelta > 0) - drawPoint.y += ceil(fHeightDelta / 2); + drawPoint.y += ceilf(fHeightDelta / 2); + Menu()->MovePenTo(drawPoint); _inherited::DrawContent(); @@ -370,9 +437,9 @@ IconMenuItem::DrawContent() BPoint where(ContentLocation()); float deltaHeight = fHeightDelta < 0 ? -fHeightDelta : 0; - where.y += ceil(deltaHeight / 2); + where.y += ceilf(deltaHeight / 2); - if (fDeviceIcon) { + if (fDeviceIcon != NULL) { if (IsEnabled()) Menu()->SetDrawingMode(B_OP_ALPHA); else { @@ -385,3 +452,55 @@ IconMenuItem::DrawContent() 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(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(topLevelItem); + if (topLevelIconMenuItem == NULL) + return; + + // our topmost menu's item is an IconMenuItem + + // update the icon + topLevelIconMenuItem->SetIcon(fDeviceIcon); + menu->Invalidate(); +} diff --git a/src/kits/tracker/Utilities.cpp b/src/kits/tracker/Utilities.cpp index 2a9a322298..e2ad9dc46f 100644 --- a/src/kits/tracker/Utilities.cpp +++ b/src/kits/tracker/Utilities.cpp @@ -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 PositionPassingMenuItem::Invoke(BMessage* message) { diff --git a/src/kits/tracker/Utilities.h b/src/kits/tracker/Utilities.h index 62cf73cc54..ab0d708142 100644 --- a/src/kits/tracker/Utilities.h +++ b/src/kits/tracker/Utilities.h @@ -271,8 +271,10 @@ class PositionPassingMenuItem : public BMenuItem { public: PositionPassingMenuItem(const char* title, BMessage*, char shortcut = 0, uint32 modifiers = 0); - PositionPassingMenuItem(BMenu*, BMessage*); + PositionPassingMenuItem(BMessage* data); + + static BArchivable* Instantiate(BMessage* data); protected: virtual status_t Invoke(BMessage* = 0);