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 * Changes scroll direction of scrollview. 353 * @param {ccs.ScrollViewDir } dir 354 */ 355 setDirection: function (dir) { 356 switch (dir) { 357 case ccs.ScrollViewDir.vertical: 358 this.setLayoutType(ccs.LayoutType.linearVertical); 359 break; 360 case ccs.ScrollViewDir.horizontal: 361 this.setLayoutType(ccs.LayoutType.linearHorizontal); 362 break; 363 case ccs.ScrollViewDir.both: 364 return; 365 default: 366 return; 367 break; 368 } 369 ccs.ScrollView.prototype.setDirection.call(this, dir); 370 371 }, 372 373 /** 374 * add event listener 375 * @param {Function} selector 376 * @param {Object} target 377 */ 378 addEventListenerListView: function (selector, target) { 379 this._listViewEventListener = target; 380 this._listViewEventSelector = selector; 381 }, 382 383 selectedItemEvent: function () { 384 if(this._listViewEventSelector&&this._listViewEventListener){ 385 this._listViewEventSelector.call(this._listViewEventListener, this, ccs.ListViewEventType.listViewOnselectedItem); 386 } 387 }, 388 389 interceptTouchEvent: function (handleState, sender, touchPoint) { 390 ccs.ScrollView.prototype.interceptTouchEvent.call(this, handleState, sender, touchPoint); 391 if (handleState != 1) { 392 var parent = sender; 393 while (parent) { 394 if (parent && parent.getParent() == this._innerContainer) { 395 this._curSelectedIndex = this.getIndex(parent); 396 break; 397 } 398 parent = parent.getParent(); 399 } 400 this.selectedItemEvent(); 401 } 402 }, 403 404 /** 405 * get current selected index 406 * @returns {number} 407 */ 408 getCurSelectedIndex: function () { 409 return this._curSelectedIndex; 410 }, 411 412 /** 413 * request refresh view 414 */ 415 requestRefreshView: function () { 416 this._refreshViewDirty = true; 417 }, 418 419 refreshView: function () { 420 for (var i = 0; i < this._items.length; i++) { 421 var item = this._items[i]; 422 item.setZOrder(i); 423 this.remedyLayoutParameter(item); 424 } 425 this.updateInnerContainerSize(); 426 }, 427 428 sortAllChildren: function () { 429 ccs.ScrollView.prototype.sortAllChildren.call(this); 430 if (this._refreshViewDirty) { 431 this.refreshView(); 432 this._refreshViewDirty = false; 433 } 434 }, 435 436 onSizeChanged: function () { 437 ccs.ScrollView.prototype.onSizeChanged.call(this); 438 this._refreshViewDirty = true; 439 }, 440 441 /** 442 * Returns the "class name" of widget. 443 * @returns {string} 444 */ 445 getDescription: function () { 446 return "ListView"; 447 }, 448 449 createCloneInstance: function () { 450 return ccs.ListView.create(); 451 }, 452 453 copyClonedWidgetChildren: function (model) { 454 var arrayItems = model.getItems(); 455 for (var i = 0; i < arrayItems.length; i++) { 456 var item = arrayItems[i]; 457 this.pushBackCustomItem(item.clone()); 458 } 459 }, 460 461 copySpecialProperties: function (listView) { 462 ccs.ScrollView.prototype.copySpecialProperties.call(this, listView); 463 this.setItemModel(listView._model); 464 this.setItemsMargin(listView._itemsMargin); 465 this.setGravity(listView._gravity); 466 } 467 }); 468 469 ccs.ListView.create = function () { 470 var uiListView = new ccs.ListView(); 471 if (uiListView && uiListView.init()) { 472 return uiListView; 473 } 474 return null; 475 };