From 4fa167e12d1c7feb2ac0cada5a3062d7d0cdc771 Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Sun, 17 Jun 2007 01:15:05 +0000 Subject: [PATCH] * Added layout-related methods (Min/Max/PreferredSize(), InvalidateLayout(), DoLayout()). * Don't resize the view and the window anymore, when fResizeToFit is not set. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21426 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/os/interface/Menu.h | 10 ++- src/kits/interface/Menu.cpp | 139 ++++++++++++++++++++++++++++++------ 2 files changed, 127 insertions(+), 22 deletions(-) diff --git a/headers/os/interface/Menu.h b/headers/os/interface/Menu.h index e853da3905..4d69cf0da4 100644 --- a/headers/os/interface/Menu.h +++ b/headers/os/interface/Menu.h @@ -113,11 +113,16 @@ virtual void SetMaxContentWidth(float max); virtual void MessageReceived(BMessage *msg); virtual void KeyDown(const char *bytes, int32 numBytes); virtual void Draw(BRect updateRect); +virtual BSize MinSize(); +virtual BSize MaxSize(); +virtual BSize PreferredSize(); virtual void GetPreferredSize(float *width, float *height); virtual void ResizeToPreferred(); +virtual void DoLayout(); virtual void FrameMoved(BPoint new_position); virtual void FrameResized(float new_width, float new_height); void InvalidateLayout(); +virtual void InvalidateLayout(bool descendants); virtual BHandler *ResolveSpecifier(BMessage *msg, int32 index, @@ -180,6 +185,8 @@ friend status_t _init_interface_kit_(); friend status_t set_menu_info(menu_info *); friend status_t get_menu_info(menu_info *); +struct LayoutData; + virtual void _ReservedMenu3(); virtual void _ReservedMenu4(); virtual void _ReservedMenu5(); @@ -202,6 +209,7 @@ virtual void _ReservedMenu6(); bool del = false); bool RelayoutIfNeeded(); void LayoutItems(int32 index); + BSize _ValidatePreferredSize(); void ComputeLayout(int32 index, bool bestFit, bool moveItems, float* width, float* height); void _ComputeColumnLayout(int32 index, bool bestFit, bool moveItems, BRect &outRect); @@ -292,7 +300,7 @@ static bool sAltAsCommandKey; BPoint *fInitMatrixSize; _ExtraMenuData_ *fExtraMenuData; - uint32 _reserved[1]; + LayoutData* fLayoutData; int32 fSubmenus; diff --git a/src/kits/interface/Menu.cpp b/src/kits/interface/Menu.cpp index 9f4477d716..5801fe87d7 100644 --- a/src/kits/interface/Menu.cpp +++ b/src/kits/interface/Menu.cpp @@ -14,6 +14,8 @@ #include #include #include +#include +#include #include #include #include @@ -143,6 +145,11 @@ sPropList[] = { const char *kEmptyMenuLabel = ""; +struct BMenu::LayoutData { + BSize preferred; +}; + + BMenu::BMenu(const char *name, menu_layout layout) : BView(BRect(0, 0, 0, 0), name, 0, B_WILL_DRAW), fChosenItem(NULL), @@ -220,6 +227,7 @@ BMenu::~BMenu() delete fInitMatrixSize; delete fExtraMenuData; + delete fLayoutData; } @@ -840,10 +848,48 @@ BMenu::Draw(BRect updateRect) } +BSize +BMenu::MinSize() +{ + _ValidatePreferredSize(); + + BSize size = (GetLayout() ? GetLayout()->MinSize() + : fLayoutData->preferred); + return BLayoutUtils::ComposeSize(ExplicitMinSize(), size); +} + + +BSize +BMenu::MaxSize() +{ + _ValidatePreferredSize(); + + BSize size = (GetLayout() ? GetLayout()->MaxSize() + : fLayoutData->preferred); + return BLayoutUtils::ComposeSize(ExplicitMaxSize(), size); +} + + +BSize +BMenu::PreferredSize() +{ + _ValidatePreferredSize(); + + BSize size = (GetLayout() ? GetLayout()->PreferredSize() + : fLayoutData->preferred); + return BLayoutUtils::ComposeSize(ExplicitPreferredSize(), size); +} + + void BMenu::GetPreferredSize(float *_width, float *_height) { - ComputeLayout(0, true, false, _width, _height); + _ValidatePreferredSize(); + + if (_width) + *_width = fLayoutData->preferred.width; + if (_height) + *_height = fLayoutData->preferred.height; } @@ -854,6 +900,21 @@ BMenu::ResizeToPreferred() } +void +BMenu::DoLayout() +{ + // If the user set a layout, we let the base class version call its + // hook. + if (GetLayout()) { + BView::DoLayout(); + return; + } + + if (RelayoutIfNeeded()) + Invalidate(); +} + + void BMenu::FrameMoved(BPoint new_position) { @@ -870,8 +931,18 @@ BMenu::FrameResized(float new_width, float new_height) void BMenu::InvalidateLayout() +{ + InvalidateLayout(false); +} + + +void +BMenu::InvalidateLayout(bool descendants) { fUseCachedMenuLayout = false; + fLayoutData->preferred.Set(B_SIZE_UNSET, B_SIZE_UNSET); + + BView::InvalidateLayout(descendants); } @@ -1127,10 +1198,12 @@ BMenu::InitData(BMessage *data) font.SetFamilyAndStyle(sMenuInfo.f_family, sMenuInfo.f_style); font.SetSize(sMenuInfo.font_size); SetFont(&font, B_FONT_FAMILY_AND_STYLE | B_FONT_SIZE); - + + fLayoutData = new LayoutData; + SetLowColor(sMenuInfo.background_color); SetViewColor(sMenuInfo.background_color); - + if (data != NULL) { data->FindInt32("_layout", (int32 *)&fLayout); data->FindBool("_rsize_to_fit", &fResizeToFit); @@ -1488,10 +1561,13 @@ BMenu::RemoveItems(int32 index, int32 count, BMenuItem *item, bool deleteItems) } } - if (invalidateLayout && locked && window != NULL) { - LayoutItems(0); - UpdateWindowViewSize(false); - Invalidate(); + if (invalidateLayout) { + InvalidateLayout(); + if (locked && window != NULL) { + LayoutItems(0); + UpdateWindowViewSize(false); + Invalidate(); + } } if (locked) @@ -1522,7 +1598,18 @@ BMenu::LayoutItems(int32 index) float width, height; ComputeLayout(index, fResizeToFit, true, &width, &height); - ResizeTo(width, height); + if (fResizeToFit) + ResizeTo(width, height); +} + + +BSize +BMenu::_ValidatePreferredSize() +{ + if (!fLayoutData->preferred.IsWidthSet()) + ComputeLayout(0, true, false, NULL, NULL); + + return fLayoutData->preferred; } @@ -1552,21 +1639,28 @@ BMenu::ComputeLayout(int32 index, bool bestFit, bool moveItems, break; } - if (_width) { - // change width depending on resize mode - if ((ResizingMode() & B_FOLLOW_LEFT_RIGHT) == B_FOLLOW_LEFT_RIGHT) { - if (Parent()) - *_width = Parent()->Frame().Width() + 1; - else if (Window()) - *_width = Window()->Frame().Width() + 1; - else - *_width = Bounds().Width(); - } else - *_width = frame.Width(); - } + // change width depending on resize mode + BSize size; + if ((ResizingMode() & B_FOLLOW_LEFT_RIGHT) == B_FOLLOW_LEFT_RIGHT) { + if (Parent()) + size.width = Parent()->Frame().Width() + 1; + else if (Window()) + size.width = Window()->Frame().Width() + 1; + else + size.width = Bounds().Width(); + } else + size.width = frame.Width(); + + size.height = frame.Height(); + + if (_width) + *_width = size.width; if (_height) - *_height = frame.Height(); + *_height = size.height; + + if (bestFit) + fLayoutData->preferred = size; if (moveItems) fUseCachedMenuLayout = true; @@ -2152,6 +2246,9 @@ BMenu::UpdateWindowViewSize(bool upWind) if (dynamic_cast(this) != NULL) return; + if (fResizeToFit) + return; + bool scroll; const BPoint screenLocation = upWind ? ScreenLocation() : window->Frame().LeftTop(); BRect frame = CalcFrame(screenLocation, &scroll);