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