xref: /haiku/src/tests/kits/interface/menu/menuworld/ViewLayoutFactory.cpp (revision 372eb8749cfa097031c6ff888508c0b61f577746)
1 //--------------------------------------------------------------------
2 //
3 //	ViewLayoutFactory.cpp
4 //
5 //	Written by: Owen Smith
6 //
7 //--------------------------------------------------------------------
8 
9 /*
10 	Copyright 1999, Be Incorporated.   All Rights Reserved.
11 	This file may be used under the terms of the Be Sample Code License.
12 */
13 
14 #include "ViewLayoutFactory.h"
15 
16 #include <Button.h>
17 #include <CheckBox.h>
18 #include <TextControl.h>
19 #include <View.h>
20 #include <List.h>
21 #include <algorithm>
22 #include <assert.h>
23 #include <stdio.h>
24 
25 template <class T>
average(const T & x,const T & y)26 inline T average(const T& x, const T& y)
27 {
28 	return (x + y) / 2;
29 }
30 
31 
32 //--------------------------------------------------------------------
33 //	ViewLayoutFactory factory generators
34 
MakeButton(const char * name,const char * label,uint32 msgID,BPoint pos,corner posRef)35 BButton* ViewLayoutFactory::MakeButton(const char* name, const char* label,
36 	uint32 msgID, BPoint pos, corner posRef)
37 {
38 	BRect dummyFrame(0,0,0,0);
39 	BButton* pButton = new BButton(dummyFrame, name, label,
40 		new BMessage(msgID));
41 	pButton->ResizeToPreferred();
42 	MoveViewCorner(*pButton, pos, posRef);
43 	return pButton;
44 }
45 
MakeCheckBox(const char * name,const char * label,uint32 msgID,BPoint pos,corner posRef)46 BCheckBox* ViewLayoutFactory::MakeCheckBox(const char* name,
47 	const char* label, uint32 msgID, BPoint pos, corner posRef)
48 {
49 	BRect dummyFrame(0,0,0,0);
50 	BCheckBox* pCheckBox = new BCheckBox(dummyFrame, name, label,
51 		new BMessage(msgID));
52 	pCheckBox->ResizeToPreferred();
53 	MoveViewCorner(*pCheckBox, pos, posRef);
54 	return pCheckBox;
55 }
56 
MakeTextControl(const char * name,const char * label,const char * text,BPoint pos,float controlWidth,corner posRef)57 BTextControl* ViewLayoutFactory::MakeTextControl(const char* name,
58 	const char* label, const char* text, BPoint pos, float controlWidth,
59 	corner posRef)
60 {
61 	// Note: this function is almost identical to the regular
62 	// BTextControl constructor, but it minimizes the label
63 	// width and maximizes the field width, instead of divvying
64 	// them up half-&-half or 2 : 3, and gives the standard
65 	// flexibility of corner positioning.
66 	BRect dummyFrame(0,0,0,0);
67 	BTextControl* pCtrl = new BTextControl(dummyFrame, name, label,
68 		text, NULL);
69 	LayoutTextControl(*pCtrl, pos, controlWidth, posRef);
70 	return pCtrl;
71 }
72 
LayoutTextControl(BTextControl & control,BPoint pos,float controlWidth,corner posRef)73 void ViewLayoutFactory::LayoutTextControl(BTextControl& control,
74 	BPoint pos, float controlWidth, corner posRef)
75 {
76 	control.ResizeToPreferred();
77 	BTextView* pTextView = control.TextView();
78 	float widthExpand = controlWidth;
79 	widthExpand -= control.Bounds().Width();
80 	if (widthExpand > 0) {
81 		control.ResizeBy(widthExpand, 0);
82 		pTextView->ResizeBy(widthExpand, 0);
83 	}
84 	MoveViewCorner(control, pos, posRef);
85 }
86 
87 
88 
89 //--------------------------------------------------------------------
90 //	ViewLayoutFactory implementation member functions
91 
MoveViewCorner(BView & view,BPoint pos,corner posRef)92 void ViewLayoutFactory::MoveViewCorner(BView& view, BPoint pos, corner posRef)
93 {
94 	BRect frame = view.Frame();
95 	BPoint topLeft;
96 	switch (posRef) {
97 	case CORNER_TOPLEFT:
98 		topLeft = pos;
99 		break;
100 	case CORNER_BOTTOMLEFT:
101 		topLeft.x = pos.x;
102 		topLeft.y = pos.y - frame.Height();
103 		break;
104 	case CORNER_TOPRIGHT:
105 		topLeft.x = pos.x - frame.Width();
106 		topLeft.y = pos.y;
107 		break;
108 	case CORNER_BOTTOMRIGHT:
109 		topLeft.x = pos.x - frame.Width();
110 		topLeft.y = pos.y - frame.Height();
111 		break;
112 	}
113 
114 	view.MoveTo(topLeft);
115 }
116 
Align(BList & viewList,align_side side,float alignLen)117 void ViewLayoutFactory::Align(BList& viewList, align_side side,
118 	float alignLen)
119 {
120 	int32 i, len = viewList.CountItems();
121 	if (len <= 1) {
122 		return;
123 	}
124 
125 	// make sure alignment is recognized
126 	if ((side != ALIGN_LEFT) && (side != ALIGN_TOP)
127 		&& (side != ALIGN_RIGHT) && (side != ALIGN_BOTTOM)
128 		&& (side != ALIGN_HCENTER) && (side != ALIGN_VCENTER))
129 	{
130 		return;
131 	}
132 
133 	// find initial location for placement, based on head item
134 	BPoint viewLoc;
135 	BView* pView = reinterpret_cast<BView*>(viewList.ItemAt(0));
136 	if (! pView) {
137 		return;
138 	}
139 
140 	BRect frame = pView->Frame();
141 	switch (side) {
142 	case ALIGN_LEFT:
143 	case ALIGN_TOP:
144 		viewLoc.Set(frame.left, frame.top);
145 		break;
146 	case ALIGN_RIGHT:
147 		viewLoc.Set(frame.right, frame.top);
148 		break;
149 	case ALIGN_BOTTOM:
150 		viewLoc.Set(frame.left, frame.bottom);
151 		break;
152 	case ALIGN_HCENTER:
153 		viewLoc.Set(frame.left, average(frame.top, frame.bottom));
154 		break;
155 	case ALIGN_VCENTER:
156 		viewLoc.Set(average(frame.left, frame.right), frame.top);
157 		printf("Aligning along vcenter\nInitial position: ");
158 		viewLoc.PrintToStream();
159 		break;
160 	}
161 
162 	// align items relative to head item
163 	for (i=1; i<len; i++) {
164 		BView* pView = reinterpret_cast<BView*>(viewList.ItemAt(i));
165 		if (pView) {
166 			switch (side) {
167 			case ALIGN_LEFT:
168 				viewLoc.y += alignLen;
169 				MoveViewCorner(*pView, viewLoc, CORNER_TOPLEFT);
170 				break;
171 			case ALIGN_TOP:
172 				viewLoc.x += alignLen;
173 				MoveViewCorner(*pView, viewLoc, CORNER_TOPLEFT);
174 				break;
175 			case ALIGN_RIGHT:
176 				viewLoc.y += alignLen;
177 				MoveViewCorner(*pView, viewLoc, CORNER_TOPRIGHT);
178 				break;
179 			case ALIGN_BOTTOM:
180 				viewLoc.x += alignLen;
181 				MoveViewCorner(*pView, viewLoc, CORNER_BOTTOMLEFT);
182 				break;
183 			case ALIGN_HCENTER:
184 				{
185 					viewLoc.x += alignLen;
186 					BPoint moveLoc = viewLoc;
187 					BRect r = pView->Frame();
188 					moveLoc.y -= (r.bottom - r.top) / 2;
189 					MoveViewCorner(*pView, moveLoc, CORNER_TOPLEFT);
190 					break;
191 				}
192 			case ALIGN_VCENTER:
193 				{
194 					viewLoc.y += alignLen;
195 					BPoint moveLoc = viewLoc;
196 					BRect r = pView->Frame();
197 					moveLoc.x -= (r.right - r.left) / 2;
198 					MoveViewCorner(*pView, moveLoc, CORNER_TOPLEFT);
199 					break;
200 				}
201 			}
202 		}
203 	}
204 }
205 
ResizeToListMax(BList & viewList,rect_dim resizeDim,corner anchor)206 void ViewLayoutFactory::ResizeToListMax(BList& viewList, rect_dim resizeDim,
207 	corner anchor)
208 {
209 	int32 i, len = viewList.CountItems();
210 	float maxWidth = 0.0f, maxHeight = 0.0f;
211 	float curWidth = 0.0f, curHeight = 0.0f;
212 
213 	// find maximum dimensions
214 	for (i=0; i<len; i++) {
215 		BView* pView = reinterpret_cast<BView*>(viewList.ItemAt(i));
216 		if (pView) {
217 			BRect frame = pView->Frame();
218 			curWidth = frame.Width();
219 			curHeight = frame.Height();
220 			if (curWidth > maxWidth) {
221 				maxWidth = curWidth;
222 			}
223 			if (curHeight > maxHeight) {
224 				maxHeight = curHeight;
225 			}
226 		}
227 	}
228 
229 	// now resize everything in the list based on selected dimension
230 	for (i=0; i<len; i++) {
231 		BView* pView = reinterpret_cast<BView*>(viewList.ItemAt(i));
232 		if (pView) {
233 			float newWidth, newHeight;
234 			BRect frame = pView->Frame();
235 			newWidth = (resizeDim & RECT_WIDTH)
236 				? maxWidth : frame.Width();
237 			newHeight = (resizeDim & RECT_HEIGHT)
238 				? maxHeight : frame.Height();
239 			pView->ResizeTo(newWidth, newHeight);
240 		}
241 	}
242 }
243 
ResizeAroundChildren(BView & view,BPoint margin)244 void ViewLayoutFactory::ResizeAroundChildren(BView& view, BPoint margin)
245 {
246 	float fMax_x = 0.0f, fMax_y = 0.0f;
247 	int32 numChild = view.CountChildren();
248 	for (int32 i = 0; i < numChild; i++)
249 	{
250 		BView* childView = view.ChildAt(i);
251 		if (childView) {
252 			BRect r = childView->Frame();
253 			fMax_x = std::max(fMax_x, r.right);
254 			fMax_y = std::max(fMax_y, r.bottom);
255 		}
256 	}
257 
258 	fMax_x += margin.x;
259 	fMax_y += margin.y;
260 	view.ResizeTo(fMax_x, fMax_y);
261 }
262