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  * The button controls of Cocos UI.
 28  * @class
 29  * @extends ccui.Widget
 30  *
 31  * @property {String}   titleText               - The content string of the button title
 32  * @property {String}   titleFont               - The content string font of the button title
 33  * @property {Number}   titleFontSize           - The content string font size of the button title
 34  * @property {String}   titleFontName           - The content string font name of the button title
 35  * @property {cc.Color} titleFontColor          - The content string font color of the button title
 36  * @property {Boolean}  pressedActionEnabled    - Indicate whether button has zoom effect when clicked
 37  */
 38 ccui.Button = ccui.Widget.extend(/** @lends ccui.Button# */{
 39     _buttonNormalRenderer: null,
 40     _buttonClickedRenderer: null,
 41     _buttonDisableRenderer: null,
 42     _titleRenderer: null,
 43 
 44     _normalFileName: "",
 45     _clickedFileName: "",
 46     _disabledFileName: "",
 47 
 48     _prevIgnoreSize: true,
 49     _scale9Enabled: false,
 50 
 51     _capInsetsNormal: null,
 52     _capInsetsPressed: null,
 53     _capInsetsDisabled: null,
 54 
 55     _normalTexType: ccui.Widget.LOCAL_TEXTURE,
 56     _pressedTexType: ccui.Widget.LOCAL_TEXTURE,
 57     _disabledTexType: ccui.Widget.LOCAL_TEXTURE,
 58 
 59     _normalTextureSize: null,
 60     _pressedTextureSize: null,
 61     _disabledTextureSize: null,
 62 
 63     pressedActionEnabled: false,
 64     _titleColor: null,
 65     _normalTextureScaleXInSize: 1,
 66     _normalTextureScaleYInSize: 1,
 67     _pressedTextureScaleXInSize: 1,
 68     _pressedTextureScaleYInSize: 1,
 69 
 70     _zoomScale: 0.1,
 71 
 72     _normalTextureLoaded: false,
 73     _pressedTextureLoaded: false,
 74     _disabledTextureLoaded: false,
 75 
 76     _className: "Button",
 77     _normalTextureAdaptDirty: true,
 78     _pressedTextureAdaptDirty: true,
 79     _disabledTextureAdaptDirty: true,
 80 
 81     _fontName: "Thonburi",
 82     _fontSize: 12,
 83     _type: 0,
 84 
 85     /**
 86      * Allocates and initializes a UIButton.
 87      * Constructor of ccui.Button. override it to extend the construction behavior, remember to call "this._super()" in the extended "ctor" function.
 88      * @param {String} normalImage
 89      * @param {String} [selectedImage=""]
 90      * @param {String} [disableImage=""]
 91      * @param {Number} [texType=ccui.Widget.LOCAL_TEXTURE]
 92      * @example
 93      * // example
 94      * var uiButton = new ccui.Button();
 95      */
 96     ctor: function (normalImage, selectedImage, disableImage, texType) {
 97         this._capInsetsNormal = cc.rect(0, 0, 0, 0);
 98         this._capInsetsPressed = cc.rect(0, 0, 0, 0);
 99         this._capInsetsDisabled = cc.rect(0, 0, 0, 0);
100         this._normalTextureSize = cc.size(0, 0);
101         this._pressedTextureSize = cc.size(0, 0);
102         this._disabledTextureSize = cc.size(0, 0);
103         this._titleColor = cc.color.WHITE;
104         ccui.Widget.prototype.ctor.call(this);
105         this.setTouchEnabled(true);
106         this.init(normalImage, selectedImage, disableImage, texType);
107     },
108 
109     /**
110      * Initializes a button. please do not call this function by yourself, you should pass the parameters to constructor to initialize it.
111      * @param {String} normalImage
112      * @param {String} [selectedImage=""]
113      * @param {String} [disableImage=""]
114      * @param {Number} [texType=ccui.Widget.LOCAL_TEXTURE]
115      * @returns {boolean}
116      * @override
117      */
118     init: function (normalImage, selectedImage,disableImage, texType) {
119         if (ccui.Widget.prototype.init.call(this)) {
120             if(normalImage === undefined)
121                 return true;
122             this.loadTextures(normalImage, selectedImage,disableImage, texType);
123         }
124         return false;
125     },
126 
127     _initRenderer: function () {
128         //todo create Scale9Sprite
129         this._buttonNormalRenderer = new cc.Sprite();
130         this._buttonClickedRenderer = new cc.Sprite();
131         this._buttonDisableRenderer = new cc.Sprite();
132         this._titleRenderer = new cc.LabelTTF("");
133         this._titleRenderer.setAnchorPoint(0.5, 0.5);
134 
135         this.addProtectedChild(this._buttonNormalRenderer, ccui.Button.NORMAL_RENDERER_ZORDER, -1);
136         this.addProtectedChild(this._buttonClickedRenderer, ccui.Button.PRESSED_RENDERER_ZORDER, -1);
137         this.addProtectedChild(this._buttonDisableRenderer, ccui.Button.DISABLED_RENDERER_ZORDER, -1);
138         this.addProtectedChild(this._titleRenderer, ccui.Button.TITLE_RENDERER_ZORDER, -1);
139     },
140 
141     /**
142      * Sets if button is using scale9 renderer.
143      * @param {Boolean} able true that using scale9 renderer, false otherwise.
144      */
145     setScale9Enabled: function (able) {
146         //todo create Scale9Sprite
147         if (this._scale9Enabled === able)
148             return;
149 
150         this._brightStyle = ccui.Widget.BRIGHT_STYLE_NONE;
151         this._scale9Enabled = able;
152 
153         this.removeProtectedChild(this._buttonNormalRenderer);
154         this.removeProtectedChild(this._buttonClickedRenderer);
155         this.removeProtectedChild(this._buttonDisableRenderer);
156 
157         if (this._scale9Enabled) {
158             this._buttonNormalRenderer = new ccui.Scale9Sprite();
159             this._buttonClickedRenderer = new ccui.Scale9Sprite();
160             this._buttonDisableRenderer = new ccui.Scale9Sprite();
161         } else {
162             this._buttonNormalRenderer = new cc.Sprite();
163             this._buttonClickedRenderer = new cc.Sprite();
164             this._buttonDisableRenderer = new cc.Sprite();
165         }
166 
167         this._buttonClickedRenderer.setVisible(false);
168         this._buttonDisableRenderer.setVisible(false);
169 
170         this.loadTextureNormal(this._normalFileName, this._normalTexType);
171         this.loadTexturePressed(this._clickedFileName, this._pressedTexType);
172         this.loadTextureDisabled(this._disabledFileName, this._disabledTexType);
173 
174         this.addProtectedChild(this._buttonNormalRenderer, ccui.Button.NORMAL_RENDERER_ZORDER, -1);
175         this.addProtectedChild(this._buttonClickedRenderer, ccui.Button.PRESSED_RENDERER_ZORDER, -1);
176         this.addProtectedChild(this._buttonDisableRenderer, ccui.Button.DISABLED_RENDERER_ZORDER, -1);
177         if (this._scale9Enabled) {
178             var ignoreBefore = this._ignoreSize;
179             this.ignoreContentAdaptWithSize(false);
180             this._prevIgnoreSize = ignoreBefore;
181         } else {
182             this.ignoreContentAdaptWithSize(this._prevIgnoreSize);
183         }
184         this.setCapInsetsNormalRenderer(this._capInsetsNormal);
185         this.setCapInsetsPressedRenderer(this._capInsetsPressed);
186         this.setCapInsetsDisabledRenderer(this._capInsetsDisabled);
187         this.setBright(this._bright);
188 
189         this._normalTextureAdaptDirty = true;
190         this._pressedTextureAdaptDirty = true;
191         this._disabledTextureAdaptDirty = true;
192     },
193 
194     /**
195      *  Returns button is using scale9 renderer or not.
196      * @returns {Boolean}
197      */
198     isScale9Enabled: function () {
199         return this._scale9Enabled;
200     },
201 
202     /**
203      * Sets whether ignore the widget size
204      * @param {Boolean} ignore true that widget will ignore it's size, use texture size, false otherwise. Default value is true.
205      * @override
206      */
207     ignoreContentAdaptWithSize: function (ignore) {
208         if(this._unifySize){
209             this._updateContentSize();
210             return;
211         }
212         if (!this._scale9Enabled || (this._scale9Enabled && !ignore)) {
213             ccui.Widget.prototype.ignoreContentAdaptWithSize.call(this, ignore);
214             this._prevIgnoreSize = ignore;
215         }
216     },
217 
218     /**
219      * Returns the renderer size.
220      * @returns {cc.Size}
221      */
222     getVirtualRendererSize: function(){
223         if (this._unifySize)
224             return this._getNormalSize();
225 
226         if (!this._normalTextureLoaded && this._titleRenderer.getString().length > 0) {
227             return this._titleRenderer.getContentSize();
228         }
229         return cc.size(this._normalTextureSize);
230     },
231 
232     /**
233      * Load textures for button.
234      * @param {String} normal normal state of texture's filename.
235      * @param {String} selected  selected state of texture's filename.
236      * @param {String} disabled  disabled state of texture's filename.
237      * @param {ccui.Widget.LOCAL_TEXTURE|ccui.Widget.PLIST_TEXTURE} texType
238      */
239     loadTextures: function (normal, selected, disabled, texType) {
240         this.loadTextureNormal(normal, texType);
241         this.loadTexturePressed(selected, texType);
242         this.loadTextureDisabled(disabled, texType);
243     },
244 
245     /**
246      * Load normal state texture for button.
247      * @param {String} normal normal state of texture's filename.
248      * @param {ccui.Widget.LOCAL_TEXTURE|ccui.Widget.PLIST_TEXTURE} texType
249      */
250     loadTextureNormal: function (normal, texType) {
251         if (!normal)
252             return;
253         texType = texType || ccui.Widget.LOCAL_TEXTURE;
254         this._normalFileName = normal;
255         this._normalTexType = texType;
256 
257         var self = this;
258         var normalRenderer = this._buttonNormalRenderer;
259         if(!normalRenderer._textureLoaded){
260             normalRenderer.addEventListener("load", function(){
261                 self.loadTextureNormal(self._normalFileName, self._normalTexType);
262             });
263         }
264         switch (this._normalTexType){
265             case ccui.Widget.LOCAL_TEXTURE:
266                 //SetTexture cannot load resource
267                 normalRenderer.initWithFile(normal);
268                 break;
269             case ccui.Widget.PLIST_TEXTURE:
270                 //SetTexture cannot load resource
271                 normalRenderer.initWithSpriteFrameName(normal);
272                 break;
273             default:
274                 break;
275         }
276 
277         this._normalTextureLoaded = normalRenderer._textureLoaded;
278 
279         this._normalTextureSize = this._buttonNormalRenderer.getContentSize();
280         this._updateChildrenDisplayedRGBA();
281         if (this._unifySize){
282             if (this._scale9Enabled){
283                 normalRenderer.setCapInsets(this._capInsetsNormal);
284                 this._updateContentSizeWithTextureSize(this._getNormalSize());
285             }
286         }else
287             this._updateContentSizeWithTextureSize(this._normalTextureSize);
288 
289         this._normalTextureAdaptDirty = true;
290         this._findLayout();
291     },
292 
293     /**
294      * Load selected state texture for button.
295      * @param {String} selected selected state of texture's filename.
296      * @param {ccui.Widget.LOCAL_TEXTURE|ccui.Widget.PLIST_TEXTURE} texType
297      */
298     loadTexturePressed: function (selected, texType) {
299         if (!selected)
300             return;
301         texType = texType || ccui.Widget.LOCAL_TEXTURE;
302         this._clickedFileName = selected;
303         this._pressedTexType = texType;
304 
305         var self = this;
306         var clickedRenderer = this._buttonClickedRenderer;
307         if(!clickedRenderer._textureLoaded){
308             clickedRenderer.addEventListener("load", function(){
309                 self.loadTexturePressed(self._clickedFileName, self._pressedTexType);
310             });
311         }
312 
313         switch (this._pressedTexType) {
314             case ccui.Widget.LOCAL_TEXTURE:
315                 //SetTexture cannot load resource
316                 clickedRenderer.initWithFile(selected);
317                 break;
318             case ccui.Widget.PLIST_TEXTURE:
319                 //SetTexture cannot load resource
320                 clickedRenderer.initWithSpriteFrameName(selected);
321                 break;
322             default:
323                 break;
324         }
325 
326         if (this._scale9Enabled)
327             clickedRenderer.setCapInsets(this._capInsetsPressed);
328 
329         this._pressedTextureSize = this._buttonClickedRenderer.getContentSize();
330         this._updateChildrenDisplayedRGBA();
331 
332         this._pressedTextureLoaded = true;
333         this._pressedTextureAdaptDirty = true;
334         this._findLayout();
335     },
336 
337     /**
338      * Load dark state texture for button.
339      * @param {String} disabled disabled state of texture's filename.
340      * @param {ccui.Widget.LOCAL_TEXTURE|ccui.Widget.PLIST_TEXTURE} texType
341      */
342     loadTextureDisabled: function (disabled, texType) {
343         if (!disabled)
344             return;
345 
346         texType = texType || ccui.Widget.LOCAL_TEXTURE;
347         this._disabledFileName = disabled;
348         this._disabledTexType = texType;
349 
350         var self = this;
351         var disabledRenderer = this._buttonDisableRenderer;
352         if(!disabledRenderer._textureLoaded){
353             disabledRenderer.addEventListener("load", function() {
354                 self.loadTextureDisabled(self._disabledFileName, self._disabledTexType);
355             });
356         }
357 
358         switch (this._disabledTexType) {
359             case ccui.Widget.LOCAL_TEXTURE:
360                 //SetTexture cannot load resource
361                 disabledRenderer.initWithFile(disabled);
362                 break;
363             case ccui.Widget.PLIST_TEXTURE:
364                 //SetTexture cannot load resource
365                 disabledRenderer.initWithSpriteFrameName(disabled);
366                 break;
367             default:
368                 break;
369         }
370 
371         if (this._scale9Enabled)
372             disabledRenderer.setCapInsets(this._capInsetsDisabled);
373 
374         this._disabledTextureSize = this._buttonDisableRenderer.getContentSize();
375         this._updateChildrenDisplayedRGBA();
376 
377         this._disabledTextureLoaded = true;
378         this._disabledTextureAdaptDirty = true;
379         this._findLayout();
380     },
381 
382     /**
383      * Sets capinsets for button, if button is using scale9 renderer.
384      * @param {cc.Rect} capInsets
385      */
386     setCapInsets: function (capInsets) {
387         this.setCapInsetsNormalRenderer(capInsets);
388         this.setCapInsetsPressedRenderer(capInsets);
389         this.setCapInsetsDisabledRenderer(capInsets);
390     },
391 
392     /**
393      * Sets capinsets for button, if button is using scale9 renderer.
394      * @param {cc.Rect} capInsets
395      */
396     setCapInsetsNormalRenderer: function (capInsets) {
397         if(!capInsets)
398             return;
399 
400         var x = capInsets.x, y = capInsets.y;
401         var width = capInsets.width, height = capInsets.height;
402         if (this._normalTextureSize.width < width){
403             x = 0;
404             width = 0;
405         }
406         if (this._normalTextureSize.height < height){
407             y = 0;
408             height = 0;
409         }
410 
411         var locInsets = this._capInsetsNormal;
412         locInsets.x = x;
413         locInsets.y = y;
414         locInsets.width = width;
415         locInsets.height = height;
416 
417         if (!this._scale9Enabled)
418             return;
419         this._buttonNormalRenderer.setCapInsets(locInsets);
420     },
421 
422     /**
423      *  Returns normal renderer cap insets.
424      * @returns {cc.Rect}
425      */
426     getCapInsetsNormalRenderer:function(){
427         return cc.rect(this._capInsetsNormal);
428     },
429 
430     /**
431      * Sets capinsets for button, if button is using scale9 renderer.
432      * @param {cc.Rect} capInsets
433      */
434     setCapInsetsPressedRenderer: function (capInsets) {
435         if(!capInsets || !this._scale9Enabled)
436             return;
437 
438         var x = capInsets.x, y = capInsets.y;
439         var width = capInsets.width, height = capInsets.height;
440 
441         if (this._pressedTextureSize.width < width) {
442             x = 0;
443             width = 0;
444         }
445         if (this._pressedTextureSize.height < height) {
446             y = 0;
447             height = 0;
448         }
449 
450         var locInsets = this._capInsetsPressed;
451         locInsets.x = x;
452         locInsets.y = y;
453         locInsets.width = width;
454         locInsets.height = height;
455 
456         this._buttonClickedRenderer.setCapInsets(locInsets);
457     },
458 
459     /**
460      *  Returns pressed renderer cap insets.
461      * @returns {cc.Rect}
462      */
463     getCapInsetsPressedRenderer: function () {
464         return cc.rect(this._capInsetsPressed);
465     },
466 
467     /**
468      * Sets capinsets for button, if button is using scale9 renderer.
469      * @param {cc.Rect} capInsets
470      */
471     setCapInsetsDisabledRenderer: function (capInsets) {
472         if(!capInsets || !this._scale9Enabled)
473             return;
474 
475         var x = capInsets.x, y = capInsets.y;
476         var width = capInsets.width, height = capInsets.height;
477 
478         if (this._disabledTextureSize.width < width) {
479             x = 0;
480             width = 0;
481         }
482         if (this._disabledTextureSize.height < height) {
483             y = 0;
484             height = 0;
485         }
486 
487         var locInsets = this._capInsetsDisabled;
488         locInsets.x = x;
489         locInsets.y = y;
490         locInsets.width = width;
491         locInsets.height = height;
492 
493         this._buttonDisableRenderer.setCapInsets(locInsets);
494     },
495 
496     /**
497      * Returns disable renderer cap insets.
498      * @returns {cc.Rect}
499      */
500     getCapInsetsDisabledRenderer: function () {
501         return cc.rect(this._capInsetsDisabled);
502     },
503 
504     _onPressStateChangedToNormal: function () {
505         this._buttonNormalRenderer.setVisible(true);
506         this._buttonClickedRenderer.setVisible(false);
507         this._buttonDisableRenderer.setVisible(false);
508         if (this._scale9Enabled)
509             this._buttonNormalRenderer.setState( ccui.Scale9Sprite.state.NORMAL);
510         if (this._pressedTextureLoaded) {
511             if (this.pressedActionEnabled){
512                 this._buttonNormalRenderer.stopAllActions();
513                 this._buttonClickedRenderer.stopAllActions();
514                 //var zoomAction = cc.scaleTo(ccui.Button.ZOOM_ACTION_TIME_STEP, this._normalTextureScaleXInSize, this._normalTextureScaleYInSize);
515                 //fixme: the zoomAction will run in the next frame which will cause the _buttonNormalRenderer to a wrong scale
516                 //this._buttonNormalRenderer.runAction(zoomAction);
517                 this._buttonNormalRenderer.setScale(this._normalTextureScaleXInSize, this._normalTextureScaleYInSize);
518                 this._buttonClickedRenderer.setScale(this._pressedTextureScaleXInSize, this._pressedTextureScaleYInSize);
519 
520                 this._titleRenderer.stopAllActions();
521                 if (this._unifySize){
522                     var zoomTitleAction = cc.scaleTo(ccui.Button.ZOOM_ACTION_TIME_STEP, 1, 1);
523                     this._titleRenderer.runAction(zoomTitleAction);
524                 }else{
525                     this._titleRenderer.setScaleX(1);
526                     this._titleRenderer.setScaleY(1);
527                 }
528             }
529         } else {
530             this._buttonNormalRenderer.stopAllActions();
531             this._buttonNormalRenderer.setScale(this._normalTextureScaleXInSize, this._normalTextureScaleYInSize);
532 
533             this._titleRenderer.stopAllActions();
534             if (this._scale9Enabled)
535                 this._buttonNormalRenderer.setColor(cc.color.WHITE);
536 
537             this._titleRenderer.setScaleX(1);
538             this._titleRenderer.setScaleY(1);
539         }
540     },
541 
542     _onPressStateChangedToPressed: function () {
543         var locNormalRenderer = this._buttonNormalRenderer;
544         if (this._scale9Enabled)
545             locNormalRenderer.setState(ccui.Scale9Sprite.state.NORMAL);
546 
547         if (this._pressedTextureLoaded) {
548             locNormalRenderer.setVisible(false);
549             this._buttonClickedRenderer.setVisible(true);
550             this._buttonDisableRenderer.setVisible(false);
551             if (this.pressedActionEnabled) {
552                 locNormalRenderer.stopAllActions();
553                 this._buttonClickedRenderer.stopAllActions();
554                 var zoomAction = cc.scaleTo(ccui.Button.ZOOM_ACTION_TIME_STEP, this._pressedTextureScaleXInSize + this._zoomScale,
555                         this._pressedTextureScaleYInSize + this._zoomScale);
556                 this._buttonClickedRenderer.runAction(zoomAction);
557                 locNormalRenderer.setScale(this._pressedTextureScaleXInSize + this._zoomScale, this._pressedTextureScaleYInSize + this._zoomScale);
558 
559                 this._titleRenderer.stopAllActions();
560                 this._titleRenderer.runAction(cc.scaleTo(ccui.Button.ZOOM_ACTION_TIME_STEP, 1 + this._zoomScale, 1 + this._zoomScale));
561             }
562         } else {
563             locNormalRenderer.setVisible(true);
564             this._buttonClickedRenderer.setVisible(true);
565             this._buttonDisableRenderer.setVisible(false);
566             locNormalRenderer.stopAllActions();
567             locNormalRenderer.setScale(this._normalTextureScaleXInSize + this._zoomScale, this._normalTextureScaleYInSize + this._zoomScale);
568 
569             this._titleRenderer.stopAllActions();
570             this._titleRenderer.setScaleX(1 + this._zoomScale);
571             this._titleRenderer.setScaleY(1 + this._zoomScale);
572         }
573     },
574 
575     _onPressStateChangedToDisabled: function () {
576         //if disable resource is null
577         if (!this._disabledTextureLoaded){
578             if (this._normalTextureLoaded && this._scale9Enabled)
579                 this._buttonNormalRenderer.setState(ccui.Scale9Sprite.state.GRAY);
580         }else{
581             this._buttonNormalRenderer.setVisible(false);
582             this._buttonDisableRenderer.setVisible(true);
583         }
584 
585         this._buttonClickedRenderer.setVisible(false);
586         this._buttonNormalRenderer.setScale(this._normalTextureScaleXInSize, this._normalTextureScaleYInSize);
587         this._buttonClickedRenderer.setScale(this._pressedTextureScaleXInSize, this._pressedTextureScaleYInSize);
588     },
589 
590     _updateContentSize: function(){
591         if (this._unifySize){
592             if (this._scale9Enabled)
593                 ccui.ProtectedNode.setContentSize(this._customSize);
594             else{
595                 var s = this._getNormalSize();
596                 ccui.ProtectedNode.setContentSize(s);
597             }
598             this._onSizeChanged();
599             return;
600         }
601 
602         if (this._ignoreSize)
603             this.setContentSize(this.getVirtualRendererSize());
604     },
605 
606     _updateTexturesRGBA: function(){
607         this._buttonNormalRenderer.setColor(this.getColor());
608         this._buttonClickedRenderer.setColor(this.getColor());
609         this._buttonDisableRenderer.setColor(this.getColor());
610 
611         this._buttonNormalRenderer.setOpacity(this.getOpacity());
612         this._buttonClickedRenderer.setOpacity(this.getOpacity());
613         this._buttonDisableRenderer.setOpacity(this.getOpacity());
614     },
615 
616     _onSizeChanged: function () {
617         ccui.Widget.prototype._onSizeChanged.call(this);
618         this._updateTitleLocation();
619         this._normalTextureAdaptDirty = true;
620         this._pressedTextureAdaptDirty = true;
621         this._disabledTextureAdaptDirty = true;
622     },
623 
624     /**
625      * Gets the Virtual Renderer of widget.
626      * @returns {cc.Node}
627      */
628     getVirtualRenderer: function () {
629         if (this._bright) {
630             switch (this._brightStyle) {
631                 case ccui.Widget.BRIGHT_STYLE_NORMAL:
632                     return this._buttonNormalRenderer;
633                 case ccui.Widget.BRIGHT_STYLE_HIGH_LIGHT:
634                     return this._buttonClickedRenderer;
635                 default:
636                     return null;
637             }
638         } else
639             return this._buttonDisableRenderer;
640     },
641 
642     _normalTextureScaleChangedWithSize: function () {
643         if(this._ignoreSize && !this._unifySize){
644             if(!this._scale9Enabled){
645                 this._buttonNormalRenderer.setScale(1);
646                 this._normalTextureScaleXInSize = this._normalTextureScaleYInSize = 1;
647             }
648         }else{
649             if (this._scale9Enabled){
650                 this._buttonNormalRenderer.setPreferredSize(this._contentSize);
651                 this._normalTextureScaleXInSize = this._normalTextureScaleYInSize = 1;
652                 this._buttonNormalRenderer.setScale(this._normalTextureScaleXInSize, this._normalTextureScaleYInSize);
653             }else{
654                 var textureSize = this._normalTextureSize;
655                 if (textureSize.width <= 0 || textureSize.height <= 0)
656                 {
657                     this._buttonNormalRenderer.setScale(1);
658                     return;
659                 }
660                 var scaleX = this._contentSize.width / textureSize.width;
661                 var scaleY = this._contentSize.height / textureSize.height;
662                 this._buttonNormalRenderer.setScaleX(scaleX);
663                 this._buttonNormalRenderer.setScaleY(scaleY);
664                 this._normalTextureScaleXInSize = scaleX;
665                 this._normalTextureScaleYInSize = scaleY;
666             }
667         }
668         this._buttonNormalRenderer.setPosition(this._contentSize.width / 2, this._contentSize.height / 2);
669     },
670 
671     _pressedTextureScaleChangedWithSize: function () {
672         if (this._ignoreSize && !this._unifySize) {
673             if (!this._scale9Enabled) {
674                 this._buttonClickedRenderer.setScale(1);
675                 this._pressedTextureScaleXInSize = this._pressedTextureScaleYInSize = 1;
676             }
677         } else {
678             if (this._scale9Enabled) {
679                 this._buttonClickedRenderer.setPreferredSize(this._contentSize);
680                 this._pressedTextureScaleXInSize = this._pressedTextureScaleYInSize = 1;
681                 this._buttonClickedRenderer.setScale(this._pressedTextureScaleXInSize, this._pressedTextureScaleYInSize);
682             } else {
683                 var textureSize = this._pressedTextureSize;
684                 if (textureSize.width <= 0 || textureSize.height <= 0) {
685                     this._buttonClickedRenderer.setScale(1);
686                     return;
687                 }
688                 var scaleX = this._contentSize.width / textureSize.width;
689                 var scaleY = this._contentSize.height / textureSize.height;
690                 this._buttonClickedRenderer.setScaleX(scaleX);
691                 this._buttonClickedRenderer.setScaleY(scaleY);
692                 this._pressedTextureScaleXInSize = scaleX;
693                 this._pressedTextureScaleYInSize = scaleY;
694             }
695         }
696         this._buttonClickedRenderer.setPosition(this._contentSize.width / 2, this._contentSize.height / 2);
697     },
698 
699     _disabledTextureScaleChangedWithSize: function () {
700         if(this._ignoreSize && !this._unifySize){
701             if (this._scale9Enabled)
702                 this._buttonDisableRenderer.setScale(1);
703         }else {
704             if (this._scale9Enabled){
705                 this._buttonDisableRenderer.setScale(1);
706                 this._buttonDisableRenderer.setPreferredSize(this._contentSize);
707             }else{
708                 var textureSize = this._disabledTextureSize;
709                 if (textureSize.width <= 0 || textureSize.height <= 0) {
710                     this._buttonDisableRenderer.setScale(1);
711                     return;
712                 }
713                 var scaleX = this._contentSize.width / textureSize.width;
714                 var scaleY = this._contentSize.height / textureSize.height;
715                 this._buttonDisableRenderer.setScaleX(scaleX);
716                 this._buttonDisableRenderer.setScaleY(scaleY);
717             }
718         }
719         this._buttonDisableRenderer.setPosition(this._contentSize.width / 2, this._contentSize.height / 2);
720     },
721 
722     _adaptRenderers: function(){
723         if (this._normalTextureAdaptDirty) {
724             this._normalTextureScaleChangedWithSize();
725             this._normalTextureAdaptDirty = false;
726         }
727         if (this._pressedTextureAdaptDirty) {
728             this._pressedTextureScaleChangedWithSize();
729             this._pressedTextureAdaptDirty = false;
730         }
731         if (this._disabledTextureAdaptDirty) {
732             this._disabledTextureScaleChangedWithSize();
733             this._disabledTextureAdaptDirty = false;
734         }
735     },
736 
737     _updateTitleLocation: function(){
738         this._titleRenderer.setPosition(this._contentSize.width * 0.5, this._contentSize.height * 0.5);
739     },
740 
741     /**
742      * Changes if button can be clicked zoom effect.
743      * @param {Boolean} enabled
744      */
745     setPressedActionEnabled: function (enabled) {
746         this.pressedActionEnabled = enabled;
747     },
748 
749     /**
750      * Sets title text to ccui.Button
751      * @param {String} text
752      */
753     setTitleText: function (text) {
754         if(text === this.getTitleText())
755             return;
756         this._titleRenderer.setString(text);
757         if (this._ignoreSize){
758             var s = this.getVirtualRendererSize();
759             this.setContentSize(s);
760         }else{
761             this._titleRenderer._renderCmd._updateTTF();
762         }
763     },
764 
765     /**
766      * Returns title text of ccui.Button
767      * @returns {String} text
768      */
769     getTitleText: function () {
770         return this._titleRenderer.getString();
771     },
772 
773     /**
774      * Sets title color to ccui.Button.
775      * @param {cc.Color} color
776      */
777     setTitleColor: function (color) {
778         this._titleRenderer.setFontFillColor(color);
779     },
780 
781     /**
782      * Returns title color of ccui.Button
783      * @returns {cc.Color}
784      */
785     getTitleColor: function () {
786         return this._titleRenderer._getFillStyle();
787     },
788 
789     /**
790      * Sets title fontSize to ccui.Button
791      * @param {cc.Size} size
792      */
793     setTitleFontSize: function (size) {
794         this._titleRenderer.setFontSize(size);
795         this._fontSize = size;
796     },
797 
798     /**
799      * Returns title fontSize of ccui.Button.
800      * @returns {Number}
801      */
802     getTitleFontSize: function () {
803         return this._titleRenderer.getFontSize();
804     },
805 
806     /**
807      * When user pressed the button, the button will zoom to a scale.
808      * The final scale of the button  equals (button original scale + _zoomScale)
809      * @since v3.2
810      * @param scale
811      */
812     setZoomScale: function(scale){
813         this._zoomScale = scale;
814     },
815 
816     /**
817      * Returns a zoom scale
818      * @since v3.2
819      * @returns {number}
820      */
821     getZoomScale: function(){
822         return this._zoomScale;
823     },
824 
825     /**
826      * Returns the normalize of texture size
827      * @since v3.3
828      * @returns {cc.Size}
829      */
830     getNormalTextureSize: function(){
831         return this._normalTextureSize;
832     },
833 
834     /**
835      * Sets title fontName to ccui.Button.
836      * @param {String} fontName
837      */
838     setTitleFontName: function (fontName) {
839         this._titleRenderer.setFontName(fontName);
840         this._fontName = fontName;
841     },
842 
843     /**
844      * Get the title renderer.
845      * title ttf object.
846      * @returns {cc.LabelTTF}
847      */
848     getTitleRenderer: function(){
849         return this._titleRenderer;
850     },
851 
852     /**
853      * Gets title fontName of ccui.Button.
854      * @returns {String}
855      */
856     getTitleFontName: function () {
857         return this._titleRenderer.getFontName();
858     },
859 
860     _setTitleFont: function (font) {
861         this._titleRenderer.font = font;
862     },
863     _getTitleFont: function () {
864         return this._titleRenderer.font;
865     },
866 
867     /**
868      * Returns the "class name" of widget.
869      * @override
870      * @returns {string}
871      */
872     getDescription: function () {
873         return "Button";
874     },
875 
876     _createCloneInstance: function () {
877         return new ccui.Button();
878     },
879 
880     _copySpecialProperties: function (uiButton) {
881         this._prevIgnoreSize = uiButton._prevIgnoreSize;
882         this.setScale9Enabled(uiButton._scale9Enabled);
883         this.loadTextureNormal(uiButton._normalFileName, uiButton._normalTexType);
884         this.loadTexturePressed(uiButton._clickedFileName, uiButton._pressedTexType);
885         this.loadTextureDisabled(uiButton._disabledFileName, uiButton._disabledTexType);
886         this.setCapInsetsNormalRenderer(uiButton._capInsetsNormal);
887         this.setCapInsetsPressedRenderer(uiButton._capInsetsPressed);
888         this.setCapInsetsDisabledRenderer(uiButton._capInsetsDisabled);
889         this.setTitleText(uiButton.getTitleText());
890         this.setTitleFontName(uiButton.getTitleFontName());
891         this.setTitleFontSize(uiButton.getTitleFontSize());
892         this.setTitleColor(uiButton.getTitleColor());
893         this.setPressedActionEnabled(uiButton.pressedActionEnabled);
894         this.setZoomScale(uiButton._zoomScale);
895     },
896 
897     setColor: function(color){
898         cc.ProtectedNode.prototype.setColor.call(this, color);
899         this._updateTexturesRGBA();
900     },
901 
902     _getNormalSize: function(){
903         var titleSize;
904         if (this._titleRenderer !== null)
905             titleSize = this._titleRenderer.getContentSize();
906 
907         var imageSize;
908         if (this._buttonNormalRenderer !== null)
909             imageSize = this._buttonNormalRenderer.getContentSize();
910         var width = titleSize.width > imageSize.width ? titleSize.width : imageSize.width;
911         var height = titleSize.height > imageSize.height ? titleSize.height : imageSize.height;
912 
913         return cc.size(width,height);
914     }
915 });
916 
917 var _p = ccui.Button.prototype;
918 
919 // Extended properties
920 /** @expose */
921 _p.titleText;
922 cc.defineGetterSetter(_p, "titleText", _p.getTitleText, _p.setTitleText);
923 /** @expose */
924 _p.titleFont;
925 cc.defineGetterSetter(_p, "titleFont", _p._getTitleFont, _p._setTitleFont);
926 /** @expose */
927 _p.titleFontSize;
928 cc.defineGetterSetter(_p, "titleFontSize", _p.getTitleFontSize, _p.setTitleFontSize);
929 /** @expose */
930 _p.titleFontName;
931 cc.defineGetterSetter(_p, "titleFontName", _p.getTitleFontName, _p.setTitleFontName);
932 /** @expose */
933 _p.titleColor;
934 cc.defineGetterSetter(_p, "titleColor", _p.getTitleColor, _p.setTitleColor);
935 
936 _p = null;
937 
938 /**
939  * allocates and initializes a UIButton.
940  * @deprecated since v3.0, please use new ccui.Button() instead.
941  * @param {string} [normalImage]    normal state texture name
942  * @param {string} [selectedImage]  selected state texture name
943  * @param {string} [disableImage]   disabled state texture name
944  * @param {string} [texType]
945  * @return {ccui.Button}
946  */
947 ccui.Button.create = function (normalImage, selectedImage, disableImage, texType) {
948     return new ccui.Button(normalImage, selectedImage, disableImage, texType);
949 };
950 
951 // Constants
952 /**
953  * The normal renderer's zOrder value of ccui.Button.
954  * @constant
955  * @type {number}
956  */
957 ccui.Button.NORMAL_RENDERER_ZORDER = -2;
958 /**
959  * The pressed renderer's zOrder value ccui.Button.
960  * @constant
961  * @type {number}
962  */
963 ccui.Button.PRESSED_RENDERER_ZORDER = -2;
964 /**
965  * The disabled renderer's zOrder value of ccui.Button.
966  * @constant
967  * @type {number}
968  */
969 ccui.Button.DISABLED_RENDERER_ZORDER = -2;
970 /**
971  * The title renderer's zOrder value of ccui.Button.
972  * @constant
973  * @type {number}
974  */
975 ccui.Button.TITLE_RENDERER_ZORDER = -1;
976 
977 /**
978  * the zoom action time step of ccui.Button
979  * @constant
980  * @type {number}
981  */
982 ccui.Button.ZOOM_ACTION_TIME_STEP = 0.05;
983 
984 /**
985  * @ignore
986  */
987 ccui.Button.SYSTEM = 0;
988 ccui.Button.TTF = 1;
989