1 /****************************************************************************
  2  Copyright (c) 2010-2012 cocos2d-x.org
  3 
  4  http://www.cocos2d-x.org
  5 
  6  Permission is hereby granted, free of charge, to any person obtaining a copy
  7  of this software and associated documentation files (the "Software"), to deal
  8  in the Software without restriction, including without limitation the rights
  9  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 10  copies of the Software, and to permit persons to whom the Software is
 11  furnished to do so, subject to the following conditions:
 12 
 13  The above copyright notice and this permission notice shall be included in
 14  all copies or substantial portions of the Software.
 15 
 16  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 17  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 18  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 19  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 20  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 21  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 22  THE SOFTWARE.
 23  ****************************************************************************/
 24 /**
 25  * layoutBackGround color type
 26  * @type {Object}
 27  */
 28 ccs.LayoutBackGroundColorType = {
 29     none: 0,
 30     solid: 1,
 31     gradient: 2
 32 };
 33 
 34 /**
 35  * Layout type
 36  * @type {Object}
 37  */
 38 ccs.LayoutType = {
 39     absolute: 0,
 40     linearVertical: 1,
 41     linearHorizontal: 2,
 42     relative: 3
 43 };
 44 
 45 /**
 46  * Base class for ccs.UILayout
 47  * @class
 48  * @extends ccs.UIWidget
 49  */
 50 ccs.UILayout = ccs.UIWidget.extend(/** @lends ccs.UILayout# */{
 51     _clippingEnabled: null,
 52     _backGroundScale9Enabled: null,
 53     _backGroundImage: null,
 54     _backGroundImageFileName: null,
 55     _backGroundImageCapInsets: null,
 56     _colorType: null,
 57     _bgImageTexType: null,
 58     _colorRender: null,
 59     _gradientRender: null,
 60     _color: null,
 61     _startColor: null,
 62     _endColor: null,
 63     _alongVector: null,
 64     _opacity: null,
 65     _backGroundImageTextureSize: null,
 66     _layoutType: null,
 67     ctor: function () {
 68         ccs.UIWidget.prototype.ctor.call(this);
 69         this._clippingEnabled = false;
 70         this._backGroundScale9Enabled = false;
 71         this._backGroundImage = null;
 72         this._backGroundImageFileName = "";
 73         this._backGroundImageCapInsets = cc.RectZero();
 74         this._colorType = ccs.LayoutBackGroundColorType.none;
 75         this._bgImageTexType = ccs.TextureResType.local;
 76         this._colorRender = null;
 77         this._gradientRender = null;
 78         this._color = cc.WHITE;
 79         this._startColor = cc.WHITE;
 80         this._endColor = cc.WHITE;
 81         this._alongVector = cc.p(0, -1);
 82         this._opacity = 255;
 83         this._backGroundImageTextureSize = cc.SizeZero();
 84         this._layoutType = ccs.LayoutType.absolute;
 85         this._widgetType = ccs.WidgetType.container;
 86     },
 87     init: function () {
 88         this._layoutParameterDictionary = {};
 89         this._children = [];
 90         this.initRenderer();
 91         this._renderer.setZOrder(this._widgetZOrder);
 92         if (this._renderer.RGBAProtocol) {
 93             this._renderer.setCascadeColorEnabled(false);
 94             this._renderer.setCascadeOpacityEnabled(false);
 95         }
 96         this.ignoreContentAdaptWithSize(false);
 97         this.setSize(cc.SizeZero());
 98         this.setBright(true);
 99         this.setAnchorPoint(cc.p(0, 0));
100         this._scheduler = cc.Director.getInstance().getScheduler();
101         return true;
102     },
103 
104     initRenderer: function () {
105         this._renderer = ccs.UIRectClippingNode.create();
106     },
107 
108     /**
109      * Adds a locChild to the container.
110      * @param {ccs.UIWidget} locChild
111      * @returns {boolean}
112      */
113     addChild: function (locChild) {
114         this.supplyTheLayoutParameterLackToChild(locChild);
115         return ccs.UIWidget.prototype.addChild.call(this, locChild);
116     },
117 
118     /**
119      * Gets if layout is clipping enabled.
120      * @returns {Boolean}
121      */
122     isClippingEnabled: function () {
123         return this._clippingEnabled;
124     },
125 
126     hitTest: function (pt) {
127         var nsp = this._renderer.convertToNodeSpace(pt);
128         var bb = cc.rect(0.0, 0, this._size.width, this._size.height);
129         if (nsp.x >= bb.x && nsp.x <= bb.x + bb.width && nsp.y >= bb.y && nsp.y <= bb.y + bb.height) {
130             return true;
131         }
132         return false;
133     },
134 
135     /**
136      * Changes if layout can clip it's content and locChild.
137      * @param {Boolean} able
138      */
139     setClippingEnabled: function (able) {
140         this._clippingEnabled = able;
141         if (this._renderer instanceof ccs.UIRectClippingNode)
142             this._renderer.setClippingEnabled(able);
143     },
144 
145     onSizeChanged: function () {
146         if (this._renderer instanceof ccs.UIRectClippingNode)
147             this._renderer.setClippingSize(this._size);
148         if(this.getDescription() == "Layout"){
149             for (var i = 0; i < this._children.length; i++) {
150                 var child = this._children[i];
151                 child.updateSizeAndPosition();
152             }
153             this.doLayout();
154         }
155         if (this._backGroundImage) {
156             this._backGroundImage.setPosition(cc.p(this._size.width / 2.0, this._size.height / 2.0));
157             if (this._backGroundScale9Enabled) {
158                 if (this._backGroundImage instanceof cc.Scale9Sprite) {
159                     this._backGroundImage.setPreferredSize(this._size);
160                 }
161             }
162         }
163         if (this._colorRender) {
164             this._colorRender.setContentSize(this._size);
165         }
166         if (this._gradientRender) {
167             this._gradientRender.setContentSize(this._size);
168         }
169     },
170 
171     /**
172      * Sets background iamge use scale9 renderer.
173      * @param {Boolean} able
174      */
175     setBackGroundImageScale9Enabled: function (able) {
176         if (this._backGroundScale9Enabled == able) {
177             return;
178         }
179         this._renderer.removeChild(this._backGroundImage, true);
180         this._backGroundImage = null;
181         this._backGroundScale9Enabled = able;
182         if (this._backGroundScale9Enabled) {
183             this._backGroundImage = cc.Scale9Sprite.create();
184         }
185         else {
186             this._backGroundImage = cc.Sprite.create();
187         }
188         this._renderer.addChild(this._backGroundImage);
189         this._backGroundImage.setZOrder(-1);
190         this.setBackGroundImage(this._backGroundImageFileName, this._bgImageTexType);
191         this.setBackGroundImageCapInsets(this._backGroundImageCapInsets);
192     },
193 
194     /**
195      * Sets a background image for layout
196      * @param {String} fileName
197      * @param {ccs.TextureResType} texType
198      */
199     setBackGroundImage: function (fileName, texType) {
200         if (!fileName) {
201             return;
202         }
203         texType = texType || ccs.TextureResType.local;
204         if (this._backGroundImage == null) {
205             this.addBackGroundImage();
206         }
207         this._backGroundImageFileName = fileName;
208         this._bgImageTexType = texType;
209         if (this._backGroundScale9Enabled) {
210             switch (this._bgImageTexType) {
211                 case ccs.TextureResType.local:
212                     this._backGroundImage.initWithFile(fileName);
213                     break;
214                 case ccs.TextureResType.plist:
215                     this._backGroundImage.initWithSpriteFrameName(fileName);
216                     break;
217                 default:
218                     break;
219             }
220             this._backGroundImage.setPreferredSize(this._size);
221         }
222         else {
223             switch (this._bgImageTexType) {
224                 case ccs.TextureResType.local:
225                     this._backGroundImage.initWithFile(fileName);
226                     break;
227                 case ccs.TextureResType.plist:
228                     this._backGroundImage.initWithSpriteFrameName(fileName);
229                     break;
230                 default:
231                     break;
232             }
233         }
234         if (this._backGroundScale9Enabled) {
235             this._backGroundImage.setColor(this.getColor());
236             this._backGroundImage.setOpacity(this.getOpacity());
237         }
238         else {
239             this._backGroundImage.setColor(this.getColor());
240             this._backGroundImage.setOpacity(this.getOpacity());
241         }
242         this._backGroundImageTextureSize = this._backGroundImage.getContentSize();
243         this._backGroundImage.setPosition(cc.p(this._size.width / 2.0, this._size.height / 2.0));
244     },
245 
246     /**
247      * Sets a background image capinsets for layout, if the background image is a scale9 render.
248      * @param {cc.Rect} capInsets
249      */
250     setBackGroundImageCapInsets: function (capInsets) {
251         this._backGroundImageCapInsets = capInsets;
252         if (this._backGroundScale9Enabled) {
253             this._backGroundImage.setCapInsets(capInsets);
254         }
255     },
256 
257     supplyTheLayoutParameterLackToChild: function (locChild) {
258         if (!locChild) {
259             return;
260         }
261         switch (this._layoutType) {
262             case ccs.LayoutType.absolute:
263                 break;
264             case ccs.LayoutType.linearHorizontal:
265             case ccs.LayoutType.linearVertical:
266                 var layoutParameter = locChild.getLayoutParameter(ccs.LayoutParameterType.linear);
267                 if (!layoutParameter) {
268                     locChild.setLayoutParameter(ccs.UILinearLayoutParameter.create());
269                 }
270                 break;
271             case ccs.LayoutType.relative:
272                 var layoutParameter = locChild.getLayoutParameter(ccs.LayoutParameterType.relative);
273                 if (!layoutParameter) {
274                     locChild.setLayoutParameter(ccs.UIRelativeLayoutParameter.create());
275                 }
276                 break;
277             default:
278                 break;
279         }
280     },
281 
282     /**
283      * init background image renderer.
284      */
285     addBackGroundImage: function () {
286         if (this._backGroundScale9Enabled) {
287             this._backGroundImage = cc.Scale9Sprite.create();
288             this._backGroundImage.setZOrder(-1);
289             this._renderer.addChild(this._backGroundImage);
290             this._backGroundImage.setPreferredSize(this._size);
291         }
292         else {
293             this._backGroundImage = cc.Sprite.create();
294             this._backGroundImage.setZOrder(-1);
295             this._renderer.addChild(this._backGroundImage);
296         }
297         this._backGroundImage.setPosition(cc.p(this._size.width / 2.0, this._size.height / 2.0));
298     },
299 
300     /**
301      * Remove the background image of layout.
302      */
303     removeBackGroundImage: function () {
304         if (!this._backGroundImage) {
305             return;
306         }
307         this._renderer.removeChild(this._backGroundImage, true);
308         this._backGroundImage = null;
309         this._backGroundImageFileName = "";
310         this._backGroundImageTextureSize = cc.SizeZero();
311     },
312 
313     /**
314      * Sets Color Type for layout.
315      * @param {ccs.LayoutBackGroundColorType} type
316      */
317     setBackGroundColorType: function (type) {
318         if (this._colorType == type) {
319             return;
320         }
321         switch (this._colorType) {
322             case ccs.LayoutBackGroundColorType.none:
323                 if (this._colorRender) {
324                     this._renderer.removeChild(this._colorRender, true);
325                     this._colorRender = null;
326                 }
327                 if (this._gradientRender) {
328                     this._renderer.removeChild(this._gradientRender, true);
329                     this._gradientRender = null;
330                 }
331                 break;
332             case ccs.LayoutBackGroundColorType.solid:
333                 if (this._colorRender) {
334                     this._renderer.removeChild(this._colorRender, true);
335                     this._colorRender = null;
336                 }
337                 break;
338             case ccs.LayoutBackGroundColorType.gradient:
339                 if (this._gradientRender) {
340                     this._renderer.removeChild(this._gradientRender, true);
341                     this._gradientRender = null;
342                 }
343                 break;
344             default:
345                 break;
346         }
347         this._colorType = type;
348         switch (this._colorType) {
349             case ccs.LayoutBackGroundColorType.none:
350                 break;
351             case ccs.LayoutBackGroundColorType.solid:
352                 this._colorRender = cc.LayerColor.create();
353                 this._colorRender.setContentSize(this._size);
354                 this._colorRender.setOpacity(this._opacity);
355                 this._colorRender.setColor(this._color);
356                 this._renderer.addChild(this._colorRender, -2);
357                 break;
358             case ccs.LayoutBackGroundColorType.gradient:
359                 this._gradientRender = cc.LayerGradient.create(cc.c4b(255, 0, 0, 255), cc.c4b(0, 255, 0, 255));
360                 this._gradientRender.setContentSize(this._size);
361                 this._gradientRender.setOpacity(this._opacity);
362                 this._gradientRender.setStartColor(this._startColor);
363                 this._gradientRender.setEndColor(this._endColor);
364                 this._gradientRender.setVector(this._alongVector);
365                 this._renderer.addChild(this._gradientRender, -2);
366                 break;
367             default:
368                 break;
369         }
370     },
371 
372     /**
373      * Sets background color for layout, if color type is LAYOUT_COLOR_SOLID
374      * @param {cc.c3b} color
375      * @param {cc.c3b} endColor
376      */
377     setBackGroundColor: function (color, endColor) {
378         if (!endColor) {
379             this._color = color;
380             if (this._colorRender) {
381                 this._colorRender.setColor(color);
382             }
383         } else {
384             this._startColor = color;
385             if (this._gradientRender) {
386                 this._gradientRender.setStartColor(color);
387             }
388             this._endColor = endColor;
389             if (this._gradientRender) {
390                 this._gradientRender.setEndColor(endColor);
391             }
392         }
393     },
394 
395     /**
396      * Sets background opacity layout.
397      * @param {number} opacity
398      */
399     setBackGroundColorOpacity: function (opacity) {
400         this._opacity = opacity;
401         switch (this._colorType) {
402             case ccs.LayoutBackGroundColorType.none:
403                 break;
404             case ccs.LayoutBackGroundColorType.solid:
405                 this._colorRender.setOpacity(opacity);
406                 break;
407             case ccs.LayoutBackGroundColorType.gradient:
408                 this._gradientRender.setOpacity(opacity);
409                 break;
410             default:
411                 break;
412         }
413     },
414 
415     /**
416      * Sets background color vector for layout, if color type is LAYOUT_COLOR_GRADIENT
417      * @param {cc.Point} vector
418      */
419     setBackGroundColorVector: function (vector) {
420         this._alongVector = vector;
421         if (this._gradientRender) {
422             this._gradientRender.setVector(vector);
423         }
424     },
425 
426     /**
427      * Sets background color
428      * @param {cc.c3b} color
429      */
430     setColor: function (color) {
431         ccs.UIWidget.prototype.setColor.call(this, color);
432         if (this._backGroundImage) {
433             if (this._backGroundImage.RGBAProtocol) {
434                 this._backGroundImage.setColor(color);
435             }
436         }
437     },
438 
439     /**
440      * Sets background opacity
441      * @param {number} opacity
442      */
443     setOpacity: function (opacity) {
444         ccs.UIWidget.prototype.setOpacity.call(this, opacity);
445         if (this._backGroundImage) {
446             if (this._backGroundImage.RGBAProtocol) {
447                 this._backGroundImage.setOpacity(opacity);
448             }
449         }
450     },
451 
452     /**
453      * Gets background image texture size.
454      * @returns {cc.Size}
455      */
456     getBackGroundImageTextureSize: function () {
457         return this._backGroundImageTextureSize;
458     },
459 
460     /**
461      * Gets the content size of widget.
462      * @returns {cc.Size}
463      */
464     getContentSize: function () {
465         return this._renderer.getContentSize();
466     },
467 
468     /**
469      * Sets LayoutType.
470      * @param {ccs.LayoutType} type
471      */
472     setLayoutType: function (type) {
473         this._layoutType = type;
474         var layoutChildrenArray = this.getChildren();
475         var locChild = null;
476         for (var i = 0; i < layoutChildrenArray.length; i++) {
477             locChild = layoutChildrenArray[i];
478             this.supplyTheLayoutParameterLackToChild(locChild);
479         }
480     },
481 
482     /**
483      * Gets LayoutType.
484      * @returns {null}
485      */
486     getLayoutType: function () {
487         return this._layoutType;
488     },
489 
490     doLayout_LINEAR_VERTICAL: function () {
491         var layoutChildrenArray = this.getChildren();
492         var layoutSize = this.getSize();
493         var topBoundary = layoutSize.height;
494         for (var i = 0; i < layoutChildrenArray.length; ++i) {
495             var locChild = layoutChildrenArray[i];
496             var locLayoutParameter = locChild.getLayoutParameter(ccs.LayoutParameterType.linear);
497 
498             if (locLayoutParameter) {
499                 var locChildGravity = locLayoutParameter.getGravity();
500                 var locAP = locChild.getAnchorPoint();
501                 var locSize = locChild.getSize();
502                 var locFinalPosX = locAP.x * locSize.width;
503                 var locFinalPosY = topBoundary - ((1 - locAP.y) * locSize.height);
504                 switch (locChildGravity) {
505                     case ccs.UILinearGravity.none:
506                     case ccs.UILinearGravity.left:
507                         break;
508                     case ccs.UILinearGravity.right:
509                         locFinalPosX = layoutSize.width - ((1 - locAP.x) * locSize.width);
510                         break;
511                     case ccs.UILinearGravity.centerHorizontal:
512                         locFinalPosX = layoutSize.width / 2 - locSize.width * (0.5 - locAP.x);
513                         break;
514                     default:
515                         break;
516                 }
517                 var locMargin = locLayoutParameter.getMargin();
518                 locFinalPosX += locMargin.left;
519                 locFinalPosY -= locMargin.top;
520                 locChild.setPosition(cc.p(locFinalPosX, locFinalPosY));
521                 topBoundary = locChild.getBottomInParent() - locMargin.bottom;
522             }
523         }
524     },
525     doLayout_LINEAR_HORIZONTAL: function () {
526         var layoutChildrenArray = this.getChildren();
527         var layoutSize = this.getSize();
528         var leftBoundary = 0;
529         for (var i = 0; i < layoutChildrenArray.length; ++i) {
530             var locChild = layoutChildrenArray[i];
531             var locLayoutParameter = locChild.getLayoutParameter(ccs.LayoutParameterType.linear);
532 
533             if (locLayoutParameter) {
534                 var locChildGravity = locLayoutParameter.getGravity();
535                 var locAP = locChild.getAnchorPoint();
536                 var locSize = locChild.getSize();
537                 var locFinalPosX = leftBoundary + (locAP.x * locSize.width);
538                 var locFinalPosY = layoutSize.height - (1 - locAP.y) * locSize.height;
539                 switch (locChildGravity) {
540                     case ccs.UILinearGravity.none:
541                     case ccs.UILinearGravity.top:
542                         break;
543                     case ccs.UILinearGravity.bottom:
544                         locFinalPosY = locAP.y * locSize.height;
545                         break;
546                     case ccs.UILinearGravity.centerVertical:
547                         locFinalPosY = layoutSize.height / 2 - locSize.height * (0.5 - locAP.y);
548                         break;
549                     default:
550                         break;
551                 }
552                 var locMargin = locLayoutParameter.getMargin();
553                 locFinalPosX += locMargin.left;
554                 locFinalPosY -= locMargin.top;
555                 locChild.setPosition(cc.p(locFinalPosX, locFinalPosY));
556                 leftBoundary = locChild.getRightInParent() + locMargin.right;
557             }
558         }
559     },
560     doLayout_RELATIVE: function () {
561         var layoutChildrenArray = this.getChildren();
562         var length = layoutChildrenArray.length;
563         var unlayoutChildCount = length;
564         var layoutSize = this.getSize();
565 
566         for (var i = 0; i < length; i++) {
567             var locChild = layoutChildrenArray[i];
568             var locLayoutParameter = locChild.getLayoutParameter(ccs.LayoutParameterType.relative);
569             locLayoutParameter._put = false;
570         }
571 
572         while (unlayoutChildCount > 0) {
573             for (var i = 0; i < length; i++) {
574                 var locChild = layoutChildrenArray[i];
575                 var locLayoutParameter = locChild.getLayoutParameter(ccs.LayoutParameterType.relative);
576 
577                 if (locLayoutParameter) {
578                     if (locLayoutParameter._put) {
579                         continue;
580                     }
581                     var locAP = locChild.getAnchorPoint();
582                     var locSize = locChild.getSize();
583                     var locAlign = locLayoutParameter.getAlign();
584                     var locRelativeName = locLayoutParameter.getRelativeToWidgetName();
585                     var locRelativeWidget = null;
586                     var locRelativeWidgetLP = null;
587                     var locFinalPosX = 0;
588                     var locFinalPosY = 0;
589                     if (locRelativeName) {
590                         locRelativeWidget = ccs.UIHelper.seekWidgetByRelativeName(this, locRelativeName);
591                         if (locRelativeWidget) {
592                             locRelativeWidgetLP = locRelativeWidget.getLayoutParameter(ccs.LayoutParameterType.relative);
593                         }
594                     }
595                     switch (locAlign) {
596                         case ccs.UIRelativeAlign.alignNone:
597                         case ccs.UIRelativeAlign.alignParentTopLeft:
598                             locFinalPosX = locAP.x * locSize.width;
599                             locFinalPosY = layoutSize.height - ((1 - locAP.y) * locSize.height);
600                             break;
601                         case ccs.UIRelativeAlign.alignParentTopCenterHorizontal:
602                             locFinalPosX = layoutSize.width * 0.5 - locSize.width * (0.5 - locAP.x);
603                             locFinalPosY = layoutSize.height - ((1 - locAP.y) * locSize.height);
604                             break;
605                         case ccs.UIRelativeAlign.alignParentTopRight:
606                             locFinalPosX = layoutSize.width - ((1 - locAP.x) * locSize.width);
607                             locFinalPosY = layoutSize.height - ((1 - locAP.y) * locSize.height);
608                             break;
609                         case ccs.UIRelativeAlign.alignParentLeftCenterVertical:
610                             locFinalPosX = locAP.x * locSize.width;
611                             locFinalPosY = layoutSize.height * 0.5 - locSize.height * (0.5 - locAP.y);
612                             break;
613                         case ccs.UIRelativeAlign.centerInParent:
614                             locFinalPosX = layoutSize.width * 0.5 - locSize.width * (0.5 - locAP.x);
615                             locFinalPosY = layoutSize.height * 0.5 - locSize.height * (0.5 - locAP.y);
616                             break;
617                         case ccs.UIRelativeAlign.alignParentRightCenterVertical:
618                             locFinalPosX = layoutSize.width - ((1 - locAP.x) * locSize.width);
619                             locFinalPosY = layoutSize.height * 0.5 - locSize.height * (0.5 - locAP.y);
620                             break;
621                         case ccs.UIRelativeAlign.alignParentLeftBottom:
622                             locFinalPosX = locAP.x * locSize.width;
623                             locFinalPosY = locAP.y * locSize.height;
624                             break;
625                         case ccs.UIRelativeAlign.alignParentBottomCenterHorizontal:
626                             locFinalPosX = layoutSize.width * 0.5 - locSize.width * (0.5 - locAP.x);
627                             locFinalPosY = locAP.y * locSize.height;
628                             break;
629                         case ccs.UIRelativeAlign.alignParentRightBottom:
630                             locFinalPosX = layoutSize.width - ((1 - locAP.x) * locSize.width);
631                             locFinalPosY = locAP.y * locSize.height;
632                             break;
633 
634                         case ccs.UIRelativeAlign.locationAboveLeftAlign:
635                             if (locRelativeWidget) {
636                                 if (locRelativeWidgetLP && !locRelativeWidgetLP._put) {
637                                     continue;
638                                 }
639                                 var locationBottom = locRelativeWidget.getTopInParent();
640                                 var locationLeft = locRelativeWidget.getLeftInParent();
641                                 locFinalPosY = locationBottom + locAP.y * locSize.height;
642                                 locFinalPosX = locationLeft + locAP.x * locSize.width;
643                             }
644                             break;
645                         case ccs.UIRelativeAlign.locationAboveCenter:
646                             if (locRelativeWidget) {
647                                 if (locRelativeWidgetLP && !locRelativeWidgetLP._put) {
648                                     continue;
649                                 }
650                                 var rbs = locRelativeWidget.getSize();
651                                 var locationBottom = locRelativeWidget.getTopInParent();
652 
653                                 locFinalPosY = locationBottom + locAP.y * locSize.height;
654                                 locFinalPosX = locRelativeWidget.getLeftInParent() + rbs.width * 0.5 + locAP.x * locSize.width - locSize.width * 0.5;
655                             }
656                             break;
657                         case ccs.UIRelativeAlign.locationAboveRightAlign:
658                             if (locRelativeWidget) {
659                                 if (locRelativeWidgetLP && !locRelativeWidgetLP._put) {
660                                     continue;
661                                 }
662                                 var locationBottom = locRelativeWidget.getTopInParent();
663                                 var locationRight = locRelativeWidget.getRightInParent();
664                                 locFinalPosY = locationBottom + locAP.y * locSize.height;
665                                 locFinalPosX = locationRight - (1 - locAP.x) * locSize.width;
666                             }
667                             break;
668                         case ccs.UIRelativeAlign.locationLeftOfTopAlign:
669                             if (locRelativeWidget) {
670                                 if (locRelativeWidgetLP && !locRelativeWidgetLP._put) {
671                                     continue;
672                                 }
673                                 var locationTop = locRelativeWidget.getTopInParent();
674                                 var locationRight = locRelativeWidget.getLeftInParent();
675                                 locFinalPosY = locationTop - (1 - locAP.y) * locSize.height;
676                                 locFinalPosX = locationRight - (1 - locAP.x) * locSize.width;
677                             }
678                             break;
679                         case ccs.UIRelativeAlign.locationLeftOfCenter:
680                             if (locRelativeWidget) {
681                                 if (locRelativeWidgetLP && !locRelativeWidgetLP._put) {
682                                     continue;
683                                 }
684                                 var rbs = locRelativeWidget.getSize();
685                                 var locationRight = locRelativeWidget.getLeftInParent();
686                                 locFinalPosX = locationRight - (1 - locAP.x) * locSize.width;
687 
688                                 locFinalPosY = locRelativeWidget.getBottomInParent() + rbs.height * 0.5 + locAP.y * locSize.height - locSize.height * 0.5;
689                             }
690                             break;
691                         case ccs.UIRelativeAlign.locationLeftOfBottomAlign:
692                             if (locRelativeWidget) {
693                                 if (locRelativeWidgetLP && !locRelativeWidgetLP._put) {
694                                     continue;
695                                 }
696                                 var locationBottom = locRelativeWidget.getBottomInParent();
697                                 var locationRight = locRelativeWidget.getLeftInParent();
698                                 locFinalPosY = locationBottom + locAP.y * locSize.height;
699                                 locFinalPosX = locationRight - (1 - locAP.x) * locSize.width;
700                             }
701                             break;
702                         case ccs.UIRelativeAlign.locationRightOfTopAlign:
703                             if (locRelativeWidget) {
704                                 if (locRelativeWidgetLP && !locRelativeWidgetLP._put) {
705                                     continue;
706                                 }
707                                 var locationTop = locRelativeWidget.getTopInParent();
708                                 var locationLeft = locRelativeWidget.getRightInParent();
709                                 locFinalPosY = locationTop - (1 - locAP.y) * locSize.height;
710                                 locFinalPosX = locationLeft + locAP.x * locSize.width;
711                             }
712                             break;
713                         case ccs.UIRelativeAlign.locationRightOfCenter:
714                             if (locRelativeWidget) {
715                                 if (locRelativeWidgetLP && !locRelativeWidgetLP._put) {
716                                     continue;
717                                 }
718                                 var rbs = locRelativeWidget.getSize();
719                                 var locationLeft = locRelativeWidget.getRightInParent();
720                                 locFinalPosX = locationLeft + locAP.x * locSize.width;
721 
722                                 locFinalPosY = locRelativeWidget.getBottomInParent() + rbs.height * 0.5 + locAP.y * locSize.height - locSize.height * 0.5;
723                             }
724                             break;
725                         case ccs.UIRelativeAlign.locationRightOfBottomAlign:
726                             if (locRelativeWidget) {
727                                 if (locRelativeWidgetLP && !locRelativeWidgetLP._put) {
728                                     continue;
729                                 }
730                                 var locationBottom = locRelativeWidget.getBottomInParent();
731                                 var locationLeft = locRelativeWidget.getRightInParent();
732                                 locFinalPosY = locationBottom + locAP.y * locSize.height;
733                                 locFinalPosX = locationLeft + locAP.x * locSize.width;
734                             }
735                             break;
736                         case ccs.UIRelativeAlign.locationBelowLeftAlign:
737                             if (locRelativeWidget) {
738                                 if (locRelativeWidgetLP && !locRelativeWidgetLP._put) {
739                                     continue;
740                                 }
741                                 var locationTop = locRelativeWidget.getBottomInParent();
742                                 var locationLeft = locRelativeWidget.getLeftInParent();
743                                 locFinalPosY = locationTop - (1 - locAP.y) * locSize.height;
744                                 locFinalPosX = locationLeft + locAP.x * locSize.width;
745                             }
746                             break;
747                         case ccs.UIRelativeAlign.locationBelowCenter:
748                             if (locRelativeWidget) {
749                                 if (locRelativeWidgetLP && !locRelativeWidgetLP._put) {
750                                     continue;
751                                 }
752                                 var rbs = locRelativeWidget.getSize();
753                                 var locationTop = locRelativeWidget.getBottomInParent();
754 
755                                 locFinalPosY = locationTop - (1 - locAP.y) * locSize.height;
756                                 locFinalPosX = locRelativeWidget.getLeftInParent() + rbs.width * 0.5 + locAP.x * locSize.width - locSize.width * 0.5;
757                             }
758                             break;
759                         case ccs.UIRelativeAlign.locationBelowRightAlign:
760                             if (locRelativeWidget) {
761                                 if (locRelativeWidgetLP && !locRelativeWidgetLP._put) {
762                                     continue;
763                                 }
764                                 var locationTop = locRelativeWidget.getBottomInParent();
765                                 var locationRight = locRelativeWidget.getRightInParent();
766                                 locFinalPosY = locationTop - (1 - locAP.y) * locSize.height;
767                                 locFinalPosX = locationRight - (1 - locAP.x) * locSize.width;
768                             }
769                             break;
770                         default:
771                             break;
772                     }
773                     var locRelativeWidgetMargin;
774                     var locMargin = locLayoutParameter.getMargin();
775                     if (locRelativeWidget) {
776                         locRelativeWidgetMargin = locRelativeWidget.getLayoutParameter(ccs.LayoutParameterType.relative).getMargin();
777                     }
778                     //handle margin
779                     switch (locAlign) {
780                         case ccs.UIRelativeAlign.alignNone:
781                         case ccs.UIRelativeAlign.alignParentTopLeft:
782                             locFinalPosX += locMargin.left;
783                             locFinalPosY -= locMargin.top;
784                             break;
785                         case ccs.UIRelativeAlign.alignParentTopCenterHorizontal:
786                             locFinalPosY -= locMargin.top;
787                             break;
788                         case ccs.UIRelativeAlign.alignParentTopRight:
789                             locFinalPosX -= locMargin.right;
790                             locFinalPosY -= locMargin.top;
791                             break;
792                         case ccs.UIRelativeAlign.alignParentLeftCenterVertical:
793                             locFinalPosX += locMargin.left;
794                             break;
795                         case ccs.UIRelativeAlign.centerInParent:
796                             break;
797                         case ccs.UIRelativeAlign.alignParentRightCenterVertical:
798                             locFinalPosX -= locMargin.right;
799                             break;
800                         case ccs.UIRelativeAlign.alignParentLeftBottom:
801                             locFinalPosX += locMargin.left;
802                             locFinalPosY += locMargin.bottom;
803                             break;
804                         case ccs.UIRelativeAlign.alignParentBottomCenterHorizontal:
805                             locFinalPosY += locMargin.bottom;
806                             break;
807                         case ccs.UIRelativeAlign.alignParentRightBottom:
808                             locFinalPosX -= locMargin.right;
809                             locFinalPosY += locMargin.bottom;
810                             break;
811 
812                         case ccs.UIRelativeAlign.locationAboveLeftAlign:
813                         case ccs.UIRelativeAlign.locationAboveCenter:
814                         case ccs.UIRelativeAlign.locationAboveRightAlign:
815                             locFinalPosY += locMargin.bottom;
816                             locFinalPosY += locRelativeWidgetMargin.top;
817                             break;
818                         case ccs.UIRelativeAlign.locationLeftOfTopAlign:
819                         case ccs.UIRelativeAlign.locationLeftOfCenter:
820                         case ccs.UIRelativeAlign.locationLeftOfBottomAlign:
821                             locFinalPosX -= locMargin.right;
822                             locFinalPosX -= locRelativeWidgetMargin.left;
823                             break;
824                         case ccs.UIRelativeAlign.locationRightOfTopAlign:
825                         case ccs.UIRelativeAlign.locationRightOfCenter:
826                         case ccs.UIRelativeAlign.locationRightOfBottomAlign:
827                             locFinalPosX += locMargin.left;
828                             locFinalPosX += locRelativeWidgetMargin.right;
829                             break;
830                         case ccs.UIRelativeAlign.locationBelowLeftAlign:
831                         case ccs.UIRelativeAlign.locationBelowCenter:
832                         case ccs.UIRelativeAlign.locationBelowRightAlign:
833                             locFinalPosY -= locMargin.top;
834                             locFinalPosY -= locRelativeWidgetMargin.bottom;
835                             break;
836                         default:
837                             break;
838                     }
839                     locChild.setPosition(cc.p(locFinalPosX, locFinalPosY));
840                     locLayoutParameter._put = true;
841                     unlayoutChildCount--;
842                 }
843             }
844         }
845     },
846     doLayout: function () {
847         switch (this._layoutType) {
848             case ccs.LayoutType.absolute:
849                 break;
850             case ccs.LayoutType.linearVertical:
851                 this.doLayout_LINEAR_VERTICAL();
852                 break;
853             case ccs.LayoutType.linearHorizontal:
854                 this.doLayout_LINEAR_HORIZONTAL();
855                 break;
856             case ccs.LayoutType.relative:
857                 this.doLayout_RELATIVE();
858                 break;
859             default:
860                 break;
861         }
862     },
863 
864     /**
865      * Returns the "class name" of widget.
866      * @returns {string}
867      */
868     getDescription: function () {
869         return "Layout";
870     },
871 
872     createCloneInstance: function () {
873         return ccs.UILayout.create();
874     },
875 
876     copyClonedWidgetChildren: function (model) {
877         ccs.UIWidget.prototype.copyClonedWidgetChildren.call(this, model);
878         this.doLayout();
879     },
880 
881     copySpecialProperties: function (layout) {
882         this.setBackGroundImageScale9Enabled(layout._backGroundScale9Enabled);
883         this.setBackGroundImage(layout._backGroundImageFileName, layout._bgImageTexType);
884         this.setBackGroundImageCapInsets(layout._backGroundImageCapInsets);
885         this.setBackGroundColorType(layout._colorType);
886         this.setBackGroundColor(layout._color);
887         this.setBackGroundColor(layout._startColor, layout._endColor);
888         this.setBackGroundColorOpacity(layout._opacity);
889         this.setBackGroundColorVector(layout._alongVector);
890         this.setLayoutType(layout._layoutType);
891         this.setClippingEnabled(layout._clippingEnabled);
892     }
893 });
894 /**
895  * allocates and initializes a UILayout.
896  * @constructs
897  * @return {ccs.UILayout}
898  * @example
899  * // example
900  * var uiLayout = ccs.UILayout.create();
901  */
902 ccs.UILayout.create = function () {
903     var layout = new ccs.UILayout();
904     if (layout && layout.init()) {
905         return layout;
906     }
907     return null;
908 };
909 
910 ccs.UIRectClippingNode = cc.ClippingNode.extend({
911     _innerStencil: null,
912     _enabled: null,
913     _arrRect: null,
914     _clippingSize: null,
915     _clippingEnabled: null,
916     ctor: function () {
917         cc.ClippingNode.prototype.ctor.call(this);
918         this._innerStencil = null;
919         this._enabled = true;
920         this._arrRect = [];
921         this._clippingSize = cc.size(50, 50);
922         this._clippingEnabled = false;
923     },
924 
925     init: function () {
926         this._innerStencil = cc.DrawNode.create();
927         this._arrRect[0] = cc.p(0, 0);
928         this._arrRect[1] = cc.p(this._clippingSize.width, 0);
929         this._arrRect[2] = cc.p(this._clippingSize.width, this._clippingSize.height);
930         this._arrRect[3] = cc.p(0, this._clippingSize.height);
931 
932         var green = cc.c4f(0, 1, 0, 1);
933         this._innerStencil.drawPoly(this._arrRect, 4, green, 0, green);
934         if (cc.Browser.supportWebGL) {
935             if (cc.ClippingNode.prototype.init.call(this, this._innerStencil)) {
936                 return true;
937             }
938         } else {
939             this._stencil = this._innerStencil;
940             this._alphaThreshold = 1;
941             this._inverted = false;
942             return true;
943         }
944 
945         return false;
946     },
947 
948     setClippingSize: function (size) {
949         this.setContentSize(size);
950         this._clippingSize = cc.size(size.width, size.height);
951         this._arrRect[0] = cc.p(0, 0);
952         this._arrRect[1] = cc.p(this._clippingSize.width, 0);
953         this._arrRect[2] = cc.p(this._clippingSize.width, this._clippingSize.height);
954         this._arrRect[3] = cc.p(0, this._clippingSize.height);
955         var green = cc.c4f(0, 1, 0, 1);
956         this._innerStencil.clear();
957         this._innerStencil.drawPoly(this._arrRect, 4, green, 0, green);
958     },
959 
960     setClippingEnabled: function (enabled) {
961         this._clippingEnabled = enabled;
962     },
963 
964     visit: function (ctx) {
965         if (!this._enabled) {
966             return;
967         }
968         if (this._clippingEnabled) {
969             if (cc.Browser.supportWebGL) {
970                 cc.ClippingNode.prototype.visit.call(this, ctx);
971             } else {
972                 this.visitCanvas(ctx);
973             }
974         }
975         else {
976             cc.Node.prototype.visit.call(this, ctx);
977         }
978     },
979 
980     visitCanvas: function (ctx) {
981         // quick return if not visible
982         if (!this._visible)
983             return;
984 
985         //visit for canvas
986         var context = ctx || cc.renderContext, i;
987         var children = this._children, locChild;
988         context.save();
989         this.transform(context);
990         context.beginPath();
991         var locContentSize = this.getContentSize();
992         var locRect = cc.rect(0, 0, locContentSize.width, locContentSize.height);
993         var locEGL_ScaleX = cc.EGLView.getInstance().getScaleX(), locEGL_ScaleY = cc.EGLView.getInstance().getScaleY();
994 
995         context.rect(locRect.x * locEGL_ScaleX, locRect.y * locEGL_ScaleY, locRect.width * locEGL_ScaleX, -locRect.height * locEGL_ScaleY);
996         context.clip();
997         context.closePath();
998         var len = children.length;
999         if (len > 0) {
1000             this.sortAllChildren();
1001             // draw children zOrder < 0
1002             for (i = 0; i < len; i++) {
1003                 locChild = children[i];
1004                 if (locChild._zOrder < 0)
1005                     locChild.visit(context);
1006                 else
1007                     break;
1008             }
1009             this.draw(context);
1010             for (; i < len; i++) {
1011                 children[i].visit(context);
1012             }
1013         } else
1014             this.draw(context);
1015 
1016         this._orderOfArrival = 0;
1017         context.restore();
1018     },
1019 
1020     setEnabled: function (enabled) {
1021         this._enabled = enabled;
1022     },
1023 
1024     isEnabled: function () {
1025         return this._enabled;
1026     }
1027 });
1028 ccs.UIRectClippingNode.create = function () {
1029     var node = new ccs.UIRectClippingNode();
1030     if (node && node.init()) {
1031         return node;
1032     }
1033     return null;
1034 };