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
This commit is contained in:
Stefano Ceccherini 2006-03-28 13:06:47 +00:00
parent cd94fddab2
commit 4185bd8b34
3 changed files with 41 additions and 29 deletions

View File

@ -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:

View File

@ -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<BMenuWindow *>(Window());
if (window == NULL || !window->Lock())
return;
SelectItem(NULL);
BMenuWindow *window = static_cast<BMenuWindow *>(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;

View File

@ -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.