1/*
2 * Copyright 2006, Haiku.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Stephan A��mus <superstippi@gmx.de>
7 */
8
9#include "Group.h"
10
11#include <stdio.h>
12
13// constructor
14Group::Group(BRect frame, const char* name, orientation direction)
15	: BView(frame, name, B_FOLLOW_ALL, B_FRAME_EVENTS),
16	  fOrientation(direction),
17	  fInset(4.0),
18	  fSpacing(0.0)
19{
20	SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
21}
22
23// destructor
24Group::~Group()
25{
26}
27
28// AttachedToWindow
29void
30Group::AttachedToWindow()
31{
32	// trigger a layout
33	FrameResized(Bounds().Width(), Bounds().Height());
34}
35
36// FrameResized
37void
38Group::FrameResized(float width, float height)
39{
40	// layout controls
41	BRect r(Bounds());
42	r.InsetBy(fInset, fInset);
43	_LayoutControls(r);
44}
45
46// GetPreferredSize
47void
48Group::GetPreferredSize(float* width, float* height)
49{
50	BRect r(_MinFrame());
51
52	if (width)
53		*width = r.Width();
54	if (height)
55		*height = r.Height();
56}
57
58// #pragma mark -
59
60void
61Group::SetSpacing(float insetFromBorder, float childSpacing)
62{
63	if (fSpacing == childSpacing && fInset == insetFromBorder)
64		return;
65
66	fInset = insetFromBorder;
67	fSpacing = childSpacing;
68	// trigger a layout
69	FrameResized(Bounds().Width(), Bounds().Height());
70}
71
72// #pragma mark -
73
74// _LayoutControls
75void
76Group::_LayoutControls(BRect r) const
77{
78	if (fOrientation == B_HORIZONTAL) {
79		r.left -= fSpacing;
80		for (int32 i = 0; BView* child = ChildAt(i); i++) {
81			r.right = r.left + child->Bounds().Width() + 2 * fSpacing;
82			_LayoutControl(child, r);
83			r.left = r.right + 1.0 - fSpacing;
84		}
85	} else {
86		r.top -= fSpacing;
87		for (int32 i = 0; BView* child = ChildAt(i); i++) {
88			r.bottom = r.top + child->Bounds().Height() + 2 * fSpacing;
89			_LayoutControl(child, r);
90			r.top = r.bottom + 1.0 - fSpacing;
91		}
92	}
93}
94
95// _MinFrame
96BRect
97Group::_MinFrame() const
98{
99	float minWidth = fInset * 2.0;
100	float minHeight = fInset * 2.0;
101
102	if (fOrientation == B_HORIZONTAL) {
103		minWidth += fSpacing;
104		for (int32 i = 0; BView* child = ChildAt(i); i++) {
105			minWidth += child->Bounds().Width() + 1 + fSpacing;
106			minHeight = max_c(minHeight,
107							  child->Bounds().Height() + 1 + fInset * 2.0);
108		}
109	} else {
110		minHeight += fSpacing;
111		for (int32 i = 0; BView* child = ChildAt(i); i++) {
112			minHeight += child->Bounds().Height() + 1 + fSpacing;
113			minWidth = max_c(minWidth,
114							 child->Bounds().Width() + 1 + fInset * 2.0);
115		}
116	}
117
118	return BRect(0.0, 0.0, minWidth - 1.0, minHeight - 1.0);
119}
120
121// _LayoutControl
122void
123Group::_LayoutControl(BView* view, BRect frame,
124					  bool resizeWidth, bool resizeHeight) const
125{
126	if (!resizeHeight)
127		// center vertically
128		frame.top = (frame.top + frame.bottom) / 2.0 - view->Bounds().Height() / 2.0;
129	if (!resizeWidth)
130		// center horizontally
131		frame.left = (frame.left + frame.right) / 2.0 - view->Bounds().Width() / 2.0;
132	view->MoveTo(frame.LeftTop());
133	float width = resizeWidth ? frame.Width() : view->Bounds().Width();
134	float height = resizeHeight ? frame.Height() : view->Bounds().Height();
135	if (resizeWidth || resizeHeight)
136		view->ResizeTo(width, height);
137}
138
139