Menus don't flicker anymore, extended some ToDos, small cleanups. Implemented BMenu::IsItemVisible() as I think I'll need it soon, extended Bmenu::OverSubmenu() to be recursive, it's not used at the moment but should be.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@12899 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stefano Ceccherini 2005-05-30 10:10:52 +00:00
parent 60d5a3fc59
commit 26ad9841a2
2 changed files with 56 additions and 36 deletions

View File

@ -31,6 +31,7 @@
#include <MenuItem.h> #include <MenuItem.h>
#include <Path.h> #include <Path.h>
#include <PropertyInfo.h> #include <PropertyInfo.h>
#include <Screen.h>
#include <Window.h> #include <Window.h>
#include <MenuWindow.h> #include <MenuWindow.h>
@ -356,17 +357,16 @@ bool
BMenu::AddList(BList *list, int32 index) BMenu::AddList(BList *list, int32 index)
{ {
// TODO: test this function, it's not documented in the bebook. // TODO: test this function, it's not documented in the bebook.
int32 numItems = 0; if (list == NULL)
if (list != NULL) return false;
numItems = list->CountItems();
int32 numItems = list->CountItems();
for (int32 i = 0; i < numItems; i++) { for (int32 i = 0; i < numItems; i++) {
BMenuItem *item = static_cast<BMenuItem *>(list->ItemAt(i)); BMenuItem *item = static_cast<BMenuItem *>(list->ItemAt(i));
if (item != NULL) if (item != NULL)
_AddItem(item, index + i); _AddItem(item, index + i);
} }
// TODO: return false if needed
return true; return true;
} }
@ -406,7 +406,7 @@ BMenu::RemoveItems(int32 index, int32 count, bool del)
bool bool
BMenu::RemoveItem(BMenu *submenu) BMenu::RemoveItem(BMenu *submenu)
{ {
for (int i = 0; i < fItems.CountItems(); i++) for (int32 i = 0; i < fItems.CountItems(); i++)
if (static_cast<BMenuItem *>(fItems.ItemAt(i))->Submenu() == submenu) if (static_cast<BMenuItem *>(fItems.ItemAt(i))->Submenu() == submenu)
return RemoveItems(i, 1, NULL, false); return RemoveItems(i, 1, NULL, false);
@ -501,22 +501,32 @@ BMenu::FindItem(uint32 command) const
status_t status_t
BMenu::SetTargetForItems(BHandler *handler) BMenu::SetTargetForItems(BHandler *handler)
{ {
for (int32 i = 0; i < fItems.CountItems(); i++) // TODO: Test what beos returns here in
if (ItemAt(i)->SetTarget(handler) < B_OK) // case there are no items
return B_ERROR; status_t status = B_OK;
for (int32 i = 0; i < fItems.CountItems(); i++) {
return B_OK; status = ItemAt(i)->SetTarget(handler);
if (status < B_OK)
break;
}
return status;
} }
status_t status_t
BMenu::SetTargetForItems(BMessenger messenger) BMenu::SetTargetForItems(BMessenger messenger)
{ {
for (int32 i = 0; i < fItems.CountItems(); i++) // TODO: Test what beos returns here in
if (ItemAt(i)->SetTarget(messenger) < B_OK) // case there are no items
return B_ERROR; status_t status = B_OK;
for (int32 i = 0; i < fItems.CountItems(); i++) {
status = ItemAt(i)->SetTarget(messenger);
if (status < B_OK)
break;
}
return B_OK; return status;
} }
@ -603,11 +613,14 @@ BMenu::MaxContentWidth() const
BMenuItem * BMenuItem *
BMenu::FindMarked() BMenu::FindMarked()
{ {
for (int i = 0; i < fItems.CountItems(); i++) BMenuItem *item = NULL;
if (((BMenuItem*)fItems.ItemAt(i))->IsMarked()) for (int32 i = 0; i < fItems.CountItems(); i++) {
return (BMenuItem*)fItems.ItemAt(i); item = ItemAt(i);
if (item->IsMarked())
break;
}
return NULL; return item;
} }
@ -1102,14 +1115,9 @@ BMenu::_track(int *action, long start)
item = HitTestItems(location, B_ORIGIN); item = HitTestItems(location, B_ORIGIN);
// TODO: Sometimes the menu flickers a bit.
// try to be smarter and suggest an update area,
// instead of invalidating the whole view.
if (item != NULL) { if (item != NULL) {
if (item != fSelected) { if (item != fSelected)
SelectItem(item); SelectItem(item);
Invalidate();
}
int submenuAction = 0; int submenuAction = 0;
BMenuItem *submenuItem = NULL; BMenuItem *submenuItem = NULL;
@ -1381,8 +1389,9 @@ void
BMenu::DrawItems(BRect updateRect) BMenu::DrawItems(BRect updateRect)
{ {
for (int32 i = 0; i < fItems.CountItems(); i++) { for (int32 i = 0; i < fItems.CountItems(); i++) {
if (ItemAt(i)->Frame().Intersects(updateRect)) BMenuItem *item = ItemAt(i);
ItemAt(i)->Draw(); if (item->Frame().Intersects(updateRect))
item->Draw();
} }
} }
@ -1421,11 +1430,18 @@ BMenu::OverSuper(BPoint location)
bool bool
BMenu::OverSubmenu(BMenuItem *item, BPoint loc) BMenu::OverSubmenu(BMenuItem *item, BPoint loc)
{ {
// TODO: we assume that loc is in screen coords // we assume that loc is in screen coords
if (!item->Submenu()) BMenu *subMenu = item->Submenu();
if (subMenu == NULL)
return false; return false;
return item->Submenu()->Window()->Frame().Contains(loc); if (subMenu->Window()->Frame().Contains(loc))
return true;
if (subMenu->fSelected == NULL)
return false;
return subMenu->OverSubmenu(subMenu->fSelected, loc);
} }
@ -1554,7 +1570,12 @@ BMenu::NextItem(BMenuItem *item, bool forward) const
bool bool
BMenu::IsItemVisible(BMenuItem *item) const BMenu::IsItemVisible(BMenuItem *item) const
{ {
return false; BRect itemFrame = item->Frame();
ConvertToScreen(&itemFrame);
BRect visibilityFrame = Window()->Frame() & BScreen(Window()).Frame();
return visibilityFrame.Intersects(itemFrame);
} }

View File

@ -395,13 +395,14 @@ BMenuBar::Track(int32 *action, int32 startIndex, bool showMenu)
{ {
// TODO: This function is very incomplete and just partially working: // TODO: This function is very incomplete and just partially working:
// For example, it doesn't respect the "sticky mode" setting. // For example, it doesn't respect the "sticky mode" setting.
// Cleanup // Cleanup: We shouldn't use two nested loops. This simplifies the code
// but doesn't work well
BMenuItem *resultItem = NULL; BMenuItem *resultItem = NULL;
BWindow *window = Window(); BWindow *window = Window();
int localAction; int localAction;
bool exitLoop = false; bool exitLoop = false;
do { do {
if (window->LockLooperWithTimeout(200000) < B_OK) if (window->LockWithTimeout(200000) < B_OK)
break; break;
BPoint where; BPoint where;
@ -432,7 +433,7 @@ BMenuBar::Track(int32 *action, int32 startIndex, bool showMenu)
resultItem = menu->_track(&localAction, startIndex); resultItem = menu->_track(&localAction, startIndex);
if (window->LockLooperWithTimeout(200000) < B_OK) if (window->LockWithTimeout(200000) < B_OK)
break; break;
// the returned action is "5" when the BMenu is closed. // the returned action is "5" when the BMenu is closed.
@ -487,12 +488,10 @@ BMenuBar::RestoreFocus()
if (BPrivate::gDefaultTokens.GetToken(fPrevFocusToken, B_HANDLER_TOKEN, if (BPrivate::gDefaultTokens.GetToken(fPrevFocusToken, B_HANDLER_TOKEN,
(void **)&handler, NULL) == B_OK) { (void **)&handler, NULL) == B_OK) {
BView *view = dynamic_cast<BView *>(handler); BView *view = dynamic_cast<BView *>(handler);
// TODO: Are there other things to do in case the BHandler
// is not a BView ?
if (view != NULL) if (view != NULL)
view->MakeFocus(); view->MakeFocus();
} }
fPrevFocusToken = NULL; fPrevFocusToken = -1;
window->Unlock(); window->Unlock();
} }
} }