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:
@@ -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:
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
Reference in New Issue
Block a user