diff --git a/core/ui/UILayout.cpp b/core/ui/UILayout.cpp index 23be4e67e7..a2a188604c 100644 --- a/core/ui/UILayout.cpp +++ b/core/ui/UILayout.cpp @@ -643,6 +643,7 @@ void Layout::supplyTheLayoutParameterLackToChild(Widget* child) case Type::HORIZONTAL: case Type::VERTICAL: case Type::CENTER_VERTICAL: + case Type::CENTER_HORIZONTAL: { LinearLayoutParameter* layoutParameter = dynamic_cast(child->getLayoutParameter()); if (!layoutParameter) @@ -934,6 +935,9 @@ LayoutManager* Layout::createLayoutManager() case Type::CENTER_VERTICAL: exe = LinearCenterVerticalLayoutManager::create(); break; + case Type::CENTER_HORIZONTAL: + exe = LinearCenterHorizontalLayoutManager::create(); + break; case Type::HORIZONTAL: exe = LinearHorizontalLayoutManager::create(); break; @@ -1049,7 +1053,7 @@ Vec2 Layout::getLayoutAccumulatedSize() const // subtract extra size Type type = this->getLayoutType(); - if (type == Type::HORIZONTAL) + if (type == Type::HORIZONTAL || type == Type::CENTER_HORIZONTAL) { layoutSize = layoutSize - Vec2(0, layoutSize.height / widgetCount * (widgetCount - 1)); } @@ -1725,7 +1729,7 @@ bool Layout::isWidgetAncestorSupportLoopFocus(Widget* widget, FocusDirection dir if (parent->isLoopFocus()) { const auto layoutType = parent->getLayoutType(); - if (layoutType == Type::HORIZONTAL) + if (layoutType == Type::HORIZONTAL || _layoutType == Type::CENTER_HORIZONTAL) { if (direction == FocusDirection::LEFT || direction == FocusDirection::RIGHT) { @@ -1789,7 +1793,7 @@ Widget* Layout::findNextFocusedWidget(FocusDirection direction, Widget* current) } else if (current->isFocused() || dynamic_cast(current)) { - if (_layoutType == Type::HORIZONTAL) + if (_layoutType == Type::HORIZONTAL || _layoutType == Type::CENTER_HORIZONTAL) { switch (direction) { diff --git a/core/ui/UILayout.h b/core/ui/UILayout.h index 308ac95b26..3e234d3224 100644 --- a/core/ui/UILayout.h +++ b/core/ui/UILayout.h @@ -125,6 +125,7 @@ public: HORIZONTAL, RELATIVE, CENTER_VERTICAL, + CENTER_HORIZONTAL, }; /** diff --git a/core/ui/UILayoutManager.cpp b/core/ui/UILayoutManager.cpp index 16734af02b..8a037e3539 100644 --- a/core/ui/UILayoutManager.cpp +++ b/core/ui/UILayoutManager.cpp @@ -204,6 +204,74 @@ void LinearCenterVerticalLayoutManager::doLayout(LayoutProtocol* layout) } } +// LinearCenterHorizontalLayoutManager +LinearCenterHorizontalLayoutManager* LinearCenterHorizontalLayoutManager::create() +{ + auto* ret = new LinearCenterHorizontalLayoutManager(); + ret->autorelease(); + return ret; +} + +void LinearCenterHorizontalLayoutManager::doLayout(LayoutProtocol* layout) +{ + const auto layoutSize = layout->getLayoutContentSize(); + auto&& container = layout->getLayoutElements(); + + auto totalWidth = 0.f; + // need to get total sub-widget height + for (auto&& subWidget : container) + { + auto* child = dynamic_cast(subWidget); + if (child) + { + auto* layoutParameter = dynamic_cast(child->getLayoutParameter()); + if (layoutParameter) + { + auto&& mg = layoutParameter->getMargin(); + totalWidth += subWidget->getBoundingBox().size.width + mg.left + mg.right; + } + } + } + + auto leftBoundary = (layoutSize.width - totalWidth) / 2.f; + + for (auto&& subWidget : container) + { + Widget* child = dynamic_cast(subWidget); + if (child) + { + LinearLayoutParameter* layoutParameter = dynamic_cast(child->getLayoutParameter()); + if (layoutParameter) + { + LinearLayoutParameter::LinearGravity childGravity = layoutParameter->getGravity(); + Vec2 ap = child->getAnchorPoint(); + Vec2 cs = child->getBoundingBox().size; + float finalPosX = leftBoundary + (ap.x * cs.width); + float finalPosY = layoutSize.height - (1.0f - ap.y) * cs.height; + switch (childGravity) + { + case LinearLayoutParameter::LinearGravity::NONE: + case LinearLayoutParameter::LinearGravity::TOP: + break; + case LinearLayoutParameter::LinearGravity::BOTTOM: + finalPosY = ap.y * cs.height; + break; + case LinearLayoutParameter::LinearGravity::CENTER_VERTICAL: + finalPosY = layoutSize.height / 2.0f - cs.height * (0.5f - ap.y); + break; + default: + break; + } + Margin mg = layoutParameter->getMargin(); + finalPosX += mg.left; + finalPosY -= mg.top; + child->setPosition(Vec2(finalPosX, finalPosY)); + leftBoundary = child->getRightBoundary() + mg.right; + } + } + } +} + // RelativeLayoutManager RelativeLayoutManager* RelativeLayoutManager::create() diff --git a/core/ui/UILayoutManager.h b/core/ui/UILayoutManager.h index f83c6986ac..a39c3d3c44 100644 --- a/core/ui/UILayoutManager.h +++ b/core/ui/UILayoutManager.h @@ -50,11 +50,11 @@ class RelativeLayoutParameter; class AX_GUI_DLL LayoutManager : public Ref { public: - virtual ~LayoutManager(){}; - LayoutManager(){}; + virtual ~LayoutManager(){} + LayoutManager(){} /** - * The interface does the actual layouting work. + * The interface does the actual layout work. */ virtual void doLayout(LayoutProtocol* layout) = 0; @@ -62,7 +62,7 @@ public: }; /** - *@brief Linear vertical layouting class. + *@brief Linear vertical layout class. * Note: This class is used only by @see `Layout` class. * @lua NA * @js NA @@ -70,8 +70,8 @@ public: class AX_GUI_DLL LinearVerticalLayoutManager : public LayoutManager { private: - LinearVerticalLayoutManager(){}; - virtual ~LinearVerticalLayoutManager(){}; + LinearVerticalLayoutManager(){} + virtual ~LinearVerticalLayoutManager(){} static LinearVerticalLayoutManager* create(); virtual void doLayout(LayoutProtocol* layout) override; @@ -79,7 +79,7 @@ private: }; /** - *@brief Linear horizontal layouting class. + *@brief Linear horizontal layout class. *Note: This class is used only by @see `Layout` class. * @lua NA * @js NA @@ -87,8 +87,8 @@ private: class AX_GUI_DLL LinearHorizontalLayoutManager : public LayoutManager { private: - LinearHorizontalLayoutManager(){}; - virtual ~LinearHorizontalLayoutManager(){}; + LinearHorizontalLayoutManager(){} + virtual ~LinearHorizontalLayoutManager(){} static LinearHorizontalLayoutManager* create(); virtual void doLayout(LayoutProtocol* layout) override; @@ -96,7 +96,7 @@ private: }; /** - *@brief Linear vertical layouting class. + *@brief Linear vertical layout class. * Note: This class is used only by @see `Layout` class. * @lua NA * @js NA @@ -104,8 +104,8 @@ private: class AX_GUI_DLL LinearCenterVerticalLayoutManager : public LayoutManager { private: - LinearCenterVerticalLayoutManager(){}; - virtual ~LinearCenterVerticalLayoutManager(){}; + LinearCenterVerticalLayoutManager(){} + virtual ~LinearCenterVerticalLayoutManager(){} static LinearCenterVerticalLayoutManager* create(); virtual void doLayout(LayoutProtocol* layout) override; @@ -113,7 +113,25 @@ private: }; /** - *@brief Relative layouting class. + *@brief Linear horizontal layout class. + * Note: This class is used only by @see `Layout` class. + * @lua NA + * @js NA + */ +class AX_GUI_DLL LinearCenterHorizontalLayoutManager : public LayoutManager +{ +private: + LinearCenterHorizontalLayoutManager(){} + virtual ~LinearCenterHorizontalLayoutManager(){} + static LinearCenterHorizontalLayoutManager* create(); + virtual void doLayout(LayoutProtocol* layout) override; + + friend class Layout; +}; + + +/** + *@brief Relative layout class. *Note: This class is used only by `Layout` class. * @lua NA * @js NA @@ -128,7 +146,7 @@ private: , _finalPositionY(0.0f) , _relativeWidgetLP(nullptr) {} - virtual ~RelativeLayoutManager(){}; + virtual ~RelativeLayoutManager(){} static RelativeLayoutManager* create(); virtual void doLayout(LayoutProtocol* layout) override; diff --git a/tests/cpp-tests/Classes/UITest/CocoStudioGUITest/UILayoutTest/UILayoutTest.cpp b/tests/cpp-tests/Classes/UITest/CocoStudioGUITest/UILayoutTest/UILayoutTest.cpp index 8670c8a96e..e8dd4da9d7 100644 --- a/tests/cpp-tests/Classes/UITest/CocoStudioGUITest/UILayoutTest/UILayoutTest.cpp +++ b/tests/cpp-tests/Classes/UITest/CocoStudioGUITest/UILayoutTest/UILayoutTest.cpp @@ -36,6 +36,8 @@ UILayoutTests::UILayoutTests() ADD_TEST_CASE(UILayoutTest_BackGroundImage_Scale9); ADD_TEST_CASE(UILayoutTest_Layout_Linear_Vertical); ADD_TEST_CASE(UILayoutTest_Layout_Linear_Horizontal); + ADD_TEST_CASE(UILayoutTest_Layout_Linear_CenterVertical); + ADD_TEST_CASE(UILayoutTest_Layout_Linear_CenterHorizontal); ADD_TEST_CASE(UILayoutTest_Layout_Relative_Align_Parent); ADD_TEST_CASE(UILayoutTest_Layout_Relative_Location); ADD_TEST_CASE(UILayoutTest_Layout_Scaled_Widget); @@ -494,6 +496,122 @@ bool UILayoutTest_Layout_Linear_Horizontal::init() return false; } +// UILayoutTest_Layout_Linear_CenterVertical + +UILayoutTest_Layout_Linear_CenterVertical::UILayoutTest_Layout_Linear_CenterVertical() {} + +UILayoutTest_Layout_Linear_CenterVertical::~UILayoutTest_Layout_Linear_CenterVertical() {} + +bool UILayoutTest_Layout_Linear_CenterVertical::init() +{ + if (UIScene::init()) + { + Size widgetSize = _widget->getContentSize(); + + // Add the alert + Text* alert = Text::create("Layout Linear Center Vertical", "fonts/Marker Felt.ttf", 20); + alert->setColor(Color3B(159, 168, 176)); + alert->setPosition( + Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 4.5f)); + + _uiLayer->addChild(alert); + + Layout* root = static_cast(_uiLayer->getChildByTag(81)); + + Layout* background = static_cast(root->getChildByName("background_Panel")); + + // Create the layout + Layout* layout = Layout::create(); + layout->setLayoutType(Layout::Type::CENTER_VERTICAL); + layout->setContentSize(Size(280, 150)); + Size backgroundSize = background->getContentSize(); + layout->setPosition(Vec2((widgetSize.width - backgroundSize.width) / 2.0f + + (backgroundSize.width - layout->getContentSize().width) / 2.0f, + (widgetSize.height - backgroundSize.height) / 2.0f + + (backgroundSize.height - layout->getContentSize().height) / 2.0f)); + _uiLayer->addChild(layout); + + Button* button = Button::create("cocosui/animationbuttonnormal.png", "cocosui/animationbuttonpressed.png"); + layout->addChild(button); + + LinearLayoutParameter* lp1 = LinearLayoutParameter::create(); + button->setLayoutParameter(lp1); + lp1->setGravity(LinearLayoutParameter::LinearGravity::CENTER_HORIZONTAL); + lp1->setMargin(Margin(0.0f, 5.0f, 0.0f, 10.0f)); + + Button* titleButton = Button::create("cocosui/backtotopnormal.png", "cocosui/backtotoppressed.png"); + titleButton->setTitleText("Title Button"); + layout->addChild(titleButton); + + LinearLayoutParameter* lp2 = LinearLayoutParameter::create(); + titleButton->setLayoutParameter(lp2); + lp2->setGravity(LinearLayoutParameter::LinearGravity::CENTER_HORIZONTAL); + lp2->setMargin(Margin(0.0f, 10.0f, 0.0f, 10.0f)); + + return true; + } + + return false; +} + +// UILayoutTest_Layout_Linear_CenterHorizontal + +UILayoutTest_Layout_Linear_CenterHorizontal::UILayoutTest_Layout_Linear_CenterHorizontal() {} + +UILayoutTest_Layout_Linear_CenterHorizontal::~UILayoutTest_Layout_Linear_CenterHorizontal() {} + +bool UILayoutTest_Layout_Linear_CenterHorizontal::init() +{ + if (UIScene::init()) + { + Size widgetSize = _widget->getContentSize(); + + // Add the alert + Text* alert = Text::create("Layout Linear Center Horizontal", "fonts/Marker Felt.ttf", 20); + alert->setColor(Color3B(159, 168, 176)); + alert->setPosition( + Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 4.5f)); + _uiLayer->addChild(alert); + + Layout* root = static_cast(_uiLayer->getChildByTag(81)); + + Layout* background = dynamic_cast(root->getChildByName("background_Panel")); + + // Create the layout + Layout* layout = Layout::create(); + layout->setLayoutType(Layout::Type::CENTER_HORIZONTAL); + layout->setClippingEnabled(true); + layout->setContentSize(Size(280, 150)); + Size backgroundSize = background->getContentSize(); + layout->setPosition(Vec2((widgetSize.width - backgroundSize.width) / 2.0f + + (backgroundSize.width - layout->getContentSize().width) / 2.0f, + (widgetSize.height - backgroundSize.height) / 2.0f + + (backgroundSize.height - layout->getContentSize().height) / 2.0f)); + _uiLayer->addChild(layout); + + Button* button = Button::create("cocosui/animationbuttonnormal.png", "cocosui/animationbuttonpressed.png"); + layout->addChild(button); + + LinearLayoutParameter* lp1 = LinearLayoutParameter::create(); + button->setLayoutParameter(lp1); + lp1->setGravity(LinearLayoutParameter::LinearGravity::CENTER_VERTICAL); + lp1->setMargin(Margin(10.0f, 10.0f, 10.0f, 10.0f)); + + Button* titleButton = Button::create("cocosui/backtotopnormal.png", "cocosui/backtotoppressed.png"); + titleButton->setTitleText("Title Button"); + layout->addChild(titleButton); + + LinearLayoutParameter* lp2 = LinearLayoutParameter::create(); + titleButton->setLayoutParameter(lp2); + lp2->setGravity(LinearLayoutParameter::LinearGravity::CENTER_VERTICAL); + lp2->setMargin(Margin(10.0f, 10.0f, 10.0f, 10.0f)); + + return true; + } + + return false; +} + // UILayoutTest_Layout_Relative_Align_Parent UILayoutTest_Layout_Relative_Align_Parent::UILayoutTest_Layout_Relative_Align_Parent() {} diff --git a/tests/cpp-tests/Classes/UITest/CocoStudioGUITest/UILayoutTest/UILayoutTest.h b/tests/cpp-tests/Classes/UITest/CocoStudioGUITest/UILayoutTest/UILayoutTest.h index 899ddb0b90..398e292f7b 100644 --- a/tests/cpp-tests/Classes/UITest/CocoStudioGUITest/UILayoutTest/UILayoutTest.h +++ b/tests/cpp-tests/Classes/UITest/CocoStudioGUITest/UILayoutTest/UILayoutTest.h @@ -105,6 +105,27 @@ public: CREATE_FUNC(UILayoutTest_Layout_Linear_Horizontal); }; +class UILayoutTest_Layout_Linear_CenterVertical : public UIScene +{ +public: + UILayoutTest_Layout_Linear_CenterVertical(); + ~UILayoutTest_Layout_Linear_CenterVertical(); + virtual bool init() override; + + CREATE_FUNC(UILayoutTest_Layout_Linear_CenterVertical); +}; + +class UILayoutTest_Layout_Linear_CenterHorizontal : public UIScene +{ +public: + UILayoutTest_Layout_Linear_CenterHorizontal(); + ~UILayoutTest_Layout_Linear_CenterHorizontal(); + virtual bool init() override; + + CREATE_FUNC(UILayoutTest_Layout_Linear_CenterHorizontal); +}; + + class UILayoutTest_Layout_Relative_Align_Parent : public UIScene { public: