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