xref: /haiku/src/libs/alm/Area.cpp (revision 6490c5b6211c94ec48c03c12b90e8603fe268d1b)
1 /*
2  * Copyright 2007-2008, Christof Lutteroth, lutteroth@cs.auckland.ac.nz
3  * Copyright 2007-2008, James Kim, jkim202@ec.auckland.ac.nz
4  * Distributed under the terms of the MIT License.
5  */
6 
7 #include "Area.h"
8 #include "Column.h"
9 #include "BALMLayout.h"
10 #include "OperatorType.h"
11 #include "Row.h"
12 #include "XTab.h"
13 #include "YTab.h"
14 
15 #include <Button.h>
16 #include <RadioButton.h>
17 #include <CheckBox.h>
18 #include <StringView.h>
19 #include <PictureButton.h>
20 #include <StatusBar.h>
21 
22 #include <algorithm>	// for max
23 
24 using namespace std;
25 
26 BSize Area::kMaxSize(INT_MAX, INT_MAX);
27 BSize Area::kMinSize(0, 0);
28 BSize Area::kUndefinedSize(-1, -1);
29 
30 
31 /**
32  * Gets the auto preferred content size.
33  *
34  * @return the auto preferred content size
35  */
36 bool
37 Area::AutoPreferredContentSize() const
38 {
39 	return fAutoPreferredContentSize;
40 }
41 
42 
43 /**
44  * Sets the auto preferred content size true or false.
45  *
46  * @param value	the auto preferred content size
47  */
48 void
49 Area::SetAutoPreferredContentSize(bool value)
50 {
51 	fAutoPreferredContentSize = value;
52 }
53 
54 
55 /**
56  * Gets the left tab of the area.
57  *
58  * @return the left tab of the area
59  */
60 XTab*
61 Area::Left() const
62 {
63 	return fLeft;
64 }
65 
66 
67 /**
68  * Sets the left tab of the area.
69  *
70  * @param left	the left tab of the area
71  */
72 void
73 Area::SetLeft(XTab* left)
74 {
75 	fLeft = left;
76 
77 	fColumn = NULL;
78 
79 	if (fChildArea == NULL) {
80 		fMinContentWidth->SetLeftSide(-1.0, fLeft, 1.0, fRight);
81 
82 		if (fMaxContentWidth != NULL)
83 			fMaxContentWidth->SetLeftSide(-1.0, fLeft, 1.0, fRight);
84 	} else
85 		UpdateHorizontal();
86 	fLS->InvalidateLayout();
87 }
88 
89 
90 /**
91  * Gets the right tab of the area.
92  *
93  * @return the right tab of the area
94  */
95 XTab*
96 Area::Right() const
97 {
98 	return fRight;
99 }
100 
101 
102 /**
103  * Sets the right tab of the area.
104  *
105  * @param right	the right tab of the area
106  */
107 void
108 Area::SetRight(XTab* right)
109 {
110 	fRight = right;
111 
112 	fColumn = NULL;
113 
114 	if (fChildArea == NULL) {
115 		fMinContentWidth->SetLeftSide(-1.0, fLeft, 1.0, fRight);
116 
117 		if (fMaxContentWidth != NULL)
118 			fMaxContentWidth->SetLeftSide(-1.0, fLeft, 1.0, fRight);
119 	} else
120 		UpdateHorizontal();
121 	fLS->InvalidateLayout();
122 }
123 
124 
125 /**
126  * Gets the top tab of the area.
127  */
128 YTab*
129 Area::Top() const
130 {
131 	return fTop;
132 }
133 
134 
135 /**
136  * Sets the top tab of the area.
137  */
138 void
139 Area::SetTop(YTab* top)
140 {
141 	fTop = top;
142 
143 	fRow = NULL;
144 
145 	if (fChildArea == NULL) {
146 		fMinContentHeight->SetLeftSide(-1.0, fTop, 1.0, fBottom);
147 
148 		if (fMaxContentHeight != NULL)
149 			fMaxContentHeight->SetLeftSide(-1.0, fTop, 1.0, fBottom);
150 	} else
151 		UpdateVertical();
152 	fLS->InvalidateLayout();
153 }
154 
155 
156 /**
157  * Gets the bottom tab of the area.
158  */
159 YTab*
160 Area::Bottom() const
161 {
162 	return fBottom;
163 }
164 
165 
166 /**
167  * Sets the bottom tab of the area.
168  */
169 void
170 Area::SetBottom(YTab* bottom)
171 {
172 	fBottom = bottom;
173 
174 	fRow = NULL;
175 
176 	if (fChildArea == NULL) {
177 		fMinContentHeight->SetLeftSide(-1.0, fTop, 1.0, fBottom);
178 
179 		if (fMaxContentHeight != NULL)
180 			fMaxContentHeight->SetLeftSide(-1.0, fTop, 1.0, fBottom);
181 	} else
182 		UpdateVertical();
183 	fLS->InvalidateLayout();
184 }
185 
186 
187 /**
188  * Gets the row that defines the top and bottom tabs.
189  */
190 Row*
191 Area::GetRow() const
192 {
193 	return fRow;
194 }
195 
196 
197 /**
198  * Sets the row that defines the top and bottom tabs.
199  * May be null.
200  */
201 void
202 Area::SetRow(Row* row)
203 {
204 	SetTop(row->Top());
205 	SetBottom(row->Bottom());
206 	fRow = row;
207 	fLS->InvalidateLayout();
208 }
209 
210 
211 /**
212  * Gets the column that defines the left and right tabs.
213  */
214 Column*
215 Area::GetColumn() const
216 {
217 	return fColumn;
218 }
219 
220 
221 /**
222  * Sets the column that defines the left and right tabs.
223  * May be null.
224  */
225 void
226 Area::SetColumn(Column* column)
227 {
228 	SetLeft(column->Left());
229 	SetRight(column->Right());
230 	fColumn = column;
231 	fLS->InvalidateLayout();
232 }
233 
234 
235 /**
236  * Gets the control that is the content of the area.
237  */
238 BView*
239 Area::Content() const
240 {
241 	return (fChildArea == NULL) ? fContent : fChildArea->Content();
242 }
243 
244 
245 /**
246  * Sets the control that is the content of the area.
247  */
248 void
249 Area::SetContent(BView* content)
250 {
251 	if (fChildArea == NULL) fContent = content;
252 	else fChildArea->fContent = content;
253 	fLS->InvalidateLayout();
254 }
255 
256 
257 /**
258  * Left tab of the area's content. May be different from the left tab of the area.
259  */
260 XTab*
261 Area::ContentLeft() const
262 {
263 	return (fChildArea == NULL) ? fLeft : fChildArea->fLeft;
264 }
265 
266 
267 /**
268  * Top tab of the area's content. May be different from the top tab of the area.
269  */
270 YTab*
271 Area::ContentTop() const
272 {
273 	return (fChildArea == NULL) ? fTop : fChildArea->fTop;
274 }
275 
276 
277 /**
278  * Right tab of the area's content. May be different from the right tab of the area.
279  */
280 XTab*
281 Area::ContentRight() const
282 {
283 	return (fChildArea == NULL) ? fRight : fChildArea->fRight;
284 }
285 
286 
287 /**
288  * Bottom tab of the area's content. May be different from the bottom tab of the area.
289  */
290 YTab*
291 Area::ContentBottom() const
292 {
293 	return (fChildArea == NULL) ? fBottom : fChildArea->fBottom;
294 }
295 
296 
297 /**
298  * Gets minimum size of the area's content.
299  */
300 BSize
301 Area::MinContentSize() const
302 {
303 	return (fChildArea == NULL) ? fMinContentSize : fChildArea->fMinContentSize;
304 }
305 
306 
307 /**
308  * Sets minimum size of the area's content.
309  * May be different from the minimum size of the area.
310  */
311 void
312 Area::SetMinContentSize(BSize min)
313 {
314 	if (fChildArea == NULL) {
315 		fMinContentSize = min;
316 		fMinContentWidth->SetRightSide(fMinContentSize.Width());
317 		fMinContentHeight->SetRightSide(fMinContentSize.Height());
318 	} else
319 		fChildArea->SetMinContentSize(min);
320 	fLS->InvalidateLayout();
321 }
322 
323 
324 /**
325  * Gets maximum size of the area's content.
326  */
327 BSize Area::MaxContentSize() const {
328 	return (fChildArea == NULL) ? fMaxContentSize : fChildArea->fMaxContentSize;
329 }
330 
331 
332 /**
333  * Sets maximum size of the area's content.
334  * May be different from the maximum size of the area.
335  */
336 void
337 Area::SetMaxContentSize(BSize max)
338 {
339 	if (fChildArea == NULL) {
340 		fMaxContentSize = max;
341 		if (fMaxContentWidth == NULL) {
342 			fMaxContentWidth = fLS->AddConstraint(-1.0, fLeft, 1.0, fRight, OperatorType(LE),
343 					fMaxContentSize.Width());
344 			fConstraints->AddItem(fMaxContentWidth);
345 
346 			fMaxContentHeight = fLS->AddConstraint(-1.0, fTop, 1.0, fBottom, OperatorType(LE),
347 					fMaxContentSize.Height());
348 			fConstraints->AddItem(fMaxContentHeight);
349 		} else {
350 			fMaxContentWidth->SetRightSide(fMaxContentSize.Width());
351 			fMaxContentHeight->SetRightSide(fMaxContentSize.Height());
352 		}
353 	} else
354 		fChildArea->SetMaxContentSize(max);
355 	fLS->InvalidateLayout();
356 }
357 
358 
359 /**
360  * Gets Preferred size of the area's content.
361  */
362 BSize
363 Area::PreferredContentSize() const
364 {
365 	return (fChildArea == NULL) ? fPreferredContentSize
366 		: fChildArea->fPreferredContentSize;
367 }
368 
369 
370 /**
371  * Sets Preferred size of the area's content.
372  * May be different from the preferred size of the area.
373  * Manual changes of PreferredContentSize are ignored unless
374  * autoPreferredContentSize is set to false.
375  */
376 void
377 Area::SetPreferredContentSize(BSize preferred)
378 {
379 	if (fChildArea == NULL) {
380 		fPreferredContentSize = preferred;
381 		if (fPreferredContentWidth == NULL) {
382 			fPreferredContentWidth = fLS->AddConstraint(
383 				-1.0, fLeft, 1.0, fRight, OperatorType(EQ),
384 				fPreferredContentSize.Width(), fShrinkPenalties.Width(),
385 				fGrowPenalties.Width());
386 			fConstraints->AddItem(fPreferredContentWidth);
387 
388 			fPreferredContentHeight = fLS->AddConstraint(
389 				-1.0, fTop, 1.0, fBottom, OperatorType(EQ),
390 				fPreferredContentSize.Height(), fShrinkPenalties.Height(),
391 				fGrowPenalties.Height());
392 			fConstraints->AddItem(fPreferredContentHeight);
393 		} else {
394 			fPreferredContentWidth->SetRightSide(preferred.Width());
395 			fPreferredContentHeight->SetRightSide(preferred.Height());
396 		}
397 	} else
398 		fChildArea->SetPreferredContentSize(preferred);
399 	fLS->InvalidateLayout();
400 }
401 
402 
403 /**
404  * The reluctance with which the area's content shrinks below its preferred size.
405  * The bigger the less likely is such shrinking.
406  */
407 BSize
408 Area::ShrinkPenalties() const
409 {
410 	return (fChildArea == NULL) ? fShrinkPenalties : fChildArea->fShrinkPenalties;
411 }
412 
413 
414 void Area::SetShrinkPenalties(BSize shrink) {
415 	if (fChildArea == NULL) {
416 		fShrinkPenalties = shrink;
417 		if (fPreferredContentWidth != NULL) {
418 			fPreferredContentWidth->SetPenaltyNeg(shrink.Width());
419 			fPreferredContentHeight->SetPenaltyNeg(shrink.Height());
420 		}
421 	} else
422 		fChildArea->SetShrinkPenalties(shrink);
423 	fLS->InvalidateLayout();
424 }
425 
426 
427 /**
428  * The reluctance with which the area's content grows over its preferred size.
429  * The bigger the less likely is such growth.
430  */
431 BSize
432 Area::GrowPenalties() const
433 {
434 	return (fChildArea == NULL) ? fGrowPenalties : fChildArea->fGrowPenalties;
435 }
436 
437 
438 void
439 Area::SetGrowPenalties(BSize grow)
440 {
441 	if (fChildArea == NULL) {
442 		fGrowPenalties = grow;
443 		if (fPreferredContentWidth != NULL) {
444 			fPreferredContentWidth->SetPenaltyPos(grow.Width());
445 			fPreferredContentHeight->SetPenaltyPos(grow.Height());
446 		}
447 	} else
448 		fChildArea->SetGrowPenalties(grow);
449 	fLS->InvalidateLayout();
450 }
451 
452 
453 /**
454  * Gets aspect ratio of the area's content.
455  */
456 double
457 Area::ContentAspectRatio() const
458 {
459 	return (fChildArea == NULL) ? fContentAspectRatio : fChildArea->fContentAspectRatio;
460 }
461 
462 
463 /**
464  * Sets aspect ratio of the area's content.
465  * May be different from the aspect ratio of the area.
466  */
467 void
468 Area::SetContentAspectRatio(double ratio)
469 {
470 	if (fChildArea == NULL) {
471 		fContentAspectRatio = ratio;
472 		if (fContentAspectRatioC == NULL) {
473 			fContentAspectRatioC = fLS->AddConstraint(
474 				-1.0, fLeft, 1.0, fRight, ratio, fTop, -ratio, fBottom,
475 				OperatorType(EQ), 0.0);
476 			fConstraints->AddItem(fContentAspectRatioC);
477 		} else {
478 			fContentAspectRatioC->SetLeftSide(
479 				-1.0, fLeft, 1.0, fRight, ratio, fTop, -ratio, fBottom);
480 		}
481 	} else
482 		fChildArea->SetContentAspectRatio(ratio);
483 	fLS->InvalidateLayout();
484 }
485 
486 
487 /**
488  * Gets alignment of the content in its area.
489  */
490 BAlignment
491 Area::Alignment() const
492 {
493 	return fAlignment;
494 }
495 
496 
497 /**
498  * Sets alignment of the content in its area.
499  */
500 void
501 Area::SetAlignment(BAlignment alignment)
502 {
503 	fAlignment = alignment;
504 	UpdateHorizontal();
505 	UpdateVertical();
506 	fLS->InvalidateLayout();
507 }
508 
509 
510 /**
511  * Sets horizontal alignment of the content in its area.
512  */
513 void Area::SetHorizontalAlignment(alignment horizontal) {
514 	fAlignment.SetHorizontal(horizontal);
515 	UpdateHorizontal();
516 	fLS->InvalidateLayout();
517 }
518 
519 
520 /**
521  * Sets vertical alignment of the content in its area.
522  */
523 void
524 Area::SetVerticalAlignment(vertical_alignment vertical)
525 {
526 	fAlignment.SetVertical(vertical);
527 	UpdateVertical();
528 	fLS->InvalidateLayout();
529 }
530 
531 
532 /**
533  * Gets left inset between area and its content.
534  */
535 int32
536 Area::LeftInset() const
537 {
538 	return fLeftInset;
539 }
540 
541 
542 /**
543  * Sets left inset between area and its content.
544  */
545 void
546 Area::SetLeftInset(int32 left)
547 {
548 	fLeftInset = left;
549 	UpdateHorizontal();
550 	fLS->InvalidateLayout();
551 }
552 
553 
554 /**
555  * Gets top inset between area and its content.
556  */
557 int32
558 Area::TopInset() const
559 {
560 	return fTopInset;
561 }
562 
563 
564 /**
565  * Sets top inset between area and its content.
566  */
567 void
568 Area::SetTopInset(int32 top)
569 {
570 	fTopInset = top;
571 	UpdateVertical();
572 	fLS->InvalidateLayout();
573 }
574 
575 
576 /**
577  * Gets right inset between area and its content.
578  */
579 int32
580 Area::RightInset() const
581 {
582 	return fRightInset;
583 }
584 
585 
586 /**
587  * Sets right inset between area and its content.
588  */
589 void
590 Area::SetRightInset(int32 right)
591 {
592 	fRightInset = right;
593 	UpdateHorizontal();
594 }
595 
596 
597 /**
598  * Gets bottom inset between area and its content.
599  */
600 int32
601 Area::BottomInset() const
602 {
603 	return fBottomInset;
604 }
605 
606 
607 /**
608  * Sets bottom inset between area and its content.
609  */
610 void
611 Area::SetBottomInset(int32 bottom)
612 {
613 	fBottomInset = bottom;
614 	UpdateVertical();
615 }
616 
617 
618 /**
619  * Sets the preferred size according to the content's PreferredSize method,
620  * and the penalties according to heuristics.
621  */
622 void
623 Area::SetDefaultBehavior()
624 {
625 	if (Content() == NULL) {
626 		SetPreferredContentSize(BSize(0, 0));
627 		SetShrinkPenalties(BSize(0, 0));
628 		SetGrowPenalties(BSize(0, 0));
629 		return;
630 	}
631 
632 	if (PreferredContentSize() != Content()->PreferredSize()){
633 		SetPreferredContentSize(Content()->PreferredSize());
634 		fLS->InvalidateLayout();
635 	}
636 
637 	if (dynamic_cast<BButton*>(Content()) != NULL
638 		|| dynamic_cast<BRadioButton*>(Content()) != NULL
639 		|| dynamic_cast<BCheckBox*>(Content()) != NULL
640 		|| dynamic_cast<BStringView*>(Content()) != NULL
641 		|| dynamic_cast<BPictureButton*>(Content()) != NULL
642 		|| dynamic_cast<BStatusBar*>(Content()) != NULL) {
643 		fShrinkPenalties = BSize(4, 4);
644 		fGrowPenalties = BSize(3, 3);
645 	} else {
646 		fShrinkPenalties = BSize(2, 2);
647 		fGrowPenalties = BSize(1, 1);
648 	}
649 }
650 
651 
652 Area::operator BString() const
653 {
654 	BString string;
655 	GetString(string);
656 	return string;
657 }
658 
659 
660 void
661 Area::GetString(BString& string) const
662 {
663 	string << "Area(";
664 	fLeft->GetString(string);
665 	string << ", ";
666 	fTop->GetString(string);
667 	string << ", ";
668 	fRight->GetString(string);
669 	string << ", ";
670 	fBottom->GetString(string);
671 	string << ")";
672 }
673 
674 
675 /**
676  * Sets the width of the area to be the same as the width of the given area.
677  *
678  * @param area	the area that should have the same width
679  * @return the same-width constraint
680  */
681 Constraint*
682 Area::HasSameWidthAs(Area* area)
683 {
684 	return fLS->AddConstraint(
685 		-1.0, fLeft, 1.0, fRight, 1.0, area->fLeft, -1.0, area->fRight,
686 		OperatorType(EQ), 0.0);
687 }
688 
689 
690 /**
691  * Sets the height of the area to be the same as the height of the given area.
692  *
693  * @param area	the area that should have the same height
694  * @return the same-height constraint
695  */
696 Constraint*
697 Area::HasSameHeightAs(Area* area)
698 {
699 	return fLS->AddConstraint(
700 		-1.0, fTop, 1.0, fBottom, 1.0, area->fTop, -1.0, area->fBottom,
701 		OperatorType(EQ), 0.0);
702 }
703 
704 
705 /**
706  * Sets the size of the area to be the same as the size of the given area.
707  *
708  * @param area	the area that should have the same size
709  * @return a list containing a same-width and same-height constraint
710  */
711 BList*
712 Area::HasSameSizeAs(Area* area)
713 {
714 	BList* constraints = new BList(2);
715 	constraints->AddItem(this->HasSameWidthAs(area));
716 	constraints->AddItem(this->HasSameHeightAs(area));
717 	return constraints;
718 }
719 
720 
721 /**
722  * Destructor.
723  * Removes the area from its specification.
724  */
725 Area::~Area()
726 {
727 	if (fChildArea != NULL) delete fChildArea;
728 	for (int32 i = 0; i < fConstraints->CountItems(); i++)
729 		delete (Constraint*)fConstraints->ItemAt(i);
730 	fLS->Areas()->RemoveItem(this);
731 }
732 
733 
734 /**
735  * Constructor.
736  * Uses XTabs and YTabs.
737  */
738 Area::Area(BALMLayout* ls, XTab* left, YTab* top, XTab* right, YTab* bottom,
739 	BView* content, BSize minContentSize)
740 {
741 	Init(ls, left, top, right, bottom, content, minContentSize);
742 }
743 
744 
745 /**
746  * Constructor.
747  * Uses Rows and Columns.
748  */
749 Area::Area(BALMLayout* ls, Row* row, Column* column, BView* content,
750 	BSize minContentSize)
751 {
752 
753 	Init(ls, column->Left(), row->Top(), column->Right(), row->Bottom(),
754 			content, minContentSize);
755 	fRow = row;
756 	fColumn = column;
757 }
758 
759 
760 /**
761  * Initialize variables.
762  */
763 void
764 Area::Init(BALMLayout* ls, XTab* left, YTab* top, XTab* right, YTab* bottom,
765 	BView* content, BSize minContentSize)
766 {
767 
768 	fConstraints = new BList(2);
769 	fMaxContentSize = kMaxSize;
770 
771 	fMaxContentWidth = NULL;
772 	fMaxContentHeight = NULL;
773 
774 	fPreferredContentSize = kUndefinedSize;
775 	fShrinkPenalties = BSize(2, 2);
776 	fGrowPenalties = BSize(1, 1);
777 	fContentAspectRatio = 0;
778 	fContentAspectRatioC = NULL;
779 
780 	fAutoPreferredContentSize = false;
781 
782 	fPreferredContentWidth = NULL;
783 	fPreferredContentHeight = NULL;
784 
785 	fChildArea = NULL;
786 
787 	fAlignment = BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_USE_FULL_HEIGHT);
788 	fLeftInset = 0;
789 	fTopInset = 0;
790 	fRightInset = 0;
791 	fBottomInset = 0;
792 
793 	fLeftConstraint = NULL;
794 	fTopConstraint = NULL;
795 	fRightConstraint = NULL;
796 	fBottomConstraint = NULL;
797 
798 	fLS = ls;
799 	fLeft = left;
800 	fRight = right;
801 	fTop = top;
802 	fBottom = bottom;
803 	SetContent(content);
804 	fMinContentSize = minContentSize;
805 
806 	// adds the two essential constraints of the area that make sure that the left x-tab is
807 	// really to the left of the right x-tab, and the top y-tab really above the bottom y-tab
808 	fMinContentWidth = ls->AddConstraint(-1.0, left, 1.0, right, OperatorType(GE),
809 			minContentSize.Width());
810 	fConstraints->AddItem(fMinContentWidth);
811 
812 	fMinContentHeight = ls->AddConstraint(-1.0, top, 1.0, bottom, OperatorType(GE),
813 			minContentSize.Height());
814 	fConstraints->AddItem(fMinContentHeight);
815 }
816 
817 
818 /**
819  * Perform layout on the area.
820  */
821 void Area::DoLayout()
822 {
823 	if (Content() == NULL)
824 		return; // empty areas need no layout
825 
826 	// if there is a childArea, then it is the childArea that actually contains the content
827 	Area* area = (fChildArea != NULL) ? fChildArea : this;
828 
829 	// set content location and size
830 	area->Content()->MoveTo(floor(area->Left()->Value() + 0.5),
831 			floor(area->Top()->Value() + 0.5));
832 	int32 width = (int32)floor(area->Right()->Value() - area->Left()->Value() + 0.5);
833 	int32 height = (int32)floor(area->Bottom()->Value() - area->Top()->Value() + 0.5);
834 	area->Content()->ResizeTo(width, height);
835 }
836 
837 
838 /**
839  * Adds a childArea to this area, together with constraints that specify the relative location
840  * of the childArea within this area. It is called when such a childArea becomes necessary,
841  * i.e. when the user requests insets or special alignment.
842  */
843 void
844 Area::InitChildArea()
845 {
846 	// add a child area with new tabs,
847 	// and add constraints that set its tabs to be equal to the
848 	// coresponding tabs of this area (for a start)
849 	fChildArea = new Area(fLS, new XTab(fLS), new YTab(fLS), new XTab(fLS),
850 			new YTab(fLS), fContent, BSize(0, 0));
851 	fLeftConstraint = fLeft->IsEqual(fChildArea->Left());
852 	fConstraints->AddItem(fLeftConstraint);
853 	fTopConstraint = fTop->IsEqual(fChildArea->Top());
854 	fConstraints->AddItem(fTopConstraint);
855 	fRightConstraint = fRight->IsEqual(fChildArea->Right());
856 	fConstraints->AddItem(fRightConstraint);
857 	fBottomConstraint = fBottom->IsEqual(fChildArea->Bottom());
858 	fConstraints->AddItem(fBottomConstraint);
859 
860 	// remove the minimum content size constraints from this area
861 	// and copy the minimum content size setting to the childArea
862 	fConstraints->RemoveItem(fMinContentWidth);
863 	delete fMinContentWidth;
864 	fMinContentWidth = fChildArea->fMinContentWidth;
865 	fConstraints->RemoveItem(fMinContentHeight);
866 	delete fMinContentHeight;
867 	fMinContentHeight = fChildArea->fMinContentHeight;
868 	fChildArea->SetMinContentSize(fMinContentSize);
869 
870 	// if there are maximum content size constraints on this area,
871 	// change them so that they refer to the tabs of the childArea
872 	// and copy the minimum content size settings to the childArea
873 	if (fMaxContentWidth != NULL) {
874 		fChildArea->fMaxContentSize = fMaxContentSize;
875 
876 		fChildArea->fMaxContentWidth = fMaxContentWidth;
877 		fMaxContentWidth->SetLeftSide(
878 			-1.0, fChildArea->Left(), 1.0, fChildArea->Right());
879 
880 		fChildArea->fMaxContentHeight = fMaxContentHeight;
881 		fMaxContentHeight->SetLeftSide(
882 			-1.0, fChildArea->Top(), 1.0, fChildArea->Bottom());
883 	}
884 
885 	// if there are preferred content size constraints on this area,
886 	// change them so that they refer to the tabs of the childArea
887 	// and copy the preferred content size settings to the childArea
888 	if (fPreferredContentHeight != NULL) {
889 		fChildArea->fPreferredContentSize = fPreferredContentSize;
890 		fChildArea->fShrinkPenalties = fShrinkPenalties;
891 		fChildArea->fGrowPenalties = fGrowPenalties;
892 
893 		fChildArea->fPreferredContentWidth = fPreferredContentWidth;
894 		fPreferredContentWidth->SetLeftSide(
895 			-1.0, fChildArea->Left(), 1.0, fChildArea->Right());
896 
897 		fChildArea->fPreferredContentHeight = fPreferredContentHeight;
898 		fPreferredContentHeight->SetLeftSide(
899 			-1.0, fChildArea->Top(), 1.0, fChildArea->Bottom());
900 	}
901 }
902 
903 
904 /**
905  * Update the constraints for horizontal insets and alignment.
906  */
907 void
908 Area::UpdateHorizontal()
909 {
910 	// if the area does not have a childAdrea yet, this is the time to add it
911 	if (fChildArea == NULL)
912 		InitChildArea();
913 
914 	// change the constraints leftConstraint and rightConstraint so that the horizontal
915 	// alignment and insets of the childArea within this area are as specified by the user
916 	if (fAlignment.Horizontal() == B_ALIGN_LEFT) {
917 		fLeftConstraint->SetLeftSide(-1.0, fLeft, 1.0, fChildArea->Left());
918 		fLeftConstraint->SetOp(OperatorType(EQ));
919 		fLeftConstraint->SetRightSide(fLeftInset);
920 
921 		fRightConstraint->SetLeftSide(-1.0, fChildArea->Right(), 1.0, fRight);
922 		fRightConstraint->SetOp(OperatorType(GE));
923 		fRightConstraint->SetRightSide(fRightInset);
924 	} else if (fAlignment.Horizontal() == B_ALIGN_RIGHT) {
925 		fLeftConstraint->SetLeftSide(-1.0, fLeft, 1.0, fChildArea->Left());
926 		fLeftConstraint->SetOp(OperatorType(GE));
927 		fLeftConstraint->SetRightSide(fLeftInset);
928 
929 		fRightConstraint->SetLeftSide(-1.0, fChildArea->Right(), 1.0, fRight);
930 		fRightConstraint->SetOp(OperatorType(EQ));
931 		fRightConstraint->SetRightSide(fRightInset);
932 	} else if (fAlignment.Horizontal() == B_ALIGN_HORIZONTAL_CENTER) {
933 		fLeftConstraint->SetLeftSide(-1.0, fLeft, 1.0, fChildArea->Left());
934 		fLeftConstraint->SetOp(OperatorType(GE));
935 		fLeftConstraint->SetRightSide(max(fLeftInset, fRightInset));
936 
937 		fRightConstraint->SetLeftSide(-1.0, fLeft, 1.0, fChildArea->Left(), 1.0, fChildArea->Right(), -1.0, fRight);
938 		fRightConstraint->SetOp(OperatorType(EQ));
939 		fRightConstraint->SetRightSide(0);
940 	} else if (fAlignment.Horizontal() == B_ALIGN_USE_FULL_WIDTH) {
941 		fLeftConstraint->SetLeftSide(-1.0, fLeft, 1.0, fChildArea->Left());
942 		fLeftConstraint->SetOp(OperatorType(EQ));
943 		fLeftConstraint->SetRightSide(fLeftInset);
944 
945 		fRightConstraint->SetLeftSide(-1.0, fChildArea->Right(), 1.0, fRight);
946 		fRightConstraint->SetOp(OperatorType(EQ));
947 		fRightConstraint->SetRightSide(fRightInset);
948 	} else if (fAlignment.Horizontal() == B_ALIGN_HORIZONTAL_UNSET) {
949 		fLeftConstraint->SetLeftSide(-1.0, fLeft, 1.0, fChildArea->Left());
950 		fLeftConstraint->SetOp(OperatorType(GE));
951 		fLeftConstraint->SetRightSide(fLeftInset);
952 
953 		fRightConstraint->SetLeftSide(-1.0, fChildArea->Right(), 1.0, fRight);
954 		fRightConstraint->SetOp(OperatorType(GE));
955 		fRightConstraint->SetRightSide(fRightInset);
956 	}
957 }
958 
959 
960 /**
961  * Update the constraints for vertical insets and alignment.
962  */
963 void Area::UpdateVertical() {
964 	// if the area does not have a childAdrea yet, this is the time to add it
965 	if (fChildArea == NULL)
966 		InitChildArea();
967 
968 	// change the constraints topConstraint and bottomConstraint so that the vertical
969 	// alignment and insets of the childArea within this area are as specified by the user
970 	if (fAlignment.Vertical() == B_ALIGN_TOP) {
971 		fTopConstraint->SetLeftSide(-1.0, fTop, 1.0, fChildArea->Top());
972 		fTopConstraint->SetOp(OperatorType(EQ));
973 		fTopConstraint->SetRightSide(fTopInset);
974 
975 		fBottomConstraint->SetLeftSide(-1.0, fChildArea->Bottom(), 1.0, fBottom);
976 		fBottomConstraint->SetOp(OperatorType(GE));
977 		fBottomConstraint->SetRightSide(fBottomInset);
978 	} else if (fAlignment.Vertical() == B_ALIGN_BOTTOM) {
979 		fTopConstraint->SetLeftSide(-1.0, fTop, 1.0, fChildArea->Top());
980 		fTopConstraint->SetOp(OperatorType(GE));
981 		fTopConstraint->SetRightSide(fTopInset);
982 
983 		fBottomConstraint->SetLeftSide(-1.0, fChildArea->Bottom(), 1.0, fBottom);
984 		fBottomConstraint->SetOp(OperatorType(EQ));
985 		fBottomConstraint->SetRightSide(fBottomInset);
986 	} else if (fAlignment.Vertical() == B_ALIGN_VERTICAL_CENTER) {
987 		fTopConstraint->SetLeftSide(-1.0, fTop, 1.0, fChildArea->Top());
988 		fTopConstraint->SetOp(OperatorType(GE));
989 		fTopConstraint->SetRightSide(max(fTopInset, fBottomInset));
990 
991 		fBottomConstraint->SetLeftSide(-1.0, fTop, 1.0, fChildArea->Top(), 1.0, fChildArea->Bottom(), -1.0, fBottom);
992 		fBottomConstraint->SetOp(OperatorType(EQ));
993 		fBottomConstraint->SetRightSide(0);
994 	} else if (fAlignment.Vertical() == B_ALIGN_USE_FULL_HEIGHT) {
995 		fTopConstraint->SetLeftSide(-1.0, fTop, 1.0, fChildArea->Top());
996 		fTopConstraint->SetOp(OperatorType(EQ));
997 		fTopConstraint->SetRightSide(fTopInset);
998 
999 		fBottomConstraint->SetLeftSide(-1.0, fChildArea->Bottom(), 1.0, fBottom);
1000 		fBottomConstraint->SetOp(OperatorType(EQ));
1001 		fBottomConstraint->SetRightSide(fBottomInset);
1002 	} else if (fAlignment.Vertical() == B_ALIGN_VERTICAL_UNSET) {
1003 		fTopConstraint->SetLeftSide(-1.0, fTop, 1.0, fChildArea->Top());
1004 		fTopConstraint->SetOp(OperatorType(GE));
1005 		fTopConstraint->SetRightSide(fTopInset);
1006 
1007 		fBottomConstraint->SetLeftSide(-1.0, fChildArea->Bottom(), 1.0, fBottom);
1008 		fBottomConstraint->SetOp(OperatorType(GE));
1009 		fBottomConstraint->SetRightSide(fBottomInset);
1010 	}
1011 }
1012 
1013