1 /****************************************************************************
  2  Copyright (c) 2010-2012 cocos2d-x.org
  3  Copyright (c) 2008-2010 Ricardo Quesada
  4  Copyright (c) 2011      Zynga Inc.
  5 
  6  http://www.cocos2d-x.org
  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 /**
 29  * default size for font size
 30  * @constant
 31  * @type Number
 32  */
 33 cc.ITEM_SIZE = 32;
 34 
 35 cc._fontSize = cc.ITEM_SIZE;
 36 cc._fontName = "Arial";
 37 cc._fontNameRelease = false;
 38 
 39 /**
 40  * default tag for current item
 41  * @constant
 42  * @type Number
 43  */
 44 cc.CURRENT_ITEM = 0xc0c05001;
 45 /**
 46  * default tag for zoom action tag
 47  * @constant
 48  * @type Number
 49  */
 50 cc.ZOOM_ACTION_TAG = 0xc0c05002;
 51 /**
 52  * default tag for normal
 53  * @constant
 54  * @type Number
 55  */
 56 cc.NORMAL_TAG = 8801;
 57 
 58 /**
 59  * default selected tag
 60  * @constant
 61  * @type Number
 62  */
 63 cc.SELECTED_TAG = 8802;
 64 
 65 /**
 66  * default disabled tag
 67  * @constant
 68  * @type Number
 69  */
 70 cc.DISABLE_TAG = 8803;
 71 
 72 /**
 73  * Subclass cc.MenuItem (or any subclass) to create your custom cc.MenuItem objects.
 74  * @class
 75  * @extends cc.Node
 76  */
 77 cc.MenuItem = cc.Node.extend(/** @lends cc.MenuItem# */{
 78     _listener:null,
 79     _selector:null,
 80     _isSelected:false,
 81     _isEnabled:false,
 82 
 83     /**
 84      * MenuItem is selected
 85      * @return {Boolean}
 86      */
 87     isSelected:function () {
 88         return this._isSelected;
 89     },
 90 
 91     /**
 92      * set the target/selector of the menu item
 93      * @param {function|String} selector
 94      * @param {cc.Node} rec
 95      */
 96     setTarget:function (selector, rec) {
 97         this._listener = rec;
 98         this._selector = selector;
 99     },
100 
101     /**
102      * MenuItem is Enabled
103      * @return {Boolean}
104      */
105     isEnabled:function () {
106         return this._isEnabled;
107     },
108 
109     /**
110      * set enable value of MenuItem
111      * @param {Boolean} enable
112      */
113     setEnabled:function (enable) {
114         this._isEnabled = enable;
115     },
116 
117     /**
118      * @param {function|String} selector
119      * @param {cc.Node} rec
120      * @return {Boolean}
121      */
122     initWithCallback:function (selector, rec) {
123         this.setAnchorPoint(cc.p(0.5, 0.5));
124         this._listener = rec;
125         this._selector = selector;
126         this._isEnabled = true;
127         this._isSelected = false;
128         return true;
129     },
130 
131     /**
132      * return rect value of cc.MenuItem
133      * @return {cc.Rect}
134      */
135     rect:function () {
136         return cc.rect(this._position.x - this._contentSize.width * this._anchorPoint.x,
137             this._position.y - this._contentSize.height * this._anchorPoint.y,
138             this._contentSize.width, this._contentSize.height);
139     },
140 
141     /**
142      * same as setIsSelected(true)
143      */
144     selected:function () {
145         this._isSelected = true;
146     },
147 
148     /**
149      * same as setIsSelected(false)
150      */
151     unselected:function () {
152         this._isSelected = false;
153     },
154 
155     /**
156      * @param {function|String} selector
157      * @param {cc.Node} rec
158      */
159     setCallback:function (selector, rec) {
160         this._listener = rec;
161         this._selector = selector;
162     },
163 
164     /**
165      * call the selector with target
166      */
167     activate:function () {
168         if (this._isEnabled) {
169             if (this._listener && (typeof(this._selector) == "string")) {
170                 this._listener[this._selector](this);
171             } else if (this._listener && (typeof(this._selector) == "function")) {
172                 this._selector.call(this._listener, this);
173             } else {
174                 this._selector(this);
175             }
176         }
177     }
178 });
179 
180 /**
181  * creates an empty menu item with target and callback<br/>
182  * Not recommended to use the base class, should use more defined menu item classes
183  * @param {function|String} selector callback
184  * @param {cc.Node} rec target
185  * @return {cc.MenuItem}
186  */
187 cc.MenuItem.create = function (selector, rec) {
188     var ret = new cc.MenuItem();
189     ret.initWithCallback(rec, selector);
190     return ret;
191 };
192 
193 
194 /**
195  *  Any cc.Node that supports the cc.LabelProtocol protocol can be added.<br/>
196  * Supported nodes:<br/>
197  * - cc.BitmapFontAtlas<br/>
198  * - cc.LabelAtlas<br/>
199  * - cc.LabelTTF<br/>
200  * @class
201  * @extends cc.MenuItem
202  */
203 cc.MenuItemLabel = cc.MenuItem.extend(/** @lends cc.MenuItemLabel# */{
204 
205     /**
206      * this identifies that this object have implemented RGBAProtocol
207      * @type Boolean
208      */
209     RGBAProtocol:true,
210 
211     _disabledColor:new cc.Color3B(),
212 
213     /**
214      * @return {cc.Color3B}
215      */
216     getDisabledColor:function () {
217         return this._disabledColor;
218     },
219 
220     /**
221      * @param {cc.Color3B} color
222      */
223     setDisabledColor:function (color) {
224         this._disabledColor = color;
225     },
226     _label:null,
227 
228     /**
229      * return label of MenuItemLabel
230      * @return {cc.Node}
231      */
232     getLabel:function () {
233         return this._label;
234     },
235 
236     /**
237      * @param {cc.Node} label
238      */
239     setLabel:function (label) {
240         if (label) {
241             this.addChild(label);
242             label.setAnchorPoint(cc.p(0, 0));
243             this.setContentSize(label.getContentSize());
244         }
245 
246         if (this._label) {
247             this.removeChild(this._label, true);
248         }
249 
250         this._label = label;
251     },
252     _orginalScale:0,
253 
254     /**
255      * @param {Boolean} enabled
256      */
257     setEnabled:function (enabled) {
258         if (this._isEnabled != enabled) {
259             if (!enabled) {
260                 this._colorBackup = this._label.getColor();
261                 this._label.setColor(this._disabledColor);
262             } else {
263                 this._label.setColor(this._colorBackup);
264             }
265         }
266         this._super(enabled);
267     },
268 
269     /**
270      * @param {Number} opacity from 0-255
271      */
272     setOpacity:function (opacity) {
273         this._label.setOpacity(opacity);
274     },
275 
276     /**
277      * @return {Number}
278      */
279     getOpacity:function () {
280         return this._label.getOpacity();
281     },
282 
283     /**
284      * @param {cc.Color3B} color
285      */
286     setColor:function (color) {
287         this._label.setColor(color);
288     },
289 
290     /**
291      * @return {cc.Color3B}
292      */
293     getColor:function () {
294         return this._label.getColor();
295     },
296 
297     setOpacityModifyRGB:function (value) {
298     },
299 
300     isOpacityModifyRGB:function () {
301     },
302 
303     /**
304      * @param {cc.Node} label
305      * @param {function|String} selector
306      * @param {cc.Node} target
307      * @return {Boolean}
308      */
309     initWithLabel:function (label, selector, target) {
310         this.initWithCallback(selector, target);
311         this._originalScale = 1.0;
312         this._colorBackup = cc.white();
313         this._disabledColor = cc.c3b(126, 126, 126);
314         this.setLabel(label);
315         return true;
316     },
317 
318     /**
319      * @param {String} label
320      */
321     setString:function (label) {
322         this._label.setString(label);
323         this.setContentSize(this._label.getContentSize());
324     },
325 
326     /**
327      * activate the menu item
328      */
329     activate:function () {
330         if (this._isEnabled) {
331             this.stopAllActions();
332             this.setScale(this._originalScale);
333             this._super();
334         }
335     },
336 
337     /**
338      * menu item is selected (runs callback)
339      */
340     selected:function () {
341         if (this._isEnabled) {
342             this._super();
343 
344             var action = this.getActionByTag(cc.ZOOM_ACTION_TAG);
345             if (action) {
346                 this.stopAction(action);
347             } else {
348                 this._originalScale = this.getScale();
349             }
350 
351             var zoomAction = cc.ScaleTo.create(0.1, this._originalScale * 1.2);
352             zoomAction.setTag(cc.ZOOM_ACTION_TAG);
353             this.runAction(zoomAction);
354         }
355     },
356 
357     /**
358      * menu item goes back to unselected state
359      */
360     unselected:function () {
361         if (this._isEnabled) {
362             this._super();
363             this.stopActionByTag(cc.ZOOM_ACTION_TAG);
364             var zoomAction = cc.ScaleTo.create(0.1, this._originalScale);
365             zoomAction.setTag(cc.ZOOM_ACTION_TAG);
366             this.runAction(zoomAction);
367         }
368     }
369 });
370 
371 /**
372  * @param {cc.Node} label
373  * @param {function|String|Null} selector
374  * @param {cc.Node|Null} target
375  * @return {cc.MenuItemLabel}
376  */
377 cc.MenuItemLabel.create = function (label, selector, target) {
378     var ret = new cc.MenuItemLabel();
379     ret.initWithLabel(label, selector, target);
380     return ret;
381 };
382 
383 /**
384  * Helper class that creates a MenuItemLabel class with a LabelAtlas
385  * @class
386  * @extends cc.MenuItemLabel
387  */
388 cc.MenuItemAtlasFont = cc.MenuItemLabel.extend(/** @lends cc.MenuItemAtlasFont# */{
389 
390     /**
391      * @param {String} value
392      * @param {String} charMapFile
393      * @param {Number} itemWidth
394      * @param {Number} itemHeight
395      * @param {String} startCharMap a single character
396      * @param {function|String|Null} selector
397      * @param {cc.Node|Null} target
398      * @return {Boolean}
399      */
400     initWithString:function (value, charMapFile, itemWidth, itemHeight, startCharMap, selector, target) {
401         cc.Assert(value != null && value.length != 0, "value length must be greater than 0");
402         var label = new cc.LabelAtlas();
403         label.initWithString(value, charMapFile, itemWidth, itemHeight, startCharMap);
404         if (this.initWithLabel(label,  selector, target)) {
405             // do something ?
406         }
407         return true;
408     }
409 });
410 
411 /**
412  * create menu item from string with font
413  * @param {String} value the text to display
414  * @param {String} charMapFile the character map file
415  * @param {Number} itemWidth
416  * @param {Number} itemHeight
417  * @param {String} startCharMap a single character
418  * @param {cc.Node|Null} target
419  * @param {function|String|Null} selector
420  * @return {cc.MenuItemAtlasFont}
421  * @example
422  * // Example
423  * var item = cc.MenuItemAtlasFont.create('text to display', 'font.fnt', 12, 32, ' ')
424  *
425  * //OR
426  * var item = cc.MenuItemAtlasFont.create('text to display', 'font.fnt', 12, 32, ' ', game, game.run)
427  */
428 cc.MenuItemAtlasFont.create = function (value, charMapFile, itemWidth, itemHeight, startCharMap, target, selector) {
429     var ret = new cc.MenuItemAtlasFont();
430     ret.initWithString(value, charMapFile, itemWidth, itemHeight, startCharMap, target, selector);
431     return ret;
432 };
433 
434 
435 /**
436  * Helper class that creates a CCMenuItemLabel class with a Label
437  * @class
438  * @extends cc.MenuItemLabel
439  */
440 cc.MenuItemFont = cc.MenuItemLabel.extend(/** @lends cc.MenuItemFont# */{
441 
442     /**
443      * @param {String} value text for the menu item
444      * @param {function|String} selector
445      * @param {cc.Node} target
446      * @return {Boolean}
447      */
448     initWithString:function (value, selector, target) {
449         cc.Assert(value != null && value.length != 0, "Value length must be greater than 0");
450 
451         this._fontName = cc._fontName;
452         this._fontSize = cc._fontSize;
453 
454         var label = cc.LabelTTF.create(value, this._fontName, this._fontSize);
455         if (this.initWithLabel(label, selector, target)) {
456             // do something ?
457         }
458         return true;
459     },
460 
461     /**
462      * @param {Number} s
463      */
464     setFontSize:function (s) {
465         this._fontSize = s;
466         this._recreateLabel();
467     },
468 
469     /**
470      *
471      * @return {Number}
472      */
473     fontSize:function () {
474         return this._fontSize;
475     },
476 
477     /**
478      * @param {String} name
479      */
480     setFontName:function (name) {
481         this._fontName = name;
482         this._recreateLabel();
483     },
484 
485     /**
486      * @return {String}
487      */
488     fontName:function () {
489         return this._fontName;
490     },
491     _recreateLabel:function () {
492         var label = cc.LabelTTF.create(this._label.getString(),
493             this._fontName, this._fontSize);
494         this.setLabel(label);
495     },
496     _fontSize:0,
497     _fontName:''
498 });
499 
500 /**
501  * a shared function to set the fontSize for menuitem font
502  * @param {Number} fontSize
503  */
504 cc.MenuItemFont.setFontSize = function (fontSize) {
505     cc._fontSize = fontSize;
506 };
507 
508 /**
509  * a shared function to get the font size for menuitem font
510  * @return {Number}
511  */
512 cc.MenuItemFont.fontSize = function () {
513     return cc._fontSize;
514 };
515 
516 /**
517  * a shared function to set the fontsize for menuitem font
518  * @param name
519  */
520 cc.MenuItemFont.setFontName = function (name) {
521     if (cc._fontNameRelease) {
522         cc._fontName = '';
523     }
524     cc._fontName = name;
525     cc._fontNameRelease = true;
526 };
527 
528 /**
529  * a shared function to get the font name for menuitem font
530  * @return {String}
531  */
532 cc.MenuItemFont.fontName = function () {
533     return cc._fontName
534 };
535 
536 /**
537  * create a menu item from string
538  * @param {String} value the text to display
539  * @param {String|function|Null} selector the callback to run, either in function name or pass in the actual function
540  * @param {cc.Node|Null} target the target to run callback
541  * @return {cc.MenuItemFont}
542  * @example
543  * // Example
544  * var item = cc.MenuItemFont.create("Game start", 'start', Game)
545  * //creates a menu item from string "Game start", and when clicked, it will run Game.start()
546  *
547  * var item = cc.MenuItemFont.create("Game start", game.start, Game)//same as above
548  *
549  * var item = cc.MenuItemFont.create("i do nothing")//create a text menu item that does nothing
550  *
551  * //you can set font size and name before or after
552  * cc.MenuItemFont.setFontName('my Fancy Font');
553  * cc.MenuItemFont.setFontSize(62);
554  */
555 cc.MenuItemFont.create = function (value, selector, target) {
556     var ret = new cc.MenuItemFont();
557     ret.initWithString(value, selector, target);
558     return ret;
559 };
560 
561 
562 /**
563  * CCMenuItemSprite accepts CCNode<CCRGBAProtocol> objects as items.<br/>
564  The images has 3 different states:<br/>
565  - unselected image<br/>
566  - selected image<br/>
567  - disabled image<br/>
568  * @class
569  * @extends cc.MenuItem
570  */
571 cc.MenuItemSprite = cc.MenuItem.extend(/** @lends cc.MenuItemSprite# */{
572     /**
573      * identifies that this class implements RGBAProtocol methods
574      */
575     RGBAProtocol:true,
576     _normalImage:null,
577 
578     /**
579      * @return {cc.Node}
580      */
581     getNormalImage:function () {
582         return this._normalImage;
583     },
584 
585     /**
586      * @param {cc.Node} normalImage
587      */
588     setNormalImage:function (normalImage) {
589         if (this._normalImage == normalImage) {
590             return;
591         }
592         if (normalImage) {
593             this.addChild(normalImage, 0, cc.NORMAL_TAG);
594             normalImage.setAnchorPoint(cc.p(0, 0));
595         }
596         if (this._normalImage) {
597             this.removeChild(this._normalImage, true);
598         }
599 
600         this._normalImage = normalImage;
601         this.setContentSize(this._normalImage.getContentSize());
602         this._updateImagesVisibility();
603     },
604     _selectedImage:null,
605 
606     /**
607      * @return {cc.Node}
608      */
609     getSelectedImage:function () {
610         return this._selectedImage;
611     },
612 
613     /**
614      * @param {cc.Node} selectedImage
615      */
616     setSelectedImage:function (selectedImage) {
617         if (this._selectedImage == selectedImage)
618             return;
619 
620         if (selectedImage) {
621             this.addChild(selectedImage, 0, cc.SELECTED_TAG);
622             selectedImage.setAnchorPoint(cc.p(0, 0));
623         }
624 
625         if (this._selectedImage) {
626             this.removeChild(this._selectedImage, true);
627         }
628 
629         this._selectedImage = selectedImage;
630         this._updateImagesVisibility();
631     },
632     _disabledImage:null,
633 
634     /**
635      * @return {cc.Sprite}
636      */
637     getDisabledImage:function () {
638         return this._disabledImage;
639     },
640 
641     /**
642      * @param {cc.Sprite} disabledImage
643      */
644     setDisabledImage:function (disabledImage) {
645         if (this._disabledImage == disabledImage)
646             return;
647 
648         if (disabledImage) {
649             this.addChild(disabledImage, 0, cc.DISABLE_TAG);
650             disabledImage.setAnchorPoint(cc.p(0, 0));
651         }
652 
653         if (this._disabledImage) {
654             this.removeChild(this._disabledImage, true);
655         }
656 
657         this._disabledImage = disabledImage;
658         this._updateImagesVisibility();
659     },
660 
661     /**
662      * @param {cc.Sprite} normalSprite
663      * @param {cc.Sprite} selectedSprite
664      * @param {cc.Sprite} disabledSprite
665      * @param {function|String} selector
666      * @param {cc.Node} target
667      * @return {Boolean}
668      */
669     initWithNormalSprite:function (normalSprite, selectedSprite, disabledSprite, selector, target) {
670         this.initWithCallback(selector, target);
671         this.setNormalImage(normalSprite);
672         this.setSelectedImage(selectedSprite);
673         this.setDisabledImage(disabledSprite);
674         if (this._normalImage) {
675             this.setContentSize(this._normalImage.getContentSize());
676         }
677         return true;
678     },
679 
680     /**
681      * @param {cc.Color3B} color
682      */
683     setColor:function (color) {
684         this._normalImage.setColor(color);
685 
686         if (this._selectedImage) {
687             this._selectedImage.setColor(color);
688         }
689 
690         if (this._disabledImage) {
691             this._disabledImage.setColor(color);
692         }
693     },
694 
695     /**
696      * @return {cc.Color3B}
697      */
698     getColor:function () {
699         return this._normalImage.getColor();
700     },
701 
702     /**
703      * @param {Number} opacity 0 - 255
704      */
705     setOpacity:function (opacity) {
706         this._normalImage.setOpacity(opacity);
707 
708         if (this._selectedImage) {
709             this._selectedImage.setOpacity(opacity);
710         }
711 
712         if (this._disabledImage) {
713             this._disabledImage.setOpacity(opacity);
714         }
715     },
716 
717     /**
718      * @return {Number} opacity from 0 - 255
719      */
720     getOpacity:function () {
721         return this._normalImage.getOpacity();
722     },
723 
724     /**
725      * menu item is selected (runs callback)
726      */
727     selected:function () {
728         this._super();
729         if (this._normalImage) {
730             if (this._disabledImage) {
731                 this._disabledImage.setVisible(false);
732             }
733 
734             if (this._selectedImage) {
735                 this._normalImage.setVisible(false);
736                 this._selectedImage.setVisible(true);
737             }
738             else {
739                 this._normalImage.setVisible(true);
740             }
741         }
742     },
743 
744     /**
745      * menu item goes back to unselected state
746      */
747     unselected:function () {
748         this._super();
749 
750         if (this._normalImage) {
751             this._normalImage.setVisible(true);
752 
753             if (this._selectedImage) {
754                 this._selectedImage.setVisible(false);
755             }
756 
757             if (this._disabledImage) {
758                 this._disabledImage.setVisible(false);
759             }
760         }
761     },
762 
763     /**
764      * @param {Boolean} bEnabled
765      */
766     setEnabled:function (bEnabled) {
767         if (this._isEnabled != bEnabled) {
768             this._super(bEnabled);
769             this._updateImagesVisibility();
770         }
771     },
772 
773     setOpacityModifyRGB:function (value) {
774     },
775 
776     isOpacityModifyRGB:function () {
777         return false;
778     },
779 
780     _updateImagesVisibility:function () {
781         if (this._isEnabled) {
782             if (this._normalImage)
783                 this._normalImage.setVisible(true);
784             if (this._selectedImage)
785                 this._selectedImage.setVisible(false);
786             if (this._disabledImage)
787                 this._disabledImage.setVisible(false);
788         } else {
789             if (this._disabledImage) {
790                 if (this._normalImage)
791                     this._normalImage.setVisible(false);
792                 if (this._selectedImage)
793                     this._selectedImage.setVisible(false);
794                 if (this._disabledImage)
795                     this._disabledImage.setVisible(true);
796             } else {
797                 if (this._normalImage)
798                     this._normalImage.setVisible(true);
799                 if (this._selectedImage)
800                     this._selectedImage.setVisible(false);
801                 if (this._disabledImage)
802                     this._disabledImage.setVisible(false);
803             }
804         }
805     }
806 });
807 
808 /**
809  * create a menu item from sprite
810  * @param {Image} normal normal state image
811  * @param {Image|Null} selected selected state image
812  * @param {Image|cc.Node|Null} three disabled state image OR target node
813  * @param {String|function|cc.Node|Null} four callback function name in string or actual function, OR target Node
814  * @param {String|function|Null} five callback function name in string or actual function
815  * @return {cc.MenuItemSprite}
816  * @example
817  * // Example
818  * var item = cc.MenuItemSprite.create(normalImage)//create a menu item from a sprite with no functionality
819  *
820  * var item = cc.MenuItemSprite.create(normalImage, selectedImage)//create a menu Item, nothing will happen when clicked
821  *
822  * var item = cc.MenuItemSprite.create(normalImage, SelectedImage, disabledImage)//same above, but with disabled state image
823  *
824  * var item = cc.MenuItemSprite.create(normalImage, SelectedImage, 'callback', targetNode)//create a menu item, when clicked runs targetNode.callback()
825  *
826  * var item = cc.MenuItemSprite.create(normalImage, SelectedImage, disabledImage, targetNode.callback, targetNode)
827  * //same as above, but with disabled image, and passing in callback function
828  */
829 cc.MenuItemSprite.create = function (normalSprite, selectedSprite, three, four, five) {
830     var len = arguments.length;
831     var normalSprite = arguments[0], selectedSprite = arguments[1], disabledImage, target, callback;
832     var ret = new cc.MenuItemSprite();
833     //when you send 4 arguments, five is undefined
834     if (len == 5) {
835         disabledImage = arguments[2], callback = arguments[3], target = arguments[4];
836     } else if (len == 4 && typeof arguments[3] === "function") {
837         disabledImage = arguments[2], callback = arguments[3];
838     } else if (len == 4 && typeof arguments[2] === "function") {
839         target = arguments[3], callback = arguments[2];
840     } else if (len <= 2) {
841         disabledImage = arguments[2];
842     }
843     ret.initWithNormalSprite(normalSprite, selectedSprite, disabledImage,  callback, target);
844     return ret;
845 };
846 
847 
848 /**
849  * cc.MenuItemImage accepts images as items.<br/>
850  * The images has 3 different states:<br/>
851  * - unselected image<br/>
852  * - selected image<br/>
853  * - disabled image<br/>
854  * <br/>
855  * For best results try that all images are of the same size<br/>
856  * @class
857  * @extends cc.MenuItemSprite
858  */
859 cc.MenuItemImage = cc.MenuItemSprite.extend(/** @lends cc.MenuItemImage# */{
860     /**
861      * sets the sprite frame for the normal image
862      * @param {cc.SpriteFrame} frame
863      */
864     setNormalSpriteFrame:function (frame) {
865         this.setNormalImage(cc.Sprite.createWithSpriteFrame(frame));
866     },
867 
868     /**
869      * sets the sprite frame for the selected image
870      * @param {cc.SpriteFrame} frame
871      */
872     setSelectedSpriteFrame:function (frame) {
873         this.setSelectedImage(cc.Sprite.createWithSpriteFrame(frame));
874     },
875 
876     /**
877      * sets the sprite frame for the disabled image
878      * @param {cc.SpriteFrame} frame
879      */
880     setDisabledSpriteFrame:function (frame) {
881         this.setDisabledImage(cc.Sprite.createWithSpriteFrame(frame));
882     },
883 
884     /**
885      * @return {Boolean}
886      */
887     initWithNormalImage:function (normalImage, selectedImage, disabledImage,  selector, target) {
888         var normalSprite = null;
889         var selectedSprite = null;
890         var disabledSprite = null;
891 
892         if (normalImage) {
893             normalSprite = cc.Sprite.create(normalImage);
894         }
895         if (selectedImage) {
896             selectedSprite = cc.Sprite.create(selectedImage);
897         }
898         if (disabledImage) {
899             disabledSprite = cc.Sprite.create(disabledImage);
900         }
901         return this.initWithNormalSprite(normalSprite, selectedSprite, disabledSprite, selector, target);
902     }
903 });
904 
905 /**
906  * creates a new menu item image
907  * @param {String} normalImage file name for normal state
908  * @param {String} selectedImage image for selected state
909  * @param {String|cc.Node} three Disabled image OR target
910  * @param {String|function|Null} five callback function, either name in string, or pass the whole function
911  * * @param {cc.Node|String|function|Null} four cc.Node target to run callback when clicked OR the callback
912  * @return {cc.MenuItemImage}
913  * @example
914  * // Example
915  * var item = cc.MenuItemImage.create('normal.png', 'selected.png', gameScene, 'run')
916  * //create a dom menu item with normal and selected state, when clicked it will run the run function from gameScene object
917  *
918  * var item = cc.MenuItemImage.create('normal.png', 'selected.png', 'disabled.png',  gameScene, gameScene.run)
919  * //same as above, but pass in the actual function and disabled image
920  */
921 cc.MenuItemImage.create = function (normalImage, selectedImage, three, four, five) {
922     if (arguments.length == 0) {
923         return cc.MenuItemImage.create(null, null, null, null, null);
924     }
925     if (arguments.length == 3)  {
926         return cc.MenuItemImage.create(normalImage, selectedImage, null, three, null);
927     }
928     if (arguments.length == 4) {
929         return cc.MenuItemImage.create(normalImage, selectedImage, null, three, four);
930     }
931     var ret = new cc.MenuItemImage();
932     if (ret.initWithNormalImage(normalImage, selectedImage, three, four, five)) {
933         return ret;
934     }
935     return null;
936 };
937 
938 
939 /**
940  * A simple container class that "toggles" it's inner items<br/>
941  * The inner items can be any MenuItem
942  * @class
943  * @extends cc.MenuItem
944  */
945 cc.MenuItemToggle = cc.MenuItem.extend(/** @lends cc.MenuItemToggle# */{
946 
947     /**
948      * this identifies this class implements RGBAProtocol methods
949      */
950     RGBAProtocol:true,
951     _opacity:0,
952 
953     /**
954      * @return {Number}
955      */
956     getOpacity:function () {
957         return this._opacity;
958     },
959 
960     /**
961      * @param {Number} Opacity
962      */
963     setOpacity:function (Opacity) {
964         this._opacity = Opacity;
965         if (this._subItems && this._subItems.length > 0) {
966             for (var it = 0; it < this._subItems.length; it++) {
967                 this._subItems[it].setOpacity(Opacity);
968             }
969         }
970     },
971     _color:new cc.Color3B(),
972 
973     /**
974      * @return {cc.Color3B}
975      */
976     getColor:function () {
977         return this._color;
978     },
979 
980     /**
981      * @param {cc.Color3B} Color
982      */
983     setColor:function (Color) {
984         this._color = Color;
985         if (this._subItems && this._subItems.length > 0) {
986             for (var it = 0; it < this._subItems.length; it++) {
987                 this._subItems[it].setColor(Color);
988             }
989         }
990     },
991     _selectedIndex:0,
992 
993     /**
994      * @return {Number}
995      */
996     getSelectedIndex:function () {
997         return this._selectedIndex;
998     },
999 
1000     /**
1001      * @param {Number} SelectedIndex
1002      */
1003     setSelectedIndex:function (SelectedIndex) {
1004         if (SelectedIndex != this._selectedIndex) {
1005             this._selectedIndex = SelectedIndex;
1006             var currItem = this.getChildByTag(cc.CURRENT_ITEM);
1007             if (currItem) {
1008                 currItem.removeFromParent(false);
1009             }
1010 
1011             var item = this._subItems[this._selectedIndex];
1012             this.addChild(item, 0, cc.CURRENT_ITEM);
1013             var s = item.getContentSize();
1014             this.setContentSize(s);
1015             item.setPosition(cc.p(s.width / 2, s.height / 2));
1016         }
1017     },
1018     _subItems:[],
1019 
1020     /**
1021      * similar to get children
1022      * @return {cc.MenuItem}
1023      */
1024     getSubItems:function () {
1025         return this._subItems;
1026     },
1027 
1028     /**
1029      * @param {cc.MenuItem} SubItems
1030      */
1031     setSubItems:function (SubItems) {
1032         this._subItems = SubItems;
1033     },
1034 
1035     /**
1036      * @param {cc.MenuItem} args[0...last-2] the rest in the array are cc.MenuItems
1037      * @param {function|String} args[last-1] the second item in the args array is the callback
1038      * @param {cc.Node} args[last] the first item in the args array is a target
1039      * @return {Boolean}
1040      */
1041     initWithItems:function (args) {
1042         var l =  args.length;
1043         // passing callback.
1044         if (typeof args[args.length-2] === 'function') {
1045             this.initWithCallback( args[args.length-2], args[args.length-1] );
1046             l = l-2;
1047         } else if(typeof args[args.length-1] === 'function'){
1048             this.initWithCallback( args[args.length-1], null );
1049             l = l-1;
1050         } else {
1051             this.initWithCallback(null, null);
1052         }
1053 
1054         this._subItems = [];
1055         for (var i = 0; i < l; i++) {
1056             if (args[i]) {
1057                 this._subItems.push(args[i]);
1058             }
1059         }
1060         this._selectedIndex = cc.UINT_MAX;
1061         this.setSelectedIndex(0);
1062         return true;
1063     },
1064 
1065     /**
1066      * @param {cc.MenuItem} item
1067      */
1068     addSubItem:function (item) {
1069         this._subItems.push(item);
1070     },
1071 
1072     /**
1073      * activate the menu item
1074      */
1075     activate:function () {
1076         // update index
1077         if (this._isEnabled) {
1078             var newIndex = (this._selectedIndex + 1) % this._subItems.length;
1079             this.setSelectedIndex(newIndex);
1080         }
1081         this._super();
1082     },
1083 
1084     /**
1085      * menu item is selected (runs callback)
1086      */
1087     selected:function () {
1088         this._super();
1089         this._subItems[this._selectedIndex].selected();
1090     },
1091 
1092     /**
1093      * menu item goes back to unselected state
1094      */
1095     unselected:function () {
1096         this._super();
1097         this._subItems[this._selectedIndex].unselected();
1098     },
1099 
1100     /**
1101      * @param {Boolean} enabled
1102      */
1103     setEnabled:function (enabled) {
1104         if (this._isEnabled == enabled) {
1105             this._super(enabled);
1106 
1107             if (this._subItems && this._subItems.length > 0) {
1108                 for (var it = 0; it < this._subItems.length; it++) {
1109                     this._subItems[it].setEnabled(enabled);
1110                 }
1111             }
1112         }
1113     },
1114 
1115     /**
1116      * returns the selected item
1117      * @return {cc.MenuItem}
1118      */
1119     selectedItem:function () {
1120         return this._subItems[this._selectedIndex];
1121     },
1122 
1123     setOpacityModifyRGB:function (value) {
1124     },
1125 
1126     isOpacityModifyRGB:function () {
1127         return false;
1128     },
1129     onEnter:function () {
1130         this._super();
1131         this.setSelectedIndex(this._selectedIndex);
1132     }
1133 });
1134 
1135 /**
1136  * create a simple container class that "toggles" it's inner items<br/>
1137  * The inner items can be any MenuItem
1138  * @return {cc.MenuItemToggle}
1139  * @example
1140  * // Example
1141  *
1142  * //create a toggle item with 2 menu items (which you can then toggle between them later)
1143  * var toggler = cc.MenuItemToggle.create(this, this.callback, cc.MenuItemFont.create("On"), cc.MenuItemFont.create("Off"))
1144  * //Note: the first param is the target, the second is the callback function, afterwards, you can pass in any number of menuitems
1145  *
1146  * //if you pass only 1 variable, then it must be a cc.MenuItem
1147  * var notYetToggler = cc.MenuItemToggle.create(cc.MenuItemFont.create("On"));//it is useless right now, until you add more stuff to it
1148  * notYetToggler.addSubItem(cc.MenuItemFont.create("Off"));
1149  * //this is useful for constructing a toggler without a callback function (you wish to control the behavior from somewhere else)
1150  */
1151 cc.MenuItemToggle.create = function (/*Multiple arguments follow*/) {
1152     var ret = new cc.MenuItemToggle();
1153     ret.initWithItems(arguments);
1154     return ret;
1155 };
1156