1 /**
  2  * CCControlButton.m
  3  *
  4  * Copyright (c) 2008-2010 Ricardo Quesada
  5  * Copyright (c) 2011-2012 cocos2d-x.org
  6  * Copyright (c) 2013-2014 Chukong Technologies Inc.
  7  * Copyright 2011 Yannick Loriot.
  8  * http://yannickloriot.com
  9  *
 10  * Permission is hereby granted, free of charge, to any person obtaining a copy
 11  * of this software and associated documentation files (the "Software"), to deal
 12  * in the Software without restriction, including without limitation the rights
 13  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 14  * copies of the Software, and to permit persons to whom the Software is
 15  * furnished to do so, subject to the following conditions:
 16  *
 17  * The above copyright notice and this permission notice shall be included in
 18  * all copies or substantial portions of the Software.
 19  *
 20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 21  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 22  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 23  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 24  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 25  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 26  * THE SOFTWARE.
 27  */
 28 
 29 /**
 30  * @ignore
 31  */
 32 cc.CONTROL_ZOOM_ACTION_TAG = 0xCCCB0001;
 33 
 34 /**
 35  * CCControlButton: Button control for Cocos2D.
 36  * @class
 37  * @extends cc.Control
 38  *
 39  * @property {Boolean}  adjustBackgroundImage   - Indicate whether the background image will be adjusted
 40  * @property {Boolean}  zoomOnTouchDown         - Indicate whether the button will be zoomed while touch down
 41  * @property {cc.Size}  preferredSize           - The preferred size of the control button
 42  * @property {Boolean}  labelAnchor             - The anchor point for the label of the control button
 43  */
 44 cc.ControlButton = cc.Control.extend(/** @lends cc.ControlButton# */{
 45     _doesAdjustBackgroundImage: false,
 46     zoomOnTouchDown: false,
 47     _preferredSize: null,
 48     _labelAnchorPoint: null,
 49     _currentTitle: null,
 50     _currentTitleColor: null,
 51     _titleLabel: null,
 52     _backgroundSprite: null,
 53     _opacity: 0,
 54     _isPushed: false,
 55     _titleDispatchTable: null,
 56     _titleColorDispatchTable: null,
 57     _titleLabelDispatchTable: null,
 58     _backgroundSpriteDispatchTable: null,
 59     _parentInited: false,
 60 
 61     _marginV: 0,
 62     _marginH: 0,
 63     _className: "ControlButton",
 64 
 65     ctor: function (label, backgroundSprite, fontSize) {
 66         cc.Control.prototype.ctor.call(this);
 67         this._preferredSize = cc.size(0, 0);
 68         this._labelAnchorPoint = cc.p(0, 0);
 69         this._currentTitle = "";
 70         this._currentTitleColor = cc.color.WHITE;
 71         this._titleDispatchTable = {};
 72         this._titleColorDispatchTable = {};
 73         this._titleLabelDispatchTable = {};
 74         this._backgroundSpriteDispatchTable = {};
 75 
 76         if(fontSize != undefined)
 77             this.initWithTitleAndFontNameAndFontSize(label, backgroundSprite, fontSize);
 78         else if(backgroundSprite != undefined)
 79             this.initWithLabelAndBackgroundSprite(label, backgroundSprite);
 80         else if(label != undefined)
 81             this.initWithBackgroundSprite(label);
 82         else
 83             this.init();
 84     },
 85 
 86     init: function () {
 87         return this.initWithLabelAndBackgroundSprite(new cc.LabelTTF("", "Arial", 12), new cc.Scale9Sprite());
 88     },
 89 
 90     needsLayout: function () {
 91         if (!this._parentInited) {
 92             return;
 93         }
 94         // Hide the background and the label
 95         if (this._titleLabel)
 96             this._titleLabel.setVisible(false);
 97         if (this._backgroundSprite)
 98             this._backgroundSprite.setVisible(false);
 99 
100         // Update anchor of all labels
101         this.setLabelAnchorPoint(this._labelAnchorPoint);
102 
103         // Update the label to match with the current state
104         //CC_SAFE_RELEASE(this._currentTitle)
105         var locState = this._state;
106 
107         this._currentTitle = this.getTitleForState(locState);
108         this._currentTitleColor = this.getTitleColorForState(locState);
109         this._titleLabel = this.getTitleLabelForState(locState);
110 
111         var label = this._titleLabel;
112         if (label && label.setString)
113             label.setString(this._currentTitle);
114         if (label)
115             label.setColor(this._currentTitleColor);
116 
117         var locContentSize = this.getContentSize();
118         if (label)
119             label.setPosition(locContentSize.width / 2, locContentSize.height / 2);
120 
121         // Update the background sprite
122         this._backgroundSprite = this.getBackgroundSpriteForState(locState);
123         var locBackgroundSprite = this._backgroundSprite;
124         if (locBackgroundSprite)
125             locBackgroundSprite.setPosition(locContentSize.width / 2, locContentSize.height / 2);
126 
127         // Get the title label size
128         var titleLabelSize = cc.size(0, 0);
129         if (label) {
130             var boundingBox = label.getBoundingBox();
131             titleLabelSize.width = boundingBox.width;
132             titleLabelSize.height = boundingBox.height;
133         }
134         // Adjust the background image if necessary
135         if (this._doesAdjustBackgroundImage) {
136             // Add the margins
137             if (locBackgroundSprite)
138                 locBackgroundSprite.setContentSize(titleLabelSize.width + this._marginH * 2, titleLabelSize.height + this._marginV * 2);
139         } else {
140             //TODO: should this also have margins if one of the preferred sizes is relaxed?
141             if (locBackgroundSprite) {
142                 var preferredSize = locBackgroundSprite.getPreferredSize();
143                 preferredSize = cc.size(preferredSize.width, preferredSize.height);
144                 if (preferredSize.width <= 0)
145                     preferredSize.width = titleLabelSize.width;
146                 if (preferredSize.height <= 0)
147                     preferredSize.height = titleLabelSize.height;
148 
149                 locBackgroundSprite.setContentSize(preferredSize);
150             }
151         }
152 
153         // Set the content size
154         var rectTitle = label ? label.getBoundingBox() : cc.rect(0, 0, 0, 0);
155         var rectBackground = locBackgroundSprite ? locBackgroundSprite.getBoundingBox() : cc.rect(0, 0, 0, 0);
156         var maxRect = cc.rectUnion(rectTitle, rectBackground);
157         this.setContentSize(maxRect.width, maxRect.height);
158         locContentSize = this.getContentSize();
159         if (label) {
160             label.setPosition(locContentSize.width / 2, locContentSize.height / 2);
161             label.setVisible(true);
162         }
163         if (locBackgroundSprite) {
164             locBackgroundSprite.setPosition(locContentSize.width / 2, locContentSize.height / 2);
165             locBackgroundSprite.setVisible(true);
166         }
167     },
168 
169     initWithLabelAndBackgroundSprite: function (label, backgroundSprite) {
170         if (!label)
171             throw new Error("cc.ControlButton.initWithLabelAndBackgroundSprite(): label should be non-null");
172         if (!backgroundSprite)
173             throw new Error("cc.ControlButton.initWithLabelAndBackgroundSprite(): backgroundSprite should be non-null");
174         if (cc.Control.prototype.init.call(this, true)) {
175             this._parentInited = true;
176 
177             // Initialize the button state tables
178             this._titleDispatchTable = {};
179             this._titleColorDispatchTable = {};
180             this._titleLabelDispatchTable = {};
181             this._backgroundSpriteDispatchTable = {};
182 
183             this._isPushed = false;
184             this.zoomOnTouchDown = true;
185 
186             this._currentTitle = null;
187 
188             // Adjust the background image by default
189             this.setAdjustBackgroundImage(true);
190             this.setPreferredSize(cc.size(0, 0));
191 
192             // Zooming button by default
193             this.zoomOnTouchDown = true;
194 
195             // Set the default anchor point
196             this.ignoreAnchorPointForPosition(false);
197             this.setAnchorPoint(0.5, 0.5);
198 
199             // Set the nodes
200             this._titleLabel = label;
201             this._backgroundSprite = backgroundSprite;
202 
203             // Set the default color and opacity
204             this.setOpacity(255);
205             this.setOpacityModifyRGB(true);
206 
207             // Initialize the dispatch table
208             var tempString = label.getString();
209             //tempString.autorelease();
210             this.setTitleForState(tempString, cc.CONTROL_STATE_NORMAL);
211             this.setTitleColorForState(label.getColor(), cc.CONTROL_STATE_NORMAL);
212             this.setTitleLabelForState(label, cc.CONTROL_STATE_NORMAL);
213             this.setBackgroundSpriteForState(backgroundSprite, cc.CONTROL_STATE_NORMAL);
214 
215             this._state = cc.CONTROL_STATE_NORMAL;
216 
217             //default margins
218             this._marginH = 24;
219             this._marginV = 12;
220 
221             this._labelAnchorPoint = cc.p(0.5, 0.5);
222 
223             this.setPreferredSize(cc.size(0, 0));
224 
225             // Layout update
226             this.needsLayout();
227             return true;
228         }//couldn't init the CCControl
229         else
230             return false;
231     },
232 
233     initWithTitleAndFontNameAndFontSize: function (title, fontName, fontSize) {
234         var label = new cc.LabelTTF(title, fontName, fontSize);
235         return this.initWithLabelAndBackgroundSprite(label, new cc.Scale9Sprite());
236     },
237 
238     initWithBackgroundSprite: function (sprite) {
239         var label = new cc.LabelTTF("", "Arial", 30);//
240         return this.initWithLabelAndBackgroundSprite(label, sprite);
241     },
242 
243     /**
244      * Adjust the background image. YES by default. If the property is set to NO, the background will use the preferred size of the background image.
245      * @return {Boolean}
246      */
247     doesAdjustBackgroundImage: function () {
248         return this._doesAdjustBackgroundImage;
249     },
250 
251     setAdjustBackgroundImage: function (adjustBackgroundImage) {
252         this._doesAdjustBackgroundImage = adjustBackgroundImage;
253         this.needsLayout();
254     },
255 
256     /** Adjust the button zooming on touchdown. Default value is YES. */
257     getZoomOnTouchDown: function () {
258         return this.zoomOnTouchDown;
259     },
260 
261     setZoomOnTouchDown: function (zoomOnTouchDown) {
262         return this.zoomOnTouchDown = zoomOnTouchDown;
263     },
264 
265     /** The preferred size of the button, if label is larger it will be expanded. */
266     getPreferredSize: function () {
267         return this._preferredSize;
268     },
269 
270     setPreferredSize: function (size) {
271         if (size.width === 0 && size.height === 0) {
272             this._doesAdjustBackgroundImage = true;
273         } else {
274             this._doesAdjustBackgroundImage = false;
275             var locTable = this._backgroundSpriteDispatchTable;
276             for (var itemKey in locTable)
277                 locTable[itemKey].setPreferredSize(size);
278         }
279         this._preferredSize = size;
280         this.needsLayout();
281     },
282 
283     getLabelAnchorPoint: function () {
284         return this._labelAnchorPoint;
285     },
286     setLabelAnchorPoint: function (labelAnchorPoint) {
287         this._labelAnchorPoint = labelAnchorPoint;
288         if (this._titleLabel)
289             this._titleLabel.setAnchorPoint(labelAnchorPoint);
290     },
291 
292     /**
293      * The current title that is displayed on the button.
294      * @return {string}
295      */
296     _getCurrentTitle: function () {
297         return this._currentTitle;
298     },
299 
300     /** The current color used to display the title. */
301     _getCurrentTitleColor: function () {
302         return this._currentTitleColor;
303     },
304 
305     /* Override setter to affect a background sprite too */
306     getOpacity: function () {
307         return this._opacity;
308     },
309 
310     setOpacity: function (opacity) {
311         // XXX fixed me if not correct
312         cc.Control.prototype.setOpacity.call(this, opacity);
313         /*this._opacity = opacity;
314          var controlChildren = this.getChildren();
315          for (var i = 0; i < controlChildren.length; i++) {
316          var selChild = controlChildren[i];
317          if (selChild)
318          selChild.setOpacity(opacity);
319          }*/
320         var locTable = this._backgroundSpriteDispatchTable;
321         for (var itemKey in locTable)
322             locTable[itemKey].setOpacity(opacity);
323     },
324 
325     setColor: function (color) {
326         cc.Control.prototype.setColor.call(this, color);
327         var locTable = this._backgroundSpriteDispatchTable;
328         for (var key in locTable)
329             locTable[key].setColor(color);
330     },
331 
332     getColor: function () {
333         var locRealColor = this._realColor;
334         return cc.color(locRealColor.r, locRealColor.g, locRealColor.b, locRealColor.a);
335     },
336 
337 
338     /** Flag to know if the button is currently pushed.  */
339     isPushed: function () {
340         return this._isPushed;
341     },
342 
343     /* Define the button margin for Top/Bottom edge */
344     _getVerticalMargin: function () {
345         return this._marginV;
346     },
347     /* Define the button margin for Left/Right edge */
348     _getHorizontalOrigin: function () {
349         return this._marginH;
350     },
351 
352     /**
353      * set the margins at once (so we only have to do one call of needsLayout)
354      * @param {Number} marginH
355      * @param {Number} marginV
356      */
357     setMargins: function (marginH, marginV) {
358         this._marginV = marginV;
359         this._marginH = marginH;
360         this.needsLayout();
361     },
362 
363     setEnabled: function (enabled) {
364         cc.Control.prototype.setEnabled.call(this, enabled);
365         this.needsLayout();
366     },
367     setSelected: function (enabled) {
368         cc.Control.prototype.setSelected.call(this, enabled);
369         this.needsLayout();
370     },
371 
372     setHighlighted: function (enabled) {
373         this._state = enabled ? cc.CONTROL_STATE_HIGHLIGHTED : cc.CONTROL_STATE_NORMAL;
374 
375         cc.Control.prototype.setHighlighted.call(this, enabled);
376         var action = this.getActionByTag(cc.CONTROL_ZOOM_ACTION_TAG);
377         if (action)
378             this.stopAction(action);
379 
380         //this.needsLayout();// needn't
381         if (this.zoomOnTouchDown) {
382             var scaleValue = (this.isHighlighted() && this.isEnabled() && !this.isSelected()) ? 1.1 : 1.0;
383             var zoomAction = cc.scaleTo(0.05, scaleValue);
384             zoomAction.setTag(cc.CONTROL_ZOOM_ACTION_TAG);
385             this.runAction(zoomAction);
386         }
387     },
388 
389     onTouchBegan: function (touch, event) {
390         if (!this.isTouchInside(touch) || !this.isEnabled() || !this.isVisible() || !this.hasVisibleParents())
391             return false;
392 
393         this._isPushed = true;
394         this.setHighlighted(true);
395         this.sendActionsForControlEvents(cc.CONTROL_EVENT_TOUCH_DOWN);
396         return true;
397     },
398 
399     onTouchMoved: function (touch, event) {
400         if (!this._enabled || !this._isPushed || this._selected) {
401             if (this._highlighted)
402                 this.setHighlighted(false);
403             return;
404         }
405 
406         var isTouchMoveInside = this.isTouchInside(touch);
407         if (isTouchMoveInside && !this._highlighted) {
408             this.setHighlighted(true);
409             this.sendActionsForControlEvents(cc.CONTROL_EVENT_TOUCH_DRAG_ENTER);
410         } else if (isTouchMoveInside && this._highlighted) {
411             this.sendActionsForControlEvents(cc.CONTROL_EVENT_TOUCH_DRAG_INSIDE);
412         } else if (!isTouchMoveInside && this._highlighted) {
413             this.setHighlighted(false);
414             this.sendActionsForControlEvents(cc.CONTROL_EVENT_TOUCH_DRAG_EXIT);
415         } else if (!isTouchMoveInside && !this._highlighted) {
416             this.sendActionsForControlEvents(cc.CONTROL_EVENT_TOUCH_DRAG_OUTSIDE);
417         }
418     },
419     onTouchEnded: function (touch, event) {
420         this._isPushed = false;
421         this.setHighlighted(false);
422 
423         if (this.isTouchInside(touch)) {
424             this.sendActionsForControlEvents(cc.CONTROL_EVENT_TOUCH_UP_INSIDE);
425         } else {
426             this.sendActionsForControlEvents(cc.CONTROL_EVENT_TOUCH_UP_OUTSIDE);
427         }
428     },
429 
430     onTouchCancelled: function (touch, event) {
431         this._isPushed = false;
432         this.setHighlighted(false);
433         this.sendActionsForControlEvents(cc.CONTROL_EVENT_TOUCH_CANCEL);
434     },
435 
436     /**
437      * Returns the title used for a state.
438      *
439      * @param {Number} state The state that uses the title. Possible values are described in "CCControlState".
440      * @return {string} The title for the specified state.
441      */
442     getTitleForState: function (state) {
443         var locTable = this._titleDispatchTable;
444         if (locTable) {
445             if (locTable[state])
446                 return locTable[state];
447             return locTable[cc.CONTROL_STATE_NORMAL];
448         }
449         return "";
450     },
451 
452     /**
453      * <p>
454      * Sets the title string to use for the specified state.                                                  <br/>
455      * If a property is not specified for a state, the default is to use the CCButtonStateNormal value.
456      * </p>
457      * @param {string} title The title string to use for the specified state.
458      * @param {Number} state The state that uses the specified title. The values are described in "CCControlState".
459      */
460     setTitleForState: function (title, state) {
461         this._titleDispatchTable[state] = title || "";
462 
463         // If the current state if equal to the given state we update the layout
464         if (this.getState() === state)
465             this.needsLayout();
466     },
467 
468     /**
469      * Returns the title color used for a state.
470      *
471      * @param {Number} state The state that uses the specified color. The values are described in "CCControlState".
472      * @return {cc.Color} The color of the title for the specified state.
473      */
474     getTitleColorForState: function (state) {
475         var colorObject = this._titleColorDispatchTable[state];
476         if (colorObject)
477             return colorObject;
478         colorObject = this._titleColorDispatchTable[cc.CONTROL_STATE_NORMAL];
479         if (colorObject)
480             return colorObject;
481         return cc.color.WHITE;
482     },
483 
484     /**
485      * Sets the color of the title to use for the specified state.
486      *
487      * @param {cc.Color} color The color of the title to use for the specified state.
488      * @param {Number} state The state that uses the specified color. The values are described in "CCControlState".
489      */
490     setTitleColorForState: function (color, state) {
491         //ccColor3B* colorValue=&color;
492         this._titleColorDispatchTable[state] = color;
493 
494         // If the current state if equal to the given state we update the layout
495         if (this.getState() === state)
496             this.needsLayout();
497     },
498 
499     /**
500      * Returns the title label used for a state.
501      *
502      * @param state The state that uses the title label. Possible values are described in "CCControlState".
503      * @return {cc.Node} the title label used for a state.
504      */
505     getTitleLabelForState: function (state) {
506         var locTable = this._titleLabelDispatchTable;
507         if (locTable[state])
508             return locTable[state];
509 
510         return locTable[cc.CONTROL_STATE_NORMAL];
511     },
512 
513     /**
514      * <p>Sets the title label to use for the specified state.                                          <br/>
515      * If a property is not specified for a state, the default is to use the CCButtonStateNormal value. </p>
516      *
517      * @param {cc.Node} titleLabel The title label to use for the specified state.
518      * @param {Number} state The state that uses the specified title. The values are described in "CCControlState".
519      */
520     setTitleLabelForState: function (titleLabel, state) {
521         var locTable = this._titleLabelDispatchTable;
522         if (locTable[state]) {
523             var previousLabel = locTable[state];
524             if (previousLabel)
525                 this.removeChild(previousLabel, true);
526         }
527 
528         locTable[state] = titleLabel;
529         titleLabel.setVisible(false);
530         titleLabel.setAnchorPoint(0.5, 0.5);
531         this.addChild(titleLabel, 1);
532 
533         // If the current state if equal to the given state we update the layout
534         if (this.getState() === state)
535             this.needsLayout();
536     },
537 
538     /**
539      * Sets the title TTF filename to use for the specified state.
540      * @param {string} fntFile
541      * @param {Number} state
542      */
543     setTitleTTFForState: function (fntFile, state) {
544         var title = this.getTitleForState(state);
545         if (!title)
546             title = "";
547         this.setTitleLabelForState(new cc.LabelTTF(title, fntFile, 12), state);
548     },
549 
550     /**
551      * return the title TTF filename to use for the specified state.
552      * @param {Number} state
553      * @returns {string}
554      */
555     getTitleTTFForState: function (state) {
556         var labelTTF = this.getTitleLabelForState(state);
557         if ((labelTTF != null) && (labelTTF instanceof  cc.LabelTTF)) {
558             return labelTTF.getFontName();
559         } else {
560             return "";
561         }
562     },
563 
564     /**
565      * @param {Number} size
566      * @param {Number} state
567      */
568     setTitleTTFSizeForState: function (size, state) {
569         var labelTTF = this.getTitleLabelForState(state);
570         if ((labelTTF != null) && (labelTTF instanceof  cc.LabelTTF)) {
571             labelTTF.setFontSize(size);
572         }
573     },
574 
575     /**
576      * return the font size of LabelTTF to use for the specified state
577      * @param {Number} state
578      * @returns {Number}
579      */
580     getTitleTTFSizeForState: function (state) {
581         var labelTTF = this.getTitleLabelForState(state);
582         if ((labelTTF != null) && (labelTTF instanceof  cc.LabelTTF)) {
583             return labelTTF.getFontSize();
584         }
585         return 0;
586     },
587 
588     /**
589      * Sets the font of the label, changes the label to a CCLabelBMFont if necessary.
590      * @param {string} fntFile The name of the font to change to
591      * @param {Number} state The state that uses the specified fntFile. The values are described in "CCControlState".
592      */
593     setTitleBMFontForState: function (fntFile, state) {
594         var title = this.getTitleForState(state);
595         if (!title)
596             title = "";
597         this.setTitleLabelForState(new cc.LabelBMFont(title, fntFile), state);
598     },
599 
600     getTitleBMFontForState: function (state) {
601         var labelBMFont = this.getTitleLabelForState(state);
602         if ((labelBMFont != null) && (labelBMFont instanceof  cc.LabelBMFont)) {
603             return labelBMFont.getFntFile();
604         }
605         return "";
606     },
607 
608     /**
609      * Returns the background sprite used for a state.
610      *
611      * @param {Number} state The state that uses the background sprite. Possible values are described in "CCControlState".
612      */
613     getBackgroundSpriteForState: function (state) {
614         var locTable = this._backgroundSpriteDispatchTable;
615         if (locTable[state]) {
616             return locTable[state];
617         }
618         return locTable[cc.CONTROL_STATE_NORMAL];
619     },
620 
621     /**
622      * Sets the background sprite to use for the specified button state.
623      *
624      * @param {Scale9Sprite} sprite The background sprite to use for the specified state.
625      * @param {Number} state The state that uses the specified image. The values are described in "CCControlState".
626      */
627     setBackgroundSpriteForState: function (sprite, state) {
628         var locTable = this._backgroundSpriteDispatchTable;
629         if (locTable[state]) {
630             var previousSprite = locTable[state];
631             if (previousSprite)
632                 this.removeChild(previousSprite, true);
633         }
634 
635         locTable[state] = sprite;
636         sprite.setVisible(false);
637         sprite.setAnchorPoint(0.5, 0.5);
638         this.addChild(sprite);
639 
640         var locPreferredSize = this._preferredSize;
641         if (locPreferredSize.width !== 0 || locPreferredSize.height !== 0) {
642             sprite.setPreferredSize(locPreferredSize);
643         }
644 
645         // If the current state if equal to the given state we update the layout
646         if (this._state === state)
647             this.needsLayout();
648     },
649 
650     /**
651      * Sets the background spriteFrame to use for the specified button state.
652      *
653      * @param {SpriteFrame} spriteFrame The background spriteFrame to use for the specified state.
654      * @param {Number} state The state that uses the specified image. The values are described in "CCControlState".
655      */
656     setBackgroundSpriteFrameForState: function (spriteFrame, state) {
657         var sprite = cc.Scale9Sprite.createWithSpriteFrame(spriteFrame);
658         this.setBackgroundSpriteForState(sprite, state);
659     }
660 });
661 
662 var _p = cc.ControlButton.prototype;
663 
664 // Extended properties
665 /** @expose */
666 _p.adjustBackground;
667 cc.defineGetterSetter(_p, "adjustBackground", _p.getAdjustBackgroundImage, _p.setAdjustBackgroundImage);
668 /** @expose */
669 _p.preferredSize;
670 cc.defineGetterSetter(_p, "preferredSize", _p.getPreferredSize, _p.setPreferredSize);
671 /** @expose */
672 _p.labelAnchor;
673 cc.defineGetterSetter(_p, "labelAnchor", _p.getLabelAnchorPoint, _p.setLabelAnchorPoint);
674 
675 _p = null;
676 
677 /**
678  * @deprecated
679  * @param label
680  * @param backgroundSprite
681  * @param fontSize
682  * @returns {ControlButton}
683  */
684 cc.ControlButton.create = function (label, backgroundSprite, fontSize) {
685     return new cc.ControlButton(label, backgroundSprite, fontSize);
686 };
687 
688 
689