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:
parent
cd94fddab2
commit
4185bd8b34
@ -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:
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user