1 /**************************************************************************** 2 Copyright (c) 2013 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 * listView event type 27 * @type {Object} 28 */ 29 ccs.ListViewEventType = { 30 listViewOnselectedItem: 0 31 }; 32 33 /** 34 * listView gravity 35 * @type {Object} 36 */ 37 ccs.ListViewGravity = { 38 left: 0, 39 right: 1, 40 centerHorizontal: 2, 41 top: 3, 42 bottom: 4, 43 centerVertical: 5 44 }; 45 46 /** 47 * Base class for ccs.ListView 48 * @class 49 * @extends ccs.ScrollView 50 */ 51 ccs.ListView = ccs.ScrollView.extend({ 52 _model: null, 53 _items: null, 54 _gravity: null, 55 _itemsMargin: 0, 56 _listViewEventListener: null, 57 _listViewEventSelector: null, 58 _curSelectedIndex: 0, 59 _refreshViewDirty: true, 60 ctor: function () { 61 ccs.ScrollView.prototype.ctor.call(this); 62 this._model = null; 63 this._items = []; 64 this._gravity = ccs.ListViewGravity.centerHorizontal; 65 this._itemsMargin = 0; 66 this._listViewEventListener = null; 67 this._listViewEventSelector = null; 68 this._curSelectedIndex = 0; 69 this._refreshViewDirty = true; 70 }, 71 72 init: function () { 73 if (ccs.ScrollView.prototype.init.call(this)) { 74 this._items = []; 75 this.setLayoutType(ccs.LayoutType.linearVertical); 76 return true; 77 } 78 return false; 79 }, 80 81 /** 82 * Sets a item model for listview. A model will be cloned for adding default item. 83 * @param {ccs.Widget} model 84 */ 85 setItemModel: function (model) { 86 if (!model) { 87 return; 88 } 89 this._model = model; 90 }, 91 92 updateInnerContainerSize: function () { 93 switch (this._direction) { 94 case ccs.ScrollViewDir.vertical: 95 var length = this._items.length; 96 var totalHeight = (length - 1) * this._itemsMargin; 97 for (var i = 0; i < length; i++) { 98 var item = this._items[i]; 99 totalHeight += item.getSize().height; 100 } 101 var finalWidth = this._size.width; 102 var finalHeight = totalHeight; 103 this.setInnerContainerSize(cc.size(finalWidth, finalHeight)); 104 break; 105 case ccs.ScrollViewDir.horizontal: 106 var length = this._items.length; 107 var totalWidth = (length - 1) * this._itemsMargin; 108 for (var i = 0; i < length; i++) { 109 var item = this._items[i]; 110 totalWidth += item.getSize().width; 111 } 112 var finalWidth = totalWidth; 113 var finalHeight = this._size.height; 114 this.setInnerContainerSize(cc.size(finalWidth, finalHeight)); 115 break; 116 default: 117 break; 118 } 119 }, 120 121 remedyLayoutParameter: function (item) { 122 if (!item) { 123 return; 124 } 125 switch (this._direction) { 126 case ccs.ScrollViewDir.vertical: 127 var llp = item.getLayoutParameter(ccs.LayoutParameterType.linear); 128 if (!llp) { 129 var defaultLp = ccs.LinearLayoutParameter.create(); 130 switch (this._gravity) { 131 case ccs.ListViewGravity.left: 132 defaultLp.setGravity(ccs.LinearGravity.left); 133 break; 134 case ccs.ListViewGravity.right: 135 defaultLp.setGravity(ccs.LinearGravity.right); 136 break; 137 case ccs.ListViewGravity.centerHorizontal: 138 defaultLp.setGravity(ccs.LinearGravity.centerHorizontal); 139 break; 140 default: 141 break; 142 } 143 if (this.getIndex(item) == 0) { 144 defaultLp.setMargin(ccs.MarginZero()); 145 } 146 else { 147 defaultLp.setMargin(new ccs.Margin(0.0, this._itemsMargin, 0.0, 0.0)); 148 } 149 item.setLayoutParameter(defaultLp); 150 } 151 else { 152 if (this.getIndex(item) == 0) { 153 llp.setMargin(ccs.MarginZero()); 154 } 155 else { 156 llp.setMargin(new ccs.Margin(0, this._itemsMargin, 0, 0)); 157 } 158 switch (this._gravity) { 159 case ccs.ListViewGravity.left: 160 llp.setGravity(ccs.LinearGravity.left); 161 break; 162 case ccs.ListViewGravity.right: 163 llp.setGravity(ccs.LinearGravity.right); 164 break; 165 case ccs.ListViewGravity.centerHorizontal: 166 llp.setGravity(ccs.LinearGravity.centerHorizontal); 167 break; 168 default: 169 break; 170 } 171 } 172 break; 173 case ccs.ScrollViewDir.horizontal: 174 var llp = item.getLayoutParameter(ccs.LayoutParameterType.linear); 175 if (!llp) { 176 var defaultLp = ccs.LinearLayoutParameter.create(); 177 switch (this._gravity) { 178 case ccs.ListViewGravity.top: 179 defaultLp.setGravity(ccs.LinearGravity.top); 180 break; 181 case ccs.ListViewGravity.bottom: 182 defaultLp.setGravity(ccs.LinearGravity.bottom); 183 break; 184 case ccs.ListViewGravity.centerVertical: 185 defaultLp.setGravity(ccs.LinearGravity.centerVertical); 186 break; 187 default: 188 break; 189 } 190 if (this.getIndex(item) == 0) { 191 defaultLp.setMargin(ccs.MarginZero()); 192 } 193 else { 194 defaultLp.setMargin(new ccs.Margin(this._itemsMargin, 0.0, 0.0, 0.0)); 195 } 196 item.setLayoutParameter(defaultLp); 197 } 198 else { 199 if (this.getIndex(item) == 0) { 200 llp.setMargin(ccs.MarginZero()); 201 } 202 else { 203 llp.setMargin(new ccs.Margin(this._itemsMargin, 0.0, 0.0, 0.0)); 204 } 205 switch (this._gravity) { 206 case ccs.ListViewGravity.top: 207 llp.setGravity(ccs.LinearGravity.top); 208 break; 209 case ccs.ListViewGravity.bottom: 210 llp.setGravity(ccs.LinearGravity.bottom); 211 break; 212 case ccs.ListViewGravity.centerVertical: 213 llp.setGravity(ccs.LinearGravity.centerVertical); 214 break; 215 default: 216 break; 217 } 218 } 219 break; 220 default: 221 break; 222 } 223 }, 224 225 /** 226 * Push back a default item(create by a cloned model) into listview. 227 */ 228 pushBackDefaultItem: function () { 229 if (!this._model) { 230 return; 231 } 232 var newItem = this._model.clone(); 233 this._items.push(newItem); 234 this.remedyLayoutParameter(newItem); 235 this.addChild(newItem); 236 this._refreshViewDirty = true; 237 }, 238 239 /** 240 * Insert a default item(create by a cloned model) into listview. 241 * @param {Number} index 242 */ 243 insertDefaultItem: function (index) { 244 if (!this._model) { 245 return; 246 } 247 var newItem = this._model.clone(); 248 cc.ArrayAppendObjectToIndex(this._items, newItem, index); 249 this.remedyLayoutParameter(newItem); 250 this.addChild(newItem); 251 this._refreshViewDirty = true; 252 }, 253 254 /** 255 * Push back custom item into listview. 256 * @param {ccs.Widget} item 257 */ 258 pushBackCustomItem: function (item) { 259 this._items.push(item); 260 this.remedyLayoutParameter(item); 261 this.addChild(item); 262 this._refreshViewDirty = true; 263 }, 264 265 /** 266 * Push back custom item into listview. 267 * @param {ccs.Widget} item 268 * @param {Number} index 269 */ 270 insertCustomItem: function (item, index) { 271 cc.ArrayAppendObjectToIndex(this._items, item, index); 272 this.remedyLayoutParameter(item); 273 this.addChild(item); 274 this._refreshViewDirty = true; 275 }, 276 277 /** 278 * Removes a item whose index is same as the parameter. 279 * @param {Number} index 280 */ 281 removeItem: function (index) { 282 var item = this.getItem(index); 283 if (!item) { 284 return; 285 } 286 cc.ArrayRemoveObject(this._items, item); 287 this.removeChild(item); 288 this._refreshViewDirty = true; 289 }, 290 291 /** 292 * Removes the last item of listview. 293 */ 294 removeLastItem: function () { 295 this.removeItem(this._items.length - 1); 296 }, 297 298 /** 299 * Returns a item whose index is same as the parameter. 300 * @param {Number} index 301 * @returns {cc.Widget} 302 */ 303 getItem: function (index) { 304 if (index < 0 || index >= this._items.length) { 305 return null; 306 } 307 return this._items[index]; 308 }, 309 310 /** 311 * Returns the item container. 312 * @returns {Array} 313 */ 314 getItems: function () { 315 return this._items; 316 }, 317 318 /** 319 * Returns the index of item. 320 * @param {ccs.Widget} item 321 * @returns {Number} 322 */ 323 getIndex: function (item) { 324 return cc.ArrayGetIndexOfObject(this._items, item); 325 }, 326 327 /** 328 * Changes the gravity of listview. 329 * @param {ccs.ListViewGravity} gravity 330 */ 331 setGravity: function (gravity) { 332 if (this._gravity == gravity) { 333 return; 334 } 335 this._gravity = gravity; 336 this._refreshViewDirty = true; 337 }, 338 339 /** 340 * Changes the margin between each item. 341 * @param {Number} margin 342 */ 343 setItemsMargin: function (margin) { 344 if (this._itemsMargin == margin) { 345 return; 346 } 347 this._itemsMargin = margin; 348 this._refreshViewDirty = true; 349 }, 350 351 /** 352 * Get the margin between each item. 353 * @returns {Number} 354 */ 355 getItemsMargin:function(){ 356 return this._itemsMargin; 357 }, 358 359 /** 360 * Changes scroll direction of scrollview. 361 * @param {ccs.ScrollViewDir } dir 362 */ 363 setDirection: function (dir) { 364 switch (dir) { 365 case ccs.ScrollViewDir.vertical: 366 this.setLayoutType(ccs.LayoutType.linearVertical); 367 break; 368 case ccs.ScrollViewDir.horizontal: 369 this.setLayoutType(ccs.LayoutType.linearHorizontal); 370 break; 371 case ccs.ScrollViewDir.both: 372 return; 373 default: 374 return; 375 break; 376 } 377 ccs.ScrollView.prototype.setDirection.call(this, dir); 378 379 }, 380 381 /** 382 * add event listener 383 * @param {Function} selector 384 * @param {Object} target 385 */ 386 addEventListenerListView: function (selector, target) { 387 this._listViewEventListener = target; 388 this._listViewEventSelector = selector; 389 }, 390 391 selectedItemEvent: function () { 392 if(this._listViewEventSelector&&this._listViewEventListener){ 393 this._listViewEventSelector.call(this._listViewEventListener, this, ccs.ListViewEventType.listViewOnselectedItem); 394 } 395 }, 396 397 interceptTouchEvent: function (handleState, sender, touchPoint) { 398 ccs.ScrollView.prototype.interceptTouchEvent.call(this, handleState, sender, touchPoint); 399 if (handleState != 1) { 400 var parent = sender; 401 while (parent) { 402 if (parent && parent.getParent() == this._innerContainer) { 403 this._curSelectedIndex = this.getIndex(parent); 404 break; 405 } 406 parent = parent.getParent(); 407 } 408 this.selectedItemEvent(); 409 } 410 }, 411 412 /** 413 * get current selected index 414 * @returns {number} 415 */ 416 getCurSelectedIndex: function () { 417 return this._curSelectedIndex; 418 }, 419 420 /** 421 * request refresh view 422 */ 423 requestRefreshView: function () { 424 this._refreshViewDirty = true; 425 }, 426 427 refreshView: function () { 428 for (var i = 0; i < this._items.length; i++) { 429 var item = this._items[i]; 430 item.setZOrder(i); 431 this.remedyLayoutParameter(item); 432 } 433 this.updateInnerContainerSize(); 434 }, 435 436 sortAllChildren: function () { 437 ccs.ScrollView.prototype.sortAllChildren.call(this); 438 if (this._refreshViewDirty) { 439 this.refreshView(); 440 this._refreshViewDirty = false; 441 } 442 }, 443 444 onSizeChanged: function () { 445 ccs.ScrollView.prototype.onSizeChanged.call(this); 446 this._refreshViewDirty = true; 447 }, 448 449 /** 450 * Returns the "class name" of widget. 451 * @returns {string} 452 */ 453 getDescription: function () { 454 return "ListView"; 455 }, 456 457 createCloneInstance: function () { 458 return ccs.ListView.create(); 459 }, 460 461 copyClonedWidgetChildren: function (model) { 462 var arrayItems = model.getItems(); 463 for (var i = 0; i < arrayItems.length; i++) { 464 var item = arrayItems[i]; 465 this.pushBackCustomItem(item.clone()); 466 } 467 }, 468 469 copySpecialProperties: function (listView) { 470 ccs.ScrollView.prototype.copySpecialProperties.call(this, listView); 471 this.setItemModel(listView._model); 472 this.setItemsMargin(listView._itemsMargin); 473 this.setGravity(listView._gravity); 474 } 475 }); 476 477 ccs.ListView.create = function () { 478 var uiListView = new ccs.ListView(); 479 if (uiListView && uiListView.init()) { 480 return uiListView; 481 } 482 return null; 483 };