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._normalTextureSize = this._buttonNormalRenderer.getContentSize();
278         this._updateChildrenDisplayedRGBA();
279         if (this._unifySize){
280             if (this._scale9Enabled){
281                 normalRenderer.setCapInsets(this._capInsetsNormal);
282                 this._updateContentSizeWithTextureSize(this._getNormalSize());
283             }
284         }else
285             this._updateContentSizeWithTextureSize(this._normalTextureSize);
286 
287         this._normalTextureLoaded = true;
288         this._normalTextureAdaptDirty = true;
289         this._findLayout();
290     },
291 
292     /**
293      * Load selected state texture for button.
294      * @param {String} selected selected state of texture's filename.
295      * @param {ccui.Widget.LOCAL_TEXTURE|ccui.Widget.PLIST_TEXTURE} texType
296      */
297     loadTexturePressed: function (selected, texType) {
298         if (!selected)
299             return;
300         texType = texType || ccui.Widget.LOCAL_TEXTURE;
301         this._clickedFileName = selected;
302         this._pressedTexType = texType;
303 
304         var self = this;
305         var clickedRenderer = this._buttonClickedRenderer;
306         if(!clickedRenderer._textureLoaded){
307             clickedRenderer.addEventListener("load", function(){
308                 self.loadTexturePressed(self._clickedFileName, self._pressedTexType);
309             });
310         }
311 
312         switch (this._pressedTexType) {
313             case ccui.Widget.LOCAL_TEXTURE:
314                 //SetTexture cannot load resource
315                 clickedRenderer.initWithFile(selected);
316                 break;
317             case ccui.Widget.PLIST_TEXTURE:
318                 //SetTexture cannot load resource
319                 clickedRenderer.initWithSpriteFrameName(selected);
320                 break;
321             default:
322                 break;
323         }
324 
325         if (this._scale9Enabled)
326             clickedRenderer.setCapInsets(this._capInsetsPressed);
327 
328         this._pressedTextureSize = this._buttonClickedRenderer.getContentSize();
329         this._updateChildrenDisplayedRGBA();
330 
331         this._pressedTextureLoaded = true;
332         this._pressedTextureAdaptDirty = true;
333         this._findLayout();
334     },
335 
336     /**
337      * Load dark state texture for button.
338      * @param {String} disabled disabled state of texture's filename.
339      * @param {ccui.Widget.LOCAL_TEXTURE|ccui.Widget.PLIST_TEXTURE} texType
340      */
341     loadTextureDisabled: function (disabled, texType) {
342         if (!disabled)
343             return;
344 
345         texType = texType || ccui.Widget.LOCAL_TEXTURE;
346         this._disabledFileName = disabled;
347         this._disabledTexType = texType;
348 
349         var self = this;
350         var disabledRenderer = this._buttonDisableRenderer;
351         if(!disabledRenderer._textureLoaded){
352             disabledRenderer.addEventListener("load", function() {
353                 self.loadTextureDisabled(self._disabledFileName, self._disabledTexType);
354             });
355         }
356 
357         switch (this._disabledTexType) {
358             case ccui.Widget.LOCAL_TEXTURE:
359                 //SetTexture cannot load resource
360                 disabledRenderer.initWithFile(disabled);
361                 break;
362             case ccui.Widget.PLIST_TEXTURE:
363                 //SetTexture cannot load resource
364                 disabledRenderer.initWithSpriteFrameName(disabled);
365                 break;
366             default:
367                 break;
368         }
369 
370         if (this._scale9Enabled)
371             disabledRenderer.setCapInsets(this._capInsetsDisabled);
372 
373         this._disabledTextureSize = this._buttonDisableRenderer.getContentSize();
374         this._updateChildrenDisplayedRGBA();
375 
376         this._disabledTextureLoaded = true;
377         this._disabledTextureAdaptDirty = true;
378         this._findLayout();
379     },
380 
381     /**
382      * Sets capinsets for button, if button is using scale9 renderer.
383      * @param {cc.Rect} capInsets
384      */
385     setCapInsets: function (capInsets) {
386         this.setCapInsetsNormalRenderer(capInsets);
387         this.setCapInsetsPressedRenderer(capInsets);
388         this.setCapInsetsDisabledRenderer(capInsets);
389     },
390 
391     /**
392      * Sets capinsets for button, if button is using scale9 renderer.
393      * @param {cc.Rect} capInsets
394      */
395     setCapInsetsNormalRenderer: function (capInsets) {
396         if(!capInsets)
397             return;
398 
399         var x = capInsets.x, y = capInsets.y;
400         var width = capInsets.width, height = capInsets.height;
401         if (this._normalTextureSize.width < width){
402             x = 0;
403             width = 0;
404         }
405         if (this._normalTextureSize.height < height){
406             y = 0;
407             height = 0;
408         }
409 
410         var locInsets = this._capInsetsNormal;
411         locInsets.x = x;
412         locInsets.y = y;
413         locInsets.width = width;
414         locInsets.height = height;
415 
416         if (!this._scale9Enabled)
417             return;
418         this._buttonNormalRenderer.setCapInsets(locInsets);
419     },
420 
421     /**
422      *  Returns normal renderer cap insets.
423      * @returns {cc.Rect}
424      */
425     getCapInsetsNormalRenderer:function(){
426         return cc.rect(this._capInsetsNormal);
427     },
428 
429     /**
430      * Sets capinsets for button, if button is using scale9 renderer.
431      * @param {cc.Rect} capInsets
432      */
433     setCapInsetsPressedRenderer: function (capInsets) {
434         if(!capInsets || !this._scale9Enabled)
435             return;
436 
437         var x = capInsets.x, y = capInsets.y;
438         var width = capInsets.width, height = capInsets.height;
439 
440         if (this._pressedTextureSize.width < width) {
441             x = 0;
442             width = 0;
443         }
444         if (this._pressedTextureSize.height < height) {
445             y = 0;
446             height = 0;
447         }
448 
449         var locInsets = this._capInsetsPressed;
450         locInsets.x = x;
451         locInsets.y = y;
452         locInsets.width = width;
453         locInsets.height = height;
454 
455         this._buttonClickedRenderer.setCapInsets(locInsets);
456     },
457 
458     /**
459      *  Returns pressed renderer cap insets.
460      * @returns {cc.Rect}
461      */
462     getCapInsetsPressedRenderer: function () {
463         return cc.rect(this._capInsetsPressed);
464     },
465 
466     /**
467      * Sets capinsets for button, if button is using scale9 renderer.
468      * @param {cc.Rect} capInsets
469      */
470     setCapInsetsDisabledRenderer: function (capInsets) {
471         if(!capInsets || !this._scale9Enabled)
472             return;
473 
474         var x = capInsets.x, y = capInsets.y;
475         var width = capInsets.width, height = capInsets.height;
476 
477         if (this._disabledTextureSize.width < width) {
478             x = 0;
479             width = 0;
480         }
481         if (this._disabledTextureSize.height < height) {
482             y = 0;
483             height = 0;
484         }
485 
486         var locInsets = this._capInsetsDisabled;
487         locInsets.x = x;
488         locInsets.y = y;
489         locInsets.width = width;
490         locInsets.height = height;
491 
492         this._buttonDisableRenderer.setCapInsets(locInsets);
493     },
494 
495     /**
496      * Returns disable renderer cap insets.
497      * @returns {cc.Rect}
498      */
499     getCapInsetsDisabledRenderer: function () {
500         return cc.rect(this._capInsetsDisabled);
501     },
502 
503     _onPressStateChangedToNormal: function () {
504         this._buttonNormalRenderer.setVisible(true);
505         this._buttonClickedRenderer.setVisible(false);
506         this._buttonDisableRenderer.setVisible(false);
507         if (this._scale9Enabled)
508             this._buttonNormalRenderer.setState( ccui.Scale9Sprite.state.NORMAL);
509         if (this._pressedTextureLoaded) {
510             if (this.pressedActionEnabled){
511                 this._buttonNormalRenderer.stopAllActions();
512                 this._buttonClickedRenderer.stopAllActions();
513                 //var zoomAction = cc.scaleTo(ccui.Button.ZOOM_ACTION_TIME_STEP, this._normalTextureScaleXInSize, this._normalTextureScaleYInSize);
514                 //fixme: the zoomAction will run in the next frame which will cause the _buttonNormalRenderer to a wrong scale
515                 //this._buttonNormalRenderer.runAction(zoomAction);
516                 this._buttonNormalRenderer.setScale(this._normalTextureScaleXInSize, this._normalTextureScaleYInSize);
517                 this._buttonClickedRenderer.setScale(this._pressedTextureScaleXInSize, this._pressedTextureScaleYInSize);
518 
519                 this._titleRenderer.stopAllActions();
520                 if (this._unifySize){
521                     var zoomTitleAction = cc.scaleTo(ccui.Button.ZOOM_ACTION_TIME_STEP, 1, 1);
522                     this._titleRenderer.runAction(zoomTitleAction);
523                 }else{
524                     this._titleRenderer.setScaleX(1);
525                     this._titleRenderer.setScaleY(1);
526                 }
527             }
528         } else {
529             this._buttonNormalRenderer.stopAllActions();
530             this._buttonNormalRenderer.setScale(this._normalTextureScaleXInSize, this._normalTextureScaleYInSize);
531 
532             this._titleRenderer.stopAllActions();
533             if (this._scale9Enabled)
534                 this._buttonNormalRenderer.setColor(cc.color.WHITE);
535 
536             this._titleRenderer.setScaleX(1);
537             this._titleRenderer.setScaleY(1);
538         }
539     },
540 
541     _onPressStateChangedToPressed: function () {
542         var locNormalRenderer = this._buttonNormalRenderer;
543         if (this._scale9Enabled)
544             locNormalRenderer.setState(ccui.Scale9Sprite.state.NORMAL);
545 
546         if (this._pressedTextureLoaded) {
547             locNormalRenderer.setVisible(false);
548             this._buttonClickedRenderer.setVisible(true);
549             this._buttonDisableRenderer.setVisible(false);
550             if (this.pressedActionEnabled) {
551                 locNormalRenderer.stopAllActions();
552                 this._buttonClickedRenderer.stopAllActions();
553                 var zoomAction = cc.scaleTo(ccui.Button.ZOOM_ACTION_TIME_STEP, this._pressedTextureScaleXInSize + this._zoomScale,
554                         this._pressedTextureScaleYInSize + this._zoomScale);
555                 this._buttonClickedRenderer.runAction(zoomAction);
556                 locNormalRenderer.setScale(this._pressedTextureScaleXInSize + this._zoomScale, this._pressedTextureScaleYInSize + this._zoomScale);
557 
558                 this._titleRenderer.stopAllActions();
559                 this._titleRenderer.runAction(cc.scaleTo(ccui.Button.ZOOM_ACTION_TIME_STEP, 1 + this._zoomScale, 1 + this._zoomScale));
560             }
561         } else {
562             locNormalRenderer.setVisible(true);
563             this._buttonClickedRenderer.setVisible(true);
564             this._buttonDisableRenderer.setVisible(false);
565             locNormalRenderer.stopAllActions();
566             locNormalRenderer.setScale(this._normalTextureScaleXInSize + this._zoomScale, this._normalTextureScaleYInSize + this._zoomScale);
567 
568             this._titleRenderer.stopAllActions();
569             this._titleRenderer.setScaleX(1 + this._zoomScale);
570             this._titleRenderer.setScaleY(1 + this._zoomScale);
571         }
572     },
573 
574     _onPressStateChangedToDisabled: function () {
575         //if disable resource is null
576         if (!this._disabledTextureLoaded){
577             if (this._normalTextureLoaded && this._scale9Enabled)
578                 this._buttonNormalRenderer.setState(ccui.Scale9Sprite.state.GRAY);
579         }else{
580             this._buttonNormalRenderer.setVisible(false);
581             this._buttonDisableRenderer.setVisible(true);
582         }
583 
584         this._buttonClickedRenderer.setVisible(false);
585         this._buttonNormalRenderer.setScale(this._normalTextureScaleXInSize, this._normalTextureScaleYInSize);
586         this._buttonClickedRenderer.setScale(this._pressedTextureScaleXInSize, this._pressedTextureScaleYInSize);
587     },
588 
589     _updateContentSize: function(){
590         if (this._unifySize){
591             if (this._scale9Enabled)
592                 ccui.ProtectedNode.setContentSize(this._customSize);
593             else{
594                 var s = this._getNormalSize();
595                 ccui.ProtectedNode.setContentSize(s);
596             }
597             this._onSizeChanged();
598             return;
599         }
600 
601         if (this._ignoreSize)
602             this.setContentSize(this.getVirtualRendererSize());
603     },
604 
605     _updateTexturesRGBA: function(){
606         this._buttonNormalRenderer.setColor(this.getColor());
607         this._buttonClickedRenderer.setColor(this.getColor());
608         this._buttonDisableRenderer.setColor(this.getColor());
609 
610         this._buttonNormalRenderer.setOpacity(this.getOpacity());
611         this._buttonClickedRenderer.setOpacity(this.getOpacity());
612         this._buttonDisableRenderer.setOpacity(this.getOpacity());
613     },
614 
615     _onSizeChanged: function () {
616         ccui.Widget.prototype._onSizeChanged.call(this);
617         this._updateTitleLocation();
618         this._normalTextureAdaptDirty = true;
619         this._pressedTextureAdaptDirty = true;
620         this._disabledTextureAdaptDirty = true;
621     },
622 
623     /**
624      * Gets the Virtual Renderer of widget.
625      * @returns {cc.Node}
626      */
627     getVirtualRenderer: function () {
628         if (this._bright) {
629             switch (this._brightStyle) {
630                 case ccui.Widget.BRIGHT_STYLE_NORMAL:
631                     return this._buttonNormalRenderer;
632                 case ccui.Widget.BRIGHT_STYLE_HIGH_LIGHT:
633                     return this._buttonClickedRenderer;
634                 default:
635                     return null;
636             }
637         } else
638             return this._buttonDisableRenderer;
639     },
640 
641     _normalTextureScaleChangedWithSize: function () {
642         if(this._ignoreSize && !this._unifySize){
643             if(!this._scale9Enabled){
644                 this._buttonNormalRenderer.setScale(1);
645                 this._normalTextureScaleXInSize = this._normalTextureScaleYInSize = 1;
646             }
647         }else{
648             if (this._scale9Enabled){
649                 this._buttonNormalRenderer.setPreferredSize(this._contentSize);
650                 this._normalTextureScaleXInSize = this._normalTextureScaleYInSize = 1;
651                 this._buttonNormalRenderer.setScale(this._normalTextureScaleXInSize, this._normalTextureScaleYInSize);
652             }else{
653                 var textureSize = this._normalTextureSize;
654                 if (textureSize.width <= 0 || textureSize.height <= 0)
655                 {
656                     this._buttonNormalRenderer.setScale(1);
657                     return;
658                 }
659                 var scaleX = this._contentSize.width / textureSize.width;
660                 var scaleY = this._contentSize.height / textureSize.height;
661                 this._buttonNormalRenderer.setScaleX(scaleX);
662                 this._buttonNormalRenderer.setScaleY(scaleY);
663                 this._normalTextureScaleXInSize = scaleX;
664                 this._normalTextureScaleYInSize = scaleY;
665             }
666         }
667         this._buttonNormalRenderer.setPosition(this._contentSize.width / 2, this._contentSize.height / 2);
668     },
669 
670     _pressedTextureScaleChangedWithSize: function () {
671         if (this._ignoreSize && !this._unifySize) {
672             if (!this._scale9Enabled) {
673                 this._buttonClickedRenderer.setScale(1);
674                 this._pressedTextureScaleXInSize = this._pressedTextureScaleYInSize = 1;
675             }
676         } else {
677             if (this._scale9Enabled) {
678                 this._buttonClickedRenderer.setPreferredSize(this._contentSize);
679                 this._pressedTextureScaleXInSize = this._pressedTextureScaleYInSize = 1;
680                 this._buttonClickedRenderer.setScale(this._pressedTextureScaleXInSize, this._pressedTextureScaleYInSize);
681             } else {
682                 var textureSize = this._pressedTextureSize;
683                 if (textureSize.width <= 0 || textureSize.height <= 0) {
684                     this._buttonClickedRenderer.setScale(1);
685                     return;
686                 }
687                 var scaleX = this._contentSize.width / textureSize.width;
688                 var scaleY = this._contentSize.height / textureSize.height;
689                 this._buttonClickedRenderer.setScaleX(scaleX);
690                 this._buttonClickedRenderer.setScaleY(scaleY);
691                 this._pressedTextureScaleXInSize = scaleX;
692                 this._pressedTextureScaleYInSize = scaleY;
693             }
694         }
695         this._buttonClickedRenderer.setPosition(this._contentSize.width / 2, this._contentSize.height / 2);
696     },
697 
698     _disabledTextureScaleChangedWithSize: function () {
699         if(this._ignoreSize && !this._unifySize){
700             if (this._scale9Enabled)
701                 this._buttonDisableRenderer.setScale(1);
702         }else {
703             if (this._scale9Enabled){
704                 this._buttonDisableRenderer.setScale(1);
705                 this._buttonDisableRenderer.setPreferredSize(this._contentSize);
706             }else{
707                 var textureSize = this._disabledTextureSize;
708                 if (textureSize.width <= 0 || textureSize.height <= 0) {
709                     this._buttonDisableRenderer.setScale(1);
710                     return;
711                 }
712                 var scaleX = this._contentSize.width / textureSize.width;
713                 var scaleY = this._contentSize.height / textureSize.height;
714                 this._buttonDisableRenderer.setScaleX(scaleX);
715                 this._buttonDisableRenderer.setScaleY(scaleY);
716             }
717         }
718         this._buttonDisableRenderer.setPosition(this._contentSize.width / 2, this._contentSize.height / 2);
719     },
720 
721     _adaptRenderers: function(){
722         if (this._normalTextureAdaptDirty) {
723             this._normalTextureScaleChangedWithSize();
724             this._normalTextureAdaptDirty = false;
725         }
726         if (this._pressedTextureAdaptDirty) {
727             this._pressedTextureScaleChangedWithSize();
728             this._pressedTextureAdaptDirty = false;
729         }
730         if (this._disabledTextureAdaptDirty) {
731             this._disabledTextureScaleChangedWithSize();
732             this._disabledTextureAdaptDirty = false;
733         }
734     },
735 
736     _updateTitleLocation: function(){
737         this._titleRenderer.setPosition(this._contentSize.width * 0.5, this._contentSize.height * 0.5);
738     },
739 
740     /**
741      * Changes if button can be clicked zoom effect.
742      * @param {Boolean} enabled
743      */
744     setPressedActionEnabled: function (enabled) {
745         this.pressedActionEnabled = enabled;
746     },
747 
748     /**
749      * Sets title text to ccui.Button
750      * @param {String} text
751      */
752     setTitleText: function (text) {
753         if(text === this.getTitleText())
754             return;
755         this._titleRenderer.setString(text);
756         if (this._ignoreSize){
757             var s = this.getVirtualRendererSize();
758             this.setContentSize(s);
759         }else{
760             this._titleRenderer._renderCmd._updateTTF();
761         }
762     },
763 
764     /**
765      * Returns title text of ccui.Button
766      * @returns {String} text
767      */
768     getTitleText: function () {
769         return this._titleRenderer.getString();
770     },
771 
772     /**
773      * Sets title color to ccui.Button.
774      * @param {cc.Color} color
775      */
776     setTitleColor: function (color) {
777         this._titleRenderer.setFontFillColor(color);
778     },
779 
780     /**
781      * Returns title color of ccui.Button
782      * @returns {cc.Color}
783      */
784     getTitleColor: function () {
785         return this._titleRenderer._getFillStyle();
786     },
787 
788     /**
789      * Sets title fontSize to ccui.Button
790      * @param {cc.Size} size
791      */
792     setTitleFontSize: function (size) {
793         this._titleRenderer.setFontSize(size);
794         this._fontSize = size;
795     },
796 
797     /**
798      * Returns title fontSize of ccui.Button.
799      * @returns {Number}
800      */
801     getTitleFontSize: function () {
802         return this._titleRenderer.getFontSize();
803     },
804 
805     /**
806      * When user pressed the button, the button will zoom to a scale.
807      * The final scale of the button  equals (button original scale + _zoomScale)
808      * @since v3.2
809      * @param scale
810      */
811     setZoomScale: function(scale){
812         this._zoomScale = scale;
813     },
814 
815     /**
816      * Returns a zoom scale
817      * @since v3.2
818      * @returns {number}
819      */
820     getZoomScale: function(){
821         return this._zoomScale;
822     },
823 
824     /**
825      * Returns the normalize of texture size
826      * @since v3.3
827      * @returns {cc.Size}
828      */
829     getNormalTextureSize: function(){
830         return this._normalTextureSize;
831     },
832 
833     /**
834      * Sets title fontName to ccui.Button.
835      * @param {String} fontName
836      */
837     setTitleFontName: function (fontName) {
838         this._titleRenderer.setFontName(fontName);
839         this._fontName = fontName;
840     },
841 
842     /**
843      * Get the title renderer.
844      * title ttf object.
845      * @returns {cc.LabelTTF}
846      */
847     getTitleRenderer: function(){
848         return this._titleRenderer;
849     },
850 
851     /**
852      * Gets title fontName of ccui.Button.
853      * @returns {String}
854      */
855     getTitleFontName: function () {
856         return this._titleRenderer.getFontName();
857     },
858 
859     _setTitleFont: function (font) {
860         this._titleRenderer.font = font;
861     },
862     _getTitleFont: function () {
863         return this._titleRenderer.font;
864     },
865 
866     /**
867      * Returns the "class name" of widget.
868      * @override
869      * @returns {string}
870      */
871     getDescription: function () {
872         return "Button";
873     },
874 
875     _createCloneInstance: function () {
876         return new ccui.Button();
877     },
878 
879     _copySpecialProperties: function (uiButton) {
880         this._prevIgnoreSize = uiButton._prevIgnoreSize;
881         this.setScale9Enabled(uiButton._scale9Enabled);
882         this.loadTextureNormal(uiButton._normalFileName, uiButton._normalTexType);
883         this.loadTexturePressed(uiButton._clickedFileName, uiButton._pressedTexType);
884         this.loadTextureDisabled(uiButton._disabledFileName, uiButton._disabledTexType);
885         this.setCapInsetsNormalRenderer(uiButton._capInsetsNormal);
886         this.setCapInsetsPressedRenderer(uiButton._capInsetsPressed);
887         this.setCapInsetsDisabledRenderer(uiButton._capInsetsDisabled);
888         this.setTitleText(uiButton.getTitleText());
889         this.setTitleFontName(uiButton.getTitleFontName());
890         this.setTitleFontSize(uiButton.getTitleFontSize());
891         this.setTitleColor(uiButton.getTitleColor());
892         this.setPressedActionEnabled(uiButton.pressedActionEnabled);
893         this.setZoomScale(uiButton._zoomScale);
894     },
895 
896     setColor: function(color){
897         cc.ProtectedNode.prototype.setColor.call(this, color);
898         this._updateTexturesRGBA();
899     },
900 
901     _getNormalSize: function(){
902         var titleSize;
903         if (this._titleRenderer !== null)
904             titleSize = this._titleRenderer.getContentSize();
905 
906         var imageSize;
907         if (this._buttonNormalRenderer !== null)
908             imageSize = this._buttonNormalRenderer.getContentSize();
909         var width = titleSize.width > imageSize.width ? titleSize.width : imageSize.width;
910         var height = titleSize.height > imageSize.height ? titleSize.height : imageSize.height;
911 
912         return cc.size(width,height);
913     }
914 });
915 
916 var _p = ccui.Button.prototype;
917 
918 // Extended properties
919 /** @expose */
920 _p.titleText;
921 cc.defineGetterSetter(_p, "titleText", _p.getTitleText, _p.setTitleText);
922 /** @expose */
923 _p.titleFont;
924 cc.defineGetterSetter(_p, "titleFont", _p._getTitleFont, _p._setTitleFont);
925 /** @expose */
926 _p.titleFontSize;
927 cc.defineGetterSetter(_p, "titleFontSize", _p.getTitleFontSize, _p.setTitleFontSize);
928 /** @expose */
929 _p.titleFontName;
930 cc.defineGetterSetter(_p, "titleFontName", _p.getTitleFontName, _p.setTitleFontName);
931 /** @expose */
932 _p.titleColor;
933 cc.defineGetterSetter(_p, "titleColor", _p.getTitleColor, _p.setTitleColor);
934 
935 _p = null;
936 
937 /**
938  * allocates and initializes a UIButton.
939  * @deprecated since v3.0, please use new ccui.Button() instead.
940  * @param {string} [normalImage]    normal state texture name
941  * @param {string} [selectedImage]  selected state texture name
942  * @param {string} [disableImage]   disabled state texture name
943  * @param {string} [texType]
944  * @return {ccui.Button}
945  */
946 ccui.Button.create = function (normalImage, selectedImage, disableImage, texType) {
947     return new ccui.Button(normalImage, selectedImage, disableImage, texType);
948 };
949 
950 // Constants
951 /**
952  * The normal renderer's zOrder value of ccui.Button.
953  * @constant
954  * @type {number}
955  */
956 ccui.Button.NORMAL_RENDERER_ZORDER = -2;
957 /**
958  * The pressed renderer's zOrder value ccui.Button.
959  * @constant
960  * @type {number}
961  */
962 ccui.Button.PRESSED_RENDERER_ZORDER = -2;
963 /**
964  * The disabled renderer's zOrder value of ccui.Button.
965  * @constant
966  * @type {number}
967  */
968 ccui.Button.DISABLED_RENDERER_ZORDER = -2;
969 /**
970  * The title renderer's zOrder value of ccui.Button.
971  * @constant
972  * @type {number}
973  */
974 ccui.Button.TITLE_RENDERER_ZORDER = -1;
975 
976 /**
977  * the zoom action time step of ccui.Button
978  * @constant
979  * @type {number}
980  */
981 ccui.Button.ZOOM_ACTION_TIME_STEP = 0.05;
982 
983 /**
984  * @ignore
985  */
986 ccui.Button.SYSTEM = 0;
987 ccui.Button.TTF = 1;
988