diff --git a/doc/classes/CSplitContainer.xml b/doc/classes/CSplitContainer.xml new file mode 100644 index 000000000..45d2231f5 --- /dev/null +++ b/doc/classes/CSplitContainer.xml @@ -0,0 +1,44 @@ + + + + Horizontal or vertical split container. + + + Horizontal or vertical split container depending on it's [member mode] setting. See [SplitContainer]. + + + $DOCS_URL/tutorials/ui/gui_containers.md + + + + + + Sets whether this [CSplitContainer] will act as a [HSplitContainer] or a [VSplitContainer]. + + + + + This [CSplitContainer] will act as a [HSplitContainer]. + + + This [CSplitContainer] will act as a [VSplitContainer]. + + + + + Boolean value. If 1 ([code]true[/code]), the grabber will hide automatically when it isn't under the cursor. If 0 ([code]false[/code]), it's always visible. + + + The horizontal or vertical space between the [CSplitContainer]'s elements. + + + The icon used for the horizontal grabber drawn in the middle area. + + + The icon used for the vertical grabber drawn in the middle area. + + + The background drawn under this control. + + + diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp index 6ffc09bd1..cf4ea7394 100644 --- a/editor/editor_themes.cpp +++ b/editor/editor_themes.cpp @@ -1063,17 +1063,22 @@ Ref create_editor_theme(const Ref p_theme) { // H/VSplitContainer theme->set_stylebox("bg", "VSplitContainer", make_stylebox(theme->get_icon("GuiVsplitBg", "EditorIcons"), 1, 1, 1, 1)); theme->set_stylebox("bg", "HSplitContainer", make_stylebox(theme->get_icon("GuiHsplitBg", "EditorIcons"), 1, 1, 1, 1)); + theme->set_stylebox("bg", "CSplitContainer", make_stylebox(theme->get_icon("GuiHsplitBg", "EditorIcons"), 1, 1, 1, 1)); theme->set_icon("grabber", "VSplitContainer", theme->get_icon("GuiVsplitter", "EditorIcons")); theme->set_icon("grabber", "HSplitContainer", theme->get_icon("GuiHsplitter", "EditorIcons")); + theme->set_icon("vgrabber", "CSplitContainer", theme->get_icon("GuiVsplitter", "EditorIcons")); + theme->set_icon("hgrabber", "CSplitContainer", theme->get_icon("GuiHsplitter", "EditorIcons")); theme->set_constant("separation", "HSplitContainer", default_margin_size * 2 * EDSCALE); theme->set_constant("separation", "VSplitContainer", default_margin_size * 2 * EDSCALE); + theme->set_constant("separation", "CSplitContainer", default_margin_size * 2 * EDSCALE); // Containers theme->set_constant("separation", "BoxContainer", default_margin_size * EDSCALE); theme->set_constant("separation", "HBoxContainer", default_margin_size * EDSCALE); theme->set_constant("separation", "VBoxContainer", default_margin_size * EDSCALE); + theme->set_constant("separation", "CBoxContainer", default_margin_size * EDSCALE); theme->set_constant("margin_left", "MarginContainer", 0); theme->set_constant("margin_top", "MarginContainer", 0); theme->set_constant("margin_right", "MarginContainer", 0); diff --git a/editor/icons/icon_c_split_container.svg b/editor/icons/icon_c_split_container.svg new file mode 100644 index 000000000..3bdb62a1b --- /dev/null +++ b/editor/icons/icon_c_split_container.svg @@ -0,0 +1,42 @@ + + + + + + + diff --git a/scene/gui/split_container.cpp b/scene/gui/split_container.cpp index f7df97742..e40a5dcd9 100644 --- a/scene/gui/split_container.cpp +++ b/scene/gui/split_container.cpp @@ -55,6 +55,25 @@ Control *SplitContainer::_getch(int p_idx) const { return nullptr; } +bool SplitContainer::_get_vertical() const { + return vertical; +} +void SplitContainer::_set_vertical(bool p_vertical) { + if (vertical == p_vertical) { + return; + } + + vertical = p_vertical; + + should_clamp_split_offset = true; + queue_sort(); + minimum_size_changed(); +} + +String SplitContainer::get_grabber_theme_constant_name() const { + return "grabber"; +} + void SplitContainer::_resort() { int axis = vertical ? 1 : 0; @@ -76,7 +95,7 @@ void SplitContainer::_resort() { bool second_expanded = (vertical ? second->get_v_size_flags() : second->get_h_size_flags()) & SIZE_EXPAND; // Determine the separation between items - Ref g = get_theme_icon("grabber"); + Ref g = get_theme_icon(get_grabber_theme_constant_name()); int sep = get_theme_constant("separation"); sep = (dragger_visibility != DRAGGER_HIDDEN_COLLAPSED) ? MAX(sep, vertical ? g->get_height() : g->get_width()) : 0; @@ -124,7 +143,7 @@ Size2 SplitContainer::get_minimum_size() const { /* Calculate MINIMUM SIZE */ Size2i minimum; - Ref g = get_theme_icon("grabber"); + Ref g = get_theme_icon(get_grabber_theme_constant_name()); int sep = get_theme_constant("separation"); sep = (dragger_visibility != DRAGGER_HIDDEN_COLLAPSED) ? MAX(sep, vertical ? g->get_height() : g->get_width()) : 0; @@ -180,7 +199,7 @@ void SplitContainer::_notification(int p_what) { } int sep = dragger_visibility != DRAGGER_HIDDEN_COLLAPSED ? get_theme_constant("separation") : 0; - Ref tex = get_theme_icon("grabber"); + Ref tex = get_theme_icon(get_grabber_theme_constant_name()); Size2 size = get_size(); if (vertical) { @@ -353,3 +372,39 @@ SplitContainer::SplitContainer(bool p_vertical) { collapsed = false; dragger_visibility = DRAGGER_VISIBLE; } + +CSplitContainer::ContainerMode CSplitContainer::get_mode() const { + return _mode; +} +void CSplitContainer::set_mode(const ContainerMode p_mode) { + if (p_mode == _mode) { + return; + } + + _mode = p_mode; + + _set_vertical(_mode == CONTAINER_MODE_VERTICAL); +} + +CSplitContainer::CSplitContainer() { + _mode = CONTAINER_MODE_HORIZONTAL; +} +CSplitContainer::~CSplitContainer() { +} + +String CSplitContainer::get_grabber_theme_constant_name() const { + if (_get_vertical()) { + return "vgrabber"; + } else { + return "hgrabber"; + } +} + +void CSplitContainer::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_mode"), &CSplitContainer::get_mode); + ClassDB::bind_method(D_METHOD("set_mode", "mode"), &CSplitContainer::set_mode); + ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Horizontal,Vertical"), "set_mode", "get_mode"); + + BIND_ENUM_CONSTANT(CONTAINER_MODE_HORIZONTAL); + BIND_ENUM_CONSTANT(CONTAINER_MODE_VERTICAL); +} diff --git a/scene/gui/split_container.h b/scene/gui/split_container.h index f0a128808..265c2e36e 100644 --- a/scene/gui/split_container.h +++ b/scene/gui/split_container.h @@ -56,9 +56,14 @@ private: Control *_getch(int p_idx) const; +protected: + bool _get_vertical() const; + void _set_vertical(bool p_vertical); + + virtual String get_grabber_theme_constant_name() const; + void _resort(); -protected: void _gui_input(const Ref &p_event); void _notification(int p_what); static void _bind_methods(); @@ -83,6 +88,8 @@ public: VARIANT_ENUM_CAST(SplitContainer::DraggerVisibility); +// ==== HSplitContainer ==== + class HSplitContainer : public SplitContainer { GDCLASS(HSplitContainer, SplitContainer); @@ -91,6 +98,8 @@ public: SplitContainer(false) {} }; +// ==== VSplitContainer ==== + class VSplitContainer : public SplitContainer { GDCLASS(VSplitContainer, SplitContainer); @@ -99,4 +108,31 @@ public: SplitContainer(true) {} }; +// ==== CSplitContainer ==== + +class CSplitContainer : public SplitContainer { + GDCLASS(CSplitContainer, SplitContainer); + +public: + enum ContainerMode { + CONTAINER_MODE_HORIZONTAL = 0, + CONTAINER_MODE_VERTICAL, + }; + + ContainerMode get_mode() const; + void set_mode(const ContainerMode p_mode); + + CSplitContainer(); + ~CSplitContainer(); + +protected: + virtual String get_grabber_theme_constant_name() const; + + static void _bind_methods(); + + ContainerMode _mode; +}; + +VARIANT_ENUM_CAST(CSplitContainer::ContainerMode); + #endif // SPLIT_CONTAINER_H diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index cd5b10e0b..1e8b97fb5 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -387,6 +387,7 @@ void register_scene_types() { ClassDB::register_virtual_class(); ClassDB::register_class(); ClassDB::register_class(); + ClassDB::register_class(); ClassDB::register_class(); ClassDB::register_class(); diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp index 1bf9bfe74..3fea74c1a 100644 --- a/scene/resources/default_theme/default_theme.cpp +++ b/scene/resources/default_theme/default_theme.cpp @@ -880,12 +880,17 @@ void fill_default_theme(Ref &theme, const Ref &default_font, const theme->set_stylebox("bg", "VSplitContainer", make_stylebox(vsplit_bg_png, 1, 1, 1, 1)); theme->set_stylebox("bg", "HSplitContainer", make_stylebox(hsplit_bg_png, 1, 1, 1, 1)); + theme->set_stylebox("bg", "CSplitContainer", make_stylebox(hsplit_bg_png, 1, 1, 1, 1)); theme->set_icon("grabber", "VSplitContainer", make_icon(vsplitter_png)); theme->set_icon("grabber", "HSplitContainer", make_icon(hsplitter_png)); + theme->set_icon("vgrabber", "CSplitContainer", make_icon(vsplitter_png)); + theme->set_icon("hgrabber", "CSplitContainer", make_icon(hsplitter_png)); theme->set_constant("separation", "HBoxContainer", 4 * scale); theme->set_constant("separation", "VBoxContainer", 4 * scale); + theme->set_constant("separation", "CBoxContainer", 4 * scale); + theme->set_constant("margin_left", "MarginContainer", 0 * scale); theme->set_constant("margin_top", "MarginContainer", 0 * scale); theme->set_constant("margin_right", "MarginContainer", 0 * scale); @@ -894,8 +899,10 @@ void fill_default_theme(Ref &theme, const Ref &default_font, const theme->set_constant("vseparation", "GridContainer", 4 * scale); theme->set_constant("separation", "HSplitContainer", 12 * scale); theme->set_constant("separation", "VSplitContainer", 12 * scale); + theme->set_constant("separation", "CSplitContainer", 12 * scale); theme->set_constant("autohide", "HSplitContainer", 1); theme->set_constant("autohide", "VSplitContainer", 1); + theme->set_constant("autohide", "CSplitContainer", 1); theme->set_constant("hseparation", "HFlowContainer", 4 * scale); theme->set_constant("vseparation", "HFlowContainer", 4 * scale); theme->set_constant("hseparation", "VFlowContainer", 4 * scale);