xref: /haiku/src/kits/interface/LayoutUtils.cpp (revision c90684742e7361651849be4116d0e5de3a817194)
1 /*
2  * Copyright 2006, Ingo Weinhold <bonefish@cs.tu-berlin.de>.
3  * All rights reserved. Distributed under the terms of the MIT License.
4  */
5 
6 #include <LayoutUtils.h>
7 
8 #include <View.h>
9 
10 
11 // // AddSizesFloat
12 // float
13 // BLayoutUtils::AddSizesFloat(float a, float b)
14 // {
15 // 	float sum = a + b + 1;
16 // 	if (sum >= B_SIZE_UNLIMITED)
17 // 		return B_SIZE_UNLIMITED;
18 //
19 // 	return sum;
20 // }
21 //
22 // // AddSizesFloat
23 // float
24 // BLayoutUtils::AddSizesFloat(float a, float b, float c)
25 // {
26 // 	return AddSizesFloat(AddSizesFloat(a, b), c);
27 // }
28 
29 
30 // AddSizesInt32
31 int32
32 BLayoutUtils::AddSizesInt32(int32 a, int32 b)
33 {
34 	if (a >= B_SIZE_UNLIMITED - b)
35 		return B_SIZE_UNLIMITED;
36 	return a + b;
37 }
38 
39 
40 // AddSizesInt32
41 int32
42 BLayoutUtils::AddSizesInt32(int32 a, int32 b, int32 c)
43 {
44 	return AddSizesInt32(AddSizesInt32(a, b), c);
45 }
46 
47 
48 // AddDistances
49 float
50 BLayoutUtils::AddDistances(float a, float b)
51 {
52 	float sum = a + b + 1;
53 	if (sum >= B_SIZE_UNLIMITED)
54 		return B_SIZE_UNLIMITED;
55 
56 	return sum;
57 }
58 
59 
60 // AddDistances
61 float
62 BLayoutUtils::AddDistances(float a, float b, float c)
63 {
64 	return AddDistances(AddDistances(a, b), c);
65 }
66 
67 
68 // // SubtractSizesFloat
69 // float
70 // BLayoutUtils::SubtractSizesFloat(float a, float b)
71 // {
72 // 	if (a < b)
73 // 		return -1;
74 // 	return a - b - 1;
75 // }
76 
77 
78 // SubtractSizesInt32
79 int32
80 BLayoutUtils::SubtractSizesInt32(int32 a, int32 b)
81 {
82 	if (a < b)
83 		return 0;
84 	return a - b;
85 }
86 
87 
88 // SubtractDistances
89 float
90 BLayoutUtils::SubtractDistances(float a, float b)
91 {
92 	if (a < b)
93 		return -1;
94 	return a - b - 1;
95 }
96 
97 
98 // FixSizeConstraints
99 void
100 BLayoutUtils::FixSizeConstraints(float& min, float& max, float& preferred)
101 {
102 	if (max < min)
103 		max = min;
104 	if (preferred < min)
105 		preferred = min;
106 	else if (preferred > max)
107 		preferred = max;
108 }
109 
110 
111 // FixSizeConstraints
112 void
113 BLayoutUtils::FixSizeConstraints(BSize& min, BSize& max, BSize& preferred)
114 {
115 	FixSizeConstraints(min.width, max.width, preferred.width);
116 	FixSizeConstraints(min.height, max.height, preferred.height);
117 }
118 
119 
120 // ComposeSize
121 BSize
122 BLayoutUtils::ComposeSize(BSize size, BSize layoutSize)
123 {
124 	if (!size.IsWidthSet())
125 		size.width = layoutSize.width;
126 	if (!size.IsHeightSet())
127 		size.height = layoutSize.height;
128 
129 	return size;
130 }
131 
132 
133 // ComposeAlignment
134 BAlignment
135 BLayoutUtils::ComposeAlignment(BAlignment alignment, BAlignment layoutAlignment)
136 {
137 	if (!alignment.IsHorizontalSet())
138 		alignment.horizontal = layoutAlignment.horizontal;
139 	if (!alignment.IsVerticalSet())
140 		alignment.vertical = layoutAlignment.vertical;
141 
142 	return alignment;
143 }
144 
145 
146 // AlignInFrame
147 BRect
148 BLayoutUtils::AlignInFrame(BRect frame, BSize maxSize, BAlignment alignment)
149 {
150 	// align according to the given alignment
151 	if (maxSize.width < frame.Width()
152 		&& alignment.horizontal != B_ALIGN_USE_FULL_WIDTH) {
153 		frame.left += (int)((frame.Width() - maxSize.width)
154 			* alignment.RelativeHorizontal());
155 		frame.right = frame.left + maxSize.width;
156 	}
157 	if (maxSize.height < frame.Height()
158 		&& alignment.vertical != B_ALIGN_USE_FULL_HEIGHT) {
159 		frame.top += (int)((frame.Height() - maxSize.height)
160 			* alignment.RelativeVertical());
161 		frame.bottom = frame.top + maxSize.height;
162 	}
163 
164 	return frame;
165 }
166 
167 
168 // AlignInFrame
169 void
170 BLayoutUtils::AlignInFrame(BView* view, BRect frame)
171 {
172  	BSize maxSize = view->MaxSize();
173  	BAlignment alignment = view->LayoutAlignment();
174 
175  	if (view->HasHeightForWidth()) {
176  		// The view has height for width, so we do the horizontal alignment
177  		// ourselves and restrict the height max constraint respectively.
178 
179  		if (maxSize.width < frame.Width()
180  			&& alignment.horizontal != B_ALIGN_USE_FULL_WIDTH) {
181  			frame.OffsetBy(floor((frame.Width() - maxSize.width)
182  				* alignment.RelativeHorizontal()), 0);
183  			frame.right = frame.left + maxSize.width;
184  		}
185  		alignment.horizontal = B_ALIGN_USE_FULL_WIDTH;
186 
187  		float minHeight;
188  		float maxHeight;
189  		float preferredHeight;
190  		view->GetHeightForWidth(frame.Width(), &minHeight, &maxHeight,
191  			&preferredHeight);
192 
193  		frame.bottom = frame.top + max_c(frame.Height(), minHeight);
194  		maxSize.height = minHeight;
195  	}
196 
197  	frame = AlignInFrame(frame, maxSize, alignment);
198  	view->MoveTo(frame.LeftTop());
199  	view->ResizeTo(frame.Size());
200 }
201 
202