From 315e42b126b08848537d66234f6d3bf15c280900 Mon Sep 17 00:00:00 2001 From: halx99 Date: Thu, 26 Nov 2020 23:43:25 -0800 Subject: [PATCH] Merge: 4c1ff6bd01 369bef3614 Merge pull request #286 from rh101/add-center-vertical-layout-support Add support for center vertical layout --- cocos/ui/UILayout.cpp | 17 +++++--- cocos/ui/UILayout.h | 1 + cocos/ui/UILayoutManager.cpp | 79 +++++++++++++++++++++++++++++++++++- cocos/ui/UILayoutManager.h | 17 ++++++++ 4 files changed, 106 insertions(+), 8 deletions(-) diff --git a/cocos/ui/UILayout.cpp b/cocos/ui/UILayout.cpp index ac636a925a..72357c2180 100644 --- a/cocos/ui/UILayout.cpp +++ b/cocos/ui/UILayout.cpp @@ -632,6 +632,7 @@ void Layout::supplyTheLayoutParameterLackToChild(Widget *child) break; case Type::HORIZONTAL: case Type::VERTICAL: + case Type::CENTER_VERTICAL: { LinearLayoutParameter* layoutParameter = dynamic_cast(child->getLayoutParameter()); if (!layoutParameter) @@ -922,6 +923,9 @@ LayoutManager* Layout::createLayoutManager() case Type::VERTICAL: exe = LinearVerticalLayoutManager::create(); break; + case Type::CENTER_VERTICAL: + exe = LinearCenterVerticalLayoutManager::create(); + break; case Type::HORIZONTAL: exe = LinearHorizontalLayoutManager::create(); break; @@ -1043,7 +1047,7 @@ Size Layout::getLayoutAccumulatedSize()const { layoutSize = layoutSize - Size(0, layoutSize.height/widgetCount * (widgetCount-1)); } - if (type == Type::VERTICAL) + if (type == Type::VERTICAL || type == Type::CENTER_VERTICAL) { layoutSize = layoutSize - Size(layoutSize.width/widgetCount * (widgetCount-1), 0); } @@ -1634,7 +1638,8 @@ bool Layout::isLastWidgetInContainer(Widget* widget, FocusDirection direction)c auto& container = parent->getChildren(); ssize_t index = container.getIndex(widget); - if (parent->getLayoutType() == Type::HORIZONTAL) + const auto parentLayoutType = parent->getLayoutType(); + if (parentLayoutType == Type::HORIZONTAL) { if (direction == FocusDirection::LEFT) { @@ -1668,7 +1673,7 @@ bool Layout::isLastWidgetInContainer(Widget* widget, FocusDirection direction)c return isLastWidgetInContainer(parent, direction); } } - else if(parent->getLayoutType() == Type::VERTICAL) + else if (parentLayoutType == Type::VERTICAL || parentLayoutType == Type::CENTER_VERTICAL) { if (direction == FocusDirection::UP) { @@ -1721,7 +1726,7 @@ bool Layout::isWidgetAncestorSupportLoopFocus(Widget* widget, FocusDirection di } if (parent->isLoopFocus()) { - auto layoutType = parent->getLayoutType(); + const auto layoutType = parent->getLayoutType(); if (layoutType == Type::HORIZONTAL) { if (direction == FocusDirection::LEFT || direction == FocusDirection::RIGHT) @@ -1733,7 +1738,7 @@ bool Layout::isWidgetAncestorSupportLoopFocus(Widget* widget, FocusDirection di return isWidgetAncestorSupportLoopFocus(parent, direction); } } - if (layoutType == Type::VERTICAL) + if (layoutType == Type::VERTICAL || layoutType == Type::CENTER_VERTICAL) { if (direction == FocusDirection::DOWN || direction == FocusDirection::UP) { @@ -1823,7 +1828,7 @@ Widget* Layout::findNextFocusedWidget(FocusDirection direction, Widget* current) break; } } - else if (_layoutType == Type::VERTICAL) + else if (_layoutType == Type::VERTICAL || _layoutType == Type::CENTER_VERTICAL) { switch (direction) { diff --git a/cocos/ui/UILayout.h b/cocos/ui/UILayout.h index be5de306eb..52861c9e2d 100644 --- a/cocos/ui/UILayout.h +++ b/cocos/ui/UILayout.h @@ -120,6 +120,7 @@ public: { ABSOLUTE, VERTICAL, + CENTER_VERTICAL, HORIZONTAL, RELATIVE }; diff --git a/cocos/ui/UILayoutManager.cpp b/cocos/ui/UILayoutManager.cpp index 5529cb960c..e996787d6e 100644 --- a/cocos/ui/UILayoutManager.cpp +++ b/cocos/ui/UILayoutManager.cpp @@ -85,7 +85,6 @@ void LinearHorizontalLayoutManager::doLayout(LayoutProtocol* layout) } } - //LinearVerticalLayoutManager LinearVerticalLayoutManager* LinearVerticalLayoutManager::create() { @@ -142,7 +141,83 @@ void LinearVerticalLayoutManager::doLayout(LayoutProtocol* layout) } } } - + + +//LinearCenterVerticalLayoutManager +LinearCenterVerticalLayoutManager* LinearCenterVerticalLayoutManager::create() +{ + auto* exe = new (std::nothrow) LinearCenterVerticalLayoutManager(); + if (exe) + { + exe->autorelease(); + return exe; + } + CC_SAFE_DELETE(exe); + return nullptr; +} + +void LinearCenterVerticalLayoutManager::doLayout(LayoutProtocol* layout) +{ + const auto layoutSize = layout->getLayoutContentSize(); + auto&& container = layout->getLayoutElements(); + auto topBoundary = layoutSize.height; + + auto totalHeight = 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(); + totalHeight += subWidget->getBoundingBox().size.height + mg.top + mg.bottom; + } + } + } + + topBoundary = topBoundary - (topBoundary - totalHeight) / 2.f; + + for (auto&& subWidget : container) + { + auto* child = dynamic_cast(subWidget); + if (child) + { + auto* layoutParameter = dynamic_cast(child->getLayoutParameter()); + + if (layoutParameter) + { + const auto childGravity = layoutParameter->getGravity(); + const auto ap = subWidget->getAnchorPoint(); + const auto cs = subWidget->getBoundingBox().size; + auto finalPosX = ap.x * cs.width; + auto finalPosY = topBoundary - ((1.0f - ap.y) * cs.height); + switch (childGravity) + { + case LinearLayoutParameter::LinearGravity::NONE: + case LinearLayoutParameter::LinearGravity::LEFT: + break; + case LinearLayoutParameter::LinearGravity::RIGHT: + finalPosX = layoutSize.width - ((1.0f - ap.x) * cs.width); + break; + case LinearLayoutParameter::LinearGravity::CENTER_HORIZONTAL: + finalPosX = layoutSize.width / 2.0f - cs.width * (0.5f - ap.x); + break; + default: + break; + } + auto&& mg = layoutParameter->getMargin(); + finalPosX += mg.left; + finalPosY -= mg.top; + subWidget->setPosition(finalPosX, finalPosY); + topBoundary = subWidget->getPosition().y - subWidget->getAnchorPoint().y * subWidget->getBoundingBox().size.height - mg.bottom; + } + } + } +} + //RelativeLayoutManager RelativeLayoutManager* RelativeLayoutManager::create() diff --git a/cocos/ui/UILayoutManager.h b/cocos/ui/UILayoutManager.h index 08608f04fc..8f25670788 100644 --- a/cocos/ui/UILayoutManager.h +++ b/cocos/ui/UILayoutManager.h @@ -94,6 +94,23 @@ private: friend class Layout; }; +/** + *@brief Linear vertical layouting class. + * Note: This class is used only by @see `Layout` class. + * @lua NA + * @js NA + */ +class CC_GUI_DLL LinearCenterVerticalLayoutManager : public LayoutManager +{ +private: + LinearCenterVerticalLayoutManager() {}; + virtual ~LinearCenterVerticalLayoutManager() {}; + static LinearCenterVerticalLayoutManager* create(); + virtual void doLayout(LayoutProtocol* layout) override; + + friend class Layout; +}; + /** *@brief Relative layouting class. *Note: This class is used only by `Layout` class.