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