Path: blob/master/tests/scene/test_split_container.cpp
45997 views
/**************************************************************************/1/* test_split_container.cpp */2/**************************************************************************/3/* This file is part of: */4/* GODOT ENGINE */5/* https://godotengine.org */6/**************************************************************************/7/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */8/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */9/* */10/* Permission is hereby granted, free of charge, to any person obtaining */11/* a copy of this software and associated documentation files (the */12/* "Software"), to deal in the Software without restriction, including */13/* without limitation the rights to use, copy, modify, merge, publish, */14/* distribute, sublicense, and/or sell copies of the Software, and to */15/* permit persons to whom the Software is furnished to do so, subject to */16/* the following conditions: */17/* */18/* The above copyright notice and this permission notice shall be */19/* included in all copies or substantial portions of the Software. */20/* */21/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */22/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */23/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */24/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */25/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */26/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */27/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */28/**************************************************************************/2930#include "tests/test_macros.h"3132TEST_FORCE_LINK(test_split_container)3334#ifndef ADVANCED_GUI_DISABLED3536#include "scene/gui/split_container.h"37#include "scene/main/scene_tree.h"38#include "scene/main/window.h"39#include "tests/display_server_mock.h"40#include "tests/signal_watcher.h"4142namespace TestSplitContainer {4344#define CHECK_RECTS(m_rects, m_child_rects) \45CHECK(m_rects.size() == m_child_rects.size()); \46for (int i = 0; i < (int)m_child_rects.size(); i++) { \47CHECK_MESSAGE(m_child_rects[i] == m_rects[i], vformat("Child %s is the wrong size. Child rect: %s, expected: %s.", i, m_child_rects[i], m_rects[i])); \48}4950static inline Vector<Rect2> get_rects_multi(SplitContainer *p_sc, const Vector<int> &p_positions, int p_sep, bool p_horizontal = true) {51// p_positions is the top/left side of the dragger.52Vector<Rect2> rects;53int last_pos = 0;54for (int i = 0; i < (int)p_positions.size() + 1; i++) {55const int pos = i >= (int)p_positions.size() ? p_sc->get_size()[p_horizontal ? 0 : 1] : p_positions[i];56Rect2 rect;57if (p_horizontal) {58rect.size.y = p_sc->get_size().y;59rect.position.x = last_pos;60rect.size.x = pos - last_pos;61} else {62rect.size.x = p_sc->get_size().x;63rect.position.y = last_pos;64rect.size.y = pos - last_pos;65}66rects.push_back(rect);67last_pos = pos + p_sep;68}69return rects;70}7172static inline Vector<Rect2> get_rects(SplitContainer *p_sc, int p_position, int p_sep, bool p_horizontal = true) {73return get_rects_multi(p_sc, Vector<int>({ p_position }), p_sep, p_horizontal);74}7576static inline Vector<Rect2> get_rects_multi_rtl(SplitContainer *p_sc, const Vector<int> &p_positions, int p_sep) {77Vector<Rect2> rects;78int last_pos = p_sc->get_size().x;79for (int i = 0; i < (int)p_positions.size() + 1; i++) {80const int pos = i >= (int)p_positions.size() ? 0 : p_sc->get_size().x - p_positions[i];81Rect2 rect;82rect.size.y = p_sc->get_size().y;83rect.position.x = pos;84rect.size.x = last_pos - pos;85rects.push_back(rect);86last_pos = pos - p_sep;87}88return rects;89}9091static inline Vector<Rect2> get_rects_rtl(SplitContainer *p_sc, int p_position, int p_sep) {92return get_rects_multi_rtl(p_sc, Vector<int>({ p_position }), p_sep);93}9495static inline Vector<Rect2> get_child_rects(SplitContainer *p_sc) {96Vector<Rect2> rects;97for (int i = 0; i < p_sc->get_child_count(false); i++) {98Control *c = Object::cast_to<Control>(p_sc->get_child(i, false));99if (!c || !c->is_visible()) {100continue;101}102rects.push_back(c->get_rect());103}104return rects;105}106107static inline void set_size_flags(SplitContainer *p_sc, Vector<float> p_expand_ratios, bool p_horizontal = true) {108for (int i = 0; i < p_sc->get_child_count(false); i++) {109Control *c = Object::cast_to<Control>(p_sc->get_child(i, false));110if (!c || !c->is_visible()) {111continue;112}113float ratio = p_expand_ratios[i];114if (p_horizontal) {115c->set_h_size_flags(ratio > 0 ? Control::SIZE_EXPAND_FILL : Control::SIZE_FILL);116} else {117c->set_v_size_flags(ratio > 0 ? Control::SIZE_EXPAND_FILL : Control::SIZE_FILL);118}119if (ratio > 0) {120c->set_stretch_ratio(ratio);121}122}123MessageQueue::get_singleton()->flush();124}125126TEST_CASE("[SceneTree][SplitContainer] Add and remove children") {127SplitContainer *split_container = memnew(SplitContainer);128split_container->set_size(Size2(500, 500));129SceneTree::get_singleton()->get_root()->add_child(split_container);130131SUBCASE("[SplitContainer] One child") {132Control *child_a = memnew(Control);133split_container->add_child(child_a);134MessageQueue::get_singleton()->flush();135136// One child will fill the entire area.137CHECK(child_a->get_rect() == split_container->get_rect());138139split_container->set_vertical(true);140CHECK(child_a->get_rect() == split_container->get_rect());141142memdelete(child_a);143}144145SUBCASE("[SplitContainer] Preserve split offset") {146// The split offset is preserved through adding, removing, and changing visibility of children.147split_container->set_split_offset(100);148CHECK(split_container->get_split_offset() == 100);149150Control *child_a = memnew(Control);151split_container->add_child(child_a);152MessageQueue::get_singleton()->flush();153CHECK(split_container->get_split_offset() == 100);154155Control *child_b = memnew(Control);156split_container->add_child(child_b);157MessageQueue::get_singleton()->flush();158CHECK(split_container->get_split_offset() == 100);159160child_a->hide();161MessageQueue::get_singleton()->flush();162CHECK(split_container->get_split_offset() == 100);163164child_b->hide();165MessageQueue::get_singleton()->flush();166CHECK(split_container->get_split_offset() == 100);167168child_b->show();169MessageQueue::get_singleton()->flush();170CHECK(split_container->get_split_offset() == 100);171172child_a->show();173MessageQueue::get_singleton()->flush();174CHECK(split_container->get_split_offset() == 100);175176split_container->remove_child(child_a);177MessageQueue::get_singleton()->flush();178CHECK(split_container->get_split_offset() == 100);179180split_container->add_child(child_a);181MessageQueue::get_singleton()->flush();182CHECK(split_container->get_split_offset() == 100);183184memdelete(child_a);185memdelete(child_b);186}187188memdelete(split_container);189}190191TEST_CASE("[SceneTree][SplitContainer] Dragger visibility") {192SplitContainer *split_container = memnew(SplitContainer);193split_container->set_size(Size2(500, 500));194SceneTree::get_singleton()->get_root()->add_child(split_container);195Control *child_a = memnew(Control);196Control *child_b = memnew(Control);197split_container->add_child(child_a);198split_container->add_child(child_b);199SplitContainerDragger *dragger = Object::cast_to<SplitContainerDragger>(split_container->get_child(2, true));200201split_container->add_theme_constant_override("autohide", 0);202MessageQueue::get_singleton()->flush();203204const int sep_constant = split_container->get_theme_constant("separation");205const Size2i sep = Size2i(MAX(sep_constant, split_container->get_theme_icon("h_grabber")->get_width()), MAX(sep_constant, split_container->get_theme_icon("v_grabber")->get_height()));206207SUBCASE("[SplitContainer] Visibility based on child count") {208split_container->remove_child(child_a);209split_container->remove_child(child_b);210MessageQueue::get_singleton()->flush();211212// No children, not visible.213CHECK_FALSE(dragger->is_visible());214215// Add one child, not visible.216split_container->add_child(child_a);217MessageQueue::get_singleton()->flush();218CHECK_FALSE(dragger->is_visible());219220// Two children, visible.221split_container->add_child(child_b);222MessageQueue::get_singleton()->flush();223CHECK(dragger->is_visible());224225// Remove a child, not visible.226split_container->remove_child(child_b);227MessageQueue::get_singleton()->flush();228CHECK_FALSE(dragger->is_visible());229}230231SUBCASE("[SplitContainer] Set dragger visibility") {232split_container->set_dragger_visibility(SplitContainer::DRAGGER_HIDDEN);233MessageQueue::get_singleton()->flush();234CHECK_RECTS(get_rects(split_container, 0, sep.x), get_child_rects(split_container));235// Can't check the visibility since it happens in draw.236237split_container->set_dragger_visibility(SplitContainer::DRAGGER_HIDDEN_COLLAPSED);238MessageQueue::get_singleton()->flush();239CHECK_RECTS(get_rects(split_container, 0, 0), get_child_rects(split_container));240241split_container->set_dragger_visibility(SplitContainer::DRAGGER_VISIBLE);242MessageQueue::get_singleton()->flush();243CHECK_RECTS(get_rects(split_container, 0, sep.x), get_child_rects(split_container));244}245246SUBCASE("[SplitContainer] Not visible when collapsed") {247split_container->set_collapsed(true);248MessageQueue::get_singleton()->flush();249CHECK_FALSE(dragger->is_visible());250251split_container->set_collapsed(false);252MessageQueue::get_singleton()->flush();253CHECK(dragger->is_visible());254}255256memdelete(child_a);257memdelete(child_b);258memdelete(split_container);259}260261TEST_CASE("[SceneTree][SplitContainer] Collapsed") {262DisplayServerMock *DS = (DisplayServerMock *)(DisplayServer::get_singleton());263264SplitContainer *split_container = memnew(SplitContainer);265split_container->set_size(Size2(500, 500));266SceneTree::get_singleton()->get_root()->add_child(split_container);267Control *child_a = memnew(Control);268split_container->add_child(child_a);269Control *child_b = memnew(Control);270split_container->add_child(child_b);271MessageQueue::get_singleton()->flush();272273const int sep_constant = split_container->get_theme_constant("separation");274const Size2i sep = Size2i(MAX(sep_constant, split_container->get_theme_icon("h_grabber")->get_width()), MAX(sep_constant, split_container->get_theme_icon("v_grabber")->get_height()));275276SUBCASE("[SplitContainer] Dragging and cursor") {277split_container->set_collapsed(true);278279// Cursor is default.280SEND_GUI_MOUSE_MOTION_EVENT(Point2(1, 1), MouseButtonMask::NONE, Key::NONE);281CHECK(DS->get_cursor_shape() == DisplayServerEnums::CURSOR_ARROW);282283// Dragger is disabled, cannot drag.284SEND_GUI_MOUSE_BUTTON_EVENT(Point2(1, 1), MouseButton::LEFT, MouseButtonMask::LEFT, Key::NONE);285MessageQueue::get_singleton()->flush();286CHECK_RECTS(get_rects(split_container, 0, sep.x), get_child_rects(split_container));287CHECK(split_container->get_split_offset() == 0);288SEND_GUI_MOUSE_MOTION_EVENT(Point2(10, 1), MouseButtonMask::LEFT, Key::NONE);289MessageQueue::get_singleton()->flush();290CHECK_RECTS(get_rects(split_container, 0, sep.x), get_child_rects(split_container));291CHECK(split_container->get_split_offset() == 0);292}293294SUBCASE("[SplitContainer] No expand flags") {295int def_pos = 0;296297split_container->set_split_offset(10);298MessageQueue::get_singleton()->flush();299CHECK_RECTS(get_rects(split_container, def_pos + 10, sep.x), get_child_rects(split_container));300301split_container->set_collapsed(true);302MessageQueue::get_singleton()->flush();303304// The split offset is treated as 0 when collapsed.305CHECK_RECTS(get_rects(split_container, def_pos, sep.x), get_child_rects(split_container));306CHECK(split_container->get_split_offset() == 10);307}308309SUBCASE("[SplitContainer] First child expanded") {310int def_pos = split_container->get_size().x - sep.x;311child_a->set_h_size_flags(Control::SIZE_EXPAND_FILL);312split_container->set_split_offset(-10);313MessageQueue::get_singleton()->flush();314315CHECK_RECTS(get_rects(split_container, def_pos - 10, sep.x), get_child_rects(split_container));316317split_container->set_collapsed(true);318MessageQueue::get_singleton()->flush();319320// The split offset is treated as 0 when collapsed.321CHECK_RECTS(get_rects(split_container, def_pos, sep.x), get_child_rects(split_container));322CHECK(split_container->get_split_offset() == -10);323}324325SUBCASE("[SplitContainer] Second child expanded") {326int def_pos = 0;327child_b->set_h_size_flags(Control::SIZE_EXPAND_FILL);328split_container->set_split_offset(10);329MessageQueue::get_singleton()->flush();330331CHECK_RECTS(get_rects(split_container, def_pos + 10, sep.x), get_child_rects(split_container));332333split_container->set_collapsed(true);334MessageQueue::get_singleton()->flush();335336// The split offset is treated as 0 when collapsed.337CHECK_RECTS(get_rects(split_container, def_pos, sep.x), get_child_rects(split_container));338CHECK(split_container->get_split_offset() == 10);339}340341SUBCASE("[SplitContainer] Both children expanded") {342int def_pos = (split_container->get_size().y - sep.y) / 2;343child_a->set_h_size_flags(Control::SIZE_EXPAND_FILL);344child_b->set_h_size_flags(Control::SIZE_EXPAND_FILL);345split_container->set_split_offset(10);346MessageQueue::get_singleton()->flush();347348CHECK_RECTS(get_rects(split_container, def_pos + 10, sep.x), get_child_rects(split_container));349350split_container->set_collapsed(true);351MessageQueue::get_singleton()->flush();352353// The split offset is treated as 0 when collapsed.354CHECK_RECTS(get_rects(split_container, def_pos, sep.x), get_child_rects(split_container));355CHECK(split_container->get_split_offset() == 10);356}357358memdelete(child_a);359memdelete(child_b);360memdelete(split_container);361}362363TEST_CASE("[SceneTree][SplitContainer] Cursor shape") {364DisplayServerMock *DS = (DisplayServerMock *)(DisplayServer::get_singleton());365366SplitContainer *split_container = memnew(SplitContainer);367split_container->set_size(Size2(500, 500));368SceneTree::get_singleton()->get_root()->add_child(split_container);369Control *child_a = memnew(Control);370split_container->add_child(child_a);371Control *child_b = memnew(Control);372split_container->add_child(child_b);373MessageQueue::get_singleton()->flush();374375Point2 on_dragger = Point2(1, 1);376Point2 not_on_dragger = Point2(50, 50);377378// Default cursor shape.379SEND_GUI_MOUSE_MOTION_EVENT(not_on_dragger, MouseButtonMask::NONE, Key::NONE);380CHECK(DS->get_cursor_shape() == DisplayServerEnums::CURSOR_ARROW);381382// Horizontal cursor shape.383SEND_GUI_MOUSE_MOTION_EVENT(on_dragger, MouseButtonMask::NONE, Key::NONE);384CHECK(DS->get_cursor_shape() == DisplayServerEnums::CURSOR_HSPLIT);385386// Vertical cursor shape.387split_container->set_vertical(true);388SEND_GUI_MOUSE_MOTION_EVENT(on_dragger, MouseButtonMask::NONE, Key::NONE);389CHECK(DS->get_cursor_shape() == DisplayServerEnums::CURSOR_VSPLIT);390391// Move off, default cursor shape.392SEND_GUI_MOUSE_MOTION_EVENT(not_on_dragger, MouseButtonMask::NONE, Key::NONE);393CHECK(DS->get_cursor_shape() == DisplayServerEnums::CURSOR_ARROW);394395memdelete(child_a);396memdelete(child_b);397memdelete(split_container);398}399400TEST_CASE("[SceneTree][SplitContainer] Two children") {401SplitContainer *split_container = memnew(SplitContainer);402split_container->set_size(Size2(500, 500));403SceneTree::get_singleton()->get_root()->add_child(split_container);404Control *child_a = memnew(Control);405Control *child_b = memnew(Control);406split_container->add_child(child_a);407split_container->add_child(child_b);408MessageQueue::get_singleton()->flush();409410const int sep_constant = split_container->get_theme_constant("separation");411const Size2i sep = Size2i(MAX(sep_constant, split_container->get_theme_icon("h_grabber")->get_width()), MAX(sep_constant, split_container->get_theme_icon("v_grabber")->get_height()));412413SUBCASE("[SplitContainer] Minimum size") {414// Minimum size is the sum of both children's minimum sizes and the separator depending on the vertical axis.415child_a->set_custom_minimum_size(Size2(100, 200));416child_b->set_custom_minimum_size(Size2(100, 200));417MessageQueue::get_singleton()->flush();418419Size2 min_size = split_container->get_minimum_size();420CHECK(min_size.x == 200 + sep.x);421CHECK(min_size.y == 200);422423split_container->set_vertical(true);424MessageQueue::get_singleton()->flush();425min_size = split_container->get_minimum_size();426CHECK(min_size.x == 100);427CHECK(min_size.y == 400 + sep.y);428}429430SUBCASE("[SplitContainer] Default position") {431SUBCASE("[SplitContainer] Vertical") {432// Make sure clamping the split offset doesn't change it or the position.433split_container->set_vertical(true);434435// No expand flags set.436MessageQueue::get_singleton()->flush();437int def_pos = 0;438CHECK_RECTS(get_rects(split_container, def_pos, sep.y, false), get_child_rects(split_container));439split_container->clamp_split_offset();440MessageQueue::get_singleton()->flush();441CHECK(split_container->get_split_offset() == 0);442CHECK_RECTS(get_rects(split_container, def_pos, sep.y, false), get_child_rects(split_container));443444// First expand flags set.445child_a->set_v_size_flags(Control::SIZE_EXPAND_FILL);446child_b->set_v_size_flags(Control::SIZE_FILL);447MessageQueue::get_singleton()->flush();448def_pos = split_container->get_size().y - sep.y;449CHECK_RECTS(get_rects(split_container, def_pos, sep.y, false), get_child_rects(split_container));450split_container->clamp_split_offset();451MessageQueue::get_singleton()->flush();452CHECK(split_container->get_split_offset() == 0);453CHECK_RECTS(get_rects(split_container, def_pos, sep.y, false), get_child_rects(split_container));454455// Second expand flags set.456child_a->set_v_size_flags(Control::SIZE_FILL);457child_b->set_v_size_flags(Control::SIZE_EXPAND_FILL);458MessageQueue::get_singleton()->flush();459def_pos = 0;460CHECK_RECTS(get_rects(split_container, 0, sep.y, false), get_child_rects(split_container));461split_container->clamp_split_offset();462MessageQueue::get_singleton()->flush();463CHECK(split_container->get_split_offset() == 0);464CHECK_RECTS(get_rects(split_container, def_pos, sep.y, false), get_child_rects(split_container));465466// Both expand flags set.467child_a->set_v_size_flags(Control::SIZE_EXPAND_FILL);468child_b->set_v_size_flags(Control::SIZE_EXPAND_FILL);469MessageQueue::get_singleton()->flush();470def_pos = (split_container->get_size().y - sep.y) / 2;471CHECK_RECTS(get_rects(split_container, def_pos, sep.y, false), get_child_rects(split_container));472split_container->clamp_split_offset();473MessageQueue::get_singleton()->flush();474CHECK(split_container->get_split_offset() == 0);475CHECK_RECTS(get_rects(split_container, def_pos, sep.y, false), get_child_rects(split_container));476477// Unequal stretch ratios.478child_a->set_stretch_ratio(2.0);479MessageQueue::get_singleton()->flush();480def_pos = (split_container->get_size().y * 2 / 3) - sep.y / 2;481CHECK_RECTS(get_rects(split_container, def_pos, sep.y, false), get_child_rects(split_container));482split_container->clamp_split_offset();483MessageQueue::get_singleton()->flush();484CHECK(split_container->get_split_offset() == 0);485CHECK_RECTS(get_rects(split_container, def_pos, sep.y, false), get_child_rects(split_container));486}487488SUBCASE("[SplitContainer] Right to left") {489split_container->set_layout_direction(Control::LAYOUT_DIRECTION_RTL);490split_container->set_position(Point2(0, 0));491492// No expand flags set.493MessageQueue::get_singleton()->flush();494int def_pos = 0;495CHECK_RECTS(get_rects_rtl(split_container, def_pos, sep.y), get_child_rects(split_container));496split_container->clamp_split_offset();497MessageQueue::get_singleton()->flush();498CHECK(split_container->get_split_offset() == 0);499CHECK_RECTS(get_rects_rtl(split_container, def_pos, sep.y), get_child_rects(split_container));500501// First expand flags set.502child_a->set_h_size_flags(Control::SIZE_EXPAND_FILL);503child_b->set_h_size_flags(Control::SIZE_FILL);504MessageQueue::get_singleton()->flush();505def_pos = split_container->get_size().y - sep.y;506CHECK_RECTS(get_rects_rtl(split_container, def_pos, sep.y), get_child_rects(split_container));507split_container->clamp_split_offset();508MessageQueue::get_singleton()->flush();509CHECK(split_container->get_split_offset() == 0);510CHECK_RECTS(get_rects_rtl(split_container, def_pos, sep.y), get_child_rects(split_container));511512// Second expand flags set.513child_a->set_h_size_flags(Control::SIZE_FILL);514child_b->set_h_size_flags(Control::SIZE_EXPAND_FILL);515MessageQueue::get_singleton()->flush();516def_pos = 0;517CHECK_RECTS(get_rects_rtl(split_container, def_pos, sep.y), get_child_rects(split_container));518split_container->clamp_split_offset();519MessageQueue::get_singleton()->flush();520CHECK(split_container->get_split_offset() == 0);521CHECK_RECTS(get_rects_rtl(split_container, def_pos, sep.y), get_child_rects(split_container));522523// Both expand flags set.524child_a->set_h_size_flags(Control::SIZE_EXPAND_FILL);525child_b->set_h_size_flags(Control::SIZE_EXPAND_FILL);526MessageQueue::get_singleton()->flush();527def_pos = (split_container->get_size().y - sep.y) / 2;528CHECK_RECTS(get_rects_rtl(split_container, def_pos, sep.y), get_child_rects(split_container));529split_container->clamp_split_offset();530MessageQueue::get_singleton()->flush();531CHECK(split_container->get_split_offset() == 0);532CHECK_RECTS(get_rects_rtl(split_container, def_pos, sep.y), get_child_rects(split_container));533534// Unequal stretch ratios.535child_a->set_stretch_ratio(2.0);536MessageQueue::get_singleton()->flush();537def_pos = (split_container->get_size().y * 2 / 3) - sep.y / 2;538CHECK_RECTS(get_rects_rtl(split_container, def_pos, sep.y), get_child_rects(split_container));539split_container->clamp_split_offset();540MessageQueue::get_singleton()->flush();541CHECK(split_container->get_split_offset() == 0);542CHECK_RECTS(get_rects_rtl(split_container, def_pos, sep.y), get_child_rects(split_container));543}544545SUBCASE("[SplitContainer] No expand flags") {546int def_pos = 0;547548CHECK(split_container->get_split_offset() == 0);549CHECK_RECTS(get_rects(split_container, def_pos, sep.x), get_child_rects(split_container));550551split_container->clamp_split_offset();552MessageQueue::get_singleton()->flush();553CHECK(split_container->get_split_offset() == 0);554CHECK_RECTS(get_rects(split_container, def_pos, sep.x), get_child_rects(split_container));555556// Minimum sizes affect default position.557558// First child with minimum size.559child_a->set_custom_minimum_size(Size2(400, 0));560MessageQueue::get_singleton()->flush();561def_pos = 400;562CHECK_RECTS(get_rects(split_container, def_pos, sep.x), get_child_rects(split_container));563split_container->clamp_split_offset();564MessageQueue::get_singleton()->flush();565CHECK(split_container->get_split_offset() == def_pos);566CHECK_RECTS(get_rects(split_container, def_pos, sep.x), get_child_rects(split_container));567568// Second child with minimum size.569child_a->set_custom_minimum_size(Size2(0, 0));570child_b->set_custom_minimum_size(Size2(400, 0));571MessageQueue::get_singleton()->flush();572def_pos = split_container->get_size().x - 400 - sep.x;573CHECK_RECTS(get_rects(split_container, def_pos, sep.x), get_child_rects(split_container));574split_container->clamp_split_offset();575MessageQueue::get_singleton()->flush();576CHECK(split_container->get_split_offset() == def_pos);577CHECK_RECTS(get_rects(split_container, def_pos, sep.x), get_child_rects(split_container));578579// Both children with minimum size.580child_a->set_custom_minimum_size(Size2(200, 0));581child_b->set_custom_minimum_size(Size2(288, 0));582MessageQueue::get_singleton()->flush();583def_pos = 200;584CHECK_RECTS(get_rects(split_container, def_pos, sep.x), get_child_rects(split_container));585split_container->clamp_split_offset();586MessageQueue::get_singleton()->flush();587CHECK(split_container->get_split_offset() == def_pos);588CHECK_RECTS(get_rects(split_container, def_pos, sep.x), get_child_rects(split_container));589}590591SUBCASE("[SplitContainer] First child expanded") {592const int def_pos = split_container->get_size().x - sep.x;593child_a->set_h_size_flags(Control::SIZE_EXPAND_FILL);594MessageQueue::get_singleton()->flush();595596CHECK_RECTS(get_rects(split_container, def_pos, sep.x), get_child_rects(split_container));597598split_container->clamp_split_offset();599MessageQueue::get_singleton()->flush();600CHECK(split_container->get_split_offset() == 0);601CHECK_RECTS(get_rects(split_container, def_pos, sep.x), get_child_rects(split_container));602603// Minimum sizes affect default position.604605// First child with minimum size.606child_a->set_custom_minimum_size(Size2(400, 0));607MessageQueue::get_singleton()->flush();608CHECK_RECTS(get_rects(split_container, def_pos, sep.x), get_child_rects(split_container));609split_container->clamp_split_offset();610MessageQueue::get_singleton()->flush();611CHECK(split_container->get_split_offset() == 0);612CHECK_RECTS(get_rects(split_container, def_pos, sep.x), get_child_rects(split_container));613614// Second child with minimum size.615child_a->set_custom_minimum_size(Size2(0, 0));616child_b->set_custom_minimum_size(Size2(400, 0));617MessageQueue::get_singleton()->flush();618int pos = split_container->get_size().x - 400 - sep.x;619CHECK_RECTS(get_rects(split_container, pos, sep.x), get_child_rects(split_container));620split_container->clamp_split_offset();621MessageQueue::get_singleton()->flush();622CHECK(split_container->get_split_offset() == pos - def_pos);623CHECK_RECTS(get_rects(split_container, pos, sep.x), get_child_rects(split_container));624625// Both children with minimum size.626child_a->set_custom_minimum_size(Size2(200, 0));627child_b->set_custom_minimum_size(Size2(288, 0));628MessageQueue::get_singleton()->flush();629pos = 200;630CHECK_RECTS(get_rects(split_container, pos, sep.x), get_child_rects(split_container));631split_container->clamp_split_offset();632MessageQueue::get_singleton()->flush();633CHECK(split_container->get_split_offset() == pos - def_pos);634CHECK_RECTS(get_rects(split_container, pos, sep.x), get_child_rects(split_container));635}636637SUBCASE("[SplitContainer] Second child expanded") {638int def_pos = 0;639child_b->set_h_size_flags(Control::SIZE_EXPAND_FILL);640MessageQueue::get_singleton()->flush();641642CHECK_RECTS(get_rects(split_container, def_pos, sep.x), get_child_rects(split_container));643644split_container->clamp_split_offset();645MessageQueue::get_singleton()->flush();646CHECK(split_container->get_split_offset() == 0);647CHECK_RECTS(get_rects(split_container, def_pos, sep.x), get_child_rects(split_container));648649// Minimum sizes affect default position.650651// First child with minimum size.652child_a->set_custom_minimum_size(Size2(400, 0));653MessageQueue::get_singleton()->flush();654def_pos = 400;655CHECK_RECTS(get_rects(split_container, def_pos, sep.x), get_child_rects(split_container));656split_container->clamp_split_offset();657MessageQueue::get_singleton()->flush();658CHECK(split_container->get_split_offset() == def_pos);659CHECK_RECTS(get_rects(split_container, def_pos, sep.x), get_child_rects(split_container));660661// Second child with minimum size.662child_a->set_custom_minimum_size(Size2(0, 0));663child_b->set_custom_minimum_size(Size2(400, 0));664MessageQueue::get_singleton()->flush();665def_pos = 500 - 400 - sep.x;666CHECK_RECTS(get_rects(split_container, def_pos, sep.x), get_child_rects(split_container));667split_container->clamp_split_offset();668MessageQueue::get_singleton()->flush();669CHECK(split_container->get_split_offset() == def_pos);670CHECK_RECTS(get_rects(split_container, def_pos, sep.x), get_child_rects(split_container));671672// Both children with minimum size.673child_a->set_custom_minimum_size(Size2(200, 0));674child_b->set_custom_minimum_size(Size2(288, 0));675MessageQueue::get_singleton()->flush();676def_pos = 200;677CHECK_RECTS(get_rects(split_container, def_pos, sep.x), get_child_rects(split_container));678split_container->clamp_split_offset();679MessageQueue::get_singleton()->flush();680CHECK(split_container->get_split_offset() == def_pos);681CHECK_RECTS(get_rects(split_container, def_pos, sep.x), get_child_rects(split_container));682}683684SUBCASE("[SplitContainer] Both children expanded") {685const int def_pos = (split_container->get_size().x - sep.x) / 2;686child_a->set_h_size_flags(Control::SIZE_EXPAND_FILL);687child_b->set_h_size_flags(Control::SIZE_EXPAND_FILL);688MessageQueue::get_singleton()->flush();689690CHECK_RECTS(get_rects(split_container, def_pos, sep.x), get_child_rects(split_container));691692split_container->clamp_split_offset();693MessageQueue::get_singleton()->flush();694CHECK(split_container->get_split_offset() == 0);695CHECK_RECTS(get_rects(split_container, def_pos, sep.x), get_child_rects(split_container));696697// Minimum sizes affect default position.698699// First child with minimum size.700child_a->set_custom_minimum_size(Size2(400, 0));701MessageQueue::get_singleton()->flush();702int pos = 400;703CHECK_RECTS(get_rects(split_container, pos, sep.x), get_child_rects(split_container));704split_container->clamp_split_offset();705MessageQueue::get_singleton()->flush();706CHECK(split_container->get_split_offset() == pos - def_pos);707CHECK_RECTS(get_rects(split_container, pos, sep.x), get_child_rects(split_container));708709// Second child with minimum size.710child_a->set_custom_minimum_size(Size2(0, 0));711child_b->set_custom_minimum_size(Size2(400, 0));712MessageQueue::get_singleton()->flush();713pos = split_container->get_size().x - 400 - sep.x;714CHECK_RECTS(get_rects(split_container, pos, sep.x), get_child_rects(split_container));715split_container->clamp_split_offset();716MessageQueue::get_singleton()->flush();717CHECK(split_container->get_split_offset() == pos - def_pos);718CHECK_RECTS(get_rects(split_container, pos, sep.x), get_child_rects(split_container));719720// Both children with minimum size.721child_a->set_custom_minimum_size(Size2(200, 0));722child_b->set_custom_minimum_size(Size2(288, 0));723MessageQueue::get_singleton()->flush();724pos = 200;725CHECK_RECTS(get_rects(split_container, pos, sep.x), get_child_rects(split_container));726split_container->clamp_split_offset();727MessageQueue::get_singleton()->flush();728CHECK(split_container->get_split_offset() == pos - def_pos);729CHECK_RECTS(get_rects(split_container, pos, sep.x), get_child_rects(split_container));730}731732SUBCASE("[SplitContainer] Unequal stretch ratios") {733const int def_pos = (split_container->get_size().x * 2 / 3) - sep.x / 2;734child_a->set_h_size_flags(Control::SIZE_EXPAND_FILL);735child_b->set_h_size_flags(Control::SIZE_EXPAND_FILL);736child_a->set_stretch_ratio(2.0);737MessageQueue::get_singleton()->flush();738739CHECK_RECTS(get_rects(split_container, def_pos, sep.x), get_child_rects(split_container));740741split_container->clamp_split_offset();742MessageQueue::get_singleton()->flush();743CHECK(split_container->get_split_offset() == 0);744CHECK_RECTS(get_rects(split_container, def_pos, sep.x), get_child_rects(split_container));745746// Minimum sizes affect default position.747748// First child with minimum size.749child_a->set_custom_minimum_size(Size2(400, 0));750MessageQueue::get_singleton()->flush();751int pos = 400;752CHECK_RECTS(get_rects(split_container, pos, sep.x), get_child_rects(split_container));753split_container->clamp_split_offset();754MessageQueue::get_singleton()->flush();755CHECK(split_container->get_split_offset() == pos - def_pos);756CHECK_RECTS(get_rects(split_container, pos, sep.x), get_child_rects(split_container));757758// Second child with minimum size.759child_a->set_custom_minimum_size(Size2(0, 0));760child_b->set_custom_minimum_size(Size2(400, 0));761MessageQueue::get_singleton()->flush();762pos = split_container->get_size().x - 400 - sep.x;763CHECK_RECTS(get_rects(split_container, pos, sep.x), get_child_rects(split_container));764split_container->clamp_split_offset();765MessageQueue::get_singleton()->flush();766CHECK(split_container->get_split_offset() == pos - def_pos);767CHECK_RECTS(get_rects(split_container, pos, sep.x), get_child_rects(split_container));768769// Both children with minimum size.770child_a->set_custom_minimum_size(Size2(200, 0));771child_b->set_custom_minimum_size(Size2(288, 0));772MessageQueue::get_singleton()->flush();773pos = 200;774CHECK_RECTS(get_rects(split_container, pos, sep.x), get_child_rects(split_container));775split_container->clamp_split_offset();776MessageQueue::get_singleton()->flush();777CHECK(split_container->get_split_offset() == pos - def_pos);778CHECK_RECTS(get_rects(split_container, pos, sep.x), get_child_rects(split_container));779}780}781782SUBCASE("[SplitContainer] Set split offset") {783SUBCASE("[SplitContainer] Right to left") {784split_container->set_layout_direction(Control::LAYOUT_DIRECTION_RTL);785split_container->set_position(Point2(0, 0));786int def_pos = 0;787// Positive.788split_container->set_split_offset(10);789MessageQueue::get_singleton()->flush();790CHECK(split_container->get_split_offset() == 10);791CHECK_RECTS(get_rects_rtl(split_container, def_pos + 10, sep.y), get_child_rects(split_container));792793// Negative.794split_container->set_split_offset(-10);795MessageQueue::get_singleton()->flush();796CHECK(split_container->get_split_offset() == -10);797CHECK_RECTS(get_rects_rtl(split_container, def_pos, sep.y), get_child_rects(split_container));798}799800SUBCASE("[SplitContainer] No expand flags") {801int def_pos = 0;802803// Positive.804split_container->set_split_offset(10);805MessageQueue::get_singleton()->flush();806CHECK(split_container->get_split_offset() == 10);807CHECK_RECTS(get_rects(split_container, def_pos + 10, sep.x), get_child_rects(split_container));808809// Negative.810split_container->set_split_offset(-10);811MessageQueue::get_singleton()->flush();812CHECK(split_container->get_split_offset() == -10);813CHECK_RECTS(get_rects(split_container, def_pos, sep.x), get_child_rects(split_container));814815// Clamped.816split_container->set_split_offset(1000);817MessageQueue::get_singleton()->flush();818CHECK(split_container->get_split_offset() == 1000);819CHECK_RECTS(get_rects(split_container, split_container->get_size().x - sep.x, sep.x), get_child_rects(split_container));820}821822SUBCASE("[SplitContainer] First child expanded") {823int def_pos = split_container->get_size().x - sep.x;824child_a->set_h_size_flags(Control::SIZE_EXPAND_FILL);825MessageQueue::get_singleton()->flush();826827// Positive.828split_container->set_split_offset(10);829MessageQueue::get_singleton()->flush();830CHECK(split_container->get_split_offset() == 10);831CHECK_RECTS(get_rects(split_container, def_pos, sep.x), get_child_rects(split_container));832833// Negative.834split_container->set_split_offset(-10);835MessageQueue::get_singleton()->flush();836CHECK(split_container->get_split_offset() == -10);837CHECK_RECTS(get_rects(split_container, def_pos - 10, sep.x), get_child_rects(split_container));838839// Clamped.840split_container->set_split_offset(-1000);841MessageQueue::get_singleton()->flush();842CHECK(split_container->get_split_offset() == -1000);843CHECK_RECTS(get_rects(split_container, 0, sep.x), get_child_rects(split_container));844}845846SUBCASE("[SplitContainer] Second child expanded") {847int def_pos = 0;848child_b->set_h_size_flags(Control::SIZE_EXPAND_FILL);849MessageQueue::get_singleton()->flush();850851// Positive.852split_container->set_split_offset(10);853MessageQueue::get_singleton()->flush();854CHECK(split_container->get_split_offset() == 10);855CHECK_RECTS(get_rects(split_container, def_pos + 10, sep.x), get_child_rects(split_container));856857// Negative.858split_container->set_split_offset(-10);859MessageQueue::get_singleton()->flush();860CHECK(split_container->get_split_offset() == -10);861CHECK_RECTS(get_rects(split_container, def_pos, sep.x), get_child_rects(split_container));862863// Clamped.864split_container->set_split_offset(1000);865MessageQueue::get_singleton()->flush();866CHECK(split_container->get_split_offset() == 1000);867CHECK_RECTS(get_rects(split_container, split_container->get_size().x - sep.x, sep.x), get_child_rects(split_container));868}869870SUBCASE("[SplitContainer] Both children expanded") {871int def_pos = (split_container->get_size().x - sep.x) / 2;872child_a->set_h_size_flags(Control::SIZE_EXPAND_FILL);873child_b->set_h_size_flags(Control::SIZE_EXPAND_FILL);874MessageQueue::get_singleton()->flush();875876// Positive.877split_container->set_split_offset(10);878MessageQueue::get_singleton()->flush();879CHECK(split_container->get_split_offset() == 10);880CHECK_RECTS(get_rects(split_container, def_pos + 10, sep.x), get_child_rects(split_container));881882// Negative.883split_container->set_split_offset(-10);884MessageQueue::get_singleton()->flush();885CHECK(split_container->get_split_offset() == -10);886CHECK_RECTS(get_rects(split_container, def_pos - 10, sep.x), get_child_rects(split_container));887888// Clamped positive.889split_container->set_split_offset(1000);890MessageQueue::get_singleton()->flush();891CHECK(split_container->get_split_offset() == 1000);892CHECK_RECTS(get_rects(split_container, split_container->get_size().x - sep.x, sep.x), get_child_rects(split_container));893894// Clamped negative.895split_container->set_split_offset(-1000);896MessageQueue::get_singleton()->flush();897CHECK(split_container->get_split_offset() == -1000);898CHECK_RECTS(get_rects(split_container, 0, sep.x), get_child_rects(split_container));899}900901SUBCASE("[SplitContainer] Unequal stretch ratios") {902int def_pos = (split_container->get_size().x * 2 / 3) - sep.x / 2;903child_a->set_h_size_flags(Control::SIZE_EXPAND_FILL);904child_b->set_h_size_flags(Control::SIZE_EXPAND_FILL);905child_a->set_stretch_ratio(2.0);906MessageQueue::get_singleton()->flush();907908// Positive.909split_container->set_split_offset(10);910MessageQueue::get_singleton()->flush();911CHECK(split_container->get_split_offset() == 10);912CHECK_RECTS(get_rects(split_container, def_pos + 10, sep.x), get_child_rects(split_container));913914// Negative.915split_container->set_split_offset(-10);916MessageQueue::get_singleton()->flush();917CHECK(split_container->get_split_offset() == -10);918CHECK_RECTS(get_rects(split_container, def_pos - 10, sep.x), get_child_rects(split_container));919920// Clamped positive.921split_container->set_split_offset(1000);922MessageQueue::get_singleton()->flush();923CHECK(split_container->get_split_offset() == 1000);924CHECK_RECTS(get_rects(split_container, split_container->get_size().x - sep.x, sep.x), get_child_rects(split_container));925926// Clamped negative.927split_container->set_split_offset(-1000);928MessageQueue::get_singleton()->flush();929CHECK(split_container->get_split_offset() == -1000);930CHECK_RECTS(get_rects(split_container, 0, sep.x), get_child_rects(split_container));931}932}933934SUBCASE("[SplitContainer] Keep split offset when changing minimum size") {935SUBCASE("[SplitContainer] No expand flags") {936int def_pos = 0;937938split_container->set_split_offset(100);939child_a->set_custom_minimum_size(Size2(10, 0));940MessageQueue::get_singleton()->flush();941CHECK(split_container->get_split_offset() == 100);942CHECK_RECTS(get_rects(split_container, def_pos + 100, sep.x), get_child_rects(split_container));943944child_a->set_custom_minimum_size(Size2(50, 0));945MessageQueue::get_singleton()->flush();946CHECK(split_container->get_split_offset() == 100);947CHECK_RECTS(get_rects(split_container, def_pos + 100, sep.x), get_child_rects(split_container));948}949950SUBCASE("[SplitContainer] First child expanded") {951int def_pos = split_container->get_size().x - sep.x;952child_a->set_h_size_flags(Control::SIZE_EXPAND_FILL);953MessageQueue::get_singleton()->flush();954955split_container->set_split_offset(-100);956child_b->set_custom_minimum_size(Size2(10, 0));957MessageQueue::get_singleton()->flush();958CHECK(split_container->get_split_offset() == -100);959CHECK_RECTS(get_rects(split_container, def_pos - 100, sep.x), get_child_rects(split_container));960961child_b->set_custom_minimum_size(Size2(50, 0));962MessageQueue::get_singleton()->flush();963CHECK(split_container->get_split_offset() == -100);964CHECK_RECTS(get_rects(split_container, def_pos - 100, sep.x), get_child_rects(split_container));965}966967SUBCASE("[SplitContainer] Second child expanded") {968int def_pos = 0;969child_b->set_h_size_flags(Control::SIZE_EXPAND_FILL);970MessageQueue::get_singleton()->flush();971972split_container->set_split_offset(100);973child_a->set_custom_minimum_size(Size2(10, 0));974MessageQueue::get_singleton()->flush();975CHECK(split_container->get_split_offset() == 100);976CHECK_RECTS(get_rects(split_container, def_pos + 100, sep.x), get_child_rects(split_container));977978child_a->set_custom_minimum_size(Size2(50, 0));979MessageQueue::get_singleton()->flush();980CHECK(split_container->get_split_offset() == 100);981CHECK_RECTS(get_rects(split_container, def_pos + 100, sep.x), get_child_rects(split_container));982}983984SUBCASE("[SplitContainer] Both children expanded") {985int def_pos = (split_container->get_size().x - sep.x) / 2;986child_a->set_h_size_flags(Control::SIZE_EXPAND_FILL);987child_b->set_h_size_flags(Control::SIZE_EXPAND_FILL);988MessageQueue::get_singleton()->flush();989990split_container->set_split_offset(20);991child_a->set_custom_minimum_size(Size2(10, 0));992child_b->set_custom_minimum_size(Size2(10, 0));993MessageQueue::get_singleton()->flush();994CHECK(split_container->get_split_offset() == 20);995CHECK_RECTS(get_rects(split_container, def_pos + 20, sep.x), get_child_rects(split_container));996997child_a->set_custom_minimum_size(Size2(50, 0));998child_b->set_custom_minimum_size(Size2(50, 0));999MessageQueue::get_singleton()->flush();1000CHECK(split_container->get_split_offset() == 20);1001CHECK_RECTS(get_rects(split_container, def_pos + 20, sep.x), get_child_rects(split_container));1002}1003}10041005SUBCASE("[SplitContainer] Keep split offset when changing visibility") {1006SUBCASE("[SplitContainer] No expand flags") {1007int def_pos = 0;1008split_container->set_split_offset(100);10091010child_a->hide();1011MessageQueue::get_singleton()->flush();1012CHECK(split_container->get_split_offset() == 100);1013CHECK_RECTS(get_rects_multi(split_container, Vector<int>(), sep.x), get_child_rects(split_container));10141015child_b->hide();1016MessageQueue::get_singleton()->flush();1017CHECK(split_container->get_split_offset() == 100);10181019child_a->show();1020MessageQueue::get_singleton()->flush();1021CHECK(split_container->get_split_offset() == 100);1022CHECK_RECTS(get_rects_multi(split_container, Vector<int>(), sep.x), get_child_rects(split_container));10231024child_b->show();1025MessageQueue::get_singleton()->flush();1026CHECK(split_container->get_split_offset() == 100);1027CHECK_RECTS(get_rects(split_container, def_pos + 100, sep.x), get_child_rects(split_container));1028}10291030SUBCASE("[SplitContainer] First child expanded") {1031int def_pos = split_container->get_size().x - sep.x;1032child_a->set_h_size_flags(Control::SIZE_EXPAND_FILL);1033MessageQueue::get_singleton()->flush();1034split_container->set_split_offset(-100);10351036child_a->hide();1037MessageQueue::get_singleton()->flush();1038CHECK(split_container->get_split_offset() == -100);1039CHECK_RECTS(get_rects_multi(split_container, Vector<int>(), sep.x), get_child_rects(split_container));10401041child_b->hide();1042MessageQueue::get_singleton()->flush();1043CHECK(split_container->get_split_offset() == -100);10441045child_a->show();1046MessageQueue::get_singleton()->flush();1047CHECK(split_container->get_split_offset() == -100);1048CHECK_RECTS(get_rects_multi(split_container, Vector<int>(), sep.x), get_child_rects(split_container));10491050child_b->show();1051MessageQueue::get_singleton()->flush();1052CHECK(split_container->get_split_offset() == -100);1053CHECK_RECTS(get_rects(split_container, def_pos - 100, sep.x), get_child_rects(split_container));1054}10551056SUBCASE("[SplitContainer] Second child expanded") {1057int def_pos = 0;1058child_b->set_h_size_flags(Control::SIZE_EXPAND_FILL);1059MessageQueue::get_singleton()->flush();1060split_container->set_split_offset(100);10611062child_a->hide();1063MessageQueue::get_singleton()->flush();1064CHECK(split_container->get_split_offset() == 100);1065CHECK_RECTS(get_rects_multi(split_container, Vector<int>(), sep.x), get_child_rects(split_container));10661067child_b->hide();1068MessageQueue::get_singleton()->flush();1069CHECK(split_container->get_split_offset() == 100);10701071child_a->show();1072MessageQueue::get_singleton()->flush();1073CHECK(split_container->get_split_offset() == 100);1074CHECK_RECTS(get_rects_multi(split_container, Vector<int>(), sep.x), get_child_rects(split_container));10751076child_b->show();1077MessageQueue::get_singleton()->flush();1078CHECK(split_container->get_split_offset() == 100);1079CHECK_RECTS(get_rects(split_container, def_pos + 100, sep.x), get_child_rects(split_container));1080}10811082SUBCASE("[SplitContainer] Both children expanded") {1083int def_pos = (split_container->get_size().x - sep.x) / 2;1084child_a->set_h_size_flags(Control::SIZE_EXPAND_FILL);1085child_b->set_h_size_flags(Control::SIZE_EXPAND_FILL);1086MessageQueue::get_singleton()->flush();1087split_container->set_split_offset(20);10881089child_a->hide();1090MessageQueue::get_singleton()->flush();1091CHECK(split_container->get_split_offset() == 20);1092CHECK_RECTS(get_rects_multi(split_container, Vector<int>(), sep.x), get_child_rects(split_container));10931094child_b->hide();1095MessageQueue::get_singleton()->flush();1096CHECK(split_container->get_split_offset() == 20);10971098child_a->show();1099MessageQueue::get_singleton()->flush();1100CHECK(split_container->get_split_offset() == 20);1101CHECK_RECTS(get_rects_multi(split_container, Vector<int>(), sep.x), get_child_rects(split_container));11021103child_b->show();1104MessageQueue::get_singleton()->flush();1105CHECK(split_container->get_split_offset() == 20);1106CHECK_RECTS(get_rects(split_container, def_pos + 20, sep.x), get_child_rects(split_container));1107}1108}11091110SUBCASE("[SplitContainer] Keep split offset when removing children") {1111SUBCASE("[SplitContainer] No expand flags") {1112int def_pos = 0;1113split_container->set_split_offset(100);11141115split_container->remove_child(child_a);1116MessageQueue::get_singleton()->flush();1117CHECK(split_container->get_split_offset() == 100);1118CHECK_RECTS(get_rects_multi(split_container, Vector<int>(), sep.x), get_child_rects(split_container));11191120split_container->remove_child(child_b);1121MessageQueue::get_singleton()->flush();1122CHECK(split_container->get_split_offset() == 100);11231124split_container->add_child(child_a);1125MessageQueue::get_singleton()->flush();1126CHECK(split_container->get_split_offset() == 100);1127CHECK_RECTS(get_rects_multi(split_container, Vector<int>(), sep.x), get_child_rects(split_container));11281129split_container->add_child(child_b);1130MessageQueue::get_singleton()->flush();1131CHECK(split_container->get_split_offset() == 100);1132CHECK_RECTS(get_rects(split_container, def_pos + 100, sep.x), get_child_rects(split_container));1133}11341135SUBCASE("[SplitContainer] First child expanded") {1136int def_pos = split_container->get_size().x - sep.x;1137child_a->set_h_size_flags(Control::SIZE_EXPAND_FILL);1138MessageQueue::get_singleton()->flush();1139split_container->set_split_offset(-100);11401141split_container->remove_child(child_a);1142MessageQueue::get_singleton()->flush();1143CHECK(split_container->get_split_offset() == -100);1144CHECK_RECTS(get_rects_multi(split_container, Vector<int>(), sep.x), get_child_rects(split_container));11451146split_container->remove_child(child_b);1147MessageQueue::get_singleton()->flush();1148CHECK(split_container->get_split_offset() == -100);11491150split_container->add_child(child_a);1151MessageQueue::get_singleton()->flush();1152CHECK(split_container->get_split_offset() == -100);1153CHECK_RECTS(get_rects_multi(split_container, Vector<int>(), sep.x), get_child_rects(split_container));11541155split_container->add_child(child_b);1156MessageQueue::get_singleton()->flush();1157CHECK(split_container->get_split_offset() == -100);1158CHECK_RECTS(get_rects(split_container, def_pos - 100, sep.x), get_child_rects(split_container));1159}11601161SUBCASE("[SplitContainer] Second child expanded") {1162int def_pos = 0;1163child_b->set_h_size_flags(Control::SIZE_EXPAND_FILL);1164MessageQueue::get_singleton()->flush();1165split_container->set_split_offset(100);11661167split_container->remove_child(child_a);1168MessageQueue::get_singleton()->flush();1169CHECK(split_container->get_split_offset() == 100);1170CHECK_RECTS(get_rects_multi(split_container, Vector<int>(), sep.x), get_child_rects(split_container));11711172split_container->remove_child(child_b);1173MessageQueue::get_singleton()->flush();1174CHECK(split_container->get_split_offset() == 100);11751176split_container->add_child(child_a);1177MessageQueue::get_singleton()->flush();1178CHECK(split_container->get_split_offset() == 100);1179CHECK_RECTS(get_rects_multi(split_container, Vector<int>(), sep.x), get_child_rects(split_container));11801181split_container->add_child(child_b);1182MessageQueue::get_singleton()->flush();1183CHECK(split_container->get_split_offset() == 100);1184CHECK_RECTS(get_rects(split_container, def_pos + 100, sep.x), get_child_rects(split_container));1185}11861187SUBCASE("[SplitContainer] Both children expanded") {1188int def_pos = (split_container->get_size().x - sep.x) / 2;1189child_a->set_h_size_flags(Control::SIZE_EXPAND_FILL);1190child_b->set_h_size_flags(Control::SIZE_EXPAND_FILL);1191MessageQueue::get_singleton()->flush();1192split_container->set_split_offset(20);11931194split_container->remove_child(child_a);1195MessageQueue::get_singleton()->flush();1196CHECK(split_container->get_split_offset() == 20);1197CHECK_RECTS(get_rects_multi(split_container, Vector<int>(), sep.x), get_child_rects(split_container));11981199split_container->remove_child(child_b);1200MessageQueue::get_singleton()->flush();1201CHECK(split_container->get_split_offset() == 20);12021203split_container->add_child(child_a);1204MessageQueue::get_singleton()->flush();1205CHECK(split_container->get_split_offset() == 20);1206CHECK_RECTS(get_rects_multi(split_container, Vector<int>(), sep.x), get_child_rects(split_container));12071208split_container->add_child(child_b);1209MessageQueue::get_singleton()->flush();1210CHECK(split_container->get_split_offset() == 20);1211CHECK_RECTS(get_rects(split_container, def_pos + 20, sep.x), get_child_rects(split_container));1212}1213}12141215SUBCASE("[SplitContainer] Keep split offset when changing expand flags") {1216int def_pos = 0;1217split_container->set_split_offset(20);1218MessageQueue::get_singleton()->flush();1219CHECK(split_container->get_split_offset() == 20);1220CHECK_RECTS(get_rects(split_container, def_pos + 20, sep.x), get_child_rects(split_container));12211222child_a->set_h_size_flags(Control::SIZE_EXPAND_FILL);1223def_pos = split_container->get_size().x - sep.x;1224MessageQueue::get_singleton()->flush();1225CHECK(split_container->get_split_offset() == 20);1226CHECK_RECTS(get_rects(split_container, def_pos, sep.x), get_child_rects(split_container));12271228child_a->set_h_size_flags(Control::SIZE_FILL);1229child_b->set_h_size_flags(Control::SIZE_EXPAND_FILL);1230def_pos = 0;1231MessageQueue::get_singleton()->flush();1232CHECK(split_container->get_split_offset() == 20);1233CHECK_RECTS(get_rects(split_container, def_pos + 20, sep.x), get_child_rects(split_container));12341235child_a->set_h_size_flags(Control::SIZE_EXPAND_FILL);1236child_b->set_h_size_flags(Control::SIZE_EXPAND_FILL);1237def_pos = (split_container->get_size().x - sep.x) / 2;1238MessageQueue::get_singleton()->flush();1239CHECK(split_container->get_split_offset() == 20);1240CHECK_RECTS(get_rects(split_container, def_pos + 20, sep.x), get_child_rects(split_container));12411242child_a->set_h_size_flags(Control::SIZE_FILL);1243child_b->set_h_size_flags(Control::SIZE_FILL);1244def_pos = 0;1245MessageQueue::get_singleton()->flush();1246CHECK(split_container->get_split_offset() == 20);1247CHECK_RECTS(get_rects(split_container, def_pos + 20, sep.x), get_child_rects(split_container));1248}12491250SUBCASE("[SplitContainer] Keep split offset when moving children") {1251int def_pos = 0;1252split_container->set_split_offset(100);12531254split_container->move_child(child_a, 1);1255MessageQueue::get_singleton()->flush();1256CHECK(split_container->get_split_offset() == 100);1257CHECK_RECTS(get_rects(split_container, def_pos + 100, sep.x), get_child_rects(split_container));1258}12591260SUBCASE("[SplitContainer] Resize split container") {1261SUBCASE("[SplitContainer] No expand flags") {1262int def_pos = 0;1263// Increase the size.1264split_container->set_size(Size2(600, 500));1265MessageQueue::get_singleton()->flush();1266CHECK_RECTS(get_rects(split_container, def_pos, sep.x), get_child_rects(split_container));12671268// Decrease the size.1269split_container->set_size(Size2(400, 500));1270MessageQueue::get_singleton()->flush();1271CHECK_RECTS(get_rects(split_container, def_pos, sep.x), get_child_rects(split_container));12721273// Change size with a split offset.1274split_container->set_split_offset(100);1275MessageQueue::get_singleton()->flush();1276CHECK_RECTS(get_rects(split_container, def_pos + 100, sep.x), get_child_rects(split_container));12771278split_container->set_size(Size2(500, 500));1279MessageQueue::get_singleton()->flush();1280CHECK_RECTS(get_rects(split_container, def_pos + 100, sep.x), get_child_rects(split_container));1281CHECK(split_container->get_split_offset() == 100);12821283// Change size so that the first child changes size.1284split_container->set_size(Size2(80, 500));1285MessageQueue::get_singleton()->flush();1286CHECK_RECTS(get_rects(split_container, 80 - sep.x, sep.x), get_child_rects(split_container));1287CHECK(split_container->get_split_offset() == 100);12881289// Increase size again.1290split_container->set_size(Size2(500, 500));1291MessageQueue::get_singleton()->flush();1292CHECK_RECTS(get_rects(split_container, def_pos + 100, sep.x), get_child_rects(split_container));1293CHECK(split_container->get_split_offset() == 100);1294}12951296SUBCASE("[SplitContainer] First child expanded") {1297int def_pos = split_container->get_size().x - sep.x;1298child_a->set_h_size_flags(Control::SIZE_EXPAND_FILL);1299MessageQueue::get_singleton()->flush();13001301// Increase the size.1302split_container->set_size(Size2(600, 500));1303def_pos = split_container->get_size().x - sep.x;1304MessageQueue::get_singleton()->flush();1305CHECK_RECTS(get_rects(split_container, def_pos, sep.x), get_child_rects(split_container));13061307// Decrease the size.1308split_container->set_size(Size2(400, 500));1309def_pos = split_container->get_size().x - sep.x;1310MessageQueue::get_singleton()->flush();1311CHECK_RECTS(get_rects(split_container, def_pos, sep.x), get_child_rects(split_container));13121313// Change size with a split offset.1314split_container->set_split_offset(-100);1315MessageQueue::get_singleton()->flush();1316CHECK_RECTS(get_rects(split_container, def_pos - 100, sep.x), get_child_rects(split_container));13171318split_container->set_size(Size2(500, 500));1319def_pos = split_container->get_size().x - sep.x;1320MessageQueue::get_singleton()->flush();1321CHECK_RECTS(get_rects(split_container, def_pos - 100, sep.x), get_child_rects(split_container));1322CHECK(split_container->get_split_offset() == -100);13231324// Change size so that the second child changes size.1325split_container->set_size(Size2(80, 500));1326MessageQueue::get_singleton()->flush();1327CHECK_RECTS(get_rects(split_container, 0, sep.x), get_child_rects(split_container));1328CHECK(split_container->get_split_offset() == -100);13291330// Increase size again.1331split_container->set_size(Size2(500, 500));1332MessageQueue::get_singleton()->flush();1333CHECK_RECTS(get_rects(split_container, def_pos - 100, sep.x), get_child_rects(split_container));1334CHECK(split_container->get_split_offset() == -100);1335}13361337SUBCASE("[SplitContainer] Second child expanded") {1338int def_pos = 0;1339child_b->set_h_size_flags(Control::SIZE_EXPAND_FILL);1340MessageQueue::get_singleton()->flush();13411342// Increase the size.1343split_container->set_size(Size2(600, 500));1344MessageQueue::get_singleton()->flush();1345CHECK_RECTS(get_rects(split_container, def_pos, sep.x), get_child_rects(split_container));13461347// Decrease the size.1348split_container->set_size(Size2(400, 500));1349MessageQueue::get_singleton()->flush();1350CHECK_RECTS(get_rects(split_container, def_pos, sep.x), get_child_rects(split_container));13511352// Change size with a split offset.1353split_container->set_split_offset(100);1354MessageQueue::get_singleton()->flush();1355CHECK_RECTS(get_rects(split_container, def_pos + 100, sep.x), get_child_rects(split_container));13561357split_container->set_size(Size2(500, 500));1358MessageQueue::get_singleton()->flush();1359CHECK_RECTS(get_rects(split_container, def_pos + 100, sep.x), get_child_rects(split_container));1360CHECK(split_container->get_split_offset() == 100);13611362// Change size so that the first child changes size.1363split_container->set_size(Size2(80, 500));1364MessageQueue::get_singleton()->flush();1365CHECK_RECTS(get_rects(split_container, 80 - sep.x, sep.x), get_child_rects(split_container));1366CHECK(split_container->get_split_offset() == 100);13671368// Increase size again.1369split_container->set_size(Size2(500, 500));1370MessageQueue::get_singleton()->flush();1371CHECK_RECTS(get_rects(split_container, def_pos + 100, sep.x), get_child_rects(split_container));1372CHECK(split_container->get_split_offset() == 100);1373}13741375SUBCASE("[SplitContainer] Both children expanded") {1376int def_pos = (split_container->get_size().x - sep.x) / 2;1377child_a->set_h_size_flags(Control::SIZE_EXPAND_FILL);1378child_b->set_h_size_flags(Control::SIZE_EXPAND_FILL);1379MessageQueue::get_singleton()->flush();13801381// Increase the size.1382split_container->set_size(Size2(600, 500));1383def_pos = (split_container->get_size().x - sep.x) / 2;1384MessageQueue::get_singleton()->flush();1385CHECK_RECTS(get_rects(split_container, def_pos, sep.x), get_child_rects(split_container));13861387// Decrease the size.1388split_container->set_size(Size2(400, 500));1389def_pos = (split_container->get_size().x - sep.x) / 2;1390MessageQueue::get_singleton()->flush();1391CHECK_RECTS(get_rects(split_container, def_pos, sep.x), get_child_rects(split_container));13921393// Change size with a split offset.1394split_container->set_split_offset(100);1395MessageQueue::get_singleton()->flush();1396CHECK_RECTS(get_rects(split_container, def_pos + 100, sep.x), get_child_rects(split_container));13971398split_container->set_size(Size2(500, 500));1399def_pos = (split_container->get_size().x - sep.x) / 2;1400MessageQueue::get_singleton()->flush();1401CHECK_RECTS(get_rects(split_container, def_pos + 100, sep.x), get_child_rects(split_container));1402CHECK(split_container->get_split_offset() == 100);14031404// Change size so that the second child is minimized.1405split_container->set_size(Size2(80, 500));1406MessageQueue::get_singleton()->flush();1407CHECK_RECTS(get_rects(split_container, 80 - sep.x, sep.x), get_child_rects(split_container));1408CHECK(split_container->get_split_offset() == 100);14091410// Increase size again.1411split_container->set_size(Size2(500, 500));1412def_pos = (split_container->get_size().x - sep.x) / 2;1413MessageQueue::get_singleton()->flush();1414CHECK_RECTS(get_rects(split_container, def_pos + 100, sep.x), get_child_rects(split_container));1415CHECK(split_container->get_split_offset() == 100);1416}14171418SUBCASE("[SplitContainer] Unequal stretch ratios") {1419int def_pos = (split_container->get_size().x * 2 / 3) - sep.x / 2;1420child_a->set_h_size_flags(Control::SIZE_EXPAND_FILL);1421child_b->set_h_size_flags(Control::SIZE_EXPAND_FILL);1422child_a->set_stretch_ratio(2.0);1423MessageQueue::get_singleton()->flush();14241425// Increase the size.1426split_container->set_size(Size2(600, 500));1427def_pos = (split_container->get_size().x * 2 / 3) - sep.x / 2;1428MessageQueue::get_singleton()->flush();1429CHECK_RECTS(get_rects(split_container, def_pos, sep.x), get_child_rects(split_container));14301431// Decrease the size.1432split_container->set_size(Size2(400, 500));1433def_pos = (split_container->get_size().x * 2 / 3) - sep.x / 2;1434MessageQueue::get_singleton()->flush();1435CHECK_RECTS(get_rects(split_container, def_pos, sep.x), get_child_rects(split_container));14361437// Change size with a split offset.1438split_container->set_split_offset(100);1439MessageQueue::get_singleton()->flush();1440CHECK_RECTS(get_rects(split_container, def_pos + 100, sep.x), get_child_rects(split_container));14411442split_container->set_size(Size2(500, 500));1443def_pos = (split_container->get_size().x * 2 / 3) - sep.x / 2;1444MessageQueue::get_singleton()->flush();1445CHECK_RECTS(get_rects(split_container, def_pos + 100, sep.x), get_child_rects(split_container));1446CHECK(split_container->get_split_offset() == 100);14471448// Change size so that the second child is minimized.1449split_container->set_size(Size2(80, 500));1450MessageQueue::get_singleton()->flush();1451CHECK_RECTS(get_rects(split_container, 80 - sep.x, sep.x), get_child_rects(split_container));1452CHECK(split_container->get_split_offset() == 100);14531454// Increase size again.1455split_container->set_size(Size2(500, 500));1456def_pos = (split_container->get_size().x * 2 / 3) - sep.x / 2;1457MessageQueue::get_singleton()->flush();1458CHECK_RECTS(get_rects(split_container, def_pos + 100, sep.x), get_child_rects(split_container));1459CHECK(split_container->get_split_offset() == 100);1460}1461}14621463SUBCASE("[SplitContainer] Drag") {1464SUBCASE("[SplitContainer] Vertical, no expand flags") {1465SIGNAL_WATCH(split_container, "dragged");1466Array signal_args = { { 0 } };14671468split_container->set_vertical(true);1469Point2 mouse_offset = Point2(1, 1);1470int dragger_pos = 0;1471int split_dragger_ofs = 0;14721473// Grab the dragger.1474SEND_GUI_MOUSE_BUTTON_EVENT(mouse_offset + Point2(0, dragger_pos), MouseButton::LEFT, MouseButtonMask::LEFT, Key::NONE);1475MessageQueue::get_singleton()->flush();1476CHECK_RECTS(get_rects(split_container, dragger_pos, sep.y, false), get_child_rects(split_container));1477CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs);1478SIGNAL_CHECK_FALSE("dragged");14791480// Move the dragger.1481dragger_pos = 10;1482SEND_GUI_MOUSE_MOTION_EVENT(mouse_offset + Point2(0, dragger_pos), MouseButtonMask::LEFT, Key::NONE);1483MessageQueue::get_singleton()->flush();1484CHECK_RECTS(get_rects(split_container, dragger_pos, sep.y, false), get_child_rects(split_container));1485CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs);1486// It is clamped.1487split_container->clamp_split_offset();1488CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs);1489((Array)signal_args[0])[0] = split_container->get_split_offset();1490SIGNAL_CHECK("dragged", signal_args);14911492// Move down.1493dragger_pos = 400;1494SEND_GUI_MOUSE_MOTION_EVENT(mouse_offset + Point2(0, dragger_pos), MouseButtonMask::LEFT, Key::NONE);1495MessageQueue::get_singleton()->flush();1496CHECK_RECTS(get_rects(split_container, dragger_pos, sep.y, false), get_child_rects(split_container));1497CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs);1498((Array)signal_args[0])[0] = split_container->get_split_offset();1499SIGNAL_CHECK("dragged", signal_args);15001501// Moves even when mouse is outside.1502dragger_pos = split_container->get_size().y - sep.y;1503SEND_GUI_MOUSE_MOTION_EVENT(mouse_offset + Point2(0, 1000), MouseButtonMask::LEFT, Key::NONE);1504MessageQueue::get_singleton()->flush();1505CHECK_RECTS(get_rects(split_container, dragger_pos, sep.y, false), get_child_rects(split_container));1506CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs);1507((Array)signal_args[0])[0] = split_container->get_split_offset();1508SIGNAL_CHECK("dragged", signal_args);15091510// Move up.1511dragger_pos = 100;1512SEND_GUI_MOUSE_MOTION_EVENT(mouse_offset + Point2(0, dragger_pos), MouseButtonMask::LEFT, Key::NONE);1513MessageQueue::get_singleton()->flush();1514CHECK_RECTS(get_rects(split_container, dragger_pos, sep.y, false), get_child_rects(split_container));1515CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs);1516((Array)signal_args[0])[0] = split_container->get_split_offset();1517SIGNAL_CHECK("dragged", signal_args);15181519// Release.1520SEND_GUI_MOUSE_BUTTON_RELEASED_EVENT(mouse_offset + Point2(0, dragger_pos), MouseButton::LEFT, MouseButtonMask::NONE, Key::NONE);1521MessageQueue::get_singleton()->flush();1522CHECK_RECTS(get_rects(split_container, dragger_pos, sep.y, false), get_child_rects(split_container));1523CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs);1524SIGNAL_CHECK_FALSE("dragged");15251526// No longer moves with the mouse.1527SEND_GUI_MOUSE_MOTION_EVENT(mouse_offset + Point2(0, 200), MouseButtonMask::NONE, Key::NONE);1528MessageQueue::get_singleton()->flush();1529CHECK_RECTS(get_rects(split_container, dragger_pos, sep.y, false), get_child_rects(split_container));1530CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs);1531SIGNAL_CHECK_FALSE("dragged");15321533SIGNAL_UNWATCH(split_container, "dragged");1534}15351536SUBCASE("[SplitContainer] No expand flags") {1537Point2 mouse_offset = Point2(1, 1);1538int dragger_pos = 0;1539int split_dragger_ofs = 0;15401541// Grab the dragger.1542SEND_GUI_MOUSE_BUTTON_EVENT(mouse_offset + Point2(dragger_pos, 0), MouseButton::LEFT, MouseButtonMask::LEFT, Key::NONE);1543MessageQueue::get_singleton()->flush();1544CHECK_RECTS(get_rects(split_container, dragger_pos, sep.x), get_child_rects(split_container));1545CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs);15461547// Move the dragger.1548dragger_pos = 10;1549SEND_GUI_MOUSE_MOTION_EVENT(mouse_offset + Point2(dragger_pos, 0), MouseButtonMask::LEFT, Key::NONE);1550MessageQueue::get_singleton()->flush();1551CHECK_RECTS(get_rects(split_container, dragger_pos, sep.x), get_child_rects(split_container));1552CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs);1553// It is clamped.1554split_container->clamp_split_offset();1555CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs);15561557// Continue moving.1558dragger_pos = 400;1559SEND_GUI_MOUSE_MOTION_EVENT(mouse_offset + Point2(dragger_pos, 0), MouseButtonMask::LEFT, Key::NONE);1560MessageQueue::get_singleton()->flush();1561CHECK_RECTS(get_rects(split_container, dragger_pos, sep.x), get_child_rects(split_container));1562CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs);15631564// Moves even when mouse is outside.1565dragger_pos = split_container->get_size().x - sep.x;1566SEND_GUI_MOUSE_MOTION_EVENT(mouse_offset + Point2(1000, 0), MouseButtonMask::LEFT, Key::NONE);1567MessageQueue::get_singleton()->flush();1568CHECK_RECTS(get_rects(split_container, dragger_pos, sep.x), get_child_rects(split_container));1569CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs);15701571// Move back in.1572dragger_pos = 100;1573SEND_GUI_MOUSE_MOTION_EVENT(mouse_offset + Point2(dragger_pos, 0), MouseButtonMask::LEFT, Key::NONE);1574MessageQueue::get_singleton()->flush();1575CHECK_RECTS(get_rects(split_container, dragger_pos, sep.x), get_child_rects(split_container));1576CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs);15771578// Release.1579SEND_GUI_MOUSE_BUTTON_RELEASED_EVENT(mouse_offset + Point2(dragger_pos, 0), MouseButton::LEFT, MouseButtonMask::NONE, Key::NONE);1580MessageQueue::get_singleton()->flush();1581CHECK_RECTS(get_rects(split_container, dragger_pos, sep.x), get_child_rects(split_container));1582CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs);15831584// No longer moves with the mouse.1585SEND_GUI_MOUSE_MOTION_EVENT(mouse_offset + Point2(200, 0), MouseButtonMask::NONE, Key::NONE);1586MessageQueue::get_singleton()->flush();1587CHECK_RECTS(get_rects(split_container, dragger_pos, sep.x), get_child_rects(split_container));1588CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs);1589}15901591SUBCASE("[SplitContainer] First child expanded") {1592child_a->set_h_size_flags(Control::SIZE_EXPAND_FILL);1593MessageQueue::get_singleton()->flush();1594Point2 mouse_offset = Point2(1, 1);1595int dragger_pos = split_container->get_size().x - sep.x;1596int split_dragger_ofs = -dragger_pos;15971598// Grab the dragger.1599SEND_GUI_MOUSE_BUTTON_EVENT(mouse_offset + Point2(dragger_pos, 0), MouseButton::LEFT, MouseButtonMask::LEFT, Key::NONE);1600MessageQueue::get_singleton()->flush();1601CHECK_RECTS(get_rects(split_container, dragger_pos, sep.x), get_child_rects(split_container));1602CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs);16031604// Move the dragger.1605dragger_pos -= 10;1606SEND_GUI_MOUSE_MOTION_EVENT(mouse_offset + Point2(dragger_pos, 0), MouseButtonMask::LEFT, Key::NONE);1607MessageQueue::get_singleton()->flush();1608CHECK_RECTS(get_rects(split_container, dragger_pos, sep.x), get_child_rects(split_container));1609CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs);1610// It is clamped.1611split_container->clamp_split_offset();1612CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs);16131614// Continue moving.1615dragger_pos = 400;1616SEND_GUI_MOUSE_MOTION_EVENT(mouse_offset + Point2(dragger_pos, 0), MouseButtonMask::LEFT, Key::NONE);1617MessageQueue::get_singleton()->flush();1618CHECK_RECTS(get_rects(split_container, dragger_pos, sep.x), get_child_rects(split_container));1619CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs);16201621// Moves even when mouse is outside.1622dragger_pos = split_container->get_size().x - sep.x;1623SEND_GUI_MOUSE_MOTION_EVENT(mouse_offset + Point2(1000, 0), MouseButtonMask::LEFT, Key::NONE);1624MessageQueue::get_singleton()->flush();1625CHECK_RECTS(get_rects(split_container, dragger_pos, sep.x), get_child_rects(split_container));1626CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs);16271628// Move back in.1629dragger_pos = 100;1630SEND_GUI_MOUSE_MOTION_EVENT(mouse_offset + Point2(dragger_pos, 0), MouseButtonMask::LEFT, Key::NONE);1631MessageQueue::get_singleton()->flush();1632CHECK_RECTS(get_rects(split_container, dragger_pos, sep.x), get_child_rects(split_container));1633CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs);16341635// Release.1636SEND_GUI_MOUSE_BUTTON_RELEASED_EVENT(mouse_offset + Point2(dragger_pos, 0), MouseButton::LEFT, MouseButtonMask::NONE, Key::NONE);1637MessageQueue::get_singleton()->flush();1638CHECK_RECTS(get_rects(split_container, dragger_pos, sep.x), get_child_rects(split_container));1639CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs);16401641// No longer moves with the mouse.1642SEND_GUI_MOUSE_MOTION_EVENT(mouse_offset + Point2(200, 0), MouseButtonMask::NONE, Key::NONE);1643MessageQueue::get_singleton()->flush();1644CHECK_RECTS(get_rects(split_container, dragger_pos, sep.x), get_child_rects(split_container));1645CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs);1646}16471648SUBCASE("[SplitContainer] Second child expanded") {1649child_b->set_h_size_flags(Control::SIZE_EXPAND_FILL);1650MessageQueue::get_singleton()->flush();1651Point2 mouse_offset = Point2(1, 1);1652int dragger_pos = 0;1653int split_dragger_ofs = 0;16541655// Grab the dragger.1656SEND_GUI_MOUSE_BUTTON_EVENT(mouse_offset + Point2(dragger_pos, 0), MouseButton::LEFT, MouseButtonMask::LEFT, Key::NONE);1657MessageQueue::get_singleton()->flush();1658CHECK_RECTS(get_rects(split_container, dragger_pos, sep.x), get_child_rects(split_container));1659CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs);16601661// Move the dragger.1662dragger_pos = 10;1663SEND_GUI_MOUSE_MOTION_EVENT(mouse_offset + Point2(dragger_pos, 0), MouseButtonMask::LEFT, Key::NONE);1664MessageQueue::get_singleton()->flush();1665CHECK_RECTS(get_rects(split_container, dragger_pos, sep.x), get_child_rects(split_container));1666CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs);1667// It is clamped.1668split_container->clamp_split_offset();1669CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs);16701671// Continue moving.1672dragger_pos = 400;1673SEND_GUI_MOUSE_MOTION_EVENT(mouse_offset + Point2(dragger_pos, 0), MouseButtonMask::LEFT, Key::NONE);1674MessageQueue::get_singleton()->flush();1675CHECK_RECTS(get_rects(split_container, dragger_pos, sep.x), get_child_rects(split_container));1676CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs);16771678// Moves even when mouse is outside.1679dragger_pos = split_container->get_size().x - sep.x;1680SEND_GUI_MOUSE_MOTION_EVENT(mouse_offset + Point2(1000, 0), MouseButtonMask::LEFT, Key::NONE);1681MessageQueue::get_singleton()->flush();1682CHECK_RECTS(get_rects(split_container, dragger_pos, sep.x), get_child_rects(split_container));1683CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs);16841685// Move back in.1686dragger_pos = 100;1687SEND_GUI_MOUSE_MOTION_EVENT(mouse_offset + Point2(dragger_pos, 0), MouseButtonMask::LEFT, Key::NONE);1688MessageQueue::get_singleton()->flush();1689CHECK_RECTS(get_rects(split_container, dragger_pos, sep.x), get_child_rects(split_container));1690CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs);16911692// Release.1693SEND_GUI_MOUSE_BUTTON_RELEASED_EVENT(mouse_offset + Point2(dragger_pos, 0), MouseButton::LEFT, MouseButtonMask::NONE, Key::NONE);1694MessageQueue::get_singleton()->flush();1695CHECK_RECTS(get_rects(split_container, dragger_pos, sep.x), get_child_rects(split_container));1696CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs);16971698// No longer moves with the mouse.1699SEND_GUI_MOUSE_MOTION_EVENT(mouse_offset + Point2(200, 0), MouseButtonMask::NONE, Key::NONE);1700MessageQueue::get_singleton()->flush();1701CHECK_RECTS(get_rects(split_container, dragger_pos, sep.x), get_child_rects(split_container));1702CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs);1703}17041705SUBCASE("[SplitContainer] Both children expanded") {1706child_a->set_h_size_flags(Control::SIZE_EXPAND_FILL);1707child_b->set_h_size_flags(Control::SIZE_EXPAND_FILL);1708MessageQueue::get_singleton()->flush();1709Point2 mouse_offset = Point2(1, 1);1710int dragger_pos = (split_container->get_size().x - sep.x) / 2;1711int split_dragger_ofs = -dragger_pos;17121713// Grab the dragger.1714SEND_GUI_MOUSE_BUTTON_EVENT(mouse_offset + Point2(dragger_pos, 0), MouseButton::LEFT, MouseButtonMask::LEFT, Key::NONE);1715MessageQueue::get_singleton()->flush();1716CHECK_RECTS(get_rects(split_container, dragger_pos, sep.x), get_child_rects(split_container));1717CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs);17181719// Move the dragger.1720dragger_pos += 10;1721SEND_GUI_MOUSE_MOTION_EVENT(mouse_offset + Point2(dragger_pos, 0), MouseButtonMask::LEFT, Key::NONE);1722MessageQueue::get_singleton()->flush();1723CHECK_RECTS(get_rects(split_container, dragger_pos, sep.x), get_child_rects(split_container));1724CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs);1725// It is clamped.1726split_container->clamp_split_offset();1727CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs);17281729// Continue moving.1730dragger_pos = 400;1731SEND_GUI_MOUSE_MOTION_EVENT(mouse_offset + Point2(dragger_pos, 0), MouseButtonMask::LEFT, Key::NONE);1732MessageQueue::get_singleton()->flush();1733CHECK_RECTS(get_rects(split_container, dragger_pos, sep.x), get_child_rects(split_container));1734CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs);17351736// Moves even when mouse is outside.1737dragger_pos = split_container->get_size().x - sep.x;1738SEND_GUI_MOUSE_MOTION_EVENT(mouse_offset + Point2(1000, 0), MouseButtonMask::LEFT, Key::NONE);1739MessageQueue::get_singleton()->flush();1740CHECK_RECTS(get_rects(split_container, dragger_pos, sep.x), get_child_rects(split_container));1741CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs);17421743// Move back in.1744dragger_pos = 100;1745SEND_GUI_MOUSE_MOTION_EVENT(mouse_offset + Point2(dragger_pos, 0), MouseButtonMask::LEFT, Key::NONE);1746MessageQueue::get_singleton()->flush();1747CHECK_RECTS(get_rects(split_container, dragger_pos, sep.x), get_child_rects(split_container));1748CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs);17491750// Release.1751SEND_GUI_MOUSE_BUTTON_RELEASED_EVENT(mouse_offset + Point2(dragger_pos, 0), MouseButton::LEFT, MouseButtonMask::NONE, Key::NONE);1752MessageQueue::get_singleton()->flush();1753CHECK_RECTS(get_rects(split_container, dragger_pos, sep.x), get_child_rects(split_container));1754CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs);17551756// No longer moves with the mouse.1757SEND_GUI_MOUSE_MOTION_EVENT(mouse_offset + Point2(200, 0), MouseButtonMask::NONE, Key::NONE);1758MessageQueue::get_singleton()->flush();1759CHECK_RECTS(get_rects(split_container, dragger_pos, sep.x), get_child_rects(split_container));1760CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs);1761}1762}17631764memdelete(child_b);1765memdelete(child_a);1766memdelete(split_container);1767}17681769TEST_CASE("[SceneTree][SplitContainer] More children") {1770SplitContainer *split_container = memnew(SplitContainer);1771split_container->set_size(Size2(500, 500));1772SceneTree::get_singleton()->get_root()->add_child(split_container);1773Control *child_a = memnew(Control);1774Control *child_b = memnew(Control);1775Control *child_c = memnew(Control);1776split_container->add_child(child_a);1777split_container->add_child(child_b);1778split_container->add_child(child_c);1779Size2i min_size = Size2i(10, 10);1780child_a->set_custom_minimum_size(min_size);1781child_b->set_custom_minimum_size(min_size);1782child_c->set_custom_minimum_size(min_size);1783MessageQueue::get_singleton()->flush();17841785const int sep_constant = split_container->get_theme_constant("separation");1786const Size2i sep = Size2i(MAX(sep_constant, split_container->get_theme_icon("h_grabber")->get_width()), MAX(sep_constant, split_container->get_theme_icon("v_grabber")->get_height()));17871788SUBCASE("[SplitContainer] Duplicate") {1789// Make sure dynamically added internal draggers duplicate properly.1790SplitContainer *duplicate = (SplitContainer *)(Node *)split_container->duplicate();1791SceneTree::get_singleton()->get_root()->add_child(duplicate);1792MessageQueue::get_singleton()->flush();1793CHECK(duplicate->get_child_count(false) == split_container->get_child_count(false));1794CHECK(duplicate->get_child_count(true) == split_container->get_child_count(true));1795memdelete(duplicate);1796}17971798SUBCASE("[SplitContainer] Default position") {1799CHECK(split_container->get_split_offsets() == Vector<int>({ 0, 0 }));18001801set_size_flags(split_container, { -1, -1, -1 }); // None expanded.1802Vector<int> def_pos = { min_size.x, min_size.x * 2 + sep.x };1803CHECK_RECTS(get_rects_multi(split_container, def_pos, sep.x), get_child_rects(split_container));1804split_container->clamp_split_offset();1805MessageQueue::get_singleton()->flush();1806CHECK(split_container->get_split_offsets() == Vector<int>({ min_size.x, min_size.x * 2 + sep.x }));1807CHECK_RECTS(get_rects_multi(split_container, def_pos, sep.x), get_child_rects(split_container));18081809split_container->set_split_offsets({ 0, 0 });18101811set_size_flags(split_container, { 1, -1, -1 }); // First expanded.1812def_pos = { (int)split_container->get_size().x - sep.x * 2 - min_size.x * 2, (int)split_container->get_size().x - sep.x - min_size.x };1813CHECK_RECTS(get_rects_multi(split_container, def_pos, sep.x), get_child_rects(split_container));1814split_container->clamp_split_offset();1815MessageQueue::get_singleton()->flush();1816CHECK(split_container->get_split_offsets() == Vector<int>({ -min_size.x * 2 - sep.x, -min_size.x }));1817CHECK_RECTS(get_rects_multi(split_container, def_pos, sep.x), get_child_rects(split_container));1818split_container->set_split_offsets({ 0, 0 });18191820set_size_flags(split_container, { -1, 1, -1 }); // Second expanded.1821def_pos = { min_size.x, (int)split_container->get_size().x - min_size.x - sep.x };1822CHECK_RECTS(get_rects_multi(split_container, def_pos, sep.x), get_child_rects(split_container));1823split_container->clamp_split_offset();1824MessageQueue::get_singleton()->flush();1825CHECK(split_container->get_split_offsets() == Vector<int>({ min_size.x, -min_size.x }));1826CHECK_RECTS(get_rects_multi(split_container, def_pos, sep.x), get_child_rects(split_container));1827split_container->set_split_offsets({ 0, 0 });18281829set_size_flags(split_container, { -1, -1, 1 }); // Third expanded.1830def_pos = { min_size.x, min_size.x * 2 + sep.x };1831CHECK_RECTS(get_rects_multi(split_container, def_pos, sep.x), get_child_rects(split_container));1832split_container->clamp_split_offset();1833MessageQueue::get_singleton()->flush();1834CHECK(split_container->get_split_offsets() == Vector<int>({ min_size.x, min_size.x * 2 + sep.x }));1835CHECK_RECTS(get_rects_multi(split_container, def_pos, sep.x), get_child_rects(split_container));1836split_container->set_split_offsets({ 0, 0 });18371838set_size_flags(split_container, { 1, 1, -1 }); // First and second expanded.1839int child_2_expanded_size = ((int)split_container->get_size().x - min_size.x) / 2 - sep.x;1840def_pos = { child_2_expanded_size, (int)split_container->get_size().x - min_size.x - sep.x };1841CHECK_RECTS(get_rects_multi(split_container, def_pos, sep.x), get_child_rects(split_container));1842split_container->clamp_split_offset();1843MessageQueue::get_singleton()->flush();1844CHECK(split_container->get_split_offsets() == Vector<int>({ 0, -min_size.x }));1845CHECK_RECTS(get_rects_multi(split_container, def_pos, sep.x), get_child_rects(split_container));1846split_container->set_split_offsets({ 0, 0 });18471848set_size_flags(split_container, { 1, -1, 1 }); // First and third expanded.1849def_pos = { child_2_expanded_size, child_2_expanded_size + min_size.x + sep.x };1850CHECK_RECTS(get_rects_multi(split_container, def_pos, sep.x), get_child_rects(split_container));1851split_container->clamp_split_offset();1852MessageQueue::get_singleton()->flush();1853CHECK(split_container->get_split_offsets() == Vector<int>({ 0, 0 }));1854CHECK_RECTS(get_rects_multi(split_container, def_pos, sep.x), get_child_rects(split_container));1855split_container->set_split_offsets({ 0, 0 });18561857set_size_flags(split_container, { -1, 1, 1 }); // Second and third expanded.1858def_pos = { min_size.x, min_size.x + child_2_expanded_size + sep.x };1859CHECK_RECTS(get_rects_multi(split_container, def_pos, sep.x), get_child_rects(split_container));1860split_container->clamp_split_offset();1861MessageQueue::get_singleton()->flush();1862CHECK(split_container->get_split_offsets() == Vector<int>({ min_size.x, 0 }));1863CHECK_RECTS(get_rects_multi(split_container, def_pos, sep.x), get_child_rects(split_container));1864split_container->set_split_offsets({ 0, 0 });18651866set_size_flags(split_container, { 1, 1, 1 }); // All expanded.1867int child_3_expanded_size = (split_container->get_size().x - sep.x * 2) / 3;1868// Add 1 due to pixel error accumulation.1869def_pos = { child_3_expanded_size, child_3_expanded_size * 2 + sep.x + 1 };1870CHECK_RECTS(get_rects_multi(split_container, def_pos, sep.x), get_child_rects(split_container));1871split_container->clamp_split_offset();1872MessageQueue::get_singleton()->flush();1873CHECK(split_container->get_split_offsets() == Vector<int>({ 0, 0 }));1874CHECK_RECTS(get_rects_multi(split_container, def_pos, sep.x), get_child_rects(split_container));1875split_container->set_split_offsets({ 0, 0 });18761877set_size_flags(split_container, { 1, 2, 3 }); // All expanded, different ratios.1878int child_6_expanded_size = (split_container->get_size().x - sep.x * 2) / 6;1879def_pos = { child_6_expanded_size, child_6_expanded_size * 3 + sep.x + 1 };1880CHECK_RECTS(get_rects_multi(split_container, def_pos, sep.x), get_child_rects(split_container));1881split_container->clamp_split_offset();1882MessageQueue::get_singleton()->flush();1883CHECK(split_container->get_split_offsets() == Vector<int>({ 0, 0 }));1884CHECK_RECTS(get_rects_multi(split_container, def_pos, sep.x), get_child_rects(split_container));1885split_container->set_split_offsets({ 0, 0 });1886}18871888SUBCASE("[SplitContainer] Set split offset") {1889const int expanded_single_size = (int)split_container->get_size().x - min_size.x * 2 - sep.x * 2;18901891SUBCASE("[SplitContainer] No expand flags") {1892set_size_flags(split_container, { -1, -1, -1 }); // None expanded.18931894// First is positive.1895split_container->set_split_offsets({ 50, 0 });1896MessageQueue::get_singleton()->flush();1897CHECK(split_container->get_split_offsets() == Vector<int>{ 50, 0 });1898CHECK_RECTS(get_rects_multi(split_container, { 50, 50 + min_size.x + sep.x }, sep.x), get_child_rects(split_container));18991900// Second is positive.1901split_container->set_split_offsets({ 0, 50 });1902MessageQueue::get_singleton()->flush();1903CHECK(split_container->get_split_offsets() == Vector<int>{ 0, 50 });1904CHECK_RECTS(get_rects_multi(split_container, { min_size.x, 50 }, sep.x), get_child_rects(split_container));19051906// Both are positive and equal, the first will override since they both start at 0.1907split_container->set_split_offsets({ 50, 50 });1908MessageQueue::get_singleton()->flush();1909CHECK(split_container->get_split_offsets() == Vector<int>{ 50, 50 });1910CHECK_RECTS(get_rects_multi(split_container, { 50, 50 + min_size.x + sep.x }, sep.x), get_child_rects(split_container));19111912// Both are negative and clamped.1913split_container->set_split_offsets({ -50, -50 });1914MessageQueue::get_singleton()->flush();1915CHECK(split_container->get_split_offsets() == Vector<int>{ -50, -50 });1916CHECK_RECTS(get_rects_multi(split_container, { min_size.x, min_size.x * 2 + sep.x }, sep.x), get_child_rects(split_container));19171918// First positive, second negative. First takes priority.1919split_container->set_split_offsets({ 50, -50 });1920MessageQueue::get_singleton()->flush();1921CHECK(split_container->get_split_offsets() == Vector<int>{ 50, -50 });1922CHECK_RECTS(get_rects_multi(split_container, { 50, 50 + min_size.x + sep.x }, sep.x), get_child_rects(split_container));19231924// First is clamped and pushes second to the end.1925split_container->set_split_offsets({ 1000, 0 });1926MessageQueue::get_singleton()->flush();1927CHECK(split_container->get_split_offsets() == Vector<int>{ 1000, 0 });1928CHECK_RECTS(get_rects_multi(split_container, { expanded_single_size, expanded_single_size + min_size.x + sep.x }, sep.x), get_child_rects(split_container));19291930// Second is clamped.1931split_container->set_split_offsets({ 0, 1000 });1932MessageQueue::get_singleton()->flush();1933CHECK(split_container->get_split_offsets() == Vector<int>{ 0, 1000 });1934CHECK_RECTS(get_rects_multi(split_container, { min_size.x, expanded_single_size + min_size.x + sep.x }, sep.x), get_child_rects(split_container));19351936// Both are clamped positively, first one takes priority.1937split_container->set_split_offsets({ 1000, 1000 });1938MessageQueue::get_singleton()->flush();1939CHECK(split_container->get_split_offsets() == Vector<int>{ 1000, 1000 });1940CHECK_RECTS(get_rects_multi(split_container, { expanded_single_size, expanded_single_size + min_size.x + sep.x }, sep.x), get_child_rects(split_container));1941}19421943SUBCASE("[SplitContainer] First child expanded") {1944set_size_flags(split_container, { 1, -1, -1 }); // First expanded.19451946// First is positive and clamped.1947split_container->set_split_offsets({ 50, 0 });1948MessageQueue::get_singleton()->flush();1949CHECK(split_container->get_split_offsets() == Vector<int>{ 50, 0 });1950CHECK_RECTS(get_rects_multi(split_container, { expanded_single_size, expanded_single_size + min_size.x + sep.x }, sep.x), get_child_rects(split_container));19511952// Second is positive and clamped.1953split_container->set_split_offsets({ 0, 50 });1954MessageQueue::get_singleton()->flush();1955CHECK(split_container->get_split_offsets() == Vector<int>{ 0, 50 });1956CHECK_RECTS(get_rects_multi(split_container, { expanded_single_size, expanded_single_size + min_size.x + sep.x }, sep.x), get_child_rects(split_container));19571958// First is negative and moves left.1959split_container->set_split_offsets({ -50, 0 });1960MessageQueue::get_singleton()->flush();1961CHECK(split_container->get_split_offsets() == Vector<int>{ -50, 0 });1962CHECK_RECTS(get_rects_multi(split_container, { (int)split_container->get_size().x - 50 - sep.x, (int)split_container->get_size().x - min_size.x - sep.x }, sep.x), get_child_rects(split_container));19631964// Second is negative, but first has priority so it doesn't move.1965split_container->set_split_offsets({ 0, -50 });1966MessageQueue::get_singleton()->flush();1967CHECK(split_container->get_split_offsets() == Vector<int>{ 0, -50 });1968CHECK_RECTS(get_rects_multi(split_container, { expanded_single_size, expanded_single_size + min_size.x + sep.x }, sep.x), get_child_rects(split_container));19691970// Both are negative and equal, they move left but the second doesn't move as much as wanted.1971split_container->set_split_offsets({ -50, -50 });1972MessageQueue::get_singleton()->flush();1973CHECK(split_container->get_split_offsets() == Vector<int>{ -50, -50 });1974CHECK_RECTS(get_rects_multi(split_container, { (int)split_container->get_size().x - 50 - sep.x, (int)split_container->get_size().x - 50 + min_size.x }, sep.x), get_child_rects(split_container));19751976// Both are negative with space and move left.1977split_container->set_split_offsets({ -100, -50 });1978MessageQueue::get_singleton()->flush();1979CHECK(split_container->get_split_offsets() == Vector<int>{ -100, -50 });1980CHECK_RECTS(get_rects_multi(split_container, { (int)split_container->get_size().x - 100 - sep.x, (int)split_container->get_size().x - 50 - sep.x }, sep.x), get_child_rects(split_container));19811982// First moves all the way left.1983split_container->set_split_offsets({ -1000, 0 });1984MessageQueue::get_singleton()->flush();1985CHECK(split_container->get_split_offsets() == Vector<int>{ -1000, 0 });1986CHECK_RECTS(get_rects_multi(split_container, { min_size.x, expanded_single_size + min_size.x + sep.x }, sep.x), get_child_rects(split_container));19871988// Second cannot move all the way left since first takes priority.1989split_container->set_split_offsets({ 0, -1000 });1990MessageQueue::get_singleton()->flush();1991CHECK(split_container->get_split_offsets() == Vector<int>{ 0, -1000 });1992CHECK_RECTS(get_rects_multi(split_container, { expanded_single_size, expanded_single_size + min_size.x + sep.x }, sep.x), get_child_rects(split_container));19931994// First and second move all the way left.1995split_container->set_split_offsets({ -1000, -1000 });1996MessageQueue::get_singleton()->flush();1997CHECK(split_container->get_split_offsets() == Vector<int>{ -1000, -1000 });1998CHECK_RECTS(get_rects_multi(split_container, { min_size.x, min_size.x * 2 + sep.x }, sep.x), get_child_rects(split_container));1999}20002001SUBCASE("[SplitContainer] All children expanded") {2002set_size_flags(split_container, { 1, 1, 1 }); // All expanded.2003const int child_3_expanded_size = (split_container->get_size().x - sep.x * 2) / 3;20042005// First is moved positive, does not affect second.2006split_container->set_split_offsets({ 50, 0 });2007MessageQueue::get_singleton()->flush();2008CHECK(split_container->get_split_offsets() == Vector<int>{ 50, 0 });2009CHECK_RECTS(get_rects_multi(split_container, { child_3_expanded_size + 50, child_3_expanded_size * 2 + sep.x + 1 }, sep.x), get_child_rects(split_container));20102011// First is moved negative, does not affect second.2012split_container->set_split_offsets({ -50, 0 });2013MessageQueue::get_singleton()->flush();2014CHECK(split_container->get_split_offsets() == Vector<int>{ -50, 0 });2015CHECK_RECTS(get_rects_multi(split_container, { child_3_expanded_size - 50, child_3_expanded_size * 2 + sep.x + 1 }, sep.x), get_child_rects(split_container));20162017// Second is moved positive, does not affect first.2018split_container->set_split_offsets({ 0, 50 });2019MessageQueue::get_singleton()->flush();2020CHECK(split_container->get_split_offsets() == Vector<int>{ 0, 50 });2021CHECK_RECTS(get_rects_multi(split_container, { child_3_expanded_size, child_3_expanded_size * 2 + 50 + sep.x + 1 }, sep.x), get_child_rects(split_container));20222023// Second is moved negative, does not affect first.2024split_container->set_split_offsets({ 0, -50 });2025MessageQueue::get_singleton()->flush();2026CHECK(split_container->get_split_offsets() == Vector<int>{ 0, -50 });2027CHECK_RECTS(get_rects_multi(split_container, { child_3_expanded_size, child_3_expanded_size * 2 - 50 + sep.x + 1 }, sep.x), get_child_rects(split_container));20282029// First is moved positive enough to affect second.2030split_container->set_split_offsets({ 200, 0 });2031MessageQueue::get_singleton()->flush();2032CHECK(split_container->get_split_offsets() == Vector<int>{ 200, 0 });2033CHECK_RECTS(get_rects_multi(split_container, { child_3_expanded_size + 200, child_3_expanded_size + 200 + sep.x + min_size.x }, sep.x), get_child_rects(split_container));20342035// Second is moved enough to pass the first, but the first has priority.2036split_container->set_split_offsets({ 0, -200 });2037MessageQueue::get_singleton()->flush();2038CHECK(split_container->get_split_offsets() == Vector<int>{ 0, -200 });2039CHECK_RECTS(get_rects_multi(split_container, { child_3_expanded_size, child_3_expanded_size + min_size.x + sep.x }, sep.x), get_child_rects(split_container));2040}2041}20422043SUBCASE("[SplitContainer] Resize") {2044SUBCASE("[SplitContainer] No expand flags") {2045Vector<int> def_pos = { min_size.x, min_size.x * 2 + sep.x };2046// Increase the size.2047split_container->set_size(Size2(600, 500));2048MessageQueue::get_singleton()->flush();2049CHECK_RECTS(get_rects_multi(split_container, def_pos, sep.x), get_child_rects(split_container));20502051// Decrease the size.2052split_container->set_size(Size2(400, 500));2053MessageQueue::get_singleton()->flush();2054CHECK_RECTS(get_rects_multi(split_container, def_pos, sep.x), get_child_rects(split_container));20552056// Change size with a split offset.2057split_container->set_split_offsets({ 50, 100 });2058split_container->set_size(Size2(500, 500));2059MessageQueue::get_singleton()->flush();2060CHECK_RECTS(get_rects_multi(split_container, { 50, 100 }, sep.x), get_child_rects(split_container));2061CHECK(split_container->get_split_offsets() == Vector<int>{ 50, 100 });20622063// Change size so that the second child gets clamped and changes size.2064split_container->set_size(Size2(100, 500));2065MessageQueue::get_singleton()->flush();2066CHECK_RECTS(get_rects_multi(split_container, { 50, 100 - sep.x - min_size.x }, sep.x), get_child_rects(split_container));2067CHECK(split_container->get_split_offsets() == Vector<int>{ 50, 100 });20682069// Change size so that the first child changes size.2070split_container->set_size(Size2(60, 500));2071MessageQueue::get_singleton()->flush();2072CHECK_RECTS(get_rects_multi(split_container, { 60 - min_size.x * 2 - sep.x * 2, 60 - sep.x - min_size.x }, sep.x), get_child_rects(split_container));2073CHECK(split_container->get_split_offsets() == Vector<int>{ 50, 100 });20742075// Increase size again.2076split_container->set_size(Size2(500, 500));2077MessageQueue::get_singleton()->flush();2078CHECK_RECTS(get_rects_multi(split_container, { 50, 100 }, sep.x), get_child_rects(split_container));2079CHECK(split_container->get_split_offsets() == Vector<int>{ 50, 100 });2080}20812082SUBCASE("[SplitContainer] First child expanded") {2083set_size_flags(split_container, { 1, -1, -1 });2084Vector<int> def_pos = { (int)split_container->get_size().x - sep.x * 2 - min_size.x, (int)split_container->get_size().x - sep.x };2085// Increase the size.2086split_container->set_size(Size2(600, 500));2087def_pos = { (int)split_container->get_size().x - sep.x * 2 - min_size.x * 2, (int)split_container->get_size().x - sep.x - min_size.x };2088MessageQueue::get_singleton()->flush();2089CHECK_RECTS(get_rects_multi(split_container, def_pos, sep.x), get_child_rects(split_container));20902091// Decrease the size.2092split_container->set_size(Size2(400, 500));2093def_pos = { (int)split_container->get_size().x - sep.x * 2 - min_size.x * 2, (int)split_container->get_size().x - sep.x - min_size.x };2094MessageQueue::get_singleton()->flush();2095CHECK_RECTS(get_rects_multi(split_container, def_pos, sep.x), get_child_rects(split_container));20962097// Change size with a split offset.2098split_container->set_split_offsets({ -100, -50 });2099split_container->set_size(Size2(500, 500));2100MessageQueue::get_singleton()->flush();2101CHECK_RECTS(get_rects_multi(split_container, { (int)split_container->get_size().x - 100 - sep.x, (int)split_container->get_size().x - 50 - sep.x }, sep.x), get_child_rects(split_container));2102CHECK(split_container->get_split_offsets() == Vector<int>{ -100, -50 });21032104// Change size so that the first child gets clamped and changes size.2105split_container->set_size(Size2(100, 500));2106MessageQueue::get_singleton()->flush();2107CHECK_RECTS(get_rects_multi(split_container, { min_size.x, (int)split_container->get_size().x - 50 - sep.x }, sep.x), get_child_rects(split_container));2108CHECK(split_container->get_split_offsets() == Vector<int>{ -100, -50 });21092110// Change size so that the second child changes size.2111split_container->set_size(Size2(50, 500));2112MessageQueue::get_singleton()->flush();2113CHECK_RECTS(get_rects_multi(split_container, { min_size.x, min_size.x * 2 + sep.x }, sep.x), get_child_rects(split_container));2114CHECK(split_container->get_split_offsets() == Vector<int>{ -100, -50 });21152116// Increase size again.2117split_container->set_size(Size2(500, 500));2118MessageQueue::get_singleton()->flush();2119CHECK_RECTS(get_rects_multi(split_container, { (int)split_container->get_size().x - 100 - sep.x, (int)split_container->get_size().x - 50 - sep.x }, sep.x), get_child_rects(split_container));2120CHECK(split_container->get_split_offsets() == Vector<int>{ -100, -50 });2121}21222123SUBCASE("[SplitContainer] All children expanded") {2124set_size_flags(split_container, { 1, 1, 1 });2125// Increase the size.2126split_container->set_size(Size2(600, 500));2127MessageQueue::get_singleton()->flush();2128int child_3_expanded_size = (split_container->get_size().x - sep.x * 2) / 3;2129Vector<int> def_pos = { child_3_expanded_size, child_3_expanded_size * 2 + sep.x };2130CHECK_RECTS(get_rects_multi(split_container, def_pos, sep.x), get_child_rects(split_container));21312132// Decrease the size.2133split_container->set_size(Size2(400, 500));2134MessageQueue::get_singleton()->flush();2135child_3_expanded_size = (split_container->get_size().x - sep.x * 2) / 3;2136def_pos = { child_3_expanded_size, child_3_expanded_size * 2 + sep.x };2137CHECK_RECTS(get_rects_multi(split_container, def_pos, sep.x), get_child_rects(split_container));21382139// Change size with a split offset.2140split_container->set_split_offsets({ -50, 50 });2141split_container->set_size(Size2(500, 500));2142MessageQueue::get_singleton()->flush();2143child_3_expanded_size = (split_container->get_size().x - sep.x * 2) / 3;2144def_pos = { child_3_expanded_size, child_3_expanded_size * 2 + sep.x + 1 };2145CHECK_RECTS(get_rects_multi(split_container, { def_pos[0] - 50, def_pos[1] + 50 }, sep.x), get_child_rects(split_container));2146CHECK(split_container->get_split_offsets() == Vector<int>{ -50, 50 });21472148// Change size so that the children get clamped and change sizes.2149split_container->set_size(Size2(100, 500));2150MessageQueue::get_singleton()->flush();2151CHECK_RECTS(get_rects_multi(split_container, { min_size.x, (int)split_container->get_size().x - sep.x - min_size.x }, sep.x), get_child_rects(split_container));2152CHECK(split_container->get_split_offsets() == Vector<int>{ -50, 50 });21532154// Increase size again.2155split_container->set_size(Size2(500, 500));2156MessageQueue::get_singleton()->flush();2157child_3_expanded_size = (split_container->get_size().x - sep.x * 2) / 3;2158def_pos = { child_3_expanded_size, child_3_expanded_size * 2 + sep.x + 1 };2159CHECK_RECTS(get_rects_multi(split_container, { def_pos[0] - 50, def_pos[1] + 50 }, sep.x), get_child_rects(split_container));2160CHECK(split_container->get_split_offsets() == Vector<int>{ -50, 50 });2161}2162}21632164SUBCASE("[SplitContainer] Visibility changes") {2165set_size_flags(split_container, { -1, -1, -1 }); // None expanded.2166split_container->set_split_offsets({ 50, 122 });2167MessageQueue::get_singleton()->flush();2168Vector<int> def_pos = { 50, 122 };2169CHECK_RECTS(get_rects_multi(split_container, def_pos, sep.x), get_child_rects(split_container));21702171// Hide and show the first child.2172child_a->set_visible(false);2173MessageQueue::get_singleton()->flush();2174CHECK(split_container->get_split_offsets() == Vector<int>({ 60 }));2175CHECK_RECTS(get_rects_multi(split_container, { 60 }, sep.x), get_child_rects(split_container));21762177child_a->set_visible(true);2178MessageQueue::get_singleton()->flush();2179CHECK(split_container->get_split_offsets() == def_pos);2180CHECK_RECTS(get_rects_multi(split_container, def_pos, sep.x), get_child_rects(split_container));21812182// Hide and show the second child.2183child_b->set_visible(false);2184MessageQueue::get_singleton()->flush();2185CHECK(split_container->get_split_offsets() == Vector<int>({ 50 }));2186CHECK_RECTS(get_rects_multi(split_container, { 50 }, sep.x), get_child_rects(split_container));2187child_b->set_visible(true);2188MessageQueue::get_singleton()->flush();2189CHECK(split_container->get_split_offsets() == def_pos);2190CHECK_RECTS(get_rects_multi(split_container, def_pos, sep.x), get_child_rects(split_container));21912192// Hide and show the last child.2193child_c->set_visible(false);2194MessageQueue::get_singleton()->flush();2195CHECK(split_container->get_split_offsets() == Vector<int>({ 50 }));2196CHECK_RECTS(get_rects_multi(split_container, { 50 }, sep.x), get_child_rects(split_container));2197child_c->set_visible(true);2198MessageQueue::get_singleton()->flush();2199CHECK(split_container->get_split_offsets() == def_pos);2200CHECK_RECTS(get_rects_multi(split_container, def_pos, sep.x), get_child_rects(split_container));22012202set_size_flags(split_container, { 1, 1, 1 }); // All expanded.2203split_container->set_split_offsets({ 50, 60 });2204MessageQueue::get_singleton()->flush();2205int child_3_expanded_size = (split_container->get_size().x - sep.x * 2) / 3;2206def_pos = { child_3_expanded_size + 50, child_3_expanded_size * 2 + sep.x + 1 + 60 };2207CHECK_RECTS(get_rects_multi(split_container, def_pos, sep.x), get_child_rects(split_container));22082209// Hide and show the first child.2210int child_2_expanded_size = (split_container->get_size().x - sep.x) / 2;2211child_a->set_visible(false);2212MessageQueue::get_singleton()->flush();2213int half_point = (split_container->get_size().x - def_pos[0]) / 2 - sep.x;2214int so = child_3_expanded_size + 11 - half_point; // 11 is from 60 - 50 + 1 to get the second child's size.2215CHECK_RECTS(get_rects_multi(split_container, { child_2_expanded_size + so }, sep.x), get_child_rects(split_container));2216CHECK(split_container->get_split_offsets() == Vector<int>({ so }));2217child_a->set_visible(true);2218MessageQueue::get_singleton()->flush();2219CHECK_RECTS(get_rects_multi(split_container, def_pos, sep.x), get_child_rects(split_container));2220CHECK(split_container->get_split_offsets() == Vector<int>({ 50, 60 }));22212222// Hide and show the second child.2223child_b->set_visible(false);2224MessageQueue::get_singleton()->flush();2225half_point = (split_container->get_size().x - (def_pos[1] - def_pos[0] - sep.x)) / 2 - sep.x + 1;2226so = def_pos[0] - half_point;2227CHECK_RECTS(get_rects_multi(split_container, { child_2_expanded_size + so }, sep.x), get_child_rects(split_container));2228CHECK(split_container->get_split_offsets() == Vector<int>({ so }));2229child_b->set_visible(true);2230MessageQueue::get_singleton()->flush();2231// There is lost precision due to SplitContainer using ints, so this is off by one.2232CHECK_RECTS(get_rects_multi(split_container, { def_pos[0] - 1, def_pos[1] - 1 }, sep.x), get_child_rects(split_container));2233CHECK(split_container->get_split_offsets() == Vector<int>({ 49, 59 }));22342235// Hide and show the last child.2236split_container->set_split_offsets({ 50, 60 });2237child_c->set_visible(false);2238MessageQueue::get_singleton()->flush();2239half_point = (def_pos[1] - sep.x) / 2 + 1;2240so = def_pos[0] - half_point;2241CHECK_RECTS(get_rects_multi(split_container, { child_2_expanded_size + so }, sep.x), get_child_rects(split_container));2242CHECK(split_container->get_split_offsets() == Vector<int>({ so }));2243child_c->set_visible(true);2244MessageQueue::get_singleton()->flush();2245CHECK_RECTS(get_rects_multi(split_container, { def_pos[0] - 1, def_pos[1] - 1 }, sep.x), get_child_rects(split_container));2246CHECK(split_container->get_split_offsets() == Vector<int>({ 49, 59 }));2247}22482249SUBCASE("[SplitContainer] Adjust split offset when moving children") {2250split_container->set_split_offsets({ 50, 80 });2251split_container->move_child(child_a, 1);2252Vector<int> pos = { 30 - sep.x, 80 }; // 30 = 80 - 50.2253MessageQueue::get_singleton()->flush();2254CHECK(split_container->get_split_offsets() == pos);2255CHECK_RECTS(get_rects_multi(split_container, pos, sep.x), get_child_rects(split_container));22562257// Move last child to first.2258split_container->set_split_offsets({ 50, 80 });2259split_container->move_child(child_c, 0);2260pos = { (int)split_container->get_size().x - 80 - sep.x, (int)split_container->get_size().x - 30 };2261MessageQueue::get_singleton()->flush();2262CHECK(split_container->get_split_offsets() == pos);2263CHECK_RECTS(get_rects_multi(split_container, pos, sep.x), get_child_rects(split_container));22642265// Move it back.2266split_container->move_child(child_c, 2);2267pos = { 50, 80 };2268MessageQueue::get_singleton()->flush();2269CHECK(split_container->get_split_offsets() == pos);2270CHECK_RECTS(get_rects_multi(split_container, pos, sep.x), get_child_rects(split_container));2271}22722273SUBCASE("[SplitContainer] Showing child with not enough space shrinks the largest child first") {2274set_size_flags(split_container, { -1, -1, -1 }); // None expanded.22752276// Second child is largest.2277child_a->set_visible(false);2278Vector<int> pos = { 360 };2279split_container->set_split_offsets(pos);22802281MessageQueue::get_singleton()->flush();2282CHECK(split_container->get_split_offsets() == pos);2283CHECK_RECTS(get_rects_multi(split_container, pos, sep.x), get_child_rects(split_container));22842285child_a->set_size(Vector2(100, 100));2286MessageQueue::get_singleton()->flush();2287CHECK(split_container->get_split_offsets() == pos);2288CHECK_RECTS(get_rects_multi(split_container, pos, sep.x), get_child_rects(split_container));22892290child_a->set_visible(true);2291pos = { 100, 360 };2292MessageQueue::get_singleton()->flush();2293CHECK(split_container->get_split_offsets() == pos);2294CHECK_RECTS(get_rects_multi(split_container, pos, sep.x), get_child_rects(split_container));22952296// Last child is largest.2297child_a->set_visible(false);2298pos = { 60 };2299split_container->set_split_offsets(pos);23002301MessageQueue::get_singleton()->flush();2302CHECK(split_container->get_split_offsets() == pos);2303CHECK_RECTS(get_rects_multi(split_container, pos, sep.x), get_child_rects(split_container));23042305child_a->set_size(Vector2(100, 100));2306MessageQueue::get_singleton()->flush();2307CHECK(split_container->get_split_offsets() == pos);2308CHECK_RECTS(get_rects_multi(split_container, pos, sep.x), get_child_rects(split_container));23092310child_a->set_visible(true);2311pos = { 100, 160 + sep.x };2312MessageQueue::get_singleton()->flush();2313CHECK(split_container->get_split_offsets() == pos);2314CHECK_RECTS(get_rects_multi(split_container, pos, sep.x), get_child_rects(split_container));23152316// Both visible children are the same size.2317child_a->set_visible(false);2318pos = { (int)split_container->get_size().x / 2 - sep.x / 2 };2319split_container->set_split_offsets(pos);23202321MessageQueue::get_singleton()->flush();2322CHECK(split_container->get_split_offsets() == pos);2323CHECK_RECTS(get_rects_multi(split_container, pos, sep.x), get_child_rects(split_container));2324CHECK(child_b->get_size().x == child_c->get_size().x);23252326child_a->set_size(Vector2(100, 100));2327MessageQueue::get_singleton()->flush();2328CHECK(split_container->get_split_offsets() == pos);2329CHECK_RECTS(get_rects_multi(split_container, pos, sep.x), get_child_rects(split_container));23302331child_a->set_visible(true);2332pos = { 100, (int)split_container->get_size().x / 2 + 50 };2333MessageQueue::get_singleton()->flush();2334CHECK(split_container->get_split_offsets() == pos);2335CHECK_RECTS(get_rects_multi(split_container, pos, sep.x), get_child_rects(split_container));2336CHECK(child_b->get_size().x == child_c->get_size().x);23372338// Second child is slightly larger than the last child.2339child_a->set_visible(false);2340pos = { (int)split_container->get_size().x / 2 - sep.x / 2 + 20 };2341split_container->set_split_offsets(pos);23422343MessageQueue::get_singleton()->flush();2344CHECK(split_container->get_split_offsets() == pos);2345CHECK_RECTS(get_rects_multi(split_container, pos, sep.x), get_child_rects(split_container));23462347child_a->set_size(Vector2(100, 100));2348MessageQueue::get_singleton()->flush();2349CHECK(split_container->get_split_offsets() == pos);2350CHECK_RECTS(get_rects_multi(split_container, pos, sep.x), get_child_rects(split_container));23512352child_a->set_visible(true);2353pos = { 100, (int)split_container->get_size().x / 2 + 50 };2354MessageQueue::get_singleton()->flush();2355CHECK(split_container->get_split_offsets() == pos);2356CHECK_RECTS(get_rects_multi(split_container, pos, sep.x), get_child_rects(split_container));2357CHECK(child_b->get_size().x == child_c->get_size().x);2358}23592360memdelete(split_container);2361}23622363} // namespace TestSplitContainer23642365#endif // ADVANCED_GUI_DISABLED236623672368