1 /*
2 * Copyright 2001-2022 Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT license.
4 *
5 * Authors:
6 * Stephan Aßmus, superstippi@gmx.de
7 * DarkWyrm, bpmagic@columbus.rr.com
8 * Axel Dörfler, axeld@pinc-software.de
9 * Marc Flerackers, mflerackers@androme.be
10 * John Scipione, jscipione@gmail.com
11 */
12
13
14 #include <Box.h>
15
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19
20 #include <ControlLook.h>
21 #include <Layout.h>
22 #include <LayoutUtils.h>
23 #include <Message.h>
24 #include <Region.h>
25
26 #include <binary_compatibility/Interface.h>
27
28
29 struct BBox::LayoutData {
LayoutDataBBox::LayoutData30 LayoutData()
31 : valid(false)
32 {
33 }
34
35 BRect label_box; // label box (label string or label view); in case
36 // of a label string not including descent
37 BRect insets; // insets induced by border and label
38 BSize min;
39 BSize max;
40 BSize preferred;
41 BAlignment alignment;
42 bool valid; // validity the other fields
43 };
44
45
BBox(BRect frame,const char * name,uint32 resizingMode,uint32 flags,border_style border)46 BBox::BBox(BRect frame, const char* name, uint32 resizingMode, uint32 flags,
47 border_style border)
48 :
49 BView(frame, name, resizingMode, flags | B_WILL_DRAW | B_FRAME_EVENTS),
50 fStyle(border)
51 {
52 _InitObject();
53 }
54
55
BBox(const char * name,uint32 flags,border_style border,BView * child)56 BBox::BBox(const char* name, uint32 flags, border_style border, BView* child)
57 :
58 BView(name, flags | B_WILL_DRAW | B_FRAME_EVENTS),
59 fStyle(border)
60 {
61 _InitObject();
62
63 if (child)
64 AddChild(child);
65 }
66
67
BBox(border_style border,BView * child)68 BBox::BBox(border_style border, BView* child)
69 :
70 BView(NULL, B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE_JUMP),
71 fStyle(border)
72 {
73 _InitObject();
74
75 if (child)
76 AddChild(child);
77 }
78
79
BBox(BMessage * archive)80 BBox::BBox(BMessage* archive)
81 :
82 BView(archive),
83 fStyle(B_FANCY_BORDER)
84 {
85 _InitObject(archive);
86 }
87
88
~BBox()89 BBox::~BBox()
90 {
91 _ClearLabel();
92
93 delete fLayoutData;
94 }
95
96
97 BArchivable*
Instantiate(BMessage * archive)98 BBox::Instantiate(BMessage* archive)
99 {
100 if (validate_instantiation(archive, "BBox"))
101 return new BBox(archive);
102
103 return NULL;
104 }
105
106
107 status_t
Archive(BMessage * archive,bool deep) const108 BBox::Archive(BMessage* archive, bool deep) const
109 {
110 status_t ret = BView::Archive(archive, deep);
111
112 if (fLabel && ret == B_OK)
113 ret = archive->AddString("_label", fLabel);
114
115 if (fLabelView && ret == B_OK)
116 ret = archive->AddBool("_lblview", true);
117
118 if (fStyle != B_FANCY_BORDER && ret == B_OK)
119 ret = archive->AddInt32("_style", fStyle);
120
121 return ret;
122 }
123
124
125 void
SetBorder(border_style border)126 BBox::SetBorder(border_style border)
127 {
128 if (border == fStyle)
129 return;
130
131 fStyle = border;
132
133 InvalidateLayout();
134
135 if (Window() != NULL && LockLooper()) {
136 Invalidate();
137 UnlockLooper();
138 }
139 }
140
141
142 border_style
Border() const143 BBox::Border() const
144 {
145 return fStyle;
146 }
147
148
149 //! This function is not part of the R5 API and is not yet finalized yet
150 float
TopBorderOffset()151 BBox::TopBorderOffset()
152 {
153 _ValidateLayoutData();
154
155 if (fLabel != NULL || fLabelView != NULL)
156 return fLayoutData->label_box.Height() / 2;
157
158 return 0;
159 }
160
161
162 //! This function is not part of the R5 API and is not yet finalized yet
163 BRect
InnerFrame()164 BBox::InnerFrame()
165 {
166 _ValidateLayoutData();
167
168 BRect frame(Bounds());
169 frame.left += fLayoutData->insets.left;
170 frame.top += fLayoutData->insets.top;
171 frame.right -= fLayoutData->insets.right;
172 frame.bottom -= fLayoutData->insets.bottom;
173
174 return frame;
175 }
176
177
178 void
SetLabel(const char * string)179 BBox::SetLabel(const char* string)
180 {
181 _ClearLabel();
182
183 if (string)
184 fLabel = strdup(string);
185
186 InvalidateLayout();
187
188 if (Window())
189 Invalidate();
190 }
191
192
193 status_t
SetLabel(BView * viewLabel)194 BBox::SetLabel(BView* viewLabel)
195 {
196 _ClearLabel();
197
198 if (viewLabel) {
199 fLabelView = viewLabel;
200 fLabelView->MoveTo(10.0f, 0.0f);
201 AddChild(fLabelView, ChildAt(0));
202 }
203
204 InvalidateLayout();
205
206 if (Window())
207 Invalidate();
208
209 return B_OK;
210 }
211
212
213 const char*
Label() const214 BBox::Label() const
215 {
216 return fLabel;
217 }
218
219
220 BView*
LabelView() const221 BBox::LabelView() const
222 {
223 return fLabelView;
224 }
225
226
227 void
Draw(BRect updateRect)228 BBox::Draw(BRect updateRect)
229 {
230 _ValidateLayoutData();
231
232 PushState();
233
234 BRect labelBox = BRect(0, 0, 0, 0);
235 if (fLabel != NULL) {
236 labelBox = fLayoutData->label_box;
237 BRegion update(updateRect);
238 update.Exclude(labelBox);
239
240 ConstrainClippingRegion(&update);
241 } else if (fLabelView != NULL)
242 labelBox = fLabelView->Bounds();
243
244 switch (fStyle) {
245 case B_FANCY_BORDER:
246 _DrawFancy(labelBox);
247 break;
248
249 case B_PLAIN_BORDER:
250 _DrawPlain(labelBox);
251 break;
252
253 default:
254 break;
255 }
256
257 if (fLabel != NULL) {
258 ConstrainClippingRegion(NULL);
259
260 font_height fontHeight;
261 GetFontHeight(&fontHeight);
262
263 // offset label up by 1/6 the font height
264 float lineHeight = fontHeight.ascent + fontHeight.descent;
265 float yOffset = roundf(lineHeight / 6.0f);
266
267 SetHighColor(ui_color(B_PANEL_TEXT_COLOR));
268 DrawString(fLabel, BPoint(10.0f, fontHeight.ascent - yOffset));
269 }
270
271 PopState();
272 }
273
274
275 void
AttachedToWindow()276 BBox::AttachedToWindow()
277 {
278 AdoptParentColors();
279
280 // Force low color to match view color for proper label drawing.
281 float viewTint = B_NO_TINT;
282 float lowTint = B_NO_TINT;
283
284 if (LowUIColor(&lowTint) != ViewUIColor(&viewTint) || viewTint != lowTint)
285 SetLowUIColor(ViewUIColor(), viewTint);
286 else if (LowColor() != ViewColor())
287 SetLowColor(ViewColor());
288
289 if (ViewColor() == B_TRANSPARENT_COLOR)
290 AdoptSystemColors();
291
292 // The box could have been resized in the mean time
293 fBounds = Bounds().OffsetToCopy(0, 0);
294 }
295
296
297 void
DetachedFromWindow()298 BBox::DetachedFromWindow()
299 {
300 BView::DetachedFromWindow();
301 }
302
303
304 void
AllAttached()305 BBox::AllAttached()
306 {
307 BView::AllAttached();
308 }
309
310
311 void
AllDetached()312 BBox::AllDetached()
313 {
314 BView::AllDetached();
315 }
316
317
318 void
FrameResized(float width,float height)319 BBox::FrameResized(float width, float height)
320 {
321 BRect bounds(Bounds());
322
323 // invalidate the regions that the app_server did not
324 // (for removing the previous or drawing the new border)
325 if (fStyle != B_NO_BORDER) {
326 // TODO: this must be made part of the be_control_look stuff!
327 int32 borderSize = fStyle == B_PLAIN_BORDER ? 0 : 2;
328
329 // Horizontal
330 BRect invalid(bounds);
331 if (fBounds.Width() < bounds.Width()) {
332 // enlarging
333 invalid.left = bounds.left + fBounds.right - borderSize;
334 invalid.right = bounds.left + fBounds.right;
335
336 Invalidate(invalid);
337 } else if (fBounds.Width() > bounds.Width()) {
338 // shrinking
339 invalid.left = bounds.left + bounds.right - borderSize;
340
341 Invalidate(invalid);
342 }
343
344 // Vertical
345 invalid = bounds;
346 if (fBounds.Height() < bounds.Height()) {
347 // enlarging
348 invalid.top = bounds.top + fBounds.bottom - borderSize;
349 invalid.bottom = bounds.top + fBounds.bottom;
350
351 Invalidate(invalid);
352 } else if (fBounds.Height() > bounds.Height()) {
353 // shrinking
354 invalid.top = bounds.top + bounds.bottom - borderSize;
355
356 Invalidate(invalid);
357 }
358 }
359
360 fBounds.right = width;
361 fBounds.bottom = height;
362 }
363
364
365 void
MessageReceived(BMessage * message)366 BBox::MessageReceived(BMessage* message)
367 {
368 BView::MessageReceived(message);
369 }
370
371
372 void
MouseDown(BPoint point)373 BBox::MouseDown(BPoint point)
374 {
375 BView::MouseDown(point);
376 }
377
378
379 void
MouseUp(BPoint point)380 BBox::MouseUp(BPoint point)
381 {
382 BView::MouseUp(point);
383 }
384
385
386 void
WindowActivated(bool active)387 BBox::WindowActivated(bool active)
388 {
389 BView::WindowActivated(active);
390 }
391
392
393 void
MouseMoved(BPoint point,uint32 transit,const BMessage * message)394 BBox::MouseMoved(BPoint point, uint32 transit, const BMessage* message)
395 {
396 BView::MouseMoved(point, transit, message);
397 }
398
399
400 void
FrameMoved(BPoint newLocation)401 BBox::FrameMoved(BPoint newLocation)
402 {
403 BView::FrameMoved(newLocation);
404 }
405
406
407 BHandler*
ResolveSpecifier(BMessage * message,int32 index,BMessage * specifier,int32 what,const char * property)408 BBox::ResolveSpecifier(BMessage* message, int32 index, BMessage* specifier,
409 int32 what, const char* property)
410 {
411 return BView::ResolveSpecifier(message, index, specifier, what, property);
412 }
413
414
415 void
ResizeToPreferred()416 BBox::ResizeToPreferred()
417 {
418 float width, height;
419 GetPreferredSize(&width, &height);
420
421 // make sure the box don't get smaller than it already is
422 if (width < Bounds().Width())
423 width = Bounds().Width();
424 if (height < Bounds().Height())
425 height = Bounds().Height();
426
427 BView::ResizeTo(width, height);
428 }
429
430
431 void
GetPreferredSize(float * _width,float * _height)432 BBox::GetPreferredSize(float* _width, float* _height)
433 {
434 _ValidateLayoutData();
435
436 if (_width)
437 *_width = fLayoutData->preferred.width;
438 if (_height)
439 *_height = fLayoutData->preferred.height;
440 }
441
442
443 void
MakeFocus(bool focused)444 BBox::MakeFocus(bool focused)
445 {
446 BView::MakeFocus(focused);
447 }
448
449
450 status_t
GetSupportedSuites(BMessage * message)451 BBox::GetSupportedSuites(BMessage* message)
452 {
453 return BView::GetSupportedSuites(message);
454 }
455
456
457 status_t
Perform(perform_code code,void * _data)458 BBox::Perform(perform_code code, void* _data)
459 {
460 switch (code) {
461 case PERFORM_CODE_MIN_SIZE:
462 ((perform_data_min_size*)_data)->return_value
463 = BBox::MinSize();
464 return B_OK;
465 case PERFORM_CODE_MAX_SIZE:
466 ((perform_data_max_size*)_data)->return_value
467 = BBox::MaxSize();
468 return B_OK;
469 case PERFORM_CODE_PREFERRED_SIZE:
470 ((perform_data_preferred_size*)_data)->return_value
471 = BBox::PreferredSize();
472 return B_OK;
473 case PERFORM_CODE_LAYOUT_ALIGNMENT:
474 ((perform_data_layout_alignment*)_data)->return_value
475 = BBox::LayoutAlignment();
476 return B_OK;
477 case PERFORM_CODE_HAS_HEIGHT_FOR_WIDTH:
478 ((perform_data_has_height_for_width*)_data)->return_value
479 = BBox::HasHeightForWidth();
480 return B_OK;
481 case PERFORM_CODE_GET_HEIGHT_FOR_WIDTH:
482 {
483 perform_data_get_height_for_width* data
484 = (perform_data_get_height_for_width*)_data;
485 BBox::GetHeightForWidth(data->width, &data->min, &data->max,
486 &data->preferred);
487 return B_OK;
488 }
489 case PERFORM_CODE_SET_LAYOUT:
490 {
491 perform_data_set_layout* data = (perform_data_set_layout*)_data;
492 BBox::SetLayout(data->layout);
493 return B_OK;
494 }
495 case PERFORM_CODE_LAYOUT_INVALIDATED:
496 {
497 perform_data_layout_invalidated* data
498 = (perform_data_layout_invalidated*)_data;
499 BBox::LayoutInvalidated(data->descendants);
500 return B_OK;
501 }
502 case PERFORM_CODE_DO_LAYOUT:
503 {
504 BBox::DoLayout();
505 return B_OK;
506 }
507 }
508
509 return BView::Perform(code, _data);
510 }
511
512
513 BSize
MinSize()514 BBox::MinSize()
515 {
516 _ValidateLayoutData();
517
518 BSize size = (GetLayout() ? GetLayout()->MinSize() : fLayoutData->min);
519 if (size.width < fLayoutData->min.width)
520 size.width = fLayoutData->min.width;
521 return BLayoutUtils::ComposeSize(ExplicitMinSize(), size);
522 }
523
524
525 BSize
MaxSize()526 BBox::MaxSize()
527 {
528 _ValidateLayoutData();
529
530 BSize size = (GetLayout() ? GetLayout()->MaxSize() : fLayoutData->max);
531 return BLayoutUtils::ComposeSize(ExplicitMaxSize(), size);
532 }
533
534
535 BSize
PreferredSize()536 BBox::PreferredSize()
537 {
538 _ValidateLayoutData();
539
540 BSize size = (GetLayout() ? GetLayout()->PreferredSize()
541 : fLayoutData->preferred);
542 return BLayoutUtils::ComposeSize(ExplicitPreferredSize(), size);
543 }
544
545
546 BAlignment
LayoutAlignment()547 BBox::LayoutAlignment()
548 {
549 _ValidateLayoutData();
550
551 BAlignment alignment = (GetLayout() ? GetLayout()->Alignment()
552 : fLayoutData->alignment);
553 return BLayoutUtils::ComposeAlignment(ExplicitAlignment(), alignment);
554 }
555
556
557 void
LayoutInvalidated(bool descendants)558 BBox::LayoutInvalidated(bool descendants)
559 {
560 fLayoutData->valid = false;
561 }
562
563
564 void
DoLayout()565 BBox::DoLayout()
566 {
567 // Bail out, if we shan't do layout.
568 if (!(Flags() & B_SUPPORTS_LAYOUT))
569 return;
570
571 BLayout* layout = GetLayout();
572
573 // If the user set a layout, let the base class version call its
574 // hook. In case when we have BView as a label, remove it from child list
575 // so it won't be layouted with the rest of views and add it again
576 // after that.
577 if (layout != NULL) {
578 if (fLabelView)
579 RemoveChild(fLabelView);
580
581 BView::DoLayout();
582
583 if (fLabelView != NULL) {
584 DisableLayoutInvalidation();
585 // don't trigger a relayout
586 AddChild(fLabelView, ChildAt(0));
587 EnableLayoutInvalidation();
588 }
589 }
590
591 _ValidateLayoutData();
592
593 // Even if the user set a layout, restore label view to it's
594 // desired position.
595
596 // layout the label view
597 if (fLabelView != NULL) {
598 fLabelView->MoveTo(fLayoutData->label_box.LeftTop());
599 fLabelView->ResizeTo(fLayoutData->label_box.Size());
600 }
601
602 // If we have layout return here and do not layout the child
603 if (layout != NULL)
604 return;
605
606 // layout the child
607 BView* child = _Child();
608 if (child != NULL) {
609 BRect frame(Bounds());
610 frame.left += fLayoutData->insets.left;
611 frame.top += fLayoutData->insets.top;
612 frame.right -= fLayoutData->insets.right;
613 frame.bottom -= fLayoutData->insets.bottom;
614
615 if ((child->Flags() & B_SUPPORTS_LAYOUT) != 0)
616 BLayoutUtils::AlignInFrame(child, frame);
617 else
618 child->MoveTo(frame.LeftTop());
619 }
620 }
621
622
_ReservedBox1()623 void BBox::_ReservedBox1() {}
_ReservedBox2()624 void BBox::_ReservedBox2() {}
625
626
627 BBox &
operator =(const BBox &)628 BBox::operator=(const BBox &)
629 {
630 return *this;
631 }
632
633
634 void
_InitObject(BMessage * archive)635 BBox::_InitObject(BMessage* archive)
636 {
637 fBounds = Bounds().OffsetToCopy(0, 0);
638
639 fLabel = NULL;
640 fLabelView = NULL;
641 fLayoutData = new LayoutData;
642
643 int32 flags = 0;
644
645 BFont font(be_bold_font);
646
647 if (!archive || !archive->HasString("_fname"))
648 flags = B_FONT_FAMILY_AND_STYLE;
649
650 if (!archive || !archive->HasFloat("_fflt"))
651 flags |= B_FONT_SIZE;
652
653 if (flags != 0)
654 SetFont(&font, flags);
655
656 if (archive != NULL) {
657 const char* string;
658 if (archive->FindString("_label", &string) == B_OK)
659 SetLabel(string);
660
661 bool fancy;
662 int32 style;
663
664 if (archive->FindBool("_style", &fancy) == B_OK)
665 fStyle = fancy ? B_FANCY_BORDER : B_PLAIN_BORDER;
666 else if (archive->FindInt32("_style", &style) == B_OK)
667 fStyle = (border_style)style;
668
669 bool hasLabelView;
670 if (archive->FindBool("_lblview", &hasLabelView) == B_OK)
671 fLabelView = ChildAt(0);
672 }
673
674 AdoptSystemColors();
675 }
676
677
678 void
_DrawPlain(BRect labelBox)679 BBox::_DrawPlain(BRect labelBox)
680 {
681 BRect rect = Bounds();
682 rect.top += TopBorderOffset();
683
684 float lightTint;
685 float shadowTint;
686 lightTint = B_LIGHTEN_1_TINT;
687 shadowTint = B_DARKEN_1_TINT;
688
689 if (rect.Height() == 0.0 || rect.Width() == 0.0) {
690 // used as separator
691 rgb_color shadow = tint_color(ViewColor(), B_DARKEN_2_TINT);
692
693 SetHighColor(shadow);
694 StrokeLine(rect.LeftTop(),rect.RightBottom());
695 } else {
696 // used as box
697 rgb_color light = tint_color(ViewColor(), lightTint);
698 rgb_color shadow = tint_color(ViewColor(), shadowTint);
699
700 BeginLineArray(4);
701 AddLine(BPoint(rect.left, rect.bottom),
702 BPoint(rect.left, rect.top), light);
703 AddLine(BPoint(rect.left + 1.0f, rect.top),
704 BPoint(rect.right, rect.top), light);
705 AddLine(BPoint(rect.left + 1.0f, rect.bottom),
706 BPoint(rect.right, rect.bottom), shadow);
707 AddLine(BPoint(rect.right, rect.bottom - 1.0f),
708 BPoint(rect.right, rect.top + 1.0f), shadow);
709 EndLineArray();
710 }
711 }
712
713
714 void
_DrawFancy(BRect labelBox)715 BBox::_DrawFancy(BRect labelBox)
716 {
717 BRect rect = Bounds();
718 rect.top += TopBorderOffset();
719
720 rgb_color base = ViewColor();
721 if (rect.Height() == 1.0) {
722 // used as horizontal separator
723 be_control_look->DrawGroupFrame(this, rect, rect, base,
724 BControlLook::B_TOP_BORDER);
725 } else if (rect.Width() == 1.0) {
726 // used as vertical separator
727 be_control_look->DrawGroupFrame(this, rect, rect, base,
728 BControlLook::B_LEFT_BORDER);
729 } else {
730 // used as box
731 be_control_look->DrawGroupFrame(this, rect, rect, base);
732 }
733 }
734
735
736 void
_ClearLabel()737 BBox::_ClearLabel()
738 {
739 if (fLabel) {
740 free(fLabel);
741 fLabel = NULL;
742 } else if (fLabelView) {
743 fLabelView->RemoveSelf();
744 delete fLabelView;
745 fLabelView = NULL;
746 }
747 }
748
749
750 BView*
_Child() const751 BBox::_Child() const
752 {
753 for (int32 i = 0; BView* view = ChildAt(i); i++) {
754 if (view != fLabelView)
755 return view;
756 }
757
758 return NULL;
759 }
760
761
762 void
_ValidateLayoutData()763 BBox::_ValidateLayoutData()
764 {
765 if (fLayoutData->valid)
766 return;
767
768 // compute the label box, width and height
769 bool label = true;
770 float labelHeight = 0; // height of the label (pixel count)
771 if (fLabel) {
772 // leave 6 pixels of the frame, and have a gap of 4 pixels between
773 // the frame and the text on either side
774 font_height fontHeight;
775 GetFontHeight(&fontHeight);
776 fLayoutData->label_box.Set(6.0f, 0, 14.0f + StringWidth(fLabel),
777 ceilf(fontHeight.ascent));
778 labelHeight = ceilf(fontHeight.ascent + fontHeight.descent) + 1;
779 } else if (fLabelView) {
780 // the label view is placed at (0, 10) at its preferred size
781 BSize size = fLabelView->PreferredSize();
782 fLayoutData->label_box.Set(10, 0, 10 + size.width, size.height);
783 labelHeight = size.height + 1;
784 } else
785 label = false;
786
787 // border
788 switch (fStyle) {
789 case B_PLAIN_BORDER:
790 fLayoutData->insets.Set(1, 1, 1, 1);
791 break;
792 case B_FANCY_BORDER:
793 fLayoutData->insets.Set(3, 3, 3, 3);
794 break;
795 case B_NO_BORDER:
796 default:
797 fLayoutData->insets.Set(0, 0, 0, 0);
798 break;
799 }
800
801 // if there's a label, the top inset will be dictated by the label
802 if (label && labelHeight > fLayoutData->insets.top)
803 fLayoutData->insets.top = labelHeight;
804
805 // total number of pixel the border adds
806 float addWidth = fLayoutData->insets.left + fLayoutData->insets.right;
807 float addHeight = fLayoutData->insets.top + fLayoutData->insets.bottom;
808
809 // compute the minimal width induced by the label
810 float minWidth;
811 if (label)
812 minWidth = fLayoutData->label_box.right + fLayoutData->insets.right;
813 else
814 minWidth = addWidth - 1;
815
816 BAlignment alignment(B_ALIGN_HORIZONTAL_CENTER, B_ALIGN_VERTICAL_CENTER);
817
818 // finally consider the child constraints, if we shall support layout
819 BView* child = _Child();
820 if (child && (child->Flags() & B_SUPPORTS_LAYOUT)) {
821 BSize min = child->MinSize();
822 BSize max = child->MaxSize();
823 BSize preferred = child->PreferredSize();
824
825 min.width += addWidth;
826 min.height += addHeight;
827 preferred.width += addWidth;
828 preferred.height += addHeight;
829 max.width = BLayoutUtils::AddDistances(max.width, addWidth - 1);
830 max.height = BLayoutUtils::AddDistances(max.height, addHeight - 1);
831
832 if (min.width < minWidth)
833 min.width = minWidth;
834 BLayoutUtils::FixSizeConstraints(min, max, preferred);
835
836 fLayoutData->min = min;
837 fLayoutData->max = max;
838 fLayoutData->preferred = preferred;
839
840 BAlignment childAlignment = child->LayoutAlignment();
841 if (childAlignment.horizontal == B_ALIGN_USE_FULL_WIDTH)
842 alignment.horizontal = B_ALIGN_USE_FULL_WIDTH;
843 if (childAlignment.vertical == B_ALIGN_USE_FULL_HEIGHT)
844 alignment.vertical = B_ALIGN_USE_FULL_HEIGHT;
845
846 fLayoutData->alignment = alignment;
847 } else {
848 fLayoutData->min.Set(minWidth, addHeight - 1);
849 fLayoutData->max.Set(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED);
850 fLayoutData->preferred = fLayoutData->min;
851 fLayoutData->alignment = alignment;
852 }
853
854 fLayoutData->valid = true;
855 ResetLayoutInvalidation();
856 }
857
858
859 extern "C" void
B_IF_GCC_2(InvalidateLayout__4BBoxb,_ZN4BBox16InvalidateLayoutEb)860 B_IF_GCC_2(InvalidateLayout__4BBoxb, _ZN4BBox16InvalidateLayoutEb)(
861 BBox* box, bool descendants)
862 {
863 perform_data_layout_invalidated data;
864 data.descendants = descendants;
865
866 box->Perform(PERFORM_CODE_LAYOUT_INVALIDATED, &data);
867 }
868
869