From 10f4d0679a8df9f72c2a295b2f2ac80ea776538b Mon Sep 17 00:00:00 2001 From: Stefano Ceccherini Date: Fri, 11 Apr 2008 08:22:09 +0000 Subject: [PATCH] Added a class MenuPrivate to handle access to private BMenu methods. BMenuItem and BWindow are no longer friends of BMenu, but use this class instead. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@24909 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/os/interface/Menu.h | 4 +- headers/private/interface/MenuPrivate.h | 35 +++++++ src/kits/interface/Menu.cpp | 118 ++++++++++++++++++++++++ src/kits/interface/MenuItem.cpp | 67 +++++++++----- src/kits/interface/Window.cpp | 17 ++-- 5 files changed, 208 insertions(+), 33 deletions(-) diff --git a/headers/os/interface/Menu.h b/headers/os/interface/Menu.h index b3b4b1d9e7..335a27c2ec 100644 --- a/headers/os/interface/Menu.h +++ b/headers/os/interface/Menu.h @@ -19,6 +19,7 @@ namespace BPrivate { class BMenuWindow; class ExtraMenuData; class TriggerList; + class MenuPrivate; } enum menu_layout { @@ -159,9 +160,8 @@ public: void* state); private: - friend class BWindow; friend class BMenuBar; - friend class BMenuItem; + friend class BPrivate::MenuPrivate; friend status_t _init_interface_kit_(); friend status_t set_menu_info(menu_info* info); friend status_t get_menu_info(menu_info* info); diff --git a/headers/private/interface/MenuPrivate.h b/headers/private/interface/MenuPrivate.h index 05f8850124..7f96b4187b 100644 --- a/headers/private/interface/MenuPrivate.h +++ b/headers/private/interface/MenuPrivate.h @@ -8,6 +8,41 @@ enum menu_states { MENU_STATE_CLOSED = 5 }; +class BMenu; +class BWindow; + +namespace BPrivate { + +class MenuPrivate { +public: + MenuPrivate(BMenu *menu); + + menu_layout Layout() const; + + void ItemMarked(BMenuItem *item); + void CacheFontInfo(); + + float FontHeight() const; + float Ascent() const; + BRect Padding() const; + void GetItemMargins(float *, float *, float *, float *) const; + + bool IsAltCommandKey() const; + int State(BMenuItem **item = NULL) const; + + void Install(BWindow *window); + void Uninstall(); + void SetSuper(BMenu *menu); + void SetSuperItem(BMenuItem *item); + void InvokeItem(BMenuItem *item, bool now = false); + void QuitTracking(bool thisMenuOnly = true); + +private: + BMenu *fMenu; +}; + +}; + extern const char *kEmptyMenuLabel; diff --git a/src/kits/interface/Menu.cpp b/src/kits/interface/Menu.cpp index 5a671c9dee..75f16ea5cc 100644 --- a/src/kits/interface/Menu.cpp +++ b/src/kits/interface/Menu.cpp @@ -2620,3 +2620,121 @@ get_menu_info(menu_info *info) return status; } + + +// MenuPrivate +namespace BPrivate { + +MenuPrivate::MenuPrivate(BMenu *menu) + : + fMenu(menu) +{ +} + + +menu_layout +MenuPrivate::Layout() const +{ + return fMenu->Layout(); +} + + +void +MenuPrivate::ItemMarked(BMenuItem *item) +{ + fMenu->_ItemMarked(item); +} + + +void +MenuPrivate::CacheFontInfo() +{ + fMenu->_CacheFontInfo(); +} + + +float +MenuPrivate::FontHeight() const +{ + return fMenu->fFontHeight; +} + + +float +MenuPrivate::Ascent() const +{ + return fMenu->fAscent; +} + + +BRect +MenuPrivate::Padding() const +{ + return fMenu->fPad; +} + + +void +MenuPrivate::GetItemMargins(float *left, float *top, + float *right, float *bottom) const +{ + fMenu->GetItemMargins(left, top, right, bottom); +} + + +bool +MenuPrivate::IsAltCommandKey() const +{ + return fMenu->sAltAsCommandKey; +} + + +int +MenuPrivate::State(BMenuItem **item) const +{ + return fMenu->State(item); +} + + +void +MenuPrivate::Install(BWindow *window) +{ + fMenu->_Install(window); +} + + +void +MenuPrivate::Uninstall() +{ + fMenu->_Uninstall(); +} + + +void +MenuPrivate::SetSuper(BMenu *menu) +{ + fMenu->fSuper = menu; +} + + +void +MenuPrivate::SetSuperItem(BMenuItem *item) +{ + fMenu->fSuperitem = item; +} + + +void +MenuPrivate::InvokeItem(BMenuItem *item, bool now) +{ + fMenu->InvokeItem(item, now); +} + + +void +MenuPrivate::QuitTracking(bool thisMenuOnly) +{ + fMenu->QuitTracking(thisMenuOnly); +} + +} ; diff --git a/src/kits/interface/MenuItem.cpp b/src/kits/interface/MenuItem.cpp index 7098b776b2..0e0ddb1d1b 100644 --- a/src/kits/interface/MenuItem.cpp +++ b/src/kits/interface/MenuItem.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2001-2007, Haiku, Inc. + * Copyright 2001-2008, Haiku, Inc. * Distributed under the terms of the MIT License. * * Authors: @@ -21,6 +21,8 @@ #include #include +#include + #include "utf8_functions.h" const unsigned char kCtrlBits[] = { @@ -69,6 +71,7 @@ const unsigned char kShiftBits[] = { const float kLightBGTint = (B_LIGHTEN_1_TINT + B_LIGHTEN_1_TINT + B_NO_TINT) / 3.0; +using BPrivate::MenuPrivate; BMenuItem::BMenuItem(const char *label, BMessage *message, char shortcut, uint32 modifiers) @@ -247,8 +250,10 @@ BMenuItem::SetMarked(bool state) { fMark = state; - if (state && Menu() != NULL) - Menu()->_ItemMarked(this); + if (state && Menu() != NULL) { + MenuPrivate priv(Menu()); + priv.ItemMarked(this); + } } @@ -372,14 +377,18 @@ BMenuItem::Frame() const void BMenuItem::GetContentSize(float *width, float *height) { - fSuper->_CacheFontInfo(); + // TODO: Get rid of this. BMenu should handle this + // automatically. Maybe it's not even needed, since our + // BFont::Height() caches the value locally + MenuPrivate(fSuper).CacheFontInfo(); fCachedWidth = fSuper->StringWidth(fLabel); if (width) *width = (float)ceil(fCachedWidth); - if (height) - *height = fSuper->fFontHeight; + if (height) { + *height = MenuPrivate(fSuper).FontHeight(); + } } @@ -399,9 +408,9 @@ BMenuItem::TruncateLabel(float maxWidth, char *newLabel) void BMenuItem::DrawContent() { - fSuper->_CacheFontInfo(); + MenuPrivate(fSuper).CacheFontInfo(); - fSuper->MovePenBy(0, fSuper->fAscent); + fSuper->MovePenBy(0, MenuPrivate(fSuper).Ascent()); BPoint lineStart = fSuper->PenLocation(); float labelWidth, labelHeight; @@ -472,7 +481,8 @@ BMenuItem::Draw() DrawContent(); // draw extra symbols - if (fSuper->Layout() == B_ITEMS_IN_COLUMN) { + const menu_layout layout = MenuPrivate(fSuper).Layout(); + if (layout == B_ITEMS_IN_COLUMN) { if (IsMarked()) _DrawMarkSymbol(bgColor); @@ -504,8 +514,10 @@ BMenuItem::IsSelected() const BPoint BMenuItem::ContentLocation() const { - return BPoint(fBounds.left + Menu()->fPad.left, - fBounds.top + Menu()->fPad.top); + const BRect &padding = MenuPrivate(fSuper).Padding(); + + return BPoint(fBounds.left + padding.left, + fBounds.top + padding.top); } @@ -550,7 +562,8 @@ void BMenuItem::_InitMenuData(BMenu *menu) { fSubmenu = menu; - fSubmenu->fSuperitem = this; + + MenuPrivate(fSubmenu).SetSuperItem(this); BMenuItem *item = menu->FindMarked(); @@ -564,9 +577,10 @@ BMenuItem::_InitMenuData(BMenu *menu) void BMenuItem::Install(BWindow *window) { - if (fSubmenu) - fSubmenu->_Install(window); - + if (fSubmenu) { + MenuPrivate(fSubmenu).Install(window); + } + fWindow = window; if (fShortcutChar != 0 && (fModifiers & B_COMMAND_KEY) && fWindow) @@ -619,9 +633,10 @@ BMenuItem::Invoke(BMessage *message) void BMenuItem::Uninstall() { - if (fSubmenu != NULL) - fSubmenu->_Uninstall(); - + if (fSubmenu != NULL) { + MenuPrivate(fSubmenu).Uninstall(); + } + if (Target() == fWindow) SetTarget(BMessenger()); @@ -640,7 +655,7 @@ BMenuItem::SetSuper(BMenu *super) debugger("Error - can't add menu or menu item to more than 1 container (either menu or menubar)."); if (fSubmenu != NULL) { - fSubmenu->fSuper = super; + MenuPrivate(fSubmenu).SetSuper(super); } fSuper = super; @@ -667,7 +682,7 @@ BMenuItem::_DrawMarkSymbol(rgb_color bgColor) BRect r(fBounds); float leftMargin; - fSuper->GetItemMargins(&leftMargin, NULL, NULL, NULL); + MenuPrivate(fSuper).GetItemMargins(&leftMargin, NULL, NULL, NULL); r.right = r.left + leftMargin - 3; r.left += 1; @@ -715,28 +730,30 @@ BMenuItem::_DrawShortcutSymbol() if (fSubmenu) where.x -= fBounds.Height() - 3; + const float ascent = MenuPrivate(fSuper).Ascent(); switch (fShortcutChar) { case B_DOWN_ARROW: case B_UP_ARROW: case B_LEFT_ARROW: case B_RIGHT_ARROW: case B_ENTER: - _DrawControlChar(fShortcutChar, where + BPoint(0, fSuper->fAscent)); + _DrawControlChar(fShortcutChar, where + BPoint(0, ascent)); break; default: - fSuper->DrawChar(fShortcutChar, where + BPoint(0, fSuper->fAscent)); + fSuper->DrawChar(fShortcutChar, where + BPoint(0, ascent)); break; } where.y += (fBounds.Height() - 11) / 2 - 1; where.x -= 4; + const bool altCommandKey = MenuPrivate(fSuper).IsAltCommandKey(); if (fModifiers & B_COMMAND_KEY) { BRect rect(0,0,16,10); BBitmap control(rect, B_CMAP8); - if (BMenu::sAltAsCommandKey) + if (altCommandKey) control.ImportBits(kAltBits, sizeof(kAltBits), 17, 0, B_CMAP8); else control.ImportBits(kCtrlBits, sizeof(kCtrlBits), 17, 0, B_CMAP8); @@ -749,7 +766,7 @@ BMenuItem::_DrawShortcutSymbol() BRect rect(0,0,16,10); BBitmap control(rect, B_CMAP8); - if (BMenu::sAltAsCommandKey) + if (altCommandKey) control.ImportBits(kCtrlBits, sizeof(kCtrlBits), 17, 0, B_CMAP8); else control.ImportBits(kAltBits, sizeof(kAltBits), 17, 0, B_CMAP8); @@ -774,7 +791,7 @@ BMenuItem::_DrawSubmenuSymbol(rgb_color bgColor) BRect r(fBounds); float rightMargin; - fSuper->GetItemMargins(NULL, NULL, &rightMargin, NULL); + MenuPrivate(fSuper).GetItemMargins(NULL, NULL, &rightMargin, NULL); r.left = r.right - rightMargin + 3; r.right -= 1; diff --git a/src/kits/interface/Window.cpp b/src/kits/interface/Window.cpp index 2bd7b65bd1..5cb96e38a8 100644 --- a/src/kits/interface/Window.cpp +++ b/src/kits/interface/Window.cpp @@ -94,6 +94,7 @@ class BWindow::Shortcut { using BPrivate::gDefaultTokens; +using BPrivate::MenuPrivate; static property_info sWindowPropInfo[] = { { @@ -359,8 +360,9 @@ BWindow::BWindow(BRect frame, int32 bitmapToken) BWindow::~BWindow() { - if (BMenu *menu = dynamic_cast(fFocus)) - menu->QuitTracking(); + if (BMenu *menu = dynamic_cast(fFocus)) { + MenuPrivate(menu).QuitTracking(); + } // The BWindow is locked when the destructor is called, // we need to unlock because the menubar thread tries @@ -1052,9 +1054,10 @@ FrameMoved(origin); // Close an eventually opened menu // unless the target is the menu itself BMenu *menu = dynamic_cast(fFocus); + MenuPrivate privMenu(menu); if (menu != NULL && menu != view - && menu->State() != MENU_STATE_CLOSED) { - menu->QuitTracking(); + && privMenu.State() != MENU_STATE_CLOSED) { + privMenu.QuitTracking(); return; } @@ -3260,8 +3263,10 @@ BWindow::_HandleKeyDown(BMessage* event) // example) if (shortcut->MenuItem() != NULL) { BMenu* menu = shortcut->MenuItem()->Menu(); - if (menu != NULL) - menu->InvokeItem(shortcut->MenuItem(), true); + if (menu != NULL) { + MenuPrivate(menu).InvokeItem(shortcut->MenuItem(), + true); + } } else { BHandler* target = shortcut->Target(); if (target == NULL)