tcp: Fix 64 bit build with debugging features enabled.
[haiku.git] / src / kits / interface / LayoutUtils.cpp
blobba2f9d246a15243b9bca3f06553cebfbb2baa6fa
1 /*
2 * Copyright 2006-2013, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Copyright 2014 Haiku, Inc. All rights reserved.
5 * Distributed under the terms of the MIT License.
7 * Authors:
8 * John Scipione, jscipione@gmail.com
9 * Ingo Weinhold, ingo_weinhold@gmx.de
12 #include <LayoutUtils.h>
14 #include <algorithm>
15 #include <typeinfo>
17 #include <Layout.h>
18 #include <View.h>
20 #include "ViewLayoutItem.h"
23 // // AddSizesFloat
24 // float
25 // BLayoutUtils::AddSizesFloat(float a, float b)
26 // {
27 // float sum = a + b + 1;
28 // if (sum >= B_SIZE_UNLIMITED)
29 // return B_SIZE_UNLIMITED;
31 // return sum;
32 // }
34 // // AddSizesFloat
35 // float
36 // BLayoutUtils::AddSizesFloat(float a, float b, float c)
37 // {
38 // return AddSizesFloat(AddSizesFloat(a, b), c);
39 // }
42 // AddSizesInt32
43 int32
44 BLayoutUtils::AddSizesInt32(int32 a, int32 b)
46 if (a >= B_SIZE_UNLIMITED - b)
47 return B_SIZE_UNLIMITED;
48 return a + b;
52 // AddSizesInt32
53 int32
54 BLayoutUtils::AddSizesInt32(int32 a, int32 b, int32 c)
56 return AddSizesInt32(AddSizesInt32(a, b), c);
60 // AddDistances
61 float
62 BLayoutUtils::AddDistances(float a, float b)
64 float sum = a + b + 1;
65 if (sum >= B_SIZE_UNLIMITED)
66 return B_SIZE_UNLIMITED;
68 return sum;
72 // AddDistances
73 float
74 BLayoutUtils::AddDistances(float a, float b, float c)
76 return AddDistances(AddDistances(a, b), c);
80 // // SubtractSizesFloat
81 // float
82 // BLayoutUtils::SubtractSizesFloat(float a, float b)
83 // {
84 // if (a < b)
85 // return -1;
86 // return a - b - 1;
87 // }
90 // SubtractSizesInt32
91 int32
92 BLayoutUtils::SubtractSizesInt32(int32 a, int32 b)
94 if (a < b)
95 return 0;
96 return a - b;
100 // SubtractDistances
101 float
102 BLayoutUtils::SubtractDistances(float a, float b)
104 if (a < b)
105 return -1;
106 return a - b - 1;
110 // FixSizeConstraints
111 void
112 BLayoutUtils::FixSizeConstraints(float& min, float& max, float& preferred)
114 if (max < min)
115 max = min;
116 if (preferred < min)
117 preferred = min;
118 else if (preferred > max)
119 preferred = max;
123 // FixSizeConstraints
124 void
125 BLayoutUtils::FixSizeConstraints(BSize& min, BSize& max, BSize& preferred)
127 FixSizeConstraints(min.width, max.width, preferred.width);
128 FixSizeConstraints(min.height, max.height, preferred.height);
132 // ComposeSize
133 BSize
134 BLayoutUtils::ComposeSize(BSize size, BSize layoutSize)
136 if (!size.IsWidthSet())
137 size.width = layoutSize.width;
138 if (!size.IsHeightSet())
139 size.height = layoutSize.height;
141 return size;
145 // ComposeAlignment
146 BAlignment
147 BLayoutUtils::ComposeAlignment(BAlignment alignment, BAlignment layoutAlignment)
149 if (!alignment.IsHorizontalSet())
150 alignment.horizontal = layoutAlignment.horizontal;
151 if (!alignment.IsVerticalSet())
152 alignment.vertical = layoutAlignment.vertical;
154 return alignment;
158 // AlignInFrame
159 // This method restricts the dimensions of the resulting rectangle according
160 // to the available size specified by maxSize.
161 BRect
162 BLayoutUtils::AlignInFrame(BRect frame, BSize maxSize, BAlignment alignment)
164 // align according to the given alignment
165 if (maxSize.width < frame.Width()
166 && alignment.horizontal != B_ALIGN_USE_FULL_WIDTH) {
167 frame.left += (int)((frame.Width() - maxSize.width)
168 * alignment.RelativeHorizontal());
169 frame.right = frame.left + maxSize.width;
171 if (maxSize.height < frame.Height()
172 && alignment.vertical != B_ALIGN_USE_FULL_HEIGHT) {
173 frame.top += (int)((frame.Height() - maxSize.height)
174 * alignment.RelativeVertical());
175 frame.bottom = frame.top + maxSize.height;
178 return frame;
182 // AlignInFrame
183 void
184 BLayoutUtils::AlignInFrame(BView* view, BRect frame)
186 BSize maxSize = view->MaxSize();
187 BAlignment alignment = view->LayoutAlignment();
188 if (view->HasHeightForWidth()) {
189 // The view has height for width, so we do the horizontal alignment
190 // ourselves and restrict the height max constraint respectively.
191 if (maxSize.width < frame.Width()
192 && alignment.horizontal != B_ALIGN_USE_FULL_WIDTH) {
193 frame.OffsetBy(floorf((frame.Width() - maxSize.width)
194 * alignment.RelativeHorizontal()), 0);
195 frame.right = frame.left + maxSize.width;
197 alignment.horizontal = B_ALIGN_USE_FULL_WIDTH;
198 float minHeight;
199 float maxHeight;
200 float preferredHeight;
201 view->GetHeightForWidth(frame.Width(), &minHeight, &maxHeight,
202 &preferredHeight);
203 frame.bottom = frame.top + std::max(frame.Height(), minHeight);
204 maxSize.height = minHeight;
206 frame = AlignInFrame(frame, maxSize, alignment);
207 view->MoveTo(frame.LeftTop());
208 view->ResizeTo(frame.Size());
212 // AlignOnRect
213 // This method, unlike AlignInFrame(), provides the possibility to return
214 // a rectangle with dimensions greater than the available size.
215 BRect
216 BLayoutUtils::AlignOnRect(BRect rect, BSize size, BAlignment alignment)
218 rect.left += (int)((rect.Width() - size.width)
219 * alignment.RelativeHorizontal());
220 rect.top += (int)(((rect.Height() - size.height))
221 * alignment.RelativeVertical());
222 rect.right = rect.left + size.width;
223 rect.bottom = rect.top + size.height;
225 return rect;
229 /*! Offsets a rectangle's location so that it lies fully in a given rectangular
230 frame.
232 If the rectangle is too wide/high to fully fit in the frame, its left/top
233 edge is offset to 0. The rect's size always remains unchanged.
235 \param rect The rectangle to be moved.
236 \param frameSize The size of the frame the rect shall be moved into. The
237 frame's left-top is (0, 0).
238 \return The modified rect.
240 /*static*/ BRect
241 BLayoutUtils::MoveIntoFrame(BRect rect, BSize frameSize)
243 BPoint leftTop(rect.LeftTop());
245 // enforce horizontal limits; favor left edge
246 if (rect.right > frameSize.width)
247 leftTop.x -= rect.right - frameSize.width;
248 if (leftTop.x < 0)
249 leftTop.x = 0;
251 // enforce vertical limits; favor top edge
252 if (rect.bottom > frameSize.height)
253 leftTop.y -= rect.bottom - frameSize.height;
254 if (leftTop.y < 0)
255 leftTop.y = 0;
257 return rect.OffsetToSelf(leftTop);
261 /*static*/ BString
262 BLayoutUtils::GetLayoutTreeDump(BView* view)
264 BString result;
265 _GetLayoutTreeDump(view, 0, result);
266 return result;
270 /*static*/ BString
271 BLayoutUtils::GetLayoutTreeDump(BLayoutItem* item)
273 BString result;
274 _GetLayoutTreeDump(item, 0, false, result);
275 return result;
279 /*static*/ void
280 BLayoutUtils::_GetLayoutTreeDump(BView* view, int level, BString& _output)
282 BString indent;
283 indent.SetTo(' ', level * 2);
285 if (view == NULL) {
286 _output << indent << "<null view>\n";
287 return;
290 BRect frame = view->Frame();
291 BSize min = view->MinSize();
292 BSize max = view->MinSize();
293 BSize preferred = view->PreferredSize();
294 _output << BString().SetToFormat(
295 "%sview %p (%s):\n"
296 "%s frame: (%f, %f, %f, %f)\n"
297 "%s min: (%f, %f)\n"
298 "%s max: (%f, %f)\n"
299 "%s pref: (%f, %f)\n",
300 indent.String(), view, typeid(*view).name(),
301 indent.String(), frame.left, frame.top, frame.right, frame.bottom,
302 indent.String(), min.width, min.height,
303 indent.String(), max.width, max.height,
304 indent.String(), preferred.width, preferred.height);
306 if (BLayout* layout = view->GetLayout()) {
307 _GetLayoutTreeDump(layout, level, true, _output);
308 return;
311 int32 count = view->CountChildren();
312 for (int32 i = 0; i < count; i++) {
313 _output << indent << " ---\n";
314 _GetLayoutTreeDump(view->ChildAt(i), level + 1, _output);
319 /*static*/ void
320 BLayoutUtils::_GetLayoutTreeDump(BLayoutItem* item, int level,
321 bool isViewLayout, BString& _output)
323 if (BViewLayoutItem* viewItem = dynamic_cast<BViewLayoutItem*>(item)) {
324 _GetLayoutTreeDump(viewItem->View(), level, _output);
325 return;
328 BString indent;
329 indent.SetTo(' ', level * 2);
331 if (item == NULL) {
332 _output << indent << "<null item>\n";
333 return;
336 BLayout* layout = dynamic_cast<BLayout*>(item);
337 BRect frame = item->Frame();
338 BSize min = item->MinSize();
339 BSize max = item->MinSize();
340 BSize preferred = item->PreferredSize();
341 if (isViewLayout) {
342 _output << indent << BString().SetToFormat(" [layout %p (%s)]\n",
343 layout, typeid(*layout).name());
344 } else {
345 _output << indent << BString().SetToFormat("item %p (%s):\n",
346 item, typeid(*item).name());
348 _output << BString().SetToFormat(
349 "%s frame: (%f, %f, %f, %f)\n"
350 "%s min: (%f, %f)\n"
351 "%s max: (%f, %f)\n"
352 "%s pref: (%f, %f)\n",
353 indent.String(), frame.left, frame.top, frame.right, frame.bottom,
354 indent.String(), min.width, min.height,
355 indent.String(), max.width, max.height,
356 indent.String(), preferred.width, preferred.height);
358 if (layout == NULL)
359 return;
361 int32 count = layout->CountItems();
362 for (int32 i = 0; i < count; i++) {
363 _output << indent << " ---\n";
364 _GetLayoutTreeDump(layout->ItemAt(i), level + 1, false, _output);