From 376d3e580420d92a5edd05b2f86efd94161df4ed Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Tue, 15 May 2007 15:41:27 +0000 Subject: [PATCH] Added a bit of layout management to the test views framework. The maximum size of the view tested can now be overridden explicitly. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21142 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../interface/layout/WidgetLayoutTest.cpp | 782 ++++++++++++++++-- 1 file changed, 694 insertions(+), 88 deletions(-) diff --git a/src/tests/kits/interface/layout/WidgetLayoutTest.cpp b/src/tests/kits/interface/layout/WidgetLayoutTest.cpp index 4700228191..e600355272 100644 --- a/src/tests/kits/interface/layout/WidgetLayoutTest.cpp +++ b/src/tests/kits/interface/layout/WidgetLayoutTest.cpp @@ -19,7 +19,9 @@ // internal messages enum { - MSG_2D_SLIDER_VALUE_CHANGED = '2dsv', + MSG_LAYOUT_CONTAINER = 'layc', + MSG_2D_SLIDER_VALUE_CHANGED = '2dsv', + MSG_UNLIMITED_MAX_SIZE_CHANGED = 'usch', }; @@ -35,12 +37,23 @@ operator+(const BPoint& p, const BSize& size) // View class View { public: + View() + : fFrame(0, 0, 0, 0), + fContainer(NULL), + fParent(NULL), + fChildren(), + fViewColor(B_TRANSPARENT_32_BIT), + fLayoutValid(false) + { + } + View(BRect frame) : fFrame(frame), fContainer(NULL), fParent(NULL), fChildren(), - fViewColor(B_TRANSPARENT_32_BIT) + fViewColor(B_TRANSPARENT_32_BIT), + fLayoutValid(false) { } @@ -61,6 +74,12 @@ public: FrameChanged(oldFrame, frame); } + + // relayout if necessary + if (!fLayoutValid) { + Layout(); + fLayoutValid = true; + } } BRect Frame() const @@ -96,6 +115,26 @@ public: return Frame().Size(); } + virtual BSize MinSize() + { + return BSize(-1, -1); + } + + virtual BSize MaxSize() + { + return BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED); + } + + virtual BSize PreferredSize() + { + return MinSize(); + } + + virtual BAlignment Alignment() + { + return BAlignment(B_ALIGN_HORIZONTAL_CENTER, B_ALIGN_VERTICAL_CENTER); + } + BPoint LocationInContainer() const { BPoint location = fFrame.LeftTop(); @@ -155,6 +194,7 @@ public: child->_AddedToParent(this); child->Invalidate(); + InvalidateLayout(); return true; } @@ -177,6 +217,8 @@ public: child->_RemovingFromParent(); fChildren.RemoveItem(index); + InvalidateLayout(); + return child; } @@ -240,6 +282,20 @@ public: Invalidate(Bounds()); } + virtual void InvalidateLayout() + { + if (fLayoutValid) { + fLayoutValid = false; + if (fParent) + fParent->InvalidateLayout(); + } + } + + bool IsLayoutValid() const + { + return fLayoutValid; + } + void SetViewColor(rgb_color color) { fViewColor = color; @@ -273,6 +329,13 @@ public: { } + virtual void Layout() + { + // simply trigger relayouting the children + for (int32 i = 0; View* child = ChildAt(i); i++) + child->SetFrame(child->Frame()); + } + protected: virtual void _AddedToParent(View* parent) { @@ -314,9 +377,6 @@ protected: void _Draw(BView* container, BRect updateRect) { -//printf("%p->View::_Draw(): ", this); -//updateRect.PrintToStream(); - // compute the clipping region BRegion region(Bounds()); for (int32 i = 0; View* child = ChildAt(i); i++) @@ -367,6 +427,7 @@ private: View* fParent; BList fChildren; rgb_color fViewColor; + bool fLayoutValid; }; @@ -382,6 +443,34 @@ public: _AddedToContainer(this); } + virtual void InvalidateLayout() + { + if (View::IsLayoutValid()) { + View::InvalidateLayout(); + + // trigger asynchronous re-layout + if (Window()) + Window()->PostMessage(MSG_LAYOUT_CONTAINER, this); + } + } + + virtual void MessageReceived(BMessage* message) + { + switch (message->what) { + case MSG_LAYOUT_CONTAINER: + View::Layout(); + break; + default: + BView::MessageReceived(message); + break; + } + } + + virtual void AllAttached() + { + Window()->PostMessage(MSG_LAYOUT_CONTAINER, this); + } + virtual void Draw(BRect updateRect) { View::_Draw(this, updateRect); @@ -587,8 +676,8 @@ private: // WrapperView class WrapperView : public View { public: - WrapperView(BRect frame, BView* view) - : View(frame), + WrapperView(BView* view) + : View(), fView(view), fInsets(1, 1, 1, 1) { @@ -600,17 +689,17 @@ public: return fView; } - BSize MinSize() const + virtual BSize MinSize() { return _FromViewSize(fView->MinSize()); } - BSize MaxSize() const + virtual BSize MaxSize() { return _FromViewSize(fView->MaxSize()); } - BSize PreferredSize() const + virtual BSize PreferredSize() { return _FromViewSize(fView->PreferredSize()); } @@ -673,13 +762,14 @@ private: // StringView class StringView : public View { public: - StringView(BRect frame, const char* string) - : View(frame), + StringView(const char* string) + : View(), fString(string), fAlignment(B_ALIGN_LEFT), fStringAscent(0), fStringDescent(0), - fStringWidth(0) + fStringWidth(0), + fExplicitMinSize(B_SIZE_UNSET, B_SIZE_UNSET) { SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); fTextColor = (rgb_color){ 0, 0, 0, 255 }; @@ -691,6 +781,7 @@ public: _UpdateStringMetrics(); Invalidate(); + InvalidateLayout(); } void SetAlignment(alignment align) @@ -707,9 +798,19 @@ public: Invalidate(); } - BSize PreferredSize() const + virtual BSize MinSize() { - return BSize(fStringWidth - 1, fStringAscent + fStringDescent - 1); + BSize size(fExplicitMinSize); + if (!size.IsWidthSet()) + size.width = fStringWidth - 1; + if (!size.IsHeightSet()) + size.height = fStringAscent + fStringDescent - 1; + return size; + } + + void SetExplicitMinSize(BSize size) + { + fExplicitMinSize = size; } virtual void AddedToContainer() @@ -767,6 +868,511 @@ private: float fStringAscent; float fStringDescent; float fStringWidth; + BSize fExplicitMinSize; +}; + + +// CheckBox +class CheckBox : public View, public BInvoker { +public: + CheckBox(BMessage* message = NULL, BMessenger target = BMessenger()) + : View(BRect(0, 0, 12, 12)), + BInvoker(message, target), + fSelected(false), + fPressed(false) + { + SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + } + + void SetSelected(bool selected) + { + if (selected != fSelected) { + fSelected = selected; + Invalidate(); + + // send the message + if (Message()) { + BMessage message(*Message()); + message.AddBool("selected", IsSelected()); + InvokeNotify(&message); + } + } + } + + bool IsSelected() const + { + return fSelected; + } + + virtual BSize MinSize() + { + return BSize(12, 12); + } + + virtual BSize MaxSize() + { + return MinSize(); + } + + virtual void Draw(BView* container, BRect updateRect) + { + BRect rect(Bounds()); + + if (fPressed) + container->SetHighColor((rgb_color){ 120, 0, 0, 255 }); + else + container->SetHighColor((rgb_color){ 0, 0, 0, 255 }); + + container->StrokeRect(rect); + + if (fPressed ? fPressedSelected : fSelected) { + rect.InsetBy(2, 2); + container->StrokeLine(rect.LeftTop(), rect.RightBottom()); + container->StrokeLine(rect.RightTop(), rect.LeftBottom()); + } + } + + virtual void MouseDown(BPoint where, uint32 buttons, int32 modifiers) + { + if (fPressed) + return; + + fPressed = true; + fPressedSelected = fSelected; + _PressedUpdate(where); + } + + virtual void MouseUp(BPoint where, uint32 buttons, int32 modifiers) + { + if (!fPressed || (buttons & B_PRIMARY_MOUSE_BUTTON)) + return; + + _PressedUpdate(where); + fPressed = false; + SetSelected(fPressedSelected); + Invalidate(); + } + + virtual void MouseMoved(BPoint where, uint32 buttons, int32 modifiers) + { + if (!fPressed) + return; + + _PressedUpdate(where); + } + +private: + void _PressedUpdate(BPoint where) + { + bool pressedSelected = Bounds().Contains(where) ^ fSelected; + if (pressedSelected != fPressedSelected) { + fPressedSelected = pressedSelected; + Invalidate(); + } + } + +private: + bool fSelected; + bool fPressed; + bool fPressedSelected; +}; + + +// GroupView +class GroupView : public View { +public: + GroupView(enum orientation orientation, int32 lineCount = 1) + : View(BRect(0, 0, 0, 0)), + fOrientation(orientation), + fLineCount(lineCount), + fColumnSpacing(0), + fRowSpacing(0), + fInsets(0, 0, 0, 0), + fMinMaxValid(false), + fColumnInfos(NULL), + fRowInfos(NULL) + { + SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + + if (fLineCount < 1) + fLineCount = 1; + } + + virtual ~GroupView() + { + delete fColumnInfos; + delete fRowInfos; + } + + void SetSpacing(float horizontal, float vertical) + { + if (horizontal != fColumnSpacing || vertical != fRowSpacing) { + fColumnSpacing = horizontal; + fRowSpacing = vertical; + + InvalidateLayout(); + } + } + + void SetInsets(float left, float top, float right, float bottom) + { + BRect newInsets(left, top, right, bottom); + if (newInsets != fInsets) { + fInsets = newInsets; + InvalidateLayout(); + } + } + + virtual BSize MinSize() + { + _ValidateMinMax(); + return _AddInsetsAndSpacing(BSize(fMinWidth - 1, fMinHeight - 1)); + } + + virtual BSize MaxSize() + { + _ValidateMinMax(); + return _AddInsetsAndSpacing(BSize(fMaxWidth - 1, fMaxHeight - 1)); + } + + virtual BSize PreferredSize() + { + _ValidateMinMax(); + return _AddInsetsAndSpacing(BSize(fPreferredWidth - 1, + fPreferredHeight - 1)); + } + + virtual BAlignment Alignment() + { + return BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_USE_FULL_HEIGHT); + } + + + virtual void Layout() + { + _ValidateMinMax(); + // actually a little late already + + BSize size = _SubtractInsetsAndSpacing(Size()); + _LayoutLine(size.IntegerWidth() + 1, fColumnInfos, fColumnCount); + _LayoutLine(size.IntegerHeight() + 1, fRowInfos, fRowCount); + + // layout children + BPoint location = fInsets.LeftTop(); + for (int32 column = 0; column < fColumnCount; column++) { + LayoutInfo& columnInfo = fColumnInfos[column]; + location.y = fInsets.top; + for (int32 row = 0; row < fRowCount; row++) { + View* child = _ChildAt(column, row); + if (!child) + continue; + + // get the grid cell frame + BRect cellFrame(location, + BSize(columnInfo.size - 1, fRowInfos[row].size - 1)); + + // align the child frame in the grid cell + BRect childFrame = BLayoutUtils::AlignInFrame(cellFrame, + child->MaxSize(), child->Alignment()); + + // layout child + child->SetFrame(childFrame); + + location.y += fRowInfos[row].size + fRowSpacing; + } + + location.x += columnInfo.size + fColumnSpacing; + } + } + +private: + struct LayoutInfo { + int32 min; + int32 max; + int32 preferred; + int32 size; + + LayoutInfo() + : min(0), + max(B_SIZE_UNLIMITED), + preferred(0) + { + } + + void AddConstraints(float addMin, float addMax, float addPreferred) + { + if (addMin >= min) + min = (int32)addMin + 1; + if (addMax <= max) + max = (int32)addMax + 1; + if (addPreferred >= preferred) + preferred = (int32)addPreferred + 1; + } + + void Normalize() + { + if (max > min) + max = min; + if (preferred < min) + preferred = min; + if (preferred > max) + preferred = max; + } + }; + +private: + void _ValidateMinMax() + { + if (fMinMaxValid) + return; + + delete fColumnInfos; + delete fRowInfos; + + fColumnCount = _ColumnCount(); + fRowCount = _RowCount(); + + fColumnInfos = new LayoutInfo[fColumnCount]; + fRowInfos = new LayoutInfo[fRowCount]; + + // collect the children's min/max constraints + for (int32 column = 0; column < fColumnCount; column++) { + for (int32 row = 0; row < fRowCount; row++) { + View* child = _ChildAt(column, row); + if (!child) + continue; + + BSize min = child->MinSize(); + BSize max = child->MaxSize(); + BSize preferred = child->PreferredSize(); + + // apply constraints to column/row info + fColumnInfos[column].AddConstraints(min.width, max.width, + preferred.width); + fRowInfos[row].AddConstraints(min.height, max.height, + preferred.height); + } + } + + // normalize the column/row constraints and compute sum min/max + fMinWidth = 0; + fMinHeight = 0; + fMaxWidth = 0; + fMaxHeight = 0; + fPreferredWidth = 0; + fPreferredHeight = 0; + + for (int32 column = 0; column < fColumnCount; column++) { + fColumnInfos[column].Normalize(); + fMinWidth = BLayoutUtils::AddSizesInt32(fMinWidth, + fColumnInfos[column].min); + fMaxWidth = BLayoutUtils::AddSizesInt32(fMaxWidth, + fColumnInfos[column].max); + fPreferredWidth = BLayoutUtils::AddSizesInt32(fPreferredWidth, + fColumnInfos[column].preferred); + } + + for (int32 row = 0; row < fRowCount; row++) { + fRowInfos[row].Normalize(); + fMinHeight = BLayoutUtils::AddSizesInt32(fMinHeight, + fRowInfos[row].min); + fMaxHeight = BLayoutUtils::AddSizesInt32(fMaxHeight, + fRowInfos[row].max); + fPreferredHeight = BLayoutUtils::AddSizesInt32(fPreferredHeight, + fRowInfos[row].preferred); + } + + fMinMaxValid = true; + } + + void _LayoutLine(int32 size, LayoutInfo* infos, int32 infoCount) + { + BList infosToLayout; + for (int32 i = 0; i < infoCount; i++) { + infos[i].size = 0; + infosToLayout.AddItem(infos + i); + } + + // Distribute the available space over the infos. Each iteration we + // try to distribute the remaining space evenly. We respect min and + // max constraints, though, add up the space we failed to assign + // due to the constraints, and use the sum as remaining space for the + // next iteration (can be negative). Then we ignore infos that can't + // shrink or grow anymore (depending on what would be needed). + while (!infosToLayout.IsEmpty()) { + BList canShrinkInfos; + BList canGrowInfos; + + int32 sizeDiff = 0; + int32 infosToLayoutCount = infosToLayout.CountItems(); + for (int32 i = 0; i < infosToLayoutCount; i++) { + LayoutInfo* info = (LayoutInfo*)infosToLayout.ItemAt(i); + info->size += (i + 1) * size / infosToLayoutCount + - i * size / infosToLayoutCount; + if (info->size < info->min) { + sizeDiff -= info->min - info->size; + info->size = info->min; + } else if (info->size > info->max) { + sizeDiff += info->size - info->max; + info->size = info->max; + } + + if (info->size > info->min) + canShrinkInfos.AddItem(info); + if (info->size < info->max) + canGrowInfos.AddItem(info); + } + + size = sizeDiff; + if (size == 0) + break; + + if (size > 0) + infosToLayout = canGrowInfos; + else + infosToLayout = canShrinkInfos; + } + + // If unassigned space is remaining, that means, that the group has + // been resized beyond its max size. We distribute the excess space + // evenly. + if (size > 0) { + for (int32 i = 0; i < infoCount; i++) { + infos[i].size += (i + 1) * size / infoCount + - i * size / infoCount; + } + } + } + + virtual BSize _AddInsetsAndSpacing(BSize size) + { + size.width = BLayoutUtils::AddDistances(size.width, + fInsets.left + fInsets.right - 1 + + (fColumnCount - 1) * fColumnSpacing); + size.height = BLayoutUtils::AddDistances(size.height, + fInsets.top + fInsets.bottom - 1 + + (fRowCount - 1) * fRowSpacing); + return size; + } + + virtual BSize _SubtractInsetsAndSpacing(BSize size) + { + size.width = BLayoutUtils::SubtractDistances(size.width, + fInsets.left + fInsets.right - 1 + + (fColumnCount - 1) * fColumnSpacing); + size.height = BLayoutUtils::SubtractDistances(size.height, + fInsets.top + fInsets.bottom - 1 + + (fRowCount - 1) * fRowSpacing); + return size; + } + + int32 _RowCount() const + { + int32 childCount = CountChildren(); + int32 count; + if (fOrientation == B_HORIZONTAL) + count = min_c(fLineCount, childCount); + else + count = (childCount + fLineCount - 1) / fLineCount; + + return max_c(count, 1); + } + + int32 _ColumnCount() const + { + int32 childCount = CountChildren(); + int32 count; + if (fOrientation == B_HORIZONTAL) + count = (childCount + fLineCount - 1) / fLineCount; + else + count = min_c(fLineCount, childCount); + + return max_c(count, 1); + } + + View* _ChildAt(int32 column, int32 row) const + { + if (fOrientation == B_HORIZONTAL) + return ChildAt(column * fLineCount + row); + else + return ChildAt(row * fLineCount + column); + } + +private: + enum orientation fOrientation; + int32 fLineCount; + float fColumnSpacing; + float fRowSpacing; + BRect fInsets; + bool fMinMaxValid; + int32 fMinWidth; + int32 fMinHeight; + int32 fMaxWidth; + int32 fMaxHeight; + int32 fPreferredWidth; + int32 fPreferredHeight; + LayoutInfo* fColumnInfos; + LayoutInfo* fRowInfos; + int32 fColumnCount; + int32 fRowCount; +}; + + +// Glue +class Glue : public View { +public: + Glue() + : View() + { + SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + } +}; + + +// Strut +class Strut : public View { +public: + Strut(float pixelWidth, float pixelHeight) + : View(), + fSize(pixelWidth >= 0 ? pixelWidth - 1 : B_SIZE_UNSET, + pixelHeight >= 0 ? pixelHeight - 1 : B_SIZE_UNSET) + { + SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + } + + virtual BSize MinSize() + { + return BLayoutUtils::ComposeSize(fSize, BSize(-1, -1)); + } + + virtual BSize MaxSize() + { + return BLayoutUtils::ComposeSize(fSize, + BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED)); + } + +private: + BSize fSize; +}; + + +// HStrut +class HStrut : public Strut { +public: + HStrut(float width) + : Strut(width, -1) + { + } +}; + + +// VStrut +class VStrut : public Strut { +public: + VStrut(float height) + : Strut(-1, height) + { + } }; @@ -789,10 +1395,10 @@ public: view->SetViewColor((rgb_color){200, 200, 240, 255}); // wrapper view - fWrapperView = new WrapperView(BRect(10, 10, 100, 100), + fWrapperView = new WrapperView( new BButton(BRect(0, 0, 9, 9), "test button", "Ooh, press me!", (BMessage*)NULL, B_FOLLOW_NONE)); -fWrapperView->GetView()->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED)); + fWrapperView->SetLocation(BPoint(10, 10)); view->AddChild(fWrapperView); fWrapperView->SetSize(fWrapperView->PreferredSize()); @@ -804,78 +1410,58 @@ fWrapperView->GetView()->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIM _UpdateSliderConstraints(); - // size labels - - // min label - rect.top = rect.bottom + 10; - rect.bottom = rect.top + 10; - StringView* minLabel = new StringView(rect, "min: "); - minLabel->SetAlignment(B_ALIGN_RIGHT); - fViewContainer->View::AddChild(minLabel); - minLabel->SetSize(minLabel->PreferredSize()); - BRect minFrame(minLabel->Frame()); - - // max label - rect = minFrame.OffsetToCopy(minFrame.LeftBottom() + BPoint(0, 8)); - StringView* maxLabel = new StringView(rect, "max: "); - maxLabel->SetAlignment(B_ALIGN_RIGHT); - fViewContainer->View::AddChild(maxLabel); - maxLabel->SetSize(maxLabel->PreferredSize()); - BRect maxFrame(maxLabel->Frame()); - - // preferred label - rect = maxFrame.OffsetToCopy(maxFrame.LeftBottom() + BPoint(0, 8)); - StringView* preferredLabel = new StringView(rect, "preferred: "); - preferredLabel->SetAlignment(B_ALIGN_RIGHT); - fViewContainer->View::AddChild(preferredLabel); - preferredLabel->SetSize(preferredLabel->PreferredSize()); - BRect preferredFrame(preferredLabel->Frame()); - - // preferred label - rect = preferredFrame.OffsetToCopy(preferredFrame.LeftBottom() - + BPoint(0, 8)); - StringView* currentLabel = new StringView(rect, "current: "); - currentLabel->SetAlignment(B_ALIGN_RIGHT); - fViewContainer->View::AddChild(currentLabel); - currentLabel->SetSize(currentLabel->PreferredSize()); - BRect currentFrame(currentLabel->Frame()); - - float labelWidth = max_c(minFrame.Width(), maxFrame.Width()); - labelWidth = max_c(labelWidth, preferredFrame.Width()); - labelWidth = max_c(labelWidth, currentFrame.Width()); - BSize labelSize(labelWidth, minLabel->Size().height); - minLabel->SetSize(labelSize); - maxLabel->SetSize(labelSize); - preferredLabel->SetSize(labelSize); - currentLabel->SetSize(labelSize); - // size views + GroupView* sizeViewsGroup = new GroupView(B_VERTICAL, 6); + sizeViewsGroup->SetSpacing(0, 8); + fViewContainer->View::AddChild(sizeViewsGroup); // min - _CreateSizeViews(minFrame.LeftTop() + BPoint(labelWidth + 1, 0), - fMinWidthView, fMinHeightView); + _CreateSizeViews(sizeViewsGroup, "min: ", fMinWidthView, + fMinHeightView); - // max - _CreateSizeViews(maxFrame.LeftTop() + BPoint(labelWidth + 1, 0), - fMaxWidthView, fMaxHeightView); + // max (with checkbox) + GroupView* unlimitedMaxGroup = new GroupView(B_HORIZONTAL); + fUnlimitedMaxSizeCheckBox = new CheckBox( + new BMessage(MSG_UNLIMITED_MAX_SIZE_CHANGED), this); + unlimitedMaxGroup->AddChild(fUnlimitedMaxSizeCheckBox); + unlimitedMaxGroup->AddChild(new StringView(" override")); + + _CreateSizeViews(sizeViewsGroup, "max: ", fMaxWidthView, + fMaxHeightView, unlimitedMaxGroup); // preferred - _CreateSizeViews(preferredFrame.LeftTop() + BPoint(labelWidth + 1, 0), - fPreferredWidthView, fPreferredHeightView); + _CreateSizeViews(sizeViewsGroup, "preferred: ", fPreferredWidthView, + fPreferredHeightView); // current - _CreateSizeViews(currentFrame.LeftTop() + BPoint(labelWidth + 1, 0), - fCurrentWidthView, fCurrentHeightView); + _CreateSizeViews(sizeViewsGroup, "current: ", fCurrentWidthView, + fCurrentHeightView); + + sizeViewsGroup->SetFrame(BRect(BPoint(rect.left, rect.bottom + 10), + sizeViewsGroup->PreferredSize())); _UpdateSizeViews(); } + virtual void DispatchMessage(BMessage* message, BHandler* handler) + { + switch (message->what) { + case B_LAYOUT_WINDOW: + if (!fWrapperView->GetView()->IsLayoutValid()) { + _UpdateSliderConstraints(); + _UpdateSizeViews(); + } + break; + } + + BWindow::DispatchMessage(message, handler); + } + virtual void MessageReceived(BMessage* message) { switch (message->what) { case MSG_2D_SLIDER_VALUE_CHANGED: { -// message->PrintToStream(); BPoint sliderLocation(fSliderView->Location()); BPoint wrapperLocation(fWrapperView->Location()); BSize size(sliderLocation.x - wrapperLocation.x - 1, @@ -885,6 +1471,16 @@ fWrapperView->GetView()->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIM break; } + case MSG_UNLIMITED_MAX_SIZE_CHANGED: + if (fUnlimitedMaxSizeCheckBox->IsSelected()) { + fWrapperView->GetView()->SetExplicitMaxSize( + BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED)); + } else { + fWrapperView->GetView()->SetExplicitMaxSize( + BSize(B_SIZE_UNSET, B_SIZE_UNSET)); + } + break; + default: BWindow::MessageReceived(message); break; @@ -913,30 +1509,39 @@ private: fSliderView->SetLocationRange(minSliderLocation, maxSliderLocation); } - void _CreateSizeViews(BPoint location, StringView*& widthView, - StringView*& heightView) + void _CreateSizeViews(View* group, const char* labelText, + StringView*& widthView, StringView*& heightView, + View* additionalView = NULL) { + // label + StringView* label = new StringView(labelText); + label->SetAlignment(B_ALIGN_RIGHT); + group->AddChild(label); + // width view - BRect rect(location, location + BPoint(10, 10)); - widthView = new StringView(rect, "9999999999.9"); + widthView = new StringView("9999999999.9"); widthView->SetAlignment(B_ALIGN_RIGHT); - fViewContainer->View::AddChild(widthView); - widthView->SetSize(widthView->PreferredSize()); + group->AddChild(widthView); + widthView->SetExplicitMinSize(widthView->PreferredSize()); // "," label - rect = widthView->Frame(); - rect.OffsetTo(rect.RightTop() + BPoint(1, 0)); - StringView* labelView = new StringView(rect, ", "); - fViewContainer->View::AddChild(labelView); - labelView->SetSize(labelView->PreferredSize()); + StringView* labelView = new StringView(", "); + group->AddChild(labelView); // height view - rect = labelView->Frame(); - rect.OffsetTo(rect.RightTop() + BPoint(1, 0)); - heightView = new StringView(rect, "9999999999.9"); + heightView = new StringView("9999999999.9"); heightView->SetAlignment(B_ALIGN_RIGHT); - fViewContainer->View::AddChild(heightView); - heightView->SetSize(heightView->PreferredSize()); + group->AddChild(heightView); + heightView->SetExplicitMinSize(heightView->PreferredSize()); + + // spacing + group->AddChild(new HStrut(20)); + + // glue or unlimited max size check box + if (additionalView) + group->AddChild(additionalView); + else + group->AddChild(new Glue()); } void _UpdateSizeView(StringView* view, float size) @@ -980,6 +1585,7 @@ private: StringView* fPreferredHeightView; StringView* fCurrentWidthView; StringView* fCurrentHeightView; + CheckBox* fUnlimitedMaxSizeCheckBox; };