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
Group(BRect frame,const char * name,orientation direction)14 Group::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
~Group()24 Group::~Group()
25 {
26 }
27
28 // AttachedToWindow
29 void
AttachedToWindow()30 Group::AttachedToWindow()
31 {
32 // trigger a layout
33 FrameResized(Bounds().Width(), Bounds().Height());
34 }
35
36 // FrameResized
37 void
FrameResized(float width,float height)38 Group::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
47 void
GetPreferredSize(float * width,float * height)48 Group::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
60 void
SetSpacing(float insetFromBorder,float childSpacing)61 Group::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
75 void
_LayoutControls(BRect r) const76 Group::_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
96 BRect
_MinFrame() const97 Group::_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
122 void
_LayoutControl(BView * view,BRect frame,bool resizeWidth,bool resizeHeight) const123 Group::_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