1 /****************************************************************************
  2  Copyright (c) 2011-2012 cocos2d-x.org
  3  Copyright (c) 2013-2014 Chukong Technologies Inc.
  4 
  5  http://www.cocos2d-x.org
  6 
  7  Permission is hereby granted, free of charge, to any person obtaining a copy
  8  of this software and associated documentation files (the "Software"), to deal
  9  in the Software without restriction, including without limitation the rights
 10  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 11  copies of the Software, and to permit persons to whom the Software is
 12  furnished to do so, subject to the following conditions:
 13 
 14  The above copyright notice and this permission notice shall be included in
 15  all copies or substantial portions of the Software.
 16 
 17  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 18  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 19  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 20  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 21  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 22  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 23  THE SOFTWARE.
 24  ****************************************************************************/
 25 
 26 /**
 27  * Base class for ccui.Widget
 28  * @sample
 29  * var uiWidget = ccui.Widget.create();
 30  * this.addChild(uiWidget);
 31  * @class
 32  * @extends ccui.ProtectedNode
 33  *
 34  * @property {Number}           xPercent        - Position x in percentage of width
 35  * @property {Number}           yPercent        - Position y in percentage of height
 36  * @property {Number}           widthPercent    - Width in percentage of parent width
 37  * @property {Number}           heightPercent   - Height in percentage of parent height
 38  * @property {ccui.Widget}       widgetParent    - <@readonly> The direct parent when it's a widget also, otherwise equals null
 39  * @property {Boolean}          enabled         - Indicate whether the widget is enabled
 40  * @property {Boolean}          focused         - Indicate whether the widget is focused
 41  * @property {ccui.Widget.SIZE_ABSOLUTE|ccui.Widget.SIZE_PERCENT}     sizeType        - The size type of the widget
 42  * @property {ccui.Widget.TYPE_WIDGET|ccui.Widget.TYPE_CONTAINER}   widgetType      - <@readonly> The type of the widget
 43  * @property {Boolean}          touchEnabled    - Indicate whether touch events are enabled
 44  * @property {Boolean}          updateEnabled   - Indicate whether the update function is scheduled
 45  * @property {Boolean}          bright          - Indicate whether the widget is bright
 46  * @property {String}           name            - The name of the widget
 47  * @property {Number}           actionTag       - The action tag of the widget
 48  */
 49 ccui.Widget = ccui.ProtectedNode.extend(/** @lends ccui.Widget# */{
 50     _enabled: true,            ///< Highest control of widget
 51     _bright: true,             ///< is this widget bright
 52     _touchEnabled: false,       ///< is this widget touch endabled
 53 
 54     _brightStyle: null, ///< bright style
 55     _updateEnabled: false,      ///< is "update" method scheduled
 56 
 57     _touchBeganPosition: null,    ///< touch began point
 58     _touchMovePosition: null,     ///< touch moved point
 59     _touchEndPosition: null,      ///< touch ended point
 60 
 61     _touchEventListener: null,
 62     _touchEventSelector: null,
 63 
 64     _name: "default",
 65     _widgetType: null,
 66     _actionTag: 0,
 67     _size: cc.size(0,0),
 68     _customSize: null,
 69     _layoutParameterDictionary: null,
 70     _layoutParameterType:0,
 71 
 72     _focused: false,
 73     _focusEnabled: true,
 74 
 75     _ignoreSize: false,
 76     _affectByClipping: false,
 77 
 78     _sizeType: null,
 79     _sizePercent: null,
 80     positionType: null,
 81     _positionPercent: null,
 82     _reorderWidgetChildDirty: false,
 83     _hitted: false,                          //TODO typo
 84     _nodes: null,
 85     _touchListener: null,
 86     _color: null,
 87     _className: "Widget",
 88     _flippedX: false,
 89     _flippedY: false,
 90     _opacity: 255,
 91     _highlight: false,
 92 
 93     _touchEventCallback: null,
 94 
 95     ctor: function () {
 96         cc.ProtectedNode.prototype.ctor.call(this);
 97         this._brightStyle = ccui.Widget.BRIGHT_STYLE_NONE;
 98         this._touchBeganPosition = cc.p(0, 0);
 99         this._touchMovePosition = cc.p(0, 0);
100         this._touchEndPosition = cc.p(0, 0);
101         this._widgetType = ccui.Widget.TYPE_WIDGET;
102         this._size = cc.size(0, 0);
103         this._customSize = cc.size(0, 0);
104         this._layoutParameterDictionary = {};
105         this._sizeType = ccui.Widget.SIZE_ABSOLUTE;
106         this._sizePercent = cc.p(0, 0);
107         this.positionType = ccui.Widget.POSITION_ABSOLUTE;
108         this._positionPercent = cc.p(0, 0);
109         this._nodes = [];
110         this._color = cc.color(255, 255, 255, 255);
111         this._layoutParameterType = ccui.LayoutParameter.NONE;
112         this.init();                        //TODO
113     },
114 
115     /**
116      * initializes state of widget.
117      * @returns {boolean}
118      */
119     init: function () {
120         if (cc.ProtectedNode.prototype.init.call(this)) {
121             this._layoutParameterDictionary = {};
122             this.initRenderer();
123             this.setBright(true);
124 
125             this.onFocusChanged = this.onFocusChange.bind(this);
126             this.onNextFocusedWidget = null;
127             this.setAnchorPoint(cc.p(0.5, 0.5));
128 
129             this.ignoreContentAdaptWithSize(true);
130 
131 //            this.setTouchEnabled(true);
132             this.setCascadeColorEnabled(true);
133             this.setCascadeOpacityEnabled(true);
134 
135             return true;
136         }
137         return false;
138     },
139 
140     onEnter: function () {
141         this.updateSizeAndPosition();
142         cc.ProtectedNode.prototype.onEnter.call(this);
143     },
144 
145     onExit: function(){
146         this.unscheduleUpdate();
147         cc.ProtectedNode.prototype.onExit.call(this);
148     },
149 
150     visit: function (ctx) {
151         if (this._visible) {
152             this.adaptRenderers();
153             cc.ProtectedNode.prototype.visit.call(this, ctx);
154         }
155     },
156 
157     getWidgetParent: function () {
158         var widget = this.getParent();
159         if (widget instanceof ccui.Widget) {
160             return widget;
161         }
162         return null;
163     },
164 
165     _updateContentSizeWithTextureSize: function(size){
166         var locSize = this._size;
167         if (this._ignoreSize) {
168             locSize.width = size.width;
169             locSize.height = size.height;
170         } else {
171             locSize.width = this._customSize.width;
172             locSize.height = this._customSize.height;
173         }
174         this.onSizeChanged();
175     },
176 
177     _isAncestorsEnabled: function(){
178         var parentWidget = this._getAncensterWidget(this);
179         if (parentWidget == null)
180             return true;
181         if (parentWidget && !parentWidget.isEnabled())
182             return false;
183 
184         return parentWidget._isAncestorsEnabled();
185     },
186 
187     _getAncensterWidget: function(node){
188         if (null == node)
189             return null;
190 
191         var parent = node.getParent();
192         if (null == parent)
193             return null;
194 
195         if (parent instanceof ccui.Widget)
196             return parent;
197         else
198             return this._getAncensterWidget(parent.getParent());
199     },
200 
201     _isAncestorsVisible: function(node){
202         if (null == node)
203             return true;
204 
205         var parent = node.getParent();
206 
207         if (parent && !parent.isVisible())
208             return false;
209         return this._isAncestorsVisible(parent);
210     },
211 
212     _cleanupWidget: function(){
213         //clean up _touchListener
214         this._eventDispatcher.removeEventListener(this._touchListener);
215 
216         //cleanup focused widget and focus navigation controller
217         if (this._focusedWidget == this){
218             //delete
219             this._focusedWidget = null;
220         }
221     },
222 
223     /**
224      * <p>
225      *     Sets whether the widget is enabled                                                                                    <br/>
226      *     true if the widget is enabled, widget may be touched , false if the widget is disabled, widget cannot be touched.     <br/>
227      *     The default value is true, a widget is default to enabled
228      * </p>
229      * @param {Boolean} enabled
230      */
231     setEnabled: function (enabled) {
232         this._enabled = enabled;
233     },
234 
235     /**
236      * initializes renderer of widget.
237      */
238     initRenderer: function () {
239     },
240 
241     /**
242      * add node for widget
243      * @param {cc.Node} node
244      * @param {Number} zOrder
245      * @param {Number} tag
246      */
247     addNode: function (node, zOrder, tag) {
248         if (node instanceof ccui.Widget) {
249             cc.log("Please use addChild to add a Widget.");
250             return;
251         }
252         cc.Node.prototype.addChild.call(this, node, zOrder, tag);
253         this._nodes.push(node);
254     },
255 
256     /**
257      * get node by tag
258      * @param {Number} tag
259      * @returns {cc.Node}
260      */
261     getNodeByTag: function (tag) {
262         var _nodes = this._nodes;
263         for (var i = 0; i < _nodes.length; i++) {
264             var node = _nodes[i];
265             if (node && node.getTag() == tag) {
266                 return node;
267             }
268         }
269         return null;
270     },
271 
272     /**
273      * get all node
274      * @returns {Array}
275      */
276     getNodes: function () {
277         return this._nodes;
278     },
279 
280     /**
281      * remove node
282      * @param {cc.Node} node
283      * @param {Boolean} cleanup
284      */
285     removeNode: function (node, cleanup) {
286         cc.Node.prototype.removeChild.call(this, node);
287         cc.arrayRemoveObject(this._nodes, node);
288     },
289 
290     /**
291      *  remove node by tag
292      * @param {Number} tag
293      * @param {Boolean} cleanup
294      */
295     removeNodeByTag: function (tag, cleanup) {
296         var node = this.getNodeByTag(tag);
297         if (!node) {
298             cc.log("cocos2d: removeNodeByTag(tag = %d): child not found!", tag);
299         }
300         else {
301             this.removeNode(node);
302         }
303     },
304 
305     /**
306      * remove all node
307      */
308     removeAllNodes: function () {
309         for (var i = 0; i < this._nodes.length; i++) {
310             var node = this._nodes[i];
311             cc.Node.prototype.removeChild.call(this, node);
312         }
313         this._nodes.length = 0;
314     },
315 
316     /**
317      * Changes the size that is widget's size
318      * @param {cc.Size} size  that is widget's size
319      */
320     setSize: function (size) {
321         var locW = this._customSize.width = size.width;
322         var locH = this._customSize.height = size.height;
323         if (this._ignoreSize) {
324             locW = this.width;
325             locH = this.height;
326         }
327         this._size.width = locW;
328         this._size.height = locH;
329 
330         if (this._running) {
331             var widgetParent = this.getWidgetParent();
332             if (widgetParent) {
333                 locW = widgetParent.width;
334                 locH = widgetParent.height;
335             } else {
336                 locW = this._parent.width;
337                 locH = this._parent.height;
338             }
339             this._sizePercent.x = locW > 0 ? this._customSize.width / locW : 0;
340             this._sizePercent.y = locH > 0 ? this._customSize.height / locH : 0;
341         }
342         this.onSizeChanged();
343     },
344     _setWidth: function (w) {
345         var locW = this._customSize.width = w;
346         this._ignoreSize && (locW = this.width);
347         this._size.width = locW;
348 
349         if (this._running) {
350             var widgetParent = this.getWidgetParent();
351             locW = widgetParent ? widgetParent.width : this._parent.width;
352             this._sizePercent.x = locW > 0 ? this._customSize.width / locW : 0;
353         }
354         this.onSizeChanged();
355     },
356     _setHeight: function (h) {
357         var locH = this._customSize.height = h;
358         this._ignoreSize && (locH = this.height);
359         this._size.height = locH;
360 
361         if (this._running) {
362             var widgetParent = this.getWidgetParent();
363             locH = widgetParent ? widgetParent.height : this._parent.height;
364             this._sizePercent.y = locH > 0 ? this._customSize.height / locH : 0;
365         }
366         this.onSizeChanged();
367     },
368 
369     /**
370      * Changes the percent that is widget's percent size
371      * @param {cc.Point} percent that is widget's percent size
372      */
373     setSizePercent: function (percent) {
374         this._sizePercent.x = percent.x;
375         this._sizePercent.y = percent.y;
376         var width = this._customSize.width, height = this._customSize.height;
377         if (this._running) {
378             var widgetParent = this.getWidgetParent();
379             if (widgetParent) {
380                 width = widgetParent.width * percent.x;
381                 height = widgetParent.height * percent.y;
382             }
383             else {
384                 width = this._parent.width * percent.x;
385                 height = this._parent.height * percent.y;
386             }
387         }
388         if (!this._ignoreSize) {
389             this._size.width = width;
390             this._size.height = height;
391         }
392         this._customSize.width = width;
393         this._customSize.height = height;
394         this.onSizeChanged();
395     },
396 
397     _setWidthPercent: function (percent) {
398         this._sizePercent.x = percent;
399         var width = this._customSize.width;
400         if (this._running) {
401             var widgetParent = this.getWidgetParent();
402             width = (widgetParent ? widgetParent.width : this._parent.width) * percent;
403         }
404         this._ignoreSize || (this._size.width = width);
405         this._customSize.width = width;
406         this.onSizeChanged();
407     },
408     _setHeightPercent: function (percent) {
409         this._sizePercent.y = percent;
410         var height = this._customSize.height;
411         if (this._running) {
412             var widgetParent = this.getWidgetParent();
413             height = (widgetParent ? widgetParent.height : this._parent.height) * percent;
414         }
415         this._ignoreSize || (this._size.height = height);
416         this._customSize.height = height;
417         this.onSizeChanged();
418     },
419 
420     /**
421      * update size and position
422      * @param {cc.Size} [parentSize] parent size
423      */
424     updateSizeAndPosition: function (parentSize) {
425         if(!parentSize){
426             var widgetParent = this.getWidgetParent();
427             if(widgetParent)
428                 parentSize = widgetParent.getLayoutSize();
429             else
430                 parentSize = this._parent.getContentSize();
431         }
432 
433         var locSize;
434         switch (this._sizeType) {
435             case ccui.Widget.SIZE_ABSOLUTE:
436                 locSize = this._ignoreSize? this.getContentSize():this._customSize;
437                 this._size.width = locSize.width;
438                 this._size.height = locSize.height;
439 
440                 var spx = 0, spy = 0;
441                 if (parentSize.width > 0) {
442                     spx = this._customSize.width / parentSize.width;
443                 }
444                 if (parentSize.height > 0) {
445                     spy = this._customSize.height / parentSize.height;
446                 }
447                 this._sizePercent.x = spx;
448                 this._sizePercent.y = spy;
449                 break;
450             case ccui.Widget.SIZE_PERCENT:
451                 var cSize = cc.size(parentSize.width * this._sizePercent.x , parentSize.height * this._sizePercent.y);
452                 locSize = this._ignoreSize? this.getVirtualRendererSize(): cSize;
453                 this._size.width = locSize.width;
454                 this._size.height = locSize.height;
455                 this._customSize.width = cSize.width;
456                 this._customSize.height = cSize.height;
457                 break;
458             default:
459                 break;
460         }
461         this.onSizeChanged();
462         var absPos = this.getPosition();
463         switch (this.positionType) {
464             case ccui.Widget.POSITION_ABSOLUTE:
465                 if (parentSize.width <= 0 || parentSize.height <= 0) {
466                     this._positionPercent.x = 0;
467                     this._positionPercent.y = 0;
468                 } else {
469                     this._positionPercent.x = absPos.x / parentSize.width;
470                     this._positionPercent.y = absPos.y / parentSize.height;
471                 }
472                 break;
473             case ccui.Widget.POSITION_PERCENT:
474                 absPos = cc.p(parentSize.width * this._positionPercent.x, parentSize.height * this._positionPercent.y);
475                 break;
476             default:
477                 break;
478         }
479         this.setPosition(absPos);
480     },
481 
482     /**TEXTURE_RES_TYPE
483      * Changes the size type of widget.
484      * @param {ccui.Widget.SIZE_ABSOLUTE|ccui.Widget.SIZE_PERCENT} type that is widget's size type
485      */
486     setSizeType: function (type) {
487         this._sizeType = type;
488     },
489 
490     /**
491      * Gets the size type of widget.
492      * @returns {ccui.Widget.SIZE_ABSOLUTE|ccui.Widget.SIZE_PERCENT} that is widget's size type
493      */
494     getSizeType: function () {
495         return this._sizeType;
496     },
497 
498     /**
499      * Ignore the widget size
500      * @param {Boolean} ignore true that widget will ignore it's size, use texture size, false otherwise. Default value is true.
501      */
502     ignoreContentAdaptWithSize: function (ignore) {
503         if(this._ignoreSize == ignore)
504             return;
505 
506         this._ignoreSize = ignore;
507         var locSize = this._ignoreSize ? this.getContentSize(): this._customSize;
508         this._size.width = locSize.width;
509         this._size.height = locSize.height;
510         this.onSizeChanged();
511     },
512 
513     /**
514      * Gets the widget if is ignore it's size.
515      * @returns {boolean}  true that widget will ignore it's size, use texture size, false otherwise.
516      */
517     isIgnoreContentAdaptWithSize: function () {
518         return this._ignoreSize;
519     },
520 
521     /**
522      * Returns size of widget
523      * @returns {cc.Size}
524      */
525     getSize: function () {
526         return cc.size(this._size);
527     },
528 
529     /**
530      * Get custom size of widget
531      * @returns {cc.Size}
532      */
533     getCustomSize: function () {
534         return cc.size(this._customSize);
535     },
536 
537     getLayoutSize: function(){
538         return cc.size(this._size);
539     },
540 
541     /**
542      * Returns size percent of widget
543      * @returns {cc.Point}
544      */
545     getSizePercent: function () {
546         return cc.p(this._sizePercent);
547     },
548     _getWidthPercent: function () {
549         return this._sizePercent.x;
550     },
551     _getHeightPercent: function () {
552         return this._sizePercent.y;
553     },
554 
555     /**
556      *  Gets world position of widget.
557      * @returns {cc.Point} world position of widget.
558      */
559     getWorldPosition: function () {
560         return this.convertToWorldSpace(cc.p(this._anchorPoint.x * this._contentSize.width, this._anchorPoint.y * this._contentSize.height));
561     },
562 
563     /**
564      * Gets the Virtual Renderer of widget.
565      * @returns {ccui.Widget}
566      */
567     getVirtualRenderer: function () {
568         return this;
569     },
570 
571     /**
572      * Gets the content size of widget.  Content size is widget's texture size.
573      */
574     getVirtualRendererSize:function(){
575         return cc.size(this._contentSize);
576     },
577 
578     /**
579      * call back function called when size changed.
580      */
581     onSizeChanged: function () {
582         this.setContentSize(this._size);
583         var locChildren =  this.getChildren();
584         for (var i = 0, len = locChildren.length; i < len; i++) {
585             var child = locChildren[i];
586             if(child instanceof ccui.Widget)
587                 child.updateSizeAndPosition();
588         }
589     },
590 
591     /**
592      * Gets the content size of widget.
593      * @returns {cc.Size}
594      */
595     getContentSize: function () {
596         return this._size;
597     },
598     _getWidth: function () {
599         return this._size.width;
600     },
601     _getHeight: function () {
602         return this._size.height;
603     },
604 
605     /**
606      * Sets whether the widget is touch enabled. The default value is false, a widget is default to touch disabled
607      * @param {Boolean} enable  true if the widget is touch enabled, false if the widget is touch disabled.
608      */
609     setTouchEnabled: function (enable) {
610         if (this._touchEnabled === enable)
611             return;
612 
613         this._touchEnabled = enable;
614         if (this._touchEnabled) {
615             this._touchListener = cc.EventListener.create({
616                 event: cc.EventListener.TOUCH_ONE_BY_ONE,
617                 swallowTouches: true,
618                 onTouchBegan: this.onTouchBegan.bind(this),
619                 onTouchMoved: this.onTouchMoved.bind(this),
620                 onTouchEnded: this.onTouchEnded.bind(this)
621             });
622             cc.eventManager.addListener(this._touchListener, this);
623         } else {
624             cc.eventManager.removeListener(this._touchListener);
625         }
626     },
627 
628     /**
629      * To set the bright style of widget.
630      * @returns {boolean} true if the widget is touch enabled, false if the widget is touch disabled.
631      */
632     isTouchEnabled: function () {
633         return this._touchEnabled;
634     },
635 
636     /**
637      * Determines if the widget is highlighted
638      * @returns {boolean} true if the widget is highlighted, false if the widget is not highlighted .
639      */
640     isHighlighted: function(){
641         return this._highlight;
642     },
643 
644     /**
645      * Sets whether the widget is highlighted. The default value is false, a widget is default to not highlighted
646      * @param highlight true if the widget is highlighted, false if the widget is not highlighted.
647      */
648     setHighlighted:function(highlight){
649         if (highlight == this._highlight)
650             return;
651         this._highlight = highlight;
652         if (this._bright) {
653             if (this._highlight)
654                 this.setBrightStyle(ccui.Widget.BRIGHT_STYLE_HIGH_LIGHT);
655             else
656                 this.setBrightStyle(ccui.Widget.BRIGHT_STYLE_NORMAL);
657         } else
658             this.onPressStateChangedToDisabled();
659     },
660 
661     /**
662      * Schedules the "update" method.
663      * @param enable
664      */
665     setUpdateEnabled: function (enable) {
666         if (this._updateEnabled == enable) {
667             return;
668         }
669         this._updateEnabled = enable;
670         if (enable) {
671             this.scheduleUpdate();
672         }
673         else {
674             this.unscheduleUpdate();
675         }
676     },
677 
678     /**
679      * is the "update" method scheduled.
680      * @returns {boolean}
681      */
682     isUpdateEnabled: function () {
683         return this._updateEnabled;
684     },
685 
686     /**
687      * Determines if the widget is on focused
688      * @returns {boolean} whether the widget is focused or not
689      */
690     isFocused: function () {
691         return this._focused;
692     },
693 
694     /**
695      * Sets whether the widget is on focused
696      * The default value is false, a widget is default to not on focused
697      * @param {boolean} focus  pass true to let the widget get focus or pass false to let the widget lose focus
698      */
699     setFocused: function (focus) {
700         this._focused = focus;
701         //make sure there is only one focusedWidget
702         if (focus) {
703             this._focusedWidget = this;
704         }
705     },
706 
707     /**
708      * returns whether the widget could accept focus.
709      * @returns {boolean} true represent the widget could accept focus, false represent the widget couldn't accept focus
710      */
711     isFocusEnabled: function(){
712         return this._focusEnabled;
713     },
714 
715     /**
716      * sets whether the widget could accept focus.
717      * @param {Boolean} enable true represent the widget could accept focus, false represent the widget couldn't accept focus
718      */
719     setFocusEnabled: function(enable){
720         this._focused = enable;
721     },
722 
723     /**
724      * <p>
725      *     When a widget is in a layout, you could call this method to get the next focused widget within a specified direction. <br/>
726      *     If the widget is not in a layout, it will return itself
727      * </p>
728      * @param direction the direction to look for the next focused widget in a layout
729      * @param current  the current focused widget
730      * @return  the next focused widget in a layout
731      */
732     findNextFocusedWidget: function( direction, current){
733         if (null == this.onNextFocusedWidget || null == this.onNextFocusedWidget(direction) ) {
734             var isLayout = current instanceof ccui.Layout;
735             if (this.isFocused() || isLayout) {
736                 var layout = this.getParent();
737                 if (null == layout){
738                     //the outer layout's default behaviour is : loop focus
739                     if (isLayout)
740                         return current.findNextFocusedWidget(direction, current);
741                     return current;
742                 } else {
743                     return layout.findNextFocusedWidget(direction, current);
744                 }
745             } else
746                 return current;
747         } else {
748             var getFocusWidget = this.onNextFocusedWidget(direction);
749             this.dispatchFocusEvent(this, getFocusWidget);
750             return getFocusWidget;
751         }
752     },
753 
754     /**
755      * when a widget calls this method, it will get focus immediately.
756      */
757     requestFocus: function(){
758         if (this == this._focusedWidget)
759             return;
760         this.dispatchFocusEvent(this._focusedWidget, this);
761     },
762 
763     /**
764      * no matter what widget object you call this method on , it will return you the exact one focused widget
765      */
766     getCurrentFocusedWidget: function(){
767         return this._focusedWidget;
768     },
769 
770     /**
771      * call this method with parameter true to enable the Android Dpad focus navigation feature
772      * @note it doesn't implemented on Web
773      * @param {Boolean} enable set true to enable dpad focus navigation, otherwise disable dpad focus navigation
774      */
775     enableDpadNavigation: function(enable){
776         //
777         /*if (enable) {
778             if (nullptr == _focusNavigationController)
779             {
780                 _focusNavigationController = new FocusNavigationController;
781                 if (_focusedWidget) {
782                     _focusNavigationController.setFirstFocsuedWidget(_focusedWidget);
783                 }
784             }
785         }
786         else
787         {
788             CC_SAFE_DELETE(_focusNavigationController);
789         }
790         _focusNavigationController.enableFocusNavigation(enable);*/
791     },
792 
793     /**
794      * <p>
795      *    When a widget lose/get focus, this method will be called. Be Caution when you provide your own version,       <br/>
796      *    you must call widget.setFocused(true/false) to change the focus state of the current focused widget;
797      * </p>
798      */
799     onFocusChanged: null,
800 
801     /**
802      * use this function to manually specify the next focused widget regards to each direction
803      */
804     onNextFocusedWidget: null,
805 
806     /**
807      * Sends the touch event to widget's parent
808      * @param {Number}  eventType
809      * @param {ccui.Widget} sender
810      * @param {cc.Touch} touch
811      */
812     interceptTouchEvent: function(eventType, sender, touch){
813         var widgetParent = this.getWidgetParent();
814         if (widgetParent)
815             widgetParent.interceptTouchEvent(eventType,sender,touch);
816     },
817 
818     /**
819      * This method is called when a focus change event happens
820      * @param {ccui.Widget} widgetLostFocus
821      * @param {ccui.Widget} widgetGetFocus
822      */
823     onFocusChange: function(widgetLostFocus, widgetGetFocus){
824         //only change focus when there is indeed a get&lose happens
825         if (widgetLostFocus)
826             widgetLostFocus.setFocused(false);
827 
828         if (widgetGetFocus)
829             widgetGetFocus.setFocused(true);
830     },
831 
832     /**
833      * Dispatch a EventFocus through a EventDispatcher
834      * @param {ccui.Widget} widgetLostFocus
835      * @param {ccui.Widget} widgetGetFocus
836      */
837     dispatchFocusEvent: function(widgetLostFocus, widgetGetFocus){
838         //if the widgetLoseFocus doesn't get focus, it will use the previous focused widget instead
839         if (widgetLostFocus && !widgetLostFocus.isFocused())
840             widgetLostFocus = this._focusedWidget;
841 
842         if (widgetGetFocus != widgetLostFocus){
843             if (widgetGetFocus && widgetGetFocus.onFocusChanged)
844                 widgetGetFocus.onFocusChanged(widgetLostFocus, widgetGetFocus);
845 
846             if (widgetLostFocus && widgetGetFocus.onFocusChanged)
847                 widgetLostFocus.onFocusChanged(widgetLostFocus, widgetGetFocus);
848 
849             cc.eventManager.dispatchEvent(new cc.EventFocus(widgetLostFocus, widgetGetFocus));
850         }
851     },
852 
853     /**
854      *  Sets whether the widget is bright. The default value is true, a widget is default to bright
855      * @param {Boolean} bright true if the widget is bright, false if the widget is dark.
856      */
857     setBright: function (bright) {
858         this._bright = bright;
859         if (this._bright) {
860             this._brightStyle = ccui.Widget.BRIGHT_STYLE_NONE;
861             this.setBrightStyle(ccui.Widget.BRIGHT_STYLE_NORMAL);
862         } else {
863             this.onPressStateChangedToDisabled();
864         }
865     },
866 
867     /**
868      * To set the bright style of widget.
869      * @param {Number} style BRIGHT_NORMAL the widget is normal state, BRIGHT_HIGHLIGHT the widget is height light state.
870      */
871     setBrightStyle: function (style) {
872         if (this._brightStyle == style) {
873             return;
874         }
875         style = style || ccui.Widget.BRIGHT_STYLE_NORMAL;
876         this._brightStyle = style;
877         switch (this._brightStyle) {
878             case ccui.Widget.BRIGHT_STYLE_NORMAL:
879                 this.onPressStateChangedToNormal();
880                 break;
881             case ccui.Widget.BRIGHT_STYLE_HIGH_LIGHT:
882                 this.onPressStateChangedToPressed();
883                 break;
884             default:
885                 break;
886         }
887     },
888 
889     /**
890      * call back function called widget's state changed to normal.
891      */
892     onPressStateChangedToNormal: function () {
893     },
894 
895     /**
896      * call back function called widget's state changed to selected.
897      */
898     onPressStateChangedToPressed: function () {
899     },
900 
901     /**
902      * call back function called widget's state changed to dark.
903      */
904     onPressStateChangedToDisabled: function () {
905     },
906 
907     /**
908      * A call back function when widget lost of focus.
909      */
910     didNotSelectSelf: function () {
911     },
912 
913     onTouchBegan: function (touch, event) {
914         this._hitted = false;
915         if (this.isVisible() && this.isEnabled() && this._isAncestorsEnabled() && this._isAncestorsVisible(this) ){
916             var touchPoint = touch.getLocation();
917             this._touchBeganPosition.x = touchPoint.x;
918             this._touchBeganPosition.y = touchPoint.y;
919             if(this.hitTest(this._touchBeganPosition) && this.isClippingParentContainsPoint(this._touchBeganPosition))
920                 this._hitted = true;
921         }
922         if (!this._hitted) {
923             return false;
924         }
925         this.setHighlighted(true);
926         var widgetParent = this.getWidgetParent();
927         if (widgetParent) {
928             widgetParent.interceptTouchEvent(ccui.Widget.TOUCH_BAGAN, this, touch);
929         }
930         this.pushDownEvent();
931         return true;
932     },
933 
934     onTouchMoved: function (touch, event) {
935         var touchPoint = touch.getLocation();
936         this._touchMovePosition.x = touchPoint.x;
937         this._touchMovePosition.y = touchPoint.y;
938         this.setHighlighted(this.hitTest(touchPoint));
939         var widgetParent = this.getWidgetParent();
940         if (widgetParent)
941             widgetParent.interceptTouchEvent(ccui.Widget.TOUCH_MOVED, this, touch);
942         this.moveEvent();
943     },
944 
945     onTouchEnded: function (touch, event) {
946         var touchPoint = touch.getLocation();
947         this._touchEndPosition.x = touchPoint.x;
948         this._touchEndPosition.y = touchPoint.y;
949         var widgetParent = this.getWidgetParent();
950         if (widgetParent)
951             widgetParent.interceptTouchEvent(ccui.Widget.TOUCH_ENDED, this, touch);
952         var highlight = this._highlight;
953         this.setHighlighted(false);
954         if (highlight)
955             this.releaseUpEvent();
956         else
957             this.cancelUpEvent();
958     },
959 
960     /**
961      * A call back function called when widget is selected, and on touch canceled.
962      * @param {cc.Point} touchPoint
963      */
964     onTouchCancelled: function (touchPoint) {
965         this.setHighlighted(false);
966         this.cancelUpEvent();
967     },
968 
969     /**
970      * A call back function called when widget is selected, and on touch long clicked.
971      * @param {cc.Point} touchPoint
972      */
973     onTouchLongClicked: function (touchPoint) {
974         this.longClickEvent();
975     },
976 
977     //call back function called widget's state changed to dark.
978     pushDownEvent: function () {
979         if (this._touchEventCallback)
980             this._touchEventCallback(this, ccui.Widget.TOUCH_BAGAN);
981 
982         if (this._touchEventListener && this._touchEventSelector) {
983             this._touchEventSelector.call(this._touchEventListener, this, ccui.Widget.TOUCH_BEGAN);
984         }
985     },
986 
987     moveEvent: function () {
988         if (this._touchEventCallback)
989             this._touchEventCallback(this, ccui.Widget.TOUCH_MOVED);
990 
991         if (this._touchEventListener && this._touchEventSelector) {
992             this._touchEventSelector.call(this._touchEventListener, this, ccui.Widget.TOUCH_MOVED);
993         }
994     },
995 
996     releaseUpEvent: function () {
997         if (this._touchEventCallback)
998             this._touchEventCallback(this, ccui.Widget.TOUCH_ENDED);
999 
1000         if (this._touchEventListener && this._touchEventSelector) {
1001             this._touchEventSelector.call(this._touchEventListener, this, ccui.Widget.TOUCH_ENDED);
1002         }
1003     },
1004 
1005     cancelUpEvent: function () {
1006         if (this._touchEventCallback)
1007             this._touchEventCallback(this, ccui.Widget.TOUCH_CANCELED);
1008 
1009         if (this._touchEventListener && this._touchEventSelector) {
1010             this._touchEventSelector.call(this._touchEventListener, this, ccui.Widget.TOUCH_CANCELED);
1011         }
1012     },
1013 
1014     longClickEvent: function () {
1015 
1016     },
1017 
1018     /**
1019      * Sets the touch event target/selector of the menu item
1020      * @param {Function} selector
1021      * @param {Object} target
1022      */
1023     addTouchEventListener: function (selector, target) {
1024         if(target === undefined)
1025             this._touchEventCallback = selector;
1026         else {
1027             this._touchEventSelector = selector;
1028             this._touchEventListener = target;
1029         }
1030     },
1031 
1032     /**
1033      * Checks a point if is in widget's space
1034      * @param {cc.Point} pt
1035      * @returns {boolean} true if the point is in widget's space, false otherwise.
1036      */
1037     hitTest: function (pt) {
1038         //TODO need test
1039 /*        var bb = cc.rect(-this._size.width * this._anchorPoint.x, -this._size.height * this._anchorPoint.y, this._size.width, this._size.height);
1040         return (nsp.x >= bb.x && nsp.x <= bb.x + bb.width && nsp.y >= bb.y && nsp.y <= bb.y + bb.height);*/
1041         var bb = cc.rect(0,0, this._contentSize.width, this._contentSize.height);
1042         return cc.rectContainsPoint(bb, this.convertToNodeSpace(pt));
1043     },
1044 
1045     isClippingParentContainsPoint: function(pt){
1046         this._affectByClipping = false;
1047         var parent = this.getParent();
1048         var clippingParent = null;
1049         while (parent) {
1050             if (parent instanceof ccui.Layout) {
1051                 if (parent.isClippingEnabled()) {
1052                     this._affectByClipping = true;
1053                     clippingParent = parent;
1054                     break;
1055                 }
1056             }
1057             parent = parent.getParent();
1058         }
1059 
1060         if (!this._affectByClipping)
1061             return true;
1062 
1063         if (clippingParent) {
1064             if (clippingParent.hitTest(pt))
1065                 return clippingParent.isClippingParentContainsPoint(pt);
1066             return false;
1067         }
1068         return true;
1069     },
1070 
1071     /**
1072      * Checks a point if in parent's area.
1073      * @deprecated
1074      * @param {cc.Point} pt
1075      * @returns {Boolean}
1076      */
1077     clippingParentAreaContainPoint: function (pt) {
1078         cc.log("clippingParentAreaContainPoint is deprecated. Please use isClippingParentContainsPoint instead.");
1079         this.isClippingParentContainsPoint(pt);
1080     },
1081 
1082     /**
1083      * Sends the touch event to widget's parent
1084      * @param {number} handleState
1085      * @param {ccui.Widget} sender
1086      * @param {cc.Point} touchPoint
1087      */
1088     checkChildInfo: function (handleState, sender, touchPoint) {
1089         var widgetParent = this.getWidgetParent();
1090         if (widgetParent) {
1091             widgetParent.checkChildInfo(handleState, sender, touchPoint);
1092         }
1093     },
1094 
1095     /**
1096      * Changes the position (x,y) of the widget .
1097      * The original point (0,0) is at the left-bottom corner of screen.
1098      * @param {cc.Point||Number} pos
1099      * @param {Number} [posY]
1100      */
1101     setPosition: function (pos, posY) {
1102         if (this._running) {
1103             var widgetParent = this.getWidgetParent();
1104             if (widgetParent) {
1105                 var pSize = widgetParent.getSize();
1106                 if (pSize.width <= 0 || pSize.height <= 0) {
1107                     this._positionPercent.x = 0;
1108                     this._positionPercent.y = 0;
1109                 } else {
1110                     if (posY) {
1111                         this._positionPercent.x = pos / pSize.width;
1112                         this._positionPercent.y = posY / pSize.height;
1113                     } else {
1114                         this._positionPercent.x = pos.x / pSize.width;
1115                         this._positionPercent.y = pos.y / pSize.height;
1116                     }
1117                 }
1118             }
1119         }
1120 
1121         cc.Node.prototype.setPosition.call(this, pos, posY);
1122     },
1123 
1124     setPositionX: function (x) {
1125         if (this._running) {
1126             var widgetParent = this.getWidgetParent();
1127             if (widgetParent) {
1128                 var pw = widgetParent.width;
1129                 if (pw <= 0)
1130                     this._positionPercent.x = 0;
1131                 else
1132                     this._positionPercent.x = x / pw;
1133             }
1134         }
1135 
1136         cc.Node.prototype.setPositionX.call(this, x);
1137     },
1138     setPositionY: function (y) {
1139         if (this._running) {
1140             var widgetParent = this.getWidgetParent();
1141             if (widgetParent) {
1142                 var ph = widgetParent.height;
1143                 if (ph <= 0)
1144                     this._positionPercent.y = 0;
1145                 else
1146                     this._positionPercent.y = y / ph;
1147             }
1148         }
1149 
1150         cc.Node.prototype.setPositionY.call(this, y);
1151     },
1152 
1153     /**
1154      * Changes the position (x,y) of the widget
1155      * @param {cc.Point} percent
1156      */
1157     setPositionPercent: function (percent) {
1158         this._positionPercent = percent;
1159         if (this._running) {
1160             var widgetParent = this.getWidgetParent();
1161             if (widgetParent) {
1162                 var parentSize = widgetParent.getSize();
1163                 this.setPosition(parentSize.width * this._positionPercent.x, parentSize.height * this._positionPercent.y);
1164             }
1165         }
1166     },
1167     _setXPercent: function (percent) {
1168         this._positionPercent.x = percent;
1169         if (this._running) {
1170             var widgetParent = this.getWidgetParent();
1171             if (widgetParent)
1172                 this.setPositionX(widgetParent.width * percent);
1173         }
1174     },
1175     _setYPercent: function (percent) {
1176         this._positionPercent.y = percent;
1177         if (this._running) {
1178             var widgetParent = this.getWidgetParent();
1179             if (widgetParent)
1180                 this.setPositionY(widgetParent.height * percent);
1181         }
1182     },
1183 
1184     updateAnchorPoint: function () {
1185         this.setAnchorPoint(this.getAnchorPoint());
1186     },
1187 
1188     /**
1189      * Gets the percent (x,y) of the widget
1190      * @returns {cc.Point} The percent (x,y) of the widget in OpenGL coordinates
1191      */
1192     getPositionPercent: function () {
1193         return cc.p(this._positionPercent);
1194     },
1195 
1196     _getXPercent: function () {
1197         return this._positionPercent.x;
1198     },
1199     _getYPercent: function () {
1200         return this._positionPercent.y;
1201     },
1202 
1203     /**
1204      * Changes the position type of the widget
1205      * @param {Number} type  the position type of widget
1206      */
1207     setPositionType: function (type) {
1208         this.positionType = type;
1209     },
1210 
1211     /**
1212      * Gets the position type of the widget
1213      * @returns {Number} the position type of widget
1214      */
1215     getPositionType: function () {
1216         return this.positionType;
1217     },
1218 
1219     /**
1220      * Sets whether the widget should be flipped horizontally or not.
1221      * @param {Boolean} flipX true if the widget should be flipped horizontally, false otherwise.
1222      */
1223     setFlippedX: function (flipX) {
1224         this._flippedX = flipX;
1225         this.updateFlippedX();
1226     },
1227 
1228     /**
1229      * <p>
1230      *   Returns the flag which indicates whether the widget is flipped horizontally or not.             <br/>
1231      *   It only flips the texture of the widget, and not the texture of the widget's children.          <br/>
1232      *   Also, flipping the texture doesn't alter the anchorPoint.                                       <br/>
1233      *   If you want to flip the anchorPoint too, and/or to flip the children too use:                   <br/>
1234      *   widget.setScaleX(sprite.getScaleX() * -1);
1235      * </p>
1236      * @returns {Boolean} true if the widget is flipped horizontally, false otherwise.
1237      */
1238     isFlippedX: function () {
1239         return this._flippedX;
1240     },
1241 
1242     /**
1243      * Sets whether the widget should be flipped vertically or not.
1244      * @param {Boolean} flipY  true if the widget should be flipped vertically, false otherwise.
1245      */
1246     setFlippedY: function (flipY) {
1247         this._flippedY = flipY;
1248         this.updateFlippedY();
1249     },
1250 
1251     /**
1252      * <p>
1253      *     Return the flag which indicates whether the widget is flipped vertically or not.                <br/>
1254      *     It only flips the texture of the widget, and not the texture of the widget's children.          <br/>
1255      *     Also, flipping the texture doesn't alter the anchorPoint.                                       <br/>
1256      *     If you want to flip the anchorPoint too, and/or to flip the children too use:                   <br/>
1257      *     widget.setScaleY(widget.getScaleY() * -1);
1258      * </p>
1259      * @returns {Boolean} true if the widget is flipped vertically, false otherwise.
1260      */
1261     isFlippedY: function () {
1262         return this._flippedY;
1263     },
1264 
1265     updateFlippedX: function () {
1266 
1267     },
1268 
1269     updateFlippedY: function () {
1270 
1271     },
1272 
1273     adaptRenderers: function(){
1274 
1275     },
1276 
1277     /**
1278      * Determines if the widget is bright
1279      * @returns {boolean} true if the widget is bright, false if the widget is dark.
1280      */
1281     isBright: function () {
1282         return this._bright;
1283     },
1284 
1285     /**
1286      * Determines if the widget is enabled
1287      * @returns {boolean}
1288      */
1289     isEnabled: function () {
1290         return this._enabled;
1291     },
1292 
1293     /**
1294      * Gets the left boundary position of this widget.
1295      * @returns {number}
1296      */
1297     getLeftBoundary: function () {
1298         return this.getPositionX() - this._getAnchorX() * this._size.width;
1299     },
1300 
1301     /**
1302      * Gets the bottom boundary position of this widget.
1303      * @returns {number}
1304      */
1305     getBottomBoundary: function () {
1306         return this.getPositionY() - this._getAnchorY() * this._size.height;
1307     },
1308 
1309     /**
1310      * Gets the right boundary position of this widget.
1311      * @returns {number}
1312      */
1313     getRightBoundary: function () {
1314         return this.getLeftBoundary() + this._size.width;
1315     },
1316 
1317     /**
1318      * Gets the top boundary position of this widget.
1319      * @returns {number}
1320      */
1321     getTopBoundary: function () {
1322         return this.getBottomBoundary() + this._size.height;
1323     },
1324 
1325     /**
1326      * Gets the touch began point of widget when widget is selected.
1327      * @returns {cc.Point} the touch began point.
1328      */
1329     getTouchStartPos: function () {
1330         cc.log("getTouchStartPos is deprecated. Please use getTouchBeganPosition instead.");
1331         return this.getTouchBeganPosition();
1332     },
1333 
1334     getTouchBeganPosition: function(){
1335          return cc.p(this._touchBeganPosition);
1336     },
1337 
1338     /**
1339      *Gets the touch move point of widget when widget is selected.
1340      * @returns {cc.Point} the touch move point.
1341      */
1342     getTouchMovePos: function () {
1343         cc.log("getTouchMovePos is deprecated. Please use getTouchMovePosition instead.");
1344         return this.getTouchMovePosition();
1345     },
1346 
1347     getTouchMovePosition: function(){
1348         return cc.p(this._touchMovePosition);
1349     },
1350 
1351     /**
1352      * Gets the touch end point of widget when widget is selected.
1353      * @returns {cc.Point} the touch end point.
1354      */
1355     getTouchEndPos: function () {
1356         cc.log("getTouchEndPos is deprecated. Please use getTouchEndPosition instead.");
1357         return this.getTouchEndPosition();
1358     },
1359 
1360     getTouchEndPosition:function(){
1361         return cc.p(this._touchEndPosition);
1362     },
1363 
1364     /**
1365      * Sets the name of widget
1366      * @param {String} name
1367      */
1368     setName: function (name) {
1369         this._name = name;
1370     },
1371 
1372     /**
1373      * Gets the name of widget
1374      * @returns {string}
1375      */
1376     getName: function () {
1377         return this._name;
1378     },
1379 
1380     /**
1381      * get widget type
1382      * @returns {ccui.Widget.TYPE_WIDGET|ccui.Widget.TYPE_CONTAINER}
1383      */
1384     getWidgetType: function () {
1385         return this._widgetType;
1386     },
1387 
1388     /**
1389      * Gets LayoutParameter of widget.
1390      * @param {ccui.LayoutParameter} parameter
1391      */
1392     setLayoutParameter: function (parameter) {
1393         if(!parameter)
1394             return;
1395         this._layoutParameterDictionary[parameter.getLayoutType()] = parameter;
1396         this._layoutParameterType = parameter.getLayoutType();
1397     },
1398 
1399     /**
1400      * Gets layout parameter
1401      * @param {ccui.LayoutParameter.NONE|ccui.LayoutParameter.LINEAR|ccui.LayoutParameter.RELATIVE} type
1402      * @returns {ccui.LayoutParameter}
1403      */
1404     getLayoutParameter: function (type) {
1405         type = type || this._layoutParameterType;
1406         return this._layoutParameterDictionary[type];
1407     },
1408 
1409     /**
1410      * Returns the "class name" of widget.
1411      * @returns {string}
1412      */
1413     getDescription: function () {
1414         return "Widget";
1415     },
1416 
1417     clone: function () {
1418         var clonedWidget = this.createCloneInstance();
1419         clonedWidget.copyProperties(this);
1420         clonedWidget.copyClonedWidgetChildren(this);
1421         return clonedWidget;
1422     },
1423 
1424     createCloneInstance: function () {
1425         return ccui.Widget.create();
1426     },
1427 
1428     copyClonedWidgetChildren: function (model) {
1429         var widgetChildren = model.getChildren();
1430         for (var i = 0; i < widgetChildren.length; i++) {
1431             var locChild = widgetChildren[i];
1432             if (locChild instanceof ccui.Widget) {
1433                 this.addChild(locChild.clone());
1434             }
1435         }
1436     },
1437 
1438     copySpecialProperties: function (model) {
1439 
1440     },
1441 
1442     copyProperties: function (widget) {
1443         this.setEnabled(widget.isEnabled());
1444         this.setVisible(widget.isVisible());
1445         this.setBright(widget.isBright());
1446         this.setTouchEnabled(widget.isTouchEnabled());
1447         this.setLocalZOrder(widget.getLocalZOrder());
1448         this.setUpdateEnabled(widget.isUpdateEnabled());
1449         this.setTag(widget.getTag());
1450         this.setName(widget.getName());
1451         this.setActionTag(widget.getActionTag());
1452 
1453         this._ignoreSize.width = widget._ignoreSize.width;
1454         this._ignoreSize.height = widget._ignoreSize.height;
1455         this._size.width = widget._size.width;
1456         this._size.height = widget._size.height;
1457         this._customSize.width = widget._customSize.width;
1458         this._customSize.height = widget._customSize.height;
1459 
1460         this.copySpecialProperties(widget);
1461         this._sizeType = widget.getSizeType();
1462         this._sizePercent.x = widget._sizePercent.x;
1463         this._sizePercent.y = widget._sizePercent.y;
1464 
1465         this.positionType = widget.positionType;
1466         this._positionPercent.x = widget._positionPercent.x;
1467         this._positionPercent.y = widget._positionPercent.y;
1468 
1469         this.setPosition(widget.getPosition());
1470         this.setAnchorPoint(widget.getAnchorPoint());
1471         this.setScaleX(widget.getScaleX());
1472         this.setScaleY(widget.getScaleY());
1473         this.setRotation(widget.getRotation());
1474         this.setRotationX(widget.getRotationX());
1475         this.setRotationY(widget.getRotationY());
1476         this.setFlippedX(widget.isFlippedX());
1477         this.setFlippedY(widget.isFlippedY());
1478         this.setColor(widget.getColor());
1479         this.setOpacity(widget.getOpacity());
1480 
1481         this._touchEventCallback = widget._touchEventCallback;
1482         this._touchEventListener = widget._touchEventListener;
1483         this._touchEventSelector = widget._touchEventSelector;
1484         this._focused = widget._focused;
1485         this._focusEnabled = widget._focusEnabled;
1486 
1487         for (var key in widget._layoutParameterDictionary) {
1488             var parameter = widget._layoutParameterDictionary[key];
1489             if (parameter)
1490                 this.setLayoutParameter(parameter.clone());
1491         }
1492         this.onSizeChanged();
1493     },
1494 
1495     /*temp action*/
1496     setActionTag: function (tag) {
1497         this._actionTag = tag;
1498     },
1499 
1500     getActionTag: function () {
1501         return this._actionTag;
1502     },
1503 
1504     /**
1505      * Get color
1506      * @returns {cc.Color}
1507      */
1508     getColor: function () {
1509         return cc.color(this._color.r, this._color.g, this._color.b, this._color.a);
1510     },
1511 
1512     /**
1513      * Set opacity
1514      * @param {Number} opacity
1515      */
1516     setOpacity: function (opacity) {
1517         if(opacity === this._color.a) return;
1518         this._color.a = opacity;
1519         this.updateTextureOpacity(opacity);
1520     },
1521 
1522     /**
1523      * Get opacity
1524      * @returns {Number}
1525      */
1526     getOpacity: function () {
1527         //return this._color.a;   //TODO
1528         return this._displayedOpacity;
1529     },
1530 
1531     updateTextureOpacity: function (opacity) {
1532         for(var p in this._children){
1533             var item = this._children[p];
1534             if(item && item.RGBAProtocol)
1535                 item.setOpacity(opacity);
1536         }
1537     },
1538 
1539 
1540     updateColorToRenderer: function (renderer) {
1541         if (renderer.RGBAProtocol) {
1542             renderer.setColor(this._color);
1543         }
1544     },
1545 
1546     updateOpacityToRenderer: function (renderer) {
1547         if (renderer.RGBAProtocol) {
1548             renderer.setOpacity(this._color.a);
1549         }
1550     },
1551 
1552     updateRGBAToRenderer: function(renderer){
1553         renderer.setColor(this._color);
1554         renderer.setOpacity(this._opacity);
1555     }
1556 });
1557 
1558 var _p = ccui.Widget.prototype;
1559 
1560 // Extended properties
1561 /** @expose */
1562 _p.xPercent;
1563 cc.defineGetterSetter(_p, "xPercent", _p._getXPercent, _p._setXPercent);
1564 /** @expose */
1565 _p.yPercent;
1566 cc.defineGetterSetter(_p, "yPercent", _p._getYPercent, _p._setYPercent);
1567 /** @expose */
1568 _p.widthPercent;
1569 cc.defineGetterSetter(_p, "widthPercent", _p._getWidthPercent, _p._setWidthPercent);
1570 /** @expose */
1571 _p.heightPercent;
1572 cc.defineGetterSetter(_p, "heightPercent", _p._getHeightPercent, _p._setHeightPercent);
1573 /** @expose */
1574 _p.widgetParent;
1575 cc.defineGetterSetter(_p, "widgetParent", _p.getWidgetParent);
1576 /** @expose */
1577 _p.enabled;
1578 cc.defineGetterSetter(_p, "enabled", _p.isEnabled, _p.setEnabled);
1579 /** @expose */
1580 _p.focused;
1581 cc.defineGetterSetter(_p, "focused", _p.isFocused, _p.setFocused);
1582 /** @expose */
1583 _p.sizeType;
1584 cc.defineGetterSetter(_p, "sizeType", _p.getSizeType, _p.setSizeType);
1585 /** @expose */
1586 _p.widgetType;
1587 cc.defineGetterSetter(_p, "widgetType", _p.getWidgetType);
1588 /** @expose */
1589 _p.touchEnabled;
1590 cc.defineGetterSetter(_p, "touchEnabled", _p.isTouchEnabled, _p.setTouchEnabled);
1591 /** @expose */
1592 _p.updateEnabled;
1593 cc.defineGetterSetter(_p, "updateEnabled", _p.isUpdateEnabled, _p.setUpdateEnabled);
1594 /** @expose */
1595 _p.bright;
1596 cc.defineGetterSetter(_p, "bright", _p.isBright, _p.setBright);
1597 /** @expose */
1598 _p.name;
1599 cc.defineGetterSetter(_p, "name", _p.getName, _p.setName);
1600 /** @expose */
1601 _p.actionTag;
1602 cc.defineGetterSetter(_p, "actionTag", _p.getActionTag, _p.setActionTag);
1603 /** @expose */
1604 _p.opacity;
1605 cc.defineGetterSetter(_p, "opacity", _p.getOpacity, _p.setOpacity);
1606 
1607 _p = null;
1608 
1609 /**
1610  * allocates and initializes a UIWidget.
1611  * @constructs
1612  * @return {ccui.Widget}
1613  * @example
1614  * // example
1615  * var uiWidget = ccui.Widget.create();
1616  */
1617 ccui.Widget.create = function () {
1618     return new ccui.Widget();
1619 };
1620 
1621 
1622 // Constants
1623 //bright style
1624 ccui.Widget.BRIGHT_STYLE_NONE = -1;
1625 ccui.Widget.BRIGHT_STYLE_NORMAL = 0;
1626 ccui.Widget.BRIGHT_STYLE_HIGH_LIGHT = 1;
1627 
1628 //widget type
1629 ccui.Widget.TYPE_WIDGET = 0;
1630 ccui.Widget.TYPE_CONTAINER = 1;
1631 
1632 //Focus Direction
1633 ccui.Widget.LEFT = 0;
1634 ccui.Widget.RIGHT = 1;
1635 ccui.Widget.UP = 0;
1636 ccui.Widget.DOWN = 1;
1637 
1638 //texture resource type
1639 ccui.Widget.LOCAL_TEXTURE = 0;
1640 ccui.Widget.PLIST_TEXTURE = 1;
1641 
1642 //touch event type            //TODO why don't use a common define ?
1643 ccui.Widget.TOUCH_BEGAN = 0;
1644 ccui.Widget.TOUCH_MOVED = 1;
1645 ccui.Widget.TOUCH_ENDED = 2;
1646 ccui.Widget.TOUCH_CANCELED = 3;
1647 
1648 //size type
1649 ccui.Widget.SIZE_ABSOLUTE = 0;
1650 ccui.Widget.SIZE_PERCENT = 1;
1651 
1652 //position type
1653 ccui.Widget.POSITION_ABSOLUTE = 0;
1654 ccui.Widget.POSITION_PERCENT = 1;
1655 
1656 cc.EventFocus = cc.Event.extend({
1657     _widgetGetFocus: null,
1658     _widgetLoseFocus: null,
1659     ctor: function(widgetLoseFocus, widgetGetFocus){
1660         this._widgetGetFocus = widgetGetFocus;
1661         this._widgetLoseFocus = widgetLoseFocus;
1662     }
1663 });