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.UIWidget 84 * @sample 85 * var uiWidget = ccs.UIWidget.create(); 86 * var uiLayer = ccs.UILayer.create(); 87 * uiLayer.addWidget(uiWidget); 88 * @class 89 * @extends ccs.Class 90 */ 91 ccs.UIWidget = ccs.Class.extend(/** @lends ccs.UIWidget# */{ 92 _enabled: true, ///< Highest control of widget 93 _visible: true, ///< is this widget visible 94 _bright: true, ///< is this widget bright 95 _touchEnabled: false, ///< is this widget touch endabled 96 _touchPassedEnabled: false, ///< is the touch event should be passed 97 _focus: false, ///< is the widget on focus 98 _widgetZOrder: 0, ///< z-order value that affects the draw order and touch order 99 _anchorPoint: null, ///< anchor point normalized 100 _widgetParent: null, ///< parent of widget 101 _brightStyle: null, ///< bright style 102 _updateEnabled: false, ///< is "update" method scheduled 103 _renderer: null, ///< base renderer 104 _touchStartPos: null, ///< touch began point 105 _touchMovePos: null, ///< touch moved point 106 _touchEndPos: null, ///< touch ended point 107 108 _touchEventListener: null, 109 _touchEventSelector: null, 110 111 112 _widgetTag: -1, 113 _name: "default", 114 _widgetType: null, 115 _actionTag: 0, 116 _size: null, 117 _customSize: null, 118 _layoutParameterDictionary: null, 119 _ignoreSize: false, 120 _children: null, 121 _affectByClipping: false, 122 123 _scheduler: null, 124 125 _sizeType: null, 126 _sizePercent: null, 127 _positionType: null, 128 _positionPercent: null, 129 _isRunning: false, 130 _userObject: null, 131 ctor: function () { 132 this._enabled = true; 133 this._visible = true; 134 this._bright = true; 135 this._touchEnabled = false; 136 this._touchPassedEnabled = false; 137 this._focus = false; 138 this._widgetZOrder = 0; 139 this._anchorPoint = cc.p(0.5, 0.5); 140 this._widgetParent = null; 141 this._brightStyle = ccs.BrightStyle.none; 142 this._updateEnabled = false; 143 this._renderer = null; 144 this._touchStartPos = cc.PointZero(); 145 this._touchMovePos = cc.PointZero(); 146 this._touchEndPos = cc.PointZero(); 147 this._touchEventListener = null; 148 this._touchEventSelector = null; 149 this._widgetTag = -1; 150 this._name = "default"; 151 this._widgetType = ccs.WidgetType.widget; 152 this._actionTag = 0; 153 this._size = cc.SizeZero(); 154 this._customSize = cc.SizeZero(); 155 this._layoutParameterDictionary = {}; 156 this._ignoreSize = false; 157 this._children = []; 158 this._affectByClipping = false; 159 this._scheduler = null; 160 this._sizeType = ccs.SizeType.absolute; 161 this._sizePercent = cc.PointZero(); 162 this._positionType = ccs.PositionType.absolute; 163 this._positionPercent = cc.PointZero(); 164 this._isRunning = false; 165 }, 166 167 /** 168 * initializes state of widget. 169 * @returns {boolean} 170 */ 171 init: function () { 172 this._layoutParameterDictionary = {}; 173 this._children = []; 174 this.initRenderer(); 175 this._renderer.setZOrder(this._widgetZOrder); 176 if (this._renderer.RGBAProtocol) { 177 this._renderer.setCascadeColorEnabled(true); 178 this._renderer.setCascadeOpacityEnabled(true); 179 } 180 this.setBright(true); 181 this.ignoreContentAdaptWithSize(true); 182 this._scheduler = cc.Director.getInstance().getScheduler(); 183 return true; 184 }, 185 /** 186 * Release texture resoures of widget. 187 * Release renderer. 188 * If you override releaseResoures, you shall call its parent's one, e.g. UIWidget::releaseResoures(). 189 */ 190 releaseResoures: function () { 191 this.setUpdateEnabled(false); 192 this.removeAllChildren(); 193 this._children=[]; 194 this._renderer.removeAllChildren(true); 195 this._renderer.removeFromParent(true); 196 this._renderer.release(); 197 }, 198 199 onEnter: function () { 200 var locChild; 201 for (var i = 0; i < this._children.length; i++) { 202 locChild = this._children[i]; 203 if (locChild instanceof ccs.UIWidget) 204 locChild.onEnter(); 205 } 206 this._isRunning = true; 207 this.updateSizeAndPosition(); 208 }, 209 210 onExit: function () { 211 this._isRunning = false; 212 var locChild; 213 for (var i = 0; i < this._children.length; i++) { 214 locChild = this._children[i]; 215 if (locChild instanceof ccs.UIWidget) 216 locChild.onExit(); 217 } 218 }, 219 220 /** 221 * Adds a child to the container. 222 * @param {ccs.UIWidget}child 223 * @returns {boolean} 224 */ 225 addChild: function (child) { 226 if (!child) { 227 return false; 228 } 229 if (cc.ArrayContainsObject(this._children, child)) { 230 return false; 231 } 232 child.setParent(this); 233 var childrenCount = this._children.length; 234 if (childrenCount <= 0) { 235 this._children.push(child); 236 } 237 else { 238 var seekSucceed = false; 239 for (var i = childrenCount - 1; i >= 0; --i) { 240 var widget = this._children[i]; 241 if (child.getZOrder() >= widget.getZOrder()) { 242 if (i == childrenCount - 1) { 243 this._children.push(child); 244 seekSucceed = true; 245 break; 246 } 247 else { 248 cc.ArrayAppendObjectToIndex(this._children, child, i + 1); 249 seekSucceed = true; 250 break; 251 } 252 } 253 } 254 if (!seekSucceed) { 255 cc.ArrayAppendObjectToIndex(this._children, child, 0); 256 } 257 } 258 child.getRenderer().setZOrder(child.getZOrder()); 259 this._renderer.addChild(child.getRenderer()); 260 if (this._isRunning) { 261 child.onEnter(); 262 } 263 return true; 264 }, 265 266 /** 267 * Adds a child to the container. 268 * @param {ccs.UIWidget} child 269 * @returns {boolean} 270 */ 271 removeChild: function (child) { 272 if (!child) { 273 return false; 274 } 275 if (cc.ArrayContainsObject(this._children, child)) { 276 if (this._isRunning) { 277 child.onExit(); 278 } 279 child.setUpdateEnabled(false); 280 child.setParent(null); 281 this._renderer.removeChild(child.getRenderer()); 282 cc.ArrayRemoveObject(this._children, child); 283 return true; 284 } 285 return false; 286 }, 287 288 /** 289 * Removes this widget itself from its parent widget. 290 * If the widget orphan, then it will destroy itself. 291 */ 292 removeFromParent: function () { 293 if (this._widgetParent) { 294 this._widgetParent.removeChild(this); 295 } 296 }, 297 298 /** 299 * Removes all children from the container, and do a cleanup to all running actions depending on the cleanup parameter. 300 */ 301 removeAllChildren: function () { 302 if (this._children.length <= 0) { 303 return; 304 } 305 var locChild; 306 for (var i = 0; i < this._children.length; ++i) { 307 locChild = this._children[i]; 308 this.removeChild(this._children[i]); 309 } 310 }, 311 312 /** 313 * Reorders a child according to a new z value. 314 * @param {ccs.UIWidget} child 315 */ 316 reorderChild: function (child) { 317 cc.ArrayRemoveObject(this._children, child); 318 var childrenCount = this._children.length; 319 if (childrenCount <= 0) { 320 this._children.push(child); 321 } 322 else { 323 var seekSucceed = false; 324 var arrayChildren = this._children; 325 for (var i = childrenCount - 1; i >= 0; --i) { 326 var widget = arrayChildren[i]; 327 if (child.getZOrder() >= widget.getZOrder()) { 328 if (i == childrenCount - 1) { 329 this._children.push(child); 330 seekSucceed = true; 331 break; 332 } 333 else { 334 cc.ArrayAppendObjectToIndex(this._children, child, i + 1); 335 seekSucceed = true; 336 break; 337 } 338 } 339 } 340 if (!seekSucceed) { 341 cc.ArrayAppendObjectToIndex(this._children, child, 0); 342 } 343 } 344 }, 345 346 /** 347 * Set enabled renderer 348 * @param {Boolean} enabled 349 */ 350 setEnabled: function (enabled) { 351 this._enabled = enabled; 352 this._renderer.setEnabled(enabled); 353 var arrayChildren = this._children; 354 var childrenCount = arrayChildren.length; 355 for (var i = 0; i < childrenCount; i++) { 356 var child = arrayChildren[i]; 357 child.setEnabled(enabled); 358 } 359 }, 360 361 /** 362 * Gets a child from the container with its name 363 * @param {string} name 364 * @returns {ccs.UIWidget} 365 */ 366 getChildByName: function (name) { 367 return ccs.UIHelper.seekWidgetByName(this, name); 368 }, 369 370 /** 371 * Gets a child from the container with its tag 372 * @param {number} tag 373 * @returns {ccs.UIWidget} 374 */ 375 getChildByTag: function (tag) { 376 return ccs.UIHelper.seekWidgetByTag(this, tag); 377 }, 378 379 /** 380 * Return an array of children 381 * @returns {Array} 382 */ 383 getChildren: function () { 384 return this._children; 385 }, 386 387 /** 388 * initializes renderer of widget. 389 */ 390 initRenderer: function () { 391 this._renderer = ccs.GUIRenderer.create(); 392 }, 393 394 /** 395 * Changes the size that is widget's size 396 * @param {cc.Size} size 397 */ 398 setSize: function (size) { 399 this._customSize.width = size.width; 400 this._customSize.height = size.height; 401 var locSize; 402 if (this._ignoreSize) { 403 locSize = this.getContentSize(); 404 } 405 else { 406 locSize = size; 407 } 408 this._size.width = locSize.width; 409 this._size.height = locSize.height; 410 411 if (this._isRunning) { 412 this._sizePercent = (this._widgetParent == null) ? cc.PointZero() : cc.p(this._customSize.width / this._widgetParent.getSize().width, this._customSize.height / this._widgetParent.getSize().height); 413 } 414 this.onSizeChanged(); 415 }, 416 417 /** 418 * Changes the percent that is widget's percent size 419 * @param {cc.Point} percent 420 */ 421 setSizePercent: function (percent) { 422 this._sizePercent = percent; 423 if (!this._isRunning) { 424 return; 425 } 426 var size = (this._widgetParent == null) ? cc.SizeZero() : cc.size(this._widgetParent.getSize().width * percent.x, this._widgetParent.getSize().height * percent.y); 427 var locSize; 428 if (this._ignoreSize) { 429 locSize = this.getContentSize(); 430 } 431 else { 432 locSize = size; 433 } 434 this._size.width = locSize.width; 435 this._size.height = locSize.height; 436 this._customSize.width = size.width; 437 this._customSize.height = size.height; 438 this.onSizeChanged(); 439 }, 440 441 /** 442 * update size and position 443 */ 444 updateSizeAndPosition: function () { 445 switch (this._sizeType) { 446 case ccs.SizeType.absolute: 447 var locSize; 448 if (this._ignoreSize) { 449 locSize = this.getContentSize(); 450 } 451 else { 452 locSize = this._customSize; 453 } 454 this._size.width = locSize.width; 455 this._size.height = locSize.height; 456 this._sizePercent = (this._widgetParent == null) ? cc.PointZero() : cc.p(this._customSize.width / this._widgetParent.getSize().width, this._customSize.height / this._widgetParent.getSize().height); 457 break; 458 case ccs.SizeType.percent: 459 var cSize = (this._widgetParent == null) ? cc.SizeZero() : cc.size(this._widgetParent.getSize().width * this._sizePercent.x, this._widgetParent.getSize().height * this._sizePercent.y); 460 var locSize; 461 if (this._ignoreSize) { 462 locSize = this.getContentSize(); 463 } 464 else { 465 locSize = cSize; 466 } 467 this._size.width = locSize.width; 468 this._size.height = locSize.height; 469 this._customSize.width = cSize.width; 470 this._customSize.height = cSize.height; 471 break; 472 default: 473 break; 474 } 475 this.onSizeChanged(); 476 var absPos = this.getPosition(); 477 switch (this._positionType) { 478 case ccs.PositionType.absolute: 479 this._positionPercent = (this._widgetParent == null) ? cc.PointZero() : cc.p(absPos.x / this._widgetParent.getSize().width, absPos.y / this._widgetParent.getSize().height); 480 break; 481 case ccs.PositionType.percent: 482 var parentSize = this._widgetParent.getSize(); 483 absPos = cc.p(parentSize.width * this._positionPercent.x, parentSize.height * this._positionPercent.y); 484 break; 485 default: 486 break; 487 } 488 this._renderer.setPosition(absPos); 489 }, 490 491 /** 492 * Changes the size type of widget. 493 * @param {ccs.SizeType} type 494 */ 495 setSizeType: function (type) { 496 this._sizeType = type; 497 }, 498 499 /** 500 * Gets the size type of widget. 501 * @returns {ccs.SizeType} 502 */ 503 getSizeType: function () { 504 return this._sizeType; 505 }, 506 507 /** 508 * Ignore the widget size 509 * @param {Boolean} ignore 510 */ 511 ignoreContentAdaptWithSize: function (ignore) { 512 this._ignoreSize = ignore; 513 var locSize = this.getContentSize(); 514 if (this._ignoreSize) { 515 locSize = this.getContentSize(); 516 } 517 else { 518 locSize = this._customSize; 519 } 520 this._size.width = locSize.width; 521 this._size.height = locSize.height; 522 this.onSizeChanged(); 523 }, 524 525 /** 526 * Gets the widget if is ignore it's size. 527 * @returns {boolean} 528 */ 529 isIgnoreContentAdaptWithSize: function () { 530 return this._ignoreSize; 531 }, 532 533 /** 534 * Returns size of widget 535 * @returns {cc.Size} 536 */ 537 getSize: function () { 538 return this._size; 539 }, 540 541 /** 542 * Returns size percent of widget 543 * @returns {cc.Point} 544 */ 545 getSizePercent: function () { 546 return this._sizePercent; 547 }, 548 549 /** 550 * Gets world position of widget. 551 * @returns {cc.Point} 552 */ 553 getWorldPosition: function () { 554 return this._renderer.convertToWorldSpace(cc.PointZero()); 555 }, 556 557 /** 558 * Converts a Point to world space coordinates. The result is in Points. 559 * @param {cc.Point} pt 560 * @returns {cc.Point} 561 */ 562 convertToWorldSpace: function (pt) { 563 return this._renderer.convertToWorldSpace(pt); 564 }, 565 566 /** 567 * Gets the Virtual Renderer of widget. 568 * @returns {cc.Node} 569 */ 570 getVirtualRenderer: function () { 571 return this._renderer; 572 }, 573 574 /** 575 * call back function called when size changed. 576 */ 577 onSizeChanged: function () { 578 579 }, 580 581 /** 582 * Gets the content size of widget. 583 * @returns {cc.Size} 584 */ 585 getContentSize: function () { 586 return this._size; 587 }, 588 589 /** 590 * set zOrder of widget 591 * @param {number} z 592 */ 593 setZOrder: function (z) { 594 this._widgetZOrder = z; 595 this._renderer.setZOrder(z); 596 if (this._widgetParent) { 597 this._widgetParent.reorderChild(this); 598 } 599 }, 600 601 /** 602 * get zOrder of widget 603 * @returns {number} 604 */ 605 getZOrder: function () { 606 return this._widgetZOrder; 607 }, 608 609 /** 610 * Sets whether the widget is touch enabled 611 * @param enable 612 */ 613 setTouchEnabled: function (enable) { 614 this._touchEnabled = enable; 615 }, 616 617 /** 618 * To set the bright style of widget. 619 * @returns {boolean} 620 */ 621 isTouchEnabled: function () { 622 return this._touchEnabled; 623 }, 624 625 /** 626 * Schedules the "update" method. 627 * @param enable 628 */ 629 setUpdateEnabled: function (enable) { 630 if(this._updateEnabled == enable){ 631 return; 632 } 633 this._updateEnabled = enable; 634 if (enable) { 635 if (this._scheduler) { 636 this._scheduler.scheduleUpdateForTarget(this, 0, false); 637 } 638 } 639 else { 640 if (this._scheduler) { 641 this._scheduler.unscheduleUpdateForTarget(this); 642 } 643 } 644 }, 645 646 /** 647 * is the "update" method scheduled. 648 * @returns {boolean} 649 */ 650 isUpdateEnabled: function () { 651 return this._updateEnabled; 652 }, 653 654 /** 655 * Determines if the widget is on focused 656 * @returns {boolean} 657 */ 658 isFocused: function () { 659 return this._focus; 660 }, 661 662 /** 663 * Sets whether the widget is on focused 664 * The default value is false, a widget is default to not on focused 665 * @param {boolean} fucos 666 */ 667 setFocused: function (fucos) { 668 if (fucos == this._focus) { 669 return; 670 } 671 this._focus = fucos; 672 if (this._bright) { 673 if (this._focus) { 674 this.setBrightStyle(ccs.BrightStyle.highlight); 675 } 676 else { 677 this.setBrightStyle(ccs.BrightStyle.normal); 678 } 679 } 680 else { 681 this.onPressStateChangedToDisabled(); 682 } 683 }, 684 685 /** 686 * To set the bright style of widget. 687 * @param {ccs.BrightStyle} style 688 */ 689 setBrightStyle: function (style) { 690 if (this._brightStyle == style) { 691 return; 692 } 693 style = style|| ccs.BrightStyle.normal; 694 this._brightStyle = style; 695 switch (this._brightStyle) { 696 case ccs.BrightStyle.normal: 697 this.onPressStateChangedToNormal(); 698 break; 699 case ccs.BrightStyle.highlight: 700 this.onPressStateChangedToPressed(); 701 break; 702 default: 703 break; 704 } 705 }, 706 707 /** 708 * call back function called widget's state changed to normal. 709 */ 710 onPressStateChangedToNormal: function () { 711 712 }, 713 714 /** 715 * call back function called widget's state changed to selected. 716 */ 717 onPressStateChangedToPressed: function () { 718 719 }, 720 721 /** 722 * call back function called widget's state changed to dark. 723 */ 724 onPressStateChangedToDisabled: function () { 725 726 }, 727 728 /** 729 * A call back function when widget lost of focus. 730 */ 731 didNotSelectSelf: function () { 732 733 }, 734 735 /** 736 * A call back function called when widget is selected, and on touch began. 737 * @param {cc.Ponit} touchPoint 738 * @returns {boolean} 739 */ 740 onTouchBegan: function (touchPoint) { 741 this.setFocused(true); 742 this._touchStartPos.x = touchPoint.x; 743 this._touchStartPos.y = touchPoint.y; 744 if (this._widgetParent) { 745 this._widgetParent.checkChildInfo(0, this, touchPoint); 746 } 747 this.pushDownEvent(); 748 return this._touchPassedEnabled; 749 }, 750 751 /** 752 * A call back function called when widget is selected, and on touch moved. 753 * @param {cc.Point} touchPoint 754 */ 755 onTouchMoved: function (touchPoint) { 756 this._touchMovePos.x = touchPoint.x; 757 this._touchMovePos.y = touchPoint.y; 758 this.setFocused(this.hitTest(touchPoint)); 759 if (this._widgetParent) { 760 this._widgetParent.checkChildInfo(1, this, touchPoint); 761 } 762 this.moveEvent(); 763 }, 764 765 /** 766 * A call back function called when widget is selected, and on touch ended. 767 * @param {cc.Point} touchPoint 768 */ 769 onTouchEnded: function (touchPoint) { 770 this._touchEndPos.x = touchPoint.x; 771 this._touchEndPos.y = touchPoint.y; 772 var focus = this._focus; 773 this.setFocused(false); 774 if (this._widgetParent) { 775 this._widgetParent.checkChildInfo(2, this, touchPoint); 776 } 777 if (focus) { 778 this.releaseUpEvent(); 779 } 780 else { 781 this.cancelUpEvent(); 782 } 783 }, 784 785 /** 786 * A call back function called when widget is selected, and on touch canceled. 787 * @param {cc.Point} touchPoint 788 */ 789 onTouchCancelled: function (touchPoint) { 790 this.setFocused(false); 791 this.cancelUpEvent(); 792 }, 793 794 /** 795 * A call back function called when widget is selected, and on touch long clicked. 796 * @param {cc.Point} touchPoint 797 */ 798 onTouchLongClicked: function (touchPoint) { 799 this.longClickEvent(); 800 }, 801 802 //call back function called widget's state changed to dark. 803 804 pushDownEvent: function () { 805 if (this._touchEventListener && this._touchEventSelector) { 806 if (this._touchEventSelector) { 807 this._touchEventSelector.call(this._touchEventListener, this, ccs.TouchEventType.began); 808 } 809 } 810 }, 811 812 moveEvent: function () { 813 if (this._touchEventListener && this._touchEventSelector) { 814 if (this._touchEventSelector) { 815 this._touchEventSelector.call(this._touchEventListener, this, ccs.TouchEventType.moved); 816 } 817 } 818 }, 819 820 releaseUpEvent: function () { 821 if (this._touchEventListener && this._touchEventSelector) { 822 if (this._touchEventSelector) { 823 this._touchEventSelector.call(this._touchEventListener, this, ccs.TouchEventType.ended); 824 } 825 } 826 }, 827 828 cancelUpEvent: function () { 829 if (this._touchEventSelector) { 830 this._touchEventSelector.call(this._touchEventListener, this, ccs.TouchEventType.canceled); 831 } 832 }, 833 834 longClickEvent: function () { 835 836 }, 837 838 /** 839 * Sets the touch event target/selector of the menu item 840 * @param {Function} selector 841 * @param {Object} target 842 */ 843 addTouchEventListener: function (selector, target) { 844 this._touchEventSelector = selector; 845 this._touchEventListener = target; 846 }, 847 848 /** 849 * Gets the renderer of widget 850 * @returns {cc.Node} 851 */ 852 getRenderer: function () { 853 return this._renderer; 854 }, 855 856 /** 857 * Add a CCNode for rendering. 858 * renderer is a CCNode, it's for drawing 859 * @param {cc.Node} renderer 860 * @param {number} zOrder 861 */ 862 addRenderer: function (renderer, zOrder) { 863 this._renderer.addChild(renderer, zOrder); 864 }, 865 866 /** 867 * Remove a CCNode from widget. 868 * @param {cc.Node} renderer 869 * @param {Boolean} cleanup 870 */ 871 removeRenderer: function (renderer, cleanup) { 872 this._renderer.removeChild(renderer, cleanup); 873 }, 874 875 /** 876 * Checks a point if is in widget's space 877 * @param {cc.Point} pt 878 * @returns {boolean} 879 */ 880 hitTest: function (pt) { 881 var nsp = this._renderer.convertToNodeSpace(pt); 882 var bb = cc.rect(-this._size.width * this._anchorPoint.x, -this._size.height * this._anchorPoint.y, this._size.width, this._size.height); 883 if (nsp.x >= bb.x && nsp.x <= bb.x + bb.width && nsp.y >= bb.y && nsp.y <= bb.y + bb.height) { 884 return true; 885 } 886 return false; 887 }, 888 889 /** 890 * Checks a point if in parent's area. 891 * @param {cc.Point} pt 892 * @returns {Boolean} 893 */ 894 clippingParentAreaContainPoint: function (pt) { 895 this._affectByClipping = false; 896 var parent = this.getParent(); 897 var clippingParent = null; 898 while (parent) { 899 if (parent instanceof ccs.UILayout) { 900 if (parent.isClippingEnabled()) { 901 this._affectByClipping = true; 902 clippingParent = parent; 903 break; 904 } 905 } 906 parent = parent.getParent(); 907 } 908 909 if (!this._affectByClipping) { 910 return true; 911 } 912 913 914 if (clippingParent) { 915 var bRet = false; 916 if (clippingParent.hitTest(pt)) { 917 bRet = true; 918 } 919 if (bRet) { 920 return clippingParent.clippingParentAreaContainPoint(pt); 921 } 922 return false; 923 } 924 return true; 925 }, 926 927 /** 928 * Sends the touch event to widget's parent 929 * @param {number} handleState 930 * @param {ccs.UIWidget} sender 931 * @param {cc.Point} touchPoint 932 */ 933 checkChildInfo: function (handleState, sender, touchPoint) { 934 if (this._widgetParent) { 935 this._widgetParent.checkChildInfo(handleState, sender, touchPoint); 936 } 937 }, 938 939 /** 940 * Changes the position (x,y) of the widget . 941 * @param {cc.Point} pos 942 */ 943 setPosition: function (pos) { 944 if (this._isRunning) { 945 this._positionPercent = (this._widgetParent == null) ? cc.PointZero() : cc.p(pos.x / this._widgetParent.getSize().width, pos.y / this._widgetParent.getSize().height); 946 } 947 this._renderer.setPosition(pos); 948 }, 949 950 /** 951 * Changes the position (x,y) of the widget 952 * @param {cc.Point} percent 953 */ 954 setPositionPercent: function (percent) { 955 this._positionPercent = percent; 956 if (this._isRunning) { 957 var parentSize = this._widgetParent.getSize(); 958 var absPos = cc.p(parentSize.width * this._positionPercent.x, parentSize.height * this._positionPercent.y); 959 this._renderer.setPosition(absPos); 960 } 961 }, 962 963 /** 964 * Sets the anchor point in percent. 965 * @param {cc.Point} pt 966 */ 967 setAnchorPoint: function (pt) { 968 this._anchorPoint.x = pt.x; 969 this._anchorPoint.y = pt.y; 970 this._renderer.setAnchorPoint(pt); 971 }, 972 973 updateAnchorPoint: function () { 974 this.setAnchorPoint(this._anchorPoint); 975 }, 976 977 /** 978 * Gets the position (x,y) of the widget 979 * @returns {cc.Point} 980 */ 981 getPosition: function () { 982 return this._renderer.getPosition(); 983 }, 984 985 /** 986 * Gets the percent (x,y) of the widget 987 * @returns {cc.Point} 988 */ 989 getPositionPercent: function () { 990 return this._positionPercent; 991 }, 992 993 /** 994 * Changes the position type of the widget 995 * @param {ccs.PositionType} type 996 */ 997 setPositionType: function (type) { 998 this._positionType = type; 999 }, 1000 1001 /** 1002 * Gets the position type of the widget 1003 * @returns {cc.pPositionType} 1004 */ 1005 getPositionType: function () { 1006 return this._positionType; 1007 }, 1008 1009 /** 1010 * Returns the anchor point in percent. 1011 * @returns {cc.Point} 1012 */ 1013 getAnchorPoint: function () { 1014 return this._anchorPoint; 1015 }, 1016 1017 /** 1018 * Changes both X and Y scale factor of the widget. 1019 * 1.0 is the default scale factor. It modifies the X and Y scale at the same time. 1020 * @param {number} scale 1021 */ 1022 setScale: function (scale) { 1023 this._renderer.setScale(scale); 1024 }, 1025 1026 /** 1027 * Gets the scale factor of the widget, when X and Y have the same scale factor. 1028 * @returns {number} 1029 */ 1030 getScale: function () { 1031 return this._renderer.getScale(); 1032 }, 1033 1034 /** 1035 * Changes the scale factor on X axis of this widget 1036 * @param {number} scaleX 1037 */ 1038 setScaleX: function (scaleX) { 1039 this._renderer.setScaleX(scaleX); 1040 }, 1041 1042 /** 1043 * Returns the scale factor on X axis of this widget 1044 * @returns {number} 1045 */ 1046 getScaleX: function () { 1047 return this._renderer.getScaleX(); 1048 }, 1049 1050 /** 1051 * Changes the scale factor on Y axis of this widget 1052 * @param {number} scaleY 1053 */ 1054 setScaleY: function (scaleY) { 1055 this._renderer.setScaleY(scaleY); 1056 }, 1057 1058 /** 1059 * Returns the scale factor on Y axis of this widget 1060 * @returns {number} 1061 */ 1062 getScaleY: function () { 1063 return this._renderer.getScaleY(); 1064 }, 1065 1066 /** 1067 * Sets the rotation (angle) of the widget in degrees. 1068 * @param {number} rotation 1069 */ 1070 setRotation: function (rotation) { 1071 this._renderer.setRotation(rotation); 1072 }, 1073 1074 /** 1075 * Returns the rotation of the widget in degrees. 1076 * @returns {number} 1077 */ 1078 getRotation: function () { 1079 return this._renderer.getRotation(); 1080 }, 1081 1082 /** 1083 * Sets the X rotation (angle) of the widget in degrees which performs a horizontal rotational skew. 1084 * @param {number} rotationX 1085 */ 1086 setRotationX: function (rotationX) { 1087 this._renderer.setRotationX(rotationX); 1088 }, 1089 1090 /** 1091 * Gets the X rotation (angle) of the widget in degrees which performs a horizontal rotation skew. 1092 * @returns {number} 1093 */ 1094 getRotationX: function () { 1095 return this._renderer.getRotationX(); 1096 }, 1097 1098 /** 1099 * Sets the Y rotation (angle) of the widget in degrees which performs a vertical rotational skew. 1100 * @param {number} rotationY 1101 */ 1102 setRotationY: function (rotationY) { 1103 this._renderer.setRotationY(rotationY); 1104 }, 1105 1106 /** 1107 * Gets the Y rotation (angle) of the widget in degrees which performs a vertical rotational skew. 1108 * @returns {number} 1109 */ 1110 getRotationY: function () { 1111 return this._renderer.getRotationY(); 1112 }, 1113 1114 /** 1115 * Sets whether the widget is visible 1116 * The default value is true, a widget is default to visible 1117 * @param {Boolean} visible 1118 */ 1119 setVisible: function (visible) { 1120 this._visible = visible; 1121 this._renderer.setVisible(visible); 1122 }, 1123 1124 /** 1125 * Sets whether the widget should be flipped horizontally or not. 1126 * @param {Boolean} flipX 1127 */ 1128 setFlippedX:function(flipX){ 1129 1130 }, 1131 1132 /** 1133 * Returns the flag which indicates whether the widget is flipped horizontally or not. 1134 * It only flips the texture of the widget, and not the texture of the widget's children. 1135 * Also, flipping the texture doesn't alter the anchorPoint. 1136 * If you want to flip the anchorPoint too, and/or to flip the children too use: 1137 * widget.setScaleX(sprite.getScaleX() * -1); 1138 * @return {Boolean} true if the widget is flipped horizaontally, false otherwise. 1139 */ 1140 isFlippedX:function(){ 1141 false; 1142 }, 1143 1144 /** 1145 * Sets whether the widget should be flipped vertically or not. 1146 * @param {Boolean} flipY 1147 */ 1148 setFlippedY:function(flipY){ 1149 1150 }, 1151 1152 /** 1153 * Return the flag which indicates whether the widget is flipped vertically or not. 1154 * It only flips the texture of the widget, and not the texture of the widget's children. 1155 * Also, flipping the texture doesn't alter the anchorPoint. 1156 * If you want to flip the anchorPoint too, and/or to flip the children too use: 1157 * widget.setScaleY(widget.getScaleY() * -1); 1158 * @return {Boolean} true if the widget is flipped vertically, flase otherwise. 1159 */ 1160 isFlippedY:function(){ 1161 false; 1162 }, 1163 1164 /** 1165 * Determines if the widget is visible 1166 * @returns {boolean} 1167 */ 1168 isVisible: function () { 1169 return this._visible; 1170 }, 1171 1172 /** 1173 * Determines if the widget is bright 1174 * @returns {boolean} 1175 */ 1176 isBright: function () { 1177 return this._bright; 1178 }, 1179 1180 /** 1181 * Determines if the widget is enabled 1182 * @returns {boolean} 1183 */ 1184 isEnabled: function () { 1185 return this._enabled; 1186 }, 1187 1188 /** 1189 * Gets the left boundary position of this widget. 1190 * @returns {number} 1191 */ 1192 getLeftInParent: function () { 1193 return this.getPosition().x - this.getAnchorPoint().x * this._size.width; 1194 }, 1195 1196 /** 1197 * Gets the bottom boundary position of this widget. 1198 * @returns {number} 1199 */ 1200 getBottomInParent: function () { 1201 return this.getPosition().y - this.getAnchorPoint().y * this._size.height;; 1202 }, 1203 1204 /** 1205 * Gets the right boundary position of this widget. 1206 * @returns {number} 1207 */ 1208 getRightInParent: function () { 1209 return this.getLeftInParent() + this._size.width; 1210 }, 1211 1212 /** 1213 * Gets the top boundary position of this widget. 1214 * @returns {number} 1215 */ 1216 getTopInParent: function () { 1217 return this.getBottomInParent() + this._size.height; 1218 }, 1219 1220 /** 1221 * Returns a pointer to the parent widget 1222 * @returns {ccs.UIWidget} 1223 */ 1224 getParent: function () { 1225 return this._widgetParent; 1226 }, 1227 1228 /** 1229 * Sets the parent widget 1230 * @param {ccs.UIWidget} parent 1231 */ 1232 setParent: function (parent) { 1233 this._widgetParent = parent; 1234 }, 1235 1236 /** 1237 * run action 1238 * @param {cc.Action} action 1239 * @returns {*} 1240 */ 1241 runAction: function (action) { 1242 this._renderer.runAction(action); 1243 }, 1244 1245 /** 1246 * Sets the CCActionManager object that is used by all actions. 1247 * @param {cc.ActionManager} actionManager 1248 */ 1249 setActionManager: function (actionManager) { 1250 this._renderer.setActionManager(actionManager); 1251 }, 1252 1253 /** 1254 * Gets the CCActionManager object that is used by all actions. 1255 * @returns {cc.ActionManager} 1256 */ 1257 getActionManager: function () { 1258 return this._renderer.getActionManager(); 1259 }, 1260 1261 /** 1262 * Stops and removes all actions from the running action list . 1263 */ 1264 stopAllActions: function () { 1265 this._renderer.stopAllActions(); 1266 }, 1267 1268 /** 1269 * Stops and removes an action from the running action list. 1270 * @param {cc.Action} action 1271 */ 1272 stopAction: function (action) { 1273 this._renderer.stopAction(action); 1274 }, 1275 1276 /** 1277 * Removes an action from the running action list by its tag. 1278 * @param {number} tag 1279 */ 1280 stopActionByTag: function (tag) { 1281 this._renderer.stopActionByTag(tag); 1282 }, 1283 1284 /** 1285 * Removes an action from the running action list by its tag. 1286 * @param {number} tag 1287 * @returns {cc.Action} 1288 */ 1289 getActionByTag: function (tag) { 1290 return this._renderer.getActionByTag(tag); 1291 }, 1292 1293 /** 1294 * Sets color to widget 1295 * @param {cc.c3b} color 1296 */ 1297 setColor: function (color) { 1298 if (this._renderer.RGBAProtocol) { 1299 this._renderer.setColor(color); 1300 } 1301 }, 1302 1303 /** 1304 * Gets color of widget 1305 * @returns {cc.c3b} 1306 */ 1307 getColor: function () { 1308 if (this._renderer.RGBAProtocol) { 1309 return this._renderer.getColor(); 1310 } 1311 return cc.WHITE; 1312 }, 1313 1314 /** 1315 * Sets opacity to widget 1316 * @param {number} opacity 1317 */ 1318 setOpacity: function (opacity) { 1319 if (this._renderer.RGBAProtocol) { 1320 this._renderer.setOpacity(opacity); 1321 } 1322 }, 1323 1324 /** 1325 * Gets opacity of widget 1326 * @returns {number} 1327 */ 1328 getOpacity: function () { 1329 if (this._renderer.RGBAProtocol) { 1330 return this._renderer.getOpacity(); 1331 } 1332 return 255; 1333 }, 1334 1335 /** 1336 * Gets whether cascadeOpacity is enabled 1337 * @returns {Boolean} 1338 */ 1339 isCascadeOpacityEnabled: function () { 1340 if (this._renderer.RGBAProtocol) { 1341 return this._renderer.isCascadeOpacityEnabled(); 1342 } 1343 return false; 1344 }, 1345 1346 /** 1347 * Sets cascade opacity enabled 1348 * @param {Boolean} cascadeOpacityEnabled 1349 */ 1350 setCascadeOpacityEnabled: function (cascadeOpacityEnabled) { 1351 if (this._renderer.RGBAProtocol) { 1352 this._renderer.setCascadeOpacityEnabled(cascadeOpacityEnabled); 1353 } 1354 }, 1355 1356 /** 1357 * Gets whether cascadeColor is enabled 1358 * @returns {Boolean} 1359 */ 1360 isCascadeColorEnabled: function () { 1361 if (this._renderer.RGBAProtocol) { 1362 return this._renderer.isCascadeColorEnabled(); 1363 } 1364 return false; 1365 }, 1366 1367 /** 1368 * Sets cascade color enabled 1369 * @param {Boolean} cascadeColorEnabled 1370 */ 1371 setCascadeColorEnabled: function (cascadeColorEnabled) { 1372 if (this._renderer.RGBAProtocol) { 1373 this._renderer.setCascadeColorEnabled(cascadeColorEnabled); 1374 } 1375 }, 1376 1377 /** 1378 * Sets blendFunc 1379 * @param {cc.BlendFunc} blendFunc 1380 */ 1381 setBlendFunc: function (blendFunc) { 1382 if (this._renderer.setBlendFunc) { 1383 this._renderer.setBlendFunc(blendFunc); 1384 } 1385 }, 1386 1387 /** 1388 * Gets touch start position 1389 * @returns {cc.Point} 1390 */ 1391 getTouchStartPos: function () { 1392 return this._touchStartPos; 1393 }, 1394 1395 /** 1396 * Gets touch move position 1397 * @returns {cc.Point} 1398 */ 1399 getTouchMovePos: function () { 1400 return this._touchMovePos; 1401 }, 1402 1403 /** 1404 * Gets touch end position 1405 * @returns {cc.Point} 1406 */ 1407 getTouchEndPos: function () { 1408 return this._touchEndPos; 1409 }, 1410 1411 /** 1412 * Sets widget tag 1413 * @param {Number} tag 1414 */ 1415 setTag: function (tag) { 1416 this._widgetTag = tag; 1417 }, 1418 1419 /** 1420 * Gets widget tag 1421 * @returns {Number} 1422 */ 1423 getTag: function () { 1424 return this._widgetTag; 1425 }, 1426 1427 /** 1428 * Sets the name of widget 1429 * @param {String} name 1430 */ 1431 setName: function (name) { 1432 this._name = name; 1433 }, 1434 1435 /** 1436 * Gets the name of widget 1437 * @returns {string} 1438 */ 1439 getName: function () { 1440 return this._name; 1441 }, 1442 1443 /** 1444 * get widget type 1445 * @returns {ccs.WidgetType} 1446 */ 1447 getWidgetType: function () { 1448 return this._widgetType; 1449 }, 1450 1451 /** 1452 * Sets layout parameter 1453 * @param {ccs.UILayoutParameter} parameter 1454 */ 1455 setLayoutParameter: function (parameter) { 1456 this._layoutParameterDictionary[parameter.getLayoutType()] = parameter; 1457 }, 1458 1459 /** 1460 * Gets layout parameter 1461 * @param {ccs.LayoutParameterType} type 1462 * @returns {ccs.UILayoutParameter} 1463 */ 1464 getLayoutParameter: function (type) { 1465 return this._layoutParameterDictionary[type]; 1466 }, 1467 1468 /** 1469 * Returns the "class name" of widget. 1470 * @returns {string} 1471 */ 1472 getDescription: function () { 1473 return "Widget"; 1474 }, 1475 1476 clone: function () { 1477 var clonedWidget = this.createCloneInstance(); 1478 clonedWidget.copyProperties(this); 1479 clonedWidget.copyClonedWidgetChildren(this); 1480 return clonedWidget; 1481 }, 1482 1483 createCloneInstance: function () { 1484 return ccs.UIWidget.create(); 1485 }, 1486 1487 copyClonedWidgetChildren: function (model) { 1488 var widgetChildren = model.getChildren(); 1489 for (var i = 0; i < widgetChildren.length; i++) { 1490 var locChild = widgetChildren[i]; 1491 this.addChild(locChild.clone()); 1492 } 1493 }, 1494 1495 copySpecialProperties: function (model) { 1496 1497 }, 1498 1499 copyProperties: function (widget) { 1500 this.setEnabled(widget.isEnabled()); 1501 this.setVisible(widget.isVisible()); 1502 this.setBright(widget.isBright()); 1503 this.setTouchEnabled(widget.isTouchEnabled()); 1504 this._touchPassedEnabled = false; 1505 this.setZOrder(widget.getZOrder()); 1506 this.setUpdateEnabled(widget.isUpdateEnabled()); 1507 this.setTag(widget.getTag()); 1508 this.setName(widget.getName()); 1509 this.setActionTag(widget.getActionTag()); 1510 this._ignoreSize = widget._ignoreSize; 1511 this._size = widget._size; 1512 this._customSize = widget._customSize; 1513 this.copySpecialProperties(widget); 1514 this._sizeType = widget.getSizeType(); 1515 this._sizePercent = widget._sizePercent; 1516 this._positionType = widget._positionType; 1517 this._positionPercent = widget._positionPercent; 1518 this.setPosition(widget.getPosition()); 1519 this.setAnchorPoint(widget.getAnchorPoint()); 1520 this.setScaleX(widget.getScaleX()); 1521 this.setScaleY(widget.getScaleY()); 1522 this.setRotation(widget.getRotation()); 1523 this.setRotationX(widget.getRotationX()); 1524 this.setRotationY(widget.getRotationY()); 1525 this.setFlippedX(widget.isFlippedX()); 1526 this.setFlippedY(widget.isFlippedY()); 1527 this.setColor(widget.getColor()); 1528 this.setOpacity(widget.getOpacity()); 1529 this.setCascadeOpacityEnabled(widget.isCascadeOpacityEnabled()); 1530 this.setCascadeColorEnabled(widget.isCascadeColorEnabled()); 1531 this.onSizeChanged(); 1532 }, 1533 1534 /*temp action*/ 1535 setActionTag: function (tag) { 1536 this._actionTag = tag; 1537 }, 1538 1539 getActionTag: function () { 1540 return this._actionTag; 1541 }, 1542 setTouchEnable: function (enabled, containChildren) { 1543 containChildren = containChildren || false; 1544 this.setTouchEnabled(enabled); 1545 if (containChildren) { 1546 var childrenArray = this.getChildren(); 1547 var length = childrenArray.length; 1548 var child; 1549 for (var i = 0; i < length; ++i) { 1550 child = childrenArray[i]; 1551 child.setTouchEnable(enabled, true); 1552 } 1553 } 1554 }, 1555 disable: function (containChildren) { 1556 containChildren = containChildren || false; 1557 this.setBright(false, containChildren); 1558 this.setTouchEnable(false, containChildren); 1559 }, 1560 active: function (containChildren) { 1561 containChildren = containChildren || false; 1562 this.setBright(true, containChildren); 1563 this.setTouchEnable(true, containChildren); 1564 }, 1565 isActive: function () { 1566 return this.isBright(); 1567 }, 1568 setBright: function (bright, containChild) { 1569 this._bright = bright; 1570 if (this._bright) { 1571 this._brightStyle = ccs.BrightStyle.none; 1572 this.setBrightStyle(ccs.BrightStyle.normal); 1573 } 1574 else { 1575 this.onPressStateChangedToDisabled(); 1576 } 1577 1578 if (containChild) { 1579 var childrenArray = this.getChildren(); 1580 var length = childrenArray.length; 1581 var child; 1582 for (var i = 0; i < length; ++i) { 1583 child = childrenArray[i]; 1584 child.setBright(bright, containChild); 1585 } 1586 } 1587 }, 1588 1589 getRect: function () { 1590 var wPos = this.getWorldPosition(); 1591 var width = this._size.width; 1592 var height = this._size.height; 1593 var offset_width = this._anchorPoint.x * width; 1594 var offset_height = this._anchorPoint.y * height; 1595 return cc.rect(wPos.x - offset_width, wPos.y - offset_height, width, height); 1596 }, 1597 getValidNode: function () { 1598 return this.getVirtualRenderer(); 1599 }, 1600 setWidgetZOrder: function (z) { 1601 this.setZOrder(z); 1602 }, 1603 getWidgetZOrder: function () { 1604 return this.getZOrder(); 1605 }, 1606 getRelativeLeftPos: function () { 1607 return this.getLeftInParent(); 1608 }, 1609 getRelativeBottomPos: function () { 1610 return this.getBottomInParent(); 1611 }, 1612 getRelativeRightPos: function () { 1613 return this.getRightInParent(); 1614 }, 1615 getRelativeTopPos: function () { 1616 return this.getTopInParent(); 1617 }, 1618 getContainerNode: function () { 1619 return this.getRenderer(); 1620 }, 1621 setWidgetParent: function (parent) { 1622 this.setParent(parent); 1623 }, 1624 getWidgetParent: function () { 1625 return this.getParent(); 1626 }, 1627 setWidgetTag: function (tag) { 1628 this.setTag(tag); 1629 }, 1630 getWidgetTag: function () { 1631 return this.getTag(); 1632 }, 1633 addCCNode: function (node) { 1634 this.addRenderer(node, 0); 1635 }, 1636 removeCCNode: function (cleanup) { 1637 this.removeRenderer(cleanup); 1638 }, 1639 setUserObject:function(userObject){ 1640 this._userObject = userObject; 1641 }, 1642 getUserObject:function(){ 1643 return this._userObject; 1644 } 1645 }); 1646 /** 1647 * allocates and initializes a UIWidget. 1648 * @constructs 1649 * @return {ccs.UIWidget} 1650 * @example 1651 * // example 1652 * var uiWidget = ccs.UIWidget.create(); 1653 */ 1654 ccs.UIWidget.create = function () { 1655 var widget = new ccs.UIWidget(); 1656 if (widget && widget.init()) { 1657 return widget; 1658 } 1659 return null; 1660 }; 1661 1662 /** 1663 * Base class for ccs.GUIRenderer 1664 * @class 1665 * @extends ccs.NodeRGBA 1666 */ 1667 ccs.GUIRenderer = ccs.NodeRGBA.extend({ 1668 _enabled: true, 1669 setEnabled: function (enabled) { 1670 this._enabled = enabled; 1671 }, 1672 1673 isEnabled: function () { 1674 return this._enabled; 1675 }, 1676 1677 visit: function (ctx) { 1678 if (!this._enabled) { 1679 return; 1680 } 1681 cc.NodeRGBA.prototype.visit.call(this, ctx); 1682 } 1683 }); 1684 /** 1685 * allocates and initializes a GUIRenderer. 1686 * @constructs 1687 * @return {ccs.GUIRenderer} 1688 * @example 1689 * // example 1690 * var guiRenderer = ccs.GUIRenderer.create(); 1691 */ 1692 ccs.GUIRenderer.create = function () { 1693 var widget = new ccs.GUIRenderer(); 1694 if (widget && widget.init()) { 1695 return widget; 1696 } 1697 return null; 1698 };