xref: /haiku/headers/os/interface/LayoutBuilder.h (revision a085e81e62d7a860f809b4fb7c7bf5654c396985)
1 /*
2  * Copyright 2009-2012, Haiku, Inc. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  */
5 #ifndef	_LAYOUT_BUILDER_H
6 #define	_LAYOUT_BUILDER_H
7 
8 
9 #include <new>
10 
11 #include <GridLayout.h>
12 #include <GridView.h>
13 #include <GroupLayout.h>
14 #include <GroupView.h>
15 #include <Menu.h>
16 #include <MenuField.h>
17 #include <MenuItem.h>
18 #include <SpaceLayoutItem.h>
19 #include <SplitView.h>
20 #include <TextControl.h>
21 #include <Window.h>
22 
23 
24 namespace BLayoutBuilder {
25 
26 template<typename ParentBuilder> class Base;
27 template<typename ParentBuilder = void*> class Group;
28 template<typename ParentBuilder = void*> class Grid;
29 template<typename ParentBuilder = void*> class Split;
30 template<typename ParentBuilder = void*> class Menu;
31 template<typename ParentBuilder = void*> class MenuItem;
32 
33 
34 template<typename ParentBuilder>
35 class Base {
36 protected:
37 	inline						Base();
38 
39 public:
40 	inline	void				SetParent(ParentBuilder* parent);
41 		// conceptually private
42 	inline	ParentBuilder&		End();
43 
44 protected:
45 			ParentBuilder*		fParent;
46 };
47 
48 
49 template<typename ParentBuilder>
50 class Group : public Base<ParentBuilder> {
51 public:
52 	typedef Group<ParentBuilder>	ThisBuilder;
53 	typedef Group<ThisBuilder>		GroupBuilder;
54 	typedef Grid<ThisBuilder>		GridBuilder;
55 	typedef Split<ThisBuilder>		SplitBuilder;
56 
57 public:
58 	inline						Group(enum orientation orientation
59 										= B_HORIZONTAL,
60 									float spacing = B_USE_DEFAULT_SPACING);
61 	inline						Group(BWindow* window,
62 									enum orientation orientation = B_HORIZONTAL,
63 									float spacing = B_USE_DEFAULT_SPACING);
64 	inline						Group(BView* view,
65 									enum orientation orientation = B_HORIZONTAL,
66 									float spacing = B_USE_DEFAULT_SPACING);
67 	inline						Group(BGroupLayout* layout);
68 	inline						Group(BGroupView* view);
69 
70 	inline	BGroupLayout*		Layout() const;
71 	inline	BView*				View() const;
72 	inline	ThisBuilder&		GetLayout(BGroupLayout** _layout);
73 	inline	ThisBuilder&		GetView(BView** _view);
74 
75 	inline	ThisBuilder&		Add(BView* view);
76 	inline	ThisBuilder&		Add(BView* view, float weight);
77 	inline	ThisBuilder&		Add(BLayoutItem* item);
78 	inline	ThisBuilder&		Add(BLayoutItem* item, float weight);
79 
80 	inline	GroupBuilder		AddGroup(enum orientation orientation,
81 									float spacing = B_USE_DEFAULT_SPACING,
82 									float weight = 1.0f);
83 	inline	GroupBuilder		AddGroup(BGroupView* groupView,
84 									float weight = 1.0f);
85 	inline	GroupBuilder		AddGroup(BGroupLayout* groupLayout,
86 									float weight = 1.0f);
87 
88 	inline	GridBuilder			AddGrid(float horizontal
89 										= B_USE_DEFAULT_SPACING,
90 									float vertical = B_USE_DEFAULT_SPACING,
91 									float weight = 1.0f);
92 	inline	GridBuilder			AddGrid(BGridLayout* gridLayout,
93 									float weight = 1.0f);
94 	inline	GridBuilder			AddGrid(BGridView* gridView,
95 									float weight = 1.0f);
96 
97 	inline	SplitBuilder		AddSplit(enum orientation orientation,
98 									float spacing = B_USE_DEFAULT_SPACING,
99 									float weight = 1.0f);
100 	inline	SplitBuilder		AddSplit(BSplitView* splitView,
101 									float weight = 1.0f);
102 
103 	inline	ThisBuilder&		AddGlue(float weight = 1.0f);
104 	inline	ThisBuilder&		AddStrut(float size);
105 
106 	inline	ThisBuilder&		SetInsets(float left, float top, float right,
107 									float bottom);
108 	inline	ThisBuilder&		SetInsets(float horizontal, float vertical);
109 	inline	ThisBuilder&		SetInsets(float insets);
110 
111 	inline	ThisBuilder&		SetExplicitMinSize(BSize size);
112 	inline	ThisBuilder&		SetExplicitMaxSize(BSize size);
113 	inline	ThisBuilder&		SetExplicitPreferredSize(BSize size);
114 	inline	ThisBuilder&		SetExplicitAlignment(BAlignment alignment);
115 
116 	inline						operator BGroupLayout*();
117 
118 private:
119 			BGroupLayout*		fLayout;
120 };
121 
122 
123 template<typename ParentBuilder>
124 class Grid : public Base<ParentBuilder> {
125 public:
126 	typedef Grid<ParentBuilder>		ThisBuilder;
127 	typedef Group<ThisBuilder>		GroupBuilder;
128 	typedef Grid<ThisBuilder>		GridBuilder;
129 	typedef Split<ThisBuilder>		SplitBuilder;
130 
131 public:
132 	inline						Grid(float horizontal
133 										= B_USE_DEFAULT_SPACING,
134 									float vertical = B_USE_DEFAULT_SPACING);
135 	inline						Grid(BWindow* window,
136 									float horizontal = B_USE_DEFAULT_SPACING,
137 									float vertical = B_USE_DEFAULT_SPACING);
138 	inline						Grid(BView* view,
139 									float horizontal = B_USE_DEFAULT_SPACING,
140 									float vertical = B_USE_DEFAULT_SPACING);
141 	inline						Grid(BGridLayout* layout);
142 	inline						Grid(BGridView* view);
143 
144 	inline	BGridLayout*		Layout() const;
145 	inline	BView*				View() const;
146 	inline	ThisBuilder&		GetLayout(BGridLayout** _layout);
147 	inline	ThisBuilder&		GetView(BView** _view);
148 
149 	inline	ThisBuilder&		Add(BView* view, int32 column, int32 row,
150 									int32 columnCount = 1, int32 rowCount = 1);
151 	inline	ThisBuilder&		Add(BLayoutItem* item, int32 column, int32 row,
152 									int32 columnCount = 1, int32 rowCount = 1);
153 	inline	ThisBuilder&		AddMenuField(BMenuField* menuField,
154 									int32 column, int32 row,
155 									alignment labelAlignment
156 										= B_ALIGN_HORIZONTAL_UNSET,
157 									int32 labelColumnCount = 1,
158 									int32 fieldColumnCount = 1,
159 									int32 rowCount = 1);
160 	inline	ThisBuilder&		AddTextControl(BTextControl* textControl,
161 									int32 column, int32 row,
162 									alignment labelAlignment
163 										= B_ALIGN_HORIZONTAL_UNSET,
164 									int32 labelColumnCount = 1,
165 									int32 textColumnCount = 1,
166 									int32 rowCount = 1);
167 
168 	inline	GroupBuilder		AddGroup(enum orientation orientation,
169 									float spacing, int32 column, int32 row,
170 									int32 columnCount = 1, int32 rowCount = 1);
171 	inline	GroupBuilder		AddGroup(BGroupView* groupView,	int32 column,
172 									int32 row, int32 columnCount = 1,
173 									int32 rowCount = 1);
174 	inline	GroupBuilder		AddGroup(BGroupLayout* groupLayout,
175 									int32 column, int32 row,
176 									int32 columnCount = 1, int32 rowCount = 1);
177 
178 	inline	GridBuilder			AddGrid(float horizontalSpacing,
179 									float verticalSpacing, int32 column,
180 									int32 row, int32 columnCount = 1,
181 									int32 rowCount = 1);
182 	inline	GridBuilder			AddGrid(BGridLayout* gridLayout,
183 									int32 column, int32 row,
184 									int32 columnCount = 1, int32 rowCount = 1);
185 	inline	GridBuilder			AddGrid(BGridView* gridView,
186 									int32 column, int32 row,
187 									int32 columnCount = 1, int32 rowCount = 1);
188 
189 	inline	SplitBuilder		AddSplit(enum orientation orientation,
190 									float spacing, int32 column, int32 row,
191 									int32 columnCount = 1, int32 rowCount = 1);
192 	inline	SplitBuilder		AddSplit(BSplitView* splitView, int32 column,
193 									int32 row, int32 columnCount = 1,
194 									int32 rowCount = 1);
195 
196 	inline	ThisBuilder&		AddGlue(int32 column, int32 row,
197 									int32 columnCount = 1, int32 rowCount = 1);
198 
199 	inline	ThisBuilder&		SetColumnWeight(int32 column, float weight);
200 	inline	ThisBuilder&		SetRowWeight(int32 row, float weight);
201 
202 	inline	ThisBuilder&		SetInsets(float left, float top, float right,
203 									float bottom);
204 	inline	ThisBuilder&		SetInsets(float horizontal, float vertical);
205 	inline	ThisBuilder&		SetInsets(float insets);
206 
207 	inline	ThisBuilder&		SetExplicitMinSize(BSize size);
208 	inline	ThisBuilder&		SetExplicitMaxSize(BSize size);
209 	inline	ThisBuilder&		SetExplicitPreferredSize(BSize size);
210 	inline	ThisBuilder&		SetExplicitAlignment(BAlignment alignment);
211 
212 	inline						operator BGridLayout*();
213 
214 private:
215 			BGridLayout*		fLayout;
216 };
217 
218 
219 template<typename ParentBuilder>
220 class Split : public Base<ParentBuilder> {
221 public:
222 	typedef Split<ParentBuilder>	ThisBuilder;
223 	typedef Group<ThisBuilder>		GroupBuilder;
224 	typedef Grid<ThisBuilder>		GridBuilder;
225 	typedef Split<ThisBuilder>		SplitBuilder;
226 
227 public:
228 	inline						Split(enum orientation orientation
229 										= B_HORIZONTAL,
230 									float spacing = B_USE_DEFAULT_SPACING);
231 	inline						Split(BSplitView* view);
232 
233 	inline	BSplitView*			View() const;
234 	inline	ThisBuilder&		GetView(BView** _view);
235 	inline	ThisBuilder&		GetSplitView(BSplitView** _view);
236 
237 	inline	ThisBuilder&		Add(BView* view);
238 	inline	ThisBuilder&		Add(BView* view, float weight);
239 	inline	ThisBuilder&		Add(BLayoutItem* item);
240 	inline	ThisBuilder&		Add(BLayoutItem* item, float weight);
241 
242 	inline	GroupBuilder		AddGroup(enum orientation orientation,
243 									float spacing = B_USE_DEFAULT_SPACING,
244 									float weight = 1.0f);
245 	inline	GroupBuilder		AddGroup(BGroupView* groupView,
246 									float weight = 1.0f);
247 	inline	GroupBuilder		AddGroup(BGroupLayout* groupLayout,
248 									float weight = 1.0f);
249 
250 	inline	GridBuilder			AddGrid(float horizontal
251 											= B_USE_DEFAULT_SPACING,
252 									float vertical = B_USE_DEFAULT_SPACING,
253 									float weight = 1.0f);
254 	inline	GridBuilder			AddGrid(BGridView* gridView,
255 									float weight = 1.0f);
256 	inline	GridBuilder			AddGrid(BGridLayout* gridLayout,
257 									float weight = 1.0f);
258 
259 	inline	SplitBuilder		AddSplit(enum orientation orientation,
260 									float spacing = B_USE_DEFAULT_SPACING,
261 									float weight = 1.0f);
262 	inline	SplitBuilder		AddSplit(BSplitView* splitView,
263 									float weight = 1.0f);
264 
265 	inline	ThisBuilder&		SetCollapsible(bool collapsible);
266 	inline	ThisBuilder&		SetCollapsible(int32 index, bool collapsible);
267 	inline	ThisBuilder&		SetCollapsible(int32 first, int32 last,
268 									bool collapsible);
269 
270 	inline	ThisBuilder&		SetInsets(float left, float top, float right,
271 									float bottom);
272 	inline	ThisBuilder&		SetInsets(float horizontal, float vertical);
273 	inline	ThisBuilder&		SetInsets(float insets);
274 
275 	inline						operator BSplitView*();
276 
277 private:
278 			BSplitView*			fView;
279 };
280 
281 
282 template<typename ParentBuilder>
283 class Menu : public Base<ParentBuilder> {
284 public:
285 	typedef Menu<ParentBuilder>		ThisBuilder;
286 	typedef MenuItem<ParentBuilder>	ItemBuilder;
287 	typedef Menu<ThisBuilder>		MenuBuilder;
288 
289 public:
290 	inline						Menu(BMenu* menu);
291 
292 	inline	ThisBuilder&		GetMenu(BMenu*& _menu);
293 
294 	inline	ItemBuilder			AddItem(BMenuItem* item);
295 	inline	ItemBuilder			AddItem(BMenu* menu);
296 	inline	ItemBuilder			AddItem(const char* label, BMessage* message,
297 									char shortcut = 0, uint32 modifiers = 0);
298 	inline	ItemBuilder			AddItem(const char* label, uint32 messageWhat,
299 									char shortcut = 0, uint32 modifiers = 0);
300 
301 	inline	MenuBuilder			AddMenu(BMenu* menu);
302 	inline	MenuBuilder			AddMenu(const char* title,
303 									menu_layout layout = B_ITEMS_IN_COLUMN);
304 
305 	inline	ThisBuilder&		AddSeparator();
306 
307 private:
308 			BMenu*				fMenu;
309 };
310 
311 
312 template<typename ParentBuilder>
313 class MenuItem : public Menu<ParentBuilder> {
314 public:
315 	typedef MenuItem<ParentBuilder>	ThisBuilder;
316 
317 public:
318 	inline						MenuItem(ParentBuilder* parentBuilder,
319 									BMenu* menu, BMenuItem* item);
320 
321 	inline	ThisBuilder&		GetItem(BMenuItem*& _item);
322 
323 	inline	ThisBuilder&		SetEnabled(bool enabled);
324 
325 private:
326 			BMenuItem*			fMenuItem;
327 };
328 
329 
330 // #pragma mark - Base
331 
332 
333 template<typename ParentBuilder>
334 Base<ParentBuilder>::Base()
335 	:
336 	fParent(NULL)
337 {
338 }
339 
340 
341 template<typename ParentBuilder>
342 void
343 Base<ParentBuilder>::SetParent(ParentBuilder* parent)
344 {
345 	fParent = parent;
346 }
347 
348 
349 template<typename ParentBuilder>
350 ParentBuilder&
351 Base<ParentBuilder>::End()
352 {
353 	return *fParent;
354 }
355 
356 
357 // #pragma mark - Group
358 
359 
360 template<typename ParentBuilder>
361 Group<ParentBuilder>::Group(enum orientation orientation, float spacing)
362 	:
363 	fLayout((new BGroupView(orientation, spacing))->GroupLayout())
364 {
365 }
366 
367 
368 template<typename ParentBuilder>
369 Group<ParentBuilder>::Group(BWindow* window, enum orientation orientation,
370 	float spacing)
371 	:
372 	fLayout(new BGroupLayout(orientation, spacing))
373 {
374 	window->SetLayout(fLayout);
375 
376 	fLayout->Owner()->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
377 		// TODO: we get a white background if we don't do this
378 }
379 
380 
381 template<typename ParentBuilder>
382 Group<ParentBuilder>::Group(BView* view, enum orientation orientation,
383 	float spacing)
384 	:
385 	fLayout(new BGroupLayout(orientation, spacing))
386 {
387 	view->SetLayout(fLayout);
388 	view->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
389 		// TODO: we get a white background if we don't do this
390 }
391 
392 
393 template<typename ParentBuilder>
394 Group<ParentBuilder>::Group(BGroupLayout* layout)
395 	:
396 	fLayout(layout)
397 {
398 }
399 
400 
401 template<typename ParentBuilder>
402 Group<ParentBuilder>::Group(BGroupView* view)
403 	:
404 	fLayout(view->GroupLayout())
405 {
406 }
407 
408 
409 template<typename ParentBuilder>
410 BGroupLayout*
411 Group<ParentBuilder>::Layout() const
412 {
413 	return fLayout;
414 }
415 
416 
417 template<typename ParentBuilder>
418 BView*
419 Group<ParentBuilder>::View() const
420 {
421 	return fLayout->Owner();
422 }
423 
424 
425 template<typename ParentBuilder>
426 typename Group<ParentBuilder>::ThisBuilder&
427 Group<ParentBuilder>::GetLayout(BGroupLayout** _layout)
428 {
429 	*_layout = fLayout;
430 	return *this;
431 }
432 
433 
434 template<typename ParentBuilder>
435 typename Group<ParentBuilder>::ThisBuilder&
436 Group<ParentBuilder>::GetView(BView** _view)
437 {
438 	*_view = fLayout->Owner();
439 	return *this;
440 }
441 
442 
443 template<typename ParentBuilder>
444 typename Group<ParentBuilder>::ThisBuilder&
445 Group<ParentBuilder>::Add(BView* view)
446 {
447 	fLayout->AddView(view);
448 	return *this;
449 }
450 
451 
452 template<typename ParentBuilder>
453 typename Group<ParentBuilder>::ThisBuilder&
454 Group<ParentBuilder>::Add(BView* view, float weight)
455 {
456 	fLayout->AddView(view, weight);
457 	return *this;
458 }
459 
460 
461 template<typename ParentBuilder>
462 typename Group<ParentBuilder>::ThisBuilder&
463 Group<ParentBuilder>::Add(BLayoutItem* item)
464 {
465 	fLayout->AddItem(item);
466 	return *this;
467 }
468 
469 
470 template<typename ParentBuilder>
471 typename Group<ParentBuilder>::ThisBuilder&
472 Group<ParentBuilder>::Add(BLayoutItem* item, float weight)
473 {
474 	fLayout->AddItem(item, weight);
475 	return *this;
476 }
477 
478 
479 template<typename ParentBuilder>
480 typename Group<ParentBuilder>::GroupBuilder
481 Group<ParentBuilder>::AddGroup(enum orientation orientation, float spacing,
482 	float weight)
483 {
484 	GroupBuilder builder(new BGroupLayout(orientation, spacing));
485 	builder.SetParent(this);
486 	fLayout->AddItem(builder.Layout(), weight);
487 	return builder;
488 }
489 
490 
491 template<typename ParentBuilder>
492 typename Group<ParentBuilder>::GroupBuilder
493 Group<ParentBuilder>::AddGroup(BGroupView* groupView, float weight)
494 {
495 	GroupBuilder builder(groupView);
496 	builder.SetParent(this);
497 	fLayout->AddItem(builder.Layout(), weight);
498 	return builder;
499 }
500 
501 
502 template<typename ParentBuilder>
503 typename Group<ParentBuilder>::GroupBuilder
504 Group<ParentBuilder>::AddGroup(BGroupLayout* groupLayout, float weight)
505 {
506 	GroupBuilder builder(groupLayout);
507 	builder.SetParent(this);
508 	fLayout->AddItem(builder.Layout(), weight);
509 	return builder;
510 }
511 
512 
513 template<typename ParentBuilder>
514 typename Group<ParentBuilder>::GridBuilder
515 Group<ParentBuilder>::AddGrid(float horizontalSpacing,
516 	float verticalSpacing, float weight)
517 {
518 	GridBuilder builder(new BGridLayout(horizontalSpacing, verticalSpacing));
519 	builder.SetParent(this);
520 	fLayout->AddItem(builder.Layout(), weight);
521 	return builder;
522 }
523 
524 
525 template<typename ParentBuilder>
526 typename Group<ParentBuilder>::GridBuilder
527 Group<ParentBuilder>::AddGrid(BGridLayout* gridLayout, float weight)
528 {
529 	GridBuilder builder(gridLayout);
530 	builder.SetParent(this);
531 	fLayout->AddItem(builder.Layout(), weight);
532 	return builder;
533 }
534 
535 
536 template<typename ParentBuilder>
537 typename Group<ParentBuilder>::GridBuilder
538 Group<ParentBuilder>::AddGrid(BGridView* gridView, float weight)
539 {
540 	GridBuilder builder(gridView);
541 	builder.SetParent(this);
542 	fLayout->AddItem(builder.Layout(), weight);
543 	return builder;
544 }
545 
546 
547 template<typename ParentBuilder>
548 typename Group<ParentBuilder>::SplitBuilder
549 Group<ParentBuilder>::AddSplit(enum orientation orientation, float spacing,
550 	float weight)
551 {
552 	SplitBuilder builder(orientation, spacing);
553 	builder.SetParent(this);
554 	fLayout->AddView(builder.View(), weight);
555 	return builder;
556 }
557 
558 
559 template<typename ParentBuilder>
560 typename Group<ParentBuilder>::SplitBuilder
561 Group<ParentBuilder>::AddSplit(BSplitView* splitView, float weight)
562 {
563 	SplitBuilder builder(splitView);
564 	builder.SetParent(this);
565 	fLayout->AddView(builder.View(), weight);
566 	return builder;
567 }
568 
569 
570 template<typename ParentBuilder>
571 typename Group<ParentBuilder>::ThisBuilder&
572 Group<ParentBuilder>::AddGlue(float weight)
573 {
574 	fLayout->AddItem(BSpaceLayoutItem::CreateGlue(), weight);
575 	return *this;
576 }
577 
578 
579 template<typename ParentBuilder>
580 typename Group<ParentBuilder>::ThisBuilder&
581 Group<ParentBuilder>::AddStrut(float size)
582 {
583 	if (fLayout->Orientation() == B_HORIZONTAL)
584 		fLayout->AddItem(BSpaceLayoutItem::CreateHorizontalStrut(size));
585 	else
586 		fLayout->AddItem(BSpaceLayoutItem::CreateVerticalStrut(size));
587 
588 	return *this;
589 }
590 
591 
592 template<typename ParentBuilder>
593 typename Group<ParentBuilder>::ThisBuilder&
594 Group<ParentBuilder>::SetInsets(float left, float top, float right,
595 	float bottom)
596 {
597 	fLayout->SetInsets(left, top, right, bottom);
598 	return *this;
599 }
600 
601 
602 template<typename ParentBuilder>
603 typename Group<ParentBuilder>::ThisBuilder&
604 Group<ParentBuilder>::SetInsets(float horizontal, float vertical)
605 {
606 	fLayout->SetInsets(horizontal, vertical);
607 	return *this;
608 }
609 
610 
611 template<typename ParentBuilder>
612 typename Group<ParentBuilder>::ThisBuilder&
613 Group<ParentBuilder>::SetInsets(float insets)
614 {
615 	fLayout->SetInsets(insets);
616 	return *this;
617 }
618 
619 
620 template<typename ParentBuilder>
621 typename Group<ParentBuilder>::ThisBuilder&
622 Group<ParentBuilder>::SetExplicitMinSize(BSize size)
623 {
624 	fLayout->SetExplicitMinSize(size);
625 	return *this;
626 }
627 
628 
629 template<typename ParentBuilder>
630 typename Group<ParentBuilder>::ThisBuilder&
631 Group<ParentBuilder>::SetExplicitMaxSize(BSize size)
632 {
633 	fLayout->SetExplicitMaxSize(size);
634 	return *this;
635 }
636 
637 
638 template<typename ParentBuilder>
639 typename Group<ParentBuilder>::ThisBuilder&
640 Group<ParentBuilder>::SetExplicitPreferredSize(BSize size)
641 {
642 	fLayout->SetExplicitPreferredSize(size);
643 	return *this;
644 }
645 
646 
647 template<typename ParentBuilder>
648 typename Group<ParentBuilder>::ThisBuilder&
649 Group<ParentBuilder>::SetExplicitAlignment(BAlignment alignment)
650 {
651 	fLayout->SetExplicitAlignment(alignment);
652 	return *this;
653 }
654 
655 
656 template<typename ParentBuilder>
657 Group<ParentBuilder>::operator BGroupLayout*()
658 {
659 	return fLayout;
660 }
661 
662 
663 // #pragma mark - Grid
664 
665 
666 template<typename ParentBuilder>
667 Grid<ParentBuilder>::Grid(float horizontalSpacing, float verticalSpacing)
668 	:
669 	fLayout((new BGridView(horizontalSpacing, verticalSpacing))->GridLayout())
670 {
671 }
672 
673 
674 template<typename ParentBuilder>
675 Grid<ParentBuilder>::Grid(BWindow* window, float horizontalSpacing,
676 	float verticalSpacing)
677 	:
678 	fLayout(new BGridLayout(horizontalSpacing, verticalSpacing))
679 {
680 	window->SetLayout(fLayout);
681 
682 	fLayout->Owner()->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
683 		// TODO: we get a white background if we don't do this
684 }
685 
686 
687 template<typename ParentBuilder>
688 Grid<ParentBuilder>::Grid(BView* view, float horizontalSpacing,
689 	float verticalSpacing)
690 	:
691 	fLayout(new BGridLayout(horizontalSpacing, verticalSpacing))
692 {
693 	view->SetLayout(fLayout);
694 	view->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
695 		// TODO: we get a white background if we don't do this
696 }
697 
698 
699 template<typename ParentBuilder>
700 Grid<ParentBuilder>::Grid(BGridLayout* layout)
701 	:
702 	fLayout(layout)
703 {
704 }
705 
706 
707 template<typename ParentBuilder>
708 Grid<ParentBuilder>::Grid(BGridView* view)
709 	:
710 	fLayout(view->GridLayout())
711 {
712 }
713 
714 
715 template<typename ParentBuilder>
716 BGridLayout*
717 Grid<ParentBuilder>::Layout() const
718 {
719 	return fLayout;
720 }
721 
722 
723 template<typename ParentBuilder>
724 BView*
725 Grid<ParentBuilder>::View() const
726 {
727 	return fLayout->Owner();
728 }
729 
730 
731 template<typename ParentBuilder>
732 typename Grid<ParentBuilder>::ThisBuilder&
733 Grid<ParentBuilder>::GetLayout(BGridLayout** _layout)
734 {
735 	*_layout = fLayout;
736 	return *this;
737 }
738 
739 
740 template<typename ParentBuilder>
741 typename Grid<ParentBuilder>::ThisBuilder&
742 Grid<ParentBuilder>::GetView(BView** _view)
743 {
744 	*_view = fLayout->Owner();
745 	return *this;
746 }
747 
748 
749 template<typename ParentBuilder>
750 typename Grid<ParentBuilder>::ThisBuilder&
751 Grid<ParentBuilder>::Add(BView* view, int32 column, int32 row,
752 	int32 columnCount, int32 rowCount)
753 {
754 	fLayout->AddView(view, column, row, columnCount, rowCount);
755 	return *this;
756 }
757 
758 
759 template<typename ParentBuilder>
760 typename Grid<ParentBuilder>::ThisBuilder&
761 Grid<ParentBuilder>::Add(BLayoutItem* item, int32 column, int32 row,
762 	int32 columnCount, int32 rowCount)
763 {
764 	fLayout->AddItem(item, column, row, columnCount, rowCount);
765 	return *this;
766 }
767 
768 
769 template<typename ParentBuilder>
770 typename Grid<ParentBuilder>::ThisBuilder&
771 Grid<ParentBuilder>::AddMenuField(BMenuField* menuField, int32 column,
772 	int32 row, alignment labelAlignment, int32 labelColumnCount,
773 	int32 fieldColumnCount, int32 rowCount)
774 {
775 	BLayoutItem* item = menuField->CreateLabelLayoutItem();
776 	item->SetExplicitAlignment(
777 		BAlignment(labelAlignment, B_ALIGN_VERTICAL_UNSET));
778 	fLayout->AddItem(item, column, row, labelColumnCount, rowCount);
779 	fLayout->AddItem(menuField->CreateMenuBarLayoutItem(),
780 		column + labelColumnCount, row, fieldColumnCount, rowCount);
781 	return *this;
782 }
783 
784 
785 template<typename ParentBuilder>
786 typename Grid<ParentBuilder>::ThisBuilder&
787 Grid<ParentBuilder>::AddTextControl(BTextControl* textControl, int32 column,
788 	int32 row, alignment labelAlignment, int32 labelColumnCount,
789 	int32 textColumnCount, int32 rowCount)
790 {
791 	BLayoutItem* item = textControl->CreateLabelLayoutItem();
792 	item->SetExplicitAlignment(
793 		BAlignment(labelAlignment, B_ALIGN_VERTICAL_UNSET));
794 	fLayout->AddItem(item, column, row, labelColumnCount, rowCount);
795 	fLayout->AddItem(textControl->CreateTextViewLayoutItem(),
796 		column + labelColumnCount, row, textColumnCount, rowCount);
797 	return *this;
798 }
799 
800 
801 template<typename ParentBuilder>
802 typename Grid<ParentBuilder>::GroupBuilder
803 Grid<ParentBuilder>::AddGroup(enum orientation orientation, float spacing,
804 	int32 column, int32 row, int32 columnCount, int32 rowCount)
805 {
806 	GroupBuilder builder(new BGroupLayout(orientation, spacing));
807 	builder.SetParent(this);
808 	fLayout->AddItem(builder.Layout(), column, row, columnCount, rowCount);
809 	return builder;
810 }
811 
812 
813 template<typename ParentBuilder>
814 typename Grid<ParentBuilder>::GroupBuilder
815 Grid<ParentBuilder>::AddGroup(BGroupView* groupView, int32 column, int32 row,
816 	int32 columnCount, int32 rowCount)
817 {
818 	GroupBuilder builder(groupView);
819 	builder.SetParent(this);
820 	fLayout->AddItem(builder.Layout(), column, row, columnCount, rowCount);
821 	return builder;
822 }
823 
824 
825 template<typename ParentBuilder>
826 typename Grid<ParentBuilder>::GroupBuilder
827 Grid<ParentBuilder>::AddGroup(BGroupLayout* groupLayout, int32 column,
828 	int32 row, int32 columnCount, int32 rowCount)
829 {
830 	GroupBuilder builder(groupLayout);
831 	builder.SetParent(this);
832 	fLayout->AddItem(builder.Layout(), column, row, columnCount, rowCount);
833 	return builder;
834 }
835 
836 
837 template<typename ParentBuilder>
838 typename Grid<ParentBuilder>::GridBuilder
839 Grid<ParentBuilder>::AddGrid(float horizontalSpacing, float verticalSpacing,
840 	int32 column, int32 row, int32 columnCount, int32 rowCount)
841 {
842 	GridBuilder builder(new BGridLayout(horizontalSpacing, verticalSpacing));
843 	builder.SetParent(this);
844 	fLayout->AddItem(builder.Layout(), column, row, columnCount, rowCount);
845 	return builder;
846 }
847 
848 
849 template<typename ParentBuilder>
850 typename Grid<ParentBuilder>::GridBuilder
851 Grid<ParentBuilder>::AddGrid(BGridView* gridView, int32 column, int32 row,
852 	int32 columnCount, int32 rowCount)
853 {
854 	GridBuilder builder(gridView);
855 	builder.SetParent(this);
856 	fLayout->AddView(builder.View(), column, row, columnCount, rowCount);
857 	return builder;
858 }
859 
860 
861 template<typename ParentBuilder>
862 typename Grid<ParentBuilder>::SplitBuilder
863 Grid<ParentBuilder>::AddSplit(enum orientation orientation, float spacing,
864 	int32 column, int32 row, int32 columnCount, int32 rowCount)
865 {
866 	SplitBuilder builder(orientation, spacing);
867 	builder.SetParent(this);
868 	fLayout->AddView(builder.View(), column, row, columnCount, rowCount);
869 	return builder;
870 }
871 
872 
873 template<typename ParentBuilder>
874 typename Grid<ParentBuilder>::SplitBuilder
875 Grid<ParentBuilder>::AddSplit(BSplitView* splitView, int32 column, int32 row,
876 	int32 columnCount, int32 rowCount)
877 {
878 	SplitBuilder builder(splitView);
879 	builder.SetParent(this);
880 	fLayout->AddView(builder.View(), column, row, columnCount, rowCount);
881 	return builder;
882 }
883 
884 
885 template<typename ParentBuilder>
886 typename Grid<ParentBuilder>::ThisBuilder&
887 Grid<ParentBuilder>::AddGlue(int32 column, int32 row, int32 columnCount,
888 	int32 rowCount)
889 {
890 	fLayout->AddItem(BSpaceLayoutItem::CreateGlue(), column, row, columnCount,
891 		rowCount);
892 	return *this;
893 }
894 
895 
896 template<typename ParentBuilder>
897 typename Grid<ParentBuilder>::ThisBuilder&
898 Grid<ParentBuilder>::SetColumnWeight(int32 column, float weight)
899 {
900 	fLayout->SetColumnWeight(column, weight);
901 	return *this;
902 }
903 
904 
905 template<typename ParentBuilder>
906 typename Grid<ParentBuilder>::ThisBuilder&
907 Grid<ParentBuilder>::SetRowWeight(int32 row, float weight)
908 {
909 	fLayout->SetRowWeight(row, weight);
910 	return *this;
911 }
912 
913 
914 template<typename ParentBuilder>
915 typename Grid<ParentBuilder>::ThisBuilder&
916 Grid<ParentBuilder>::SetInsets(float left, float top, float right,
917 	float bottom)
918 {
919 	fLayout->SetInsets(left, top, right, bottom);
920 	return *this;
921 }
922 
923 
924 template<typename ParentBuilder>
925 typename Grid<ParentBuilder>::ThisBuilder&
926 Grid<ParentBuilder>::SetInsets(float horizontal, float vertical)
927 {
928 	fLayout->SetInsets(horizontal, vertical);
929 	return *this;
930 }
931 
932 
933 template<typename ParentBuilder>
934 typename Grid<ParentBuilder>::ThisBuilder&
935 Grid<ParentBuilder>::SetInsets(float insets)
936 {
937 	fLayout->SetInsets(insets);
938 	return *this;
939 }
940 
941 
942 template<typename ParentBuilder>
943 typename Grid<ParentBuilder>::ThisBuilder&
944 Grid<ParentBuilder>::SetExplicitMinSize(BSize size)
945 {
946 	fLayout->SetExplicitMinSize(size);
947 	return *this;
948 }
949 
950 
951 template<typename ParentBuilder>
952 typename Grid<ParentBuilder>::ThisBuilder&
953 Grid<ParentBuilder>::SetExplicitMaxSize(BSize size)
954 {
955 	fLayout->SetExplicitMaxSize(size);
956 	return *this;
957 }
958 
959 
960 template<typename ParentBuilder>
961 typename Grid<ParentBuilder>::ThisBuilder&
962 Grid<ParentBuilder>::SetExplicitPreferredSize(BSize size)
963 {
964 	fLayout->SetExplicitPreferredSize(size);
965 	return *this;
966 }
967 
968 
969 template<typename ParentBuilder>
970 typename Grid<ParentBuilder>::ThisBuilder&
971 Grid<ParentBuilder>::SetExplicitAlignment(BAlignment alignment)
972 {
973 	fLayout->SetExplicitAlignment(alignment);
974 	return *this;
975 }
976 
977 
978 template<typename ParentBuilder>
979 Grid<ParentBuilder>::operator BGridLayout*()
980 {
981 	return fLayout;
982 }
983 
984 
985 // #pragma mark - Split
986 
987 
988 template<typename ParentBuilder>
989 Split<ParentBuilder>::Split(enum orientation orientation, float spacing)
990 	:
991 	fView(new BSplitView(orientation, spacing))
992 {
993 }
994 
995 
996 template<typename ParentBuilder>
997 Split<ParentBuilder>::Split(BSplitView* view)
998 	:
999 	fView(view)
1000 {
1001 }
1002 
1003 
1004 template<typename ParentBuilder>
1005 BSplitView*
1006 Split<ParentBuilder>::View() const
1007 {
1008 	return fView;
1009 }
1010 
1011 
1012 template<typename ParentBuilder>
1013 typename Split<ParentBuilder>::ThisBuilder&
1014 Split<ParentBuilder>::GetView(BView** _view)
1015 {
1016 	*_view = fView;
1017 	return *this;
1018 }
1019 
1020 
1021 template<typename ParentBuilder>
1022 typename Split<ParentBuilder>::ThisBuilder&
1023 Split<ParentBuilder>::GetSplitView(BSplitView** _view)
1024 {
1025 	*_view = fView;
1026 	return *this;
1027 }
1028 
1029 
1030 template<typename ParentBuilder>
1031 typename Split<ParentBuilder>::ThisBuilder&
1032 Split<ParentBuilder>::Add(BView* view)
1033 {
1034 	fView->AddChild(view);
1035 	return *this;
1036 }
1037 
1038 
1039 template<typename ParentBuilder>
1040 typename Split<ParentBuilder>::ThisBuilder&
1041 Split<ParentBuilder>::Add(BView* view, float weight)
1042 {
1043 	fView->AddChild(view, weight);
1044 	return *this;
1045 }
1046 
1047 
1048 template<typename ParentBuilder>
1049 typename Split<ParentBuilder>::ThisBuilder&
1050 Split<ParentBuilder>::Add(BLayoutItem* item)
1051 {
1052 	fView->AddChild(item);
1053 	return *this;
1054 }
1055 
1056 
1057 template<typename ParentBuilder>
1058 typename Split<ParentBuilder>::ThisBuilder&
1059 Split<ParentBuilder>::Add(BLayoutItem* item, float weight)
1060 {
1061 	fView->AddChild(item, weight);
1062 	return *this;
1063 }
1064 
1065 
1066 template<typename ParentBuilder>
1067 typename Split<ParentBuilder>::GroupBuilder
1068 Split<ParentBuilder>::AddGroup(enum orientation orientation, float spacing,
1069 	float weight)
1070 {
1071 	GroupBuilder builder(new BGroupLayout(orientation, spacing));
1072 	builder.SetParent(this);
1073 	fView->AddChild(builder.Layout(), weight);
1074 	return builder;
1075 }
1076 
1077 
1078 template<typename ParentBuilder>
1079 typename Split<ParentBuilder>::GroupBuilder
1080 Split<ParentBuilder>::AddGroup(BGroupView* groupView, float weight)
1081 {
1082 	GroupBuilder builder(groupView);
1083 	builder.SetParent(this);
1084 	fView->AddChild(builder.Layout(), weight);
1085 	return builder;
1086 }
1087 
1088 
1089 template<typename ParentBuilder>
1090 typename Split<ParentBuilder>::GroupBuilder
1091 Split<ParentBuilder>::AddGroup(BGroupLayout* groupLayout, float weight)
1092 {
1093 	GroupBuilder builder(groupLayout);
1094 	builder.SetParent(this);
1095 	fView->AddChild(builder.Layout(), weight);
1096 	return builder;
1097 }
1098 
1099 
1100 template<typename ParentBuilder>
1101 typename Split<ParentBuilder>::GridBuilder
1102 Split<ParentBuilder>::AddGrid(float horizontalSpacing, float verticalSpacing,
1103 	float weight)
1104 {
1105 	GridBuilder builder(new BGridLayout(horizontalSpacing, verticalSpacing));
1106 	builder.SetParent(this);
1107 	fView->AddChild(builder.Layout(), weight);
1108 	return builder;
1109 }
1110 
1111 
1112 template<typename ParentBuilder>
1113 typename Split<ParentBuilder>::GridBuilder
1114 Split<ParentBuilder>::AddGrid(BGridView* gridView, float weight)
1115 {
1116 	GridBuilder builder(gridView);
1117 	builder.SetParent(this);
1118 	fView->AddChild(builder.Layout(), weight);
1119 	return builder;
1120 }
1121 
1122 
1123 template<typename ParentBuilder>
1124 typename Split<ParentBuilder>::GridBuilder
1125 Split<ParentBuilder>::AddGrid(BGridLayout* layout, float weight)
1126 {
1127 	GridBuilder builder(layout);
1128 	builder.SetParent(this);
1129 	fView->AddChild(builder.Layout(), weight);
1130 	return builder;
1131 }
1132 
1133 
1134 template<typename ParentBuilder>
1135 typename Split<ParentBuilder>::SplitBuilder
1136 Split<ParentBuilder>::AddSplit(enum orientation orientation, float spacing,
1137 	float weight)
1138 {
1139 	SplitBuilder builder(orientation, spacing);
1140 	builder.SetParent(this);
1141 	fView->AddChild(builder.View(), weight);
1142 	return builder;
1143 }
1144 
1145 
1146 template<typename ParentBuilder>
1147 typename Split<ParentBuilder>::ThisBuilder&
1148 Split<ParentBuilder>::SetCollapsible(bool collapsible)
1149 {
1150 	fView->SetCollapsible(collapsible);
1151 	return *this;
1152 }
1153 
1154 
1155 template<typename ParentBuilder>
1156 typename Split<ParentBuilder>::ThisBuilder&
1157 Split<ParentBuilder>::SetCollapsible(int32 index, bool collapsible)
1158 {
1159 	fView->SetCollapsible(index, collapsible);
1160 	return *this;
1161 }
1162 
1163 
1164 template<typename ParentBuilder>
1165 typename Split<ParentBuilder>::ThisBuilder&
1166 Split<ParentBuilder>::SetCollapsible(int32 first, int32 last, bool collapsible)
1167 {
1168 	fView->SetCollapsible(first, last, collapsible);
1169 	return *this;
1170 }
1171 
1172 
1173 template<typename ParentBuilder>
1174 typename Split<ParentBuilder>::ThisBuilder&
1175 Split<ParentBuilder>::SetInsets(float left, float top, float right,
1176 	float bottom)
1177 {
1178 	fView->SetInsets(left, top, right, bottom);
1179 	return *this;
1180 }
1181 
1182 
1183 template<typename ParentBuilder>
1184 typename Split<ParentBuilder>::ThisBuilder&
1185 Split<ParentBuilder>::SetInsets(float horizontal, float vertical)
1186 {
1187 	fView->SetInsets(horizontal, vertical);
1188 	return *this;
1189 }
1190 
1191 
1192 template<typename ParentBuilder>
1193 typename Split<ParentBuilder>::ThisBuilder&
1194 Split<ParentBuilder>::SetInsets(float insets)
1195 {
1196 	fView->SetInsets(insets);
1197 	return *this;
1198 }
1199 
1200 
1201 template<typename ParentBuilder>
1202 Split<ParentBuilder>::operator BSplitView*()
1203 {
1204 	return fView;
1205 }
1206 
1207 
1208 // #pragma mark - Menu
1209 
1210 
1211 template<typename ParentBuilder>
1212 Menu<ParentBuilder>::Menu(BMenu* menu)
1213 	:
1214 	fMenu(menu)
1215 {
1216 }
1217 
1218 
1219 template<typename ParentBuilder>
1220 typename Menu<ParentBuilder>::ThisBuilder&
1221 Menu<ParentBuilder>::GetMenu(BMenu*& _menu)
1222 {
1223 	_menu = fMenu;
1224 	return *this;
1225 }
1226 
1227 
1228 template<typename ParentBuilder>
1229 typename Menu<ParentBuilder>::ItemBuilder
1230 Menu<ParentBuilder>::AddItem(BMenuItem* item)
1231 {
1232 	fMenu->AddItem(item);
1233 	return MenuItem<ParentBuilder>(this->fParent, fMenu, item);
1234 }
1235 
1236 
1237 template<typename ParentBuilder>
1238 typename Menu<ParentBuilder>::ItemBuilder
1239 Menu<ParentBuilder>::AddItem(BMenu* menu)
1240 {
1241 	if (!fMenu->AddItem(menu))
1242 		throw std::bad_alloc();
1243 
1244 	return MenuItem<ParentBuilder>(this->fParent, fMenu,
1245 		fMenu->ItemAt(fMenu->CountItems() - 1));
1246 }
1247 
1248 
1249 template<typename ParentBuilder>
1250 typename Menu<ParentBuilder>::ItemBuilder
1251 Menu<ParentBuilder>::AddItem(const char* label, BMessage* message,
1252 	char shortcut, uint32 modifiers)
1253 {
1254 	BMenuItem* item = new BMenuItem(label, message, shortcut, modifiers);
1255 	if (!fMenu->AddItem(item))
1256 		delete item;
1257 
1258 	return MenuItem<ParentBuilder>(this->fParent, fMenu, item);
1259 }
1260 
1261 
1262 template<typename ParentBuilder>
1263 typename Menu<ParentBuilder>::ItemBuilder
1264 Menu<ParentBuilder>::AddItem(const char* label, uint32 messageWhat,
1265 	char shortcut, uint32 modifiers)
1266 {
1267 	BMessage* message = new BMessage(messageWhat);
1268 	BMenuItem* item;
1269 	try {
1270 		item = new BMenuItem(label, message, shortcut, modifiers);
1271 	} catch (...) {
1272 		delete message;
1273 		throw;
1274 	}
1275 
1276 	if (!fMenu->AddItem(item))
1277 		delete item;
1278 
1279 	return MenuItem<ParentBuilder>(this->fParent, fMenu, item);
1280 }
1281 
1282 
1283 template<typename ParentBuilder>
1284 typename Menu<ParentBuilder>::ThisBuilder&
1285 Menu<ParentBuilder>::AddSeparator()
1286 {
1287 	fMenu->AddSeparatorItem();
1288 	return *this;
1289 }
1290 
1291 
1292 template<typename ParentBuilder>
1293 typename Menu<ParentBuilder>::MenuBuilder
1294 Menu<ParentBuilder>::AddMenu(BMenu* menu)
1295 {
1296 	if (!fMenu->AddItem(menu))
1297 		throw std::bad_alloc();
1298 
1299 	MenuBuilder builder(menu);
1300 	builder.SetParent(this);
1301 	return builder;
1302 }
1303 
1304 
1305 template<typename ParentBuilder>
1306 typename Menu<ParentBuilder>::MenuBuilder
1307 Menu<ParentBuilder>::AddMenu(const char* title, menu_layout layout)
1308 {
1309 	BMenu* menu = new BMenu(title, layout);
1310 	if (!fMenu->AddItem(menu)) {
1311 		delete menu;
1312 		throw std::bad_alloc();
1313 	}
1314 
1315 	MenuBuilder builder(menu);
1316 	builder.SetParent(this);
1317 	return builder;
1318 }
1319 
1320 
1321 // #pragma mark - MenuItem
1322 
1323 
1324 template<typename ParentBuilder>
1325 MenuItem<ParentBuilder>::MenuItem(ParentBuilder* parentBuilder, BMenu* menu,
1326 	BMenuItem* item)
1327 	:
1328 	Menu<ParentBuilder>(menu),
1329 	fMenuItem(item)
1330 {
1331 	this->SetParent(parentBuilder);
1332 }
1333 
1334 
1335 template<typename ParentBuilder>
1336 typename MenuItem<ParentBuilder>::ThisBuilder&
1337 MenuItem<ParentBuilder>::GetItem(BMenuItem*& _item)
1338 {
1339 	_item = fMenuItem;
1340 	return *this;
1341 }
1342 
1343 
1344 template<typename ParentBuilder>
1345 typename MenuItem<ParentBuilder>::ThisBuilder&
1346 MenuItem<ParentBuilder>::SetEnabled(bool enabled)
1347 {
1348 	fMenuItem->SetEnabled(enabled);
1349 	return *this;
1350 }
1351 
1352 
1353 }	// namespace BLayoutBuilder
1354 
1355 
1356 #endif	// _LAYOUT_BUILDER_H
1357