From 26ad9841a29ff5945fc3706142f52df8b77a4c9b Mon Sep 17 00:00:00 2001 From: Stefano Ceccherini Date: Mon, 30 May 2005 10:10:52 +0000 Subject: [PATCH] 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 --- src/kits/interface/Menu.cpp | 81 +++++++++++++++++++++------------- src/kits/interface/MenuBar.cpp | 11 +++-- 2 files changed, 56 insertions(+), 36 deletions(-) diff --git a/src/kits/interface/Menu.cpp b/src/kits/interface/Menu.cpp index 6529c8c7f7..e3fee92016 100644 --- a/src/kits/interface/Menu.cpp +++ b/src/kits/interface/Menu.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -356,17 +357,16 @@ bool BMenu::AddList(BList *list, int32 index) { // TODO: test this function, it's not documented in the bebook. - int32 numItems = 0; - if (list != NULL) - numItems = list->CountItems(); + if (list == NULL) + return false; + int32 numItems = list->CountItems(); for (int32 i = 0; i < numItems; i++) { BMenuItem *item = static_cast(list->ItemAt(i)); if (item != NULL) _AddItem(item, index + i); } - // TODO: return false if needed return true; } @@ -406,7 +406,7 @@ BMenu::RemoveItems(int32 index, int32 count, bool del) bool BMenu::RemoveItem(BMenu *submenu) { - for (int i = 0; i < fItems.CountItems(); i++) + for (int32 i = 0; i < fItems.CountItems(); i++) if (static_cast(fItems.ItemAt(i))->Submenu() == submenu) return RemoveItems(i, 1, NULL, false); @@ -501,22 +501,32 @@ BMenu::FindItem(uint32 command) const status_t BMenu::SetTargetForItems(BHandler *handler) { - for (int32 i = 0; i < fItems.CountItems(); i++) - if (ItemAt(i)->SetTarget(handler) < B_OK) - return B_ERROR; - - return B_OK; + // TODO: Test what beos returns here in + // case there are no items + status_t status = B_OK; + for (int32 i = 0; i < fItems.CountItems(); i++) { + status = ItemAt(i)->SetTarget(handler); + if (status < B_OK) + break; + } + + return status; } status_t BMenu::SetTargetForItems(BMessenger messenger) { - for (int32 i = 0; i < fItems.CountItems(); i++) - if (ItemAt(i)->SetTarget(messenger) < B_OK) - return B_ERROR; + // TODO: Test what beos returns here in + // case there are no items + 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 * BMenu::FindMarked() { - for (int i = 0; i < fItems.CountItems(); i++) - if (((BMenuItem*)fItems.ItemAt(i))->IsMarked()) - return (BMenuItem*)fItems.ItemAt(i); + BMenuItem *item = NULL; + for (int32 i = 0; i < fItems.CountItems(); 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); - // 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 != fSelected) { + if (item != fSelected) SelectItem(item); - Invalidate(); - } int submenuAction = 0; BMenuItem *submenuItem = NULL; @@ -1381,8 +1389,9 @@ void BMenu::DrawItems(BRect updateRect) { for (int32 i = 0; i < fItems.CountItems(); i++) { - if (ItemAt(i)->Frame().Intersects(updateRect)) - ItemAt(i)->Draw(); + BMenuItem *item = ItemAt(i); + if (item->Frame().Intersects(updateRect)) + item->Draw(); } } @@ -1421,11 +1430,18 @@ BMenu::OverSuper(BPoint location) bool BMenu::OverSubmenu(BMenuItem *item, BPoint loc) { - // TODO: we assume that loc is in screen coords - if (!item->Submenu()) + // we assume that loc is in screen coords + BMenu *subMenu = item->Submenu(); + if (subMenu == NULL) 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 BMenu::IsItemVisible(BMenuItem *item) const { - return false; + BRect itemFrame = item->Frame(); + ConvertToScreen(&itemFrame); + + BRect visibilityFrame = Window()->Frame() & BScreen(Window()).Frame(); + + return visibilityFrame.Intersects(itemFrame); } diff --git a/src/kits/interface/MenuBar.cpp b/src/kits/interface/MenuBar.cpp index d21056b507..11077fc0b6 100644 --- a/src/kits/interface/MenuBar.cpp +++ b/src/kits/interface/MenuBar.cpp @@ -395,13 +395,14 @@ BMenuBar::Track(int32 *action, int32 startIndex, bool showMenu) { // TODO: This function is very incomplete and just partially working: // 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; BWindow *window = Window(); int localAction; bool exitLoop = false; do { - if (window->LockLooperWithTimeout(200000) < B_OK) + if (window->LockWithTimeout(200000) < B_OK) break; BPoint where; @@ -432,7 +433,7 @@ BMenuBar::Track(int32 *action, int32 startIndex, bool showMenu) resultItem = menu->_track(&localAction, startIndex); - if (window->LockLooperWithTimeout(200000) < B_OK) + if (window->LockWithTimeout(200000) < B_OK) break; // the returned action is "5" when the BMenu is closed. @@ -487,12 +488,10 @@ BMenuBar::RestoreFocus() if (BPrivate::gDefaultTokens.GetToken(fPrevFocusToken, B_HANDLER_TOKEN, (void **)&handler, NULL) == B_OK) { BView *view = dynamic_cast(handler); - // TODO: Are there other things to do in case the BHandler - // is not a BView ? if (view != NULL) view->MakeFocus(); } - fPrevFocusToken = NULL; + fPrevFocusToken = -1; window->Unlock(); } }