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);