#include <LayoutUtils.h>
#include <algorithm>
#include <ClassInfo.h>
#include <Layout.h>
#include <View.h>
#include "ViewLayoutItem.h"
int32
BLayoutUtils::AddSizesInt32(int32 a, int32 b)
{
if (a >= (int32)B_SIZE_UNLIMITED - b)
return (int32)B_SIZE_UNLIMITED;
return a + b;
}
int32
BLayoutUtils::AddSizesInt32(int32 a, int32 b, int32 c)
{
return AddSizesInt32(AddSizesInt32(a, b), c);
}
float
BLayoutUtils::AddDistances(float a, float b)
{
float sum = a + b + 1;
if (sum >= B_SIZE_UNLIMITED)
return B_SIZE_UNLIMITED;
return sum;
}
float
BLayoutUtils::AddDistances(float a, float b, float c)
{
return AddDistances(AddDistances(a, b), c);
}
int32
BLayoutUtils::SubtractSizesInt32(int32 a, int32 b)
{
if (a < b)
return 0;
return a - b;
}
float
BLayoutUtils::SubtractDistances(float a, float b)
{
if (a < b)
return -1;
return a - b - 1;
}
void
BLayoutUtils::FixSizeConstraints(float& min, float& max, float& preferred)
{
if (max < min)
max = min;
if (preferred < min)
preferred = min;
else if (preferred > max)
preferred = max;
}
void
BLayoutUtils::FixSizeConstraints(BSize& min, BSize& max, BSize& preferred)
{
FixSizeConstraints(min.width, max.width, preferred.width);
FixSizeConstraints(min.height, max.height, preferred.height);
}
BSize
BLayoutUtils::ComposeSize(BSize size, BSize layoutSize)
{
if (!size.IsWidthSet())
size.width = layoutSize.width;
if (!size.IsHeightSet())
size.height = layoutSize.height;
return size;
}
BAlignment
BLayoutUtils::ComposeAlignment(BAlignment alignment, BAlignment layoutAlignment)
{
if (!alignment.IsHorizontalSet())
alignment.horizontal = layoutAlignment.horizontal;
if (!alignment.IsVerticalSet())
alignment.vertical = layoutAlignment.vertical;
return alignment;
}
BRect
BLayoutUtils::AlignInFrame(BRect frame, BSize maxSize, BAlignment alignment)
{
if (maxSize.width < frame.Width()
&& alignment.horizontal != B_ALIGN_USE_FULL_WIDTH) {
frame.left += (int)((frame.Width() - maxSize.width)
* alignment.RelativeHorizontal());
frame.right = frame.left + maxSize.width;
}
if (maxSize.height < frame.Height()
&& alignment.vertical != B_ALIGN_USE_FULL_HEIGHT) {
frame.top += (int)((frame.Height() - maxSize.height)
* alignment.RelativeVertical());
frame.bottom = frame.top + maxSize.height;
}
return frame;
}
void
BLayoutUtils::AlignInFrame(BView* view, BRect frame)
{
BSize maxSize = view->MaxSize();
BAlignment alignment = view->LayoutAlignment();
if (view->HasHeightForWidth()) {
if (maxSize.width < frame.Width()
&& alignment.horizontal != B_ALIGN_USE_FULL_WIDTH) {
frame.OffsetBy(floorf((frame.Width() - maxSize.width)
* alignment.RelativeHorizontal()), 0);
frame.right = frame.left + maxSize.width;
}
alignment.horizontal = B_ALIGN_USE_FULL_WIDTH;
float minHeight;
float maxHeight;
float preferredHeight;
view->GetHeightForWidth(frame.Width(), &minHeight, &maxHeight,
&preferredHeight);
frame.bottom = frame.top + std::max(frame.Height(), minHeight);
maxSize.height = minHeight;
}
frame = AlignInFrame(frame, maxSize, alignment);
view->MoveTo(frame.LeftTop());
view->ResizeTo(frame.Size());
}
BRect
BLayoutUtils::AlignOnRect(BRect rect, BSize size, BAlignment alignment)
{
rect.left += (int)((rect.Width() - size.width)
* alignment.RelativeHorizontal());
rect.top += (int)(((rect.Height() - size.height))
* alignment.RelativeVertical());
rect.right = rect.left + size.width;
rect.bottom = rect.top + size.height;
return rect;
}
BRect
BLayoutUtils::MoveIntoFrame(BRect rect, BSize frameSize)
{
BPoint leftTop(rect.LeftTop());
if (rect.right > frameSize.width)
leftTop.x -= rect.right - frameSize.width;
if (leftTop.x < 0)
leftTop.x = 0;
if (rect.bottom > frameSize.height)
leftTop.y -= rect.bottom - frameSize.height;
if (leftTop.y < 0)
leftTop.y = 0;
return rect.OffsetToSelf(leftTop);
}
BString
BLayoutUtils::GetLayoutTreeDump(BView* view)
{
BString result;
_GetLayoutTreeDump(view, 0, result);
return result;
}
BString
BLayoutUtils::GetLayoutTreeDump(BLayoutItem* item)
{
BString result;
_GetLayoutTreeDump(item, 0, false, result);
return result;
}
void
BLayoutUtils::_GetLayoutTreeDump(BView* view, int level, BString& _output)
{
BString indent;
indent.SetTo(' ', level * 4);
if (view == NULL) {
_output << indent << "<null view>\n";
return;
}
BRect frame = view->Frame();
BSize min = view->MinSize();
BSize max = view->MaxSize();
BSize preferred = view->PreferredSize();
_output << BString().SetToFormat(
"%sview %p (%s %s):\n"
"%s frame: (%f, %f, %f, %f)\n"
"%s min: (%f, %f)\n"
"%s max: (%f, %f)\n"
"%s pref: (%f, %f)\n",
indent.String(), view, class_name(view), view->Name(),
indent.String(), frame.left, frame.top, frame.right, frame.bottom,
indent.String(), min.width, min.height,
indent.String(), max.width, max.height,
indent.String(), preferred.width, preferred.height);
if (BLayout* layout = view->GetLayout()) {
_GetLayoutTreeDump(layout, level, true, _output);
return;
}
int32 count = view->CountChildren();
for (int32 i = 0; i < count; i++) {
_output << indent << " ---\n";
_GetLayoutTreeDump(view->ChildAt(i), level + 1, _output);
}
}
void
BLayoutUtils::_GetLayoutTreeDump(BLayoutItem* item, int level,
bool isViewLayout, BString& _output)
{
if (BViewLayoutItem* viewItem = dynamic_cast<BViewLayoutItem*>(item)) {
_GetLayoutTreeDump(viewItem->View(), level, _output);
return;
}
BString indent;
indent.SetTo(' ', level * 4);
if (item == NULL) {
_output << indent << "<null item>\n";
return;
}
BLayout* layout = dynamic_cast<BLayout*>(item);
BRect frame = item->Frame();
BSize min = item->MinSize();
BSize max = item->MaxSize();
BSize preferred = item->PreferredSize();
if (isViewLayout) {
_output << indent << BString().SetToFormat(" [layout %p (%s)]\n",
layout, class_name(layout));
} else {
_output << indent << BString().SetToFormat("item %p (%s):\n",
item, class_name(item));
}
_output << BString().SetToFormat(
"%s frame: (%f, %f, %f, %f)\n"
"%s min: (%f, %f)\n"
"%s max: (%f, %f)\n"
"%s pref: (%f, %f)\n",
indent.String(), frame.left, frame.top, frame.right, frame.bottom,
indent.String(), min.width, min.height,
indent.String(), max.width, max.height,
indent.String(), preferred.width, preferred.height);
if (layout == NULL)
return;
int32 count = layout->CountItems();
for (int32 i = 0; i < count; i++) {
_output << indent << " ---\n";
_GetLayoutTreeDump(layout->ItemAt(i), level + 1, false, _output);
}
}