#include "BarMenuBar.h"
#include <algorithm>
#include <Bitmap.h>
#include <ControlLook.h>
#include <Debug.h>
#include <IconUtils.h>
#include <NodeInfo.h>
#include "icons.h"
#include "BarMenuTitle.h"
#include "BarView.h"
#include "BarWindow.h"
#include "DeskbarMenu.h"
#include "DeskbarUtils.h"
#include "ResourceSet.h"
#include "StatusView.h"
#include "TeamMenu.h"
const float kSepItemWidth = 5.0f;
const float kTeamIconBitmapHeight = 19.f;
TSeparatorItem::TSeparatorItem()
:
BSeparatorItem()
{
}
void
TSeparatorItem::Draw()
{
BMenu* menu = Menu();
if (menu == NULL)
return;
BRect frame(Frame());
frame.right = frame.left + kSepItemWidth;
rgb_color base = ui_color(B_MENU_BACKGROUND_COLOR);
menu->PushState();
menu->SetHighColor(tint_color(base, 1.22));
frame.top--;
menu->StrokeLine(frame.LeftTop(), frame.LeftBottom());
frame.left++;
be_control_look->DrawButtonBackground(menu, frame, frame, base);
menu->PopState();
}
TBarMenuBar::TBarMenuBar(BRect frame, const char* name, TBarView* barView)
:
BMenuBar(frame, name, B_FOLLOW_NONE, B_ITEMS_IN_ROW, false),
fBarView(barView),
fAppListMenuItem(NULL),
fSeparatorItem(NULL),
fTeamIconData(NULL),
fTeamIconSize(0)
{
SetItemMargins(0.0f, 0.0f, 0.0f, 0.0f);
SetFont(be_bold_font);
TDeskbarMenu* beMenu = new TDeskbarMenu(barView);
TBarWindow::SetDeskbarMenu(beMenu);
BBitmap* icon = NULL;
size_t dataSize;
const void* data = AppResSet()->FindResource(B_VECTOR_ICON_TYPE,
R_LeafLogoBitmap, &dataSize);
if (data != NULL) {
float width = std::max(63.f, ceilf(63 * be_bold_font->Size() / 12.f));
float height = std::max(22.f, ceilf(22 * be_bold_font->Size() / 12.f));
icon = new BBitmap(BRect(0, 0, width - 1, height - 1), B_RGBA32);
if (icon->InitCheck() != B_OK
|| BIconUtils::GetVectorIcon((const uint8*)data, dataSize, icon)
!= B_OK) {
delete icon;
icon = NULL;
}
}
fDeskbarMenuItem = new TBarMenuTitle(0.0f, 0.0f, icon, beMenu, fBarView);
AddItem(fDeskbarMenuItem);
}
TBarMenuBar::~TBarMenuBar()
{
}
void
TBarMenuBar::SmartResize(float width, float height)
{
if (width == -1.0f && height == -1.0f) {
BRect frame = Frame();
width = frame.Width();
height = frame.Height();
} else
ResizeTo(width, height);
if (fSeparatorItem != NULL)
fDeskbarMenuItem->SetContentSize(width - kSepItemWidth, height);
else {
int32 count = CountItems();
if (fDeskbarMenuItem != NULL)
fDeskbarMenuItem->SetContentSize(floorf(width / count), height);
if (fAppListMenuItem != NULL)
fAppListMenuItem->SetContentSize(floorf(width / count), height);
}
InvalidateLayout();
}
bool
TBarMenuBar::AddTeamMenu()
{
if (CountItems() > 1)
return false;
BRect frame(Frame());
delete fAppListMenuItem;
fAppListMenuItem = new TBarMenuTitle(0.0f, 0.0f, FetchTeamIcon(),
new TTeamMenu(fBarView), fBarView);
bool added = AddItem(fAppListMenuItem, fBarView->Left() ? 0 : 1);
if (added)
SmartResize(frame.Width() - 1.0f, frame.Height());
else
SmartResize(frame.Width(), frame.Height());
return added;
}
bool
TBarMenuBar::RemoveTeamMenu()
{
if (CountItems() < 2)
return false;
bool removed = false;
if (fAppListMenuItem != NULL && RemoveItem(fAppListMenuItem)) {
delete fAppListMenuItem;
fAppListMenuItem = NULL;
SmartResize(-1, -1);
removed = true;
}
return removed;
}
bool
TBarMenuBar::AddSeparatorItem()
{
if (CountItems() > 1)
return false;
BRect frame(Frame());
delete fSeparatorItem;
fSeparatorItem = new TSeparatorItem();
bool added = AddItem(fSeparatorItem);
if (added)
SmartResize(frame.Width() - 1.0f, frame.Height());
else
SmartResize(frame.Width(), frame.Height());
return added;
}
bool
TBarMenuBar::RemoveSeperatorItem()
{
if (CountItems() < 2)
return false;
bool removed = false;
if (fSeparatorItem != NULL && RemoveItem(fSeparatorItem)) {
delete fSeparatorItem;
fSeparatorItem = NULL;
SmartResize(-1, -1);
removed = true;
}
return removed;
}
void
TBarMenuBar::Draw(BRect updateRect)
{
BMenu::Draw(updateRect);
}
void
TBarMenuBar::DrawBackground(BRect updateRect)
{
BMenu::DrawBackground(updateRect);
}
void
TBarMenuBar::MouseMoved(BPoint where, uint32 code, const BMessage* message)
{
if (!message) {
fBarView->DragStop(true);
BMenuBar::MouseMoved(where, code, message);
return;
}
switch (code) {
case B_ENTERED_VIEW:
{
BPoint loc;
uint32 buttons;
GetMouse(&loc, &buttons);
if (message != NULL && buttons != 0) {
fBarView->CacheDragData(const_cast<BMessage*>(message));
MouseDown(loc);
}
break;
}
}
BMenuBar::MouseMoved(where, code, message);
}
static void
init_tracking_hook(BMenuItem* item, bool (*hookFunction)(BMenu*, void*),
void* state)
{
if (!item)
return;
BMenu* windowMenu = item->Submenu();
if (windowMenu) {
windowMenu->SetTrackingHook(hookFunction, state);
}
}
void
TBarMenuBar::InitTrackingHook(bool (*hookFunction)(BMenu*, void*),
void* state, bool both)
{
BPoint loc;
uint32 buttons;
GetMouse(&loc, &buttons);
if (fDeskbarMenuItem->Frame().Contains(loc) || both)
init_tracking_hook(fDeskbarMenuItem, hookFunction, state);
if (fAppListMenuItem && (fAppListMenuItem->Frame().Contains(loc) || both))
init_tracking_hook(fAppListMenuItem, hookFunction, state);
}
const BBitmap*
TBarMenuBar::FetchTeamIcon()
{
const BBitmap* teamIcon = NULL;
if (fTeamIconData == NULL || fTeamIconSize == 0) {
fTeamIconData = (const uint8*)AppResSet()->FindResource(
B_VECTOR_ICON_TYPE, R_TeamIcon, &fTeamIconSize);
}
if (fTeamIconData != NULL && fTeamIconSize > 0) {
float iconHeight = std::max(kTeamIconBitmapHeight,
ceilf(kTeamIconBitmapHeight * be_bold_font->Size() / 12.f));
BRect iconRect = BRect(0, 0, iconHeight, iconHeight);
iconRect.InsetBy(-1, -1);
BBitmap* icon = new(std::nothrow) BBitmap(iconRect, B_RGBA32);
if (icon != NULL && icon->InitCheck() == B_OK
&& BIconUtils::GetVectorIcon(fTeamIconData, fTeamIconSize, icon)
== B_OK) {
teamIcon = icon;
} else if (icon != NULL)
delete icon;
}
return teamIcon;
}