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     _onSizeChanged: function () {
607         ccui.Widget.prototype._onSizeChanged.call(this);
608         this._updateTitleLocation();
609         this._normalTextureAdaptDirty = true;
610         this._pressedTextureAdaptDirty = true;
611         this._disabledTextureAdaptDirty = true;
612     },
613 
614     /**
615      * Gets the Virtual Renderer of widget.
616      * @returns {cc.Node}
617      */
618     getVirtualRenderer: function () {
619         if (this._bright) {
620             switch (this._brightStyle) {
621                 case ccui.Widget.BRIGHT_STYLE_NORMAL:
622                     return this._buttonNormalRenderer;
623                 case ccui.Widget.BRIGHT_STYLE_HIGH_LIGHT:
624                     return this._buttonClickedRenderer;
625                 default:
626                     return null;
627             }
628         } else
629             return this._buttonDisableRenderer;
630     },
631 
632     _normalTextureScaleChangedWithSize: function () {
633         if(this._ignoreSize && !this._unifySize){
634             if(!this._scale9Enabled){
635                 this._buttonNormalRenderer.setScale(1);
636                 this._normalTextureScaleXInSize = this._normalTextureScaleYInSize = 1;
637             }
638         }else{
639             if (this._scale9Enabled){
640                 this._buttonNormalRenderer.setPreferredSize(this._contentSize);
641                 this._normalTextureScaleXInSize = this._normalTextureScaleYInSize = 1;
642                 this._buttonNormalRenderer.setScale(this._normalTextureScaleXInSize, this._normalTextureScaleYInSize);
643             }else{
644                 var textureSize = this._normalTextureSize;
645                 if (textureSize.width <= 0 || textureSize.height <= 0)
646                 {
647                     this._buttonNormalRenderer.setScale(1);
648                     return;
649                 }
650                 var scaleX = this._contentSize.width / textureSize.width;
651                 var scaleY = this._contentSize.height / textureSize.height;
652                 this._buttonNormalRenderer.setScaleX(scaleX);
653                 this._buttonNormalRenderer.setScaleY(scaleY);
654                 this._normalTextureScaleXInSize = scaleX;
655                 this._normalTextureScaleYInSize = scaleY;
656             }
657         }
658         this._buttonNormalRenderer.setPosition(this._contentSize.width / 2, this._contentSize.height / 2);
659     },
660 
661     _pressedTextureScaleChangedWithSize: function () {
662         if (this._ignoreSize && !this._unifySize) {
663             if (!this._scale9Enabled) {
664                 this._buttonClickedRenderer.setScale(1);
665                 this._pressedTextureScaleXInSize = this._pressedTextureScaleYInSize = 1;
666             }
667         } else {
668             if (this._scale9Enabled) {
669                 this._buttonClickedRenderer.setPreferredSize(this._contentSize);
670                 this._pressedTextureScaleXInSize = this._pressedTextureScaleYInSize = 1;
671                 this._buttonClickedRenderer.setScale(this._pressedTextureScaleXInSize, this._pressedTextureScaleYInSize);
672             } else {
673                 var textureSize = this._pressedTextureSize;
674                 if (textureSize.width <= 0 || textureSize.height <= 0) {
675                     this._buttonClickedRenderer.setScale(1);
676                     return;
677                 }
678                 var scaleX = this._contentSize.width / textureSize.width;
679                 var scaleY = this._contentSize.height / textureSize.height;
680                 this._buttonClickedRenderer.setScaleX(scaleX);
681                 this._buttonClickedRenderer.setScaleY(scaleY);
682                 this._pressedTextureScaleXInSize = scaleX;
683                 this._pressedTextureScaleYInSize = scaleY;
684             }
685         }
686         this._buttonClickedRenderer.setPosition(this._contentSize.width / 2, this._contentSize.height / 2);
687     },
688 
689     _disabledTextureScaleChangedWithSize: function () {
690         if(this._ignoreSize && !this._unifySize){
691             if (this._scale9Enabled)
692                 this._buttonDisableRenderer.setScale(1);
693         }else {
694             if (this._scale9Enabled){
695                 this._buttonDisableRenderer.setScale(1);
696                 this._buttonDisableRenderer.setPreferredSize(this._contentSize);
697             }else{
698                 var textureSize = this._disabledTextureSize;
699                 if (textureSize.width <= 0 || textureSize.height <= 0) {
700                     this._buttonDisableRenderer.setScale(1);
701                     return;
702                 }
703                 var scaleX = this._contentSize.width / textureSize.width;
704                 var scaleY = this._contentSize.height / textureSize.height;
705                 this._buttonDisableRenderer.setScaleX(scaleX);
706                 this._buttonDisableRenderer.setScaleY(scaleY);
707             }
708         }
709         this._buttonDisableRenderer.setPosition(this._contentSize.width / 2, this._contentSize.height / 2);
710     },
711 
712     _adaptRenderers: function(){
713         if (this._normalTextureAdaptDirty) {
714             this._normalTextureScaleChangedWithSize();
715             this._normalTextureAdaptDirty = false;
716         }
717         if (this._pressedTextureAdaptDirty) {
718             this._pressedTextureScaleChangedWithSize();
719             this._pressedTextureAdaptDirty = false;
720         }
721         if (this._disabledTextureAdaptDirty) {
722             this._disabledTextureScaleChangedWithSize();
723             this._disabledTextureAdaptDirty = false;
724         }
725     },
726 
727     _updateTitleLocation: function(){
728         this._titleRenderer.setPosition(this._contentSize.width * 0.5, this._contentSize.height * 0.5);
729     },
730 
731     /**
732      * Changes if button can be clicked zoom effect.
733      * @param {Boolean} enabled
734      */
735     setPressedActionEnabled: function (enabled) {
736         this.pressedActionEnabled = enabled;
737     },
738 
739     /**
740      * Sets title text to ccui.Button
741      * @param {String} text
742      */
743     setTitleText: function (text) {
744         if(text === this.getTitleText())
745             return;
746         this._titleRenderer.setString(text);
747         if (this._ignoreSize){
748             var s = this.getVirtualRendererSize();
749             this.setContentSize(s);
750         }else{
751             this._titleRenderer._renderCmd._updateTTF();
752         }
753     },
754 
755     /**
756      * Returns title text of ccui.Button
757      * @returns {String} text
758      */
759     getTitleText: function () {
760         return this._titleRenderer.getString();
761     },
762 
763     /**
764      * Sets title color to ccui.Button.
765      * @param {cc.Color} color
766      */
767     setTitleColor: function (color) {
768         this._titleRenderer.setFontFillColor(color);
769     },
770 
771     /**
772      * Returns title color of ccui.Button
773      * @returns {cc.Color}
774      */
775     getTitleColor: function () {
776         return this._titleRenderer._getFillStyle();
777     },
778 
779     /**
780      * Sets title fontSize to ccui.Button
781      * @param {cc.Size} size
782      */
783     setTitleFontSize: function (size) {
784         this._titleRenderer.setFontSize(size);
785         this._fontSize = size;
786     },
787 
788     /**
789      * Returns title fontSize of ccui.Button.
790      * @returns {Number}
791      */
792     getTitleFontSize: function () {
793         return this._titleRenderer.getFontSize();
794     },
795 
796     /**
797      * When user pressed the button, the button will zoom to a scale.
798      * The final scale of the button  equals (button original scale + _zoomScale)
799      * @since v3.2
800      * @param scale
801      */
802     setZoomScale: function(scale){
803         this._zoomScale = scale;
804     },
805 
806     /**
807      * Returns a zoom scale
808      * @since v3.2
809      * @returns {number}
810      */
811     getZoomScale: function(){
812         return this._zoomScale;
813     },
814 
815     /**
816      * Returns the normalize of texture size
817      * @since v3.3
818      * @returns {cc.Size}
819      */
820     getNormalTextureSize: function(){
821         return this._normalTextureSize;
822     },
823 
824     /**
825      * Sets title fontName to ccui.Button.
826      * @param {String} fontName
827      */
828     setTitleFontName: function (fontName) {
829         this._titleRenderer.setFontName(fontName);
830         this._fontName = fontName;
831     },
832 
833     /**
834      * Get the title renderer.
835      * title ttf object.
836      * @returns {cc.LabelTTF}
837      */
838     getTitleRenderer: function(){
839         return this._titleRenderer;
840     },
841 
842     /**
843      * Gets title fontName of ccui.Button.
844      * @returns {String}
845      */
846     getTitleFontName: function () {
847         return this._titleRenderer.getFontName();
848     },
849 
850     _setTitleFont: function (font) {
851         this._titleRenderer.font = font;
852     },
853     _getTitleFont: function () {
854         return this._titleRenderer.font;
855     },
856 
857     /**
858      * Returns the "class name" of widget.
859      * @override
860      * @returns {string}
861      */
862     getDescription: function () {
863         return "Button";
864     },
865 
866     _createCloneInstance: function () {
867         return new ccui.Button();
868     },
869 
870     _copySpecialProperties: function (uiButton) {
871         this._prevIgnoreSize = uiButton._prevIgnoreSize;
872         this.setScale9Enabled(uiButton._scale9Enabled);
873         this.loadTextureNormal(uiButton._normalFileName, uiButton._normalTexType);
874         this.loadTexturePressed(uiButton._clickedFileName, uiButton._pressedTexType);
875         this.loadTextureDisabled(uiButton._disabledFileName, uiButton._disabledTexType);
876         this.setCapInsetsNormalRenderer(uiButton._capInsetsNormal);
877         this.setCapInsetsPressedRenderer(uiButton._capInsetsPressed);
878         this.setCapInsetsDisabledRenderer(uiButton._capInsetsDisabled);
879         this.setTitleText(uiButton.getTitleText());
880         this.setTitleFontName(uiButton.getTitleFontName());
881         this.setTitleFontSize(uiButton.getTitleFontSize());
882         this.setTitleColor(uiButton.getTitleColor());
883         this.setPressedActionEnabled(uiButton.pressedActionEnabled);
884         this.setZoomScale(uiButton._zoomScale);
885     },
886 
887     _getNormalSize: function(){
888         var titleSize;
889         if (this._titleRenderer !== null)
890             titleSize = this._titleRenderer.getContentSize();
891 
892         var imageSize;
893         if (this._buttonNormalRenderer !== null)
894             imageSize = this._buttonNormalRenderer.getContentSize();
895         var width = titleSize.width > imageSize.width ? titleSize.width : imageSize.width;
896         var height = titleSize.height > imageSize.height ? titleSize.height : imageSize.height;
897 
898         return cc.size(width,height);
899     }
900 });
901 
902 var _p = ccui.Button.prototype;
903 
904 // Extended properties
905 /** @expose */
906 _p.titleText;
907 cc.defineGetterSetter(_p, "titleText", _p.getTitleText, _p.setTitleText);
908 /** @expose */
909 _p.titleFont;
910 cc.defineGetterSetter(_p, "titleFont", _p._getTitleFont, _p._setTitleFont);
911 /** @expose */
912 _p.titleFontSize;
913 cc.defineGetterSetter(_p, "titleFontSize", _p.getTitleFontSize, _p.setTitleFontSize);
914 /** @expose */
915 _p.titleFontName;
916 cc.defineGetterSetter(_p, "titleFontName", _p.getTitleFontName, _p.setTitleFontName);
917 /** @expose */
918 _p.titleColor;
919 cc.defineGetterSetter(_p, "titleColor", _p.getTitleColor, _p.setTitleColor);
920 
921 _p = null;
922 
923 /**
924  * allocates and initializes a UIButton.
925  * @deprecated since v3.0, please use new ccui.Button() instead.
926  * @param {string} [normalImage]    normal state texture name
927  * @param {string} [selectedImage]  selected state texture name
928  * @param {string} [disableImage]   disabled state texture name
929  * @param {string} [texType]
930  * @return {ccui.Button}
931  */
932 ccui.Button.create = function (normalImage, selectedImage, disableImage, texType) {
933     return new ccui.Button(normalImage, selectedImage, disableImage, texType);
934 };
935 
936 // Constants
937 /**
938  * The normal renderer's zOrder value of ccui.Button.
939  * @constant
940  * @type {number}
941  */
942 ccui.Button.NORMAL_RENDERER_ZORDER = -2;
943 /**
944  * The pressed renderer's zOrder value ccui.Button.
945  * @constant
946  * @type {number}
947  */
948 ccui.Button.PRESSED_RENDERER_ZORDER = -2;
949 /**
950  * The disabled renderer's zOrder value of ccui.Button.
951  * @constant
952  * @type {number}
953  */
954 ccui.Button.DISABLED_RENDERER_ZORDER = -2;
955 /**
956  * The title renderer's zOrder value of ccui.Button.
957  * @constant
958  * @type {number}
959  */
960 ccui.Button.TITLE_RENDERER_ZORDER = -1;
961 
962 /**
963  * the zoom action time step of ccui.Button
964  * @constant
965  * @type {number}
966  */
967 ccui.Button.ZOOM_ACTION_TIME_STEP = 0.05;
968 
969 /**
970  * @ignore
971  */
972 ccui.Button.SYSTEM = 0;
973 ccui.Button.TTF = 1;
974