From 3c7376c1a6e21829d0220a2b1d5ca694e01fc546 Mon Sep 17 00:00:00 2001 From: Humdinger Date: Mon, 14 Oct 2024 07:44:41 +0200 Subject: [PATCH] Add source files for IconMenuItem Forgot to add those before... --- source/IconMenuItem.cpp | 298 ++++++++++++++++++++++++++++++++++++++++ source/IconMenuItem.h | 51 +++++++ 2 files changed, 349 insertions(+) create mode 100644 source/IconMenuItem.cpp create mode 100644 source/IconMenuItem.h diff --git a/source/IconMenuItem.cpp b/source/IconMenuItem.cpp new file mode 100644 index 0000000..56e8b90 --- /dev/null +++ b/source/IconMenuItem.cpp @@ -0,0 +1,298 @@ +/* + * Copyright 2023 Nexus6 + * All rights reserved. Distributed under the terms of the MIT license. + * Parts are taken from the IconMenuItem class from Haiku (Tracker) under the + * Open Tracker Licence + * Copyright (c) 1991-2000, Be Incorporated. All rights reserved. + * + * dospuntos (Johan Wagenheim) + */ + +#include "IconMenuItem.h" + +#include +#include +#include +#include +#include + + +// #include "IconCache.h" + +IconMenuItem::IconMenuItem(const char* label, BMessage* message, BBitmap* icon, icon_size which) + : BMenuItem(label, message), + fDeviceIcon(NULL), + fHeightDelta(0), + fWhich(which) +{ + _SetIcon(icon); + + // IconMenuItem is used in synchronously invoked menus, make sure + // we invoke with a timeout + SetTimeout(kSynchMenuInvokeTimeout); +} + + +IconMenuItem::IconMenuItem( + const char* label, BMessage* message, const BNodeInfo* nodeInfo, icon_size which) + : BMenuItem(label, message), + fDeviceIcon(NULL), + fHeightDelta(0), + fWhich(which) +{ + if (nodeInfo != NULL) { + fDeviceIcon = new BBitmap( + BRect(BPoint(0, 0), be_control_look->ComposeIconSize(which)), kDefaultIconDepth); + if (nodeInfo->GetTrackerIcon(fDeviceIcon, (icon_size)-1) != B_OK) { + delete fDeviceIcon; + fDeviceIcon = NULL; + } + } + + // IconMenuItem is used in synchronously invoked menus, make sure + // we invoke with a timeout + SetTimeout(kSynchMenuInvokeTimeout); +} + + +IconMenuItem::IconMenuItem( + const char* label, BMessage* message, const char* iconType, icon_size which) + : BMenuItem(label, message), + fDeviceIcon(NULL), + fHeightDelta(0), + fWhich(which) +{ + BMimeType mime(iconType); + fDeviceIcon = new BBitmap( + BRect(BPoint(0, 0), be_control_look->ComposeIconSize(which)), kDefaultIconDepth); + + if (mime.GetIcon(fDeviceIcon, which) != B_OK) { + BMimeType super; + mime.GetSupertype(&super); + if (super.GetIcon(fDeviceIcon, which) != B_OK) { + delete fDeviceIcon; + fDeviceIcon = NULL; + } + } + + // IconMenuItem is used in synchronously invoked menus, make sure + // we invoke with a timeout + SetTimeout(kSynchMenuInvokeTimeout); +} + + +IconMenuItem::IconMenuItem(BMenu* submenu, BMessage* message, const char* iconType, icon_size which) + : BMenuItem(submenu, message), + fDeviceIcon(NULL), + fHeightDelta(0), + fWhich(which) +{ + BMimeType mime(iconType); + fDeviceIcon = new BBitmap( + BRect(BPoint(0, 0), be_control_look->ComposeIconSize(which)), kDefaultIconDepth); + + if (mime.GetIcon(fDeviceIcon, which) != B_OK) { + BMimeType super; + mime.GetSupertype(&super); + if (super.GetIcon(fDeviceIcon, which) != B_OK) { + delete fDeviceIcon; + fDeviceIcon = NULL; + } + } + + // IconMenuItem is used in synchronously invoked menus, make sure + // we invoke with a timeout + SetTimeout(kSynchMenuInvokeTimeout); +} + + +IconMenuItem::IconMenuItem(BMenu* menu, BMessage* message, BBitmap* icon, icon_size which) + : BMenuItem(menu, message), + fDeviceIcon(NULL), + fHeightDelta(0), + fWhich(which) +{ + _SetIcon(icon); + + // IconMenuItem is used in synchronously invoked menus, make sure + // we invoke with a timeout + SetTimeout(kSynchMenuInvokeTimeout); +} + + +IconMenuItem::IconMenuItem(BMessage* data) + : BMenuItem(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(BPoint(0, 0), be_control_look->ComposeIconSize(fWhich)), 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 = _inherited::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; +} + + +void +IconMenuItem::GetContentSize(float* width, float* height) +{ + _inherited::GetContentSize(width, height); + + int32 iconHeight = fWhich; + if (fDeviceIcon != NULL) + iconHeight = fDeviceIcon->Bounds().IntegerHeight() + 1; + + fHeightDelta = iconHeight - *height; + if (*height < iconHeight) + *height = iconHeight; + + *width += 20; +} + + +void +IconMenuItem::DrawContent() +{ + BPoint drawPoint(ContentLocation()); + if (fDeviceIcon != NULL) + drawPoint.x += (fDeviceIcon->Bounds().Width() + 1) + 4.0f; + + if (fHeightDelta > 0) + drawPoint.y += ceilf(fHeightDelta / 2); + + Menu()->MovePenTo(drawPoint); + _inherited::DrawContent(); + + Menu()->PushState(); + + BPoint where(ContentLocation()); + float deltaHeight = fHeightDelta < 0 ? -fHeightDelta : 0; + where.y += ceilf(deltaHeight / 2); + + if (fDeviceIcon != NULL) { + if (IsEnabled()) { + Menu()->SetDrawingMode(B_OP_ALPHA); + } else { + Menu()->SetDrawingMode(B_OP_ALPHA); + Menu()->SetHighColor(0, 0, 0, 64); + Menu()->SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_OVERLAY); + } + Menu()->DrawBitmapAsync(fDeviceIcon, where); + } + + 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(); +} + + +void +IconMenuItem::_SetIcon(BBitmap* icon) +{ + if (icon != NULL) { + if (fDeviceIcon != NULL) + delete fDeviceIcon; + + fDeviceIcon = new BBitmap( + BRect(BPoint(0, 0), be_control_look->ComposeIconSize(fWhich)), icon->ColorSpace()); + fDeviceIcon->ImportBits(icon); + } else { + delete fDeviceIcon; + fDeviceIcon = NULL; + } +} diff --git a/source/IconMenuItem.h b/source/IconMenuItem.h new file mode 100644 index 0000000..94a701a --- /dev/null +++ b/source/IconMenuItem.h @@ -0,0 +1,51 @@ +/* + * Copyright 2023 Nexus6 + * All rights reserved. Distributed under the terms of the MIT license. + * Parts are taken from the IconMenuItem class from Haiku (Tracker) under the + * Open Tracker Licence + * Copyright (c) 1991-2000, Be Incorporated. All rights reserved. + */ +#ifndef ICON_MENU_ITEM_H +#define ICON_MENU_ITEM_H + + +#include +#include + +class BBitmap; +class BNodeInfo; + +const bigtime_t kSynchMenuInvokeTimeout = 5000000; +const color_space kDefaultIconDepth = B_RGBA32; + +class IconMenuItem : public BMenuItem { +public: + IconMenuItem( + const char* label, BMessage* message, BBitmap* icon, icon_size which = B_MINI_ICON); + IconMenuItem( + const char* label, BMessage* message, const char* iconType, icon_size which = B_MINI_ICON); + IconMenuItem(const char* label, BMessage* message, const BNodeInfo* nodeInfo, icon_size which); + IconMenuItem(BMenu*, BMessage*, const char* iconType, icon_size which = B_MINI_ICON); + IconMenuItem(BMenu*, BMessage*, BBitmap* icon, icon_size which = B_MINI_ICON); + 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); + +private: + virtual void _SetIcon(BBitmap* icon); + +private: + BBitmap* fDeviceIcon; + float fHeightDelta; + icon_size fWhich; + + typedef BMenuItem _inherited; +}; + +#endif // ICON_MENU_ITEM_H