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