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 * bright style 27 * @type {Object} 28 */ 29 ccs.BrightStyle = { 30 none: -1, 31 normal: 0, 32 highlight: 1 33 }; 34 35 /** 36 * widget type 37 * @type {Object} 38 */ 39 ccs.WidgetType = { 40 widget: 0, //control 41 container: 1 //container 42 }; 43 44 /** 45 * texture resource type 46 * @type {Object} 47 */ 48 ccs.TextureResType = { 49 local: 0, 50 plist: 1 51 }; 52 53 /** 54 * touch event type 55 * @type {Object} 56 */ 57 ccs.TouchEventType = { 58 began: 0, 59 moved: 1, 60 ended: 2, 61 canceled: 3 62 }; 63 64 /** 65 * size type 66 * @type {Object} 67 */ 68 ccs.SizeType = { 69 absolute: 0, 70 percent: 1 71 }; 72 73 /** 74 * position type 75 * @type {Object} 76 */ 77 ccs.PositionType = { 78 absolute: 0, 79 percent: 1 80 }; 81 82 /** 83 * Base class for ccs.Widget 84 * @sample 85 * var uiWidget = ccs.Widget.create(); 86 * var uiLayer = ccs.UILayer.create(); 87 * uiLayer.addWidget(uiWidget); 88 * @class 89 * @extends ccs.Class 90 */ 91 ccs.Widget = ccs.NodeRGBA.extend(/** @lends ccs.Widget# */{ 92 _enabled: true, ///< Highest control of widget 93 _bright: true, ///< is this widget bright 94 _touchEnabled: false, ///< is this widget touch endabled 95 _touchPassedEnabled: false, ///< is the touch event should be passed 96 _focus: false, ///< is the widget on focus 97 _brightStyle: null, ///< bright style 98 _updateEnabled: false, ///< is "update" method scheduled 99 _touchStartPos: null, ///< touch began point 100 _touchMovePos: null, ///< touch moved point 101 _touchEndPos: null, ///< touch ended point 102 103 _touchEventListener: null, 104 _touchEventSelector: null, 105 106 _name: "default", 107 _widgetType: null, 108 _actionTag: 0, 109 _size: null, 110 _customSize: null, 111 _layoutParameterDictionary: null, 112 _ignoreSize: false, 113 _widgetChildren: null, 114 _affectByClipping: false, 115 116 _sizeType: null, 117 _sizePercent: null, 118 _positionType: null, 119 _positionPercent: null, 120 _reorderWidgetChildDirty: false, 121 _hitted: false, 122 _nodes: null, 123 ctor: function () { 124 cc.NodeRGBA.prototype.ctor.call(this); 125 this._enabled = true; 126 this._bright = true; 127 this._touchEnabled = false; 128 this._touchPassedEnabled = false; 129 this._focus = false; 130 this._brightStyle = ccs.BrightStyle.none; 131 this._updateEnabled = false; 132 this._touchStartPos = cc.PointZero(); 133 this._touchMovePos = cc.PointZero(); 134 this._touchEndPos = cc.PointZero(); 135 this._touchEventListener = null; 136 this._touchEventSelector = null; 137 this._name = "default"; 138 this._widgetType = ccs.WidgetType.widget; 139 this._actionTag = 0; 140 this._size = cc.SizeZero(); 141 this._customSize = cc.SizeZero(); 142 this._layoutParameterDictionary = {}; 143 this._ignoreSize = false; 144 this._widgetChildren = []; 145 this._affectByClipping = false; 146 this._sizeType = ccs.SizeType.absolute; 147 this._sizePercent = cc.PointZero(); 148 this._positionType = ccs.PositionType.absolute; 149 this._positionPercent = cc.PointZero(); 150 this._reorderWidgetChildDirty = false; 151 this._hitted = false; 152 this._nodes = []; 153 }, 154 155 /** 156 * initializes state of widget. 157 * @returns {boolean} 158 */ 159 init: function () { 160 if (cc.NodeRGBA.prototype.init.call(this)){ 161 this._layoutParameterDictionary = {}; 162 this._widgetChildren = []; 163 this.initRenderer(); 164 this.setCascadeColorEnabled(true); 165 this.setCascadeOpacityEnabled(true); 166 this.setBright(true); 167 this.ignoreContentAdaptWithSize(true); 168 this.setAnchorPoint(cc.p(0.5, 0.5)); 169 } 170 return true; 171 }, 172 173 onEnter: function () { 174 this.updateSizeAndPosition(); 175 cc.NodeRGBA.prototype.onEnter.call(this); 176 }, 177 178 visit: function (ctx) { 179 if (this._enabled) { 180 cc.NodeRGBA.prototype.visit.call(this,ctx); 181 } 182 }, 183 184 /** 185 * Adds a child to the container. 186 * @param {ccs.Widget} child 187 */ 188 addChild: function (child, zOrder, tag) { 189 if(!(child instanceof ccs.Widget)){ 190 cc.log("Widget only supports Widgets as children"); 191 return; 192 } 193 cc.NodeRGBA.prototype.addChild.call(this, child, zOrder, tag); 194 this._widgetChildren.push(child); 195 }, 196 197 sortAllChildren: function () { 198 this._reorderWidgetChildDirty = this._reorderChildDirty; 199 cc.NodeRGBA.prototype.sortAllChildren.call(this); 200 if (this._reorderWidgetChildDirty) { 201 var _children = this._widgetChildren; 202 var i, j, length = _children.length, tempChild; 203 204 // insertion sort 205 for (i = 0; i < length; i++) { 206 var tempItem = _children[i]; 207 j = i - 1; 208 tempChild = _children[j]; 209 210 //continue moving element downwards while zOrder is smaller or when zOrder is the same but mutatedIndex is smaller 211 while (j >= 0 && ( tempItem._zOrder < tempChild._zOrder || 212 ( tempItem._zOrder == tempChild._zOrder && tempItem._orderOfArrival < tempChild._orderOfArrival ))) { 213 _children[j + 1] = tempChild; 214 j = j - 1; 215 tempChild = _children[j]; 216 } 217 _children[j + 1] = tempItem; 218 } 219 220 //don't need to check children recursively, that's done in visit of each child 221 222 this._reorderWidgetChildDirty = false; 223 } 224 }, 225 226 /** 227 * Return an array of children 228 * @returns {Array} 229 */ 230 getChildren: function () { 231 return this._widgetChildren; 232 }, 233 234 /** 235 * get the count of children 236 * @returns {Number} 237 */ 238 getChildrenCount: function () { 239 return this._widgetChildren ? this._widgetChildren.length : 0; 240 }, 241 242 getWidgetParent: function () { 243 var widget = this.getParent(); 244 if(widget instanceof ccs.Widget){ 245 return widget; 246 } 247 return null; 248 }, 249 250 removeFromParent: function (cleanup) { 251 cc.NodeRGBA.prototype.removeFromParent.call(this, cleanup); 252 }, 253 254 removeFromParentAndCleanup: function (cleanup) { 255 cc.NodeRGBA.prototype.removeFromParent.call(this, cleanup); 256 }, 257 258 /** 259 * remove child 260 * @param {ccs.Widget} child 261 * @param {Boolean} cleanup 262 */ 263 removeChild: function (child, cleanup) { 264 cc.NodeRGBA.prototype.removeChild.call(this, child, cleanup); 265 cc.ArrayRemoveObject(this._widgetChildren, child); 266 }, 267 268 removeChildByTag: function (tag, cleanup) { 269 var child = this.getChildByTag(tag); 270 271 if (child == null) { 272 cc.log("cocos2d: removeChildByTag(tag = " + tag + "): child not found!"); 273 } 274 else { 275 this.removeChild(child, cleanup); 276 } 277 }, 278 279 /** 280 * Removes all children from the container, and do a cleanup to all running actions depending on the cleanup parameter. 281 */ 282 removeAllChildren: function (cleanup) { 283 var childrenLength = this._widgetChildren.length; 284 if (childrenLength <= 0) { 285 return 286 } 287 cc.NodeRGBA.prototype.removeAllChildren.call(this, cleanup); 288 this._widgetChildren = []; 289 }, 290 291 /** 292 * Set enabled renderer 293 * @param {Boolean} enabled 294 */ 295 setEnabled: function (enabled) { 296 this._enabled = enabled; 297 var arrayChildren = this._widgetChildren; 298 var childrenCount = arrayChildren.length; 299 for (var i = 0; i < childrenCount; i++) { 300 var child = arrayChildren[i]; 301 child.setEnabled(enabled); 302 } 303 }, 304 305 /** 306 * Gets a child from the container with its name 307 * @param {string} name 308 * @returns {ccs.Widget} 309 */ 310 getChildByName: function (name) { 311 var arrayChildren = this._widgetChildren; 312 var childrenCount = arrayChildren.length; 313 for (var i = 0; i < childrenCount; i++) { 314 var child = arrayChildren[i]; 315 if (child.getName() == name) { 316 return child; 317 } 318 } 319 }, 320 321 /** 322 * initializes renderer of widget. 323 */ 324 initRenderer: function () { 325 }, 326 327 /** 328 * add node for widget 329 * @param {cc.Node} node 330 * @param {Number} zOrder 331 * @param {Number} tag 332 */ 333 addNode: function (node, zOrder, tag) { 334 if (node instanceof ccs.Widget) { 335 cc.log("Widget only supports Nodes as renderer"); 336 return; 337 } 338 cc.NodeRGBA.prototype.addChild.call(this, node, zOrder, tag); 339 this._nodes.push(node); 340 }, 341 342 /** 343 * get node by tag 344 * @param {Number} tag 345 * @returns {cc.Node} 346 */ 347 getNodeByTag: function (tag) { 348 for (var i = 0; i < this._nodes.length; i++) { 349 var node = this._nodes[i]; 350 if (node && node.getTag() == tag) { 351 return node; 352 } 353 } 354 return null; 355 }, 356 357 /** 358 * get all node 359 * @returns {Array} 360 */ 361 getNodes: function () { 362 return this._nodes; 363 }, 364 365 /** 366 * remove node 367 * @param {cc.Node} node 368 */ 369 removeNode: function (node) { 370 cc.NodeRGBA.prototype.removeChild.call(this, node); 371 cc.ArrayRemoveObject(this._nodes, node); 372 }, 373 374 /** 375 * remove node by tag 376 * @param tag 377 */ 378 removeNodeByTag: function (tag) { 379 var node = this.getNodeByTag(tag); 380 if (!node) { 381 cc.log("cocos2d: removeNodeByTag(tag = %d): child not found!", tag); 382 } 383 else { 384 this.removeNode(node); 385 } 386 }, 387 388 /** 389 * remove all node 390 */ 391 removeAllNodes: function () { 392 for (var i = 0; i < this._nodes.length; i++) { 393 var node = this._nodes[i]; 394 cc.NodeRGBA.prototype.removeChild.call(this, node); 395 } 396 this._nodes = []; 397 }, 398 399 /** 400 * Changes the size that is widget's size 401 * @param {cc.Size} size 402 */ 403 setSize: function (size) { 404 this._customSize.width = size.width; 405 this._customSize.height = size.height; 406 var locSize; 407 if (this._ignoreSize) { 408 locSize = this.getContentSize(); 409 } 410 else { 411 locSize = size; 412 } 413 this._size.width = locSize.width; 414 this._size.height = locSize.height; 415 416 if(this._running){ 417 var widgetParent = this.getWidgetParent(); 418 if(widgetParent){ 419 locSize = widgetParent.getSize(); 420 }else{ 421 locSize = this._parent.getContentSize(); 422 } 423 this._sizePercent.x = 0; 424 this._sizePercent.y = 0; 425 if(locSize.width>0){ 426 this._sizePercent.x = this._customSize.width / locSize.width; 427 } 428 if(locSize.height>0){ 429 this._sizePercent.y = this._customSize.height / locSize.height; 430 } 431 } 432 this.onSizeChanged(); 433 }, 434 435 /** 436 * Changes the percent that is widget's percent size 437 * @param {cc.Point} percent 438 */ 439 setSizePercent: function (percent) { 440 this._sizePercent = percent; 441 var size = cc.size(this._customSize.width, this._customSize.height); 442 if (this._running) { 443 var widgetParent = this.getWidgetParent(); 444 if (widgetParent) { 445 size.width = widgetParent.getSize().width * percent.x; 446 size.height = widgetParent.getSize().height * percent.y; 447 } 448 else { 449 size.width = this._parent.getContentSize().width * percent.x; 450 size.height = this._parent.getContentSize().height * percent.y; 451 } 452 } 453 var locSize; 454 if (this._ignoreSize) { 455 locSize = this.getContentSize(); 456 } 457 else { 458 locSize = size; 459 } 460 this._size.width = locSize.width; 461 this._size.height = locSize.height; 462 this._customSize.width = size.width; 463 this._customSize.height = size.height; 464 this.onSizeChanged(); 465 }, 466 467 /** 468 * update size and position 469 */ 470 updateSizeAndPosition: function () { 471 switch (this._sizeType) { 472 case ccs.SizeType.absolute: 473 var locSize; 474 if (this._ignoreSize) { 475 locSize = this.getContentSize(); 476 } 477 else { 478 locSize = this._customSize; 479 } 480 this._size.width = locSize.width; 481 this._size.height = locSize.height; 482 483 var pSize,spx=spy=0; 484 var widgetParent = this.getWidgetParent(); 485 if (widgetParent){ 486 pSize = widgetParent.getSize(); 487 }else{ 488 pSize = this._parent.getContentSize(); 489 } 490 if (pSize.width > 0) { 491 spx = this._customSize.width / pSize.width; 492 } 493 if (pSize.height > 0) { 494 spy = this._customSize.height / pSize.height; 495 } 496 this._sizePercent.x = spx; 497 this._sizePercent.y = spy; 498 break; 499 case ccs.SizeType.percent: 500 var widgetParent = this.getWidgetParent(); 501 var cSize = cc.size(0,0); 502 if (widgetParent){ 503 cSize.width = widgetParent.getSize().width * this._sizePercent.x; 504 cSize.height = widgetParent.getSize().height * this._sizePercent.x; 505 }else{ 506 cSize.width = this._parent.getContentSize().width * this._sizePercent.x; 507 cSize.height = this._parent.getContentSize().height * this._sizePercent.y; 508 } 509 var locSize; 510 if (this._ignoreSize) { 511 locSize = this.getContentSize(); 512 } 513 else { 514 locSize = cSize; 515 } 516 this._size.width = locSize.width; 517 this._size.height = locSize.height; 518 this._customSize.width = cSize.width; 519 this._customSize.height = cSize.height; 520 break; 521 default: 522 break; 523 } 524 this.onSizeChanged(); 525 var absPos = this.getPosition(); 526 switch (this._positionType) { 527 case ccs.PositionType.absolute: 528 var widgetParent = this.getWidgetParent(); 529 var pSize; 530 if(widgetParent){ 531 pSize = widgetParent.getSize(); 532 }else{ 533 pSize = this._parent.getContentSize(); 534 } 535 if(pSize.width<=0||pSize.height<=0){ 536 this._positionPercent.x = 0; 537 this._positionPercent.y = 0; 538 }else{ 539 this._positionPercent.x = absPos.x / pSize.width; 540 this._positionPercent.y = absPos.y / pSize.height; 541 } 542 break; 543 case ccs.PositionType.percent: 544 var widgetParent = this.getWidgetParent(); 545 var pSize; 546 if(widgetParent){ 547 pSize = widgetParent.getSize(); 548 }else{ 549 pSize = this._parent.getContentSize(); 550 } 551 absPos = cc.p(pSize.width * this._positionPercent.x, pSize.height * this._positionPercent.y); 552 break; 553 default: 554 break; 555 } 556 this.setPosition(absPos); 557 }, 558 559 /** 560 * Changes the size type of widget. 561 * @param {ccs.SizeType} type 562 */ 563 setSizeType: function (type) { 564 this._sizeType = type; 565 }, 566 567 /** 568 * Gets the size type of widget. 569 * @returns {ccs.SizeType} 570 */ 571 getSizeType: function () { 572 return this._sizeType; 573 }, 574 575 /** 576 * Ignore the widget size 577 * @param {Boolean} ignore 578 */ 579 ignoreContentAdaptWithSize: function (ignore) { 580 this._ignoreSize = ignore; 581 var locSize; 582 if (this._ignoreSize) { 583 locSize = this.getContentSize(); 584 } 585 else { 586 locSize = this._customSize; 587 } 588 this._size.width = locSize.width; 589 this._size.height = locSize.height; 590 this.onSizeChanged(); 591 }, 592 593 /** 594 * Gets the widget if is ignore it's size. 595 * @returns {boolean} 596 */ 597 isIgnoreContentAdaptWithSize: function () { 598 return this._ignoreSize; 599 }, 600 601 /** 602 * Returns size of widget 603 * @returns {cc.Size} 604 */ 605 getSize: function () { 606 return this._size; 607 }, 608 609 /** 610 * Returns size percent of widget 611 * @returns {cc.Point} 612 */ 613 getSizePercent: function () { 614 return this._sizePercent; 615 }, 616 617 /** 618 * Gets world position of widget. 619 * @returns {cc.Point} 620 */ 621 getWorldPosition: function () { 622 return this.convertToWorldSpace(cc.PointZero()); 623 }, 624 625 /** 626 * Gets the Virtual Renderer of widget. 627 * @returns {cc.Node} 628 */ 629 getVirtualRenderer: function () { 630 return this; 631 }, 632 633 /** 634 * call back function called when size changed. 635 */ 636 onSizeChanged: function () { 637 for (var i = 0; i < this._widgetChildren.length; i++) { 638 var child = this._widgetChildren[i]; 639 child.updateSizeAndPosition(); 640 } 641 }, 642 643 /** 644 * Gets the content size of widget. 645 * @returns {cc.Size} 646 */ 647 getContentSize: function () { 648 return this._size; 649 }, 650 651 /** 652 * Sets whether the widget is touch enabled 653 * @param enable 654 */ 655 setTouchEnabled: function (enable) { 656 this._touchEnabled = enable; 657 }, 658 659 /** 660 * To set the bright style of widget. 661 * @returns {boolean} 662 */ 663 isTouchEnabled: function () { 664 return this._touchEnabled; 665 }, 666 667 /** 668 * Schedules the "update" method. 669 * @param enable 670 */ 671 setUpdateEnabled: function (enable) { 672 if (this._updateEnabled == enable) { 673 return; 674 } 675 this._updateEnabled = enable; 676 if (enable) { 677 this.scheduleUpdate(); 678 } 679 else { 680 this.unscheduleUpdate(); 681 } 682 }, 683 684 /** 685 * is the "update" method scheduled. 686 * @returns {boolean} 687 */ 688 isUpdateEnabled: function () { 689 return this._updateEnabled; 690 }, 691 692 /** 693 * Determines if the widget is on focused 694 * @returns {boolean} 695 */ 696 isFocused: function () { 697 return this._focus; 698 }, 699 700 /** 701 * Sets whether the widget is on focused 702 * The default value is false, a widget is default to not on focused 703 * @param {boolean} fucos 704 */ 705 setFocused: function (fucos) { 706 if (fucos == this._focus) { 707 return; 708 } 709 this._focus = fucos; 710 if (this._bright) { 711 if (this._focus) { 712 this.setBrightStyle(ccs.BrightStyle.highlight); 713 } 714 else { 715 this.setBrightStyle(ccs.BrightStyle.normal); 716 } 717 } 718 else { 719 this.onPressStateChangedToDisabled(); 720 } 721 }, 722 723 setBright: function (bright, containChild) { 724 this._bright = bright; 725 if (this._bright) { 726 this._brightStyle = ccs.BrightStyle.none; 727 this.setBrightStyle(ccs.BrightStyle.normal); 728 } 729 else { 730 this.onPressStateChangedToDisabled(); 731 } 732 }, 733 734 /** 735 * To set the bright style of widget. 736 * @param {ccs.BrightStyle} style 737 */ 738 setBrightStyle: function (style) { 739 if (this._brightStyle == style) { 740 return; 741 } 742 style = style|| ccs.BrightStyle.normal; 743 this._brightStyle = style; 744 switch (this._brightStyle) { 745 case ccs.BrightStyle.normal: 746 this.onPressStateChangedToNormal(); 747 break; 748 case ccs.BrightStyle.highlight: 749 this.onPressStateChangedToPressed(); 750 break; 751 default: 752 break; 753 } 754 }, 755 756 /** 757 * call back function called widget's state changed to normal. 758 */ 759 onPressStateChangedToNormal: function () { 760 761 }, 762 763 /** 764 * call back function called widget's state changed to selected. 765 */ 766 onPressStateChangedToPressed: function () { 767 768 }, 769 770 /** 771 * call back function called widget's state changed to dark. 772 */ 773 onPressStateChangedToDisabled: function () { 774 775 }, 776 777 /** 778 * A call back function when widget lost of focus. 779 */ 780 didNotSelectSelf: function () { 781 782 }, 783 784 onTouchBegan: function (touch,event) { 785 var touchPoint = touch.getLocation(); 786 this._touchStartPos.x = touchPoint.x; 787 this._touchStartPos.y = touchPoint.y; 788 this._hitted = this.isEnabled() && this.isTouchEnabled()&& this.hitTest(touchPoint)&& this.clippingParentAreaContainPoint(touchPoint); 789 if(!this._hitted){ 790 return false; 791 } 792 this.setFocused(true); 793 var widgetParent = this.getWidgetParent(); 794 if (widgetParent) { 795 widgetParent.checkChildInfo(0, this, touchPoint); 796 } 797 this.pushDownEvent(); 798 return !this._touchPassedEnabled; 799 }, 800 801 onTouchMoved: function (touch,event) { 802 var touchPoint = touch.getLocation(); 803 this._touchMovePos.x = touchPoint.x; 804 this._touchMovePos.y = touchPoint.y; 805 this.setFocused(this.hitTest(touchPoint)); 806 var widgetParent = this.getWidgetParent(); 807 if (widgetParent) { 808 widgetParent.checkChildInfo(1, this, touchPoint); 809 } 810 this.moveEvent(); 811 }, 812 813 814 onTouchEnded: function (touch,event) { 815 var touchPoint = touch.getLocation(); 816 this._touchEndPos.x = touchPoint.x; 817 this._touchEndPos.y = touchPoint.y; 818 var focus = this._focus; 819 this.setFocused(false); 820 var widgetParent = this.getWidgetParent(); 821 if (widgetParent) { 822 widgetParent.checkChildInfo(2, this, touchPoint); 823 } 824 if (focus) { 825 this.releaseUpEvent(); 826 } 827 else { 828 this.cancelUpEvent(); 829 } 830 }, 831 832 /** 833 * A call back function called when widget is selected, and on touch canceled. 834 * @param {cc.Point} touchPoint 835 */ 836 onTouchCancelled: function (touchPoint) { 837 this.setFocused(false); 838 this.cancelUpEvent(); 839 }, 840 841 /** 842 * A call back function called when widget is selected, and on touch long clicked. 843 * @param {cc.Point} touchPoint 844 */ 845 onTouchLongClicked: function (touchPoint) { 846 this.longClickEvent(); 847 }, 848 849 //call back function called widget's state changed to dark. 850 851 pushDownEvent: function () { 852 if (this._touchEventListener && this._touchEventSelector) { 853 if (this._touchEventSelector) { 854 this._touchEventSelector.call(this._touchEventListener, this, ccs.TouchEventType.began); 855 } 856 } 857 }, 858 859 moveEvent: function () { 860 if (this._touchEventListener && this._touchEventSelector) { 861 if (this._touchEventSelector) { 862 this._touchEventSelector.call(this._touchEventListener, this, ccs.TouchEventType.moved); 863 } 864 } 865 }, 866 867 releaseUpEvent: function () { 868 if (this._touchEventListener && this._touchEventSelector) { 869 if (this._touchEventSelector) { 870 this._touchEventSelector.call(this._touchEventListener, this, ccs.TouchEventType.ended); 871 } 872 } 873 }, 874 875 cancelUpEvent: function () { 876 if (this._touchEventSelector) { 877 this._touchEventSelector.call(this._touchEventListener, this, ccs.TouchEventType.canceled); 878 } 879 }, 880 881 longClickEvent: function () { 882 883 }, 884 885 /** 886 * Sets the touch event target/selector of the menu item 887 * @param {Function} selector 888 * @param {Object} target 889 */ 890 addTouchEventListener: function (selector, target) { 891 this._touchEventSelector = selector; 892 this._touchEventListener = target; 893 }, 894 895 /** 896 * Checks a point if is in widget's space 897 * @param {cc.Point} pt 898 * @returns {boolean} 899 */ 900 hitTest: function (pt) { 901 var nsp = this.convertToNodeSpace(pt); 902 var bb = cc.rect(-this._size.width * this._anchorPoint.x, -this._size.height * this._anchorPoint.y, this._size.width, this._size.height); 903 if (nsp.x >= bb.x && nsp.x <= bb.x + bb.width && nsp.y >= bb.y && nsp.y <= bb.y + bb.height) { 904 return true; 905 } 906 return false; 907 }, 908 909 /** 910 * Checks a point if in parent's area. 911 * @param {cc.Point} pt 912 * @returns {Boolean} 913 */ 914 clippingParentAreaContainPoint: function (pt) { 915 this._affectByClipping = false; 916 var parent = this.getParent(); 917 var clippingParent = null; 918 while (parent) { 919 if (parent instanceof ccs.Layout) { 920 if (parent.isClippingEnabled()) { 921 this._affectByClipping = true; 922 clippingParent = parent; 923 break; 924 } 925 } 926 parent = parent.getParent(); 927 } 928 929 if (!this._affectByClipping) { 930 return true; 931 } 932 933 934 if (clippingParent) { 935 var bRet = false; 936 if (clippingParent.hitTest(pt)) { 937 bRet = true; 938 } 939 if (bRet) { 940 return clippingParent.clippingParentAreaContainPoint(pt); 941 } 942 return false; 943 } 944 return true; 945 }, 946 947 /** 948 * Sends the touch event to widget's parent 949 * @param {number} handleState 950 * @param {ccs.Widget} sender 951 * @param {cc.Point} touchPoint 952 */ 953 checkChildInfo: function (handleState, sender, touchPoint) { 954 var widgetParent = this.getWidgetParent(); 955 if (widgetParent) { 956 widgetParent.checkChildInfo(handleState, sender, touchPoint); 957 } 958 }, 959 960 /** 961 * Changes the position (x,y) of the widget . 962 * @param {cc.Point||Number} pos 963 * @param {Number} posY 964 */ 965 setPosition: function (pos, posY) { 966 if (this._running) { 967 var widgetParent = this.getWidgetParent(); 968 if (widgetParent) { 969 var pSize = widgetParent.getSize(); 970 if (pSize.width <= 0 || pSize.height <= 0) { 971 this._positionPercent.x = 0; 972 this._positionPercent.y = 0; 973 } 974 else { 975 if(posY){ 976 this._positionPercent.x = pos / pSize.width; 977 this._positionPercent.y = posY / pSize.height; 978 }else{ 979 this._positionPercent.x = pos.x / pSize.width; 980 this._positionPercent.y = pos.y / pSize.height; 981 } 982 } 983 } 984 } 985 986 cc.NodeRGBA.prototype.setPosition.apply(this,arguments); 987 }, 988 989 /** 990 * Changes the position (x,y) of the widget 991 * @param {cc.Point} percent 992 */ 993 setPositionPercent: function (percent) { 994 this._positionPercent = percent; 995 if (this._running) { 996 var widgetParent = this.getWidgetParent(); 997 if(widgetParent){ 998 var parentSize = widgetParent.getSize(); 999 var absPos = cc.p(parentSize.width * this._positionPercent.x, parentSize.height * this._positionPercent.y); 1000 this.setPosition(absPos); 1001 } 1002 } 1003 }, 1004 1005 updateAnchorPoint:function(){ 1006 this.setAnchorPoint(this.getAnchorPoint()); 1007 }, 1008 1009 /** 1010 * Gets the percent (x,y) of the widget 1011 * @returns {cc.Point} 1012 */ 1013 getPositionPercent: function () { 1014 return this._positionPercent; 1015 }, 1016 1017 /** 1018 * Changes the position type of the widget 1019 * @param {ccs.PositionType} type 1020 */ 1021 setPositionType: function (type) { 1022 this._positionType = type; 1023 }, 1024 1025 /** 1026 * Gets the position type of the widget 1027 * @returns {cc.pPositionType} 1028 */ 1029 getPositionType: function () { 1030 return this._positionType; 1031 }, 1032 1033 setFlippedX: function (flipX) { 1034 }, 1035 1036 isFlippedX: function () { 1037 return false; 1038 }, 1039 1040 setFlippedY: function (flipY) { 1041 }, 1042 isFlippedY: function () { 1043 return false; 1044 }, 1045 1046 /** 1047 * Determines if the widget is bright 1048 * @returns {boolean} 1049 */ 1050 isBright: function () { 1051 return this._bright; 1052 }, 1053 1054 /** 1055 * Determines if the widget is enabled 1056 * @returns {boolean} 1057 */ 1058 isEnabled: function () { 1059 return this._enabled; 1060 }, 1061 1062 /** 1063 * Gets the left boundary position of this widget. 1064 * @returns {number} 1065 */ 1066 getLeftInParent: function () { 1067 return this.getPosition().x - this.getAnchorPoint().x * this._size.width; 1068 }, 1069 1070 /** 1071 * Gets the bottom boundary position of this widget. 1072 * @returns {number} 1073 */ 1074 getBottomInParent: function () { 1075 return this.getPosition().y - this.getAnchorPoint().y * this._size.height; 1076 }, 1077 1078 /** 1079 * Gets the right boundary position of this widget. 1080 * @returns {number} 1081 */ 1082 getRightInParent: function () { 1083 return this.getLeftInParent() + this._size.width; 1084 }, 1085 1086 /** 1087 * Gets the top boundary position of this widget. 1088 * @returns {number} 1089 */ 1090 getTopInParent: function () { 1091 return this.getBottomInParent() + this._size.height; 1092 }, 1093 1094 /** 1095 * Gets touch start position 1096 * @returns {cc.Point} 1097 */ 1098 getTouchStartPos: function () { 1099 return this._touchStartPos; 1100 }, 1101 1102 /** 1103 * Gets touch move position 1104 * @returns {cc.Point} 1105 */ 1106 getTouchMovePos: function () { 1107 return this._touchMovePos; 1108 }, 1109 1110 /** 1111 * Gets touch end position 1112 * @returns {cc.Point} 1113 */ 1114 getTouchEndPos: function () { 1115 return this._touchEndPos; 1116 }, 1117 1118 /** 1119 * Sets the name of widget 1120 * @param {String} name 1121 */ 1122 setName: function (name) { 1123 this._name = name; 1124 }, 1125 1126 /** 1127 * Gets the name of widget 1128 * @returns {string} 1129 */ 1130 getName: function () { 1131 return this._name; 1132 }, 1133 1134 /** 1135 * get widget type 1136 * @returns {ccs.WidgetType} 1137 */ 1138 getWidgetType: function () { 1139 return this._widgetType; 1140 }, 1141 1142 /** 1143 * Sets layout parameter 1144 * @param {ccs.LayoutParameter} parameter 1145 */ 1146 setLayoutParameter: function (parameter) { 1147 this._layoutParameterDictionary[parameter.getLayoutType()] = parameter; 1148 }, 1149 1150 /** 1151 * Gets layout parameter 1152 * @param {ccs.LayoutParameterType} type 1153 * @returns {ccs.LayoutParameter} 1154 */ 1155 getLayoutParameter: function (type) { 1156 return this._layoutParameterDictionary[type]; 1157 }, 1158 1159 /** 1160 * Returns the "class name" of widget. 1161 * @returns {string} 1162 */ 1163 getDescription: function () { 1164 return "Widget"; 1165 }, 1166 1167 clone: function () { 1168 var clonedWidget = this.createCloneInstance(); 1169 clonedWidget.copyProperties(this); 1170 clonedWidget.copyClonedWidgetChildren(this); 1171 return clonedWidget; 1172 }, 1173 1174 createCloneInstance: function () { 1175 return ccs.Widget.create(); 1176 }, 1177 1178 copyClonedWidgetChildren: function (model) { 1179 var widgetChildren = model.getChildren(); 1180 for (var i = 0; i < widgetChildren.length; i++) { 1181 var locChild = widgetChildren[i]; 1182 if(locChild instanceof ccs.Widget){ 1183 this.addChild(locChild.clone()); 1184 } 1185 } 1186 }, 1187 1188 copySpecialProperties: function (model) { 1189 1190 }, 1191 1192 copyProperties: function (widget) { 1193 this.setEnabled(widget.isEnabled()); 1194 this.setVisible(widget.isVisible()); 1195 this.setBright(widget.isBright()); 1196 this.setTouchEnabled(widget.isTouchEnabled()); 1197 this._touchPassedEnabled = false; 1198 this.setZOrder(widget.getZOrder()); 1199 this.setUpdateEnabled(widget.isUpdateEnabled()); 1200 this.setTag(widget.getTag()); 1201 this.setName(widget.getName()); 1202 this.setActionTag(widget.getActionTag()); 1203 this._ignoreSize = widget._ignoreSize; 1204 this._size = widget._size; 1205 this._customSize = widget._customSize; 1206 this.copySpecialProperties(widget); 1207 this._sizeType = widget.getSizeType(); 1208 this._sizePercent = widget._sizePercent; 1209 this._positionType = widget._positionType; 1210 this._positionPercent = widget._positionPercent; 1211 this.setPosition(widget.getPosition()); 1212 this.setAnchorPoint(widget.getAnchorPoint()); 1213 this.setScaleX(widget.getScaleX()); 1214 this.setScaleY(widget.getScaleY()); 1215 this.setRotation(widget.getRotation()); 1216 this.setRotationX(widget.getRotationX()); 1217 this.setRotationY(widget.getRotationY()); 1218 this.setFlippedX(widget.isFlippedX()); 1219 this.setFlippedY(widget.isFlippedY()); 1220 this.setColor(widget.getColor()); 1221 this.setOpacity(widget.getOpacity()); 1222 this.setCascadeOpacityEnabled(widget.isCascadeOpacityEnabled()); 1223 this.setCascadeColorEnabled(widget.isCascadeColorEnabled()); 1224 this.onSizeChanged(); 1225 }, 1226 1227 /*temp action*/ 1228 setActionTag: function (tag) { 1229 this._actionTag = tag; 1230 }, 1231 1232 getActionTag: function () { 1233 return this._actionTag; 1234 } 1235 }); 1236 /** 1237 * allocates and initializes a UIWidget. 1238 * @constructs 1239 * @return {ccs.Widget} 1240 * @example 1241 * // example 1242 * var uiWidget = ccs.Widget.create(); 1243 */ 1244 ccs.Widget.create = function () { 1245 var widget = new ccs.Widget(); 1246 if (widget && widget.init()) { 1247 return widget; 1248 } 1249 return null; 1250 }; 1251