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