#include "WindowMenuItem.h"
#include <Bitmap.h>
#include <ControlLook.h>
#include <Debug.h>
#include <NaturalCompare.h>
#include "BarApp.h"
#include "BarMenuBar.h"
#include "BarView.h"
#include "ExpandoMenuBar.h"
#include "ResourceSet.h"
#include "TeamMenu.h"
#include "WindowMenu.h"
#include "icons.h"
static float sHPad, sVPad, sLabelOffset = 0.0f;
TWindowMenuItem::TWindowMenuItem(const char* name, int32 id, bool minimized,
bool local, bool dragging)
:
TTruncatableMenuItem(name, NULL),
fBitmap(NULL),
fID(id),
fIsModified(false),
fIsMinimized(minimized),
fIsLocal(local),
fDragging(dragging),
fExpanded(false),
fRequireUpdate(false)
{
_Init(name);
}
void
TWindowMenuItem::GetContentSize(float* width, float* height)
{
if (width != NULL) {
if (!fExpanded) {
*width = sHPad + fLabelWidth + sHPad;
if (fID >= 0)
*width += fBitmap->Bounds().Width() + sLabelOffset;
} else
*width = Frame().Width();
}
if (height != NULL) {
*height = (fID >= 0) ? fBitmap->Bounds().Height() : 0.0f;
float labelHeight = fLabelAscent + fLabelDescent;
*height = (labelHeight > *height) ? labelHeight : *height;
*height += sVPad * 2;
}
}
void
TWindowMenuItem::Draw()
{
if (!fExpanded) {
BMenuItem::Draw();
return;
}
rgb_color menuColor = tint_color(ui_color(B_MENU_BACKGROUND_COLOR), 1.07);
BRect frame(Frame());
BMenu* menu = Menu();
menu->PushState();
TBarView* barview = (static_cast<TBarApp*>(be_app))->BarView();
if ((!IsSelected() && !menu->IsRedrawAfterSticky())
|| barview->Dragging() || !IsEnabled()) {
rgb_color shadow = tint_color(menuColor, 1.09);
menu->SetHighColor(shadow);
frame.right = frame.left + sHPad / 2;
menu->FillRect(frame);
menu->SetHighColor(menuColor);
frame.left = frame.right + 1;
frame.right = Frame().right;
menu->FillRect(frame);
}
if (IsEnabled() && IsSelected() && !menu->IsRedrawAfterSticky()) {
rgb_color backColor = tint_color(menuColor,
B_HIGHLIGHT_BACKGROUND_TINT);
menu->SetLowColor(backColor);
menu->SetHighColor(backColor);
menu->FillRect(frame);
} else {
menu->SetLowColor(menuColor);
menu->SetHighColor(menuColor);
}
DrawContent();
menu->PopState();
}
void
TWindowMenuItem::DrawContent()
{
BMenu* menu = Menu();
BPoint contentLocation = ContentLocation() + BPoint(sHPad, 0);
if (fID >= 0) {
menu->SetDrawingMode(B_OP_OVER);
const float bitmapWidth = fBitmap->Bounds().Width(),
bitmapHeight = fBitmap->Bounds().Height();
float shiftedBy = 0.0f;
if (bitmapWidth > bitmapHeight) {
shiftedBy = (bitmapHeight + 1) / 2.0f;
contentLocation.x -= shiftedBy;
}
float height;
GetContentSize(NULL, &height);
contentLocation.y += (height - bitmapHeight) / 2;
menu->MovePenTo(contentLocation);
menu->DrawBitmapAsync(fBitmap);
contentLocation.x += shiftedBy;
contentLocation.x += (bitmapWidth - shiftedBy) + sLabelOffset;
}
contentLocation.y = ContentLocation().y + sVPad + fLabelAscent;
menu->SetDrawingMode(B_OP_COPY);
menu->MovePenTo(contentLocation);
if (IsSelected())
menu->SetHighColor(ui_color(B_MENU_SELECTED_ITEM_TEXT_COLOR));
else
menu->SetHighColor(ui_color(B_MENU_ITEM_TEXT_COLOR));
float labelWidth = menu->StringWidth(Label());
BPoint penLocation = menu->PenLocation();
float offset = penLocation.x - Frame().left;
menu->DrawString(Label(labelWidth + offset));
}
status_t
TWindowMenuItem::Invoke(BMessage* )
{
if (!fDragging) {
if (fID >= 0) {
int32 action = (modifiers() & B_CONTROL_KEY) != 0
? B_MINIMIZE_WINDOW : B_BRING_TO_FRONT;
bool doZoom = false;
BRect zoomRect(0.0f, 0.0f, 0.0f, 0.0f);
BMenuItem* item;
if (!fExpanded)
item = Menu()->Superitem();
else
item = this;
if (item->Menu()->Window() != NULL) {
zoomRect = item->Menu()->ConvertToScreen(item->Frame());
doZoom = (fIsMinimized && action == B_BRING_TO_FRONT)
|| (!fIsMinimized && action == B_MINIMIZE_WINDOW);
}
do_window_action(fID, action, zoomRect, doZoom);
}
}
return B_OK;
}
void
TWindowMenuItem::SetTo(const char* name, int32 id, bool minimized,
bool local, bool dragging)
{
fIsModified = fIsLocal != local || fIsMinimized != minimized;
fID = id;
fIsMinimized = minimized;
fIsLocal = local;
fDragging = dragging;
fRequireUpdate = false;
_Init(name);
}
int32
TWindowMenuItem::InsertIndexFor(BMenu* menu, int32 startIndex,
TWindowMenuItem* newItem)
{
for (int32 index = startIndex;; index++) {
TWindowMenuItem* item
= dynamic_cast<TWindowMenuItem*>(menu->ItemAt(index));
if (item == NULL
|| NaturalCompare(item->Label(), newItem->Label()) > 0) {
return index;
}
}
}
void
TWindowMenuItem::_Init(const char* name)
{
if (sHPad == 0.0f) {
sHPad = be_control_look->ComposeSpacing(B_USE_ITEM_SPACING) - 1.0f;
sVPad = ceilf(be_control_look->ComposeSpacing(B_USE_SMALL_SPACING) / 4.0f);
sLabelOffset = ceilf((be_control_look->DefaultLabelSpacing() / 3.0f) * 4.0f);
}
TBarApp* app = static_cast<TBarApp*>(be_app);
fBitmap = app->FetchWindowIcon(fIsLocal, fIsMinimized);
menu_info info;
get_menu_info(&info);
BFont font;
font.SetFamilyAndStyle(info.f_family, info.f_style);
font.SetSize(info.font_size);
fLabelWidth = ceilf(font.StringWidth(name));
font_height fontHeight;
font.GetHeight(&fontHeight);
fLabelAscent = ceilf(fontHeight.ascent);
fLabelDescent = ceilf(fontHeight.descent + fontHeight.leading);
SetLabel(name);
}