UILayout.js 68 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847
  1. /****************************************************************************
  2. Copyright (c) 2011-2012 cocos2d-x.org
  3. Copyright (c) 2013-2014 Chukong Technologies Inc.
  4. http://www.cocos2d-x.org
  5. Permission is hereby granted, free of charge, to any person obtaining a copy
  6. of this software and associated documentation files (the "Software"), to deal
  7. in the Software without restriction, including without limitation the rights
  8. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. copies of the Software, and to permit persons to whom the Software is
  10. furnished to do so, subject to the following conditions:
  11. The above copyright notice and this permission notice shall be included in
  12. all copies or substantial portions of the Software.
  13. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  18. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  19. THE SOFTWARE.
  20. ****************************************************************************/
  21. /**
  22. * ccui.Layout is the base class of ccui.PageView and ccui.ScrollView, it does layout by layout manager
  23. * and clips area by its _clippingStencil when clippingEnabled is true.
  24. * @class
  25. * @extends ccui.Widget
  26. *
  27. * @property {Boolean} clippingEnabled - Indicate whether clipping is enabled
  28. * @property {ccui.Layout.CLIPPING_STENCIL|ccui.Layout.CLIPPING_SCISSOR} clippingType
  29. * @property {ccui.Layout.ABSOLUTE|ccui.Layout.LINEAR_VERTICAL|ccui.Layout.LINEAR_HORIZONTAL|ccui.Layout.RELATIVE} layoutType
  30. *
  31. */
  32. ccui.Layout = ccui.Widget.extend(/** @lends ccui.Layout# */{
  33. _clippingEnabled: false,
  34. _backGroundScale9Enabled: null,
  35. _backGroundImage: null,
  36. _backGroundImageFileName: null,
  37. _backGroundImageCapInsets: null,
  38. _colorType: null,
  39. _bgImageTexType: ccui.Widget.LOCAL_TEXTURE,
  40. _colorRender: null,
  41. _gradientRender: null,
  42. _color: null,
  43. _startColor: null,
  44. _endColor: null,
  45. _alongVector: null,
  46. _opacity: 255,
  47. _backGroundImageTextureSize: null,
  48. _layoutType: null,
  49. _doLayoutDirty: true,
  50. _clippingRectDirty: true,
  51. _clippingType: null,
  52. _clippingStencil: null,
  53. _handleScissor: false,
  54. _scissorRectDirty: false,
  55. _clippingRect: null,
  56. _clippingParent: null,
  57. _className: "Layout",
  58. _backGroundImageColor: null,
  59. _finalPositionX: 0,
  60. _finalPositionY: 0,
  61. //clipping
  62. _currentStencilEnabled: 0,
  63. _currentStencilWriteMask: 0,
  64. _currentStencilFunc: 0,
  65. _currentStencilRef:0,
  66. _currentStencilValueMask:0,
  67. _currentStencilFail:0,
  68. _currentStencilPassDepthFail:0,
  69. _currentStencilPassDepthPass:0,
  70. _currentDepthWriteMask:0,
  71. _currentAlphaTestEnabled:0,
  72. _currentAlphaTestFunc:0,
  73. _currentAlphaTestRef:0,
  74. _backGroundImageOpacity:0,
  75. _mask_layer_le: 0,
  76. _loopFocus: false, //whether enable loop focus or not
  77. __passFocusToChild: false, //on default, it will pass the focus to the next nearest widget
  78. _isFocusPassing:false, //when finding the next focused widget, use this variable to pass focus between layout & widget
  79. /**
  80. * Allocates and initializes an UILayout.
  81. * Constructor of ccui.Layout
  82. * @function
  83. * @example
  84. * // example
  85. * var uiLayout = new ccui.Layout();
  86. */
  87. ctor: function () {
  88. this._layoutType = ccui.Layout.ABSOLUTE;
  89. this._widgetType = ccui.Widget.TYPE_CONTAINER;
  90. this._clippingType = ccui.Layout.CLIPPING_STENCIL;
  91. this._colorType = ccui.Layout.BG_COLOR_NONE;
  92. ccui.Widget.prototype.ctor.call(this);
  93. this._backGroundImageCapInsets = cc.rect(0, 0, 0, 0);
  94. this._color = cc.color(255, 255, 255, 255);
  95. this._startColor = cc.color(255, 255, 255, 255);
  96. this._endColor = cc.color(255, 255, 255, 255);
  97. this._alongVector = cc.p(0, -1);
  98. this._backGroundImageTextureSize = cc.size(0, 0);
  99. this._clippingRect = cc.rect(0, 0, 0, 0);
  100. this._backGroundImageColor = cc.color(255, 255, 255, 255);
  101. },
  102. /**
  103. * Calls its parent's onEnter, and calls its clippingStencil's onEnter if clippingStencil isn't null.
  104. * @override
  105. */
  106. onEnter: function(){
  107. ccui.Widget.prototype.onEnter.call(this);
  108. if (this._clippingStencil)
  109. this._clippingStencil.onEnter();
  110. this._doLayoutDirty = true;
  111. this._clippingRectDirty = true;
  112. },
  113. /**
  114. * Calls its parent's onExit, and calls its clippingStencil's onExit if clippingStencil isn't null.
  115. * @override
  116. */
  117. onExit: function(){
  118. ccui.Widget.prototype.onExit.call(this);
  119. if (this._clippingStencil)
  120. this._clippingStencil.onExit();
  121. },
  122. /**
  123. * If a layout is loop focused which means that the focus movement will be inside the layout
  124. * @param {Boolean} loop pass true to let the focus movement loop inside the layout
  125. */
  126. setLoopFocus: function(loop){
  127. this._loopFocus = loop;
  128. },
  129. /**
  130. * Gets whether enable focus loop
  131. * @returns {boolean} If focus loop is enabled, then it will return true, otherwise it returns false. The default value is false.
  132. */
  133. isLoopFocus: function(){
  134. return this._loopFocus;
  135. },
  136. /**
  137. * Specifies whether the layout pass its focus to its child
  138. * @param pass To specify whether the layout pass its focus to its child
  139. */
  140. setPassFocusToChild: function(pass){
  141. this.__passFocusToChild = pass;
  142. },
  143. /**
  144. * Returns whether the layout will pass the focus to its children or not. The default value is true
  145. * @returns {boolean} To query whether the layout will pass the focus to its children or not. The default value is true
  146. */
  147. isPassFocusToChild: function(){
  148. return this.__passFocusToChild;
  149. },
  150. /**
  151. * When a widget is in a layout, you could call this method to get the next focused widget within a specified direction.
  152. * If the widget is not in a layout, it will return itself
  153. * @param {Number} direction the direction to look for the next focused widget in a layout
  154. * @param {ccui.Widget} current the current focused widget
  155. * @returns {ccui.Widget} return the index of widget in the layout
  156. */
  157. findNextFocusedWidget: function(direction, current){
  158. if (this._isFocusPassing || this.isFocused()) {
  159. var parent = this.getParent();
  160. this._isFocusPassing = false;
  161. if (this.__passFocusToChild) {
  162. var w = this._passFocusToChild(direction, current);
  163. if (w instanceof ccui.Layout && parent) {
  164. parent._isFocusPassing = true;
  165. return parent.findNextFocusedWidget(direction, this);
  166. }
  167. return w;
  168. }
  169. if (null == parent)
  170. return this;
  171. parent._isFocusPassing = true;
  172. return parent.findNextFocusedWidget(direction, this);
  173. } else if(current.isFocused() || current instanceof ccui.Layout) {
  174. if (this._layoutType == ccui.Layout.LINEAR_HORIZONTAL) {
  175. switch (direction){
  176. case ccui.Widget.LEFT:
  177. return this._getPreviousFocusedWidget(direction, current);
  178. break;
  179. case ccui.Widget.RIGHT:
  180. return this._getNextFocusedWidget(direction, current);
  181. break;
  182. case ccui.Widget.DOWN:
  183. case ccui.Widget.UP:
  184. if (this._isLastWidgetInContainer(this, direction)){
  185. if (this._isWidgetAncestorSupportLoopFocus(current, direction))
  186. return this.findNextFocusedWidget(direction, this);
  187. return current;
  188. } else {
  189. return this.findNextFocusedWidget(direction, this);
  190. }
  191. break;
  192. default:
  193. cc.assert(0, "Invalid Focus Direction");
  194. return current;
  195. }
  196. } else if (this._layoutType == ccui.Layout.LINEAR_VERTICAL) {
  197. switch (direction){
  198. case ccui.Widget.LEFT:
  199. case ccui.Widget.RIGHT:
  200. if (this._isLastWidgetInContainer(this, direction)) {
  201. if (this._isWidgetAncestorSupportLoopFocus(current, direction))
  202. return this.findNextFocusedWidget(direction, this);
  203. return current;
  204. }
  205. else
  206. return this.findNextFocusedWidget(direction, this);
  207. break;
  208. case ccui.Widget.DOWN:
  209. return this._getNextFocusedWidget(direction, current);
  210. break;
  211. case ccui.Widget.UP:
  212. return this._getPreviousFocusedWidget(direction, current);
  213. break;
  214. default:
  215. cc.assert(0, "Invalid Focus Direction");
  216. return current;
  217. }
  218. } else {
  219. cc.assert(0, "Un Supported Layout type, please use VBox and HBox instead!!!");
  220. return current;
  221. }
  222. } else
  223. return current;
  224. },
  225. /**
  226. * To specify a user-defined functor to decide which child widget of the layout should get focused
  227. * @function
  228. * @param {Number} direction
  229. * @param {ccui.Widget} current
  230. */
  231. onPassFocusToChild: null,
  232. /**
  233. * override "init" method of widget. please do not call this function by yourself, you should pass the parameters to constructor to initialize it.
  234. * @returns {boolean}
  235. * @override
  236. */
  237. init: function () {
  238. if (ccui.Widget.prototype.init.call(this)) {
  239. this.ignoreContentAdaptWithSize(false);
  240. this.setContentSize(cc.size(0, 0));
  241. this.setAnchorPoint(0, 0);
  242. this.onPassFocusToChild = this._findNearestChildWidgetIndex.bind(this);
  243. return true;
  244. }
  245. return false;
  246. },
  247. __stencilDraw: function(ctx){ //Only for Canvas
  248. var locContext = ctx || cc._renderContext;
  249. var stencil = this._clippingStencil;
  250. var locEGL_ScaleX = cc.view.getScaleX(), locEGL_ScaleY = cc.view.getScaleY();
  251. for (var i = 0; i < stencil._buffer.length; i++) {
  252. var element = stencil._buffer[i];
  253. var vertices = element.verts;
  254. var firstPoint = vertices[0];
  255. locContext.beginPath();
  256. locContext.moveTo(firstPoint.x * locEGL_ScaleX, -firstPoint.y * locEGL_ScaleY);
  257. for (var j = 1, len = vertices.length; j < len; j++)
  258. locContext.lineTo(vertices[j].x * locEGL_ScaleX, -vertices[j].y * locEGL_ScaleY);
  259. }
  260. },
  261. /**
  262. * Adds a widget to the container.
  263. * @param {ccui.Widget} widget
  264. * @param {Number} [zOrder]
  265. * @param {Number|string} [tag] tag or name
  266. * @override
  267. */
  268. addChild: function (widget, zOrder, tag) {
  269. if ((widget instanceof ccui.Widget)) {
  270. this._supplyTheLayoutParameterLackToChild(widget);
  271. }
  272. ccui.Widget.prototype.addChild.call(this, widget, zOrder, tag);
  273. this._doLayoutDirty = true;
  274. },
  275. /**
  276. * Removes child widget from ccui.Layout, and sets the layout dirty flag to true.
  277. * @param {ccui.Widget} widget
  278. * @param {Boolean} [cleanup=true]
  279. * @override
  280. */
  281. removeChild: function (widget, cleanup) {
  282. ccui.Widget.prototype.removeChild.call(this, widget, cleanup);
  283. this._doLayoutDirty = true;
  284. },
  285. /**
  286. * Removes all children from the container with a cleanup, and sets the layout dirty flag to true.
  287. * @param {Boolean} cleanup
  288. */
  289. removeAllChildren: function (cleanup) {
  290. ccui.Widget.prototype.removeAllChildren.call(this, cleanup);
  291. this._doLayoutDirty = true;
  292. },
  293. /**
  294. * Removes all children from the container, do a cleanup to all running actions depending on the cleanup parameter,
  295. * and sets the layout dirty flag to true.
  296. * @param {Boolean} cleanup true if all running actions on all children nodes should be cleanup, false otherwise.
  297. */
  298. removeAllChildrenWithCleanup: function(cleanup){
  299. ccui.Widget.prototype.removeAllChildrenWithCleanup.call(this, cleanup);
  300. this._doLayoutDirty = true;
  301. },
  302. /**
  303. * Gets if layout is clipping enabled.
  304. * @returns {Boolean} if layout is clipping enabled.
  305. */
  306. isClippingEnabled: function () {
  307. return this._clippingEnabled;
  308. },
  309. /**
  310. * <p>
  311. * Calls adaptRenderers (its subclass will override it.) and do layout.
  312. * If clippingEnabled is true, it will clip/scissor area.
  313. * </p>
  314. * @override
  315. * @param {CanvasRenderingContext2D|WebGLRenderingContext} ctx
  316. */
  317. visit: function (ctx) {
  318. if (!this._visible)
  319. return;
  320. this._adaptRenderers();
  321. this._doLayout();
  322. if (this._clippingEnabled) {
  323. switch (this._clippingType) {
  324. case ccui.Layout.CLIPPING_STENCIL:
  325. this._stencilClippingVisit(ctx);
  326. break;
  327. case ccui.Layout.CLIPPING_SCISSOR:
  328. this._scissorClippingVisit(ctx);
  329. break;
  330. default:
  331. break;
  332. }
  333. } else
  334. ccui.Widget.prototype.visit.call(this, ctx);
  335. },
  336. _stencilClippingVisit: null,
  337. _stencilClippingVisitForWebGL: function (ctx) {
  338. var gl = ctx || cc._renderContext;
  339. if (!this._clippingStencil || !this._clippingStencil.isVisible())
  340. return;
  341. // all the _stencilBits are in use?
  342. if (ccui.Layout._layer + 1 == cc.stencilBits) {
  343. // warn once
  344. ccui.Layout._visit_once = true;
  345. if (ccui.Layout._visit_once) {
  346. cc.log("Nesting more than " + cc.stencilBits + "stencils is not supported. Everything will be drawn without stencil for this node and its childs.");
  347. ccui.Layout._visit_once = false;
  348. }
  349. // draw everything, as if there where no stencil
  350. cc.Node.prototype.visit.call(this, ctx);
  351. return;
  352. }
  353. ccui.Layout._layer++;
  354. var mask_layer = 0x1 << ccui.Layout._layer;
  355. var mask_layer_l = mask_layer - 1;
  356. var mask_layer_le = mask_layer | mask_layer_l;
  357. // manually save the stencil state
  358. var currentStencilEnabled = gl.isEnabled(gl.STENCIL_TEST);
  359. var currentStencilWriteMask = gl.getParameter(gl.STENCIL_WRITEMASK);
  360. var currentStencilFunc = gl.getParameter(gl.STENCIL_FUNC);
  361. var currentStencilRef = gl.getParameter(gl.STENCIL_REF);
  362. var currentStencilValueMask = gl.getParameter(gl.STENCIL_VALUE_MASK);
  363. var currentStencilFail = gl.getParameter(gl.STENCIL_FAIL);
  364. var currentStencilPassDepthFail = gl.getParameter(gl.STENCIL_PASS_DEPTH_FAIL);
  365. var currentStencilPassDepthPass = gl.getParameter(gl.STENCIL_PASS_DEPTH_PASS);
  366. gl.enable(gl.STENCIL_TEST);
  367. gl.stencilMask(mask_layer);
  368. var currentDepthWriteMask = gl.getParameter(gl.DEPTH_WRITEMASK);
  369. gl.depthMask(false);
  370. gl.stencilFunc(gl.NEVER, mask_layer, mask_layer);
  371. gl.stencilOp(gl.ZERO, gl.KEEP, gl.KEEP);
  372. // draw a fullscreen solid rectangle to clear the stencil buffer
  373. cc.kmGLMatrixMode(cc.KM_GL_PROJECTION);
  374. cc.kmGLPushMatrix();
  375. cc.kmGLLoadIdentity();
  376. cc.kmGLMatrixMode(cc.KM_GL_MODELVIEW);
  377. cc.kmGLPushMatrix();
  378. cc.kmGLLoadIdentity();
  379. cc._drawingUtil.drawSolidRect(cc.p(-1,-1), cc.p(1,1), cc.color(255, 255, 255, 255));
  380. cc.kmGLMatrixMode(cc.KM_GL_PROJECTION);
  381. cc.kmGLPopMatrix();
  382. cc.kmGLMatrixMode(cc.KM_GL_MODELVIEW);
  383. cc.kmGLPopMatrix();
  384. gl.stencilFunc(gl.NEVER, mask_layer, mask_layer);
  385. gl.stencilOp(gl.REPLACE, gl.KEEP, gl.KEEP);
  386. cc.kmGLPushMatrix();
  387. this.transform();
  388. this._clippingStencil.visit();
  389. gl.depthMask(currentDepthWriteMask);
  390. gl.stencilFunc(gl.EQUAL, mask_layer_le, mask_layer_le);
  391. gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP);
  392. // draw (according to the stencil test func) this node and its childs
  393. var i = 0; // used by _children
  394. var j = 0; // used by _protectedChildren
  395. this.sortAllChildren();
  396. this.sortAllProtectedChildren();
  397. var locChildren = this._children, locProtectChildren = this._protectedChildren;
  398. var iLen = locChildren.length, jLen = locProtectChildren.length, child;
  399. for( ; i < iLen; i++ ){
  400. child = locChildren[i];
  401. if ( child && child.getLocalZOrder() < 0 )
  402. child.visit();
  403. else
  404. break;
  405. }
  406. for( ; j < jLen; j++ ) {
  407. child = locProtectChildren[j];
  408. if ( child && child.getLocalZOrder() < 0 )
  409. child.visit();
  410. else
  411. break;
  412. }
  413. this.draw();
  414. for (; i < iLen; i++)
  415. locChildren[i].visit();
  416. for (; j < jLen; j++)
  417. locProtectChildren[j].visit();
  418. // manually restore the stencil state
  419. gl.stencilFunc(currentStencilFunc, currentStencilRef, currentStencilValueMask);
  420. gl.stencilOp(currentStencilFail, currentStencilPassDepthFail, currentStencilPassDepthPass);
  421. gl.stencilMask(currentStencilWriteMask);
  422. if (!currentStencilEnabled)
  423. gl.disable(gl.STENCIL_TEST);
  424. ccui.Layout._layer--;
  425. cc.kmGLPopMatrix();
  426. },
  427. _stencilClippingVisitForCanvas: function (ctx) {
  428. // return fast (draw nothing, or draw everything if in inverted mode) if:
  429. // - nil stencil node
  430. // - or stencil node invisible:
  431. if (!this._clippingStencil || !this._clippingStencil.isVisible()) {
  432. return;
  433. }
  434. var context = ctx || cc._renderContext;
  435. // Composition mode, costy but support texture stencil
  436. if (this._clippingStencil instanceof cc.Sprite) {
  437. // Cache the current canvas, for later use (This is a little bit heavy, replace this solution with other walkthrough)
  438. var canvas = context.canvas;
  439. var locCache = ccui.Layout._getSharedCache();
  440. locCache.width = canvas.width;
  441. locCache.height = canvas.height;
  442. var locCacheCtx = locCache.getContext("2d");
  443. locCacheCtx.drawImage(canvas, 0, 0);
  444. context.save();
  445. // Draw everything first using node visit function
  446. cc.ProtectedNode.prototype.visit.call(this, context);
  447. context.globalCompositeOperation = "destination-in";
  448. this.transform(context);
  449. this._clippingStencil.visit();
  450. context.restore();
  451. // Redraw the cached canvas, so that the cliped area shows the background etc.
  452. context.save();
  453. context.setTransform(1, 0, 0, 1, 0, 0);
  454. context.globalCompositeOperation = "destination-over";
  455. context.drawImage(locCache, 0, 0);
  456. context.restore();
  457. } else { // Clip mode, fast, but only support cc.DrawNode
  458. var i, children = this._children, locChild;
  459. context.save();
  460. this.transform(context);
  461. this._clippingStencil.visit(context);
  462. context.clip();
  463. // Clip mode doesn't support recusive stencil, so once we used a clip stencil,
  464. // so if it has ClippingNode as a child, the child must uses composition stencil.
  465. this.sortAllChildren();
  466. this.sortAllProtectedChildren();
  467. var j, locProtectChildren = this._protectedChildren;
  468. var iLen = children.length, jLen = locProtectChildren.length;
  469. // draw children zOrder < 0
  470. for (i = 0; i < iLen; i++) {
  471. locChild = children[i];
  472. if (locChild && locChild._localZOrder < 0)
  473. locChild.visit(context);
  474. else
  475. break;
  476. }
  477. for (j = 0; j < jLen; j++) {
  478. locChild = locProtectChildren[j];
  479. if (locChild && locChild._localZOrder < 0)
  480. locChild.visit(context);
  481. else
  482. break;
  483. }
  484. //this.draw(context);
  485. for (; i < iLen; i++)
  486. children[i].visit(context);
  487. for (; j < jLen; j++)
  488. locProtectChildren[j].visit(context);
  489. context.restore();
  490. }
  491. },
  492. _scissorClippingVisit: null,
  493. _scissorClippingVisitForWebGL: function (ctx) {
  494. var clippingRect = this._getClippingRect();
  495. var gl = ctx || cc._renderContext;
  496. if (this._handleScissor) {
  497. gl.enable(gl.SCISSOR_TEST);
  498. }
  499. cc.view.setScissorInPoints(clippingRect.x, clippingRect.y, clippingRect.width, clippingRect.height);
  500. cc.Node.prototype.visit.call(this);
  501. if (this._handleScissor) {
  502. gl.disable(gl.SCISSOR_TEST);
  503. }
  504. },
  505. /**
  506. * Changes if layout can clip it's content and locChild.
  507. * If you really need this, please enable it. But it would reduce the rendering efficiency.
  508. * @param {Boolean} able clipping enabled.
  509. */
  510. setClippingEnabled: function (able) {
  511. if (able == this._clippingEnabled)
  512. return;
  513. this._clippingEnabled = able;
  514. switch (this._clippingType) {
  515. case ccui.Layout.CLIPPING_STENCIL:
  516. if (able){
  517. this._clippingStencil = cc.DrawNode.create();
  518. if(cc._renderType === cc._RENDER_TYPE_CANVAS)
  519. this._clippingStencil.draw = this.__stencilDraw.bind(this);
  520. if (this._running)
  521. this._clippingStencil.onEnter();
  522. this._setStencilClippingSize(this._contentSize);
  523. } else {
  524. if (this._running && this._clippingStencil)
  525. this._clippingStencil.onExit();
  526. this._clippingStencil = null;
  527. }
  528. break;
  529. default:
  530. break;
  531. }
  532. },
  533. /**
  534. * Sets clipping type to ccui.Layout
  535. * @param {ccui.Layout.CLIPPING_STENCIL|ccui.Layout.CLIPPING_SCISSOR} type
  536. */
  537. setClippingType: function (type) {
  538. if (type == this._clippingType)
  539. return;
  540. var clippingEnabled = this.isClippingEnabled();
  541. this.setClippingEnabled(false);
  542. this._clippingType = type;
  543. this.setClippingEnabled(clippingEnabled);
  544. },
  545. /**
  546. * Gets clipping type of ccui.Layout
  547. * @returns {ccui.Layout.CLIPPING_STENCIL|ccui.Layout.CLIPPING_SCISSOR}
  548. */
  549. getClippingType: function () {
  550. return this._clippingType;
  551. },
  552. _setStencilClippingSize: function (size) {
  553. if (this._clippingEnabled && this._clippingType == ccui.Layout.CLIPPING_STENCIL) {
  554. var rect = [];
  555. rect[0] = cc.p(0, 0);
  556. rect[1] = cc.p(size.width, 0);
  557. rect[2] = cc.p(size.width, size.height);
  558. rect[3] = cc.p(0, size.height);
  559. var green = cc.color.GREEN;
  560. this._clippingStencil.clear();
  561. this._clippingStencil.drawPoly(rect, 4, green, 0, green);
  562. }
  563. },
  564. _getClippingRect: function () {
  565. if (this._clippingRectDirty) {
  566. var worldPos = this.convertToWorldSpace(cc.p(0, 0));
  567. var t = this.nodeToWorldTransform();
  568. var scissorWidth = this._contentSize.width * t.a;
  569. var scissorHeight = this._contentSize.height * t.d;
  570. var parentClippingRect;
  571. var parent = this;
  572. while (parent) {
  573. parent = parent.getParent();
  574. if (parent && parent instanceof ccui.Layout && parent.isClippingEnabled()) {
  575. this._clippingParent = parent;
  576. break;
  577. }
  578. }
  579. if (this._clippingParent) {
  580. parentClippingRect = this._clippingParent._getClippingRect();
  581. var finalX = worldPos.x - (scissorWidth * this._anchorPoint.x);
  582. var finalY = worldPos.y - (scissorHeight * this._anchorPoint.y);
  583. var finalWidth = scissorWidth;
  584. var finalHeight = scissorHeight;
  585. var leftOffset = worldPos.x - parentClippingRect.x;
  586. if (leftOffset < 0) {
  587. finalX = parentClippingRect.x;
  588. finalWidth += leftOffset;
  589. }
  590. var rightOffset = (worldPos.x + scissorWidth) - (parentClippingRect.x + parentClippingRect.width);
  591. if (rightOffset > 0)
  592. finalWidth -= rightOffset;
  593. var topOffset = (worldPos.y + scissorHeight) - (parentClippingRect.y + parentClippingRect.height);
  594. if (topOffset > 0)
  595. finalHeight -= topOffset;
  596. var bottomOffset = worldPos.y - parentClippingRect.y;
  597. if (bottomOffset < 0) {
  598. finalY = parentClippingRect.x;
  599. finalHeight += bottomOffset;
  600. }
  601. if (finalWidth < 0)
  602. finalWidth = 0;
  603. if (finalHeight < 0)
  604. finalHeight = 0;
  605. this._clippingRect.x = finalX;
  606. this._clippingRect.y = finalY;
  607. this._clippingRect.width = finalWidth;
  608. this._clippingRect.height = finalHeight;
  609. } else {
  610. this._clippingRect.x = worldPos.x - (scissorWidth * this._anchorPoint.x);
  611. this._clippingRect.y = worldPos.y - (scissorHeight * this._anchorPoint.y);
  612. this._clippingRect.width = scissorWidth;
  613. this._clippingRect.height = scissorHeight;
  614. }
  615. this._clippingRectDirty = false;
  616. }
  617. return this._clippingRect;
  618. },
  619. _onSizeChanged: function () {
  620. ccui.Widget.prototype._onSizeChanged.call(this);
  621. var locContentSize = this._contentSize;
  622. this._setStencilClippingSize(locContentSize);
  623. this._doLayoutDirty = true;
  624. this._clippingRectDirty = true;
  625. if (this._backGroundImage) {
  626. this._backGroundImage.setPosition(locContentSize.width * 0.5, locContentSize.height * 0.5);
  627. if (this._backGroundScale9Enabled && this._backGroundImage instanceof ccui.Scale9Sprite)
  628. this._backGroundImage.setPreferredSize(locContentSize);
  629. }
  630. if (this._colorRender)
  631. this._colorRender.setContentSize(locContentSize);
  632. if (this._gradientRender)
  633. this._gradientRender.setContentSize(locContentSize);
  634. },
  635. /**
  636. * Sets background image use scale9 renderer.
  637. * @param {Boolean} able true that use scale9 renderer, false otherwise.
  638. */
  639. setBackGroundImageScale9Enabled: function (able) {
  640. if (this._backGroundScale9Enabled == able)
  641. return;
  642. this.removeProtectedChild(this._backGroundImage);
  643. this._backGroundImage = null;
  644. this._backGroundScale9Enabled = able;
  645. this._addBackGroundImage();
  646. this.setBackGroundImage(this._backGroundImageFileName, this._bgImageTexType);
  647. this.setBackGroundImageCapInsets(this._backGroundImageCapInsets);
  648. },
  649. /**
  650. * Get whether background image is use scale9 renderer.
  651. * @returns {Boolean}
  652. */
  653. isBackGroundImageScale9Enabled: function () {
  654. return this._backGroundScale9Enabled;
  655. },
  656. /**
  657. * Sets a background image for layout
  658. * @param {String} fileName
  659. * @param {ccui.Widget.LOCAL_TEXTURE|ccui.Widget.PLIST_TEXTURE} texType
  660. */
  661. setBackGroundImage: function (fileName, texType) {
  662. if (!fileName)
  663. return;
  664. texType = texType || ccui.Widget.LOCAL_TEXTURE;
  665. if (this._backGroundImage == null)
  666. this._addBackGroundImage();
  667. this._backGroundImageFileName = fileName;
  668. this._bgImageTexType = texType;
  669. var locBackgroundImage = this._backGroundImage;
  670. if (this._backGroundScale9Enabled) {
  671. var bgiScale9 = locBackgroundImage;
  672. switch (this._bgImageTexType) {
  673. case ccui.Widget.LOCAL_TEXTURE:
  674. bgiScale9.initWithFile(fileName);
  675. break;
  676. case ccui.Widget.PLIST_TEXTURE:
  677. bgiScale9.initWithSpriteFrameName(fileName);
  678. break;
  679. default:
  680. break;
  681. }
  682. bgiScale9.setPreferredSize(this._contentSize);
  683. } else {
  684. var sprite = locBackgroundImage;
  685. switch (this._bgImageTexType){
  686. case ccui.Widget.LOCAL_TEXTURE:
  687. //SetTexture cannot load resource
  688. sprite.initWithFile(fileName);
  689. break;
  690. case ccui.Widget.PLIST_TEXTURE:
  691. //SetTexture cannot load resource
  692. sprite.initWithSpriteFrameName(fileName);
  693. break;
  694. default:
  695. break;
  696. }
  697. }
  698. this._backGroundImageTextureSize = locBackgroundImage.getContentSize();
  699. locBackgroundImage.setPosition(this._contentSize.width * 0.5, this._contentSize.height * 0.5);
  700. this._updateBackGroundImageColor();
  701. /*//async load callback
  702. var self = this;
  703. if(!locBackgroundImage.texture || !locBackgroundImage.texture.isLoaded()){
  704. locBackgroundImage.addLoadedEventListener(function(){
  705. self._backGroundImageTextureSize = locBackgroundImage.getContentSize();
  706. locBackgroundImage.setPosition(self._contentSize.width * 0.5, self._contentSize.height * 0.5);
  707. self._updateBackGroundImageColor();
  708. self._imageRendererAdaptDirty = true;
  709. self._findLayout();
  710. });
  711. }*/
  712. },
  713. /**
  714. * Sets a background image CapInsets for layout, if the background image is a scale9 render.
  715. * @param {cc.Rect} capInsets capinsets of background image.
  716. */
  717. setBackGroundImageCapInsets: function (capInsets) {
  718. if(!capInsets)
  719. return;
  720. var locInsets = this._backGroundImageCapInsets;
  721. locInsets.x = capInsets.x;
  722. locInsets.y = capInsets.y;
  723. locInsets.width = capInsets.width;
  724. locInsets.height = capInsets.height;
  725. if (this._backGroundScale9Enabled)
  726. this._backGroundImage.setCapInsets(capInsets);
  727. },
  728. /**
  729. * Gets background image capinsets of ccui.Layout.
  730. * @returns {cc.Rect}
  731. */
  732. getBackGroundImageCapInsets: function () {
  733. return cc.rect(this._backGroundImageCapInsets);
  734. },
  735. _supplyTheLayoutParameterLackToChild: function (locChild) {
  736. if (!locChild) {
  737. return;
  738. }
  739. switch (this._layoutType) {
  740. case ccui.Layout.ABSOLUTE:
  741. break;
  742. case ccui.Layout.LINEAR_HORIZONTAL:
  743. case ccui.Layout.LINEAR_VERTICAL:
  744. var layoutParameter = locChild.getLayoutParameter(ccui.LayoutParameter.LINEAR);
  745. if (!layoutParameter)
  746. locChild.setLayoutParameter(ccui.LinearLayoutParameter.create());
  747. break;
  748. case ccui.Layout.RELATIVE:
  749. var layoutParameter = locChild.getLayoutParameter(ccui.LayoutParameter.RELATIVE);
  750. if (!layoutParameter)
  751. locChild.setLayoutParameter(ccui.RelativeLayoutParameter.create());
  752. break;
  753. default:
  754. break;
  755. }
  756. },
  757. _addBackGroundImage: function () {
  758. if (this._backGroundScale9Enabled) {
  759. this._backGroundImage = ccui.Scale9Sprite.create();
  760. this._backGroundImage.setPreferredSize(this._contentSize);
  761. } else
  762. this._backGroundImage = cc.Sprite.create();
  763. this.addProtectedChild(this._backGroundImage, ccui.Layout.BACKGROUND_IMAGE_ZORDER, -1);
  764. this._backGroundImage.setPosition(this._contentSize.width / 2.0, this._contentSize.height / 2.0);
  765. },
  766. /**
  767. * Remove the background image of ccui.Layout.
  768. */
  769. removeBackGroundImage: function () {
  770. if (!this._backGroundImage)
  771. return;
  772. this.removeProtectedChild(this._backGroundImage);
  773. this._backGroundImage = null;
  774. this._backGroundImageFileName = "";
  775. this._backGroundImageTextureSize.width = 0;
  776. this._backGroundImageTextureSize.height = 0;
  777. },
  778. /**
  779. * Sets Color Type for ccui.Layout.
  780. * @param {ccui.Layout.BG_COLOR_NONE|ccui.Layout.BG_COLOR_SOLID|ccui.Layout.BG_COLOR_GRADIENT} type
  781. */
  782. setBackGroundColorType: function (type) {
  783. if (this._colorType == type)
  784. return;
  785. switch (this._colorType) {
  786. case ccui.Layout.BG_COLOR_NONE:
  787. if (this._colorRender) {
  788. this.removeProtectedChild(this._colorRender);
  789. this._colorRender = null;
  790. }
  791. if (this._gradientRender) {
  792. this.removeProtectedChild(this._gradientRender);
  793. this._gradientRender = null;
  794. }
  795. break;
  796. case ccui.Layout.BG_COLOR_SOLID:
  797. if (this._colorRender) {
  798. this.removeProtectedChild(this._colorRender);
  799. this._colorRender = null;
  800. }
  801. break;
  802. case ccui.Layout.BG_COLOR_GRADIENT:
  803. if (this._gradientRender) {
  804. this.removeProtectedChild(this._gradientRender);
  805. this._gradientRender = null;
  806. }
  807. break;
  808. default:
  809. break;
  810. }
  811. this._colorType = type;
  812. switch (this._colorType) {
  813. case ccui.Layout.BG_COLOR_NONE:
  814. break;
  815. case ccui.Layout.BG_COLOR_SOLID:
  816. this._colorRender = new cc.LayerColor();
  817. this._colorRender.setContentSize(this._contentSize);
  818. this._colorRender.setOpacity(this._opacity);
  819. this._colorRender.setColor(this._color);
  820. this.addProtectedChild(this._colorRender, ccui.Layout.BACKGROUND_RENDERER_ZORDER, -1);
  821. break;
  822. case ccui.Layout.BG_COLOR_GRADIENT:
  823. this._gradientRender = new cc.LayerGradient(cc.color(255, 0, 0, 255), cc.color(0, 255, 0, 255));
  824. this._gradientRender.setContentSize(this._contentSize);
  825. this._gradientRender.setOpacity(this._opacity);
  826. this._gradientRender.setStartColor(this._startColor);
  827. this._gradientRender.setEndColor(this._endColor);
  828. this._gradientRender.setVector(this._alongVector);
  829. this.addProtectedChild(this._gradientRender, ccui.Layout.BACKGROUND_RENDERER_ZORDER, -1);
  830. break;
  831. default:
  832. break;
  833. }
  834. },
  835. /**
  836. * Get background color type of ccui.Layout.
  837. * @returns {ccui.Layout.BG_COLOR_NONE|ccui.Layout.BG_COLOR_SOLID|ccui.Layout.BG_COLOR_GRADIENT}
  838. */
  839. getBackGroundColorType: function () {
  840. return this._colorType;
  841. },
  842. /**
  843. * Sets background color for layout, if color type is Layout.COLOR_SOLID
  844. * @param {cc.Color} color
  845. * @param {cc.Color} [endColor]
  846. */
  847. setBackGroundColor: function (color, endColor) {
  848. if (!endColor) {
  849. this._color.r = color.r;
  850. this._color.g = color.g;
  851. this._color.b = color.b;
  852. if (this._colorRender)
  853. this._colorRender.setColor(color);
  854. } else {
  855. this._startColor.r = color.r;
  856. this._startColor.g = color.g;
  857. this._startColor.b = color.b;
  858. if (this._gradientRender)
  859. this._gradientRender.setStartColor(color);
  860. this._endColor.r = endColor.r;
  861. this._endColor.g = endColor.g;
  862. this._endColor.b = endColor.b;
  863. if (this._gradientRender)
  864. this._gradientRender.setEndColor(endColor);
  865. }
  866. },
  867. /**
  868. * Gets background color of ccui.Layout, if color type is Layout.COLOR_SOLID.
  869. * @returns {cc.Color}
  870. */
  871. getBackGroundColor: function () {
  872. var tmpColor = this._color;
  873. return cc.color(tmpColor.r, tmpColor.g, tmpColor.b, tmpColor.a);
  874. },
  875. /**
  876. * Gets background start color of ccui.Layout
  877. * @returns {cc.Color}
  878. */
  879. getBackGroundStartColor: function () {
  880. var tmpColor = this._startColor;
  881. return cc.color(tmpColor.r, tmpColor.g, tmpColor.b, tmpColor.a);
  882. },
  883. /**
  884. * Gets background end color of ccui.Layout
  885. * @returns {cc.Color}
  886. */
  887. getBackGroundEndColor: function () {
  888. var tmpColor = this._endColor;
  889. return cc.color(tmpColor.r, tmpColor.g, tmpColor.b, tmpColor.a);
  890. },
  891. /**
  892. * Sets background opacity to ccui.Layout.
  893. * @param {number} opacity
  894. */
  895. setBackGroundColorOpacity: function (opacity) {
  896. this._opacity = opacity;
  897. switch (this._colorType) {
  898. case ccui.Layout.BG_COLOR_NONE:
  899. break;
  900. case ccui.Layout.BG_COLOR_SOLID:
  901. this._colorRender.setOpacity(opacity);
  902. break;
  903. case ccui.Layout.BG_COLOR_GRADIENT:
  904. this._gradientRender.setOpacity(opacity);
  905. break;
  906. default:
  907. break;
  908. }
  909. },
  910. /**
  911. * Get background opacity value of ccui.Layout.
  912. * @returns {Number}
  913. */
  914. getBackGroundColorOpacity: function () {
  915. return this._opacity;
  916. },
  917. /**
  918. * Sets background color vector for layout, if color type is Layout.COLOR_GRADIENT
  919. * @param {cc.Point} vector
  920. */
  921. setBackGroundColorVector: function (vector) {
  922. this._alongVector.x = vector.x;
  923. this._alongVector.y = vector.y;
  924. if (this._gradientRender) {
  925. this._gradientRender.setVector(vector);
  926. }
  927. },
  928. /**
  929. * Gets background color vector of ccui.Layout, if color type is Layout.COLOR_GRADIENT
  930. * @returns {cc.Point}
  931. */
  932. getBackGroundColorVector: function () {
  933. return this._alongVector;
  934. },
  935. /**
  936. * Sets backGround image color
  937. * @param {cc.Color} color
  938. */
  939. setBackGroundImageColor: function (color) {
  940. this._backGroundImageColor.r = color.r;
  941. this._backGroundImageColor.g = color.g;
  942. this._backGroundImageColor.b = color.b;
  943. this._updateBackGroundImageColor();
  944. },
  945. /**
  946. * Sets backGround image Opacity
  947. * @param {Number} opacity
  948. */
  949. setBackGroundImageOpacity: function (opacity) {
  950. this._backGroundImageColor.a = opacity;
  951. this.getBackGroundImageColor();
  952. },
  953. /**
  954. * Gets backGround image color
  955. * @returns {cc.Color}
  956. */
  957. getBackGroundImageColor: function () {
  958. var color = this._backGroundImageColor;
  959. return cc.color(color.r, color.g, color.b, color.a);
  960. },
  961. /**
  962. * Gets backGround image opacity
  963. * @returns {Number}
  964. */
  965. getBackGroundImageOpacity: function () {
  966. return this._backGroundImageColor.a;
  967. },
  968. _updateBackGroundImageColor: function () {
  969. if(this._backGroundImage)
  970. this._backGroundImage.setColor(this._backGroundImageColor);
  971. },
  972. /**
  973. * Gets background image texture size.
  974. * @returns {cc.Size}
  975. */
  976. getBackGroundImageTextureSize: function () {
  977. return this._backGroundImageTextureSize;
  978. },
  979. /**
  980. * Sets LayoutType to ccui.Layout, LayoutManager will do layout by layout type..
  981. * @param {ccui.Layout.ABSOLUTE|ccui.Layout.LINEAR_VERTICAL|ccui.Layout.LINEAR_HORIZONTAL|ccui.Layout.RELATIVE} type
  982. */
  983. setLayoutType: function (type) {
  984. this._layoutType = type;
  985. var layoutChildrenArray = this._children;
  986. var locChild = null;
  987. for (var i = 0; i < layoutChildrenArray.length; i++) {
  988. locChild = layoutChildrenArray[i];
  989. if(locChild instanceof ccui.Widget)
  990. this._supplyTheLayoutParameterLackToChild(locChild);
  991. }
  992. this._doLayoutDirty = true;
  993. },
  994. /**
  995. * Gets LayoutType of ccui.Layout.
  996. * @returns {null}
  997. */
  998. getLayoutType: function () {
  999. return this._layoutType;
  1000. },
  1001. /**
  1002. * request do layout, it will do layout at visit calls
  1003. */
  1004. requestDoLayout: function () {
  1005. this._doLayoutDirty = true;
  1006. },
  1007. _doLayout: function () {
  1008. if (!this._doLayoutDirty)
  1009. return;
  1010. this.sortAllChildren();
  1011. var executant = ccui.getLayoutManager(this._layoutType);
  1012. if (executant)
  1013. executant._doLayout(this);
  1014. this._doLayoutDirty = false;
  1015. },
  1016. _getLayoutContentSize: function(){
  1017. return this.getContentSize();
  1018. },
  1019. _getLayoutElements: function(){
  1020. return this.getChildren();
  1021. },
  1022. //clipping
  1023. _onBeforeVisitStencil: function(){
  1024. //TODO NEW RENDERER
  1025. },
  1026. _drawFullScreenQuadClearStencil:function(){
  1027. //TODO NEW RENDERER
  1028. },
  1029. _onAfterDrawStencil: function(){
  1030. //TODO NEW RENDERER
  1031. },
  1032. _onAfterVisitStencil: function(){
  1033. //TODO NEW RENDERER
  1034. },
  1035. _onAfterVisitScissor: function(){
  1036. //TODO NEW RENDERER
  1037. },
  1038. _onAfterVisitScissor: function(){
  1039. //TODO NEW RENDERER
  1040. },
  1041. _updateBackGroundImageOpacity: function(){
  1042. if (this._backGroundImage)
  1043. this._backGroundImage.setOpacity(this._backGroundImageOpacity);
  1044. },
  1045. _updateBackGroundImageRGBA: function(){
  1046. if (this._backGroundImage) {
  1047. this._backGroundImage.setColor(this._backGroundImageColor);
  1048. this._backGroundImage.setOpacity(this._backGroundImageOpacity);
  1049. }
  1050. },
  1051. /**
  1052. * Gets the content size of the layout, it will accumulate all its children's content size
  1053. * @returns {cc.Size}
  1054. * @private
  1055. */
  1056. _getLayoutAccumulatedSize: function(){
  1057. var children = this.getChildren();
  1058. var layoutSize = cc.size(0, 0);
  1059. var widgetCount = 0, locSize;
  1060. for(var i = 0, len = children.length; i < len; i++) {
  1061. var layout = children[i];
  1062. if (null != layout && layout instanceof ccui.Layout){
  1063. locSize = layout._getLayoutAccumulatedSize();
  1064. layoutSize.width += locSize.width;
  1065. layoutSize.height += locSize.height;
  1066. } else {
  1067. if (layout instanceof ccui.Widget) {
  1068. widgetCount++;
  1069. var m = layout.getLayoutParameter().getMargin();
  1070. locSize = layout.getContentSize();
  1071. layoutSize.width += locSize.width + (m.right + m.left) * 0.5;
  1072. layoutSize.height += locSize.height + (m.top + m.bottom) * 0.5;
  1073. }
  1074. }
  1075. }
  1076. //substract extra size
  1077. var type = this.getLayoutType();
  1078. if (type == ccui.Layout.LINEAR_HORIZONTAL)
  1079. layoutSize.height = layoutSize.height - layoutSize.height/widgetCount * (widgetCount-1);
  1080. if (type == ccui.Layout.LINEAR_VERTICAL)
  1081. layoutSize.width = layoutSize.width - layoutSize.width/widgetCount * (widgetCount-1);
  1082. return layoutSize;
  1083. },
  1084. /**
  1085. * When the layout get focused, it the layout pass the focus to its child, it will use this method to determine which child <br/>
  1086. * will get the focus. The current algorithm to determine which child will get focus is nearest-distance-priority algorithm
  1087. * @param {Number} direction next focused widget direction
  1088. * @param {ccui.Widget} baseWidget
  1089. * @returns {Number}
  1090. * @private
  1091. */
  1092. _findNearestChildWidgetIndex: function(direction, baseWidget){
  1093. if (baseWidget == null || baseWidget == this)
  1094. return this._findFirstFocusEnabledWidgetIndex();
  1095. var index = 0, locChildren = this.getChildren();
  1096. var count = locChildren.length, widgetPosition;
  1097. var distance = cc.FLT_MAX, found = 0;
  1098. if (direction == ccui.Widget.LEFT || direction == ccui.Widget.RIGHT || direction == ccui.Widget.DOWN || direction == ccui.Widget.UP) {
  1099. widgetPosition = this._getWorldCenterPoint(baseWidget);
  1100. while (index < count) {
  1101. var w = locChildren[index];
  1102. if (w && w instanceof ccui.Widget && w.isFocusEnabled()) {
  1103. var length = (w instanceof ccui.Layout)? w._calculateNearestDistance(baseWidget)
  1104. : cc.pLength(cc.pSub(this._getWorldCenterPoint(w), widgetPosition));
  1105. if (length < distance){
  1106. found = index;
  1107. distance = length;
  1108. }
  1109. }
  1110. index++;
  1111. }
  1112. return found;
  1113. }
  1114. cc.log("invalid focus direction!");
  1115. return 0;
  1116. },
  1117. /**
  1118. * When the layout get focused, it the layout pass the focus to its child, it will use this method to determine which child
  1119. * will get the focus. The current algorithm to determine which child will get focus is farthest-distance-priority algorithm
  1120. * @param {Number} direction next focused widget direction
  1121. * @param {ccui.Widget} baseWidget
  1122. * @returns {Number} The index of child widget in the container
  1123. * @private
  1124. */
  1125. _findFarthestChildWidgetIndex: function(direction, baseWidget){
  1126. if (baseWidget == null || baseWidget == this)
  1127. return this._findFirstFocusEnabledWidgetIndex();
  1128. var index = 0, locChildren = this.getChildren();
  1129. var count = locChildren.length;
  1130. var distance = -cc.FLT_MAX, found = 0;
  1131. if (direction == ccui.Widget.LEFT || direction == ccui.Widget.RIGHT || direction == ccui.Widget.DOWN || direction == ccui.Widget.UP) {
  1132. var widgetPosition = this._getWorldCenterPoint(baseWidget);
  1133. while (index < count) {
  1134. var w = locChildren[index];
  1135. if (w && w instanceof ccui.Widget && w.isFocusEnabled()) {
  1136. var length = (w instanceof ccui.Layout)?w._calculateFarthestDistance(baseWidget)
  1137. : cc.pLength(cc.pSub(this._getWorldCenterPoint(w), widgetPosition));
  1138. if (length > distance){
  1139. found = index;
  1140. distance = length;
  1141. }
  1142. }
  1143. index++;
  1144. }
  1145. return found;
  1146. }
  1147. cc.log("invalid focus direction!!!");
  1148. return 0;
  1149. },
  1150. /**
  1151. * calculate the nearest distance between the baseWidget and the children of the layout
  1152. * @param {ccui.Widget} baseWidget the base widget which will be used to calculate the distance between the layout's children and itself
  1153. * @returns {Number} return the nearest distance between the baseWidget and the layout's children
  1154. * @private
  1155. */
  1156. _calculateNearestDistance: function(baseWidget){
  1157. var distance = cc.FLT_MAX;
  1158. var widgetPosition = this._getWorldCenterPoint(baseWidget);
  1159. var locChildren = this._children;
  1160. for (var i = 0, len = locChildren.length; i < len; i++) {
  1161. var widget = locChildren[i], length;
  1162. if (widget instanceof ccui.Layout)
  1163. length = widget._calculateNearestDistance(baseWidget);
  1164. else {
  1165. if (widget instanceof ccui.Widget && widget.isFocusEnabled())
  1166. length = cc.pLength(cc.pSub(this._getWorldCenterPoint(widget), widgetPosition));
  1167. else
  1168. continue;
  1169. }
  1170. if (length < distance)
  1171. distance = length;
  1172. }
  1173. return distance;
  1174. },
  1175. /**
  1176. * calculate the farthest distance between the baseWidget and the children of the layout
  1177. * @param baseWidget
  1178. * @returns {number}
  1179. * @private
  1180. */
  1181. _calculateFarthestDistance:function(baseWidget){
  1182. var distance = -cc.FLT_MAX;
  1183. var widgetPosition = this._getWorldCenterPoint(baseWidget);
  1184. var locChildren = this._children;
  1185. for (var i = 0, len = locChildren.length; i < len; i++) {
  1186. var layout = locChildren[i];
  1187. var length;
  1188. if (layout instanceof ccui.Layout)
  1189. length = layout._calculateFarthestDistance(baseWidget);
  1190. else {
  1191. if (layout instanceof ccui.Widget && layout.isFocusEnabled()) {
  1192. var wPosition = this._getWorldCenterPoint(layout);
  1193. length = cc.pLength(cc.pSub(wPosition, widgetPosition));
  1194. } else
  1195. continue;
  1196. }
  1197. if (length > distance)
  1198. distance = length;
  1199. }
  1200. return distance;
  1201. },
  1202. /**
  1203. * when a layout pass the focus to it's child, use this method to determine which algorithm to use, nearest or farthest distance algorithm or not
  1204. * @param direction
  1205. * @param baseWidget
  1206. * @private
  1207. */
  1208. _findProperSearchingFunctor: function(direction, baseWidget){
  1209. if (baseWidget == null)
  1210. return;
  1211. var previousWidgetPosition = this._getWorldCenterPoint(baseWidget);
  1212. var widgetPosition = this._getWorldCenterPoint(this._findFirstNonLayoutWidget());
  1213. if (direction == ccui.Widget.LEFT) {
  1214. this.onPassFocusToChild = (previousWidgetPosition.x > widgetPosition.x) ? this._findNearestChildWidgetIndex.bind(this)
  1215. : this._findFarthestChildWidgetIndex.bind(this);
  1216. } else if (direction == ccui.Widget.RIGHT) {
  1217. this.onPassFocusToChild = (previousWidgetPosition.x > widgetPosition.x) ? this._findFarthestChildWidgetIndex.bind(this)
  1218. : this._findNearestChildWidgetIndex.bind(this);
  1219. }else if(direction == ccui.Widget.DOWN) {
  1220. this.onPassFocusToChild = (previousWidgetPosition.y > widgetPosition.y) ? this._findNearestChildWidgetIndex.bind(this)
  1221. : this._findFarthestChildWidgetIndex.bind(this);
  1222. }else if(direction == ccui.Widget.UP) {
  1223. this.onPassFocusToChild = (previousWidgetPosition.y < widgetPosition.y) ? this._findNearestChildWidgetIndex.bind(this)
  1224. : this._findFarthestChildWidgetIndex.bind(this);
  1225. }else
  1226. cc.log("invalid direction!");
  1227. },
  1228. /**
  1229. * find the first non-layout widget in this layout
  1230. * @returns {ccui.Widget}
  1231. * @private
  1232. */
  1233. _findFirstNonLayoutWidget:function(){
  1234. var locChildren = this._children;
  1235. for(var i = 0, len = locChildren.length; i < len; i++) {
  1236. var child = locChildren[i];
  1237. if (child instanceof ccui.Layout){
  1238. var widget = child._findFirstNonLayoutWidget();
  1239. if(widget)
  1240. return widget;
  1241. } else{
  1242. if (child instanceof cc.Widget)
  1243. return child;
  1244. }
  1245. }
  1246. return null;
  1247. },
  1248. /**
  1249. * find the first focus enabled widget index in the layout, it will recursive searching the child widget
  1250. * @returns {number}
  1251. * @private
  1252. */
  1253. _findFirstFocusEnabledWidgetIndex: function(){
  1254. var index = 0, locChildren = this.getChildren();
  1255. var count = locChildren.length;
  1256. while (index < count) {
  1257. var w = locChildren[index];
  1258. if (w && w instanceof ccui.Widget && w.isFocusEnabled())
  1259. return index;
  1260. index++;
  1261. }
  1262. return 0;
  1263. },
  1264. /**
  1265. * find a focus enabled child Widget in the layout by index
  1266. * @param index
  1267. * @returns {*}
  1268. * @private
  1269. */
  1270. _findFocusEnabledChildWidgetByIndex: function(index){
  1271. var widget = this._getChildWidgetByIndex(index);
  1272. if (widget){
  1273. if (widget.isFocusEnabled())
  1274. return widget;
  1275. index = index + 1;
  1276. return this._findFocusEnabledChildWidgetByIndex(index);
  1277. }
  1278. return null;
  1279. },
  1280. /**
  1281. * get the center point of a widget in world space
  1282. * @param {ccui.Widget} widget
  1283. * @returns {cc.Point}
  1284. * @private
  1285. */
  1286. _getWorldCenterPoint: function(widget){
  1287. //FIXEDME: we don't need to calculate the content size of layout anymore
  1288. var widgetSize = widget instanceof ccui.Layout ? widget._getLayoutAccumulatedSize() : widget.getContentSize();
  1289. return widget.convertToWorldSpace(cc.p(widgetSize.width /2, widgetSize.height /2));
  1290. },
  1291. /**
  1292. * this method is called internally by nextFocusedWidget. When the dir is Right/Down, then this method will be called
  1293. * @param {Number} direction
  1294. * @param {ccui.Widget} current the current focused widget
  1295. * @returns {ccui.Widget} the next focused widget
  1296. * @private
  1297. */
  1298. _getNextFocusedWidget: function(direction, current){
  1299. var nextWidget = null, locChildren = this._children;
  1300. var previousWidgetPos = locChildren.indexOf(current);
  1301. previousWidgetPos = previousWidgetPos + 1;
  1302. if (previousWidgetPos < locChildren.length) {
  1303. nextWidget = this._getChildWidgetByIndex(previousWidgetPos);
  1304. //handle widget
  1305. if (nextWidget) {
  1306. if (nextWidget.isFocusEnabled()) {
  1307. if (nextWidget instanceof ccui.Layout) {
  1308. nextWidget._isFocusPassing = true;
  1309. return nextWidget.findNextFocusedWidget(direction, nextWidget);
  1310. } else {
  1311. this.dispatchFocusEvent(current, nextWidget);
  1312. return nextWidget;
  1313. }
  1314. } else
  1315. return this._getNextFocusedWidget(direction, nextWidget);
  1316. } else
  1317. return current;
  1318. } else {
  1319. if (this._loopFocus) {
  1320. if (this._checkFocusEnabledChild()) {
  1321. previousWidgetPos = 0;
  1322. nextWidget = this._getChildWidgetByIndex(previousWidgetPos);
  1323. if (nextWidget.isFocusEnabled()) {
  1324. if (nextWidget instanceof ccui.Layout) {
  1325. nextWidget._isFocusPassing = true;
  1326. return nextWidget.findNextFocusedWidget(direction, nextWidget);
  1327. } else {
  1328. this.dispatchFocusEvent(current, nextWidget);
  1329. return nextWidget;
  1330. }
  1331. } else
  1332. return this._getNextFocusedWidget(direction, nextWidget);
  1333. } else {
  1334. if (current instanceof ccui.Layout)
  1335. return current;
  1336. else
  1337. return this._focusedWidget;
  1338. }
  1339. } else{
  1340. if (this._isLastWidgetInContainer(current, direction)){
  1341. if (this._isWidgetAncestorSupportLoopFocus(this, direction))
  1342. return this.findNextFocusedWidget(direction, this);
  1343. if (current instanceof ccui.Layout)
  1344. return current;
  1345. else
  1346. return this._focusedWidget;
  1347. } else
  1348. return this.findNextFocusedWidget(direction, this);
  1349. }
  1350. }
  1351. },
  1352. /**
  1353. * this method is called internally by nextFocusedWidget. When the dir is Left/Up, then this method will be called
  1354. * @param direction
  1355. * @param {ccui.Widget} current the current focused widget
  1356. * @returns {ccui.Widget} the next focused widget
  1357. * @private
  1358. */
  1359. _getPreviousFocusedWidget: function(direction, current){
  1360. var nextWidget = null, locChildren = this._children;
  1361. var previousWidgetPos = locChildren.indexOf(current);
  1362. previousWidgetPos = previousWidgetPos - 1;
  1363. if (previousWidgetPos >= 0){
  1364. nextWidget = this._getChildWidgetByIndex(previousWidgetPos);
  1365. if (nextWidget.isFocusEnabled()) {
  1366. if (nextWidget instanceof ccui.Layout){
  1367. nextWidget._isFocusPassing = true;
  1368. return nextWidget.findNextFocusedWidget(direction, nextWidget);
  1369. }
  1370. this.dispatchFocusEvent(current, nextWidget);
  1371. return nextWidget;
  1372. } else
  1373. return this._getPreviousFocusedWidget(direction, nextWidget); //handling the disabled widget, there is no actual focus lose or get, so we don't need any envet
  1374. }else {
  1375. if (this._loopFocus){
  1376. if (this._checkFocusEnabledChild()) {
  1377. previousWidgetPos = locChildren.length -1;
  1378. nextWidget = this._getChildWidgetByIndex(previousWidgetPos);
  1379. if (nextWidget.isFocusEnabled()){
  1380. if (nextWidget instanceof ccui.Layout){
  1381. nextWidget._isFocusPassing = true;
  1382. return nextWidget.findNextFocusedWidget(direction, nextWidget);
  1383. } else {
  1384. this.dispatchFocusEvent(current, nextWidget);
  1385. return nextWidget;
  1386. }
  1387. } else
  1388. return this._getPreviousFocusedWidget(direction, nextWidget);
  1389. } else
  1390. return (current instanceof ccui.Layout) ? current : this._focusedWidget;
  1391. } else {
  1392. if (this._isLastWidgetInContainer(current, direction)) {
  1393. if (this._isWidgetAncestorSupportLoopFocus(this, direction))
  1394. return this.findNextFocusedWidget(direction, this);
  1395. return (current instanceof ccui.Layout) ? current : this._focusedWidget;
  1396. } else
  1397. return this.findNextFocusedWidget(direction, this);
  1398. }
  1399. }
  1400. },
  1401. /**
  1402. * find the nth element in the _children array. Only the Widget descendant object will be returned
  1403. * @param {Number} index
  1404. * @returns {ccui.Widget}
  1405. * @private
  1406. */
  1407. _getChildWidgetByIndex: function (index) {
  1408. var locChildren = this._children;
  1409. var size = locChildren.length, count = 0, oldIndex = index;
  1410. while (index < size) {
  1411. var firstChild = locChildren[index];
  1412. if (firstChild && firstChild instanceof ccui.Widget)
  1413. return firstChild;
  1414. count++;
  1415. index++;
  1416. }
  1417. var begin = 0;
  1418. while (begin < oldIndex) {
  1419. var child = locChildren[begin];
  1420. if (child && child instanceof ccui.Widget)
  1421. return child;
  1422. count++;
  1423. begin++;
  1424. }
  1425. return null;
  1426. },
  1427. /**
  1428. * whether it is the last element according to all their parents
  1429. * @param {ccui.Widget} widget
  1430. * @param {Number} direction
  1431. * @returns {Boolean}
  1432. * @private
  1433. */
  1434. _isLastWidgetInContainer:function(widget, direction){
  1435. var parent = widget.getParent();
  1436. if (parent instanceof ccui.Layout)
  1437. return true;
  1438. var container = parent.getChildren();
  1439. var index = container.indexOf(widget);
  1440. if (parent.getLayoutType() == ccui.Layout.LINEAR_HORIZONTAL) {
  1441. if (direction == ccui.Widget.LEFT) {
  1442. if (index == 0)
  1443. return this._isLastWidgetInContainer(parent, direction);
  1444. else
  1445. return false;
  1446. }
  1447. if (direction == ccui.Widget.RIGHT) {
  1448. if (index == container.length - 1)
  1449. return this._isLastWidgetInContainer(parent, direction);
  1450. else
  1451. return false;
  1452. }
  1453. if (direction == ccui.Widget.DOWN)
  1454. return this._isLastWidgetInContainer(parent, direction);
  1455. if (direction == ccui.Widget.UP)
  1456. return this._isLastWidgetInContainer(parent, direction);
  1457. } else if(parent.getLayoutType() == ccui.Layout.LINEAR_VERTICAL){
  1458. if (direction == ccui.Widget.UP){
  1459. if (index == 0)
  1460. return this._isLastWidgetInContainer(parent, direction);
  1461. else
  1462. return false;
  1463. }
  1464. if (direction == ccui.Widget.DOWN) {
  1465. if (index == container.length - 1)
  1466. return this._isLastWidgetInContainer(parent, direction);
  1467. else
  1468. return false;
  1469. }
  1470. if (direction == ccui.Widget.LEFT)
  1471. return this._isLastWidgetInContainer(parent, direction);
  1472. if (direction == ccui.Widget.RIGHT)
  1473. return this._isLastWidgetInContainer(parent, direction);
  1474. } else {
  1475. cc.log("invalid layout Type");
  1476. return false;
  1477. }
  1478. },
  1479. /**
  1480. * Lookup any parent widget with a layout type as the direction, if the layout is loop focused, then return true, otherwise it returns false.
  1481. * @param {ccui.Widget} widget
  1482. * @param {Number} direction
  1483. * @returns {Boolean}
  1484. * @private
  1485. */
  1486. _isWidgetAncestorSupportLoopFocus: function(widget, direction){
  1487. var parent = widget.getParent();
  1488. if (parent == null)
  1489. return false;
  1490. if (parent.isLoopFocus()) {
  1491. var layoutType = parent.getLayoutType();
  1492. if (layoutType == ccui.Layout.LINEAR_HORIZONTAL) {
  1493. if (direction == ccui.Widget.LEFT || direction == ccui.Widget.RIGHT)
  1494. return true;
  1495. else
  1496. return this._isWidgetAncestorSupportLoopFocus(parent, direction);
  1497. }
  1498. if (layoutType == ccui.Layout.LINEAR_VERTICAL){
  1499. if (direction == ccui.Widget.DOWN || direction == ccui.Widget.UP)
  1500. return true;
  1501. else
  1502. return this._isWidgetAncestorSupportLoopFocus(parent, direction);
  1503. } else
  1504. cc.assert(0, "invalid layout type");
  1505. } else
  1506. return this._isWidgetAncestorSupportLoopFocus(parent, direction);
  1507. },
  1508. /**
  1509. * pass the focus to the layout's next focus enabled child
  1510. * @param {Number} direction
  1511. * @param {ccui.Widget} current
  1512. * @returns {ccui.Widget}
  1513. * @private
  1514. */
  1515. _passFocusToChild: function(direction, current){
  1516. if (this._checkFocusEnabledChild()) {
  1517. var previousWidget = ccui.Widget.getCurrentFocusedWidget();
  1518. this._findProperSearchingFunctor(direction, previousWidget);
  1519. var index = this.onPassFocusToChild(direction, previousWidget);
  1520. var widget = this._getChildWidgetByIndex(index);
  1521. if (widget instanceof ccui.Layout) {
  1522. widget._isFocusPassing = true;
  1523. return widget.findNextFocusedWidget(direction, widget);
  1524. } else {
  1525. this.dispatchFocusEvent(current, widget);
  1526. return widget;
  1527. }
  1528. }else
  1529. return this;
  1530. },
  1531. /**
  1532. * If there are no focus enabled child in the layout, it will return false, otherwise it returns true
  1533. * @returns {boolean}
  1534. * @private
  1535. */
  1536. _checkFocusEnabledChild: function(){
  1537. var locChildren = this._children;
  1538. for(var i = 0, len = locChildren.length; i < len; i++){
  1539. var widget = locChildren[i];
  1540. if (widget && widget instanceof ccui.Widget && widget.isFocusEnabled())
  1541. return true;
  1542. }
  1543. return false;
  1544. },
  1545. /**
  1546. * Returns the "class name" of widget.
  1547. * @returns {string}
  1548. */
  1549. getDescription: function () {
  1550. return "Layout";
  1551. },
  1552. _createCloneInstance: function () {
  1553. return ccui.Layout.create();
  1554. },
  1555. _copyClonedWidgetChildren: function (model) {
  1556. ccui.Widget.prototype._copyClonedWidgetChildren.call(this, model);
  1557. },
  1558. _copySpecialProperties: function (layout) {
  1559. if(!(layout instanceof ccui.Layout))
  1560. return;
  1561. this.setBackGroundImageScale9Enabled(layout._backGroundScale9Enabled);
  1562. this.setBackGroundImage(layout._backGroundImageFileName, layout._bgImageTexType);
  1563. this.setBackGroundImageCapInsets(layout._backGroundImageCapInsets);
  1564. this.setBackGroundColorType(layout._colorType);
  1565. this.setBackGroundColor(layout._color);
  1566. this.setBackGroundColor(layout._startColor, layout._endColor);
  1567. this.setBackGroundColorOpacity(layout._opacity);
  1568. this.setBackGroundColorVector(layout._alongVector);
  1569. this.setLayoutType(layout._layoutType);
  1570. this.setClippingEnabled(layout._clippingEnabled);
  1571. this.setClippingType(layout._clippingType);
  1572. this._loopFocus = layout._loopFocus;
  1573. this.__passFocusToChild = layout.__passFocusToChild;
  1574. }
  1575. });
  1576. ccui.Layout._init_once = null;
  1577. ccui.Layout._visit_once = null;
  1578. ccui.Layout._layer = -1;
  1579. ccui.Layout._sharedCache = null;
  1580. if (cc._renderType == cc._RENDER_TYPE_WEBGL) {
  1581. //WebGL
  1582. ccui.Layout.prototype._stencilClippingVisit = ccui.Layout.prototype._stencilClippingVisitForWebGL;
  1583. ccui.Layout.prototype._scissorClippingVisit = ccui.Layout.prototype._scissorClippingVisitForWebGL;
  1584. } else {
  1585. ccui.Layout.prototype._stencilClippingVisit = ccui.Layout.prototype._stencilClippingVisitForCanvas;
  1586. ccui.Layout.prototype._scissorClippingVisit = ccui.Layout.prototype._stencilClippingVisitForCanvas;
  1587. }
  1588. ccui.Layout._getSharedCache = function () {
  1589. return (cc.ClippingNode._sharedCache) || (cc.ClippingNode._sharedCache = cc.newElement("canvas"));
  1590. };
  1591. var _p = ccui.Layout.prototype;
  1592. // Extended properties
  1593. /** @expose */
  1594. _p.clippingEnabled;
  1595. cc.defineGetterSetter(_p, "clippingEnabled", _p.isClippingEnabled, _p.setClippingEnabled);
  1596. /** @expose */
  1597. _p.clippingType;
  1598. cc.defineGetterSetter(_p, "clippingType", null, _p.setClippingType);
  1599. /** @expose */
  1600. _p.layoutType;
  1601. cc.defineGetterSetter(_p, "layoutType", _p.getLayoutType, _p.setLayoutType);
  1602. _p = null;
  1603. /**
  1604. * allocates and initializes a UILayout.
  1605. * @deprecated since v3.0, please use new ccui.Layout() instead.
  1606. * @return {ccui.Layout}
  1607. * @example
  1608. * // example
  1609. * var uiLayout = ccui.Layout.create();
  1610. */
  1611. ccui.Layout.create = function () {
  1612. return new ccui.Layout();
  1613. };
  1614. // Constants
  1615. //layoutBackGround color type
  1616. /**
  1617. * The None of ccui.Layout's background color type
  1618. * @constant
  1619. * @type {number}
  1620. */
  1621. ccui.Layout.BG_COLOR_NONE = 0;
  1622. /**
  1623. * The solid of ccui.Layout's background color type, it will use a LayerColor to draw the background.
  1624. * @constant
  1625. * @type {number}
  1626. */
  1627. ccui.Layout.BG_COLOR_SOLID = 1;
  1628. /**
  1629. * The gradient of ccui.Layout's background color type, it will use a LayerGradient to draw the background.
  1630. * @constant
  1631. * @type {number}
  1632. */
  1633. ccui.Layout.BG_COLOR_GRADIENT = 2;
  1634. //Layout type
  1635. /**
  1636. * The absolute of ccui.Layout's layout type.
  1637. * @type {number}
  1638. * @constant
  1639. */
  1640. ccui.Layout.ABSOLUTE = 0;
  1641. /**
  1642. * The vertical of ccui.Layout's layout type.
  1643. * @type {number}
  1644. * @constant
  1645. */
  1646. ccui.Layout.LINEAR_VERTICAL = 1;
  1647. /**
  1648. * The horizontal of ccui.Layout's layout type.
  1649. * @type {number}
  1650. * @constant
  1651. */
  1652. ccui.Layout.LINEAR_HORIZONTAL = 2;
  1653. /**
  1654. * The relative of ccui.Layout's layout type.
  1655. * @type {number}
  1656. * @constant
  1657. */
  1658. ccui.Layout.RELATIVE = 3;
  1659. //Layout clipping type
  1660. /**
  1661. * The stencil of ccui.Layout's clipping type.
  1662. * @type {number}
  1663. * @constant
  1664. */
  1665. ccui.Layout.CLIPPING_STENCIL = 0;
  1666. /**
  1667. * The scissor of ccui.Layout's clipping type.
  1668. * @type {number}
  1669. * @constant
  1670. */
  1671. ccui.Layout.CLIPPING_SCISSOR = 1;
  1672. /**
  1673. * The zOrder value of ccui.Layout's image background.
  1674. * @type {number}
  1675. * @constant
  1676. */
  1677. ccui.Layout.BACKGROUND_IMAGE_ZORDER = -2;
  1678. /**
  1679. * The zOrder value of ccui.Layout's color background.
  1680. * @type {number}
  1681. * @constant
  1682. */
  1683. ccui.Layout.BACKGROUND_RENDERER_ZORDER = -2;