1 /**************************************************************************** 2 Copyright (c) 2013-2014 Chukong Technologies Inc. 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 * Gets the layout manager by ccui.Layout's layout type. 27 * @param {Number} type 28 * @returns {ccui.linearVerticalLayoutManager|ccui.linearHorizontalLayoutManager|ccui.relativeLayoutManager|null} 29 */ 30 ccui.getLayoutManager = function (type) { 31 switch (type) { 32 case ccui.Layout.LINEAR_VERTICAL: 33 return ccui.linearVerticalLayoutManager; 34 case ccui.Layout.LINEAR_HORIZONTAL: 35 return ccui.linearHorizontalLayoutManager; 36 case ccui.Layout.RELATIVE: 37 return ccui.relativeLayoutManager; 38 } 39 return null; 40 }; 41 42 /** 43 * ccui.linearVerticalLayoutManager is a singleton object which is the linear vertical layout manager for ccui.Layout. 44 * @class 45 * @name ccui.linearVerticalLayoutManager 46 */ 47 ccui.linearVerticalLayoutManager = /** @lends ccui.linearVerticalLayoutManager# */{ 48 _doLayout: function(layout){ 49 var layoutSize = layout._getLayoutContentSize(); 50 var container = layout._getLayoutElements(); 51 var topBoundary = layoutSize.height; 52 53 for (var i = 0, len = container.length; i < len; i++) { 54 var child = container[i]; 55 if (child) { 56 var layoutParameter = child.getLayoutParameter(); 57 58 if (layoutParameter){ 59 var childGravity = layoutParameter.getGravity(); 60 var ap = child.getAnchorPoint(); 61 var cs = child.getContentSize(); 62 var finalPosX = ap.x * cs.width; 63 var finalPosY = topBoundary - ((1.0 - ap.y) * cs.height); 64 switch (childGravity){ 65 case ccui.LinearLayoutParameter.NONE: 66 case ccui.LinearLayoutParameter.LEFT: 67 break; 68 case ccui.LinearLayoutParameter.RIGHT: 69 finalPosX = layoutSize.width - ((1.0 - ap.x) * cs.width); 70 break; 71 case ccui.LinearLayoutParameter.CENTER_HORIZONTAL: 72 finalPosX = layoutSize.width / 2.0 - cs.width * (0.5 - ap.x); 73 break; 74 default: 75 break; 76 } 77 var mg = layoutParameter.getMargin(); 78 finalPosX += mg.left; 79 finalPosY -= mg.top; 80 child.setPosition(finalPosX, finalPosY); 81 topBoundary = child.getPositionY() - ap.y * cs.height - mg.bottom; 82 } 83 } 84 } 85 } 86 }; 87 88 /** 89 * ccui.linearHorizontalLayoutManager is a singleton object which is the linear horizontal layout manager for ccui.Layout 90 * @class 91 * @name ccui.linearHorizontalLayoutManager 92 */ 93 ccui.linearHorizontalLayoutManager = /** @lends ccui.linearHorizontalLayoutManager# */{ 94 _doLayout: function(layout){ 95 var layoutSize = layout._getLayoutContentSize(); 96 var container = layout._getLayoutElements(); 97 var leftBoundary = 0.0; 98 for (var i = 0, len = container.length; i < len; i++) { 99 var child = container[i]; 100 if (child) { 101 var layoutParameter = child.getLayoutParameter(); 102 if (layoutParameter){ 103 var childGravity = layoutParameter.getGravity(); 104 var ap = child.getAnchorPoint(); 105 var cs = child.getContentSize(); 106 var finalPosX = leftBoundary + (ap.x * cs.width); 107 var finalPosY = layoutSize.height - (1.0 - ap.y) * cs.height; 108 switch (childGravity){ 109 case ccui.LinearLayoutParameter.NONE: 110 case ccui.LinearLayoutParameter.TOP: 111 break; 112 case ccui.LinearLayoutParameter.BOTTOM: 113 finalPosY = ap.y * cs.height; 114 break; 115 case ccui.LinearLayoutParameter.CENTER_VERTICAL: 116 finalPosY = layoutSize.height / 2.0 - cs.height * (0.5 - ap.y); 117 break; 118 default: 119 break; 120 } 121 var mg = layoutParameter.getMargin(); 122 finalPosX += mg.left; 123 finalPosY -= mg.top; 124 child.setPosition(finalPosX, finalPosY); 125 leftBoundary = child.getRightBoundary() + mg.right; 126 } 127 } 128 } 129 } 130 }; 131 132 /** 133 * ccui.relativeLayoutManager is the singleton object which is the relative layout manager for ccui.Layout, it has a _doLayout function to do layout. 134 * @class 135 * @name ccui.relativeLayoutManager 136 */ 137 ccui.relativeLayoutManager = /** @lends ccui.relativeLayoutManager# */{ 138 _unlayoutChildCount: 0, 139 _widgetChildren: [], 140 _widget: null, 141 _finalPositionX:0, 142 _finalPositionY:0, 143 _relativeWidgetLP:null, 144 145 _doLayout: function(layout){ 146 this._widgetChildren = this._getAllWidgets(layout); 147 148 var locChildren = this._widgetChildren; 149 while (this._unlayoutChildCount > 0) { 150 for (var i = 0, len = locChildren.length; i < len; i++) { 151 this._widget = locChildren[i]; 152 153 var layoutParameter = this._widget.getLayoutParameter(); 154 if (layoutParameter){ 155 if (layoutParameter._put) 156 continue; 157 158 var ret = this._calculateFinalPositionWithRelativeWidget(layout); 159 if (!ret) 160 continue; 161 162 this._calculateFinalPositionWithRelativeAlign(); 163 164 this._widget.setPosition(this._finalPositionX, this._finalPositionY); 165 layoutParameter._put = true; 166 } 167 } 168 this._unlayoutChildCount--; 169 } 170 this._widgetChildren.length = 0; 171 }, 172 173 _getAllWidgets: function(layout){ 174 var container = layout._getLayoutElements(); 175 var locWidgetChildren = this._widgetChildren; 176 locWidgetChildren.length = 0; 177 for (var i = 0, len = container.length; i < len; i++){ 178 var child = container[i]; 179 if (child) { 180 var layoutParameter = child.getLayoutParameter(); 181 layoutParameter._put = false; 182 this._unlayoutChildCount++; 183 locWidgetChildren.push(child); 184 } 185 } 186 return locWidgetChildren; 187 }, 188 189 _getRelativeWidget: function(widget){ 190 var relativeWidget = null; 191 var layoutParameter = widget.getLayoutParameter(); 192 var relativeName = layoutParameter.getRelativeToWidgetName(); 193 194 if (relativeName && relativeName.length !== 0) { 195 var locChildren = this._widgetChildren; 196 for(var i = 0, len = locChildren.length; i < len; i++){ 197 var child = locChildren[i]; 198 if (child){ 199 var rlayoutParameter = child.getLayoutParameter(); 200 if (rlayoutParameter && rlayoutParameter.getRelativeName() === relativeName) { 201 relativeWidget = child; 202 this._relativeWidgetLP = rlayoutParameter; 203 break; 204 } 205 } 206 } 207 } 208 return relativeWidget; 209 }, 210 211 _calculateFinalPositionWithRelativeWidget: function(layout){ 212 var locWidget = this._widget; 213 var ap = locWidget.getAnchorPoint(); 214 var cs = locWidget.getContentSize(); 215 216 this._finalPositionX = 0.0; 217 this._finalPositionY = 0.0; 218 219 var relativeWidget = this._getRelativeWidget(locWidget); 220 var layoutParameter = locWidget.getLayoutParameter(); 221 var align = layoutParameter.getAlign(); 222 var layoutSize = layout._getLayoutContentSize(); 223 224 switch (align) { 225 case ccui.RelativeLayoutParameter.NONE: 226 case ccui.RelativeLayoutParameter.PARENT_TOP_LEFT: 227 this._finalPositionX = ap.x * cs.width; 228 this._finalPositionY = layoutSize.height - ((1.0 - ap.y) * cs.height); 229 break; 230 case ccui.RelativeLayoutParameter.PARENT_TOP_CENTER_HORIZONTAL: 231 this._finalPositionX = layoutSize.width * 0.5 - cs.width * (0.5 - ap.x); 232 this._finalPositionY = layoutSize.height - ((1.0 - ap.y) * cs.height); 233 break; 234 case ccui.RelativeLayoutParameter.PARENT_TOP_RIGHT: 235 this._finalPositionX = layoutSize.width - ((1.0 - ap.x) * cs.width); 236 this._finalPositionY = layoutSize.height - ((1.0 - ap.y) * cs.height); 237 break; 238 case ccui.RelativeLayoutParameter.PARENT_LEFT_CENTER_VERTICAL: 239 this._finalPositionX = ap.x * cs.width; 240 this._finalPositionY = layoutSize.height * 0.5 - cs.height * (0.5 - ap.y); 241 break; 242 case ccui.RelativeLayoutParameter.CENTER_IN_PARENT: 243 this._finalPositionX = layoutSize.width * 0.5 - cs.width * (0.5 - ap.x); 244 this._finalPositionY = layoutSize.height * 0.5 - cs.height * (0.5 - ap.y); 245 break; 246 case ccui.RelativeLayoutParameter.PARENT_RIGHT_CENTER_VERTICAL: 247 this._finalPositionX = layoutSize.width - ((1.0 - ap.x) * cs.width); 248 this._finalPositionY = layoutSize.height * 0.5 - cs.height * (0.5 - ap.y); 249 break; 250 case ccui.RelativeLayoutParameter.PARENT_LEFT_BOTTOM: 251 this._finalPositionX = ap.x * cs.width; 252 this._finalPositionY = ap.y * cs.height; 253 break; 254 case ccui.RelativeLayoutParameter.PARENT_BOTTOM_CENTER_HORIZONTAL: 255 this._finalPositionX = layoutSize.width * 0.5 - cs.width * (0.5 - ap.x); 256 this._finalPositionY = ap.y * cs.height; 257 break; 258 case ccui.RelativeLayoutParameter.PARENT_RIGHT_BOTTOM: 259 this._finalPositionX = layoutSize.width - ((1.0 - ap.x) * cs.width); 260 this._finalPositionY = ap.y * cs.height; 261 break; 262 263 case ccui.RelativeLayoutParameter.LOCATION_ABOVE_LEFTALIGN: 264 if (relativeWidget){ 265 if (this._relativeWidgetLP && !this._relativeWidgetLP._put) 266 return false; 267 this._finalPositionY = relativeWidget.getTopBoundary() + ap.y * cs.height; 268 this._finalPositionX = relativeWidget.getLeftBoundary() + ap.x * cs.width; 269 } 270 break; 271 case ccui.RelativeLayoutParameter.LOCATION_ABOVE_CENTER: 272 if (relativeWidget){ 273 if (this._relativeWidgetLP && !this._relativeWidgetLP._put) 274 return false; 275 var rbs = relativeWidget.getContentSize(); 276 this._finalPositionY = relativeWidget.getTopBoundary() + ap.y * cs.height; 277 this._finalPositionX = relativeWidget.getLeftBoundary() + rbs.width * 0.5 + ap.x * cs.width - cs.width * 0.5; 278 } 279 break; 280 case ccui.RelativeLayoutParameter.LOCATION_ABOVE_RIGHTALIGN: 281 if (relativeWidget) { 282 if (this._relativeWidgetLP && !this._relativeWidgetLP._put) 283 return false; 284 this._finalPositionY = relativeWidget.getTopBoundary() + ap.y * cs.height; 285 this._finalPositionX = relativeWidget.getRightBoundary() - (1.0 - ap.x) * cs.width; 286 } 287 break; 288 case ccui.RelativeLayoutParameter.LOCATION_LEFT_OF_TOPALIGN: 289 if (relativeWidget){ 290 if (this._relativeWidgetLP && !this._relativeWidgetLP._put) 291 return false; 292 this._finalPositionY = relativeWidget.getTopBoundary() - (1.0 - ap.y) * cs.height; 293 this._finalPositionX = relativeWidget.getLeftBoundary() - (1.0 - ap.x) * cs.width; 294 } 295 break; 296 case ccui.RelativeLayoutParameter.LOCATION_LEFT_OF_CENTER: 297 if (relativeWidget) { 298 if (this._relativeWidgetLP && !this._relativeWidgetLP._put) 299 return false; 300 var rbs = relativeWidget.getContentSize(); 301 this._finalPositionX = relativeWidget.getLeftBoundary() - (1.0 - ap.x) * cs.width; 302 this._finalPositionY = relativeWidget.getBottomBoundary() + rbs.height * 0.5 + ap.y * cs.height - cs.height * 0.5; 303 } 304 break; 305 case ccui.RelativeLayoutParameter.LOCATION_LEFT_OF_BOTTOMALIGN: 306 if (relativeWidget) { 307 if (this._relativeWidgetLP && !this._relativeWidgetLP._put) 308 return false; 309 this._finalPositionY = relativeWidget.getBottomBoundary() + ap.y * cs.height; 310 this._finalPositionX = relativeWidget.getLeftBoundary() - (1.0 - ap.x) * cs.width; 311 } 312 break; 313 case ccui.RelativeLayoutParameter.LOCATION_RIGHT_OF_TOPALIGN: 314 if (relativeWidget){ 315 if (this._relativeWidgetLP && !this._relativeWidgetLP._put) 316 return false; 317 this._finalPositionY = relativeWidget.getTopBoundary() - (1.0 - ap.y) * cs.height; 318 this._finalPositionX = relativeWidget.getRightBoundary() + ap.x * cs.width; 319 } 320 break; 321 case ccui.RelativeLayoutParameter.LOCATION_RIGHT_OF_CENTER: 322 if (relativeWidget){ 323 if (this._relativeWidgetLP && !this._relativeWidgetLP._put) 324 return false; 325 var rbs = relativeWidget.getContentSize(); 326 var locationRight = relativeWidget.getRightBoundary(); 327 this._finalPositionX = locationRight + ap.x * cs.width; 328 this._finalPositionY = relativeWidget.getBottomBoundary() + rbs.height * 0.5 + ap.y * cs.height - cs.height * 0.5; 329 } 330 break; 331 case ccui.RelativeLayoutParameter.LOCATION_RIGHT_OF_BOTTOMALIGN: 332 if (relativeWidget){ 333 if (this._relativeWidgetLP && !this._relativeWidgetLP._put) 334 return false; 335 this._finalPositionY = relativeWidget.getBottomBoundary() + ap.y * cs.height; 336 this._finalPositionX = relativeWidget.getRightBoundary() + ap.x * cs.width; 337 } 338 break; 339 case ccui.RelativeLayoutParameter.LOCATION_BELOW_LEFTALIGN: 340 if (relativeWidget){ 341 if (this._relativeWidgetLP && !this._relativeWidgetLP._put) 342 return false; 343 this._finalPositionY = relativeWidget.getBottomBoundary() - (1.0 - ap.y) * cs.height; 344 this._finalPositionX = relativeWidget.getLeftBoundary() + ap.x * cs.width; 345 } 346 break; 347 case ccui.RelativeLayoutParameter.LOCATION_BELOW_CENTER: 348 if (relativeWidget) { 349 if (this._relativeWidgetLP && !this._relativeWidgetLP._put) 350 return false; 351 var rbs = relativeWidget.getContentSize(); 352 this._finalPositionY = relativeWidget.getBottomBoundary() - (1.0 - ap.y) * cs.height; 353 this._finalPositionX = relativeWidget.getLeftBoundary() + rbs.width * 0.5 + ap.x * cs.width - cs.width * 0.5; 354 } 355 break; 356 case ccui.RelativeLayoutParameter.LOCATION_BELOW_RIGHTALIGN: 357 if (relativeWidget) { 358 if (this._relativeWidgetLP && !this._relativeWidgetLP._put) 359 return false; 360 this._finalPositionY = relativeWidget.getBottomBoundary() - (1.0 - ap.y) * cs.height; 361 this._finalPositionX = relativeWidget.getRightBoundary() - (1.0 - ap.x) * cs.width; 362 } 363 break; 364 default: 365 break; 366 } 367 return true; 368 }, 369 370 _calculateFinalPositionWithRelativeAlign: function(){ 371 var layoutParameter = this._widget.getLayoutParameter(); 372 373 var mg = layoutParameter.getMargin(); 374 var align = layoutParameter.getAlign(); 375 376 //handle margin 377 switch (align) { 378 case ccui.RelativeLayoutParameter.NONE: 379 case ccui.RelativeLayoutParameter.PARENT_TOP_LEFT: 380 this._finalPositionX += mg.left; 381 this._finalPositionY -= mg.top; 382 break; 383 case ccui.RelativeLayoutParameter.PARENT_TOP_CENTER_HORIZONTAL: 384 this._finalPositionY -= mg.top; 385 break; 386 case ccui.RelativeLayoutParameter.PARENT_TOP_RIGHT: 387 this._finalPositionX -= mg.right; 388 this._finalPositionY -= mg.top; 389 break; 390 case ccui.RelativeLayoutParameter.PARENT_LEFT_CENTER_VERTICAL: 391 this._finalPositionX += mg.left; 392 break; 393 case ccui.RelativeLayoutParameter.CENTER_IN_PARENT: 394 break; 395 case ccui.RelativeLayoutParameter.PARENT_RIGHT_CENTER_VERTICAL: 396 this._finalPositionX -= mg.right; 397 break; 398 case ccui.RelativeLayoutParameter.PARENT_LEFT_BOTTOM: 399 this._finalPositionX += mg.left; 400 this._finalPositionY += mg.bottom; 401 break; 402 case ccui.RelativeLayoutParameter.PARENT_BOTTOM_CENTER_HORIZONTAL: 403 this._finalPositionY += mg.bottom; 404 break; 405 case ccui.RelativeLayoutParameter.PARENT_RIGHT_BOTTOM: 406 this._finalPositionX -= mg.right; 407 this._finalPositionY += mg.bottom; 408 break; 409 case ccui.RelativeLayoutParameter.LOCATION_ABOVE_LEFTALIGN: 410 this._finalPositionY += mg.bottom; 411 this._finalPositionX += mg.left; 412 break; 413 case ccui.RelativeLayoutParameter.LOCATION_ABOVE_RIGHTALIGN: 414 this._finalPositionY += mg.bottom; 415 this._finalPositionX -= mg.right; 416 break; 417 case ccui.RelativeLayoutParameter.LOCATION_ABOVE_CENTER: 418 this._finalPositionY += mg.bottom; 419 break; 420 case ccui.RelativeLayoutParameter.LOCATION_LEFT_OF_TOPALIGN: 421 this._finalPositionX -= mg.right; 422 this._finalPositionY -= mg.top; 423 break; 424 case ccui.RelativeLayoutParameter.LOCATION_LEFT_OF_BOTTOMALIGN: 425 this._finalPositionX -= mg.right; 426 this._finalPositionY += mg.bottom; 427 break; 428 case ccui.RelativeLayoutParameter.LOCATION_LEFT_OF_CENTER: 429 this._finalPositionX -= mg.right; 430 break; 431 case ccui.RelativeLayoutParameter.LOCATION_RIGHT_OF_TOPALIGN: 432 this._finalPositionX += mg.left; 433 this._finalPositionY -= mg.top; 434 break; 435 case ccui.RelativeLayoutParameter.LOCATION_RIGHT_OF_BOTTOMALIGN: 436 this._finalPositionX += mg.left; 437 this._finalPositionY += mg.bottom; 438 break; 439 case ccui.RelativeLayoutParameter.LOCATION_RIGHT_OF_CENTER: 440 this._finalPositionX += mg.left; 441 break; 442 case ccui.RelativeLayoutParameter.LOCATION_BELOW_LEFTALIGN: 443 this._finalPositionY -= mg.top; 444 this._finalPositionX += mg.left; 445 break; 446 case ccui.RelativeLayoutParameter.LOCATION_BELOW_RIGHTALIGN: 447 this._finalPositionY -= mg.top; 448 this._finalPositionX -= mg.right; 449 break; 450 case ccui.RelativeLayoutParameter.LOCATION_BELOW_CENTER: 451 this._finalPositionY -= mg.top; 452 break; 453 default: 454 break; 455 } 456 } 457 };