Changes to make BMenu behave correctly. Implemented SetTrackingHook(). AddItem() calls the debugger in some cases, as it should. Cleanups.
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@10868 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
+72
-17
@@ -39,47 +39,73 @@
|
|||||||
menu_info BMenu::sMenuInfo;
|
menu_info BMenu::sMenuInfo;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
class _ExtraMenuData_ {
|
||||||
|
public:
|
||||||
|
menu_tracking_hook trackingHook;
|
||||||
|
void *trackingState;
|
||||||
|
|
||||||
|
_ExtraMenuData_(menu_tracking_hook func, void *state)
|
||||||
|
{
|
||||||
|
trackingHook = func;
|
||||||
|
trackingState = state;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
static property_info
|
static property_info
|
||||||
sPropList[] = {
|
sPropList[] = {
|
||||||
{ "Enabled", { B_GET_PROPERTY, 0 },
|
{ "Enabled", { B_GET_PROPERTY, 0 },
|
||||||
{ B_DIRECT_SPECIFIER, 0 }, "Returns true if menu or menu item is enabled; false "
|
{ B_DIRECT_SPECIFIER, 0 }, "Returns true if menu or menu item is enabled; false "
|
||||||
"otherwise." },
|
"otherwise." },
|
||||||
|
|
||||||
{ "Enabled", { B_SET_PROPERTY, 0 },
|
{ "Enabled", { B_SET_PROPERTY, 0 },
|
||||||
{ B_DIRECT_SPECIFIER, 0 }, "Enables or disables menu or menu item." },
|
{ B_DIRECT_SPECIFIER, 0 }, "Enables or disables menu or menu item." },
|
||||||
|
|
||||||
{ "Label", { B_GET_PROPERTY, 0 },
|
{ "Label", { B_GET_PROPERTY, 0 },
|
||||||
{ B_DIRECT_SPECIFIER, 0 }, "Returns the string label of the menu or menu item." },
|
{ B_DIRECT_SPECIFIER, 0 }, "Returns the string label of the menu or menu item." },
|
||||||
|
|
||||||
{ "Label", { B_SET_PROPERTY, 0 },
|
{ "Label", { B_SET_PROPERTY, 0 },
|
||||||
{ B_DIRECT_SPECIFIER, 0 }, "Sets the string label of the menu or menu item." },
|
{ B_DIRECT_SPECIFIER, 0 }, "Sets the string label of the menu or menu item." },
|
||||||
|
|
||||||
{ "Mark", { B_GET_PROPERTY, 0 },
|
{ "Mark", { B_GET_PROPERTY, 0 },
|
||||||
{ B_DIRECT_SPECIFIER, 0 }, "Returns true if the menu item or the menu's superitem "
|
{ B_DIRECT_SPECIFIER, 0 }, "Returns true if the menu item or the menu's superitem "
|
||||||
"is marked; false otherwise." },
|
"is marked; false otherwise." },
|
||||||
|
|
||||||
{ "Mark", { B_SET_PROPERTY, 0 },
|
{ "Mark", { B_SET_PROPERTY, 0 },
|
||||||
{ B_DIRECT_SPECIFIER, 0 }, "Marks or unmarks the menu item or the menu's superitem." },
|
{ B_DIRECT_SPECIFIER, 0 }, "Marks or unmarks the menu item or the menu's superitem." },
|
||||||
|
|
||||||
{ "Menu", { B_CREATE_PROPERTY, 0 },
|
{ "Menu", { B_CREATE_PROPERTY, 0 },
|
||||||
{ B_NAME_SPECIFIER, B_INDEX_SPECIFIER, B_REVERSE_INDEX_SPECIFIER, 0 },
|
{ B_NAME_SPECIFIER, B_INDEX_SPECIFIER, B_REVERSE_INDEX_SPECIFIER, 0 },
|
||||||
"Adds a new menu item at the specified index with the text label found in \"data\" "
|
"Adds a new menu item at the specified index with the text label found in \"data\" "
|
||||||
"and the int32 command found in \"what\" (used as the what field in the CMessage "
|
"and the int32 command found in \"what\" (used as the what field in the CMessage "
|
||||||
"sent by the item)." },
|
"sent by the item)." },
|
||||||
|
|
||||||
{ "Menu", { B_DELETE_PROPERTY, 0 },
|
{ "Menu", { B_DELETE_PROPERTY, 0 },
|
||||||
{ B_NAME_SPECIFIER, B_INDEX_SPECIFIER, B_REVERSE_INDEX_SPECIFIER, 0 },
|
{ B_NAME_SPECIFIER, B_INDEX_SPECIFIER, B_REVERSE_INDEX_SPECIFIER, 0 },
|
||||||
"Removes the selected menu or menus." },
|
"Removes the selected menu or menus." },
|
||||||
|
|
||||||
{ "Menu", { B_GET_PROPERTY, B_SET_PROPERTY, 0 },
|
{ "Menu", { B_GET_PROPERTY, B_SET_PROPERTY, 0 },
|
||||||
{ B_NAME_SPECIFIER, B_INDEX_SPECIFIER, B_REVERSE_INDEX_SPECIFIER, 0 },
|
{ B_NAME_SPECIFIER, B_INDEX_SPECIFIER, B_REVERSE_INDEX_SPECIFIER, 0 },
|
||||||
"Directs scripting message to the specified menu, first popping the current "
|
"Directs scripting message to the specified menu, first popping the current "
|
||||||
"specifier off the stack." },
|
"specifier off the stack." },
|
||||||
|
|
||||||
{ "MenuItem", { B_COUNT_PROPERTIES, 0 },
|
{ "MenuItem", { B_COUNT_PROPERTIES, 0 },
|
||||||
{ B_DIRECT_SPECIFIER, 0 }, "Counts the number of menu items in the specified menu." },
|
{ B_DIRECT_SPECIFIER, 0 }, "Counts the number of menu items in the specified menu." },
|
||||||
|
|
||||||
{ "MenuItem", { B_CREATE_PROPERTY, 0 },
|
{ "MenuItem", { B_CREATE_PROPERTY, 0 },
|
||||||
{ B_NAME_SPECIFIER, B_INDEX_SPECIFIER, B_REVERSE_INDEX_SPECIFIER, 0 },
|
{ B_NAME_SPECIFIER, B_INDEX_SPECIFIER, B_REVERSE_INDEX_SPECIFIER, 0 },
|
||||||
"Adds a new menu item at the specified index with the text label found in \"data\" "
|
"Adds a new menu item at the specified index with the text label found in \"data\" "
|
||||||
"and the int32 command found in \"what\" (used as the what field in the CMessage "
|
"and the int32 command found in \"what\" (used as the what field in the CMessage "
|
||||||
"sent by the item)." },
|
"sent by the item)." },
|
||||||
|
|
||||||
{ "MenuItem", { B_DELETE_PROPERTY, 0 },
|
{ "MenuItem", { B_DELETE_PROPERTY, 0 },
|
||||||
{ B_NAME_SPECIFIER, B_INDEX_SPECIFIER, B_REVERSE_INDEX_SPECIFIER, 0 },
|
{ B_NAME_SPECIFIER, B_INDEX_SPECIFIER, B_REVERSE_INDEX_SPECIFIER, 0 },
|
||||||
"Removes the specified menu item from its parent menu." },
|
"Removes the specified menu item from its parent menu." },
|
||||||
|
|
||||||
{ "MenuItem", { B_EXECUTE_PROPERTY, 0 },
|
{ "MenuItem", { B_EXECUTE_PROPERTY, 0 },
|
||||||
{ B_NAME_SPECIFIER, B_INDEX_SPECIFIER, B_REVERSE_INDEX_SPECIFIER, 0 },
|
{ B_NAME_SPECIFIER, B_INDEX_SPECIFIER, B_REVERSE_INDEX_SPECIFIER, 0 },
|
||||||
"Invokes the specified menu item." },
|
"Invokes the specified menu item." },
|
||||||
|
|
||||||
{ "MenuItem", { B_GET_PROPERTY, B_SET_PROPERTY, 0 },
|
{ "MenuItem", { B_GET_PROPERTY, B_SET_PROPERTY, 0 },
|
||||||
{ B_NAME_SPECIFIER, B_INDEX_SPECIFIER, B_REVERSE_INDEX_SPECIFIER, 0 },
|
{ B_NAME_SPECIFIER, B_INDEX_SPECIFIER, B_REVERSE_INDEX_SPECIFIER, 0 },
|
||||||
"Directs scripting message to the specified menu, first popping the current "
|
"Directs scripting message to the specified menu, first popping the current "
|
||||||
@@ -158,6 +184,10 @@ BMenu::BMenu(const char *name, float width, float height)
|
|||||||
BMenu::~BMenu()
|
BMenu::~BMenu()
|
||||||
{
|
{
|
||||||
RemoveItems(0, CountItems(), true);
|
RemoveItems(0, CountItems(), true);
|
||||||
|
|
||||||
|
delete fCachedMenuWindow;
|
||||||
|
delete fInitMatrixSize;
|
||||||
|
delete fExtraMenuData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -250,13 +280,17 @@ BMenu::DetachedFromWindow()
|
|||||||
bool
|
bool
|
||||||
BMenu::AddItem(BMenuItem *item)
|
BMenu::AddItem(BMenuItem *item)
|
||||||
{
|
{
|
||||||
return _AddItem(item, CountItems());
|
return AddItem(item, CountItems());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
BMenu::AddItem(BMenuItem *item, int32 index)
|
BMenu::AddItem(BMenuItem *item, int32 index)
|
||||||
{
|
{
|
||||||
|
if (fLayout == B_ITEMS_IN_MATRIX)
|
||||||
|
debugger("BMenu::AddItem(BMenuItem *, int32) this method can only"
|
||||||
|
"be called if the menu layout is not B_ITEMS_IN_MATRIX");
|
||||||
|
|
||||||
return _AddItem(item, index);
|
return _AddItem(item, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -291,6 +325,10 @@ BMenu::AddItem(BMenu *submenu)
|
|||||||
bool
|
bool
|
||||||
BMenu::AddItem(BMenu *submenu, int32 index)
|
BMenu::AddItem(BMenu *submenu, int32 index)
|
||||||
{
|
{
|
||||||
|
if (fLayout == B_ITEMS_IN_MATRIX)
|
||||||
|
debugger("BMenu::AddItem(BMenuItem *, int32) this method can only"
|
||||||
|
"be called if the menu layout is not B_ITEMS_IN_MATRIX");
|
||||||
|
|
||||||
BMenuItem *item = new BMenuItem(submenu);
|
BMenuItem *item = new BMenuItem(submenu);
|
||||||
if (!item)
|
if (!item)
|
||||||
return false;
|
return false;
|
||||||
@@ -924,8 +962,19 @@ BMenu::Track(bool openAnyway, BRect *clickToOpenRect)
|
|||||||
UnlockLooper();
|
UnlockLooper();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (clickToOpenRect != NULL && LockLooper()) {
|
||||||
|
fExtraRect = clickToOpenRect;
|
||||||
|
ConvertFromScreen(fExtraRect);
|
||||||
|
UnlockLooper();
|
||||||
|
}
|
||||||
|
|
||||||
int action;
|
int action;
|
||||||
return _track(&action, -1);
|
BMenuItem *menuItem = _track(&action, -1);
|
||||||
|
|
||||||
|
SetStickyMode(false);
|
||||||
|
fExtraRect = NULL;
|
||||||
|
|
||||||
|
return menuItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -953,6 +1002,8 @@ BMenu::DrawBackground(BRect update)
|
|||||||
void
|
void
|
||||||
BMenu::SetTrackingHook(menu_tracking_hook func, void *state)
|
BMenu::SetTrackingHook(menu_tracking_hook func, void *state)
|
||||||
{
|
{
|
||||||
|
delete fExtraMenuData;
|
||||||
|
fExtraMenuData = new _ExtraMenuData_(func, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1004,6 +1055,12 @@ BMenu::_show(bool selectFirstItem)
|
|||||||
fCachedMenuWindow = new BMenuWindow(Name());
|
fCachedMenuWindow = new BMenuWindow(Name());
|
||||||
|
|
||||||
fCachedMenuWindow->ChildAt(0)->AddChild(this);
|
fCachedMenuWindow->ChildAt(0)->AddChild(this);
|
||||||
|
|
||||||
|
// We're doing this here because ConvertToScreen() needs:
|
||||||
|
// 1. The BView to be attached (see the above line).
|
||||||
|
// 2. The looper locked or not running (the Show() call below starts the looper)
|
||||||
|
if (fSuper != NULL)
|
||||||
|
fSuperbounds = fSuper->ConvertToScreen(fSuper->Bounds());
|
||||||
fCachedMenuWindow->ResizeTo(Bounds().Width() + 4, Bounds().Height() + 4);
|
fCachedMenuWindow->ResizeTo(Bounds().Width() + 4, Bounds().Height() + 4);
|
||||||
fCachedMenuWindow->MoveTo(ScreenLocation());
|
fCachedMenuWindow->MoveTo(ScreenLocation());
|
||||||
fCachedMenuWindow->Show();
|
fCachedMenuWindow->Show();
|
||||||
@@ -1019,6 +1076,7 @@ BMenu::_hide()
|
|||||||
fCachedMenuWindow->Lock();
|
fCachedMenuWindow->Lock();
|
||||||
fCachedMenuWindow->ChildAt(0)->RemoveChild(this);
|
fCachedMenuWindow->ChildAt(0)->RemoveChild(this);
|
||||||
fCachedMenuWindow->Quit();
|
fCachedMenuWindow->Quit();
|
||||||
|
fCachedMenuWindow = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1034,21 +1092,21 @@ BMenu::_track(int *action, long start)
|
|||||||
do {
|
do {
|
||||||
if (LockLooper()) {
|
if (LockLooper()) {
|
||||||
GetMouse(&location, &buttons);
|
GetMouse(&location, &buttons);
|
||||||
|
if (OverSuper(location)) {
|
||||||
|
UnlockLooper();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
item = HitTestItems(location, B_ORIGIN);
|
item = HitTestItems(location, B_ORIGIN);
|
||||||
if (item == NULL) {
|
|
||||||
UnlockLooper();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Sometimes the menu flickers a bit.
|
// TODO: Sometimes the menu flickers a bit.
|
||||||
// try to be smarter and suggest an update area,
|
// try to be smarter and suggest an update area,
|
||||||
// instead of invalidating the whole view.
|
// instead of invalidating the whole view.
|
||||||
if (item != fSelected) {
|
if (item != NULL && item != fSelected) {
|
||||||
SelectItem(item);
|
SelectItem(item);
|
||||||
Invalidate();
|
Invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
UnlockLooper();
|
UnlockLooper();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1323,14 +1381,14 @@ BMenu::InvokeItem(BMenuItem *item, bool now)
|
|||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
BMenu::OverSuper(BPoint loc)
|
BMenu::OverSuper(BPoint location)
|
||||||
{
|
{
|
||||||
ConvertToScreen(&loc);
|
|
||||||
|
|
||||||
if (!Supermenu())
|
if (!Supermenu())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return Supermenu()->Frame().Contains(loc);
|
ConvertToScreen(&location);
|
||||||
|
|
||||||
|
return fSuperbounds.Contains(location);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1378,10 +1436,7 @@ BMenu::HitTestItems(BPoint where, BPoint slop) const
|
|||||||
BRect
|
BRect
|
||||||
BMenu::Superbounds() const
|
BMenu::Superbounds() const
|
||||||
{
|
{
|
||||||
if (fSuper)
|
return fSuperbounds;
|
||||||
return fSuper->Bounds();
|
|
||||||
|
|
||||||
return BRect();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -39,7 +39,9 @@ BMenuItem::BMenuItem(const char *label, BMessage *message, char shortcut,
|
|||||||
uint32 modifiers)
|
uint32 modifiers)
|
||||||
{
|
{
|
||||||
InitData();
|
InitData();
|
||||||
fLabel = strdup(label);
|
if (label != NULL)
|
||||||
|
fLabel = strdup(label);
|
||||||
|
|
||||||
SetMessage(message);
|
SetMessage(message);
|
||||||
|
|
||||||
fShortcutChar = shortcut;
|
fShortcutChar = shortcut;
|
||||||
@@ -161,7 +163,7 @@ BMenuItem::Archive(BMessage *data, bool deep) const
|
|||||||
|
|
||||||
|
|
||||||
BMenuItem::~BMenuItem()
|
BMenuItem::~BMenuItem()
|
||||||
{
|
{
|
||||||
free(fLabel);
|
free(fLabel);
|
||||||
delete fSubmenu;
|
delete fSubmenu;
|
||||||
}
|
}
|
||||||
@@ -460,7 +462,7 @@ void
|
|||||||
BMenuItem::InitData()
|
BMenuItem::InitData()
|
||||||
{
|
{
|
||||||
fLabel = NULL;
|
fLabel = NULL;
|
||||||
fSubmenu = 0;
|
fSubmenu = NULL;
|
||||||
fWindow = NULL;
|
fWindow = NULL;
|
||||||
fSuper = NULL;
|
fSuper = NULL;
|
||||||
fModifiers = 0;
|
fModifiers = 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user