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 * Base class for ccui.Widget 27 * @sample 28 * var uiWidget = ccui.Widget.create(); 29 * this.addChild(uiWidget); 30 * @class 31 * @extends ccui.Node 32 * 33 * @property {Number} xPercent - Position x in percentage of width 34 * @property {Number} yPercent - Position y in percentage of height 35 * @property {Number} widthPercent - Width in percentage of parent width 36 * @property {Number} heightPercent - Height in percentage of parent height 37 * @property {ccui.Widget} widgetParent - <@readonly> The direct parent when it's a widget also, otherwise equals null 38 * @property {Boolean} enabled - Indicate whether the widget is enabled 39 * @property {Boolean} focused - Indicate whether the widget is focused 40 * @property {ccui.Widget.SIZE_ABSOLUTE|ccui.Widget.SIZE_PERCENT} sizeType - The size type of the widget 41 * @property {ccui.Widget.TYPE_WIDGET|ccui.Widget.TYPE_CONTAINER} widgetType - <@readonly> The type of the widget 42 * @property {Boolean} touchEnabled - Indicate whether touch events are enabled 43 * @property {Boolean} updateEnabled - Indicate whether the update function is scheduled 44 * @property {Boolean} bright - Indicate whether the widget is bright 45 * @property {String} name - The name of the widget 46 * @property {Number} actionTag - The action tag of the widget 47 */ 48 ccui.Widget = ccui.Node.extend(/** @lends ccui.Widget# */{ 49 _enabled: true, ///< Highest control of widget 50 _bright: true, ///< is this widget bright 51 _touchEnabled: false, ///< is this widget touch endabled 52 _touchPassedEnabled: false, ///< is the touch event should be passed 53 _focus: false, ///< is the widget on focus 54 _brightStyle: null, ///< bright style 55 _updateEnabled: false, ///< is "update" method scheduled 56 _touchStartPos: null, ///< touch began point 57 _touchMovePos: null, ///< touch moved point 58 _touchEndPos: null, ///< touch ended point 59 60 _touchEventListener: null, 61 _touchEventSelector: null, 62 63 _name: "default", 64 _widgetType: null, 65 _actionTag: 0, 66 _size: null, 67 _customSize: null, 68 _layoutParameterDictionary: null, 69 _ignoreSize: false, 70 _widgetChildren: null, 71 _affectByClipping: false, 72 73 _sizeType: null, 74 _sizePercent: null, 75 positionType: null, 76 _positionPercent: null, 77 _reorderWidgetChildDirty: false, 78 _hitted: false, 79 _nodes: null, 80 _touchListener : null, 81 _color:null, 82 _className:"Widget", 83 _flippedX: false, 84 _flippedY: false, 85 ctor: function () { 86 cc.Node.prototype.ctor.call(this); 87 this._enabled = true; 88 this._bright = true; 89 this._touchEnabled = false; 90 this._touchPassedEnabled = false; 91 this._focus = false; 92 this._brightStyle = ccui.Widget.BRIGHT_STYLE_NONE; 93 this._updateEnabled = false; 94 this._touchStartPos = cc.p(0,0); 95 this._touchMovePos = cc.p(0,0); 96 this._touchEndPos = cc.p(0,0); 97 this._touchEventListener = null; 98 this._touchEventSelector = null; 99 this._name = "default"; 100 this._widgetType = ccui.Widget.TYPE_WIDGET; 101 this._actionTag = 0; 102 this._size = cc.size(0, 0); 103 this._customSize = cc.size(0, 0); 104 this._layoutParameterDictionary = {}; 105 this._ignoreSize = false; 106 this._widgetChildren = []; 107 this._affectByClipping = false; 108 this._sizeType = ccui.Widget.SIZE_ABSOLUTE; 109 this._sizePercent = cc.p(0,0); 110 this.positionType = ccui.Widget.POSITION_ABSOLUTE; 111 this._positionPercent = cc.p(0,0); 112 this._reorderWidgetChildDirty = false; 113 this._hitted = false; 114 this._nodes = []; 115 this._color = cc.color(255,255,255,255); 116 this._touchListener = null; 117 this._flippedX = false; 118 this._flippedY = false; 119 }, 120 121 /** 122 * initializes state of widget. 123 * @returns {boolean} 124 */ 125 init: function () { 126 if (cc.Node.prototype.init.call(this)){ 127 this._layoutParameterDictionary = {}; 128 this._widgetChildren = []; 129 this.initRenderer(); 130 this.setBright(true); 131 this.ignoreContentAdaptWithSize(true); 132 this.setAnchorPoint(cc.p(0.5, 0.5)); 133 } 134 return true; 135 }, 136 137 onEnter: function () { 138 this.updateSizeAndPosition(); 139 cc.Node.prototype.onEnter.call(this); 140 }, 141 142 visit: function (ctx) { 143 if (this._enabled) { 144 cc.Node.prototype.visit.call(this,ctx); 145 } 146 }, 147 148 sortAllChildren: function () { 149 this._reorderWidgetChildDirty = this._reorderChildDirty; 150 cc.Node.prototype.sortAllChildren.call(this); 151 if (this._reorderWidgetChildDirty) { 152 var _children = this._widgetChildren; 153 var i, j, length = _children.length, tempChild; 154 155 // insertion sort 156 for (i = 0; i < length; i++) { 157 var tempItem = _children[i]; 158 j = i - 1; 159 tempChild = _children[j]; 160 161 //continue moving element downwards while zOrder is smaller or when zOrder is the same but mutatedIndex is smaller 162 while (j >= 0 && ( tempItem._localZOrder < tempChild._localZOrder || 163 ( tempItem._localZOrder == tempChild._localZOrder && tempItem.arrivalOrder < tempChild.arrivalOrder ))) { 164 _children[j + 1] = tempChild; 165 j = j - 1; 166 tempChild = _children[j]; 167 } 168 _children[j + 1] = tempItem; 169 } 170 171 //don't need to check children recursively, that's done in visit of each child 172 173 this._reorderWidgetChildDirty = false; 174 } 175 }, 176 177 /** 178 * Adds a child to the container. 179 * @param {ccui.Widget} widget 180 * @param {Number} zOrder 181 * @param {Number} tag 182 */ 183 addChild: function (widget, zOrder, tag) { 184 if(widget instanceof ccui.Widget){ 185 cc.Node.prototype.addChild.call(this, widget, zOrder, tag); 186 this._widgetChildren.push(widget); 187 return; 188 } 189 if(widget instanceof cc.Node){ 190 cc.log("Please use addNode to add a CCNode."); 191 return; 192 } 193 }, 194 195 /** 196 * 197 * @param tag 198 * @returns {ccui.Widget} 199 */ 200 getChildByTag:function(tag){ 201 var __children = this._widgetChildren; 202 if (__children != null) { 203 for (var i = 0; i < __children.length; i++) { 204 var node = __children[i]; 205 if (node && node._tag == tag) 206 return node; 207 } 208 } 209 return null; 210 }, 211 212 /** 213 * Return an array of children 214 * @returns {Array} 215 */ 216 getChildren: function () { 217 return this._widgetChildren; 218 }, 219 220 /** 221 * get the count of children 222 * @returns {Number} 223 */ 224 getChildrenCount: function () { 225 return this._widgetChildren.length; 226 }, 227 228 getWidgetParent: function () { 229 var widget = this.getParent(); 230 if(widget instanceof ccui.Widget){ 231 return widget; 232 } 233 return null; 234 }, 235 236 /** 237 * remove child 238 * @param {ccui.Widget} widget 239 * @param {Boolean} cleanup 240 */ 241 removeChild: function (widget, cleanup) { 242 if(!(widget instanceof ccui.Widget)){ 243 cc.log("child must a type of ccui.Widget"); 244 return; 245 } 246 cc.Node.prototype.removeChild.call(this, widget, cleanup); 247 cc.arrayRemoveObject(this._widgetChildren, widget); 248 }, 249 250 removeChildByTag: function (tag, cleanup) { 251 var child = this.getChildByTag(tag); 252 253 if (child == null) { 254 cc.log("cocos2d: removeChildByTag(tag = " + tag + "): child not found!"); 255 } 256 else { 257 this.removeChild(child, cleanup); 258 } 259 }, 260 261 /** 262 * Removes all children from the container, and do a cleanup to all running actions depending on the cleanup parameter. 263 */ 264 removeAllChildren: function (cleanup) { 265 for (var i = 0; i < this._widgetChildren.length; i++) { 266 var widget = this._widgetChildren[i]; 267 cc.Node.prototype.removeChild.call(this, widget, cleanup); 268 } 269 this._widgetChildren.length = 0; 270 }, 271 272 /** 273 * Set enabled renderer 274 * @param {Boolean} enabled 275 */ 276 setEnabled: function (enabled) { 277 this._enabled = enabled; 278 var arrayChildren = this._widgetChildren; 279 var childrenCount = arrayChildren.length; 280 for (var i = 0; i < childrenCount; i++) { 281 var child = arrayChildren[i]; 282 child.setEnabled(enabled); 283 } 284 }, 285 286 /** 287 * Gets a child from the container with its name 288 * @param {string} name 289 * @returns {ccui.Widget} 290 */ 291 getChildByName: function (name) { 292 var arrayChildren = this._widgetChildren; 293 var childrenCount = arrayChildren.length; 294 for (var i = 0; i < childrenCount; i++) { 295 var child = arrayChildren[i]; 296 if (child.getName() == name) { 297 return child; 298 } 299 } 300 }, 301 302 /** 303 * initializes renderer of widget. 304 */ 305 initRenderer: function () { 306 }, 307 308 /** 309 * add node for widget 310 * @param {cc.Node} node 311 * @param {Number} zOrder 312 * @param {Number} tag 313 */ 314 addNode: function (node, zOrder, tag) { 315 if (node instanceof ccui.Widget) { 316 cc.log("Please use addChild to add a Widget."); 317 return; 318 } 319 cc.Node.prototype.addChild.call(this, node, zOrder, tag); 320 this._nodes.push(node); 321 }, 322 323 /** 324 * get node by tag 325 * @param {Number} tag 326 * @returns {cc.Node} 327 */ 328 getNodeByTag: function (tag) { 329 var _nodes = this._nodes; 330 for (var i = 0; i < _nodes.length; i++) { 331 var node = _nodes[i]; 332 if (node && node.getTag() == tag) { 333 return node; 334 } 335 } 336 return null; 337 }, 338 339 /** 340 * get all node 341 * @returns {Array} 342 */ 343 getNodes: function () { 344 return this._nodes; 345 }, 346 347 /** 348 * remove node 349 * @param {cc.Node} node 350 * @param {Boolean} cleanup 351 */ 352 removeNode: function (node, cleanup) { 353 cc.Node.prototype.removeChild.call(this, node); 354 cc.arrayRemoveObject(this._nodes, node); 355 }, 356 357 /** 358 * remove node by tag 359 * @param {Number} tag 360 * @param {Boolean} cleanup 361 */ 362 removeNodeByTag: function (tag, cleanup) { 363 var node = this.getNodeByTag(tag); 364 if (!node) { 365 cc.log("cocos2d: removeNodeByTag(tag = %d): child not found!", tag); 366 } 367 else { 368 this.removeNode(node); 369 } 370 }, 371 372 /** 373 * remove all node 374 */ 375 removeAllNodes: function () { 376 for (var i = 0; i < this._nodes.length; i++) { 377 var node = this._nodes[i]; 378 cc.Node.prototype.removeChild.call(this, node); 379 } 380 this._nodes.length = 0; 381 }, 382 383 /** 384 * Changes the size that is widget's size 385 * @param {cc.Size} size 386 */ 387 setSize: function (size) { 388 var locW = this._customSize.width = size.width; 389 var locH = this._customSize.height = size.height; 390 if (this._ignoreSize) { 391 locW = this.width; 392 locH = this.height; 393 } 394 this._size.width = locW; 395 this._size.height = locH; 396 397 if(this._running){ 398 var widgetParent = this.getWidgetParent(); 399 if(widgetParent){ 400 locW = widgetParent.width; 401 locH = widgetParent.height; 402 }else{ 403 locW = this._parent.width; 404 locH = this._parent.height; 405 } 406 this._sizePercent.x = locW > 0 ? this._customSize.width / locW : 0; 407 this._sizePercent.y = locH > 0 ? this._customSize.height / locH : 0; 408 } 409 this.onSizeChanged(); 410 }, 411 _setWidth: function (w) { 412 var locW = this._customSize.width = w; 413 this._ignoreSize && (locW = this.width); 414 this._size.width = locW; 415 416 if(this._running){ 417 var widgetParent = this.getWidgetParent(); 418 locW = widgetParent ? widgetParent.width : this._parent.width; 419 this._sizePercent.x = locW > 0 ? this._customSize.width / locW : 0; 420 } 421 this.onSizeChanged(); 422 }, 423 _setHeight: function (h) { 424 var locH = this._customSize.height = h; 425 this._ignoreSize && (locH = this.height); 426 this._size.height = locH; 427 428 if(this._running){ 429 var widgetParent = this.getWidgetParent(); 430 locH = widgetParent ? widgetParent.height : this._parent.height; 431 this._sizePercent.y = locH > 0 ? this._customSize.height / locH : 0; 432 } 433 this.onSizeChanged(); 434 }, 435 436 /** 437 * Changes the percent that is widget's percent size 438 * @param {cc.Point} percent 439 */ 440 setSizePercent: function (percent) { 441 this._sizePercent.x = percent.x; 442 this._sizePercent.y = percent.y; 443 var width = this._customSize.width, height = this._customSize.height; 444 if (this._running) { 445 var widgetParent = this.getWidgetParent(); 446 if (widgetParent) { 447 width = widgetParent.width * percent.x; 448 height = widgetParent.height * percent.y; 449 } 450 else { 451 width = this._parent.width * percent.x; 452 height = this._parent.height * percent.y; 453 } 454 } 455 if (!this._ignoreSize) { 456 this._size.width = width; 457 this._size.height = height; 458 } 459 this._customSize.width = width; 460 this._customSize.height = height; 461 this.onSizeChanged(); 462 }, 463 _setWidthPercent: function (percent) { 464 this._sizePercent.x = percent; 465 var width = this._customSize.width; 466 if (this._running) { 467 var widgetParent = this.getWidgetParent(); 468 width = (widgetParent ? widgetParent.width : this._parent.width) * percent; 469 } 470 this._ignoreSize || (this._size.width = width); 471 this._customSize.width = width; 472 this.onSizeChanged(); 473 }, 474 _setHeightPercent: function (percent) { 475 this._sizePercent.y = percent; 476 var height = this._customSize.height; 477 if (this._running) { 478 var widgetParent = this.getWidgetParent(); 479 height = (widgetParent ? widgetParent.height : this._parent.height) * percent; 480 } 481 this._ignoreSize || (this._size.height = height); 482 this._customSize.height = height; 483 this.onSizeChanged(); 484 }, 485 486 /** 487 * update size and position 488 */ 489 updateSizeAndPosition: function () { 490 switch (this._sizeType) { 491 case ccui.Widget.SIZE_ABSOLUTE: 492 var locSize; 493 if (this._ignoreSize) { 494 locSize = this.getContentSize(); 495 } 496 else { 497 locSize = this._customSize; 498 } 499 this._size.width = locSize.width; 500 this._size.height = locSize.height; 501 502 var pSize, spx = 0, spy = 0; 503 var widgetParent = this.getWidgetParent(); 504 if (widgetParent){ 505 pSize = widgetParent.getSize(); 506 }else{ 507 pSize = this._parent.getContentSize(); 508 } 509 if (pSize.width > 0) { 510 spx = this._customSize.width / pSize.width; 511 } 512 if (pSize.height > 0) { 513 spy = this._customSize.height / pSize.height; 514 } 515 this._sizePercent.x = spx; 516 this._sizePercent.y = spy; 517 break; 518 case ccui.Widget.SIZE_PERCENT: 519 var widgetParent = this.getWidgetParent(); 520 var cSize = cc.size(0,0); 521 if (widgetParent){ 522 cSize.width = widgetParent.getSize().width * this._sizePercent.x; 523 cSize.height = widgetParent.getSize().height * this._sizePercent.y; 524 }else{ 525 cSize.width = this._parent.getContentSize().width * this._sizePercent.x; 526 cSize.height = this._parent.getContentSize().height * this._sizePercent.y; 527 } 528 var locSize; 529 if (this._ignoreSize) { 530 locSize = this.getContentSize(); 531 } 532 else { 533 locSize = cSize; 534 } 535 this._size.width = locSize.width; 536 this._size.height = locSize.height; 537 this._customSize.width = cSize.width; 538 this._customSize.height = cSize.height; 539 break; 540 default: 541 break; 542 } 543 this.onSizeChanged(); 544 var absPos = this.getPosition(); 545 switch (this.positionType) { 546 case ccui.Widget.POSITION_ABSOLUTE: 547 var widgetParent = this.getWidgetParent(); 548 var pSize; 549 if(widgetParent){ 550 pSize = widgetParent.getSize(); 551 }else{ 552 pSize = this._parent.getContentSize(); 553 } 554 if(pSize.width<=0||pSize.height<=0){ 555 this._positionPercent.x = 0; 556 this._positionPercent.y = 0; 557 }else{ 558 this._positionPercent.x = absPos.x / pSize.width; 559 this._positionPercent.y = absPos.y / pSize.height; 560 } 561 break; 562 case ccui.Widget.POSITION_PERCENT: 563 var widgetParent = this.getWidgetParent(); 564 var pSize; 565 if(widgetParent){ 566 pSize = widgetParent.getSize(); 567 }else{ 568 pSize = this._parent.getContentSize(); 569 } 570 absPos = cc.p(pSize.width * this._positionPercent.x, pSize.height * this._positionPercent.y); 571 break; 572 default: 573 break; 574 } 575 this.setPosition(absPos); 576 }, 577 578 /**TEXTURE_RES_TYPE 579 * Changes the size type of widget. 580 * @param {ccui.Widget.SIZE_ABSOLUTE|ccui.Widget.SIZE_PERCENT} type 581 */ 582 setSizeType: function (type) { 583 this._sizeType = type; 584 }, 585 586 /** 587 * Gets the size type of widget. 588 * @returns {ccui.Widget.SIZE_ABSOLUTE|ccui.Widget.SIZE_PERCENT} 589 */ 590 getSizeType: function () { 591 return this._sizeType; 592 }, 593 594 /** 595 * Ignore the widget size 596 * @param {Boolean} ignore 597 */ 598 ignoreContentAdaptWithSize: function (ignore) { 599 this._ignoreSize = ignore; 600 var locSize; 601 if (this._ignoreSize) { 602 locSize = this.getContentSize(); 603 } 604 else { 605 locSize = this._customSize; 606 } 607 this._size.width = locSize.width; 608 this._size.height = locSize.height; 609 this.onSizeChanged(); 610 }, 611 612 /** 613 * Gets the widget if is ignore it's size. 614 * @returns {boolean} 615 */ 616 isIgnoreContentAdaptWithSize: function () { 617 return this._ignoreSize; 618 }, 619 620 /** 621 * Returns size of widget 622 * @returns {cc.Size} 623 */ 624 getSize: function () { 625 return this._size; 626 }, 627 628 /** 629 * Get custom size 630 * @returns {cc.Size} 631 */ 632 getCustomSize:function(){ 633 return this._customSize 634 }, 635 636 /** 637 * Returns size percent of widget 638 * @returns {cc.Point} 639 */ 640 getSizePercent: function () { 641 return this._sizePercent; 642 }, 643 _getWidthPercent: function () { 644 return this._sizePercent.x; 645 }, 646 _getHeightPercent: function () { 647 return this._sizePercent.y; 648 }, 649 650 /** 651 * Gets world position of widget. 652 * @returns {cc.Point} 653 */ 654 getWorldPosition: function () { 655 return this.convertToWorldSpace(cc.p(0,0)); 656 }, 657 658 /** 659 * Gets the Virtual Renderer of widget. 660 * @returns {cc.Node} 661 */ 662 getVirtualRenderer: function () { 663 return this; 664 }, 665 666 /** 667 * call back function called when size changed. 668 */ 669 onSizeChanged: function () { 670 for (var i = 0; i < this._widgetChildren.length; i++) { 671 var child = this._widgetChildren[i]; 672 child.updateSizeAndPosition(); 673 } 674 }, 675 676 /** 677 * Gets the content size of widget. 678 * @returns {cc.Size} 679 */ 680 getContentSize: function () { 681 return this._size; 682 }, 683 _getWidth: function () { 684 return this._size.width; 685 }, 686 _getHeight: function () { 687 return this._size.height; 688 }, 689 690 /** 691 * Sets whether the widget is touch enabled 692 * @param enable 693 */ 694 setTouchEnabled: function (enable) { 695 if (this._touchEnabled === enable) { 696 return; 697 } 698 this._touchEnabled = enable; 699 if(this._touchEnabled){ 700 this._touchListener = cc.EventListener.create({ 701 event: cc.EventListener.TOUCH_ONE_BY_ONE, 702 swallowTouches: true, 703 onTouchBegan: this.onTouchBegan.bind(this), 704 onTouchMoved: this.onTouchMoved.bind(this), 705 onTouchEnded: this.onTouchEnded.bind(this) 706 }); 707 cc.eventManager.addListener(this._touchListener, this); 708 }else{ 709 cc.eventManager.removeListener(this._touchListener); 710 } 711 }, 712 713 /** 714 * To set the bright style of widget. 715 * @returns {boolean} 716 */ 717 isTouchEnabled: function () { 718 return this._touchEnabled; 719 }, 720 721 /** 722 * Schedules the "update" method. 723 * @param enable 724 */ 725 setUpdateEnabled: function (enable) { 726 if (this._updateEnabled == enable) { 727 return; 728 } 729 this._updateEnabled = enable; 730 if (enable) { 731 this.scheduleUpdate(); 732 } 733 else { 734 this.unscheduleUpdate(); 735 } 736 }, 737 738 /** 739 * is the "update" method scheduled. 740 * @returns {boolean} 741 */ 742 isUpdateEnabled: function () { 743 return this._updateEnabled; 744 }, 745 746 /** 747 * Determines if the widget is on focused 748 * @returns {boolean} 749 */ 750 isFocused: function () { 751 return this._focus; 752 }, 753 754 /** 755 * Sets whether the widget is on focused 756 * The default value is false, a widget is default to not on focused 757 * @param {boolean} fucos 758 */ 759 setFocused: function (fucos) { 760 if (fucos == this._focus) { 761 return; 762 } 763 this._focus = fucos; 764 if (this._bright) { 765 if (this._focus) { 766 this.setBrightStyle(ccui.Widget.BRIGHT_STYLE_HIGH_LIGHT); 767 } 768 else { 769 this.setBrightStyle(ccui.Widget.BRIGHT_STYLE_NORMAL); 770 } 771 } 772 else { 773 this.onPressStateChangedToDisabled(); 774 } 775 }, 776 777 setBright: function (bright, containChild) { 778 this._bright = bright; 779 if (this._bright) { 780 this._brightStyle = ccui.Widget.BRIGHT_STYLE_NONE; 781 this.setBrightStyle(ccui.Widget.BRIGHT_STYLE_NORMAL); 782 } 783 else { 784 this.onPressStateChangedToDisabled(); 785 } 786 }, 787 788 /** 789 * To set the bright style of widget. 790 * @param {ccui.Widget.BRIGHT_STYLE_NONE|ccui.Widget.BRIGHT_STYLE_NORMAL|ccui.Widget.BRIGHT_STYLE_HIGH_LIGHT} style 791 */ 792 setBrightStyle: function (style) { 793 if (this._brightStyle == style) { 794 return; 795 } 796 style = style|| ccui.Widget.BRIGHT_STYLE_NORMAL; 797 this._brightStyle = style; 798 switch (this._brightStyle) { 799 case ccui.Widget.BRIGHT_STYLE_NORMAL: 800 this.onPressStateChangedToNormal(); 801 break; 802 case ccui.Widget.BRIGHT_STYLE_HIGH_LIGHT: 803 this.onPressStateChangedToPressed(); 804 break; 805 default: 806 break; 807 } 808 }, 809 810 /** 811 * call back function called widget's state changed to normal. 812 */ 813 onPressStateChangedToNormal: function () { 814 815 }, 816 817 /** 818 * call back function called widget's state changed to selected. 819 */ 820 onPressStateChangedToPressed: function () { 821 822 }, 823 824 /** 825 * call back function called widget's state changed to dark. 826 */ 827 onPressStateChangedToDisabled: function () { 828 829 }, 830 831 /** 832 * A call back function when widget lost of focus. 833 */ 834 didNotSelectSelf: function () { 835 836 }, 837 838 onTouchBegan: function (touch,event) { 839 var touchPoint = touch.getLocation(); 840 this._touchStartPos.x = touchPoint.x; 841 this._touchStartPos.y = touchPoint.y; 842 this._hitted = this.isEnabled() && this.isTouchEnabled()&& this.hitTest(touchPoint)&& this.clippingParentAreaContainPoint(touchPoint); 843 if(!this._hitted){ 844 return false; 845 } 846 this.setFocused(true); 847 var widgetParent = this.getWidgetParent(); 848 if (widgetParent) { 849 widgetParent.checkChildInfo(0, this, touchPoint); 850 } 851 this.pushDownEvent(); 852 return !this._touchPassedEnabled; 853 }, 854 855 onTouchMoved: function (touch,event) { 856 var touchPoint = touch.getLocation(); 857 this._touchMovePos.x = touchPoint.x; 858 this._touchMovePos.y = touchPoint.y; 859 this.setFocused(this.hitTest(touchPoint)); 860 var widgetParent = this.getWidgetParent(); 861 if (widgetParent) { 862 widgetParent.checkChildInfo(1, this, touchPoint); 863 } 864 this.moveEvent(); 865 }, 866 867 868 onTouchEnded: function (touch,event) { 869 var touchPoint = touch.getLocation(); 870 this._touchEndPos.x = touchPoint.x; 871 this._touchEndPos.y = touchPoint.y; 872 var focus = this._focus; 873 this.setFocused(false); 874 var widgetParent = this.getWidgetParent(); 875 if (widgetParent) { 876 widgetParent.checkChildInfo(2, this, touchPoint); 877 } 878 if (focus) { 879 this.releaseUpEvent(); 880 } 881 else { 882 this.cancelUpEvent(); 883 } 884 }, 885 886 /** 887 * A call back function called when widget is selected, and on touch canceled. 888 * @param {cc.Point} touchPoint 889 */ 890 onTouchCancelled: function (touchPoint) { 891 this.setFocused(false); 892 this.cancelUpEvent(); 893 }, 894 895 /** 896 * A call back function called when widget is selected, and on touch long clicked. 897 * @param {cc.Point} touchPoint 898 */ 899 onTouchLongClicked: function (touchPoint) { 900 this.longClickEvent(); 901 }, 902 903 //call back function called widget's state changed to dark. 904 905 pushDownEvent: function () { 906 if (this._touchEventListener && this._touchEventSelector) { 907 if (this._touchEventSelector) { 908 this._touchEventSelector.call(this._touchEventListener, this, ccui.Widget.TOUCH_BAGAN); 909 } 910 } 911 }, 912 913 moveEvent: function () { 914 if (this._touchEventListener && this._touchEventSelector) { 915 if (this._touchEventSelector) { 916 this._touchEventSelector.call(this._touchEventListener, this, ccui.Widget.TOUCH_MOVED); 917 } 918 } 919 }, 920 921 releaseUpEvent: function () { 922 if (this._touchEventListener && this._touchEventSelector) { 923 if (this._touchEventSelector) { 924 this._touchEventSelector.call(this._touchEventListener, this, ccui.Widget.TOUCH_ENDED); 925 } 926 } 927 }, 928 929 cancelUpEvent: function () { 930 if (this._touchEventSelector) { 931 this._touchEventSelector.call(this._touchEventListener, this, ccui.Widget.TOUCH_CANCELED); 932 } 933 }, 934 935 longClickEvent: function () { 936 937 }, 938 939 /** 940 * Sets the touch event target/selector of the menu item 941 * @param {Function} selector 942 * @param {Object} target 943 */ 944 addTouchEventListener: function (selector, target) { 945 this._touchEventSelector = selector; 946 this._touchEventListener = target; 947 }, 948 949 /** 950 * Checks a point if is in widget's space 951 * @param {cc.Point} pt 952 * @returns {boolean} 953 */ 954 hitTest: function (pt) { 955 var nsp = this.convertToNodeSpace(pt); 956 var bb = cc.rect(-this._size.width * this._anchorPoint.x, -this._size.height * this._anchorPoint.y, this._size.width, this._size.height); 957 if (nsp.x >= bb.x && nsp.x <= bb.x + bb.width && nsp.y >= bb.y && nsp.y <= bb.y + bb.height) { 958 return true; 959 } 960 return false; 961 }, 962 963 /** 964 * Checks a point if in parent's area. 965 * @param {cc.Point} pt 966 * @returns {Boolean} 967 */ 968 clippingParentAreaContainPoint: function (pt) { 969 this._affectByClipping = false; 970 var parent = this.getParent(); 971 var clippingParent = null; 972 while (parent) { 973 if (parent instanceof ccui.Layout) { 974 if (parent.isClippingEnabled()) { 975 this._affectByClipping = true; 976 clippingParent = parent; 977 break; 978 } 979 } 980 parent = parent.getParent(); 981 } 982 983 if (!this._affectByClipping) { 984 return true; 985 } 986 987 988 if (clippingParent) { 989 var bRet = false; 990 if (clippingParent.hitTest(pt)) { 991 bRet = true; 992 } 993 if (bRet) { 994 return clippingParent.clippingParentAreaContainPoint(pt); 995 } 996 return false; 997 } 998 return true; 999 }, 1000 1001 /** 1002 * Sends the touch event to widget's parent 1003 * @param {number} handleState 1004 * @param {ccui.Widget} sender 1005 * @param {cc.Point} touchPoint 1006 */ 1007 checkChildInfo: function (handleState, sender, touchPoint) { 1008 var widgetParent = this.getWidgetParent(); 1009 if (widgetParent) { 1010 widgetParent.checkChildInfo(handleState, sender, touchPoint); 1011 } 1012 }, 1013 1014 /** 1015 * Changes the position (x,y) of the widget . 1016 * @param {cc.Point||Number} pos 1017 * @param {Number} posY 1018 */ 1019 setPosition: function (pos, posY) { 1020 if (this._running) { 1021 var widgetParent = this.getWidgetParent(); 1022 if (widgetParent) { 1023 var pSize = widgetParent.getSize(); 1024 if (pSize.width <= 0 || pSize.height <= 0) { 1025 this._positionPercent.x = 0; 1026 this._positionPercent.y = 0; 1027 } 1028 else { 1029 if(posY){ 1030 this._positionPercent.x = pos / pSize.width; 1031 this._positionPercent.y = posY / pSize.height; 1032 }else{ 1033 this._positionPercent.x = pos.x / pSize.width; 1034 this._positionPercent.y = pos.y / pSize.height; 1035 } 1036 } 1037 } 1038 } 1039 1040 cc.Node.prototype.setPosition.apply(this, arguments); 1041 }, 1042 1043 setPositionX: function (x) { 1044 if (this._running) { 1045 var widgetParent = this.getWidgetParent(); 1046 if (widgetParent) { 1047 var pw = widgetParent.width; 1048 if (pw <= 0) 1049 this._positionPercent.x = 0; 1050 else 1051 this._positionPercent.x = x / pw; 1052 } 1053 } 1054 1055 cc.Node.prototype.setPositionX.call(this, x); 1056 }, 1057 setPositionY: function (y) { 1058 if (this._running) { 1059 var widgetParent = this.getWidgetParent(); 1060 if (widgetParent) { 1061 var ph = widgetParent.height; 1062 if (ph <= 0) 1063 this._positionPercent.y = 0; 1064 else 1065 this._positionPercent.y = y / ph; 1066 } 1067 } 1068 1069 cc.Node.prototype.setPositionY.call(this, y); 1070 }, 1071 1072 /** 1073 * Changes the position (x,y) of the widget 1074 * @param {cc.Point} percent 1075 */ 1076 setPositionPercent: function (percent) { 1077 this._positionPercent = percent; 1078 if (this._running) { 1079 var widgetParent = this.getWidgetParent(); 1080 if(widgetParent){ 1081 var parentSize = widgetParent.getSize(); 1082 this.setPosition(parentSize.width * this._positionPercent.x, parentSize.height * this._positionPercent.y); 1083 } 1084 } 1085 }, 1086 _setXPercent: function (percent) { 1087 this._positionPercent.x = percent; 1088 if (this._running) { 1089 var widgetParent = this.getWidgetParent(); 1090 if(widgetParent){ 1091 var absX = widgetParent.width * percent; 1092 this.setPositionX(absX); 1093 } 1094 } 1095 }, 1096 _setYPercent: function (percent) { 1097 this._positionPercent.y = percent; 1098 if (this._running) { 1099 var widgetParent = this.getWidgetParent(); 1100 if(widgetParent){ 1101 var absY = widgetParent.height * percent; 1102 this.setPositionY(absY); 1103 } 1104 } 1105 }, 1106 1107 updateAnchorPoint:function(){ 1108 this.setAnchorPoint(this.getAnchorPoint()); 1109 }, 1110 1111 /** 1112 * Gets the percent (x,y) of the widget 1113 * @returns {cc.Point} 1114 */ 1115 getPositionPercent: function () { 1116 return this._positionPercent; 1117 }, 1118 _getXPercent: function () { 1119 return this._positionPercent.x; 1120 }, 1121 _getYPercent: function () { 1122 return this._positionPercent.y; 1123 }, 1124 1125 /** 1126 * Changes the position type of the widget 1127 * @param {ccui.Widget.POSITION_ABSOLUTE|ccui.Widget.POSITION_PERCENT} type 1128 */ 1129 setPositionType: function (type) { 1130 this.positionType = type; 1131 }, 1132 1133 /** 1134 * Gets the position type of the widget 1135 * @returns {cc.pPositionType} 1136 */ 1137 getPositionType: function () { 1138 return this.positionType; 1139 }, 1140 1141 /** 1142 * Set flipped x 1143 * @param {Boolean} flipX 1144 */ 1145 setFlippedX: function (flipX) { 1146 this._flippedX = flipX; 1147 this.updateFlippedX(); 1148 }, 1149 1150 /** 1151 * Get flipped x 1152 * @returns {Boolean} 1153 */ 1154 isFlippedX: function () { 1155 return this._flippedX; 1156 }, 1157 1158 /** 1159 * Set flipped y 1160 * @param {Boolean} flipY 1161 */ 1162 setFlippedY: function (flipY) { 1163 this._flippedY = flipY; 1164 this.updateFlippedY(); 1165 }, 1166 1167 /** 1168 * Get flipped y 1169 * @returns {Boolean} 1170 */ 1171 isFlippedY: function () { 1172 return this._flippedY; 1173 }, 1174 1175 updateFlippedX:function(){ 1176 1177 }, 1178 1179 updateFlippedY:function(){ 1180 1181 }, 1182 1183 /** 1184 * Determines if the widget is bright 1185 * @returns {boolean} 1186 */ 1187 isBright: function () { 1188 return this._bright; 1189 }, 1190 1191 /** 1192 * Determines if the widget is enabled 1193 * @returns {boolean} 1194 */ 1195 isEnabled: function () { 1196 return this._enabled; 1197 }, 1198 1199 /** 1200 * Gets the left boundary position of this widget. 1201 * @returns {number} 1202 */ 1203 getLeftInParent: function () { 1204 return this.getPositionX() - this._getAnchorX() * this._size.width; 1205 }, 1206 1207 /** 1208 * Gets the bottom boundary position of this widget. 1209 * @returns {number} 1210 */ 1211 getBottomInParent: function () { 1212 return this.getPositionY() - this._getAnchorY() * this._size.height; 1213 }, 1214 1215 /** 1216 * Gets the right boundary position of this widget. 1217 * @returns {number} 1218 */ 1219 getRightInParent: function () { 1220 return this.getLeftInParent() + this._size.width; 1221 }, 1222 1223 /** 1224 * Gets the top boundary position of this widget. 1225 * @returns {number} 1226 */ 1227 getTopInParent: function () { 1228 return this.getBottomInParent() + this._size.height; 1229 }, 1230 1231 /** 1232 * Gets touch start position 1233 * @returns {cc.Point} 1234 */ 1235 getTouchStartPos: function () { 1236 return this._touchStartPos; 1237 }, 1238 1239 /** 1240 * Gets touch move position 1241 * @returns {cc.Point} 1242 */ 1243 getTouchMovePos: function () { 1244 return this._touchMovePos; 1245 }, 1246 1247 /** 1248 * Gets touch end position 1249 * @returns {cc.Point} 1250 */ 1251 getTouchEndPos: function () { 1252 return this._touchEndPos; 1253 }, 1254 1255 /** 1256 * Sets the name of widget 1257 * @param {String} name 1258 */ 1259 setName: function (name) { 1260 this._name = name; 1261 }, 1262 1263 /** 1264 * Gets the name of widget 1265 * @returns {string} 1266 */ 1267 getName: function () { 1268 return this._name; 1269 }, 1270 1271 /** 1272 * get widget type 1273 * @returns {ccui.Widget.TYPE_WIDGET|ccui.Widget.TYPE_CONTAINER} 1274 */ 1275 getWidgetType: function () { 1276 return this._widgetType; 1277 }, 1278 1279 /** 1280 * Sets layout parameter 1281 * @param {ccui.LayoutParameter} parameter 1282 */ 1283 setLayoutParameter: function (parameter) { 1284 this._layoutParameterDictionary[parameter.getLayoutType()] = parameter; 1285 }, 1286 1287 /** 1288 * Gets layout parameter 1289 * @param {ccui.LayoutParameter.NONE|ccui.LayoutParameter.LINEAR|ccui.LayoutParameter.RELATIVE} type 1290 * @returns {ccui.LayoutParameter} 1291 */ 1292 getLayoutParameter: function (type) { 1293 return this._layoutParameterDictionary[type]; 1294 }, 1295 1296 /** 1297 * Returns the "class name" of widget. 1298 * @returns {string} 1299 */ 1300 getDescription: function () { 1301 return "Widget"; 1302 }, 1303 1304 clone: function () { 1305 var clonedWidget = this.createCloneInstance(); 1306 clonedWidget.copyProperties(this); 1307 clonedWidget.copyClonedWidgetChildren(this); 1308 return clonedWidget; 1309 }, 1310 1311 createCloneInstance: function () { 1312 return ccui.Widget.create(); 1313 }, 1314 1315 copyClonedWidgetChildren: function (model) { 1316 var widgetChildren = model.getChildren(); 1317 for (var i = 0; i < widgetChildren.length; i++) { 1318 var locChild = widgetChildren[i]; 1319 if(locChild instanceof ccui.Widget){ 1320 this.addChild(locChild.clone()); 1321 } 1322 } 1323 }, 1324 1325 copySpecialProperties: function (model) { 1326 1327 }, 1328 1329 copyProperties: function (widget) { 1330 this.setEnabled(widget.isEnabled()); 1331 this.setVisible(widget.isVisible()); 1332 this.setBright(widget.isBright()); 1333 this.setTouchEnabled(widget.isTouchEnabled()); 1334 this._touchPassedEnabled = false; 1335 this.setLocalZOrder(widget.getLocalZOrder()); 1336 this.setUpdateEnabled(widget.isUpdateEnabled()); 1337 this.setTag(widget.getTag()); 1338 this.setName(widget.getName()); 1339 this.setActionTag(widget.getActionTag()); 1340 this._ignoreSize = widget._ignoreSize; 1341 this._size = cc.size(widget._size.width, widget._size.height); 1342 this._customSize = cc.size(widget._customSize.width, widget._customSize.height); 1343 this.copySpecialProperties(widget); 1344 this._sizeType = widget.getSizeType(); 1345 this._sizePercent = cc.p(widget._sizePercent.x, widget._sizePercent.y); 1346 this.positionType = widget.positionType; 1347 this._positionPercent = cc.p(widget._positionPercent.x, widget._positionPercent.y); 1348 this.setPosition(widget.getPosition()); 1349 this.setAnchorPoint(widget.getAnchorPoint()); 1350 this.setScaleX(widget.getScaleX()); 1351 this.setScaleY(widget.getScaleY()); 1352 this.setRotation(widget.getRotation()); 1353 this.setRotationX(widget.getRotationX()); 1354 this.setRotationY(widget.getRotationY()); 1355 this.setFlippedX(widget.isFlippedX()); 1356 this.setFlippedY(widget.isFlippedY()); 1357 this.setColor(widget.getColor()); 1358 this.setOpacity(widget.getOpacity()); 1359 for (var key in widget._layoutParameterDictionary) { 1360 var parameter = widget._layoutParameterDictionary[key]; 1361 if (parameter) 1362 this.setLayoutParameter(parameter.clone()); 1363 } 1364 this.onSizeChanged(); 1365 }, 1366 1367 /*temp action*/ 1368 setActionTag: function (tag) { 1369 this._actionTag = tag; 1370 }, 1371 1372 getActionTag: function () { 1373 return this._actionTag; 1374 }, 1375 /** 1376 * Set color 1377 * @param {cc.Color} color 1378 */ 1379 setColor: function (color) { 1380 this._color.r = color.r; 1381 this._color.g = color.g; 1382 this._color.b = color.b; 1383 this.updateTextureColor(); 1384 if (color.a !== undefined && !color.a_undefined) { 1385 this.setOpacity(color.a); 1386 } 1387 }, 1388 1389 /** 1390 * Get color 1391 * @returns {cc.Color} 1392 */ 1393 getColor:function(){ 1394 return cc.color(this._color.r,this._color.g,this._color.b,this._color.a) ; 1395 }, 1396 1397 /** 1398 * Set opacity 1399 * @param {Number} opacity 1400 */ 1401 setOpacity: function (opacity) { 1402 this._color.a = opacity; 1403 this.updateTextureOpacity(); 1404 }, 1405 1406 /** 1407 * Get opacity 1408 * @returns {Number} 1409 */ 1410 getOpacity: function () { 1411 return this._color.a; 1412 }, 1413 1414 updateTextureColor: function () { 1415 1416 }, 1417 1418 updateTextureOpacity: function () { 1419 1420 }, 1421 1422 1423 updateColorToRenderer: function (renderer) { 1424 if (renderer.RGBAProtocol) { 1425 renderer.setColor(this._color); 1426 } 1427 }, 1428 1429 updateOpacityToRenderer: function (renderer) { 1430 if (renderer.RGBAProtocol) { 1431 renderer.setOpacity(this._color.a); 1432 } 1433 } 1434 }); 1435 1436 window._p = ccui.Widget.prototype; 1437 1438 // Extended properties 1439 /** @expose */ 1440 _p.xPercent; 1441 cc.defineGetterSetter(_p, "xPercent", _p._getXPercent, _p._setXPercent); 1442 /** @expose */ 1443 _p.yPercent; 1444 cc.defineGetterSetter(_p, "yPercent", _p._getYPercent, _p._setYPercent); 1445 /** @expose */ 1446 _p.widthPercent; 1447 cc.defineGetterSetter(_p, "widthPercent", _p._getWidthPercent, _p._setWidthPercent); 1448 /** @expose */ 1449 _p.heightPercent; 1450 cc.defineGetterSetter(_p, "heightPercent", _p._getHeightPercent, _p._setHeightPercent); 1451 /** @expose */ 1452 _p.widgetParent; 1453 cc.defineGetterSetter(_p, "widgetParent", _p.getWidgetParent); 1454 /** @expose */ 1455 _p.enabled; 1456 cc.defineGetterSetter(_p, "enabled", _p.isEnabled, _p.setEnabled); 1457 /** @expose */ 1458 _p.focused; 1459 cc.defineGetterSetter(_p, "focused", _p.isFocused, _p.setFocused); 1460 /** @expose */ 1461 _p.sizeType; 1462 cc.defineGetterSetter(_p, "sizeType", _p.getSizeType, _p.setSizeType); 1463 /** @expose */ 1464 _p.widgetType; 1465 cc.defineGetterSetter(_p, "widgetType", _p.getWidgetType); 1466 /** @expose */ 1467 _p.touchEnabled; 1468 cc.defineGetterSetter(_p, "touchEnabled", _p.isTouchEnabled, _p.setTouchEnabled); 1469 /** @expose */ 1470 _p.updateEnabled; 1471 cc.defineGetterSetter(_p, "updateEnabled", _p.isUpdateEnabled, _p.setUpdateEnabled); 1472 /** @expose */ 1473 _p.bright; 1474 cc.defineGetterSetter(_p, "bright", _p.isBright, _p.setBright); 1475 /** @expose */ 1476 _p.name; 1477 cc.defineGetterSetter(_p, "name", _p.getName, _p.setName); 1478 /** @expose */ 1479 _p.actionTag; 1480 cc.defineGetterSetter(_p, "actionTag", _p.getActionTag, _p.setActionTag); 1481 1482 delete window._p; 1483 1484 /** 1485 * allocates and initializes a UIWidget. 1486 * @constructs 1487 * @return {ccui.Widget} 1488 * @example 1489 * // example 1490 * var uiWidget = ccui.Widget.create(); 1491 */ 1492 ccui.Widget.create = function () { 1493 var widget = new ccui.Widget(); 1494 if (widget && widget.init()) { 1495 return widget; 1496 } 1497 return null; 1498 }; 1499 1500 1501 // Constants 1502 //bright style 1503 ccui.Widget.BRIGHT_STYLE_NONE = -1; 1504 ccui.Widget.BRIGHT_STYLE_NORMAL = 0; 1505 ccui.Widget.BRIGHT_STYLE_HIGH_LIGHT = 1; 1506 1507 //widget type 1508 ccui.Widget.TYPE_WIDGET = 0; 1509 ccui.Widget.TYPE_CONTAINER = 1; 1510 1511 //texture resource type 1512 ccui.Widget.LOCAL_TEXTURE = 0; 1513 ccui.Widget.PLIST_TEXTURE = 1; 1514 1515 //touch event type 1516 ccui.Widget.TOUCH_BAGAN = 0; 1517 ccui.Widget.TOUCH_MOVED = 1; 1518 ccui.Widget.TOUCH_ENDED = 2; 1519 ccui.Widget.TOUCH_CANCELED = 3; 1520 1521 //size type 1522 ccui.Widget.SIZE_ABSOLUTE = 0; 1523 ccui.Widget.SIZE_PERCENT = 1; 1524 1525 //position type 1526 ccui.Widget.POSITION_ABSOLUTE = 0; 1527 ccui.Widget.POSITION_PERCENT = 1;