12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919 |
- /****************************************************************************
- Copyright (c) 2013-2017 Chukong Technologies Inc.
- 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
|