Files
haiku-beta6/src/kits/interface/Menu.cpp
T
haydentech 40ceba30d6 Janitorial work and gcc3-related fixes
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@3408 a95241bf-73f2-0310-859d-f6bbb57e9c96
2003-06-03 18:42:22 +00:00

1316 lines
37 KiB
C++

//------------------------------------------------------------------------------
// Copyright (c) 2001-2002, OpenBeOS
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// File Name: Menu.cpp
// Author: Marc Flerackers ([email protected])
// Description: BMenu display a menu of selectable items.
//------------------------------------------------------------------------------
// Standard Includes -----------------------------------------------------------
// System Includes -------------------------------------------------------------
#include <Menu.h>
#include <MenuItem.h>
#include <Window.h>
#include <PropertyInfo.h>
#include <Errors.h>
#include <File.h>
#include <FindDirectory.h>
#include <Path.h>
// Project Includes ------------------------------------------------------------
// Local Includes --------------------------------------------------------------
// Local Defines ---------------------------------------------------------------
// Globals ---------------------------------------------------------------------
static property_info prop_list[] =
{
{ "Enabled", { B_GET_PROPERTY, 0 },
{ B_DIRECT_SPECIFIER, 0 }, "Returns true if menu or menu item is enabled; false "
"otherwise." },
{ "Enabled", { B_SET_PROPERTY, 0 },
{ B_DIRECT_SPECIFIER, 0 }, "Enables or disables menu or menu item." },
{ "Label", { B_GET_PROPERTY, 0 },
{ B_DIRECT_SPECIFIER, 0 }, "Returns the string label of the menu or menu item." },
{ "Label", { B_SET_PROPERTY, 0 },
{ B_DIRECT_SPECIFIER, 0 }, "Sets the string label of the menu or menu item." },
{ "Mark", { B_GET_PROPERTY, 0 },
{ B_DIRECT_SPECIFIER, 0 }, "Returns true if the menu item or the menu's superitem "
"is marked; false otherwise." },
{ "Mark", { B_SET_PROPERTY, 0 },
{ B_DIRECT_SPECIFIER, 0 }, "Marks or unmarks the menu item or the menu's superitem." },
{ "Menu", { B_CREATE_PROPERTY, 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\" "
"and the int32 command found in \"what\" (used as the what field in the CMessage "
"sent by the item)." },
{ "Menu", { B_DELETE_PROPERTY, 0 },
{ B_NAME_SPECIFIER, B_INDEX_SPECIFIER, B_REVERSE_INDEX_SPECIFIER, 0 },
"Removes the selected menu or menus." },
{ "Menu", { B_GET_PROPERTY, B_SET_PROPERTY, 0 },
{ B_NAME_SPECIFIER, B_INDEX_SPECIFIER, B_REVERSE_INDEX_SPECIFIER, 0 },
"Directs scripting message to the specified menu, first popping the current "
"specifier off the stack." },
{ "MenuItem", { B_COUNT_PROPERTIES, 0 },
{ B_DIRECT_SPECIFIER, 0 }, "Counts the number of menu items in the specified menu." },
{ "MenuItem", { B_CREATE_PROPERTY, 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\" "
"and the int32 command found in \"what\" (used as the what field in the CMessage "
"sent by the item)." },
{ "MenuItem", { B_DELETE_PROPERTY, 0 },
{ B_NAME_SPECIFIER, B_INDEX_SPECIFIER, B_REVERSE_INDEX_SPECIFIER, 0 },
"Removes the specified menu item from its parent menu." },
{ "MenuItem", { B_EXECUTE_PROPERTY, 0 },
{ B_NAME_SPECIFIER, B_INDEX_SPECIFIER, B_REVERSE_INDEX_SPECIFIER, 0 },
"Invokes the specified menu item." },
{ "MenuItem", { B_GET_PROPERTY, B_SET_PROPERTY, 0 },
{ B_NAME_SPECIFIER, B_INDEX_SPECIFIER, B_REVERSE_INDEX_SPECIFIER, 0 },
"Directs scripting message to the specified menu, first popping the current "
"specifier off the stack." },
0
};
//------------------------------------------------------------------------------
class BMenuWindow : public BWindow
{
public:
BMenuWindow(BRect frame, BMenu *menu) :
BWindow(frame, "Menu", B_NO_BORDER_WINDOW_LOOK, B_MODAL_APP_WINDOW_FEEL,
B_NOT_ZOOMABLE)
{
fMenu = menu;
AddChild(fMenu);
ResizeTo(fMenu->Bounds().Width() + 1, fMenu->Bounds().Height() + 1);
fMenu->MakeFocus(true);
}
virtual ~BMenuWindow() {}
virtual void WindowActivated(bool active)
{
if (!active)
{
RemoveChild(fMenu);
if (Lock())
Quit();
}
}
private:
BMenu *fMenu;
};
//------------------------------------------------------------------------------
BMenu::BMenu(const char *name, menu_layout layout)
: BView(BRect(), name, B_FOLLOW_LEFT | B_FOLLOW_TOP,
B_WILL_DRAW | B_NAVIGABLE),
fChosenItem(NULL),
fPad(14.0f, 2.0f, 20.0f, 0.0f),
fSelected(NULL),
fCachedMenuWindow(NULL),
fSuper(NULL),
fSuperitem(NULL),
fAscent(-1.0f),
fDescent(-1.0f),
fFontHeight(-1.0f),
fState(0),
fLayout(layout),
fExtraRect(NULL),
fMaxContentWidth(0.0f),
fInitMatrixSize(NULL),
fExtraMenuData(NULL),
fTrigger(0),
fResizeToFit(true),
fUseCachedMenuLayout(true),
fEnabled(true),
fDynamicName(false),
fRadioMode(false),
fTrackNewBounds(false),
fStickyMode(false),
fIgnoreHidden(true),
fTriggerEnabled(true),
fRedrawAfterSticky(true),
fAttachAborted(false)
{
SetViewColor(ui_color(B_MENU_BACKGROUND_COLOR));
SetFontSize(10);
}
//------------------------------------------------------------------------------
BMenu::BMenu(const char *name, float width, float height)
: BView(BRect(0.0f, width, 0.0f, height), name,
B_FOLLOW_LEFT | B_FOLLOW_TOP, B_WILL_DRAW | B_NAVIGABLE),
fChosenItem(NULL),
fSelected(NULL),
fCachedMenuWindow(NULL),
fSuper(NULL),
fSuperitem(NULL),
fAscent(-1.0f),
fDescent(-1.0f),
fFontHeight(-1.0f),
fState(0),
fLayout(B_ITEMS_IN_MATRIX),
fExtraRect(NULL),
fMaxContentWidth(0.0f),
fInitMatrixSize(NULL),
fExtraMenuData(NULL),
fTrigger(0),
fResizeToFit(true),
fUseCachedMenuLayout(true),
fEnabled(true),
fDynamicName(false),
fRadioMode(false),
fTrackNewBounds(false),
fStickyMode(false),
fIgnoreHidden(true),
fTriggerEnabled(true),
fRedrawAfterSticky(true),
fAttachAborted(false)
{
SetViewColor(ui_color(B_MENU_BACKGROUND_COLOR));
SetFontSize(10);
}
//------------------------------------------------------------------------------
BMenu::~BMenu()
{
for (int i = 0; i < CountItems(); i++)
delete ItemAt(i);
}
//------------------------------------------------------------------------------
BMenu::BMenu(BMessage *archive)
: BView(archive)
{
SetViewColor(ui_color(B_MENU_BACKGROUND_COLOR));
}
//------------------------------------------------------------------------------
BArchivable *BMenu::Instantiate(BMessage *data)
{
if (validate_instantiation(data, "BMenu"))
return new BMenu(data);
else
return NULL;
}
//------------------------------------------------------------------------------
status_t BMenu::Archive(BMessage *data, bool deep) const
{
status_t err = BView::Archive(data, deep);
if (err != B_OK)
return err;
if (Layout() != B_ITEMS_IN_ROW)
{
err = data->AddInt32("_layout", Layout());
if (err != B_OK)
return err;
}
err = data->AddBool("_rsize_to_fit", fResizeToFit);
if (err != B_OK)
return err;
err = data->AddBool("_disable", !IsEnabled());
if (err != B_OK)
return err;
err = data->AddBool("_radio", IsRadioMode());
if (err != B_OK)
return err;
err = data->AddBool("_trig_disabled", AreTriggersEnabled());
if (err != B_OK)
return err;
err = data->AddBool("_dyn_label", fDynamicName);
if (err != B_OK)
return err;
err = data->AddFloat("_maxwidth", fDynamicName);
if (err != B_OK)
return err;
if (deep)
{
// TODO store items and rects
}
return err;
}
//------------------------------------------------------------------------------
void BMenu::AttachedToWindow()
{
BView::AttachedToWindow();
LayoutItems(0);
}
//------------------------------------------------------------------------------
void BMenu::DetachedFromWindow()
{
}
//------------------------------------------------------------------------------
bool BMenu::AddItem(BMenuItem *item)
{
return AddItem(item, CountItems());
}
//------------------------------------------------------------------------------
bool BMenu::AddItem(BMenuItem *item, int32 index)
{
item->fSuper = this;
bool err = fItems.AddItem(item, index);
if (!err)
return err;
// Make sure we update the layout in case we are already attached.
if (Window() && fResizeToFit)
LayoutItems(index);
// Find the root menu window, so we can install this item.
BMenu *root = this;
while (root->Supermenu())
root = root->Supermenu();
if (root->Window())
Install(root->Window());
return err;
}
//------------------------------------------------------------------------------
bool BMenu::AddItem(BMenuItem *item, BRect frame)
{
item->fBounds = frame;
return AddItem(item, CountItems());
}
//------------------------------------------------------------------------------
bool BMenu::AddItem(BMenu *submenu)
{
BMenuItem *item = new BMenuItem(submenu);
submenu->fSuper = this;
return AddItem(item);
}
//------------------------------------------------------------------------------
bool BMenu::AddItem(BMenu *submenu, int32 index)
{
BMenuItem *item = new BMenuItem(submenu);
submenu->fSuper = this;
return AddItem(item, index);
}
//------------------------------------------------------------------------------
bool BMenu::AddItem(BMenu *submenu, BRect frame)
{
BMenuItem *item = new BMenuItem(submenu);
submenu->fSuper = this;
item->fBounds = frame;
return AddItem(item);
}
//------------------------------------------------------------------------------
bool BMenu::AddList(BList *list, int32 index)
{
return false;
}
//------------------------------------------------------------------------------
bool BMenu::AddSeparatorItem()
{
BMenuItem *item = new BSeparatorItem();
item->fSuper = this;
return fItems.AddItem(item);
}
//------------------------------------------------------------------------------
bool BMenu::RemoveItem(BMenuItem *item)
{
return fItems.RemoveItem(item);
}
//------------------------------------------------------------------------------
BMenuItem *BMenu::RemoveItem(int32 index)
{
return (BMenuItem*)fItems.RemoveItem ( index );
}
//------------------------------------------------------------------------------
bool BMenu::RemoveItems(int32 index, int32 count, bool del)
{
return false;
}
//------------------------------------------------------------------------------
bool BMenu::RemoveItem(BMenu *submenu)
{
for (int i =0; i < fItems.CountItems(); i++)
if (((BMenuItem*)fItems.ItemAt(i))->Submenu() == submenu)
return (BMenuItem*)fItems.RemoveItem(fItems.ItemAt(i));
return false;
}
//------------------------------------------------------------------------------
int32 BMenu::CountItems() const
{
return fItems.CountItems();
}
//------------------------------------------------------------------------------
BMenuItem *BMenu::ItemAt(int32 index) const
{
return (BMenuItem*)fItems.ItemAt(index);
}
//------------------------------------------------------------------------------
BMenu *BMenu::SubmenuAt(int32 index) const
{
return ((BMenuItem*)fItems.ItemAt(index))->Submenu();
}
//------------------------------------------------------------------------------
int32 BMenu::IndexOf(BMenuItem *item) const
{
return fItems.IndexOf(item);
}
//------------------------------------------------------------------------------
int32 BMenu::IndexOf(BMenu *submenu) const
{
for (int32 i =0; i < fItems.CountItems(); i++)
if (((BMenuItem*)fItems.ItemAt(i))->Submenu() == submenu)
return i;
return -1;
}
//------------------------------------------------------------------------------
BMenuItem *BMenu::FindItem(const char *label) const
{
BMenuItem *item;
for (int32 i =0; i < CountItems(); i++)
{
item = ItemAt(i);
if (item->Label() && strcmp(item->Label(), label) == 0)
return (item);
if (item->Submenu())
{
item = item->Submenu()->FindItem(label);
if (item)
return item;
}
}
return NULL;
}
//------------------------------------------------------------------------------
BMenuItem *BMenu::FindItem(uint32 command) const
{
return NULL;
}
//------------------------------------------------------------------------------
status_t BMenu::SetTargetForItems(BHandler *handler)
{
for (int32 i = 0; i < fItems.CountItems(); i++)
if (((BMenuItem*)fItems.ItemAt(i))->SetTarget(handler) != B_OK)
return B_ERROR;
return B_OK;
}
//------------------------------------------------------------------------------
status_t BMenu::SetTargetForItems(BMessenger messenger)
{
for (int32 i = 0; i < fItems.CountItems (); i++)
if (((BMenuItem*)fItems.ItemAt(i))->SetTarget(messenger) != B_OK)
return B_ERROR;
return B_OK;
}
//------------------------------------------------------------------------------
void BMenu::SetEnabled(bool enabled)
{
fEnabled = enabled;
for (int32 i = 0; i < CountItems(); i++)
ItemAt(i)->SetEnabled(enabled);
}
//------------------------------------------------------------------------------
void BMenu::SetRadioMode(bool flag)
{
fRadioMode = flag;
}
//------------------------------------------------------------------------------
void BMenu::SetTriggersEnabled(bool flag)
{
fTriggerEnabled = flag;
}
//------------------------------------------------------------------------------
void BMenu::SetMaxContentWidth(float width)
{
fMaxContentWidth = width;
}
//------------------------------------------------------------------------------
void BMenu::SetLabelFromMarked(bool flag)
{
}
//------------------------------------------------------------------------------
bool BMenu::IsLabelFromMarked()
{
return false;
}
//------------------------------------------------------------------------------
bool BMenu::IsEnabled() const
{
return fEnabled;
}
//------------------------------------------------------------------------------
bool BMenu::IsRadioMode() const
{
return fRadioMode;
}
//------------------------------------------------------------------------------
bool BMenu::AreTriggersEnabled() const
{
return fTriggerEnabled;
}
//------------------------------------------------------------------------------
bool BMenu::IsRedrawAfterSticky() const
{
return fRedrawAfterSticky;
}
//------------------------------------------------------------------------------
float BMenu::MaxContentWidth() const
{
return fMaxContentWidth;
}
//------------------------------------------------------------------------------
BMenuItem *BMenu::FindMarked()
{
for (int i =0; i < fItems.CountItems(); i++)
if (((BMenuItem*)fItems.ItemAt(i))->IsMarked())
return (BMenuItem*)fItems.ItemAt(i);
return NULL;
}
//------------------------------------------------------------------------------
BMenu *BMenu::Supermenu() const
{
return fSuper;
}
//------------------------------------------------------------------------------
BMenuItem *BMenu::Superitem() const
{
return fSuperitem;
}
//------------------------------------------------------------------------------
void BMenu::MessageReceived(BMessage *msg)
{
BView::MessageReceived(msg);
}
//------------------------------------------------------------------------------
void BMenu::KeyDown(const char *bytes, int32 numBytes)
{
switch (bytes[0])
{
case B_UP_ARROW:
{
if (fSelected)
{
fSelected->fSelected = false;
if ( fSelected == fItems.FirstItem())
fSelected = (BMenuItem*)fItems.LastItem();
else
fSelected = ItemAt(IndexOf(fSelected) - 1);
}
else
fSelected = (BMenuItem*)fItems.LastItem();
fSelected->fSelected = true;
break;
}
case B_DOWN_ARROW:
{
if (fSelected)
{
fSelected->fSelected = false;
if (fSelected == fItems.LastItem())
fSelected = (BMenuItem*)fItems.FirstItem();
else
fSelected = ItemAt(IndexOf(fSelected) + 1);
}
else
fSelected = (BMenuItem*)fItems.FirstItem();
fSelected->fSelected = true;
break;
}
case B_HOME:
{
if (fSelected)
fSelected->fSelected = false;
fSelected = (BMenuItem*)fItems.FirstItem();
fSelected->fSelected = true;
break;
}
case B_END:
{
if (fSelected)
fSelected->fSelected = false;
fSelected = (BMenuItem*)fItems.LastItem();
fSelected->fSelected = true;
break;
}
case B_ENTER:
case B_SPACE:
{
if (fSelected)
InvokeItem(fSelected);
break;
}
default:
BView::KeyDown(bytes, numBytes);
}
}
//------------------------------------------------------------------------------
void BMenu::Draw(BRect updateRect)
{
BRect bounds(Bounds());
SetHighColor(tint_color(ui_color(B_MENU_BACKGROUND_COLOR), B_DARKEN_4_TINT));
StrokeRect(bounds);
SetHighColor(tint_color(ui_color(B_MENU_BACKGROUND_COLOR), B_DARKEN_2_TINT));
StrokeLine(BPoint(bounds.left + 2, bounds.bottom - 1),
BPoint(bounds.right - 1, bounds.bottom - 1));
StrokeLine(BPoint(bounds.right - 1, bounds.top + 1));
SetHighColor(tint_color ( ui_color ( B_MENU_BACKGROUND_COLOR ), B_LIGHTEN_2_TINT));
StrokeLine(BPoint(bounds.right - 2, bounds.top + 1),
BPoint(bounds.left + 1, bounds.top + 1));
StrokeLine(BPoint(bounds.left + 1, bounds.bottom - 2));
DrawItems(updateRect);
}
//------------------------------------------------------------------------------
void BMenu::GetPreferredSize(float *width, float *height)
{
}
//------------------------------------------------------------------------------
void BMenu::ResizeToPreferred()
{
}
//------------------------------------------------------------------------------
void BMenu::FrameMoved(BPoint new_position)
{
}
//------------------------------------------------------------------------------
void BMenu::FrameResized(float new_width, float new_height)
{
}
//------------------------------------------------------------------------------
void BMenu::InvalidateLayout()
{
CacheFontInfo();
LayoutItems(0);
}
//------------------------------------------------------------------------------
BHandler *BMenu::ResolveSpecifier(BMessage *msg, int32 index,
BMessage *specifier, int32 form,
const char *property)
{
BPropertyInfo propInfo(prop_list);
BHandler *target = NULL;
switch (propInfo.FindMatch(msg, 0, specifier, form, property))
{
case B_ERROR:
break;
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
target = this;
break;
case 8:
// TODO: redirect to menu
target = this;
break;
case 9:
case 10:
case 11:
case 12:
target = this;
break;
case 13:
// TODO: redirect to menuitem
target = this;
break;
}
if (!target)
target = BView::ResolveSpecifier(msg, index, specifier, form,
property);
return target;
}
//------------------------------------------------------------------------------
status_t BMenu::GetSupportedSuites(BMessage *data)
{
status_t err;
if (data == NULL)
return B_BAD_VALUE;
err = data->AddString("suites", "suite/vnd.Be-menu");
if (err != B_OK)
return err;
BPropertyInfo prop_info(prop_list);
err = data->AddFlat("messages", &prop_info);
if (err != B_OK)
return err;
return BView::GetSupportedSuites(data);
}
//------------------------------------------------------------------------------
status_t BMenu::Perform(perform_code d, void *arg)
{
return B_ERROR;
}
//------------------------------------------------------------------------------
void BMenu::MakeFocus(bool focused)
{
if (focused)
SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS);
BView::MakeFocus(focused);
}
//------------------------------------------------------------------------------
void BMenu::AllAttached()
{
}
//------------------------------------------------------------------------------
void BMenu::AllDetached()
{
}
//------------------------------------------------------------------------------
BMenu::BMenu(BRect frame, const char *name, uint32 resizingMode, uint32 flags,
menu_layout layout, bool resizeToFit)
: BView(frame, name, resizingMode, flags),
fChosenItem(NULL),
fSelected(NULL),
fCachedMenuWindow(NULL),
fSuper(NULL),
fSuperitem(NULL),
fAscent(-1.0f),
fDescent(-1.0f),
fFontHeight(-1.0f),
fState(0),
fLayout(layout),
fExtraRect(NULL),
fMaxContentWidth(0.0f),
fInitMatrixSize(NULL),
fExtraMenuData(NULL),
fTrigger(0),
fResizeToFit(resizeToFit),
fUseCachedMenuLayout(true),
fEnabled(true),
fDynamicName(false),
fRadioMode(false),
fTrackNewBounds(false),
fStickyMode(false),
fIgnoreHidden(true),
fTriggerEnabled(true),
fRedrawAfterSticky(true),
fAttachAborted(false)
{
SetViewColor(ui_color(B_MENU_BACKGROUND_COLOR));
SetFontSize(10);
}
//------------------------------------------------------------------------------
BPoint BMenu::ScreenLocation()
{
BMenu *superMenu = Supermenu();
if (superMenu == NULL)
return BPoint();
BMenuItem *superItem = Superitem();
if (superItem == NULL)
return BPoint();
BPoint point;
if (superMenu->Layout() == B_ITEMS_IN_COLUMN)
point = superItem->Frame().RightTop();
else
point = superItem->Frame().LeftBottom() + BPoint(0.0f, 1.0f);
superMenu->ConvertToScreen(&point);
return point;
}
//------------------------------------------------------------------------------
void BMenu::SetItemMargins(float left, float top, float right, float bottom)
{
fPad.Set(left, top, right, bottom);
}
//------------------------------------------------------------------------------
void BMenu::GetItemMargins(float *left, float *top, float *right,
float *bottom) const
{
*left = fPad.left;
*top = fPad.top;
*right = fPad.right;
*bottom = fPad.bottom;
}
//------------------------------------------------------------------------------
menu_layout BMenu::Layout() const
{
return fLayout;
}
//------------------------------------------------------------------------------
void BMenu::Show()
{
Show(false);
}
//------------------------------------------------------------------------------
void BMenu::Show(bool selectFirst)
{
_show(selectFirst);
}
//------------------------------------------------------------------------------
void BMenu::Hide()
{
_hide();
}
//------------------------------------------------------------------------------
BMenuItem *BMenu::Track(bool openAnyway, BRect *clickToOpenRect)
{
return NULL;
}
//------------------------------------------------------------------------------
bool BMenu::AddDynamicItem(add_state s)
{
return false;
}
//------------------------------------------------------------------------------
void BMenu::DrawBackground(BRect update)
{
}
//------------------------------------------------------------------------------
void BMenu::SetTrackingHook(menu_tracking_hook func, void *state)
{
}
//------------------------------------------------------------------------------
void BMenu::_ReservedMenu3() {}
void BMenu::_ReservedMenu4() {}
void BMenu::_ReservedMenu5() {}
void BMenu::_ReservedMenu6() {}
//------------------------------------------------------------------------------
BMenu &BMenu::operator=(const BMenu &)
{
return *this;
}
//------------------------------------------------------------------------------
void BMenu::InitData(BMessage *data)
{
}
//------------------------------------------------------------------------------
bool BMenu::_show(bool selectFirstItem)
{
BPoint point = ScreenLocation();
BWindow *window = new BMenuWindow(BRect(point.x, point.y,
point.x + 20, point.y + 200), this);
window->Show();
return true;
}
//------------------------------------------------------------------------------
void BMenu::_hide()
{
BWindow *window = Window();
if (window)
{
window->RemoveChild(this);
window->Lock();
window->Quit();
}
}
//------------------------------------------------------------------------------
BMenuItem *BMenu::_track(int *action, long start)
{
return NULL;
}
//------------------------------------------------------------------------------
bool BMenu::_AddItem(BMenuItem *item, int32 index)
{
return false;
}
//------------------------------------------------------------------------------
bool BMenu::RemoveItems(int32 index, int32 count, BMenuItem *item, bool del)
{
return false;
}
//------------------------------------------------------------------------------
void BMenu::LayoutItems(int32 index)
{
CalcTriggers();
float width, height;
ComputeLayout(index, true, true, &width, &height);
ResizeTo(width, height);
}
//------------------------------------------------------------------------------
void BMenu::ComputeLayout(int32 index, bool bestFit, bool moveItems,
float* width, float* height)
{
BRect frame;
float iWidth, iHeight;
BMenuItem *item;
if (fLayout == B_ITEMS_IN_COLUMN)
{
frame = BRect(0.0f, 0.0f, 0.0f, 2.0f);
for (int i = 0; i < fItems.CountItems(); i++)
{
item = (BMenuItem*)fItems.ItemAt(i);
item->GetContentSize(&iWidth, &iHeight);
if (item->fModifiers && item->fShortcutChar)
iWidth += 25.0f;
item->fBounds.left = 2.0f;
item->fBounds.top = frame.bottom;
item->fBounds.bottom = item->fBounds.top + iHeight + fPad.top + fPad.bottom;
frame.right = max_c(frame.right, iWidth + fPad.left + fPad.right);
frame.bottom = item->fBounds.bottom + 1.0f;
}
for (int i = 0; i < fItems.CountItems(); i++)
ItemAt(i)->fBounds.right = frame.right;
frame.right = (float)ceil(frame.right) + 2.0f;
frame.bottom += 1.0f;
}
else if (fLayout == B_ITEMS_IN_ROW)
{
font_height fh;
GetFontHeight(&fh);
frame = BRect(0.0f, 0.0f, 0.0f,
(float)ceil(fh.ascent) + (float)ceil(fh.descent) + fPad.top + fPad.bottom);
for (int i = 0; i < fItems.CountItems(); i++)
{
item = (BMenuItem*)fItems.ItemAt(i);
item->GetContentSize(&iWidth, &iHeight);
item->fBounds.left = frame.right;
item->fBounds.top = 0.0f;
item->fBounds.right = item->fBounds.left + iWidth + fPad.left + fPad.right;
frame.right = item->fBounds.right + 1.0f;
frame.bottom = max_c(frame.bottom, iHeight + fPad.top + fPad.bottom);
}
for (int i = 0; i < fItems.CountItems(); i++)
ItemAt(i)->fBounds.bottom = frame.bottom;
frame.right = (float)ceil(frame.right) + 8.0f;
}
if ((ResizingMode() & B_FOLLOW_LEFT_RIGHT) == B_FOLLOW_LEFT_RIGHT)
{
if (Parent())
*width = Parent()->Frame().Width() + 1.0f;
else
*width = Window()->Frame().Width() + 1.0f;
*height = frame.Height();
}
else
{
*width = frame.Width();
*height = frame.Height();
}
}
//------------------------------------------------------------------------------
BRect BMenu::Bump(BRect current, BPoint extent, int32 index) const
{
return BRect();
}
//------------------------------------------------------------------------------
BPoint BMenu::ItemLocInRect(BRect frame) const
{
return BPoint();
}
//------------------------------------------------------------------------------
BRect BMenu::CalcFrame(BPoint where, bool *scrollOn)
{
return BRect();
}
//------------------------------------------------------------------------------
bool BMenu::ScrollMenu(BRect bounds, BPoint loc, bool *fast)
{
return false;
}
//------------------------------------------------------------------------------
void BMenu::ScrollIntoView(BMenuItem *item)
{
}
//------------------------------------------------------------------------------
void BMenu::DrawItems(BRect updateRect)
{
for (int i =0; i < fItems.CountItems(); i++)
{
if (ItemAt(i)->Frame().Intersects(updateRect))
ItemAt(i)->Draw();
}
}
//------------------------------------------------------------------------------
int BMenu::State(BMenuItem **item) const
{
return 0;
}
//------------------------------------------------------------------------------
void BMenu::InvokeItem(BMenuItem *item, bool now)
{
if (item->Submenu())
item->Submenu()->Show();
else if (IsRadioMode())
item->SetMarked(true);
item->Invoke();
}
//------------------------------------------------------------------------------
bool BMenu::OverSuper(BPoint loc)
{
// TODO: we assume that loc is in screen coords
if (!Supermenu())
return false;
return Supermenu()->Window()->Frame().Contains(loc);
}
//------------------------------------------------------------------------------
bool BMenu::OverSubmenu(BMenuItem *item, BPoint loc)
{
// TODO: we assume that loc is in screen coords
if (!item->Submenu())
return false;
return item->Submenu()->Window()->Frame().Contains(loc);
}
//------------------------------------------------------------------------------
BMenuWindow *BMenu::MenuWindow()
{
return fCachedMenuWindow;
}
//------------------------------------------------------------------------------
void BMenu::DeleteMenuWindow()
{
delete fCachedMenuWindow;
fCachedMenuWindow = NULL;
}
//------------------------------------------------------------------------------
BMenuItem *BMenu::HitTestItems(BPoint where, BPoint slop) const
{
for (int i =0; i < CountItems(); i++)
if (ItemAt(i)->fBounds.Contains(where))
return ItemAt(i);
return NULL;
}
//------------------------------------------------------------------------------
BRect BMenu::Superbounds() const
{
return BRect();
}
//------------------------------------------------------------------------------
void BMenu::CacheFontInfo()
{
font_height fh;
GetFontHeight(&fh);
fAscent = fh.ascent;
fDescent = fh.descent;
fFontHeight = (float)ceil(fh.ascent + fh.descent + 0.5f);
}
//------------------------------------------------------------------------------
void BMenu::ItemMarked(BMenuItem *item)
{
if (IsRadioMode())
{
for (int32 i = 0; i < CountItems(); i++)
if (ItemAt(i) != item)
ItemAt(i)->SetMarked(false);
}
if (IsLabelFromMarked() && Superitem())
Superitem()->SetLabel(item->Label());
}
//------------------------------------------------------------------------------
void BMenu::Install(BWindow *target)
{
for (int i =0; i < CountItems(); i++)
ItemAt(i)->Install(target);
}
//------------------------------------------------------------------------------
void BMenu::Uninstall()
{
}
//------------------------------------------------------------------------------
void BMenu::SelectItem(BMenuItem *m, uint32 showSubmenu,bool selectFirstItem)
{
}
//------------------------------------------------------------------------------
BMenuItem *BMenu::CurrentSelection() const
{
return fSelected;
}
//------------------------------------------------------------------------------
bool BMenu::SelectNextItem(BMenuItem *item, bool forward)
{
return false;
}
//------------------------------------------------------------------------------
BMenuItem *BMenu::NextItem(BMenuItem *item, bool forward) const
{
return NULL;
}
//------------------------------------------------------------------------------
bool BMenu::IsItemVisible(BMenuItem *item) const
{
return false;
}
//------------------------------------------------------------------------------
void BMenu::SetIgnoreHidden(bool on)
{
fIgnoreHidden = on;
}
//------------------------------------------------------------------------------
void BMenu::SetStickyMode(bool on)
{
fStickyMode = on;
}
//------------------------------------------------------------------------------
bool BMenu::IsStickyMode() const
{
return fStickyMode;
}
//------------------------------------------------------------------------------
void BMenu::CalcTriggers()
{
}
//------------------------------------------------------------------------------
const char *BMenu::ChooseTrigger(const char *title, BList *chars)
{
return NULL;
}
//------------------------------------------------------------------------------
void BMenu::UpdateWindowViewSize(bool upWind)
{
}
//------------------------------------------------------------------------------
bool BMenu::IsStickyPrefOn()
{
return false;
}
//------------------------------------------------------------------------------
void BMenu::RedrawAfterSticky(BRect bounds)
{
}
//------------------------------------------------------------------------------
bool BMenu::OkToProceed(BMenuItem *)
{
return false;
}
//------------------------------------------------------------------------------
status_t BMenu::ParseMsg(BMessage *msg, int32 *sindex, BMessage *spec,
int32 *form, const char **prop, BMenu **tmenu,
BMenuItem **titem, int32 *user_data,
BMessage *reply) const
{
return B_ERROR;
}
//------------------------------------------------------------------------------
status_t BMenu::DoMenuMsg(BMenuItem **next, BMenu *tar, BMessage *m,
BMessage *r, BMessage *spec, int32 f) const
{
return B_ERROR;
}
//------------------------------------------------------------------------------
status_t BMenu::DoMenuItemMsg(BMenuItem **next, BMenu *tar, BMessage *m,
BMessage *r, BMessage *spec, int32 f) const
{
return B_ERROR;
}
//------------------------------------------------------------------------------
status_t BMenu::DoEnabledMsg(BMenuItem *ti, BMenu *tm, BMessage *m,
BMessage *r) const
{
return B_ERROR;
}
//------------------------------------------------------------------------------
status_t BMenu::DoLabelMsg(BMenuItem *ti, BMenu *tm, BMessage *m,
BMessage *r) const
{
return B_ERROR;
}
//------------------------------------------------------------------------------
status_t BMenu::DoMarkMsg(BMenuItem *ti, BMenu *tm, BMessage *m,
BMessage *r) const
{
return B_ERROR;
}
//------------------------------------------------------------------------------
status_t BMenu::DoDeleteMsg(BMenuItem *ti, BMenu *tm, BMessage *m,
BMessage *r) const
{
return B_ERROR;
}
//------------------------------------------------------------------------------
status_t BMenu::DoCreateMsg(BMenuItem *ti, BMenu *tm, BMessage *m,
BMessage *r, bool menu) const
{
return B_ERROR;
}
//------------------------------------------------------------------------------
// Temporary mouse hooks
//------------------------------------------------------------------------------
void BMenu::MouseDown(BPoint point)
{
BMenuItem *item = HitTestItems(point);
if (item)
InvokeItem(item);
Hide();
}
//------------------------------------------------------------------------------
void BMenu::MouseMoved(BPoint point, uint32 transit, const BMessage *message)
{
BMenuItem *item = HitTestItems(point);
if (fSelected)
{
if (fSelected == item)
return;
fSelected->fSelected = false;
//if (fSelected->Submenu())
// fSelected->Submenu()->Hide();
Invalidate(fSelected->Frame());
}
fSelected = item;
if (fSelected)
{
fSelected->fSelected = true;
//if (fSelected->Submenu())
// fSelected->Submenu()->Show();
Invalidate(fSelected->Frame());
}
}
//------------------------------------------------------------------------------
void BMenu::MouseUp(BPoint point)
{
}
//------------------------------------------------------------------------------
status_t set_menu_info(menu_info *info)
{
BPath path;
if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK)
return B_OK;
path.Append("menu_settings");
BFile file(path.Path(), B_WRITE_ONLY | B_CREATE_FILE);
if (file.InitCheck() != B_OK)
return B_OK;
file.Write(info, sizeof(menu_info));
return B_OK;
}
//------------------------------------------------------------------------------
status_t get_menu_info(menu_info *info)
{
info->font_size = 8;
memcpy(info->f_family, "Arial", 6);
memcpy(info->f_style, "Regular", 8);
info->background_color = ui_color(B_MENU_BACKGROUND_COLOR);
info->separator = 0;
info->click_to_open = true;
info->triggers_always_shown = false;
BPath path;
if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK)
return B_OK;
path.Append("menu_settings");
BFile file(path.Path(), B_READ_ONLY);
if (file.InitCheck() != B_OK)
return B_OK;
file.Read(info, sizeof(menu_info));
return B_OK;
}
//------------------------------------------------------------------------------