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