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