/**************************************************************************/ /* test_split_container.h */ /**************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ /* https://godotengine.org */ /**************************************************************************/ /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ /* "Software"), to deal in the Software without restriction, including */ /* without limitation the rights to use, copy, modify, merge, publish, */ /* distribute, sublicense, and/or sell copies of the Software, and to */ /* permit persons to whom the Software is furnished to do so, subject to */ /* the following conditions: */ /* */ /* The above copyright notice and this permission notice shall be */ /* included in all copies or substantial portions of the Software. */ /* */ /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ #ifndef TEST_SPLIT_CONTAINER_H #define TEST_SPLIT_CONTAINER_H #include "scene/gui/split_container.h" #include "scene/main/window.h" #include "tests/test_macros.h" namespace TestSplitContainer { static inline void check_positions(SplitContainer *p_sc, const Vector &p_positions, int p_sep, bool p_horizontal = true) { // Checks the rects of each split container child. CHECK(p_sc->get_child_count(false) == p_positions.size() + 1); int last_pos = 0; for (int i = 0; i < p_sc->get_child_count(false); i++) { // Assuming there is no invalid children. Control *c = Object::cast_to(p_sc->get_child(i, false)); int pos = i >= p_positions.size() ? p_sc->get_size()[p_horizontal ? 0 : 1] : p_positions[i]; Rect2 rect; if (p_horizontal) { rect.size.y = p_sc->get_size().y; rect.position.x = last_pos; rect.size.x = pos - last_pos; } else { rect.size.x = p_sc->get_size().x; rect.position.y = last_pos; rect.size.y = pos - last_pos; } CHECK_MESSAGE(c->get_rect() == rect, vformat("Child %s is the wrong size.", i)); last_pos = pos + p_sep; } } static inline void check_position(SplitContainer *p_sc, int p_position, int p_sep, bool p_horizontal = true) { check_positions(p_sc, { p_position }, p_sep, p_horizontal); } static inline void check_positions_rtl(SplitContainer *p_sc, const Vector &p_positions, int p_sep) { // Checks the rects of each split container child. Right to left layout. CHECK(p_sc->get_child_count(false) == p_positions.size() + 1); int last_pos = p_sc->get_size().x; for (int i = 0; i < p_sc->get_child_count(false); i++) { // Assuming there is no invalid children. Control *c = Object::cast_to(p_sc->get_child(i, false)); int pos = i >= p_positions.size() ? 0 : p_sc->get_size().x - p_positions[i]; Rect2 rect; rect.size.y = p_sc->get_size().y; rect.position.x = pos; rect.size.x = last_pos - pos; CHECK_MESSAGE(c->get_rect() == rect, vformat("Child %s is the wrong size.", i)); last_pos = pos - p_sep; } } static inline void check_position_rtl(SplitContainer *p_sc, int p_position, int p_sep) { check_positions_rtl(p_sc, { p_position }, p_sep); } TEST_CASE("[SceneTree][SplitContainer] Add children") { SplitContainer *split_container = memnew(SplitContainer); split_container->set_size(Size2(500, 500)); SceneTree::get_singleton()->get_root()->add_child(split_container); SUBCASE("[SplitContainer] One child") { Control *child_a = memnew(Control); split_container->add_child(child_a); MessageQueue::get_singleton()->flush(); // One child will fill the entire area. CHECK(child_a->get_rect() == split_container->get_rect()); split_container->set_vertical(true); CHECK(child_a->get_rect() == split_container->get_rect()); memdelete(child_a); } SUBCASE("[SplitContainer] Preserve split offset") { // The split offset is preserved through adding, removing, and changing visibility of children. split_container->set_split_offset(100); CHECK(split_container->get_split_offset() == 100); Control *child_a = memnew(Control); split_container->add_child(child_a); MessageQueue::get_singleton()->flush(); CHECK(split_container->get_split_offset() == 100); Control *child_b = memnew(Control); split_container->add_child(child_b); MessageQueue::get_singleton()->flush(); CHECK(split_container->get_split_offset() == 100); child_a->hide(); MessageQueue::get_singleton()->flush(); CHECK(split_container->get_split_offset() == 100); child_b->hide(); MessageQueue::get_singleton()->flush(); CHECK(split_container->get_split_offset() == 100); child_b->show(); MessageQueue::get_singleton()->flush(); CHECK(split_container->get_split_offset() == 100); child_a->show(); MessageQueue::get_singleton()->flush(); CHECK(split_container->get_split_offset() == 100); split_container->remove_child(child_a); MessageQueue::get_singleton()->flush(); CHECK(split_container->get_split_offset() == 100); split_container->add_child(child_a); MessageQueue::get_singleton()->flush(); CHECK(split_container->get_split_offset() == 100); memdelete(child_a); memdelete(child_b); } memdelete(split_container); } TEST_CASE("[SceneTree][SplitContainer] Dragger visibility") { SplitContainer *split_container = memnew(SplitContainer); split_container->set_size(Size2(500, 500)); SceneTree::get_singleton()->get_root()->add_child(split_container); Control *child_a = memnew(Control); Control *child_b = memnew(Control); split_container->add_child(child_a); split_container->add_child(child_b); SplitContainerDragger *dragger = Object::cast_to(split_container->get_child(2, true)); split_container->add_theme_constant_override("autohide", 0); MessageQueue::get_singleton()->flush(); const int sep_constant = split_container->get_theme_constant("separation"); const Size2i separator_size = 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())); SUBCASE("[SplitContainer] Visibility based on child count") { split_container->remove_child(child_a); split_container->remove_child(child_b); MessageQueue::get_singleton()->flush(); // No children, not visible. CHECK_FALSE(dragger->is_visible()); // Add one child, not visible. split_container->add_child(child_a); MessageQueue::get_singleton()->flush(); CHECK_FALSE(dragger->is_visible()); // Two children, visible. split_container->add_child(child_b); MessageQueue::get_singleton()->flush(); CHECK(dragger->is_visible()); // Remove a child, not visible. split_container->remove_child(child_b); MessageQueue::get_singleton()->flush(); CHECK_FALSE(dragger->is_visible()); } SUBCASE("[SplitContainer] Set dragger visibility") { split_container->set_dragger_visibility(SplitContainer::DRAGGER_HIDDEN); MessageQueue::get_singleton()->flush(); check_position(split_container, 0, separator_size.x); // Can't check the visibility since it happens in draw. split_container->set_dragger_visibility(SplitContainer::DRAGGER_HIDDEN_COLLAPSED); MessageQueue::get_singleton()->flush(); check_position(split_container, 0, 0); split_container->set_dragger_visibility(SplitContainer::DRAGGER_VISIBLE); MessageQueue::get_singleton()->flush(); check_position(split_container, 0, separator_size.x); } SUBCASE("[SplitContainer] Not visible when collapsed") { split_container->set_collapsed(true); MessageQueue::get_singleton()->flush(); CHECK_FALSE(dragger->is_visible()); split_container->set_collapsed(false); MessageQueue::get_singleton()->flush(); CHECK(dragger->is_visible()); } memdelete(child_a); memdelete(child_b); memdelete(split_container); } TEST_CASE("[SceneTree][SplitContainer] Collapsed") { DisplayServerMock *DS = (DisplayServerMock *)(DisplayServer::get_singleton()); SplitContainer *split_container = memnew(SplitContainer); split_container->set_size(Size2(500, 500)); SceneTree::get_singleton()->get_root()->add_child(split_container); Control *child_a = memnew(Control); split_container->add_child(child_a); Control *child_b = memnew(Control); split_container->add_child(child_b); MessageQueue::get_singleton()->flush(); const int sep_constant = split_container->get_theme_constant("separation"); const Size2i separator_size = 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())); SUBCASE("[SplitContainer] Dragging and cursor") { split_container->set_collapsed(true); // Cursor is default. SEND_GUI_MOUSE_MOTION_EVENT(Point2(1, 1), MouseButtonMask::NONE, Key::NONE); CHECK(DS->get_cursor_shape() == DisplayServer::CURSOR_ARROW); // Dragger is disabled, cannot drag. SEND_GUI_MOUSE_BUTTON_EVENT(Point2(1, 1), MouseButton::LEFT, MouseButtonMask::LEFT, Key::NONE); MessageQueue::get_singleton()->flush(); check_position(split_container, 0, separator_size.x); CHECK(split_container->get_split_offset() == 0); SEND_GUI_MOUSE_MOTION_EVENT(Point2(10, 1), MouseButtonMask::LEFT, Key::NONE); MessageQueue::get_singleton()->flush(); check_position(split_container, 0, separator_size.x); CHECK(split_container->get_split_offset() == 0); } SUBCASE("[SplitContainer] No expand flags") { int def_pos = 0; split_container->set_split_offset(10); MessageQueue::get_singleton()->flush(); check_position(split_container, def_pos + 10, separator_size.x); split_container->set_collapsed(true); MessageQueue::get_singleton()->flush(); // The split offset is treated as 0 when collapsed. check_position(split_container, def_pos, separator_size.x); CHECK(split_container->get_split_offset() == 10); } SUBCASE("[SplitContainer] First child expanded") { int def_pos = split_container->get_size().x - separator_size.x; child_a->set_h_size_flags(Control::SIZE_EXPAND_FILL); split_container->set_split_offset(-10); MessageQueue::get_singleton()->flush(); check_position(split_container, def_pos - 10, separator_size.x); split_container->set_collapsed(true); MessageQueue::get_singleton()->flush(); // The split offset is treated as 0 when collapsed. check_position(split_container, def_pos, separator_size.x); CHECK(split_container->get_split_offset() == -10); } SUBCASE("[SplitContainer] Second child expanded") { int def_pos = 0; child_b->set_h_size_flags(Control::SIZE_EXPAND_FILL); split_container->set_split_offset(10); MessageQueue::get_singleton()->flush(); check_position(split_container, def_pos + 10, separator_size.x); split_container->set_collapsed(true); MessageQueue::get_singleton()->flush(); // The split offset is treated as 0 when collapsed. check_position(split_container, def_pos, separator_size.x); CHECK(split_container->get_split_offset() == 10); } SUBCASE("[SplitContainer] Both children expanded") { int def_pos = (split_container->get_size().y - separator_size.y) / 2; child_a->set_h_size_flags(Control::SIZE_EXPAND_FILL); child_b->set_h_size_flags(Control::SIZE_EXPAND_FILL); split_container->set_split_offset(10); MessageQueue::get_singleton()->flush(); check_position(split_container, def_pos + 10, separator_size.x); split_container->set_collapsed(true); MessageQueue::get_singleton()->flush(); // The split offset is treated as 0 when collapsed. check_position(split_container, def_pos, separator_size.x); CHECK(split_container->get_split_offset() == 10); } memdelete(child_a); memdelete(child_b); memdelete(split_container); } TEST_CASE("[SceneTree][SplitContainer] Cursor shape") { DisplayServerMock *DS = (DisplayServerMock *)(DisplayServer::get_singleton()); SplitContainer *split_container = memnew(SplitContainer); split_container->set_size(Size2(500, 500)); SceneTree::get_singleton()->get_root()->add_child(split_container); Control *child_a = memnew(Control); split_container->add_child(child_a); Control *child_b = memnew(Control); split_container->add_child(child_b); MessageQueue::get_singleton()->flush(); Point2 on_dragger = Point2(1, 1); Point2 not_on_dragger = Point2(50, 50); // Default cursor shape. SEND_GUI_MOUSE_MOTION_EVENT(not_on_dragger, MouseButtonMask::NONE, Key::NONE); CHECK(DS->get_cursor_shape() == DisplayServer::CURSOR_ARROW); // Horizontal cursor shape. SEND_GUI_MOUSE_MOTION_EVENT(on_dragger, MouseButtonMask::NONE, Key::NONE); CHECK(DS->get_cursor_shape() == DisplayServer::CURSOR_HSPLIT); // Vertical cursor shape. split_container->set_vertical(true); SEND_GUI_MOUSE_MOTION_EVENT(on_dragger, MouseButtonMask::NONE, Key::NONE); CHECK(DS->get_cursor_shape() == DisplayServer::CURSOR_VSPLIT); // Move off, default cursor shape. SEND_GUI_MOUSE_MOTION_EVENT(not_on_dragger, MouseButtonMask::NONE, Key::NONE); CHECK(DS->get_cursor_shape() == DisplayServer::CURSOR_ARROW); memdelete(child_a); memdelete(child_b); memdelete(split_container); } TEST_CASE("[SceneTree][SplitContainer] Two children") { SplitContainer *split_container = memnew(SplitContainer); split_container->set_size(Size2(500, 500)); SceneTree::get_singleton()->get_root()->add_child(split_container); Control *child_a = memnew(Control); Control *child_b = memnew(Control); split_container->add_child(child_a); split_container->add_child(child_b); MessageQueue::get_singleton()->flush(); const int sep_constant = split_container->get_theme_constant("separation"); const Size2i separator_size = 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())); SUBCASE("[SplitContainer] Minimum size") { // Minimum size is the sum of both children's minimum sizes and the separator depending on the vertical axis. child_a->set_custom_minimum_size(Size2(100, 200)); child_b->set_custom_minimum_size(Size2(100, 200)); MessageQueue::get_singleton()->flush(); Size2 min_size = split_container->get_minimum_size(); CHECK(min_size.x == 200 + separator_size.x); CHECK(min_size.y == 200); split_container->set_vertical(true); MessageQueue::get_singleton()->flush(); min_size = split_container->get_minimum_size(); CHECK(min_size.x == 100); CHECK(min_size.y == 400 + separator_size.y); } SUBCASE("[SplitContainer] Default position") { SUBCASE("[SplitContainer] Vertical") { // Make sure clamping the split offset doesn't change it or the position. split_container->set_vertical(true); // No expand flags set. MessageQueue::get_singleton()->flush(); int def_pos = 0; check_position(split_container, def_pos, separator_size.y, false); split_container->clamp_split_offset(); MessageQueue::get_singleton()->flush(); CHECK(split_container->get_split_offset() == 0); check_position(split_container, def_pos, separator_size.y, false); // First expand flags set. child_a->set_v_size_flags(Control::SIZE_EXPAND_FILL); child_b->set_v_size_flags(Control::SIZE_FILL); MessageQueue::get_singleton()->flush(); def_pos = split_container->get_size().y - separator_size.y; check_position(split_container, def_pos, separator_size.y, false); split_container->clamp_split_offset(); MessageQueue::get_singleton()->flush(); CHECK(split_container->get_split_offset() == 0); check_position(split_container, def_pos, separator_size.y, false); // Second expand flags set. child_a->set_v_size_flags(Control::SIZE_FILL); child_b->set_v_size_flags(Control::SIZE_EXPAND_FILL); MessageQueue::get_singleton()->flush(); def_pos = 0; check_position(split_container, 0, separator_size.y, false); split_container->clamp_split_offset(); MessageQueue::get_singleton()->flush(); CHECK(split_container->get_split_offset() == 0); check_position(split_container, def_pos, separator_size.y, false); // Both expand flags set. child_a->set_v_size_flags(Control::SIZE_EXPAND_FILL); child_b->set_v_size_flags(Control::SIZE_EXPAND_FILL); MessageQueue::get_singleton()->flush(); def_pos = (split_container->get_size().y - separator_size.y) / 2; check_position(split_container, def_pos, separator_size.y, false); split_container->clamp_split_offset(); MessageQueue::get_singleton()->flush(); CHECK(split_container->get_split_offset() == 0); check_position(split_container, def_pos, separator_size.y, false); // Unequal stretch ratios. child_a->set_stretch_ratio(2.0); MessageQueue::get_singleton()->flush(); def_pos = (split_container->get_size().y * 2 / 3) - separator_size.y / 2; check_position(split_container, def_pos, separator_size.y, false); split_container->clamp_split_offset(); MessageQueue::get_singleton()->flush(); CHECK(split_container->get_split_offset() == 0); check_position(split_container, def_pos, separator_size.y, false); } SUBCASE("[SplitContainer] Right to left") { split_container->set_layout_direction(Control::LAYOUT_DIRECTION_RTL); split_container->set_position(Point2(0, 0)); // No expand flags set. MessageQueue::get_singleton()->flush(); int def_pos = 0; check_position_rtl(split_container, def_pos, separator_size.y); split_container->clamp_split_offset(); MessageQueue::get_singleton()->flush(); CHECK(split_container->get_split_offset() == 0); check_position_rtl(split_container, def_pos, separator_size.y); // First expand flags set. child_a->set_h_size_flags(Control::SIZE_EXPAND_FILL); child_b->set_h_size_flags(Control::SIZE_FILL); MessageQueue::get_singleton()->flush(); def_pos = split_container->get_size().y - separator_size.y; check_position_rtl(split_container, def_pos, separator_size.y); split_container->clamp_split_offset(); MessageQueue::get_singleton()->flush(); CHECK(split_container->get_split_offset() == 0); check_position_rtl(split_container, def_pos, separator_size.y); // Second expand flags set. child_a->set_h_size_flags(Control::SIZE_FILL); child_b->set_h_size_flags(Control::SIZE_EXPAND_FILL); MessageQueue::get_singleton()->flush(); def_pos = 0; check_position_rtl(split_container, 0, separator_size.y); split_container->clamp_split_offset(); MessageQueue::get_singleton()->flush(); CHECK(split_container->get_split_offset() == 0); check_position_rtl(split_container, def_pos, separator_size.y); // Both expand flags set. child_a->set_h_size_flags(Control::SIZE_EXPAND_FILL); child_b->set_h_size_flags(Control::SIZE_EXPAND_FILL); MessageQueue::get_singleton()->flush(); def_pos = (split_container->get_size().y - separator_size.y) / 2; check_position_rtl(split_container, def_pos, separator_size.y); split_container->clamp_split_offset(); MessageQueue::get_singleton()->flush(); CHECK(split_container->get_split_offset() == 0); check_position_rtl(split_container, def_pos, separator_size.y); // Unequal stretch ratios. child_a->set_stretch_ratio(2.0); MessageQueue::get_singleton()->flush(); def_pos = (split_container->get_size().y * 2 / 3) - separator_size.y / 2; check_position_rtl(split_container, def_pos, separator_size.y); split_container->clamp_split_offset(); MessageQueue::get_singleton()->flush(); CHECK(split_container->get_split_offset() == 0); check_position_rtl(split_container, def_pos, separator_size.y); } SUBCASE("[SplitContainer] No expand flags") { int def_pos = 0; check_position(split_container, def_pos, separator_size.x); split_container->clamp_split_offset(); MessageQueue::get_singleton()->flush(); CHECK(split_container->get_split_offset() == 0); check_position(split_container, def_pos, separator_size.x); // Minimum sizes affect default position. // First child with minimum size. child_a->set_custom_minimum_size(Size2(400, 0)); MessageQueue::get_singleton()->flush(); def_pos = 400; check_position(split_container, def_pos, separator_size.x); split_container->clamp_split_offset(); MessageQueue::get_singleton()->flush(); CHECK(split_container->get_split_offset() == def_pos); check_position(split_container, def_pos, separator_size.x); // Second child with minimum size. child_a->set_custom_minimum_size(Size2(0, 0)); child_b->set_custom_minimum_size(Size2(400, 0)); MessageQueue::get_singleton()->flush(); def_pos = split_container->get_size().x - 400 - separator_size.x; check_position(split_container, def_pos, separator_size.x); split_container->clamp_split_offset(); MessageQueue::get_singleton()->flush(); CHECK(split_container->get_split_offset() == def_pos); check_position(split_container, def_pos, separator_size.x); // Both children with minimum size. child_a->set_custom_minimum_size(Size2(200, 0)); child_b->set_custom_minimum_size(Size2(288, 0)); MessageQueue::get_singleton()->flush(); def_pos = 200; check_position(split_container, def_pos, separator_size.x); split_container->clamp_split_offset(); MessageQueue::get_singleton()->flush(); CHECK(split_container->get_split_offset() == def_pos); check_position(split_container, def_pos, separator_size.x); } SUBCASE("[SplitContainer] First child expanded") { const int def_pos = split_container->get_size().x - separator_size.x; child_a->set_h_size_flags(Control::SIZE_EXPAND_FILL); MessageQueue::get_singleton()->flush(); check_position(split_container, def_pos, separator_size.x); split_container->clamp_split_offset(); MessageQueue::get_singleton()->flush(); CHECK(split_container->get_split_offset() == 0); check_position(split_container, def_pos, separator_size.x); // Minimum sizes affect default position. // First child with minimum size. child_a->set_custom_minimum_size(Size2(400, 0)); MessageQueue::get_singleton()->flush(); check_position(split_container, def_pos, separator_size.x); split_container->clamp_split_offset(); MessageQueue::get_singleton()->flush(); CHECK(split_container->get_split_offset() == 0); check_position(split_container, def_pos, separator_size.x); // Second child with minimum size. child_a->set_custom_minimum_size(Size2(0, 0)); child_b->set_custom_minimum_size(Size2(400, 0)); MessageQueue::get_singleton()->flush(); int pos = split_container->get_size().x - 400 - separator_size.x; check_position(split_container, pos, separator_size.x); split_container->clamp_split_offset(); MessageQueue::get_singleton()->flush(); CHECK(split_container->get_split_offset() == pos - def_pos); check_position(split_container, pos, separator_size.x); // Both children with minimum size. child_a->set_custom_minimum_size(Size2(200, 0)); child_b->set_custom_minimum_size(Size2(288, 0)); MessageQueue::get_singleton()->flush(); pos = 200; check_position(split_container, pos, separator_size.x); split_container->clamp_split_offset(); MessageQueue::get_singleton()->flush(); CHECK(split_container->get_split_offset() == pos - def_pos); check_position(split_container, pos, separator_size.x); } SUBCASE("[SplitContainer] Second child expanded") { int def_pos = 0; child_b->set_h_size_flags(Control::SIZE_EXPAND_FILL); MessageQueue::get_singleton()->flush(); check_position(split_container, def_pos, separator_size.x); split_container->clamp_split_offset(); MessageQueue::get_singleton()->flush(); CHECK(split_container->get_split_offset() == 0); check_position(split_container, def_pos, separator_size.x); // Minimum sizes affect default position. // First child with minimum size. child_a->set_custom_minimum_size(Size2(400, 0)); MessageQueue::get_singleton()->flush(); def_pos = 400; check_position(split_container, def_pos, separator_size.x); split_container->clamp_split_offset(); MessageQueue::get_singleton()->flush(); CHECK(split_container->get_split_offset() == def_pos); check_position(split_container, def_pos, separator_size.x); // Second child with minimum size. child_a->set_custom_minimum_size(Size2(0, 0)); child_b->set_custom_minimum_size(Size2(400, 0)); MessageQueue::get_singleton()->flush(); def_pos = 500 - 400 - separator_size.x; check_position(split_container, def_pos, separator_size.x); split_container->clamp_split_offset(); MessageQueue::get_singleton()->flush(); CHECK(split_container->get_split_offset() == def_pos); check_position(split_container, def_pos, separator_size.x); // Both children with minimum size. child_a->set_custom_minimum_size(Size2(200, 0)); child_b->set_custom_minimum_size(Size2(288, 0)); MessageQueue::get_singleton()->flush(); def_pos = 200; check_position(split_container, def_pos, separator_size.x); split_container->clamp_split_offset(); MessageQueue::get_singleton()->flush(); CHECK(split_container->get_split_offset() == def_pos); check_position(split_container, def_pos, separator_size.x); } SUBCASE("[SplitContainer] Both children expanded") { const int def_pos = (split_container->get_size().x - separator_size.x) / 2; child_a->set_h_size_flags(Control::SIZE_EXPAND_FILL); child_b->set_h_size_flags(Control::SIZE_EXPAND_FILL); MessageQueue::get_singleton()->flush(); check_position(split_container, def_pos, separator_size.x); split_container->clamp_split_offset(); MessageQueue::get_singleton()->flush(); CHECK(split_container->get_split_offset() == 0); check_position(split_container, def_pos, separator_size.x); // Minimum sizes affect default position. // First child with minimum size. child_a->set_custom_minimum_size(Size2(400, 0)); MessageQueue::get_singleton()->flush(); int pos = 400; check_position(split_container, pos, separator_size.x); split_container->clamp_split_offset(); MessageQueue::get_singleton()->flush(); CHECK(split_container->get_split_offset() == pos - def_pos); check_position(split_container, pos, separator_size.x); // Second child with minimum size. child_a->set_custom_minimum_size(Size2(0, 0)); child_b->set_custom_minimum_size(Size2(400, 0)); MessageQueue::get_singleton()->flush(); pos = split_container->get_size().x - 400 - separator_size.x; check_position(split_container, pos, separator_size.x); split_container->clamp_split_offset(); MessageQueue::get_singleton()->flush(); CHECK(split_container->get_split_offset() == pos - def_pos); check_position(split_container, pos, separator_size.x); // Both children with minimum size. child_a->set_custom_minimum_size(Size2(200, 0)); child_b->set_custom_minimum_size(Size2(288, 0)); MessageQueue::get_singleton()->flush(); pos = 200; check_position(split_container, pos, separator_size.x); split_container->clamp_split_offset(); MessageQueue::get_singleton()->flush(); CHECK(split_container->get_split_offset() == pos - def_pos); check_position(split_container, pos, separator_size.x); } SUBCASE("[SplitContainer] Unequal stretch ratios") { const int def_pos = (split_container->get_size().x * 2 / 3) - separator_size.x / 2; child_a->set_h_size_flags(Control::SIZE_EXPAND_FILL); child_b->set_h_size_flags(Control::SIZE_EXPAND_FILL); child_a->set_stretch_ratio(2.0); MessageQueue::get_singleton()->flush(); check_position(split_container, def_pos, separator_size.x); split_container->clamp_split_offset(); MessageQueue::get_singleton()->flush(); CHECK(split_container->get_split_offset() == 0); check_position(split_container, def_pos, separator_size.x); // Minimum sizes affect default position. // First child with minimum size. child_a->set_custom_minimum_size(Size2(400, 0)); MessageQueue::get_singleton()->flush(); int pos = 400; check_position(split_container, pos, separator_size.x); split_container->clamp_split_offset(); MessageQueue::get_singleton()->flush(); CHECK(split_container->get_split_offset() == pos - def_pos); check_position(split_container, pos, separator_size.x); // Second child with minimum size. child_a->set_custom_minimum_size(Size2(0, 0)); child_b->set_custom_minimum_size(Size2(400, 0)); MessageQueue::get_singleton()->flush(); pos = split_container->get_size().x - 400 - separator_size.x; check_position(split_container, pos, separator_size.x); split_container->clamp_split_offset(); MessageQueue::get_singleton()->flush(); CHECK(split_container->get_split_offset() == pos - def_pos); check_position(split_container, pos, separator_size.x); // Both children with minimum size. child_a->set_custom_minimum_size(Size2(200, 0)); child_b->set_custom_minimum_size(Size2(288, 0)); MessageQueue::get_singleton()->flush(); pos = 200; check_position(split_container, pos, separator_size.x); split_container->clamp_split_offset(); MessageQueue::get_singleton()->flush(); CHECK(split_container->get_split_offset() == pos - def_pos); check_position(split_container, pos, separator_size.x); } } SUBCASE("[SplitContainer] Set split offset") { SUBCASE("[SplitContainer] Right to left") { split_container->set_layout_direction(Control::LAYOUT_DIRECTION_RTL); split_container->set_position(Point2(0, 0)); int def_pos = 0; // Positive. split_container->set_split_offset(10); MessageQueue::get_singleton()->flush(); CHECK(split_container->get_split_offset() == 10); check_position_rtl(split_container, def_pos + 10, separator_size.x); // Negative. split_container->set_split_offset(-10); MessageQueue::get_singleton()->flush(); CHECK(split_container->get_split_offset() == -10); check_position_rtl(split_container, def_pos, separator_size.x); } SUBCASE("[SplitContainer] No expand flags") { int def_pos = 0; // Positive. split_container->set_split_offset(10); MessageQueue::get_singleton()->flush(); CHECK(split_container->get_split_offset() == 10); check_position(split_container, def_pos + 10, separator_size.x); // Negative. split_container->set_split_offset(-10); MessageQueue::get_singleton()->flush(); CHECK(split_container->get_split_offset() == -10); check_position(split_container, def_pos, separator_size.x); // Clamped. split_container->set_split_offset(1000); MessageQueue::get_singleton()->flush(); CHECK(split_container->get_split_offset() == 1000); check_position(split_container, split_container->get_size().x - separator_size.x, separator_size.x); } SUBCASE("[SplitContainer] First child expanded") { int def_pos = split_container->get_size().x - separator_size.x; child_a->set_h_size_flags(Control::SIZE_EXPAND_FILL); MessageQueue::get_singleton()->flush(); // Positive. split_container->set_split_offset(10); MessageQueue::get_singleton()->flush(); CHECK(split_container->get_split_offset() == 10); check_position(split_container, def_pos, separator_size.x); // Negative. split_container->set_split_offset(-10); MessageQueue::get_singleton()->flush(); CHECK(split_container->get_split_offset() == -10); check_position(split_container, def_pos - 10, separator_size.x); // Clamped. split_container->set_split_offset(-1000); MessageQueue::get_singleton()->flush(); CHECK(split_container->get_split_offset() == -1000); check_position(split_container, 0, separator_size.x); } SUBCASE("[SplitContainer] Second child expanded") { int def_pos = 0; child_b->set_h_size_flags(Control::SIZE_EXPAND_FILL); MessageQueue::get_singleton()->flush(); // Positive. split_container->set_split_offset(10); MessageQueue::get_singleton()->flush(); CHECK(split_container->get_split_offset() == 10); check_position(split_container, def_pos + 10, separator_size.x); // Negative. split_container->set_split_offset(-10); MessageQueue::get_singleton()->flush(); CHECK(split_container->get_split_offset() == -10); check_position(split_container, def_pos, separator_size.x); // Clamped. split_container->set_split_offset(1000); MessageQueue::get_singleton()->flush(); CHECK(split_container->get_split_offset() == 1000); check_position(split_container, split_container->get_size().x - separator_size.x, separator_size.x); } SUBCASE("[SplitContainer] Both children expanded") { int def_pos = (split_container->get_size().x - separator_size.x) / 2; child_a->set_h_size_flags(Control::SIZE_EXPAND_FILL); child_b->set_h_size_flags(Control::SIZE_EXPAND_FILL); MessageQueue::get_singleton()->flush(); // Positive. split_container->set_split_offset(10); MessageQueue::get_singleton()->flush(); CHECK(split_container->get_split_offset() == 10); check_position(split_container, def_pos + 10, separator_size.x); // Negative. split_container->set_split_offset(-10); MessageQueue::get_singleton()->flush(); CHECK(split_container->get_split_offset() == -10); check_position(split_container, def_pos - 10, separator_size.x); // Clamped positive. split_container->set_split_offset(1000); MessageQueue::get_singleton()->flush(); CHECK(split_container->get_split_offset() == 1000); check_position(split_container, split_container->get_size().x - separator_size.x, separator_size.x); // Clamped negative. split_container->set_split_offset(-1000); MessageQueue::get_singleton()->flush(); CHECK(split_container->get_split_offset() == -1000); check_position(split_container, 0, separator_size.x); } SUBCASE("[SplitContainer] Unequal stretch ratios") { int def_pos = (split_container->get_size().x * 2 / 3) - separator_size.x / 2; child_a->set_h_size_flags(Control::SIZE_EXPAND_FILL); child_b->set_h_size_flags(Control::SIZE_EXPAND_FILL); child_a->set_stretch_ratio(2.0); MessageQueue::get_singleton()->flush(); // Positive. split_container->set_split_offset(10); MessageQueue::get_singleton()->flush(); CHECK(split_container->get_split_offset() == 10); check_position(split_container, def_pos + 10, separator_size.x); // Negative. split_container->set_split_offset(-10); MessageQueue::get_singleton()->flush(); CHECK(split_container->get_split_offset() == -10); check_position(split_container, def_pos - 10, separator_size.x); // Clamped positive. split_container->set_split_offset(1000); MessageQueue::get_singleton()->flush(); CHECK(split_container->get_split_offset() == 1000); check_position(split_container, split_container->get_size().x - separator_size.x, separator_size.x); // Clamped negative. split_container->set_split_offset(-1000); MessageQueue::get_singleton()->flush(); CHECK(split_container->get_split_offset() == -1000); check_position(split_container, 0, separator_size.x); } } SUBCASE("[SplitContainer] Keep split offset when changing minimum size") { SUBCASE("[SplitContainer] No expand flags") { int def_pos = 0; split_container->set_split_offset(100); child_a->set_custom_minimum_size(Size2(10, 0)); MessageQueue::get_singleton()->flush(); CHECK(split_container->get_split_offset() == 100); check_position(split_container, def_pos + 100, separator_size.x); child_a->set_custom_minimum_size(Size2(50, 0)); MessageQueue::get_singleton()->flush(); CHECK(split_container->get_split_offset() == 100); check_position(split_container, def_pos + 100, separator_size.x); } SUBCASE("[SplitContainer] First child expanded") { int def_pos = split_container->get_size().x - separator_size.x; child_a->set_h_size_flags(Control::SIZE_EXPAND_FILL); MessageQueue::get_singleton()->flush(); split_container->set_split_offset(-100); child_b->set_custom_minimum_size(Size2(10, 0)); MessageQueue::get_singleton()->flush(); CHECK(split_container->get_split_offset() == -100); check_position(split_container, def_pos - 100, separator_size.x); child_b->set_custom_minimum_size(Size2(50, 0)); MessageQueue::get_singleton()->flush(); CHECK(split_container->get_split_offset() == -100); check_position(split_container, def_pos - 100, separator_size.x); } SUBCASE("[SplitContainer] Second child expanded") { int def_pos = 0; child_b->set_h_size_flags(Control::SIZE_EXPAND_FILL); MessageQueue::get_singleton()->flush(); split_container->set_split_offset(100); child_a->set_custom_minimum_size(Size2(10, 0)); MessageQueue::get_singleton()->flush(); CHECK(split_container->get_split_offset() == 100); check_position(split_container, def_pos + 100, separator_size.x); child_a->set_custom_minimum_size(Size2(50, 0)); MessageQueue::get_singleton()->flush(); CHECK(split_container->get_split_offset() == 100); check_position(split_container, def_pos + 100, separator_size.x); } SUBCASE("[SplitContainer] Both children expanded") { int def_pos = (split_container->get_size().x - separator_size.x) / 2; child_a->set_h_size_flags(Control::SIZE_EXPAND_FILL); child_b->set_h_size_flags(Control::SIZE_EXPAND_FILL); MessageQueue::get_singleton()->flush(); split_container->set_split_offset(20); child_a->set_custom_minimum_size(Size2(10, 0)); child_b->set_custom_minimum_size(Size2(10, 0)); MessageQueue::get_singleton()->flush(); CHECK(split_container->get_split_offset() == 20); check_position(split_container, def_pos + 20, separator_size.x); child_a->set_custom_minimum_size(Size2(50, 0)); child_b->set_custom_minimum_size(Size2(50, 0)); MessageQueue::get_singleton()->flush(); CHECK(split_container->get_split_offset() == 20); check_position(split_container, def_pos + 20, separator_size.x); } } SUBCASE("[SplitContainer] Resize split container") { SUBCASE("[SplitContainer] No expand flags") { int def_pos = 0; // Increase the size. split_container->set_size(Size2(600, 500)); MessageQueue::get_singleton()->flush(); check_position(split_container, def_pos, separator_size.x); // Decrease the size. split_container->set_size(Size2(400, 500)); MessageQueue::get_singleton()->flush(); check_position(split_container, def_pos, separator_size.x); // Change size with a split offset. split_container->set_split_offset(100); MessageQueue::get_singleton()->flush(); check_position(split_container, def_pos + 100, separator_size.x); split_container->set_size(Size2(500, 500)); MessageQueue::get_singleton()->flush(); check_position(split_container, def_pos + 100, separator_size.x); CHECK(split_container->get_split_offset() == 100); // Change size so that the first child changes size. split_container->set_size(Size2(80, 500)); MessageQueue::get_singleton()->flush(); check_position(split_container, 80 - separator_size.x, separator_size.x); CHECK(split_container->get_split_offset() == 100); // Increase size again. split_container->set_size(Size2(500, 500)); MessageQueue::get_singleton()->flush(); check_position(split_container, def_pos + 100, separator_size.x); CHECK(split_container->get_split_offset() == 100); } SUBCASE("[SplitContainer] First child expanded") { int def_pos = split_container->get_size().x - separator_size.x; child_a->set_h_size_flags(Control::SIZE_EXPAND_FILL); MessageQueue::get_singleton()->flush(); // Increase the size. split_container->set_size(Size2(600, 500)); def_pos = split_container->get_size().x - separator_size.x; MessageQueue::get_singleton()->flush(); check_position(split_container, def_pos, separator_size.x); // Decrease the size. split_container->set_size(Size2(400, 500)); def_pos = split_container->get_size().x - separator_size.x; MessageQueue::get_singleton()->flush(); check_position(split_container, def_pos, separator_size.x); // Change size with a split offset. split_container->set_split_offset(-100); MessageQueue::get_singleton()->flush(); check_position(split_container, def_pos - 100, separator_size.x); split_container->set_size(Size2(500, 500)); def_pos = split_container->get_size().x - separator_size.x; MessageQueue::get_singleton()->flush(); check_position(split_container, def_pos - 100, separator_size.x); CHECK(split_container->get_split_offset() == -100); // Change size so that the second child changes size. split_container->set_size(Size2(80, 500)); MessageQueue::get_singleton()->flush(); check_position(split_container, 0, separator_size.x); CHECK(split_container->get_split_offset() == -100); // Increase size again. split_container->set_size(Size2(500, 500)); MessageQueue::get_singleton()->flush(); check_position(split_container, def_pos - 100, separator_size.x); CHECK(split_container->get_split_offset() == -100); } SUBCASE("[SplitContainer] Second child expanded") { int def_pos = 0; child_b->set_h_size_flags(Control::SIZE_EXPAND_FILL); MessageQueue::get_singleton()->flush(); // Increase the size. split_container->set_size(Size2(600, 500)); MessageQueue::get_singleton()->flush(); check_position(split_container, def_pos, separator_size.x); // Decrease the size. split_container->set_size(Size2(400, 500)); MessageQueue::get_singleton()->flush(); check_position(split_container, def_pos, separator_size.x); // Change size with a split offset. split_container->set_split_offset(100); MessageQueue::get_singleton()->flush(); check_position(split_container, def_pos + 100, separator_size.x); split_container->set_size(Size2(500, 500)); MessageQueue::get_singleton()->flush(); check_position(split_container, def_pos + 100, separator_size.x); CHECK(split_container->get_split_offset() == 100); // Change size so that the first child changes size. split_container->set_size(Size2(80, 500)); MessageQueue::get_singleton()->flush(); check_position(split_container, 80 - separator_size.x, separator_size.x); CHECK(split_container->get_split_offset() == 100); // Increase size again. split_container->set_size(Size2(500, 500)); MessageQueue::get_singleton()->flush(); check_position(split_container, def_pos + 100, separator_size.x); CHECK(split_container->get_split_offset() == 100); } SUBCASE("[SplitContainer] Both children expanded") { int def_pos = (split_container->get_size().x - separator_size.x) / 2; child_a->set_h_size_flags(Control::SIZE_EXPAND_FILL); child_b->set_h_size_flags(Control::SIZE_EXPAND_FILL); MessageQueue::get_singleton()->flush(); // Increase the size. split_container->set_size(Size2(600, 500)); def_pos = (split_container->get_size().x - separator_size.x) / 2; MessageQueue::get_singleton()->flush(); check_position(split_container, def_pos, separator_size.x); // Decrease the size. split_container->set_size(Size2(400, 500)); def_pos = (split_container->get_size().x - separator_size.x) / 2; MessageQueue::get_singleton()->flush(); check_position(split_container, def_pos, separator_size.x); // Change size with a split offset. split_container->set_split_offset(100); MessageQueue::get_singleton()->flush(); check_position(split_container, def_pos + 100, separator_size.x); split_container->set_size(Size2(500, 500)); def_pos = (split_container->get_size().x - separator_size.x) / 2; MessageQueue::get_singleton()->flush(); check_position(split_container, def_pos + 100, separator_size.x); CHECK(split_container->get_split_offset() == 100); // Change size so that the second child is minimized. split_container->set_size(Size2(80, 500)); MessageQueue::get_singleton()->flush(); check_position(split_container, 80 - separator_size.x, separator_size.x); CHECK(split_container->get_split_offset() == 100); // Increase size again. split_container->set_size(Size2(500, 500)); def_pos = (split_container->get_size().x - separator_size.x) / 2; MessageQueue::get_singleton()->flush(); check_position(split_container, def_pos + 100, separator_size.x); CHECK(split_container->get_split_offset() == 100); } SUBCASE("[SplitContainer] Unequal stretch ratios") { int def_pos = (split_container->get_size().x * 2 / 3) - separator_size.x / 2; child_a->set_h_size_flags(Control::SIZE_EXPAND_FILL); child_b->set_h_size_flags(Control::SIZE_EXPAND_FILL); child_a->set_stretch_ratio(2.0); MessageQueue::get_singleton()->flush(); // Increase the size. split_container->set_size(Size2(600, 500)); def_pos = (split_container->get_size().x * 2 / 3) - separator_size.x / 2; MessageQueue::get_singleton()->flush(); check_position(split_container, def_pos, separator_size.x); // Decrease the size. split_container->set_size(Size2(400, 500)); def_pos = (split_container->get_size().x * 2 / 3) - separator_size.x / 2; MessageQueue::get_singleton()->flush(); check_position(split_container, def_pos, separator_size.x); // Change size with a split offset. split_container->set_split_offset(100); MessageQueue::get_singleton()->flush(); check_position(split_container, def_pos + 100, separator_size.x); split_container->set_size(Size2(500, 500)); def_pos = (split_container->get_size().x * 2 / 3) - separator_size.x / 2; MessageQueue::get_singleton()->flush(); check_position(split_container, def_pos + 100, separator_size.x); CHECK(split_container->get_split_offset() == 100); // Change size so that the second child is minimized. split_container->set_size(Size2(80, 500)); MessageQueue::get_singleton()->flush(); check_position(split_container, 80 - separator_size.x, separator_size.x); CHECK(split_container->get_split_offset() == 100); // Increase size again. split_container->set_size(Size2(500, 500)); def_pos = (split_container->get_size().x * 2 / 3) - separator_size.x / 2; MessageQueue::get_singleton()->flush(); check_position(split_container, def_pos + 100, separator_size.x); CHECK(split_container->get_split_offset() == 100); } } SUBCASE("[SplitContainer] Drag") { SUBCASE("[SplitContainer] Vertical, no expand flags") { SIGNAL_WATCH(split_container, "dragged"); Array signal_args; signal_args.push_back(Array()); ((Array)signal_args[0]).push_back(0); split_container->set_vertical(true); Point2 mouse_offset = Point2(1, 1); int dragger_pos = 0; int split_dragger_ofs = 0; // Grab the dragger. SEND_GUI_MOUSE_BUTTON_EVENT(mouse_offset + Point2(0, dragger_pos), MouseButton::LEFT, MouseButtonMask::LEFT, Key::NONE); MessageQueue::get_singleton()->flush(); check_position(split_container, dragger_pos, separator_size.y, false); CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs); SIGNAL_CHECK_FALSE("dragged"); // Move the dragger. dragger_pos = 10; SEND_GUI_MOUSE_MOTION_EVENT(mouse_offset + Point2(0, dragger_pos), MouseButtonMask::LEFT, Key::NONE); MessageQueue::get_singleton()->flush(); check_position(split_container, dragger_pos, separator_size.y, false); CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs); // It is clamped. split_container->clamp_split_offset(); CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs); ((Array)signal_args[0])[0] = split_container->get_split_offset(); SIGNAL_CHECK("dragged", signal_args); // Move down. dragger_pos = 400; SEND_GUI_MOUSE_MOTION_EVENT(mouse_offset + Point2(0, dragger_pos), MouseButtonMask::LEFT, Key::NONE); MessageQueue::get_singleton()->flush(); check_position(split_container, dragger_pos, separator_size.y, false); CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs); ((Array)signal_args[0])[0] = split_container->get_split_offset(); SIGNAL_CHECK("dragged", signal_args); // Moves even when mouse is outside. dragger_pos = split_container->get_size().y - separator_size.y; SEND_GUI_MOUSE_MOTION_EVENT(mouse_offset + Point2(0, 1000), MouseButtonMask::LEFT, Key::NONE); MessageQueue::get_singleton()->flush(); check_position(split_container, dragger_pos, separator_size.y, false); CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs); ((Array)signal_args[0])[0] = split_container->get_split_offset(); SIGNAL_CHECK("dragged", signal_args); // Move up. dragger_pos = 100; SEND_GUI_MOUSE_MOTION_EVENT(mouse_offset + Point2(0, dragger_pos), MouseButtonMask::LEFT, Key::NONE); MessageQueue::get_singleton()->flush(); check_position(split_container, dragger_pos, separator_size.y, false); CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs); ((Array)signal_args[0])[0] = split_container->get_split_offset(); SIGNAL_CHECK("dragged", signal_args); // Release. SEND_GUI_MOUSE_BUTTON_RELEASED_EVENT(mouse_offset + Point2(0, dragger_pos), MouseButton::LEFT, MouseButtonMask::NONE, Key::NONE); MessageQueue::get_singleton()->flush(); check_position(split_container, dragger_pos, separator_size.y, false); CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs); SIGNAL_CHECK_FALSE("dragged"); // No longer moves with the mouse. SEND_GUI_MOUSE_MOTION_EVENT(mouse_offset + Point2(0, 200), MouseButtonMask::NONE, Key::NONE); MessageQueue::get_singleton()->flush(); check_position(split_container, dragger_pos, separator_size.y, false); CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs); SIGNAL_CHECK_FALSE("dragged"); SIGNAL_UNWATCH(split_container, "dragged"); } SUBCASE("[SplitContainer] No expand flags") { Point2 mouse_offset = Point2(1, 1); int dragger_pos = 0; int split_dragger_ofs = 0; // Grab the dragger. SEND_GUI_MOUSE_BUTTON_EVENT(mouse_offset + Point2(dragger_pos, 0), MouseButton::LEFT, MouseButtonMask::LEFT, Key::NONE); MessageQueue::get_singleton()->flush(); check_position(split_container, dragger_pos, separator_size.x); CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs); // Move the dragger. dragger_pos = 10; SEND_GUI_MOUSE_MOTION_EVENT(mouse_offset + Point2(dragger_pos, 0), MouseButtonMask::LEFT, Key::NONE); MessageQueue::get_singleton()->flush(); check_position(split_container, dragger_pos, separator_size.x); CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs); // It is clamped. split_container->clamp_split_offset(); CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs); // Continue moving. dragger_pos = 400; SEND_GUI_MOUSE_MOTION_EVENT(mouse_offset + Point2(dragger_pos, 0), MouseButtonMask::LEFT, Key::NONE); MessageQueue::get_singleton()->flush(); check_position(split_container, dragger_pos, separator_size.x); CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs); // Moves even when mouse is outside. dragger_pos = split_container->get_size().x - separator_size.x; SEND_GUI_MOUSE_MOTION_EVENT(mouse_offset + Point2(1000, 0), MouseButtonMask::LEFT, Key::NONE); MessageQueue::get_singleton()->flush(); check_position(split_container, dragger_pos, separator_size.x); CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs); // Move back in. dragger_pos = 100; SEND_GUI_MOUSE_MOTION_EVENT(mouse_offset + Point2(dragger_pos, 0), MouseButtonMask::LEFT, Key::NONE); MessageQueue::get_singleton()->flush(); check_position(split_container, dragger_pos, separator_size.x); CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs); // Release. SEND_GUI_MOUSE_BUTTON_RELEASED_EVENT(mouse_offset + Point2(dragger_pos, 0), MouseButton::LEFT, MouseButtonMask::NONE, Key::NONE); MessageQueue::get_singleton()->flush(); check_position(split_container, dragger_pos, separator_size.x); CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs); // No longer moves with the mouse. SEND_GUI_MOUSE_MOTION_EVENT(mouse_offset + Point2(200, 0), MouseButtonMask::NONE, Key::NONE); MessageQueue::get_singleton()->flush(); check_position(split_container, dragger_pos, separator_size.x); CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs); } SUBCASE("[SplitContainer] First child expanded") { child_a->set_h_size_flags(Control::SIZE_EXPAND_FILL); MessageQueue::get_singleton()->flush(); Point2 mouse_offset = Point2(1, 1); int dragger_pos = split_container->get_size().x - separator_size.x; int split_dragger_ofs = -dragger_pos; // Grab the dragger. SEND_GUI_MOUSE_BUTTON_EVENT(mouse_offset + Point2(dragger_pos, 0), MouseButton::LEFT, MouseButtonMask::LEFT, Key::NONE); MessageQueue::get_singleton()->flush(); check_position(split_container, dragger_pos, separator_size.x); CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs); // Move the dragger. dragger_pos -= 10; SEND_GUI_MOUSE_MOTION_EVENT(mouse_offset + Point2(dragger_pos, 0), MouseButtonMask::LEFT, Key::NONE); MessageQueue::get_singleton()->flush(); check_position(split_container, dragger_pos, separator_size.x); CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs); // It is clamped. split_container->clamp_split_offset(); CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs); // Continue moving. dragger_pos = 400; SEND_GUI_MOUSE_MOTION_EVENT(mouse_offset + Point2(dragger_pos, 0), MouseButtonMask::LEFT, Key::NONE); MessageQueue::get_singleton()->flush(); check_position(split_container, dragger_pos, separator_size.x); CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs); // Moves even when mouse is outside. dragger_pos = split_container->get_size().x - separator_size.x; SEND_GUI_MOUSE_MOTION_EVENT(mouse_offset + Point2(1000, 0), MouseButtonMask::LEFT, Key::NONE); MessageQueue::get_singleton()->flush(); check_position(split_container, dragger_pos, separator_size.x); CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs); // Move back in. dragger_pos = 100; SEND_GUI_MOUSE_MOTION_EVENT(mouse_offset + Point2(dragger_pos, 0), MouseButtonMask::LEFT, Key::NONE); MessageQueue::get_singleton()->flush(); check_position(split_container, dragger_pos, separator_size.x); CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs); // Release. SEND_GUI_MOUSE_BUTTON_RELEASED_EVENT(mouse_offset + Point2(dragger_pos, 0), MouseButton::LEFT, MouseButtonMask::NONE, Key::NONE); MessageQueue::get_singleton()->flush(); check_position(split_container, dragger_pos, separator_size.x); CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs); // No longer moves with the mouse. SEND_GUI_MOUSE_MOTION_EVENT(mouse_offset + Point2(200, 0), MouseButtonMask::NONE, Key::NONE); MessageQueue::get_singleton()->flush(); check_position(split_container, dragger_pos, separator_size.x); CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs); } SUBCASE("[SplitContainer] Second child expanded") { child_b->set_h_size_flags(Control::SIZE_EXPAND_FILL); MessageQueue::get_singleton()->flush(); Point2 mouse_offset = Point2(1, 1); int dragger_pos = 0; int split_dragger_ofs = 0; // Grab the dragger. SEND_GUI_MOUSE_BUTTON_EVENT(mouse_offset + Point2(dragger_pos, 0), MouseButton::LEFT, MouseButtonMask::LEFT, Key::NONE); MessageQueue::get_singleton()->flush(); check_position(split_container, dragger_pos, separator_size.x); CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs); // Move the dragger. dragger_pos = 10; SEND_GUI_MOUSE_MOTION_EVENT(mouse_offset + Point2(dragger_pos, 0), MouseButtonMask::LEFT, Key::NONE); MessageQueue::get_singleton()->flush(); check_position(split_container, dragger_pos, separator_size.x); CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs); // It is clamped. split_container->clamp_split_offset(); CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs); // Continue moving. dragger_pos = 400; SEND_GUI_MOUSE_MOTION_EVENT(mouse_offset + Point2(dragger_pos, 0), MouseButtonMask::LEFT, Key::NONE); MessageQueue::get_singleton()->flush(); check_position(split_container, dragger_pos, separator_size.x); CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs); // Moves even when mouse is outside. dragger_pos = split_container->get_size().x - separator_size.x; SEND_GUI_MOUSE_MOTION_EVENT(mouse_offset + Point2(1000, 0), MouseButtonMask::LEFT, Key::NONE); MessageQueue::get_singleton()->flush(); check_position(split_container, dragger_pos, separator_size.x); CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs); // Move back in. dragger_pos = 100; SEND_GUI_MOUSE_MOTION_EVENT(mouse_offset + Point2(dragger_pos, 0), MouseButtonMask::LEFT, Key::NONE); MessageQueue::get_singleton()->flush(); check_position(split_container, dragger_pos, separator_size.x); CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs); // Release. SEND_GUI_MOUSE_BUTTON_RELEASED_EVENT(mouse_offset + Point2(dragger_pos, 0), MouseButton::LEFT, MouseButtonMask::NONE, Key::NONE); MessageQueue::get_singleton()->flush(); check_position(split_container, dragger_pos, separator_size.x); CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs); // No longer moves with the mouse. SEND_GUI_MOUSE_MOTION_EVENT(mouse_offset + Point2(200, 0), MouseButtonMask::NONE, Key::NONE); MessageQueue::get_singleton()->flush(); check_position(split_container, dragger_pos, separator_size.x); CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs); } SUBCASE("[SplitContainer] Both children expanded") { child_a->set_h_size_flags(Control::SIZE_EXPAND_FILL); child_b->set_h_size_flags(Control::SIZE_EXPAND_FILL); MessageQueue::get_singleton()->flush(); Point2 mouse_offset = Point2(1, 1); int dragger_pos = (split_container->get_size().x - separator_size.x) / 2; int split_dragger_ofs = -dragger_pos; // Grab the dragger. SEND_GUI_MOUSE_BUTTON_EVENT(mouse_offset + Point2(dragger_pos, 0), MouseButton::LEFT, MouseButtonMask::LEFT, Key::NONE); MessageQueue::get_singleton()->flush(); check_position(split_container, dragger_pos, separator_size.x); CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs); // Move the dragger. dragger_pos += 10; SEND_GUI_MOUSE_MOTION_EVENT(mouse_offset + Point2(dragger_pos, 0), MouseButtonMask::LEFT, Key::NONE); MessageQueue::get_singleton()->flush(); check_position(split_container, dragger_pos, separator_size.x); CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs); // It is clamped. split_container->clamp_split_offset(); CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs); // Continue moving. dragger_pos = 400; SEND_GUI_MOUSE_MOTION_EVENT(mouse_offset + Point2(dragger_pos, 0), MouseButtonMask::LEFT, Key::NONE); MessageQueue::get_singleton()->flush(); check_position(split_container, dragger_pos, separator_size.x); CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs); // Moves even when mouse is outside. dragger_pos = split_container->get_size().x - separator_size.x; SEND_GUI_MOUSE_MOTION_EVENT(mouse_offset + Point2(1000, 0), MouseButtonMask::LEFT, Key::NONE); MessageQueue::get_singleton()->flush(); check_position(split_container, dragger_pos, separator_size.x); CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs); // Move back in. dragger_pos = 100; SEND_GUI_MOUSE_MOTION_EVENT(mouse_offset + Point2(dragger_pos, 0), MouseButtonMask::LEFT, Key::NONE); MessageQueue::get_singleton()->flush(); check_position(split_container, dragger_pos, separator_size.x); CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs); // Release. SEND_GUI_MOUSE_BUTTON_RELEASED_EVENT(mouse_offset + Point2(dragger_pos, 0), MouseButton::LEFT, MouseButtonMask::NONE, Key::NONE); MessageQueue::get_singleton()->flush(); check_position(split_container, dragger_pos, separator_size.x); CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs); // No longer moves with the mouse. SEND_GUI_MOUSE_MOTION_EVENT(mouse_offset + Point2(200, 0), MouseButtonMask::NONE, Key::NONE); MessageQueue::get_singleton()->flush(); check_position(split_container, dragger_pos, separator_size.x); CHECK(split_container->get_split_offset() == dragger_pos + split_dragger_ofs); } } memdelete(child_b); memdelete(child_a); memdelete(split_container); } } // namespace TestSplitContainer #endif // TEST_SPLIT_CONTAINER_H