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
+4 -2
View File
@@ -34,10 +34,12 @@ class BMenuScroller;
class BMenuWindow : public BWindow { class BMenuWindow : public BWindow {
public: public:
BMenuWindow(const char *name, BMenu *menu); BMenuWindow(const char *name);
virtual ~BMenuWindow(); virtual ~BMenuWindow();
void SetMenu(BMenu *menu); void AttachMenu(BMenu *menu);
void DetachMenu();
void UpdateScrollers(); void UpdateScrollers();
private: private:
+8 -19
View File
@@ -1060,10 +1060,6 @@ BMenu::_show(bool selectFirstItem)
if (fSuper != NULL) { if (fSuper != NULL) {
fSuperbounds = fSuper->ConvertToScreen(fSuper->Bounds()); fSuperbounds = fSuper->ConvertToScreen(fSuper->Bounds());
window = fSuper->MenuWindow(); window = fSuper->MenuWindow();
if (window != NULL && window->Lock()) {
window->SetMenu(this);
window->Unlock();
}
} }
// Otherwise, create a new one // Otherwise, create a new one
@@ -1071,14 +1067,14 @@ BMenu::_show(bool selectFirstItem)
// (i.e. not within a BMenuField) // (i.e. not within a BMenuField)
if (window == NULL) { if (window == NULL) {
// Menu windows get the BMenu's handler name // Menu windows get the BMenu's handler name
window = new BMenuWindow(Name(), this); window = new BMenuWindow(Name());
} }
if (window == NULL) if (window == NULL)
return false; return false;
if (window->Lock()) { if (window->Lock()) {
window->ChildAt(0)->AddChild(this); window->AttachMenu(this);
// TODO: for some reason, Window() can already be NULL at this point, // TODO: for some reason, Window() can already be NULL at this point,
// which causes a crash in one of the following functions... // which causes a crash in one of the following functions...
@@ -1090,7 +1086,7 @@ BMenu::_show(bool selectFirstItem)
window->Unlock(); window->Unlock();
} }
return true; return true;
} }
@@ -1098,20 +1094,14 @@ BMenu::_show(bool selectFirstItem)
void void
BMenu::_hide() BMenu::_hide()
{ {
if (!LockLooper()) BMenuWindow *window = static_cast<BMenuWindow *>(Window());
if (window == NULL || !window->Lock())
return; return;
SelectItem(NULL); 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->Hide();
window->ChildAt(0)->RemoveChild(this); window->DetachMenu();
// we don't want to be deleted when the window is removed // we don't want to be deleted when the window is removed
// Delete the menu window used by our submenus // Delete the menu window used by our submenus
@@ -1122,7 +1112,6 @@ BMenu::_hide()
window->Quit(); window->Quit();
} else { } else {
// _show() expects the window to be unlocked // _show() expects the window to be unlocked
// (UnlockLooper() won't work as we are no longer attached)
window->Unlock(); window->Unlock();
} }
} }
@@ -1616,7 +1605,7 @@ BMenu::MenuWindow()
if (fCachedMenuWindow == NULL) { if (fCachedMenuWindow == NULL) {
char windowName[64]; char windowName[64];
snprintf(windowName, 64, "%s cached menu", Name()); snprintf(windowName, 64, "%s cached menu", Name());
fCachedMenuWindow = new BMenuWindow(windowName, NULL); fCachedMenuWindow = new BMenuWindow(windowName);
} }
return fCachedMenuWindow; return fCachedMenuWindow;
+29 -8
View File
@@ -24,6 +24,7 @@ class BMenuFrame : public BView {
BMenuFrame(BMenu *menu); BMenuFrame(BMenu *menu);
virtual void AttachedToWindow(); virtual void AttachedToWindow();
virtual void DetachedFromWindow();
virtual void Draw(BRect updateRect); virtual void Draw(BRect updateRect);
private: 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 // 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, : BWindow(BRect(0, 0, 0, 0), name, B_BORDERED_WINDOW_LOOK, kMenuWindowFeel,
B_NOT_ZOOMABLE | B_AVOID_FOCUS), B_NOT_ZOOMABLE | B_AVOID_FOCUS),
fUpperScroller(NULL), fUpperScroller(NULL),
fLowerScroller(NULL) fLowerScroller(NULL)
{ {
if (menu != NULL)
SetMenu(menu);
} }
@@ -49,12 +48,22 @@ BMenuWindow::~BMenuWindow()
void void
BMenuWindow::SetMenu(BMenu *menu) BMenuWindow::AttachMenu(BMenu *menu)
{ {
if (CountChildren() > 0) if (CountChildren() > 0)
RemoveChild(ChildAt(0)); debugger("BMenuWindow (%s): a menu is already attached!");
BMenuFrame *menuFrame = new BMenuFrame(menu); if (menu != NULL) {
AddChild(menuFrame); BMenuFrame *menuFrame = new BMenuFrame(menu);
AddChild(menuFrame);
}
}
void
BMenuWindow::DetachMenu()
{
if (CountChildren() > 0)
RemoveChild(ChildAt(0));
} }
@@ -72,6 +81,10 @@ void
BMenuFrame::AttachedToWindow() BMenuFrame::AttachedToWindow()
{ {
BView::AttachedToWindow(); BView::AttachedToWindow();
if (fMenu != NULL)
AddChild(fMenu);
ResizeTo(Window()->Bounds().Width(), Window()->Bounds().Height()); ResizeTo(Window()->Bounds().Width(), Window()->Bounds().Height());
if (fMenu != NULL) { if (fMenu != NULL) {
BFont font; BFont font;
@@ -81,10 +94,18 @@ BMenuFrame::AttachedToWindow()
} }
void
BMenuFrame::DetachedFromWindow()
{
if (fMenu != NULL)
RemoveChild(fMenu);
}
void void
BMenuFrame::Draw(BRect updateRect) BMenuFrame::Draw(BRect updateRect)
{ {
if (fMenu->CountItems() == 0) { if (fMenu != NULL && fMenu->CountItems() == 0) {
// TODO: Review this as it's a bit hacky. // TODO: Review this as it's a bit hacky.
// Menu has a size of 0, 0, since there are no items in it. // 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. // So the BMenuFrame class has to fake it and draw an empty item.