Containers
Table of content
Controls
Any control can be a container. Indeed a control can have several children. For more information, see Parent and children.
While this is possible, we generally prefer to use defined containers that have specific properties to handle child controls.
Standard containers
These containers use location, size, auto_size, anchor and dock for children controls.
For more information, see Size and location properties and Position and layout of controls.
Fixed layout panel
The fixed_layout_panel is used to group collections of fixed aligned controls.
Example
The following example demonstrates the use of fixed_layout_panel container.
#include <xtd/xtd>
using namespace xtd::forms;
class form1 : public form {
public:
form1() {
client_size({400, 200});
panel1.parent(*this).dock(dock_style::fill);
panel1.controls().push_back_range({button1, button2, button3, button4});
button1.location({10, 10});
button1.text("button 1");
button2.location({10, 55});
button2.text("button 2");
button3.location({10, 100});
button3.text("button 3");
button4.location({10, 145});
button4.text("button 4");
}
private:
fixed_layout_panel panel1;
button button1;
button button2;
button button3;
button button4;
};
auto main() -> int {
application::run(form1());
}
Group box
group_box represents a Windows control that displays a frame around a group of controls with an optional caption.
Example
The following example demonstrates the use of group_box container.
#include <xtd/xtd>
using namespace xtd::forms;
class form1 : public form {
public:
form1() {
client_size({400, 200});
group_box1.parent(*this).dock(dock_style::fill);
group_box1.controls().push_back_range({button1, button2, button3, button4});
button1.location({10, 10});
button1.text("button 1");
button2.location({10, 55});
button2.text("button 2");
button3.location({10, 100});
button3.text("button 3");
button4.location({10, 145});
button4.text("button 4");
}
private:
group_box group_box1;
button button1;
button button2;
button button3;
button button4;
};
auto main() -> int {
application::run(form1());
}
Panel
panel is used to group collections of controls.
The following example demonstrates the use of panel container.
#include <xtd/xtd>
using namespace xtd::forms;
class form1 : public form {
public:
form1() {
client_size({400, 200});
panel1.parent(*this).dock(dock_style::fill);
panel1.controls().push_back_range({button1, button2, button3, button4});
button1.location({10, 10});
button1.text("button 1");
button2.location({10, 55});
button2.text("button 2");
button3.location({10, 100});
button3.text("button 3");
button4.location({10, 145});
button4.text("button 4");
}
private:
fixed_layout_panel panel1;
button button1;
button button2;
button button3;
button button4;
};
auto main() -> int {
application::run(form1());
}
Popup panel
popup_panel represents a special type of panel container that can be used for context_menu, combo_box popups and more.
Example
The following example demonstrates the use of popup_panel container.
#include <xtd/xtd>
using namespace xtd;
using namespace xtd::drawing;
using namespace xtd::forms;
class form1 : public form {
public:
form1() {
text("Popup panel example");
client_size({300, 100});
controls().push_back_range({button1, popup_panel1});
list_box1.parent(popup_panel1);
list_box1.dock(dock_style::fill);
list_box1.items().push_back_range({{"clear", button_images::from_name("weather-clear")}, {"clear night", button_images::from_name("weather-clear-night")}, {"few clouds", button_images::from_name("weather-few-clouds")}, {"few clouds night", button_images::from_name("weather-few-clouds-night")}, {"fog", button_images::from_name("weather-fog")}, {"overcast", button_images::from_name("weather-overcast")}, {"severe alert", button_images::from_name("weather-severe-alert")}, {"showers", button_images::from_name("weather-showers")}, {"showers scattered", button_images::from_name("weather-showers-scattered")}, {"snow", button_images::from_name("weather-snow")}, {"storm", button_images::from_name("weather-storm")}});
list_box1.selected_index(0);
list_box1.click += [&] {
button1.text(list_box1.selected_item().value());
button1.image(as<image>(list_box1.selected_item().tag()));
popup_panel1.hide();
};
button1.location({10, 10});
button1.size({160, 50});
button1.image_align(content_alignment::top_center);
button1.text_align(content_alignment::bottom_center);
button1.text(list_box1.selected_item().value());
button1.image(as<image>(list_box1.selected_item().tag()));
button1.click += [&] {
popup_panel1.show();
};
popup_panel1.location(button1.location());
popup_panel1.width(button1.width());
}
private:
button button1;
list_box list_box1;
popup_panel popup_panel1;
};
auto main() -> int {
application::run(form1 {});
}
Splitter panel
splitter_panel represents a panel that is associated with a split_container.
Coming soon...
Tab page
tab_page represents a single tab page in a tab_control.
Example
The following example demonstrates the use of tab_page container.
#include <xtd/xtd>
using namespace xtd::forms;
class form1 : public form {
public:
form1() {
text("Tab control example");
controls().push_back(tab_control1);
client_size({390, 270});
tab_control1.location({10, 10});
tab_control1.size({370, 250});
tab_control1.anchor(anchor_styles::left | anchor_styles::top | anchor_styles::right | anchor_styles::bottom);
tab_page1.parent(tab_control1);
tab_page1.text("Tab page 1");
label1.dock(dock_style::fill);
label1.parent(tab_page1);
label1.text("label1");
label1.text_align(xtd::forms::content_alignment::top_left);
tab_page2.parent(tab_control1);
tab_page2.text("Tab page 2");
label2.dock(dock_style::fill);
label2.parent(tab_page2);
label2.text_align(xtd::forms::content_alignment::middle_center);
label2.text("label2");
tab_page3.parent(tab_control1);
tab_page3.text("Tab page 3");
label3.dock(dock_style::fill);
label3.parent(tab_page3);
label3.text_align(xtd::forms::content_alignment::bottom_right);
label3.text("label3");
}
private:
tab_control tab_control1;
tab_page tab_page1;
tab_page tab_page2;
tab_page tab_page3;
label label1;
label label2;
label label3;
};
auto main() -> int {
application::run(form1 {});
}
Remarks
- fixed_layout_panel is the same as panel.
- splitter_panel is used with splitt_container and is the same as panel.
- tab_page is used with tab_page and is the same as panel.
Layout containers
The layout containers manage the layout of child controls. Unlike standard containers, they manage the size, position and layout of child controls and do not use user-defined child control properties.
Remarks
Layout containers can use the dock or anchor to position themselves in the parent control (Usually we use dock(dock_style::fill))
.
On the other hand, child controls of layout panel cannot use the dock or anchor properties because it is the layout panel that decides how to display them according to the chosen options.
Flow layout panel
flow_layout_panel is used to group collections of fixed aligned controls.
Coming soon...
Horizontal layout panel
horizontal_layout_panel is used to group collections of horizontally aligned controls.
Horizontal layout panel styles
For each child control of horizontal_layout_panel an horizontal_layout_style style is associate. You can specify for each chid control the layout style to the layout container by the method control_layout_style. If you don't specify the layout style, it use the style by default.
An horizontal_layout_style is composed of :
- content_alignment : One of the content_alignment values. The default is middle_center.
- top_left : Content is vertically aligned at the top, and horizontally aligned on the left.
- top_center : Content is vertically aligned at the top, and horizontally aligned at the center.
- top_right : Content is vertically aligned at the top, and horizontally aligned on the right.
- middle_left : Content is vertically aligned in the middle, and horizontally aligned on the left.
- middle_center : Content is vertically aligned at the middle, and horizontally aligned at the center.
- middle_right : Content is vertically aligned at the middle, and horizontally aligned on the right.
- bottom_left : Content is vertically aligned in the bottom, and horizontally aligned on the left.
- bottom_center : Content is vertically aligned at the bottom, and horizontally aligned at the center.
- bottom_right : Content is vertically aligned at the bottom, and horizontally aligned on the right.
- exapend : A flag indicating if control is expanded to its containing layout container. The default is false.
- size_type : One of the size_type values that specifies how layout container of user interface (UI) elements should be sized relative to their container. The default is auto_size.
- width : The prefered width in pixel or percent depending the size_type. The default is std::nullopt.
Remarks
If you don't set expand to true and you set the height of the control. the horizontal_layout_panel will take this into account. But not the width.
Examples
The following example shows how to create a horizontal_layout_panel with children that have a default style.
#include <xtd/xtd.forms.h>
using namespace xtd;
using namespace xtd::forms;
class form1 : public form {
public:
form1() {
client_size({400, 200});
panel1.parent(*this).dock(dock_style::fill);
panel1.controls().push_back_range({button1, button2, button3, button4});
button1.flat_style(xtd::forms::flat_style::popup).text("button 1");
button2.flat_style(xtd::forms::flat_style::popup).text("button 2");
button3.flat_style(xtd::forms::flat_style::popup).text("button 3");
button4.flat_style(xtd::forms::flat_style::popup).text("button 4");
}
private:
horizontal_layout_panel panel1;
button button1;
button button2;
button button3;
button button4;
};
auto main() -> int {
application::run(form1());
}
The following example shows how to create a horizontal_layout_panel whose children must have a size corresponding to a percentage of the parent container.
#include <xtd/xtd.forms.h>
using namespace xtd;
using namespace xtd::forms;
class form1 : public form {
public:
form1() {
client_size({400, 200});
panel1.parent(*this).dock(dock_style::fill);
panel1.controls().push_back_range({button1, button2, button3, button4});
panel1.control_layout_style(button1, horizontal_control_layout_style{.15f, size_type::percent});
panel1.control_layout_style(button2, horizontal_control_layout_style{.35f, size_type::percent});
panel1.control_layout_style(button3, horizontal_control_layout_style{.35f, size_type::percent});
panel1.control_layout_style(button4, horizontal_control_layout_style{.15f, size_type::percent});
button1.flat_style(xtd::forms::flat_style::popup).text("button 1");
button2.flat_style(xtd::forms::flat_style::popup).text("button 2");
button3.flat_style(xtd::forms::flat_style::popup).text("button 3");
button4.flat_style(xtd::forms::flat_style::popup).text("button 4");
}
private:
horizontal_layout_panel panel1;
button button1;
button button2;
button button3;
button button4;
};
auto main() -> int {
application::run(form1());
}
The following example shows how to create a horizontal_layout_panel whose children must have a size corresponding to a abosulte value in pixels and set expand to true.
#include <xtd/xtd.forms.h>
using namespace xtd;
using namespace xtd::forms;
class form1 : public form {
public:
form1() {
client_size({400, 200});
panel1.parent(*this).dock(dock_style::fill);
panel1.controls().push_back_range({button1, button2, button3, button4});
panel1.control_layout_style(button1, horizontal_control_layout_style{75, size_type::absolute, true});
panel1.control_layout_style(button2, horizontal_control_layout_style{125, size_type::absolute, true});
panel1.control_layout_style(button3, horizontal_control_layout_style{125, size_type::absolute, true});
panel1.control_layout_style(button4, horizontal_control_layout_style{75, size_type::absolute, true});
button1.flat_style(xtd::forms::flat_style::popup).text("button 1");
button2.flat_style(xtd::forms::flat_style::popup).text("button 2");
button3.flat_style(xtd::forms::flat_style::popup).text("button 3");
button4.flat_style(xtd::forms::flat_style::popup).text("button 4");
}
private:
horizontal_layout_panel panel1;
button button1;
button button2;
button button3;
button button4;
};
auto main() -> int {
application::run(form1());
}
Table layout panel
table_layout_panel is used to group collections of fixed aligned controls.
Coming soon...
Vertical layout panel
vertical_layout_panel is used to group collections of verticaly aligned controls.
Vertical layout panel styles
For each child control of vertical_layout_panel an vertical_layout_style style is associate. You can specify for each chid control the layout style to the layout container by the method control_layout_style. If you don't specify the layout style, it use the style by default.
An vertical_layout_style is composed of :
- content_alignment : One of the content_alignment values. The default is middle_center.
- top_left : Content is vertically aligned at the top, and horizontally aligned on the left.
- top_center : Content is vertically aligned at the top, and horizontally aligned at the center.
- top_right : Content is vertically aligned at the top, and horizontally aligned on the right.
- middle_left : Content is vertically aligned in the middle, and horizontally aligned on the left.
- middle_center : Content is vertically aligned at the middle, and horizontally aligned at the center.
- middle_right : Content is vertically aligned at the middle, and horizontally aligned on the right.
- bottom_left : Content is vertically aligned in the bottom, and horizontally aligned on the left.
- bottom_center : Content is vertically aligned at the bottom, and horizontally aligned at the center.
- bottom_right : Content is vertically aligned at the bottom, and horizontally aligned on the right.
- exapend : A flag indicating if control is expanded to its containing layout container. The default is false.
- size_type : One of the size_type values that specifies how layout container of user interface (UI) elements should be sized relative to their container. The default is auto_size.
- width : The prefered width in pixel or percent depending the size_type. The default is std::nullopt.
Remarks
If you don't set expand to true and you set the width of the control. the vertical_layout_panel will take this into account. But not the height.
Examples
The following example shows how to create a vertical_layout_panel with children that have a default style.
#include <xtd/xtd.forms.h>
using namespace xtd;
using namespace xtd::forms;
class form1 : public form {
public:
form1() {
client_size({200, 400});
panel1.parent(*this).dock(dock_style::fill);
panel1.controls().push_back_range({button1, button2, button3, button4});
button1.flat_style(xtd::forms::flat_style::popup).text("button 1");
button2.flat_style(xtd::forms::flat_style::popup).text("button 2");
button3.flat_style(xtd::forms::flat_style::popup).text("button 3");
button4.flat_style(xtd::forms::flat_style::popup).text("button 4");
}
private:
vertical_layout_panel panel1;
button button1;
button button2;
button button3;
button button4;
};
auto main() -> int {
application::run(form1());
}
The following example shows how to create a vertical_layout_panel whose children must have a size corresponding to a percentage of the parent container.
#include <xtd/xtd.forms.h>
using namespace xtd;
using namespace xtd::forms;
class form1 : public form {
public:
form1() {
client_size({200, 400});
panel1.parent(*this).dock(dock_style::fill);
panel1.controls().push_back_range({button1, button2, button3, button4});
panel1.control_layout_style(button1, vertical_control_layout_style{.15f, size_type::percent});
panel1.control_layout_style(button2, vertical_control_layout_style{.35f, size_type::percent});
panel1.control_layout_style(button3, vertical_control_layout_style{.35f, size_type::percent});
panel1.control_layout_style(button4, vertical_control_layout_style{.15f, size_type::percent});
button1.flat_style(xtd::forms::flat_style::popup).text("button 1");
button2.flat_style(xtd::forms::flat_style::popup).text("button 2");
button3.flat_style(xtd::forms::flat_style::popup).text("button 3");
button4.flat_style(xtd::forms::flat_style::popup).text("button 4");
}
private:
vertical_layout_panel panel1;
button button1;
button button2;
button button3;
button button4;
};
auto main() -> int {
application::run(form1());
}
The following example shows how to create a vertical_layout_panel whose children must have a size corresponding to a abosulte value in pixels and set expand to true.
#include <xtd/xtd.forms.h>
using namespace xtd;
using namespace xtd::forms;
class form1 : public form {
public:
form1() {
client_size({200, 400});
panel1.parent(*this).dock(dock_style::fill);
panel1.controls().push_back_range({button1, button2, button3, button4});
panel1.control_layout_style(button1, vertical_control_layout_style{75, size_type::absolute, true});
panel1.control_layout_style(button2, vertical_control_layout_style{125, size_type::absolute, true});
panel1.control_layout_style(button3, vertical_control_layout_style{125, size_type::absolute, true});
panel1.control_layout_style(button4, vertical_control_layout_style{75, size_type::absolute, true});
button1.flat_style(xtd::forms::flat_style::popup).text("button 1");
button2.flat_style(xtd::forms::flat_style::popup).text("button 2");
button3.flat_style(xtd::forms::flat_style::popup).text("button 3");
button4.flat_style(xtd::forms::flat_style::popup).text("button 4");
}
private:
vertical_layout_panel panel1;
button button1;
button button2;
button button3;
button button4;
};
auto main() -> int {
application::run(form1());
}
Specific containers
Collapsible panel
collapsible_panel is used to group collections of controls in a collapsible panel.
coming soon...
Split container
split_container represents a control consisting of a movable bar that divides a container's display area into two resizable panels.
Remarks
The child control for the split_container are splitter_panel.
coming soon...
Tab control
tab_control manages a related set of tab pages.
Remarks
The child controls for the tab_control are tab_page.
Example
The following example demonstrates the use of tab_control container.
#include <xtd/xtd>
using namespace xtd::forms;
class form1 : public form {
public:
form1() {
text("Tab control example");
controls().push_back(tab_control1);
client_size({390, 270});
tab_control1.location({10, 10});
tab_control1.size({370, 250});
tab_control1.anchor(anchor_styles::left | anchor_styles::top | anchor_styles::right | anchor_styles::bottom);
tab_page1.parent(tab_control1);
tab_page1.text("Tab page 1");
label1.dock(dock_style::fill);
label1.parent(tab_page1);
label1.text("label1");
label1.text_align(xtd::forms::content_alignment::top_left);
tab_page2.parent(tab_control1);
tab_page2.text("Tab page 2");
label2.dock(dock_style::fill);
label2.parent(tab_page2);
label2.text_align(xtd::forms::content_alignment::middle_center);
label2.text("label2");
tab_page3.parent(tab_control1);
tab_page3.text("Tab page 3");
label3.dock(dock_style::fill);
label3.parent(tab_page3);
label3.text_align(xtd::forms::content_alignment::bottom_right);
label3.text("label3");
}
private:
tab_control tab_control1;
tab_page tab_page1;
tab_page tab_page2;
tab_page tab_page3;
label label1;
label label2;
label label3;
};
auto main() -> int {
application::run(form1 {});
}
User container
xtd is flexible and complete enough to create your own container without much effort.
Own horizontal stack panel
The following example show how to make your own horizontal stack panel esasily with overloading on_layout method.
#include <xtd/xtd.forms.h>
using namespace xtd;
using namespace xtd::forms;
class horizontal_stack_panel : public panel {
protected:
void on_layout(const event_args& e) override {
panel::on_layout(e);
auto left = 0;
for (auto control : controls()) {
control.get().left(left).height(client_size().height());
left += control.get().width();
}
}
};
class form1 : public form {
public:
form1() {
client_size({400, 200});
panel1.parent(*this).size({300, 35});
panel1.controls().push_back_range({button1, button2, button3, button4});
button1.flat_style(xtd::forms::flat_style::popup).text("button 1");
button2.flat_style(xtd::forms::flat_style::popup).text("button 2");
button3.flat_style(xtd::forms::flat_style::popup).text("button 3");
button4.flat_style(xtd::forms::flat_style::popup).text("button 4");
}
private:
horizontal_stack_panel panel1;
button button1;
button button2;
button button3;
button button4;
};
auto main() -> int {
application::run(form1());
}
Own vertical stack panel
The following example show how to make your own vertical stack panel esasily with dock and overloading on_control_added method.
#include <xtd/xtd.forms.h>
using namespace xtd;
using namespace xtd::forms;
class vertical_stack_panel : public panel {
protected:
void on_control_added(const control_event_args& e) override {
panel::on_control_added(e);
e.control().dock(dock_style::top);
}
};
class form1 : public form {
public:
form1() {
client_size({400, 200});
panel1.parent(*this).size({100, 150});
panel1.controls().push_back_range({button4, button3, button2, button1});
button1.flat_style(xtd::forms::flat_style::popup).text("button 1");
button2.flat_style(xtd::forms::flat_style::popup).text("button 2");
button3.flat_style(xtd::forms::flat_style::popup).text("button 3");
button4.flat_style(xtd::forms::flat_style::popup).text("button 4");
}
private:
vertical_stack_panel panel1;
button button1;
button button2;
button button3;
button button4;
};
auto main() -> int {
application::run(form1());
}
See also