From 4185bd8b34afeea08550982b4a93d9a13a508504 Mon Sep 17 00:00:00 2001 From: Stefano Ceccherini Date: Tue, 28 Mar 2006 13:06:47 +0000 Subject: [PATCH] Hopefully simplified BMenu/BMenuWindow relationship and made it more robust. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@16910 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/private/interface/MenuWindow.h | 6 +++-- src/kits/interface/Menu.cpp | 27 ++++++------------- src/kits/interface/MenuWindow.cpp | 37 ++++++++++++++++++++------ 3 files changed, 41 insertions(+), 29 deletions(-) diff --git a/headers/private/interface/MenuWindow.h b/headers/private/interface/MenuWindow.h index dc8bb24112..8b2792999f 100644 --- a/headers/private/interface/MenuWindow.h +++ b/headers/private/interface/MenuWindow.h @@ -34,10 +34,12 @@ class BMenuScroller; class BMenuWindow : public BWindow { public: - BMenuWindow(const char *name, BMenu *menu); + BMenuWindow(const char *name); virtual ~BMenuWindow(); - void SetMenu(BMenu *menu); + void AttachMenu(BMenu *menu); + void DetachMenu(); + void UpdateScrollers(); private: diff --git a/src/kits/interface/Menu.cpp b/src/kits/interface/Menu.cpp index 369b665e95..7e91fdf525 100644 --- a/src/kits/interface/Menu.cpp +++ b/src/kits/interface/Menu.cpp @@ -1060,10 +1060,6 @@ BMenu::_show(bool selectFirstItem) if (fSuper != NULL) { fSuperbounds = fSuper->ConvertToScreen(fSuper->Bounds()); window = fSuper->MenuWindow(); - if (window != NULL && window->Lock()) { - window->SetMenu(this); - window->Unlock(); - } } // Otherwise, create a new one @@ -1071,14 +1067,14 @@ BMenu::_show(bool selectFirstItem) // (i.e. not within a BMenuField) if (window == NULL) { // Menu windows get the BMenu's handler name - window = new BMenuWindow(Name(), this); + window = new BMenuWindow(Name()); } if (window == NULL) return false; if (window->Lock()) { - window->ChildAt(0)->AddChild(this); + window->AttachMenu(this); // TODO: for some reason, Window() can already be NULL at this point, // which causes a crash in one of the following functions... @@ -1090,7 +1086,7 @@ BMenu::_show(bool selectFirstItem) window->Unlock(); } - + return true; } @@ -1098,20 +1094,14 @@ BMenu::_show(bool selectFirstItem) void BMenu::_hide() { - if (!LockLooper()) + BMenuWindow *window = static_cast(Window()); + if (window == NULL || !window->Lock()) return; - + SelectItem(NULL); - BMenuWindow *window = static_cast(Window()); - if (window == NULL) { - // Huh? What did happen here? - we're trying to be on the safe side - UnlockLooper(); - return; - } - window->Hide(); - window->ChildAt(0)->RemoveChild(this); + window->DetachMenu(); // we don't want to be deleted when the window is removed // Delete the menu window used by our submenus @@ -1122,7 +1112,6 @@ BMenu::_hide() window->Quit(); } else { // _show() expects the window to be unlocked - // (UnlockLooper() won't work as we are no longer attached) window->Unlock(); } } @@ -1616,7 +1605,7 @@ BMenu::MenuWindow() if (fCachedMenuWindow == NULL) { char windowName[64]; snprintf(windowName, 64, "%s cached menu", Name()); - fCachedMenuWindow = new BMenuWindow(windowName, NULL); + fCachedMenuWindow = new BMenuWindow(windowName); } return fCachedMenuWindow; diff --git a/src/kits/interface/MenuWindow.cpp b/src/kits/interface/MenuWindow.cpp index ed18883ed2..c56fcb4d50 100644 --- a/src/kits/interface/MenuWindow.cpp +++ b/src/kits/interface/MenuWindow.cpp @@ -24,6 +24,7 @@ class BMenuFrame : public BView { BMenuFrame(BMenu *menu); virtual void AttachedToWindow(); + virtual void DetachedFromWindow(); virtual void Draw(BRect updateRect); private: @@ -31,15 +32,13 @@ class BMenuFrame : public BView { }; -BMenuWindow::BMenuWindow(const char *name, BMenu *menu) +BMenuWindow::BMenuWindow(const char *name) // The window will be resized by BMenu, so just pass a dummy rect : BWindow(BRect(0, 0, 0, 0), name, B_BORDERED_WINDOW_LOOK, kMenuWindowFeel, B_NOT_ZOOMABLE | B_AVOID_FOCUS), fUpperScroller(NULL), fLowerScroller(NULL) { - if (menu != NULL) - SetMenu(menu); } @@ -49,12 +48,22 @@ BMenuWindow::~BMenuWindow() void -BMenuWindow::SetMenu(BMenu *menu) +BMenuWindow::AttachMenu(BMenu *menu) { if (CountChildren() > 0) - RemoveChild(ChildAt(0)); - BMenuFrame *menuFrame = new BMenuFrame(menu); - AddChild(menuFrame); + debugger("BMenuWindow (%s): a menu is already attached!"); + if (menu != NULL) { + BMenuFrame *menuFrame = new BMenuFrame(menu); + AddChild(menuFrame); + } +} + + +void +BMenuWindow::DetachMenu() +{ + if (CountChildren() > 0) + RemoveChild(ChildAt(0)); } @@ -72,6 +81,10 @@ void BMenuFrame::AttachedToWindow() { BView::AttachedToWindow(); + + if (fMenu != NULL) + AddChild(fMenu); + ResizeTo(Window()->Bounds().Width(), Window()->Bounds().Height()); if (fMenu != NULL) { BFont font; @@ -81,10 +94,18 @@ BMenuFrame::AttachedToWindow() } +void +BMenuFrame::DetachedFromWindow() +{ + if (fMenu != NULL) + RemoveChild(fMenu); +} + + void BMenuFrame::Draw(BRect updateRect) { - if (fMenu->CountItems() == 0) { + if (fMenu != NULL && fMenu->CountItems() == 0) { // TODO: Review this as it's a bit hacky. // Menu has a size of 0, 0, since there are no items in it. // So the BMenuFrame class has to fake it and draw an empty item.