1 /****************************************************************************
  2  Copyright (c) 2008-2010 Ricardo Quesada
  3  Copyright (c) 2011-2012 cocos2d-x.org
  4  Copyright (c) 2013-2014 Chukong Technologies 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  * The Spacer class
 29  * @class
 30  * @extends cc.Layer
 31  */
 32 cc.Spacer = cc.Layer.extend(/** @lends cc.Spacer */{});
 33 
 34 cc.Spacer.verticalSpacer = function (space) {
 35     var pRet = new cc.Spacer();
 36     pRet.init();
 37     pRet.setContentSize(0, space);
 38     return pRet;
 39 };
 40 
 41 cc.Spacer.horizontalSpacer = function (space) {
 42     var pRet = new cc.Spacer();
 43     pRet.init();
 44     pRet.setContentSize(space, 0);
 45     return pRet;
 46 };
 47 
 48 /**
 49  * MenuPassive: The menu passive ui component
 50  * @class
 51  * @extend cc.Layer
 52  */
 53 cc.MenuPassive = cc.Layer.extend(/** @lends cc.MenuPassive# */{
 54     RGBAProtocol:true,
 55 
 56     _color:null,
 57     _opacity:0,
 58     _className:"MenuPassive",
 59 
 60     ctor:function () {
 61     },
 62 
 63     /** Color: conforms with CCRGBAProtocol protocol */
 64     getColor:function () {
 65         var locColor = this._color;
 66         return cc.color(locColor.r, locColor.g, locColor.b, locColor.a);
 67     },
 68     setColor:function (color) {
 69         var locColor = this._color;
 70         locColor.r = color.r;
 71         locColor.g = color.g;
 72         locColor.b = color.b;
 73 
 74         if (this._children && this._children.length > 0) {
 75             for (var i = 0; i < this._children.length; i++) {
 76                 if (this._children[i] && this._children[i].RGBAProtocol) {
 77                     this._children[i].setColor(color);
 78                 }
 79             }
 80         }
 81         if (color.a !== undefined && !color.a_undefined) {
 82             this.setOpacity(color.a);
 83         }
 84     },
 85 
 86     /** Opacity: conforms with CCRGBAProtocol protocol */
 87     getOpacity:function () {
 88         return this._opacity;
 89     },
 90 
 91     setOpacity:function (opacity) {
 92         this._opacity = opacity;
 93 
 94         if (this._children && this._children.length > 0) {
 95             for (var i = 0; i < this._children.length; i++) {
 96                 if (this._children[i] && this._children[i].RGBAProtocol) {
 97                     this._children[i].setOpacity(opacity);
 98                 }
 99             }
100         }
101 
102         this._color.a = opacity;
103     },
104 
105     /** initializes a CCMenu with it's items */
106     initWithItems:function (item, args) {
107         if (this.init()) {
108             //this.m_bIsTouchEnabled = false;
109 
110             // menu in the center of the screen
111             var winSize = cc.director.getWinSize();
112 
113             // Set the default anchor point
114             this.ignoreAnchorPointForPosition(true);
115             this.setAnchorPoint(0.5, 0.5);
116             this.setContentSize(winSize);
117 
118             this.setPosition(winSize.width / 2, winSize.height / 2);
119             var z = 0;
120 
121             if (item) {
122                 this.addChild(item, z);
123                 for (var i = 0; i < args.length; i++) {
124                     if (args[i]) {
125                         z++;
126                         this.addChild(args[i], z);
127                     }
128                 }
129             }
130             return true;
131         }
132         return false;
133     },
134 
135     /** align items vertically */
136     alignItemsVertically:function () {
137         this.alignItemsVerticallyWithPadding(cc.DEFAULT_PADDING);
138     },
139 
140     /** align items vertically with padding
141      @since v0.7.2
142      */
143     alignItemsVerticallyWithPadding:function (padding) {
144         var height = -padding;
145 
146         var i;
147         if (this._children && this._children.length > 0) {
148             for (i = 0; i < this._children.length; i++) {
149                 if (this._children[i]) {
150                     height += this._children[i].getContentSize().height * this._children[i].getScaleY() + padding;
151                 }
152             }
153         }
154 
155         var width = 0;
156         var y = height / 2.0;
157         if (this._children && this._children.length > 0) {
158             for (i = 0; i < this._children.length; i++) {
159                 if (this._children[i]) {
160                     width = Math.max(width, this._children[i].getContentSize().width);
161                     this._children[i].setPosition(0, y - this._children[i].getContentSize().height * this._children[i].getScaleY() / 2.0);
162                     y -= this._children[i].getContentSize().height * this._children[i].getScaleY() + padding;
163                 }
164             }
165         }
166         this.setContentSize(width, height);
167     },
168 
169     /** align items horizontally */
170     alignItemsHorizontally:function () {
171         this.alignItemsHorizontallyWithPadding(cc.DEFAULT_PADDING);
172     },
173 
174     /** align items horizontally with padding
175      @since v0.7.2
176      */
177     alignItemsHorizontallyWithPadding:function (padding) {
178         var width = -padding;
179         var i;
180         if (this._children && this._children.length > 0) {
181             for (i = 0; i < this._children.length; i++) {
182                 if (this._children[i]) {
183                     width += this._children[i].getContentSize().width * this._children[i].getScaleX() + padding;
184                 }
185             }
186         }
187 
188         var height = 0;
189         var x = -width / 2.0;
190         if (this._children && this._children.length > 0) {
191             for (i = 0; i < this._children.length; i++) {
192                 if (this._children[i]) {
193                     height = Math.max(height, this._children[i].getContentSize().height);
194                     this._children[i].setPosition(x + this._children[i].getContentSize().width * this._children[i].getScaleX() / 2.0, 0);
195                     x += this._children[i].getContentSize().width * this._children[i].getScaleX() + padding;
196                 }
197             }
198         }
199         this.setContentSize(width, height);
200     },
201 
202     /** align items in rows of columns */
203     alignItemsInColumns:function (columns) {
204         var rows = [];
205         var i;
206         for (i = 1; i < arguments.length; i++) {
207             rows.push(arguments[i]);
208         }
209 
210         var height = -5;
211         var row = 0;
212         var rowHeight = 0;
213         var columnsOccupied = 0;
214         var rowColumns;
215 
216         var tmp;
217         if (this._children && this._children.length > 0) {
218             for (i = 0; i < this._children.length; i++) {
219                 if (this._children[i]) {
220                     if(row >= rows.length){
221                         cc.log("cc.MenuPassive.alignItemsInColumns(): invalid row index");
222                         continue;
223                     }
224 
225                     rowColumns = rows[row];
226                     // can not have zero columns on a row
227                     if(!rowColumns) {
228                         cc.log("cc.MenuPassive.alignItemsInColumns(): can not have zero columns on a row");
229                         continue;
230                     }
231 
232                     tmp = this._children[i].getContentSize().height;
233                     rowHeight = 0 | ((rowHeight >= tmp || (tmp == null)) ? rowHeight : tmp);
234 
235                     ++columnsOccupied;
236                     if (columnsOccupied >= rowColumns) {
237                         height += rowHeight + 5;
238 
239                         columnsOccupied = 0;
240                         rowHeight = 0;
241                         ++row;
242                     }
243                 }
244             }
245         }
246 
247         // check if too many rows/columns for available menu items
248         //cc.assert(!columnsOccupied, "");            //?
249 
250         var winSize = cc.director.getWinSize();
251 
252         row = 0;
253         rowHeight = 0;
254         rowColumns = 0;
255         var w = 0.0;
256         var x = 0.0;
257         var y = (height / 2);
258         if (this._children && this._children.length > 0) {
259             for (i = 0; i < this._children.length; i++) {
260                 if (this._children[i]) {
261                     if (rowColumns == 0) {
262                         rowColumns = rows[row];
263                         w = winSize.width / (1 + rowColumns);
264                         x = w;
265                     }
266 
267                     tmp = this._children[i].getContentSize().height;
268                     rowHeight = 0 | ((rowHeight >= tmp || (tmp == null)) ? rowHeight : tmp);
269 
270                     this._children[i].setPosition(x - winSize.width / 2,
271                         y - this._children[i].getContentSize().height / 2);
272 
273                     x += w;
274                     ++columnsOccupied;
275 
276                     if (columnsOccupied >= rowColumns) {
277                         y -= rowHeight + 5;
278 
279                         columnsOccupied = 0;
280                         rowColumns = 0;
281                         rowHeight = 0;
282                         ++row;
283                     }
284                 }
285             }
286         }
287     },
288 
289     /** align items in columns of rows */
290     alignItemsInRows:function (rows) {
291         var columns = [];
292         var i;
293         for (i = 1; i < arguments.length; i++) {
294             columns.push(arguments[i]);
295         }
296 
297         var columnWidths = [];
298         var columnHeights = [];
299 
300         var width = -10;
301         var columnHeight = -5;
302         var column = 0;
303         var columnWidth = 0;
304         var rowsOccupied = 0;
305         var columnRows;
306 
307         var tmp;
308         if (this._children && this._children.length > 0) {
309             for (i = 0; i < this._children.length; i++) {
310                 if (this._children[i]) {
311                     // check if too many menu items for the amount of rows/columns
312                     if(column >= columns.length){
313                         cc.log("cc.MenuPassive.alignItemsInRows(): invalid row index");
314                         continue;
315                     }
316 
317                     columnRows = columns[column];
318                     // can't have zero rows on a column
319                     if(!columnRows) {
320                         cc.log("cc.MenuPassive.alignItemsInColumns(): can't have zero rows on a column");
321                         continue;
322                     }
323 
324                     // columnWidth = fmaxf(columnWidth, [item contentSize].width);
325                     tmp = this._children[i].getContentSize().width;
326                     columnWidth = 0 | ((columnWidth >= tmp || (tmp == null)) ? columnWidth : tmp);
327 
328                     columnHeight += 0 | (this._children[i].getContentSize().height + 5);
329                     ++rowsOccupied;
330 
331                     if (rowsOccupied >= columnRows) {
332                         columnWidths.push(columnWidth);
333                         columnHeights.push(columnHeight);
334                         width += columnWidth + 10;
335 
336                         rowsOccupied = 0;
337                         columnWidth = 0;
338                         columnHeight = -5;
339                         ++column;
340                     }
341                 }
342             }
343         }
344 
345         // check if too many rows/columns for available menu items.
346         //cc.assert(!rowsOccupied, "");      //?
347 
348         var winSize = cc.director.getWinSize();
349 
350         column = 0;
351         columnWidth = 0;
352         columnRows = null;
353         var x = (-width / 2);
354         var y = 0.0;
355         if (this._children && this._children.length > 0) {
356             for (i = 0; i < this._children.length; i++) {
357                 if (this._children[i]) {
358                     if (columnRows == null) {
359                         columnRows = columns[column];
360                         y = columnHeights[column];
361                     }
362 
363                     // columnWidth = fmaxf(columnWidth, [item contentSize].width);
364                     tmp = this._children[i].getContentSize().width;
365                     columnWidth = 0 | ((columnWidth >= tmp || (tmp == null)) ? columnWidth : tmp);
366 
367                     this._children[i].setPosition(x + columnWidths[column] / 2, y - winSize.height / 2);
368 
369                     y -= this._children[i].getContentSize().height + 10;
370                     ++rowsOccupied;
371 
372                     if (rowsOccupied >= columnRows) {
373                         x += columnWidth + 5;
374                         rowsOccupied = 0;
375                         columnRows = 0;
376                         columnWidth = 0;
377                         ++column;
378                     }
379                 }
380             }
381         }
382     },
383 
384     //RGBA protocol
385     setOpacityModifyRGB:function (bValue) {
386     },
387     isOpacityModifyRGB:function () {
388         return false;
389     }
390 });
391 
392 /** creates an empty CCMenu */
393 cc.MenuPassive.create = function (item) {
394     if (!item) {
395         item = null;
396     }
397 
398     var argArr = [];
399     for (var i = 1; i < arguments.length; i++) {
400         argArr.push(arguments[i]);
401     }
402 
403     var pRet = new cc.MenuPassive();
404     if (pRet && pRet.initWithItems(item, argArr)) {
405         return pRet;
406     }
407     return null;
408 };
409 
410 /** creates a CCMenu with it's item, then use addChild() to add
411  * other items. It is used for script, it can't init with undetermined
412  * number of variables.
413  */
414 cc.MenuPassive.createWithItem = function (item) {
415     return cc.MenuPassive.create(item, null);
416 };