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
24namespace BLayoutBuilder {
25
26template<typename ParentBuilder> class Base;
27template<typename ParentBuilder = void*> class Group;
28template<typename ParentBuilder = void*> class Grid;
29template<typename ParentBuilder = void*> class Split;
30template<typename ParentBuilder = void*> class Menu;
31template<typename ParentBuilder = void*> class MenuItem;
32
33
34template<typename ParentBuilder>
35class Base {
36protected:
37	inline						Base();
38
39public:
40	inline	void				SetParent(ParentBuilder* parent);
41		// conceptually private
42	inline	ParentBuilder&		End();
43
44protected:
45			ParentBuilder*		fParent;
46};
47
48
49template<typename ParentBuilder>
50class Group : public Base<ParentBuilder> {
51public:
52	typedef Group<ParentBuilder>	ThisBuilder;
53	typedef Group<ThisBuilder>		GroupBuilder;
54	typedef Grid<ThisBuilder>		GridBuilder;
55	typedef Split<ThisBuilder>		SplitBuilder;
56
57public:
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
118private:
119			BGroupLayout*		fLayout;
120};
121
122
123template<typename ParentBuilder>
124class Grid : public Base<ParentBuilder> {
125public:
126	typedef Grid<ParentBuilder>		ThisBuilder;
127	typedef Group<ThisBuilder>		GroupBuilder;
128	typedef Grid<ThisBuilder>		GridBuilder;
129	typedef Split<ThisBuilder>		SplitBuilder;
130
131public:
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
214private:
215			BGridLayout*		fLayout;
216};
217
218
219template<typename ParentBuilder>
220class Split : public Base<ParentBuilder> {
221public:
222	typedef Split<ParentBuilder>	ThisBuilder;
223	typedef Group<ThisBuilder>		GroupBuilder;
224	typedef Grid<ThisBuilder>		GridBuilder;
225	typedef Split<ThisBuilder>		SplitBuilder;
226
227public:
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
277private:
278			BSplitView*			fView;
279};
280
281
282template<typename ParentBuilder>
283class Menu : public Base<ParentBuilder> {
284public:
285	typedef Menu<ParentBuilder>		ThisBuilder;
286	typedef MenuItem<ParentBuilder>	ItemBuilder;
287	typedef Menu<ThisBuilder>		MenuBuilder;
288
289public:
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
307private:
308			BMenu*				fMenu;
309};
310
311
312template<typename ParentBuilder>
313class MenuItem : public Menu<ParentBuilder> {
314public:
315	typedef MenuItem<ParentBuilder>	ThisBuilder;
316
317public:
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
325private:
326			BMenuItem*			fMenuItem;
327};
328
329
330// #pragma mark - Base
331
332
333template<typename ParentBuilder>
334Base<ParentBuilder>::Base()
335	:
336	fParent(NULL)
337{
338}
339
340
341template<typename ParentBuilder>
342void
343Base<ParentBuilder>::SetParent(ParentBuilder* parent)
344{
345	fParent = parent;
346}
347
348
349template<typename ParentBuilder>
350ParentBuilder&
351Base<ParentBuilder>::End()
352{
353	return *fParent;
354}
355
356
357// #pragma mark - Group
358
359
360template<typename ParentBuilder>
361Group<ParentBuilder>::Group(enum orientation orientation, float spacing)
362	:
363	fLayout((new BGroupView(orientation, spacing))->GroupLayout())
364{
365}
366
367
368template<typename ParentBuilder>
369Group<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
381template<typename ParentBuilder>
382Group<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
393template<typename ParentBuilder>
394Group<ParentBuilder>::Group(BGroupLayout* layout)
395	:
396	fLayout(layout)
397{
398}
399
400
401template<typename ParentBuilder>
402Group<ParentBuilder>::Group(BGroupView* view)
403	:
404	fLayout(view->GroupLayout())
405{
406}
407
408
409template<typename ParentBuilder>
410BGroupLayout*
411Group<ParentBuilder>::Layout() const
412{
413	return fLayout;
414}
415
416
417template<typename ParentBuilder>
418BView*
419Group<ParentBuilder>::View() const
420{
421	return fLayout->Owner();
422}
423
424
425template<typename ParentBuilder>
426typename Group<ParentBuilder>::ThisBuilder&
427Group<ParentBuilder>::GetLayout(BGroupLayout** _layout)
428{
429	*_layout = fLayout;
430	return *this;
431}
432
433
434template<typename ParentBuilder>
435typename Group<ParentBuilder>::ThisBuilder&
436Group<ParentBuilder>::GetView(BView** _view)
437{
438	*_view = fLayout->Owner();
439	return *this;
440}
441
442
443template<typename ParentBuilder>
444typename Group<ParentBuilder>::ThisBuilder&
445Group<ParentBuilder>::Add(BView* view)
446{
447	fLayout->AddView(view);
448	return *this;
449}
450
451
452template<typename ParentBuilder>
453typename Group<ParentBuilder>::ThisBuilder&
454Group<ParentBuilder>::Add(BView* view, float weight)
455{
456	fLayout->AddView(view, weight);
457	return *this;
458}
459
460
461template<typename ParentBuilder>
462typename Group<ParentBuilder>::ThisBuilder&
463Group<ParentBuilder>::Add(BLayoutItem* item)
464{
465	fLayout->AddItem(item);
466	return *this;
467}
468
469
470template<typename ParentBuilder>
471typename Group<ParentBuilder>::ThisBuilder&
472Group<ParentBuilder>::Add(BLayoutItem* item, float weight)
473{
474	fLayout->AddItem(item, weight);
475	return *this;
476}
477
478
479template<typename ParentBuilder>
480typename Group<ParentBuilder>::GroupBuilder
481Group<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
491template<typename ParentBuilder>
492typename Group<ParentBuilder>::GroupBuilder
493Group<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
502template<typename ParentBuilder>
503typename Group<ParentBuilder>::GroupBuilder
504Group<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
513template<typename ParentBuilder>
514typename Group<ParentBuilder>::GridBuilder
515Group<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
525template<typename ParentBuilder>
526typename Group<ParentBuilder>::GridBuilder
527Group<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
536template<typename ParentBuilder>
537typename Group<ParentBuilder>::GridBuilder
538Group<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
547template<typename ParentBuilder>
548typename Group<ParentBuilder>::SplitBuilder
549Group<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
559template<typename ParentBuilder>
560typename Group<ParentBuilder>::SplitBuilder
561Group<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
570template<typename ParentBuilder>
571typename Group<ParentBuilder>::ThisBuilder&
572Group<ParentBuilder>::AddGlue(float weight)
573{
574	fLayout->AddItem(BSpaceLayoutItem::CreateGlue(), weight);
575	return *this;
576}
577
578
579template<typename ParentBuilder>
580typename Group<ParentBuilder>::ThisBuilder&
581Group<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
592template<typename ParentBuilder>
593typename Group<ParentBuilder>::ThisBuilder&
594Group<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
602template<typename ParentBuilder>
603typename Group<ParentBuilder>::ThisBuilder&
604Group<ParentBuilder>::SetInsets(float horizontal, float vertical)
605{
606	fLayout->SetInsets(horizontal, vertical);
607	return *this;
608}
609
610
611template<typename ParentBuilder>
612typename Group<ParentBuilder>::ThisBuilder&
613Group<ParentBuilder>::SetInsets(float insets)
614{
615	fLayout->SetInsets(insets);
616	return *this;
617}
618
619
620template<typename ParentBuilder>
621typename Group<ParentBuilder>::ThisBuilder&
622Group<ParentBuilder>::SetExplicitMinSize(BSize size)
623{
624	fLayout->SetExplicitMinSize(size);
625	return *this;
626}
627
628
629template<typename ParentBuilder>
630typename Group<ParentBuilder>::ThisBuilder&
631Group<ParentBuilder>::SetExplicitMaxSize(BSize size)
632{
633	fLayout->SetExplicitMaxSize(size);
634	return *this;
635}
636
637
638template<typename ParentBuilder>
639typename Group<ParentBuilder>::ThisBuilder&
640Group<ParentBuilder>::SetExplicitPreferredSize(BSize size)
641{
642	fLayout->SetExplicitPreferredSize(size);
643	return *this;
644}
645
646
647template<typename ParentBuilder>
648typename Group<ParentBuilder>::ThisBuilder&
649Group<ParentBuilder>::SetExplicitAlignment(BAlignment alignment)
650{
651	fLayout->SetExplicitAlignment(alignment);
652	return *this;
653}
654
655
656template<typename ParentBuilder>
657Group<ParentBuilder>::operator BGroupLayout*()
658{
659	return fLayout;
660}
661
662
663// #pragma mark - Grid
664
665
666template<typename ParentBuilder>
667Grid<ParentBuilder>::Grid(float horizontalSpacing, float verticalSpacing)
668	:
669	fLayout((new BGridView(horizontalSpacing, verticalSpacing))->GridLayout())
670{
671}
672
673
674template<typename ParentBuilder>
675Grid<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
687template<typename ParentBuilder>
688Grid<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
699template<typename ParentBuilder>
700Grid<ParentBuilder>::Grid(BGridLayout* layout)
701	:
702	fLayout(layout)
703{
704}
705
706
707template<typename ParentBuilder>
708Grid<ParentBuilder>::Grid(BGridView* view)
709	:
710	fLayout(view->GridLayout())
711{
712}
713
714
715template<typename ParentBuilder>
716BGridLayout*
717Grid<ParentBuilder>::Layout() const
718{
719	return fLayout;
720}
721
722
723template<typename ParentBuilder>
724BView*
725Grid<ParentBuilder>::View() const
726{
727	return fLayout->Owner();
728}
729
730
731template<typename ParentBuilder>
732typename Grid<ParentBuilder>::ThisBuilder&
733Grid<ParentBuilder>::GetLayout(BGridLayout** _layout)
734{
735	*_layout = fLayout;
736	return *this;
737}
738
739
740template<typename ParentBuilder>
741typename Grid<ParentBuilder>::ThisBuilder&
742Grid<ParentBuilder>::GetView(BView** _view)
743{
744	*_view = fLayout->Owner();
745	return *this;
746}
747
748
749template<typename ParentBuilder>
750typename Grid<ParentBuilder>::ThisBuilder&
751Grid<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
759template<typename ParentBuilder>
760typename Grid<ParentBuilder>::ThisBuilder&
761Grid<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
769template<typename ParentBuilder>
770typename Grid<ParentBuilder>::ThisBuilder&
771Grid<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
785template<typename ParentBuilder>
786typename Grid<ParentBuilder>::ThisBuilder&
787Grid<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
801template<typename ParentBuilder>
802typename Grid<ParentBuilder>::GroupBuilder
803Grid<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
813template<typename ParentBuilder>
814typename Grid<ParentBuilder>::GroupBuilder
815Grid<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
825template<typename ParentBuilder>
826typename Grid<ParentBuilder>::GroupBuilder
827Grid<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
837template<typename ParentBuilder>
838typename Grid<ParentBuilder>::GridBuilder
839Grid<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
849template<typename ParentBuilder>
850typename Grid<ParentBuilder>::GridBuilder
851Grid<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
861template<typename ParentBuilder>
862typename Grid<ParentBuilder>::SplitBuilder
863Grid<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
873template<typename ParentBuilder>
874typename Grid<ParentBuilder>::SplitBuilder
875Grid<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
885template<typename ParentBuilder>
886typename Grid<ParentBuilder>::ThisBuilder&
887Grid<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
896template<typename ParentBuilder>
897typename Grid<ParentBuilder>::ThisBuilder&
898Grid<ParentBuilder>::SetColumnWeight(int32 column, float weight)
899{
900	fLayout->SetColumnWeight(column, weight);
901	return *this;
902}
903
904
905template<typename ParentBuilder>
906typename Grid<ParentBuilder>::ThisBuilder&
907Grid<ParentBuilder>::SetRowWeight(int32 row, float weight)
908{
909	fLayout->SetRowWeight(row, weight);
910	return *this;
911}
912
913
914template<typename ParentBuilder>
915typename Grid<ParentBuilder>::ThisBuilder&
916Grid<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
924template<typename ParentBuilder>
925typename Grid<ParentBuilder>::ThisBuilder&
926Grid<ParentBuilder>::SetInsets(float horizontal, float vertical)
927{
928	fLayout->SetInsets(horizontal, vertical);
929	return *this;
930}
931
932
933template<typename ParentBuilder>
934typename Grid<ParentBuilder>::ThisBuilder&
935Grid<ParentBuilder>::SetInsets(float insets)
936{
937	fLayout->SetInsets(insets);
938	return *this;
939}
940
941
942template<typename ParentBuilder>
943typename Grid<ParentBuilder>::ThisBuilder&
944Grid<ParentBuilder>::SetExplicitMinSize(BSize size)
945{
946	fLayout->SetExplicitMinSize(size);
947	return *this;
948}
949
950
951template<typename ParentBuilder>
952typename Grid<ParentBuilder>::ThisBuilder&
953Grid<ParentBuilder>::SetExplicitMaxSize(BSize size)
954{
955	fLayout->SetExplicitMaxSize(size);
956	return *this;
957}
958
959
960template<typename ParentBuilder>
961typename Grid<ParentBuilder>::ThisBuilder&
962Grid<ParentBuilder>::SetExplicitPreferredSize(BSize size)
963{
964	fLayout->SetExplicitPreferredSize(size);
965	return *this;
966}
967
968
969template<typename ParentBuilder>
970typename Grid<ParentBuilder>::ThisBuilder&
971Grid<ParentBuilder>::SetExplicitAlignment(BAlignment alignment)
972{
973	fLayout->SetExplicitAlignment(alignment);
974	return *this;
975}
976
977
978template<typename ParentBuilder>
979Grid<ParentBuilder>::operator BGridLayout*()
980{
981	return fLayout;
982}
983
984
985// #pragma mark - Split
986
987
988template<typename ParentBuilder>
989Split<ParentBuilder>::Split(enum orientation orientation, float spacing)
990	:
991	fView(new BSplitView(orientation, spacing))
992{
993}
994
995
996template<typename ParentBuilder>
997Split<ParentBuilder>::Split(BSplitView* view)
998	:
999	fView(view)
1000{
1001}
1002
1003
1004template<typename ParentBuilder>
1005BSplitView*
1006Split<ParentBuilder>::View() const
1007{
1008	return fView;
1009}
1010
1011
1012template<typename ParentBuilder>
1013typename Split<ParentBuilder>::ThisBuilder&
1014Split<ParentBuilder>::GetView(BView** _view)
1015{
1016	*_view = fView;
1017	return *this;
1018}
1019
1020
1021template<typename ParentBuilder>
1022typename Split<ParentBuilder>::ThisBuilder&
1023Split<ParentBuilder>::GetSplitView(BSplitView** _view)
1024{
1025	*_view = fView;
1026	return *this;
1027}
1028
1029
1030template<typename ParentBuilder>
1031typename Split<ParentBuilder>::ThisBuilder&
1032Split<ParentBuilder>::Add(BView* view)
1033{
1034	fView->AddChild(view);
1035	return *this;
1036}
1037
1038
1039template<typename ParentBuilder>
1040typename Split<ParentBuilder>::ThisBuilder&
1041Split<ParentBuilder>::Add(BView* view, float weight)
1042{
1043	fView->AddChild(view, weight);
1044	return *this;
1045}
1046
1047
1048template<typename ParentBuilder>
1049typename Split<ParentBuilder>::ThisBuilder&
1050Split<ParentBuilder>::Add(BLayoutItem* item)
1051{
1052	fView->AddChild(item);
1053	return *this;
1054}
1055
1056
1057template<typename ParentBuilder>
1058typename Split<ParentBuilder>::ThisBuilder&
1059Split<ParentBuilder>::Add(BLayoutItem* item, float weight)
1060{
1061	fView->AddChild(item, weight);
1062	return *this;
1063}
1064
1065
1066template<typename ParentBuilder>
1067typename Split<ParentBuilder>::GroupBuilder
1068Split<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
1078template<typename ParentBuilder>
1079typename Split<ParentBuilder>::GroupBuilder
1080Split<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
1089template<typename ParentBuilder>
1090typename Split<ParentBuilder>::GroupBuilder
1091Split<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
1100template<typename ParentBuilder>
1101typename Split<ParentBuilder>::GridBuilder
1102Split<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
1112template<typename ParentBuilder>
1113typename Split<ParentBuilder>::GridBuilder
1114Split<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
1123template<typename ParentBuilder>
1124typename Split<ParentBuilder>::GridBuilder
1125Split<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
1134template<typename ParentBuilder>
1135typename Split<ParentBuilder>::SplitBuilder
1136Split<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
1146template<typename ParentBuilder>
1147typename Split<ParentBuilder>::ThisBuilder&
1148Split<ParentBuilder>::SetCollapsible(bool collapsible)
1149{
1150	fView->SetCollapsible(collapsible);
1151	return *this;
1152}
1153
1154
1155template<typename ParentBuilder>
1156typename Split<ParentBuilder>::ThisBuilder&
1157Split<ParentBuilder>::SetCollapsible(int32 index, bool collapsible)
1158{
1159	fView->SetCollapsible(index, collapsible);
1160	return *this;
1161}
1162
1163
1164template<typename ParentBuilder>
1165typename Split<ParentBuilder>::ThisBuilder&
1166Split<ParentBuilder>::SetCollapsible(int32 first, int32 last, bool collapsible)
1167{
1168	fView->SetCollapsible(first, last, collapsible);
1169	return *this;
1170}
1171
1172
1173template<typename ParentBuilder>
1174typename Split<ParentBuilder>::ThisBuilder&
1175Split<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
1183template<typename ParentBuilder>
1184typename Split<ParentBuilder>::ThisBuilder&
1185Split<ParentBuilder>::SetInsets(float horizontal, float vertical)
1186{
1187	fView->SetInsets(horizontal, vertical);
1188	return *this;
1189}
1190
1191
1192template<typename ParentBuilder>
1193typename Split<ParentBuilder>::ThisBuilder&
1194Split<ParentBuilder>::SetInsets(float insets)
1195{
1196	fView->SetInsets(insets);
1197	return *this;
1198}
1199
1200
1201template<typename ParentBuilder>
1202Split<ParentBuilder>::operator BSplitView*()
1203{
1204	return fView;
1205}
1206
1207
1208// #pragma mark - Menu
1209
1210
1211template<typename ParentBuilder>
1212Menu<ParentBuilder>::Menu(BMenu* menu)
1213	:
1214	fMenu(menu)
1215{
1216}
1217
1218
1219template<typename ParentBuilder>
1220typename Menu<ParentBuilder>::ThisBuilder&
1221Menu<ParentBuilder>::GetMenu(BMenu*& _menu)
1222{
1223	_menu = fMenu;
1224	return *this;
1225}
1226
1227
1228template<typename ParentBuilder>
1229typename Menu<ParentBuilder>::ItemBuilder
1230Menu<ParentBuilder>::AddItem(BMenuItem* item)
1231{
1232	fMenu->AddItem(item);
1233	return MenuItem<ParentBuilder>(this->fParent, fMenu, item);
1234}
1235
1236
1237template<typename ParentBuilder>
1238typename Menu<ParentBuilder>::ItemBuilder
1239Menu<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
1249template<typename ParentBuilder>
1250typename Menu<ParentBuilder>::ItemBuilder
1251Menu<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
1262template<typename ParentBuilder>
1263typename Menu<ParentBuilder>::ItemBuilder
1264Menu<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
1283template<typename ParentBuilder>
1284typename Menu<ParentBuilder>::ThisBuilder&
1285Menu<ParentBuilder>::AddSeparator()
1286{
1287	fMenu->AddSeparatorItem();
1288	return *this;
1289}
1290
1291
1292template<typename ParentBuilder>
1293typename Menu<ParentBuilder>::MenuBuilder
1294Menu<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
1305template<typename ParentBuilder>
1306typename Menu<ParentBuilder>::MenuBuilder
1307Menu<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
1324template<typename ParentBuilder>
1325MenuItem<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
1335template<typename ParentBuilder>
1336typename MenuItem<ParentBuilder>::ThisBuilder&
1337MenuItem<ParentBuilder>::GetItem(BMenuItem*& _item)
1338{
1339	_item = fMenuItem;
1340	return *this;
1341}
1342
1343
1344template<typename ParentBuilder>
1345typename MenuItem<ParentBuilder>::ThisBuilder&
1346MenuItem<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