Files
haiku-beta6/src/kits/interface/BMCPrivate.cpp
T
Stefano Ceccherini e3d0715523 Enlarged a bit the BMCMenuBar's frame, so that it's drawn more nicely
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@16795 a95241bf-73f2-0310-859d-f6bbb57e9c96
2006-03-14 20:41:50 +00:00

375 lines
7.8 KiB
C++

/*
* Copyright 2001-2006, Haiku Inc.
* Distributed under the terms of the MIT License.
*
* Authors:
* Marc Flerackers ([email protected])
* Stephan Aßmus <[email protected]>
*/
#include <stdio.h>
#include <BMCPrivate.h>
#include <MenuField.h>
#include <MenuItem.h>
#include <Message.h>
#include <Region.h>
#include <Window.h>
_BMCItem_::_BMCItem_(BMenu *menu)
: BMenuItem(menu),
fShowPopUpMarker(true)
{
printf("_BMCItem_::_BMCItem_()\n");
}
_BMCItem_::_BMCItem_(BMessage *message)
: BMenuItem(message),
fShowPopUpMarker(true)
{
}
_BMCItem_::~_BMCItem_()
{
}
BArchivable *
_BMCItem_::Instantiate(BMessage *data)
{
if (validate_instantiation(data, "_BMCItem_"))
return new _BMCItem_(data);
else
return NULL;
}
void
_BMCItem_::Draw()
{
BMenu *menu = Menu();
BMenuItem::Draw();
if (!fShowPopUpMarker)
return;
return;
BRect rect(menu->Bounds());
rect.right -= 4;
rect.bottom -= 5;
rect.left = rect.right - 4;
rect.top = rect.bottom - 2;
if (IsEnabled())
menu->SetHighColor(tint_color(ui_color(B_MENU_BACKGROUND_COLOR),
B_DARKEN_4_TINT));
else
menu->SetHighColor(tint_color(ui_color(B_MENU_BACKGROUND_COLOR),
B_DARKEN_4_TINT));
menu->StrokeLine(BPoint(rect.left, rect.top), BPoint(rect.right, rect.top));
menu->StrokeLine(BPoint(rect.left + 1.0f, rect.top + 1.0f),
BPoint(rect.right - 1.0f, rect.top + 1.0f));
menu->StrokeLine(BPoint(rect.left + 2.0f, rect.bottom),
BPoint(rect.left + 2.0f, rect.bottom));
}
void
_BMCItem_::GetContentSize(float *width, float *height)
{
BMenuItem::GetContentSize(width, height);
}
/*
_BMCFilter_::_BMCFilter_(BMenuField *menuField, uint32)
{
}
_BMCFilter_::~_BMCFilter_()
{
}
filter_result
_BMCFilter_::Filter(BMessage *message, BHandler **handler)
{
}
_BMCFilter_ &
_BMCFilter_::operator=(const _BMCFilter_ &)
{
return *this;
}*/
_BMCMenuBar_::_BMCMenuBar_(BRect frame, bool fixed_size, BMenuField *menuField)
: BMenuBar(frame, "_mc_mb_", B_FOLLOW_LEFT | B_FOLLOW_TOP, B_ITEMS_IN_ROW,
!fixed_size)
{
SetFlags(Flags() | B_FRAME_EVENTS);
SetBorder(B_BORDER_CONTENTS);
fMenuField = menuField;
fFixedSize = fixed_size;
fRunner = NULL;
float left, top, right, bottom;
GetItemMargins(&left, &top, &right, &bottom);
// give a bit more space to draw the small thumb
left -= 1;
right += 3;
SetItemMargins(left, top, right, bottom);
SetMaxContentWidth(frame.Width() - (left + right));
}
_BMCMenuBar_::_BMCMenuBar_(BMessage *data)
: BMenuBar(data)
{
SetFlags(Flags() | B_FRAME_EVENTS);
bool rsize_to_fit;
if (data->FindBool("_rsize_to_fit", &rsize_to_fit) == B_OK)
fFixedSize = !rsize_to_fit;
else
fFixedSize = true;
}
_BMCMenuBar_::~_BMCMenuBar_()
{
}
BArchivable *
_BMCMenuBar_::Instantiate(BMessage *data)
{
if (validate_instantiation(data, "_BMCMenuBar_"))
return new _BMCMenuBar_(data);
return NULL;
}
void
_BMCMenuBar_::AttachedToWindow()
{
fMenuField = static_cast<BMenuField *>(Parent());
BMenuBar *menuBar = Window()->KeyMenuBar();
BMenuBar::AttachedToWindow();
Window()->SetKeyMenuBar(menuBar);
}
void
_BMCMenuBar_::Draw(BRect updateRect)
{
// draw the right side with the popup marker
// prevent the original BMenuBar's Draw from
// drawing in those parts
BRect bounds(Bounds());
bounds.right -= 10.0;
bounds.bottom -= 1.0;
BRegion clipping(bounds);
ConstrainClippingRegion(&clipping);
BMenuBar::Draw(updateRect);
// restore clipping
ConstrainClippingRegion(NULL);
bounds.right += 10.0;
bounds.bottom += 1.0;
// prepare some colors
rgb_color normalNoTint = ui_color(B_MENU_BACKGROUND_COLOR);
rgb_color noTint = tint_color(normalNoTint, 0.74);
rgb_color darken4;
rgb_color normalDarken4;
rgb_color darken1;
rgb_color lighten1;
rgb_color lighten2;
if (IsEnabled()) {
darken4 = tint_color(noTint, B_DARKEN_4_TINT);
normalDarken4 = tint_color(normalNoTint, B_DARKEN_4_TINT);
darken1 = tint_color(noTint, B_DARKEN_1_TINT);
lighten1 = tint_color(noTint, B_LIGHTEN_1_TINT);
lighten2 = tint_color(noTint, B_LIGHTEN_2_TINT);
} else {
darken4 = tint_color(noTint, B_DARKEN_2_TINT);
normalDarken4 = tint_color(normalNoTint, B_DARKEN_2_TINT);
darken1 = tint_color(noTint, (B_NO_TINT + B_DARKEN_1_TINT) / 2.0);
lighten1 = tint_color(noTint, (B_NO_TINT + B_LIGHTEN_1_TINT) / 2.0);
lighten2 = tint_color(noTint, B_LIGHTEN_1_TINT);
}
BRect r(bounds);
r.left = r.right - 10.0;
BeginLineArray(6);
// bottom below item text, darker then BMenuBar
// would normaly draw it
AddLine(BPoint(bounds.left, r.bottom),
BPoint(r.left - 1.0, r.bottom), normalDarken4);
// bottom below popup marker
AddLine(BPoint(r.left, r.bottom),
BPoint(r.right, r.bottom), darken4);
// right of popup marker
AddLine(BPoint(r.right, r.bottom - 1),
BPoint(r.right, r.top), darken4);
// top above popup marker
AddLine(BPoint(r.left, r.top),
BPoint(r.right - 2, r.top), lighten2);
r.top += 1;
r.bottom -= 1;
r.right -= 1;
// bottom below popup marker
AddLine(BPoint(r.left, r.bottom),
BPoint(r.right, r.bottom), darken1);
// right of popup marker
AddLine(BPoint(r.right, r.bottom - 1),
BPoint(r.right, r.top), darken1);
EndLineArray();
r.bottom -= 1;
r.right -= 1;
SetHighColor(noTint);
FillRect(r);
// popup marker
BPoint center(roundf((r.left + r.right) / 2.0),
roundf((r.top + r.bottom) / 2.0));
BPoint triangle[3];
triangle[0] = center + BPoint(-2.5, -0.5);
triangle[1] = center + BPoint(2.5, -0.5);
triangle[2] = center + BPoint(0.0, 2.0);
uint32 flags = Flags();
SetFlags(flags | B_SUBPIXEL_PRECISE);
SetHighColor(normalDarken4);
FillTriangle(triangle[0], triangle[1], triangle[2]);
SetFlags(flags);
}
void
_BMCMenuBar_::FrameResized(float width, float height)
{
// we need to take care of resizing and cleaning up
// the parent menu field
float diff = Frame().right - fMenuField->Bounds().right;
if (Window()) {
if (diff > 0) {
// clean up the dirty right top corner of
// the menu field when enlarging
BRect dirty(fMenuField->Bounds());
dirty.left = dirty.right - 2;
dirty.bottom = Frame().top - 1;
fMenuField->Invalidate(dirty);
} else if (diff < 0) {
// clean up the dirty right line of
// the menu field when shrinking
BRect dirty(fMenuField->Bounds());
dirty.left = dirty.right + diff + 1;
dirty.right = dirty.left + 1;
fMenuField->Invalidate(dirty);
}
}
// we have been shrinked or enlarged and need to take
// of the size of the parent menu field as well
// NOTE: no worries about follow mode, we follow left and top
fMenuField->ResizeBy(diff + 2, 0.0);
BMenuBar::FrameResized(width, height);
}
void
_BMCMenuBar_::MessageReceived(BMessage *msg)
{
switch (msg->what) {
case 'TICK':
{
BMenuItem *item = ItemAt(0);
if (item && item->Submenu() && item->Submenu()->Window()) {
BMessage message(B_KEY_DOWN);
message.AddInt8("byte", B_ESCAPE);
message.AddInt8("key", B_ESCAPE);
message.AddInt32("modifiers", 0);
message.AddInt8("raw_char", B_ESCAPE);
Window()->PostMessage(&message, this, NULL);
}
}
// fall through
default:
BMenuBar::MessageReceived(msg);
break;
}
}
void
_BMCMenuBar_::MakeFocus(bool focused)
{
if (IsFocus() == focused)
return;
BMenuBar::MakeFocus(focused);
if (focused) {
BMessage message('TICK');
//fRunner = new BMessageRunner(BMessenger(this, NULL, NULL), &message,
// 50000, -1);
} else if (fRunner) {
//delete fRunner;
fRunner = NULL;
}
if (focused)
return;
fMenuField->fSelected = false;
fMenuField->fTransition = true;
BRect bounds(fMenuField->Bounds());
fMenuField->Invalidate(BRect(bounds.left, bounds.top, fMenuField->fDivider,
bounds.bottom));
}
void
_BMCMenuBar_::MouseDown(BPoint where)
{
// Don't show the associated menu if it's disabled
if (fMenuField->IsEnabled() && SubmenuAt(0)->IsEnabled())
BMenuBar::MouseDown(where);
}
_BMCMenuBar_
&_BMCMenuBar_::operator=(const _BMCMenuBar_ &)
{
return *this;
}