123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920 |
- /****************************************************************************
- Copyright (c) 2013-2016 Chukong Technologies Inc.
- Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
- http://www.cocos2d-x.org
- 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.
- ****************************************************************************/
- #include "ui/UILayout.h"
- #include "ui/UIHelper.h"
- #include "ui/UIScale9Sprite.h"
- #include "renderer/CCGLProgram.h"
- #include "renderer/CCGLProgramCache.h"
- #include "renderer/ccGLStateCache.h"
- #include "renderer/CCRenderState.h"
- #include "base/CCDirector.h"
- #include "2d/CCDrawingPrimitives.h"
- #include "renderer/CCRenderer.h"
- #include "ui/UILayoutManager.h"
- #include "2d/CCDrawNode.h"
- #include "2d/CCLayer.h"
- #include "2d/CCSprite.h"
- #include "base/CCEventFocus.h"
- #include "base/CCStencilStateManager.h"
- #include "editor-support/cocostudio/CocosStudioExtension.h"
- NS_CC_BEGIN
- namespace ui {
-
- static const int BACKGROUNDIMAGE_Z = (-1);
- static const int BCAKGROUNDCOLORRENDERER_Z = (-2);
-
- IMPLEMENT_CLASS_GUI_INFO(Layout)
- Layout::Layout():
- _backGroundScale9Enabled(false),
- _backGroundImage(nullptr),
- _backGroundImageFileName(""),
- _backGroundImageCapInsets(Rect::ZERO),
- _colorType(BackGroundColorType::NONE),
- _bgImageTexType(TextureResType::LOCAL),
- _backGroundImageTextureSize(Size::ZERO),
- _backGroundImageColor(Color3B::WHITE),
- _backGroundImageOpacity(255),
- _colorRender(nullptr),
- _gradientRender(nullptr),
- _cColor(Color3B::WHITE),
- _gStartColor(Color3B::WHITE),
- _gEndColor(Color3B::WHITE),
- _alongVector(Vec2(0.0f, -1.0f)),
- _cOpacity(255),
- _clippingEnabled(false),
- _layoutType(Type::ABSOLUTE),
- _clippingType(ClippingType::STENCIL),
- _clippingStencil(nullptr),
- _clippingRect(Rect::ZERO),
- _clippingParent(nullptr),
- _clippingRectDirty(true),
- _stencilStateManager(new StencilStateManager()),
- _doLayoutDirty(true),
- _isInterceptTouch(false),
- _loopFocus(false),
- _passFocusToChild(true),
- _isFocusPassing(false)
- {
- //no-op
- }
- Layout::~Layout()
- {
- CC_SAFE_RELEASE(_clippingStencil);
- CC_SAFE_DELETE(_stencilStateManager);
- }
-
- void Layout::onEnter()
- {
- #if CC_ENABLE_SCRIPT_BINDING
- if (_scriptType == kScriptTypeJavascript)
- {
- if (ScriptEngineManager::sendNodeEventToJSExtended(this, kNodeOnEnter))
- return;
- }
- #endif
-
- Widget::onEnter();
- if (_clippingStencil)
- {
- _clippingStencil->onEnter();
- }
- _doLayoutDirty = true;
- _clippingRectDirty = true;
- }
-
- void Layout::onExit()
- {
- #if CC_ENABLE_SCRIPT_BINDING
- if (_scriptType == kScriptTypeJavascript)
- {
- if (ScriptEngineManager::sendNodeEventToJSExtended(this, kNodeOnExit))
- return;
- }
- #endif
-
- Widget::onExit();
- if (_clippingStencil)
- {
- _clippingStencil->onExit();
- }
- }
-
- void Layout::setGlobalZOrder(float globalZOrder)
- {
- // _protectedChildren's global z order is set in ProtectedNode::setGlobalZOrder()
- Widget::setGlobalZOrder(globalZOrder);
- if (_clippingStencil)
- _clippingStencil->setGlobalZOrder(globalZOrder);
-
- for (auto &child : _children)
- child->setGlobalZOrder(globalZOrder);
- }
- Layout* Layout::create()
- {
- Layout* layout = new (std::nothrow) Layout();
- if (layout && layout->init())
- {
- layout->autorelease();
- return layout;
- }
- CC_SAFE_DELETE(layout);
- return nullptr;
- }
- bool Layout::init()
- {
- if (Widget::init())
- {
- ignoreContentAdaptWithSize(false);
- setContentSize(Size::ZERO);
- setAnchorPoint(Vec2::ZERO);
- onPassFocusToChild = CC_CALLBACK_2(Layout::findNearestChildWidgetIndex, this);
- return true;
- }
- return false;
- }
-
- void Layout::addChild(Node* child)
- {
- Layout::addChild(child, child->getLocalZOrder(), child->getTag());
- }
-
- void Layout::addChild(Node * child, int localZOrder)
- {
- Layout::addChild(child, localZOrder, child->getTag());
- }
- void Layout::addChild(Node *child, int zOrder, int tag)
- {
- if (dynamic_cast<Widget*>(child)) {
- supplyTheLayoutParameterLackToChild(static_cast<Widget*>(child));
- }
- child->setGlobalZOrder(_globalZOrder);
- Widget::addChild(child, zOrder, tag);
- _doLayoutDirty = true;
- }
-
- void Layout::addChild(Node* child, int zOrder, const std::string &name)
- {
- if (dynamic_cast<Widget*>(child)) {
- supplyTheLayoutParameterLackToChild(static_cast<Widget*>(child));
- }
- child->setGlobalZOrder(_globalZOrder);
- Widget::addChild(child, zOrder, name);
- _doLayoutDirty = true;
- }
-
- void Layout::removeChild(Node *child, bool cleanup)
- {
- Widget::removeChild(child, cleanup);
- _doLayoutDirty = true;
- }
-
- void Layout::removeAllChildren()
- {
- Widget::removeAllChildren();
- _doLayoutDirty = true;
- }
-
- void Layout::removeAllChildrenWithCleanup(bool cleanup)
- {
- Widget::removeAllChildrenWithCleanup(cleanup);
- _doLayoutDirty = true;
- }
- bool Layout::isClippingEnabled()const
- {
- return _clippingEnabled;
- }
- void Layout::visit(Renderer *renderer, const Mat4 &parentTransform, uint32_t parentFlags)
- {
- if (!_visible)
- {
- return;
- }
-
- adaptRenderers();
- doLayout();
-
- if (_clippingEnabled)
- {
- switch (_clippingType)
- {
- case ClippingType::STENCIL:
- stencilClippingVisit(renderer, parentTransform, parentFlags);
- break;
- case ClippingType::SCISSOR:
- scissorClippingVisit(renderer, parentTransform, parentFlags);
- break;
- default:
- break;
- }
- }
- else
- {
- Widget::visit(renderer, parentTransform, parentFlags);
- }
- }
-
- void Layout::stencilClippingVisit(Renderer *renderer, const Mat4& parentTransform, uint32_t parentFlags)
- {
- if(!_visible)
- return;
-
- uint32_t flags = processParentFlags(parentTransform, parentFlags);
- // IMPORTANT:
- // To ease the migration to v3.0, we still support the Mat4 stack,
- // but it is deprecated and your code should not rely on it
- Director* director = Director::getInstance();
- CCASSERT(nullptr != director, "Director is null when setting matrix stack");
- director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
- director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, _modelViewTransform);
- //Add group command
- _groupCommand.init(_globalZOrder);
- renderer->addCommand(&_groupCommand);
-
- renderer->pushGroup(_groupCommand.getRenderQueueID());
-
- _beforeVisitCmdStencil.init(_globalZOrder);
- _beforeVisitCmdStencil.func = CC_CALLBACK_0(StencilStateManager::onBeforeVisit, _stencilStateManager);
- renderer->addCommand(&_beforeVisitCmdStencil);
-
- _clippingStencil->visit(renderer, _modelViewTransform, flags);
-
- _afterDrawStencilCmd.init(_globalZOrder);
- _afterDrawStencilCmd.func = CC_CALLBACK_0(StencilStateManager::onAfterDrawStencil, _stencilStateManager);
- renderer->addCommand(&_afterDrawStencilCmd);
-
- int i = 0; // used by _children
- int j = 0; // used by _protectedChildren
-
- sortAllChildren();
- sortAllProtectedChildren();
-
- //
- // draw children and protectedChildren zOrder < 0
- //
- for(auto size = _children.size(); i < size; i++)
- {
- auto node = _children.at(i);
-
- if (node && node->getLocalZOrder() < 0)
- node->visit(renderer, _modelViewTransform, flags);
- else
- break;
- }
-
- for(auto size = _protectedChildren.size(); j < size; j++)
- {
- auto node = _protectedChildren.at(j);
-
- if (node && node->getLocalZOrder() < 0)
- node->visit(renderer, _modelViewTransform, flags);
- else
- break;
- }
-
- //
- // draw self
- //
- this->draw(renderer, _modelViewTransform, flags);
-
- //
- // draw children and protectedChildren zOrder >= 0
- //
- for(auto it=_protectedChildren.cbegin()+j, itCend = _protectedChildren.cend(); it != itCend; ++it)
- (*it)->visit(renderer, _modelViewTransform, flags);
-
- for(auto it=_children.cbegin()+i, itCend = _children.cend(); it != itCend; ++it)
- (*it)->visit(renderer, _modelViewTransform, flags);
-
- _afterVisitCmdStencil.init(_globalZOrder);
- _afterVisitCmdStencil.func = CC_CALLBACK_0(StencilStateManager::onAfterVisit, _stencilStateManager);
- renderer->addCommand(&_afterVisitCmdStencil);
-
- renderer->popGroup();
-
- director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
- }
-
- void Layout::onBeforeVisitScissor()
- {
- auto glview = Director::getInstance()->getOpenGLView();
- // apply scissor test
- _scissorOldState = glview->isScissorEnabled();
- if (false == _scissorOldState)
- {
- glEnable(GL_SCISSOR_TEST);
- }
- // apply scissor box
- Rect clippingRect = getClippingRect();
- _clippingOldRect = glview->getScissorRect();
- if (false == _clippingOldRect.equals(clippingRect))
- {
- glview->setScissorInPoints(clippingRect.origin.x,
- clippingRect.origin.y,
- clippingRect.size.width,
- clippingRect.size.height);
- }
- }
- void Layout::onAfterVisitScissor()
- {
- if (_scissorOldState)
- {
- // revert scissor box
- if (false == _clippingOldRect.equals(_clippingRect))
- {
- auto glview = Director::getInstance()->getOpenGLView();
- glview->setScissorInPoints(_clippingOldRect.origin.x,
- _clippingOldRect.origin.y,
- _clippingOldRect.size.width,
- _clippingOldRect.size.height);
- }
- }
- else
- {
- // revert scissor test
- glDisable(GL_SCISSOR_TEST);
- }
- }
-
- void Layout::scissorClippingVisit(Renderer *renderer, const Mat4& parentTransform, uint32_t parentFlags)
- {
- if (parentFlags & FLAGS_DIRTY_MASK)
- {
- _clippingRectDirty = true;
- }
- _beforeVisitCmdScissor.init(_globalZOrder);
- _beforeVisitCmdScissor.func = CC_CALLBACK_0(Layout::onBeforeVisitScissor, this);
- renderer->addCommand(&_beforeVisitCmdScissor);
- ProtectedNode::visit(renderer, parentTransform, parentFlags);
-
- _afterVisitCmdScissor.init(_globalZOrder);
- _afterVisitCmdScissor.func = CC_CALLBACK_0(Layout::onAfterVisitScissor, this);
- renderer->addCommand(&_afterVisitCmdScissor);
- }
- void Layout::setClippingEnabled(bool able)
- {
- if (able == _clippingEnabled)
- {
- return;
- }
- _clippingEnabled = able;
- switch (_clippingType)
- {
- case ClippingType::STENCIL:
- if (able)
- {
- _clippingStencil = DrawNode::create();
- _clippingStencil->setGlobalZOrder(_globalZOrder);
- if (_running)
- {
- _clippingStencil->onEnter();
- }
- _clippingStencil->retain();
- setStencilClippingSize(_contentSize);
- }
- else
- {
- if (_running)
- {
- _clippingStencil->onExit();
- }
- _clippingStencil->release();
- _clippingStencil = nullptr;
- }
- break;
- default:
- break;
- }
- }
-
- void Layout::setClippingType(ClippingType type)
- {
- if (type == _clippingType)
- {
- return;
- }
- bool clippingEnabled = isClippingEnabled();
- setClippingEnabled(false);
- _clippingType = type;
- setClippingEnabled(clippingEnabled);
- }
-
- Layout::ClippingType Layout::getClippingType()const
- {
- return _clippingType;
- }
-
- void Layout::setStencilClippingSize(const Size& /*size*/)
- {
- if (_clippingEnabled && _clippingType == ClippingType::STENCIL)
- {
- Vec2 rect[4];
- // rect[0].setZero(); Zero default
- rect[1].set(_contentSize.width, 0.0f);
- rect[2].set(_contentSize.width, _contentSize.height);
- rect[3].set(0.0f, _contentSize.height);
- Color4F green(0.0f, 1.0f, 0.0f, 1.0f);
- _clippingStencil->clear();
- _clippingStencil->drawPolygon(rect, 4, green, 0, green);
- }
- }
-
- const Rect& Layout::getClippingRect()
- {
- if (_clippingRectDirty)
- {
- Vec2 worldPos = convertToWorldSpace(Vec2::ZERO);
- AffineTransform t = getNodeToWorldAffineTransform();
- float scissorWidth = _contentSize.width*t.a;
- float scissorHeight = _contentSize.height*t.d;
- Rect parentClippingRect;
- Layout* parent = this;
- while (parent)
- {
- parent = dynamic_cast<Layout*>(parent->getParent());
- if(parent)
- {
- if (parent->isClippingEnabled())
- {
- _clippingParent = parent;
- break;
- }
- }
- }
-
- if (_clippingParent)
- {
- parentClippingRect = _clippingParent->getClippingRect();
- float finalX = worldPos.x - (scissorWidth * _anchorPoint.x);
- float finalY = worldPos.y - (scissorHeight * _anchorPoint.y);
- float finalWidth = scissorWidth;
- float finalHeight = scissorHeight;
-
- float leftOffset = worldPos.x - parentClippingRect.origin.x;
- if (leftOffset < 0.0f)
- {
- finalX = parentClippingRect.origin.x;
- finalWidth += leftOffset;
- }
- float rightOffset = (worldPos.x + scissorWidth) - (parentClippingRect.origin.x + parentClippingRect.size.width);
- if (rightOffset > 0.0f)
- {
- finalWidth -= rightOffset;
- }
- float topOffset = (worldPos.y + scissorHeight) - (parentClippingRect.origin.y + parentClippingRect.size.height);
- if (topOffset > 0.0f)
- {
- finalHeight -= topOffset;
- }
- float bottomOffset = worldPos.y - parentClippingRect.origin.y;
- if (bottomOffset < 0.0f)
- {
- finalY = parentClippingRect.origin.y;
- finalHeight += bottomOffset;
- }
- if (finalWidth < 0.0f)
- {
- finalWidth = 0.0f;
- }
- if (finalHeight < 0.0f)
- {
- finalHeight = 0.0f;
- }
- _clippingRect.origin.x = finalX;
- _clippingRect.origin.y = finalY;
- _clippingRect.size.width = finalWidth;
- _clippingRect.size.height = finalHeight;
- }
- else
- {
- _clippingRect.origin.x = worldPos.x - (scissorWidth * _anchorPoint.x);
- _clippingRect.origin.y = worldPos.y - (scissorHeight * _anchorPoint.y);
- _clippingRect.size.width = scissorWidth;
- _clippingRect.size.height = scissorHeight;
- }
- _clippingRectDirty = false;
- }
- return _clippingRect;
- }
- void Layout::onSizeChanged()
- {
- Widget::onSizeChanged();
- setStencilClippingSize(_contentSize);
- _doLayoutDirty = true;
- _clippingRectDirty = true;
- if (_backGroundImage)
- {
- _backGroundImage->setPosition(_contentSize.width/2.0f, _contentSize.height/2.0f);
- if (_backGroundScale9Enabled){
- _backGroundImage->setPreferredSize(_contentSize);
- }
- else{
- _backGroundImage->setPreferredSize(_backGroundImageTextureSize);
- }
- }
- if (_colorRender)
- {
- _colorRender->setContentSize(_contentSize);
- }
- if (_gradientRender)
- {
- _gradientRender->setContentSize(_contentSize);
- }
- }
- void Layout::setBackGroundImageScale9Enabled(bool able)
- {
- if (_backGroundScale9Enabled == able)
- {
- return;
- }
- _backGroundScale9Enabled = able;
- if (nullptr == _backGroundImage)
- {
- addBackGroundImage();
- setBackGroundImage(_backGroundImageFileName,_bgImageTexType);
- }
- if(_backGroundScale9Enabled){
- _backGroundImage->setRenderingType(Scale9Sprite::RenderingType::SLICE);
- _backGroundImage->setPreferredSize(_contentSize);
- }else{
- _backGroundImage->setRenderingType(Scale9Sprite::RenderingType::SIMPLE);
- _backGroundImage->setPreferredSize(_backGroundImageTextureSize);
- }
-
- setBackGroundImageCapInsets(_backGroundImageCapInsets);
- }
-
- bool Layout::isBackGroundImageScale9Enabled()const
- {
- return _backGroundScale9Enabled;
- }
- void Layout::setBackGroundImage(const std::string& fileName,TextureResType texType)
- {
- if (fileName.empty())
- {
- return;
- }
- if (_backGroundImage == nullptr)
- {
- addBackGroundImage();
- if(_backGroundScale9Enabled){
- _backGroundImage->setRenderingType(Scale9Sprite::RenderingType::SLICE);
- }else{
- _backGroundImage->setRenderingType(Scale9Sprite::RenderingType::SIMPLE);
- }
- }
- _backGroundImageFileName = fileName;
- _bgImageTexType = texType;
-
- switch (_bgImageTexType)
- {
- case TextureResType::LOCAL:
- _backGroundImage->initWithFile(fileName);
- break;
- case TextureResType::PLIST:
- _backGroundImage->initWithSpriteFrameName(fileName);
- break;
- default:
- break;
- }
-
- _backGroundImageTextureSize = _backGroundImage->getContentSize();
- _backGroundImage->setPosition(_contentSize.width/2.0f, _contentSize.height/2.0f);
- if (_backGroundScale9Enabled) {
- _backGroundImage->setPreferredSize(_contentSize);
- }
- else{
- _backGroundImage->setPreferredSize(_backGroundImageTextureSize);
- }
- updateBackGroundImageRGBA();
- }
- void Layout::setBackGroundImageCapInsets(const Rect &capInsets)
- {
- _backGroundImageCapInsets = capInsets;
- if (_backGroundScale9Enabled && _backGroundImage)
- {
- _backGroundImage->setCapInsets(capInsets);
- }
- }
-
- const Rect& Layout::getBackGroundImageCapInsets()const
- {
- return _backGroundImageCapInsets;
- }
- void Layout::supplyTheLayoutParameterLackToChild(Widget *child)
- {
- if (!child)
- {
- return;
- }
- switch (_layoutType)
- {
- case Type::ABSOLUTE:
- break;
- case Type::HORIZONTAL:
- case Type::VERTICAL:
- {
- LinearLayoutParameter* layoutParameter = dynamic_cast<LinearLayoutParameter*>(child->getLayoutParameter());
- if (!layoutParameter)
- {
- child->setLayoutParameter(LinearLayoutParameter::create());
- }
- break;
- }
- case Type::RELATIVE:
- {
- RelativeLayoutParameter* layoutParameter = dynamic_cast<RelativeLayoutParameter*>(child->getLayoutParameter());
- if (!layoutParameter)
- {
- child->setLayoutParameter(RelativeLayoutParameter::create());
- }
- break;
- }
- default:
- break;
- }
- }
- void Layout::addBackGroundImage()
- {
- _backGroundImage = Scale9Sprite::create();
- _backGroundImage->setRenderingType(Scale9Sprite::RenderingType::SIMPLE);
-
- addProtectedChild(_backGroundImage, BACKGROUNDIMAGE_Z, -1);
-
- _backGroundImage->setPosition(_contentSize.width/2.0f, _contentSize.height/2.0f);
- }
- void Layout::removeBackGroundImage()
- {
- if (!_backGroundImage)
- {
- return;
- }
- removeProtectedChild(_backGroundImage);
- _backGroundImage = nullptr;
- _backGroundImageFileName = "";
- _backGroundImageTextureSize = Size::ZERO;
- }
- void Layout::setBackGroundColorType(BackGroundColorType type)
- {
- if (_colorType == type)
- {
- return;
- }
- switch (_colorType)
- {
- case BackGroundColorType::NONE:
- if (_colorRender)
- {
- removeProtectedChild(_colorRender);
- _colorRender = nullptr;
- }
- if (_gradientRender)
- {
- removeProtectedChild(_gradientRender);
- _gradientRender = nullptr;
- }
- break;
- case BackGroundColorType::SOLID:
- if (_colorRender)
- {
- removeProtectedChild(_colorRender);
- _colorRender = nullptr;
- }
- break;
- case BackGroundColorType::GRADIENT:
- if (_gradientRender)
- {
- removeProtectedChild(_gradientRender);
- _gradientRender = nullptr;
- }
- break;
- default:
- break;
- }
- _colorType = type;
- switch (_colorType)
- {
- case BackGroundColorType::NONE:
- break;
- case BackGroundColorType::SOLID:
- _colorRender = LayerColor::create();
- _colorRender->setContentSize(_contentSize);
- _colorRender->setOpacity(_cOpacity);
- _colorRender->setColor(_cColor);
- addProtectedChild(_colorRender, BCAKGROUNDCOLORRENDERER_Z, -1);
- break;
- case BackGroundColorType::GRADIENT:
- _gradientRender = LayerGradient::create();
- _gradientRender->setContentSize(_contentSize);
- _gradientRender->setOpacity(_cOpacity);
- _gradientRender->setStartColor(_gStartColor);
- _gradientRender->setEndColor(_gEndColor);
- _gradientRender->setVector(_alongVector);
- addProtectedChild(_gradientRender, BCAKGROUNDCOLORRENDERER_Z, -1);
- break;
- default:
- break;
- }
- }
-
- Layout::BackGroundColorType Layout::getBackGroundColorType()const
- {
- return _colorType;
- }
- void Layout::setBackGroundColor(const Color3B &color)
- {
- _cColor = color;
- if (_colorRender)
- {
- _colorRender->setColor(color);
- }
- }
-
- const Color3B& Layout::getBackGroundColor()const
- {
- return _cColor;
- }
- void Layout::setBackGroundColor(const Color3B &startColor, const Color3B &endColor)
- {
- _gStartColor = startColor;
- if (_gradientRender)
- {
- _gradientRender->setStartColor(startColor);
- }
- _gEndColor = endColor;
- if (_gradientRender)
- {
- _gradientRender->setEndColor(endColor);
- }
- }
-
- const Color3B& Layout::getBackGroundStartColor()const
- {
- return _gStartColor;
- }
- const Color3B& Layout::getBackGroundEndColor()const
- {
- return _gEndColor;
- }
- void Layout::setBackGroundColorOpacity(GLubyte opacity)
- {
- _cOpacity = opacity;
- switch (_colorType)
- {
- case BackGroundColorType::NONE:
- break;
- case BackGroundColorType::SOLID:
- _colorRender->setOpacity(opacity);
- break;
- case BackGroundColorType::GRADIENT:
- _gradientRender->setOpacity(opacity);
- break;
- default:
- break;
- }
- }
-
- GLubyte Layout::getBackGroundColorOpacity()const
- {
- return _cOpacity;
- }
- void Layout::setBackGroundColorVector(const Vec2 &vector)
- {
- _alongVector = vector;
- if (_gradientRender)
- {
- _gradientRender->setVector(vector);
- }
- }
-
- const Vec2& Layout::getBackGroundColorVector()const
- {
- return _alongVector;
- }
- void Layout::setBackGroundImageColor(const Color3B &color)
- {
- _backGroundImageColor = color;
- updateBackGroundImageColor();
- }
- void Layout::setBackGroundImageOpacity(GLubyte opacity)
- {
- _backGroundImageOpacity = opacity;
- updateBackGroundImageOpacity();
- }
- const Color3B& Layout::getBackGroundImageColor()const
- {
- return _backGroundImageColor;
- }
- GLubyte Layout::getBackGroundImageOpacity()const
- {
- return _backGroundImageOpacity;
- }
- void Layout::updateBackGroundImageColor()
- {
- if (_backGroundImage)
- {
- _backGroundImage->setColor(_backGroundImageColor);
- }
- }
- void Layout::updateBackGroundImageOpacity()
- {
- if (_backGroundImage)
- {
- _backGroundImage->setOpacity(_backGroundImageOpacity);
- }
- }
- void Layout::updateBackGroundImageRGBA()
- {
- if (_backGroundImage)
- {
- _backGroundImage->setColor(_backGroundImageColor);
- _backGroundImage->setOpacity(_backGroundImageOpacity);
- }
- }
- const Size& Layout::getBackGroundImageTextureSize() const
- {
- return _backGroundImageTextureSize;
- }
- void Layout::setLayoutType(Type type)
- {
- _layoutType = type;
-
- for (auto& child : _children)
- {
- Widget* widgetChild = dynamic_cast<Widget*>(child);
- if (widgetChild)
- {
- supplyTheLayoutParameterLackToChild(static_cast<Widget*>(child));
- }
- }
- _doLayoutDirty = true;
- }
-
- Layout::Type Layout::getLayoutType() const
- {
- return _layoutType;
- }
- void Layout::forceDoLayout()
- {
- this->requestDoLayout();
- this->doLayout();
- }
-
- void Layout::requestDoLayout()
- {
- _doLayoutDirty = true;
- }
-
- Size Layout::getLayoutContentSize()const
- {
- return this->getContentSize();
- }
-
- const Vector<Node*>& Layout::getLayoutElements()const
- {
- return this->getChildren();
- }
-
- LayoutManager* Layout::createLayoutManager()
- {
- LayoutManager* exe = nullptr;
- switch (_layoutType)
- {
- case Type::VERTICAL:
- exe = LinearVerticalLayoutManager::create();
- break;
- case Type::HORIZONTAL:
- exe = LinearHorizontalLayoutManager::create();
- break;
- case Type::RELATIVE:
- exe = RelativeLayoutManager::create();
- break;
- default:
- break;
- }
- return exe;
- }
- void Layout::doLayout()
- {
-
- if (!_doLayoutDirty)
- {
- return;
- }
-
- sortAllChildren();
- LayoutManager* executant = this->createLayoutManager();
-
- if (executant)
- {
- executant->doLayout(this);
- }
-
- _doLayoutDirty = false;
- }
- std::string Layout::getDescription() const
- {
- return "Layout";
- }
- Widget* Layout::createCloneInstance()
- {
- return Layout::create();
- }
- void Layout::copyClonedWidgetChildren(Widget* model)
- {
- Widget::copyClonedWidgetChildren(model);
- }
- void Layout::copySpecialProperties(Widget *widget)
- {
- Layout* layout = dynamic_cast<Layout*>(widget);
- if (layout)
- {
- setBackGroundImageScale9Enabled(layout->_backGroundScale9Enabled);
- setBackGroundImage(layout->_backGroundImageFileName,layout->_bgImageTexType);
- setBackGroundImageCapInsets(layout->_backGroundImageCapInsets);
- setBackGroundColorType(layout->_colorType);
- setBackGroundColor(layout->_cColor);
- setBackGroundColor(layout->_gStartColor, layout->_gEndColor);
- setBackGroundColorOpacity(layout->_cOpacity);
- setBackGroundColorVector(layout->_alongVector);
- setLayoutType(layout->_layoutType);
- setClippingEnabled(layout->_clippingEnabled);
- setClippingType(layout->_clippingType);
- _loopFocus = layout->_loopFocus;
- _passFocusToChild = layout->_passFocusToChild;
- _isInterceptTouch = layout->_isInterceptTouch;
- }
- }
-
- void Layout::setLoopFocus(bool loop)
- {
- _loopFocus = loop;
- }
- bool Layout::isLoopFocus()const
- {
- return _loopFocus;
- }
- void Layout::setPassFocusToChild(bool pass)
- {
- _passFocusToChild = pass;
- }
- bool Layout::isPassFocusToChild()const
- {
- return _passFocusToChild;
- }
- Size Layout::getLayoutAccumulatedSize()const
- {
- const auto& children = this->getChildren();
- Size layoutSize = Size::ZERO;
- int widgetCount =0;
- for(const auto& widget : children)
- {
- Layout *layout = dynamic_cast<Layout*>(widget);
- if (nullptr != layout)
- {
- layoutSize = layoutSize + layout->getLayoutAccumulatedSize();
- }
- else
- {
- Widget *w = dynamic_cast<Widget*>(widget);
- if (w)
- {
- widgetCount++;
- Margin m = w->getLayoutParameter()->getMargin();
- layoutSize = layoutSize + w->getContentSize() + Size(m.right + m.left, m.top + m.bottom) * 0.5;
- }
- }
- }
-
- //subtract extra size
- Type type = this->getLayoutType();
- if (type == Type::HORIZONTAL)
- {
- layoutSize = layoutSize - Size(0, layoutSize.height/widgetCount * (widgetCount-1));
- }
- if (type == Type::VERTICAL)
- {
- layoutSize = layoutSize - Size(layoutSize.width/widgetCount * (widgetCount-1), 0);
- }
- return layoutSize;
- }
- Vec2 Layout::getWorldCenterPoint(Widget* widget)const
- {
- Layout *layout = dynamic_cast<Layout*>(widget);
- //FIXEDME: we don't need to calculate the content size of layout anymore
- Size widgetSize = layout ? layout->getLayoutAccumulatedSize() : widget->getContentSize();
- // CCLOG("content size : width = %f, height = %f", widgetSize.width, widgetSize.height);
- return widget->convertToWorldSpace(Vec2(widgetSize.width/2, widgetSize.height/2));
- }
- float Layout::calculateNearestDistance(Widget* baseWidget)
- {
- float distance = FLT_MAX;
-
- Vec2 widgetPosition = this->getWorldCenterPoint(baseWidget);
-
- for (Node* node : _children)
- {
- Layout *layout = dynamic_cast<Layout*>(node);
- int length;
- if (layout)
- {
- length = layout->calculateNearestDistance(baseWidget);
- }
- else
- {
- Widget* w = dynamic_cast<Widget*>(node);
- if (w && w->isFocusEnabled())
- {
- Vec2 wPosition = this->getWorldCenterPoint(w);
- length = (wPosition - widgetPosition).length();
- }
- else
- {
- continue;
- }
- }
-
- if (length < distance)
- {
- distance = length;
- }
-
-
- }
- return distance;
- }
-
- float Layout::calculateFarthestDistance(cocos2d::ui::Widget *baseWidget)
- {
- float distance = -FLT_MAX;
-
- Vec2 widgetPosition = this->getWorldCenterPoint(baseWidget);
-
- for (Node* node : _children)
- {
- Layout *layout = dynamic_cast<Layout*>(node);
- int length;
- if (layout)
- {
- length = layout->calculateFarthestDistance(baseWidget);
- }
- else
- {
- Widget* w = dynamic_cast<Widget*>(node);
- if (w && w->isFocusEnabled()) {
- Vec2 wPosition = this->getWorldCenterPoint(w);
- length = (wPosition - widgetPosition).length();
- }
- else
- {
- continue;
- }
- }
-
- if (length > distance)
- {
- distance = length;
- }
- }
- return distance;
- }
- int Layout::findFirstFocusEnabledWidgetIndex()
- {
- ssize_t index = 0;
- ssize_t count = this->getChildren().size();
- while (index < count)
- {
- Widget* w = dynamic_cast<Widget*>(_children.at(index));
- if (w && w->isFocusEnabled())
- {
- return (int)index;
- }
- index++;
- }
- CCASSERT(0, "invalid operation");
- return 0;
- }
- int Layout::findNearestChildWidgetIndex(FocusDirection direction, Widget* baseWidget)
- {
- if (baseWidget == nullptr || baseWidget == this)
- {
- return this->findFirstFocusEnabledWidgetIndex();
- }
- int index = 0;
- ssize_t count = this->getChildren().size();
-
- float distance = FLT_MAX;
- int found = 0;
- if (direction == FocusDirection::LEFT || direction == FocusDirection::RIGHT ||
- direction == FocusDirection::DOWN || direction == FocusDirection::UP)
- {
- Vec2 widgetPosition = this->getWorldCenterPoint(baseWidget);
- while (index < count)
- {
- Widget *w = dynamic_cast<Widget*>(this->getChildren().at(index));
- if (w && w->isFocusEnabled())
- {
- Vec2 wPosition = this->getWorldCenterPoint(w);
- float length;
- Layout *layout = dynamic_cast<Layout*>(w);
- if (layout)
- {
- length = layout->calculateNearestDistance(baseWidget);
- }
- else
- {
- length = (wPosition - widgetPosition).getLength();
- }
-
- if (length < distance)
- {
- found = index;
- distance = length;
- }
- }
- index++;
- }
- return found;
- }
-
-
- CCASSERT(0, "invalid focus direction!!!");
- return 0;
- }
-
- int Layout::findFarthestChildWidgetIndex(FocusDirection direction, cocos2d::ui::Widget *baseWidget)
- {
- if (baseWidget == nullptr || baseWidget == this)
- {
- return this->findFirstFocusEnabledWidgetIndex();
- }
- int index = 0;
- ssize_t count = this->getChildren().size();
-
- float distance = -FLT_MAX;
- int found = 0;
- if (direction == FocusDirection::LEFT || direction == FocusDirection::RIGHT
- || direction == FocusDirection::DOWN || direction == FocusDirection::UP)
- {
- Vec2 widgetPosition = this->getWorldCenterPoint(baseWidget);
- while (index < count)
- {
- Widget *w = dynamic_cast<Widget*>(this->getChildren().at(index));
- if (w && w->isFocusEnabled())
- {
- Vec2 wPosition = this->getWorldCenterPoint(w);
- float length;
- Layout *layout = dynamic_cast<Layout*>(w);
- if (layout)
- {
- length = layout->calculateFarthestDistance(baseWidget);
- }
- else
- {
- length = (wPosition - widgetPosition).getLength();
- }
-
- if (length > distance)
- {
- found = index;
- distance = length;
- }
- }
- index++;
- }
- return found;
- }
-
- CCASSERT(0, "invalid focus direction!!!");
- return 0;
- }
-
- Widget* Layout::findFocusEnabledChildWidgetByIndex(ssize_t index)
- {
-
- Widget *widget = this->getChildWidgetByIndex(index);
-
- if (widget)
- {
- if (widget->isFocusEnabled())
- {
- return widget;
- }
- index = index + 1;
- return this->findFocusEnabledChildWidgetByIndex(index);
- }
- return nullptr;
- }
-
- Widget *Layout::findFirstNonLayoutWidget()
- {
- Widget* widget = nullptr;
- for(Node *node : _children)
- {
- Layout* layout = dynamic_cast<Layout*>(node);
- if (layout)
- {
- widget = layout->findFirstNonLayoutWidget();
- if (widget != nullptr)
- {
- return widget;
- }
- }
- else
- {
- Widget *w = dynamic_cast<Widget*>(node);
- if (w)
- {
- widget = w;
- break;
- }
- }
-
- }
-
- return widget;
- }
-
- void Layout::findProperSearchingFunctor(FocusDirection dir, Widget* baseWidget)
- {
- if (baseWidget == nullptr)
- {
- return;
- }
-
- Vec2 previousWidgetPosition = this->getWorldCenterPoint(baseWidget);
-
- Vec2 widgetPosition = this->getWorldCenterPoint(this->findFirstNonLayoutWidget());
-
- if (dir == FocusDirection::LEFT)
- {
- if (previousWidgetPosition.x > widgetPosition.x)
- {
- onPassFocusToChild = CC_CALLBACK_2(Layout::findNearestChildWidgetIndex, this);
- }
- else
- {
- onPassFocusToChild = CC_CALLBACK_2(Layout::findFarthestChildWidgetIndex, this);
- }
- }
- else if(dir == FocusDirection::RIGHT)
- {
- if (previousWidgetPosition.x > widgetPosition.x)
- {
- onPassFocusToChild = CC_CALLBACK_2(Layout::findFarthestChildWidgetIndex, this);
- }
- else
- {
- onPassFocusToChild = CC_CALLBACK_2(Layout::findNearestChildWidgetIndex, this);
- }
- }
- else if(dir == FocusDirection::DOWN)
- {
- if (previousWidgetPosition.y > widgetPosition.y)
- {
- onPassFocusToChild = CC_CALLBACK_2(Layout::findNearestChildWidgetIndex, this);
- }
- else
- {
- onPassFocusToChild = CC_CALLBACK_2(Layout::findFarthestChildWidgetIndex, this);
- }
- }
- else if(dir == FocusDirection::UP)
- {
- if (previousWidgetPosition.y < widgetPosition.y)
- {
- onPassFocusToChild = CC_CALLBACK_2(Layout::findNearestChildWidgetIndex, this);
- }
- else
- {
- onPassFocusToChild = CC_CALLBACK_2(Layout::findFarthestChildWidgetIndex, this);
- }
- }
- else
- {
- CCASSERT(0, "invalid direction!");
- }
- }
- Widget* Layout::passFocusToChild(FocusDirection dir, cocos2d::ui::Widget *current)
- {
- if (checkFocusEnabledChild())
- {
- Widget* previousWidget = this->getCurrentFocusedWidget();
-
- this->findProperSearchingFunctor(dir, previousWidget);
-
- int index = onPassFocusToChild(dir, previousWidget);
-
- Widget *widget = this->getChildWidgetByIndex(index);
- Layout *layout = dynamic_cast<Layout*>(widget);
- if (layout)
- {
- layout->_isFocusPassing = true;
- return layout->findNextFocusedWidget(dir, layout);
- }
- else
- {
- this->dispatchFocusEvent(current, widget);
- return widget;
- }
- }
- else
- {
- return this;
- }
-
- }
- bool Layout::checkFocusEnabledChild()const
- {
- bool ret = false;
- for(Node* node : _children)
- {
- Widget* widget = dynamic_cast<Widget*>(node);
- if (widget && widget->isFocusEnabled())
- {
- ret = true;
- break;
- }
- }
- return ret;
- }
- Widget* Layout::getChildWidgetByIndex(ssize_t index)const
- {
- ssize_t size = _children.size();
- int count = 0;
- ssize_t oldIndex = index;
- Widget *widget = nullptr;
- while (index < size)
- {
- Widget* firstChild = dynamic_cast<Widget*>(_children.at(index));
- if (firstChild)
- {
- widget = firstChild;
- break;
- }
- count++;
- index++;
- }
-
- if (nullptr == widget)
- {
- int begin = 0;
- while (begin < oldIndex)
- {
- Widget* firstChild = dynamic_cast<Widget*>(_children.at(begin));
- if (firstChild)
- {
- widget = firstChild;
- break;
- }
- count++;
- begin++;
- }
- }
-
-
- return widget;
- }
- Widget* Layout::getPreviousFocusedWidget(FocusDirection direction, Widget *current)
- {
- Widget *nextWidget = nullptr;
- ssize_t previousWidgetPos = _children.getIndex(current);
- previousWidgetPos = previousWidgetPos - 1;
- if (previousWidgetPos >= 0)
- {
- nextWidget = this->getChildWidgetByIndex(previousWidgetPos);
- if (nextWidget->isFocusEnabled())
- {
- Layout* layout = dynamic_cast<Layout*>(nextWidget);
- if (layout)
- {
- layout->_isFocusPassing = true;
- return layout->findNextFocusedWidget(direction, layout);
- }
- this->dispatchFocusEvent(current, nextWidget);
- return nextWidget;
- }
- else
- {
- //handling the disabled widget, there is no actual focus lose or get, so we don't need any event
- return this->getPreviousFocusedWidget(direction, nextWidget);
- }
- }
- else
- {
- if (_loopFocus)
- {
- if (checkFocusEnabledChild())
- {
- previousWidgetPos = _children.size()-1;
- nextWidget = this->getChildWidgetByIndex(previousWidgetPos);
- if (nextWidget->isFocusEnabled())
- {
- Layout* layout = dynamic_cast<Layout*>(nextWidget);
- if (layout)
- {
- layout->_isFocusPassing = true;
- return layout->findNextFocusedWidget(direction, layout);
- }
- else
- {
- this->dispatchFocusEvent(current, nextWidget);
- return nextWidget;
- }
- }
- else
- {
- return this->getPreviousFocusedWidget(direction, nextWidget);
- }
- }
- else
- {
- if (dynamic_cast<Layout*>(current))
- {
- return current;
- }
- else
- {
- return _focusedWidget;
- }
- }
- }
- else
- {
- if (isLastWidgetInContainer(current, direction))
- {
- if (isWidgetAncestorSupportLoopFocus(this, direction))
- {
- return Widget::findNextFocusedWidget(direction, this);
- }
- if (dynamic_cast<Layout*>(current))
- {
- return current;
- }
- else
- {
- return _focusedWidget;
- }
- }
- else
- {
- return Widget::findNextFocusedWidget(direction, this);
- }
- }
- }
- }
- Widget* Layout::getNextFocusedWidget(FocusDirection direction, Widget *current)
- {
- Widget *nextWidget = nullptr;
- ssize_t previousWidgetPos = _children.getIndex(current);
- previousWidgetPos = previousWidgetPos + 1;
- if (previousWidgetPos < _children.size())
- {
- nextWidget = this->getChildWidgetByIndex(previousWidgetPos);
- //handle widget
- if (nextWidget)
- {
- if (nextWidget->isFocusEnabled())
- {
- Layout* layout = dynamic_cast<Layout*>(nextWidget);
- if (layout)
- {
- layout->_isFocusPassing = true;
- return layout->findNextFocusedWidget(direction, layout);
- }
- else
- {
- this->dispatchFocusEvent(current, nextWidget);
- return nextWidget;
- }
- }
- else
- {
- return this->getNextFocusedWidget(direction, nextWidget);
- }
- }
- else
- {
- return current;
- }
- }
- else
- {
- if (_loopFocus)
- {
- if (checkFocusEnabledChild())
- {
- previousWidgetPos = 0;
- nextWidget = this->getChildWidgetByIndex(previousWidgetPos);
- if (nextWidget->isFocusEnabled())
- {
- Layout* layout = dynamic_cast<Layout*>(nextWidget);
- if (layout)
- {
- layout->_isFocusPassing = true;
- return layout->findNextFocusedWidget(direction, layout);
- }
- else
- {
- this->dispatchFocusEvent(current, nextWidget);
- return nextWidget;
- }
- }
- else
- {
- return this->getNextFocusedWidget(direction, nextWidget);
- }
- }
- else
- {
- if (dynamic_cast<Layout*>(current)) {
- return current;
- }
- else
- {
- return _focusedWidget;
- }
- }
- }
- else
- {
- if (isLastWidgetInContainer(current, direction))
- {
- if (isWidgetAncestorSupportLoopFocus(this, direction))
- {
- return Widget::findNextFocusedWidget(direction, this);
- }
- if (dynamic_cast<Layout*>(current)) {
- return current;
- }
- else
- {
- return _focusedWidget;
- }
- }
- else
- {
- return Widget::findNextFocusedWidget(direction, this);
- }
- }
- }
- }
- bool Layout::isLastWidgetInContainer(Widget* widget, FocusDirection direction)const
- {
- Layout* parent = dynamic_cast<Layout*>(widget->getParent());
- if (parent == nullptr)
- {
- return true;
- }
-
- auto& container = parent->getChildren();
- ssize_t index = container.getIndex(widget);
- if (parent->getLayoutType() == Type::HORIZONTAL)
- {
- if (direction == FocusDirection::LEFT)
- {
- if (index == 0)
- {
- return isLastWidgetInContainer(parent, direction);
- }
- else
- {
- return false;
- }
- }
- if (direction == FocusDirection::RIGHT)
- {
- if (index == container.size()-1)
- {
- return isLastWidgetInContainer(parent, direction);
- }
- else
- {
- return false;
- }
- }
- if (direction == FocusDirection::DOWN)
- {
- return isLastWidgetInContainer(parent, direction);
- }
-
- if (direction == FocusDirection::UP)
- {
- return isLastWidgetInContainer(parent, direction);
- }
- }
- else if(parent->getLayoutType() == Type::VERTICAL)
- {
- if (direction == FocusDirection::UP)
- {
- if (index == 0)
- {
- return isLastWidgetInContainer(parent, direction);
-
- }
- else
- {
- return false;
- }
- }
- if (direction == FocusDirection::DOWN)
- {
- if (index == container.size() - 1)
- {
- return isLastWidgetInContainer(parent, direction);
- }
- else
- {
- return false;
- }
- }
- if (direction == FocusDirection::LEFT)
- {
- return isLastWidgetInContainer(parent, direction);
- }
-
- if (direction == FocusDirection::RIGHT)
- {
- return isLastWidgetInContainer(parent, direction);
- }
- }
- else
- {
- CCASSERT(0, "invalid layout Type");
- return false;
- }
-
- return false;
- }
- bool Layout::isWidgetAncestorSupportLoopFocus(Widget* widget, FocusDirection direction)const
- {
- Layout* parent = dynamic_cast<Layout*>(widget->getParent());
- if (parent == nullptr)
- {
- return false;
- }
- if (parent->isLoopFocus())
- {
- auto layoutType = parent->getLayoutType();
- if (layoutType == Type::HORIZONTAL)
- {
- if (direction == FocusDirection::LEFT || direction == FocusDirection::RIGHT)
- {
- return true;
- }
- else
- {
- return isWidgetAncestorSupportLoopFocus(parent, direction);
- }
- }
- if (layoutType == Type::VERTICAL)
- {
- if (direction == FocusDirection::DOWN || direction == FocusDirection::UP)
- {
- return true;
- }
- else
- {
- return isWidgetAncestorSupportLoopFocus(parent, direction);
- }
- }
- else
- {
- CCASSERT(0, "invalid layout type");
- return false;
- }
- }
- else
- {
- return isWidgetAncestorSupportLoopFocus(parent, direction);
- }
- }
- Widget* Layout::findNextFocusedWidget(FocusDirection direction, Widget* current)
- {
- if (_isFocusPassing || this->isFocused())
- {
- Layout* parent = dynamic_cast<Layout*>(this->getParent());
- _isFocusPassing = false;
-
- if (_passFocusToChild)
- {
- Widget * w = this->passFocusToChild(direction, current);
- if (dynamic_cast<Layout*>(w))
- {
- if (parent)
- {
- parent->_isFocusPassing = true;
- return parent->findNextFocusedWidget(direction, this);
- }
- }
- return w;
- }
-
- if (nullptr == parent)
- {
- return this;
- }
- parent->_isFocusPassing = true;
- return parent->findNextFocusedWidget(direction, this);
-
- }
- else if(current->isFocused() || dynamic_cast<Layout*>(current))
- {
- if (_layoutType == Type::HORIZONTAL)
- {
- switch (direction)
- {
- case FocusDirection::LEFT:
- {
- return this->getPreviousFocusedWidget(direction, current);
- }break;
- case FocusDirection::RIGHT:
- {
- return this->getNextFocusedWidget(direction, current);
- }break;
- case FocusDirection::DOWN:
- case FocusDirection::UP:
- {
- if (isLastWidgetInContainer(this, direction))
- {
- if (isWidgetAncestorSupportLoopFocus(current, direction))
- {
- return Widget::findNextFocusedWidget(direction, this);
- }
- return current;
- }
- else
- {
- return Widget::findNextFocusedWidget(direction, this);
- }
- }break;
- default:
- {
- CCASSERT(0, "Invalid Focus Direction");
- return current;
- }
- break;
- }
- }
- else if (_layoutType == Type::VERTICAL)
- {
- switch (direction)
- {
- case FocusDirection::LEFT:
- case FocusDirection::RIGHT:
- {
- if (isLastWidgetInContainer(this, direction))
- {
- if (isWidgetAncestorSupportLoopFocus(current, direction))
- {
- return Widget::findNextFocusedWidget(direction, this);
- }
- return current;
- }
- else
- {
- return Widget::findNextFocusedWidget(direction, this);
- }
- } break;
- case FocusDirection::DOWN:
- {
- return getNextFocusedWidget(direction, current);
- }
- break;
- case FocusDirection::UP:
- {
- return getPreviousFocusedWidget(direction, current);
- }
- break;
- default:
- {
- CCASSERT(0, "Invalid Focus Direction");
- return current;
- }
- break;
- }
- }
- else
- {
- CCASSERT(0, "Un Supported Layout type, please use VBox and HBox instead!!!");
- return current;
- }
- }
- else
- {
- return current;
- }
- }
-
- void Layout::setCameraMask(unsigned short mask, bool applyChildren)
- {
- Widget::setCameraMask(mask, applyChildren);
- if (_clippingStencil){
- _clippingStencil->setCameraMask(mask, applyChildren);
- }
- }
-
- ResourceData Layout::getRenderFile()
- {
- ResourceData rData;
- rData.type = (int)_bgImageTexType;
- rData.file = _backGroundImageFileName;
- return rData;
- }
- }
- NS_CC_END
|