1 /**************************************************************************** 2 Copyright (c) 2011-2012 cocos2d-x.org 3 Copyright (c) 2013-2014 Chukong Technologies Inc. 4 5 http://www.cocos2d-x.org 6 7 Permission is hereby granted, free of charge, to any person obtaining a copy 8 of this software and associated documentation files (the "Software"), to deal 9 in the Software without restriction, including without limitation the rights 10 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 copies of the Software, and to permit persons to whom the Software is 12 furnished to do so, subject to the following conditions: 13 14 The above copyright notice and this permission notice shall be included in 15 all copies or substantial portions of the Software. 16 17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 THE SOFTWARE. 24 ****************************************************************************/ 25 26 ccui._FocusNavigationController = cc.Class.extend({ 27 _keyboardListener: null, 28 _firstFocusedWidget: null, 29 _enableFocusNavigation: false, 30 _keyboardEventPriority: 1, 31 32 enableFocusNavigation: function(flag){ 33 if (this._enableFocusNavigation === flag) 34 return; 35 36 this._enableFocusNavigation = flag; 37 if (flag) 38 this._addKeyboardEventListener(); 39 else 40 this._removeKeyboardEventListener(); 41 }, 42 43 _setFirstFocsuedWidget: function(widget){ 44 this._firstFocusedWidget = widget; 45 }, 46 47 _onKeyPressed: function(keyCode, event){ 48 if (this._enableFocusNavigation && this._firstFocusedWidget) { 49 if (keyCode === cc.KEY.dpadDown) { 50 this._firstFocusedWidget = this._firstFocusedWidget.findNextFocusedWidget(ccui.Widget.DOWN, this._firstFocusedWidget); 51 } 52 if (keyCode === cc.KEY.dpadUp){ 53 this._firstFocusedWidget = this._firstFocusedWidget.findNextFocusedWidget(ccui.Widget.UP, this._firstFocusedWidget); 54 } 55 if (keyCode === cc.KEY.dpadLeft) { 56 this._firstFocusedWidget = this._firstFocusedWidget.findNextFocusedWidget(ccui.Widget.LEFT, this._firstFocusedWidget); 57 } 58 if (keyCode === cc.KEY.dpadRight) { 59 this._firstFocusedWidget = this._firstFocusedWidget.findNextFocusedWidget(ccui.Widget.RIGHT, this._firstFocusedWidget); 60 } 61 } 62 }, 63 64 _addKeyboardEventListener: function(){ 65 if (!this._keyboardListener) { 66 this._keyboardListener = cc.EventListener.create({ 67 event: cc.EventListener.KEYBOARD, 68 onKeyReleased: this._onKeyPressed.bind(this) 69 }); 70 cc.eventManager.addListener(this._keyboardListener, this._keyboardEventPriority); 71 } 72 }, 73 74 _removeKeyboardEventListener: function(){ 75 if (this._keyboardListener) { 76 cc.eventManager.removeEventListener(this._keyboardListener); 77 this._keyboardListener = null; 78 } 79 } 80 }); 81 82 ccui.__LAYOUT_COMPONENT_NAME = "__ui_layout"; 83 84 /** 85 * The base class for ccui controls and layout 86 * @sample 87 * var uiWidget = new ccui.Widget(); 88 * this.addChild(uiWidget); 89 * @class 90 * @extends ccui.ProtectedNode 91 * 92 * @property {Number} xPercent - Position x in percentage of width 93 * @property {Number} yPercent - Position y in percentage of height 94 * @property {Number} widthPercent - Width in percentage of parent width 95 * @property {Number} heightPercent - Height in percentage of parent height 96 * @property {ccui.Widget} widgetParent - <@readonly> The direct parent when it's a widget also, otherwise equals null 97 * @property {Boolean} enabled - Indicate whether the widget is enabled 98 * @property {Boolean} focused - Indicate whether the widget is focused 99 * @property {ccui.Widget.SIZE_ABSOLUTE|ccui.Widget.SIZE_PERCENT} sizeType - The size type of the widget 100 * @property {ccui.Widget.TYPE_WIDGET|ccui.Widget.TYPE_CONTAINER} widgetType - <@readonly> The type of the widget 101 * @property {Boolean} touchEnabled - Indicate whether touch events are enabled 102 * @property {Boolean} updateEnabled - Indicate whether the update function is scheduled 103 * @property {Boolean} bright - Indicate whether the widget is bright 104 * @property {String} name - The name of the widget 105 * @property {Number} actionTag - The action tag of the widget 106 */ 107 ccui.Widget = ccui.ProtectedNode.extend(/** @lends ccui.Widget# */{ 108 _enabled: true, ///< Highest control of widget 109 _bright: true, ///< is this widget bright 110 _touchEnabled: false, ///< is this widget touch endabled 111 112 _brightStyle: null, ///< bright style 113 114 _touchBeganPosition: null, ///< touch began point 115 _touchMovePosition: null, ///< touch moved point 116 _touchEndPosition: null, ///< touch ended point 117 118 _touchEventListener: null, 119 _touchEventSelector: null, 120 121 _name: "default", 122 _widgetType: null, 123 _actionTag: 0, 124 _customSize: null, 125 _layoutParameterDictionary: null, 126 _layoutParameterType:0, 127 128 _focused: false, 129 _focusEnabled: true, 130 131 _ignoreSize: false, 132 _affectByClipping: false, 133 134 _sizeType: null, 135 _sizePercent: null, 136 _positionType: null, 137 _positionPercent: null, 138 _hit: false, 139 _nodes: null, 140 _touchListener: null, 141 _className: "Widget", 142 _flippedX: false, 143 _flippedY: false, 144 _opacity: 255, 145 _highlight: false, 146 147 _touchEventCallback: null, 148 _clickEventListener: null, 149 150 _propagateTouchEvents: true, 151 _unifySize: false, 152 153 _callbackName: null, 154 _callbackType: null, 155 _usingLayoutComponent: false, 156 157 /** 158 * Constructor function, override it to extend the construction behavior, remember to call "this._super()" in the extended "ctor" function. 159 * @function 160 */ 161 ctor: function () { 162 cc.ProtectedNode.prototype.ctor.call(this); 163 this._brightStyle = ccui.Widget.BRIGHT_STYLE_NONE; 164 this._touchBeganPosition = cc.p(0, 0); 165 this._touchMovePosition = cc.p(0, 0); 166 this._touchEndPosition = cc.p(0, 0); 167 this._widgetType = ccui.Widget.TYPE_WIDGET; 168 this._customSize = cc.size(0, 0); 169 this._layoutParameterDictionary = {}; 170 this._sizeType = ccui.Widget.SIZE_ABSOLUTE; 171 this._sizePercent = cc.p(0, 0); 172 this._positionType = ccui.Widget.POSITION_ABSOLUTE; 173 this._positionPercent = cc.p(0, 0); 174 this._nodes = []; 175 this._layoutParameterType = ccui.LayoutParameter.NONE; 176 this.init(); //TODO 177 }, 178 179 /** 180 * initializes state of widget. please do not call this function by yourself, you should pass the parameters to constructor to initialize it
. 181 * @returns {boolean} 182 */ 183 init: function () { 184 if (cc.ProtectedNode.prototype.init.call(this)) { 185 this._layoutParameterDictionary = {}; 186 this._initRenderer(); 187 this.setBright(true); 188 189 this.onFocusChanged = this.onFocusChange.bind(this); 190 this.onNextFocusedWidget = null; 191 this.setAnchorPoint(cc.p(0.5, 0.5)); 192 193 this.ignoreContentAdaptWithSize(true); 194 return true; 195 } 196 return false; 197 }, 198 199 /** 200 * Calls updateSizeAndPosition and its parent's onEnter 201 * @override 202 */ 203 onEnter: function () { 204 var locListener = this._touchListener; 205 if (locListener && !locListener._isRegistered() && this._touchEnabled) 206 cc.eventManager.addListener(locListener, this); 207 if(!this._usingLayoutComponent) 208 this.updateSizeAndPosition(); 209 cc.ProtectedNode.prototype.onEnter.call(this); 210 }, 211 212 /** 213 * Calls unscheduleUpdate and its parent's onExit 214 * @override 215 */ 216 onExit: function(){ 217 this.unscheduleUpdate(); 218 cc.ProtectedNode.prototype.onExit.call(this); 219 }, 220 221 _getOrCreateLayoutComponent: function(){ 222 var layoutComponent = this.getComponent(ccui.__LAYOUT_COMPONENT_NAME); 223 if (null == layoutComponent){ 224 layoutComponent = new ccui.LayoutComponent(); 225 this.addComponent(layoutComponent); 226 } 227 return layoutComponent; 228 }, 229 230 /** 231 * The direct parent when it's a widget also, otherwise equals null 232 * @returns {ccui.Widget|null} 233 */ 234 getWidgetParent: function () { 235 var widget = this.getParent(); 236 if (widget instanceof ccui.Widget) 237 return widget; 238 return null; 239 }, 240 241 _updateContentSizeWithTextureSize: function(size){ 242 if(this._unifySize){ 243 this.setContentSize(size); 244 return; 245 } 246 this.setContentSize(this._ignoreSize ? size : this._customSize); 247 }, 248 249 _isAncestorsEnabled: function(){ 250 var parentWidget = this._getAncensterWidget(this); 251 if (parentWidget == null) 252 return true; 253 if (parentWidget && !parentWidget.isEnabled()) 254 return false; 255 256 return parentWidget._isAncestorsEnabled(); 257 }, 258 259 /** 260 * Allow widget touch events to propagate to its parents. Set false will disable propagation 261 * @since v3.2 262 * @param {Boolean} isPropagate 263 */ 264 setPropagateTouchEvents: function(isPropagate){ 265 this._propagateTouchEvents = isPropagate; 266 }, 267 268 /** 269 * Return whether the widget is propagate touch events to its parents or not 270 * @since v3.2 271 * @returns {boolean} 272 */ 273 isPropagateTouchEvents: function(){ 274 return this._propagateTouchEvents; 275 }, 276 277 /** 278 * Specify widget to swallow touches or not 279 * @since v3.2 280 * @param {Boolean} swallow 281 */ 282 setSwallowTouches: function(swallow){ 283 if (this._touchListener) 284 this._touchListener.setSwallowTouches(swallow); 285 }, 286 287 /** 288 * Return whether the widget is swallowing touch or not 289 * @since v3.2 290 * @returns {boolean} 291 */ 292 isSwallowTouches: function(){ 293 if (this._touchListener){ 294 //return true; //todo need test 295 return this._touchListener.isSwallowTouches(); 296 } 297 return false; 298 }, 299 300 _getAncensterWidget: function(node){ 301 if (null == node) 302 return null; 303 304 var parent = node.getParent(); 305 if (null == parent) 306 return null; 307 308 if (parent instanceof ccui.Widget) 309 return parent; 310 else 311 return this._getAncensterWidget(parent.getParent()); 312 }, 313 314 _isAncestorsVisible: function(node){ 315 if (null == node) 316 return true; 317 318 var parent = node.getParent(); 319 320 if (parent && !parent.isVisible()) 321 return false; 322 return this._isAncestorsVisible(parent); 323 }, 324 325 _cleanupWidget: function(){ 326 //clean up _touchListener 327 this._eventDispatcher.removeEventListener(this._touchListener); 328 this._touchEnabled = false; 329 this._touchListener = null; 330 331 //cleanup focused widget and focus navigation controller 332 if (ccui.Widget._focusedWidget === this){ 333 ccui.Widget._focusedWidget = null; 334 ccui.Widget._focusNavigationController = null; 335 } 336 }, 337 338 /** 339 * <p> 340 * Sets whether the widget is enabled <br/> 341 * true if the widget is enabled, widget may be touched , false if the widget is disabled, widget cannot be touched. <br/> 342 * The default value is true, a widget is default to enabled 343 * </p> 344 * @param {Boolean} enabled 345 */ 346 setEnabled: function (enabled) { 347 this._enabled = enabled; 348 }, 349 350 /** 351 * initializes renderer of widget. 352 */ 353 _initRenderer: function () {}, 354 355 /** 356 * Sets _customSize of ccui.Widget, if ignoreSize is true, the content size is its renderer's contentSize, otherwise the content size is parameter. 357 * and updates size percent by parent content size. At last, updates its children's size and position. 358 * @param {cc.Size|Number} contentSize content size or width of content size 359 * @param {Number} [height] 360 * @override 361 */ 362 setContentSize: function(contentSize, height){ 363 var locWidth = (height === undefined) ? contentSize.width : contentSize; 364 var locHeight = (height === undefined) ? contentSize.height : height; 365 cc.Node.prototype.setContentSize.call(this, locWidth, locHeight); 366 367 this._customSize.width = locWidth; 368 this._customSize.height = locHeight; 369 if(this._unifySize){ 370 //unify size logic 371 } else if (this._ignoreSize){ 372 this._contentSize = this.getVirtualRendererSize(); 373 } 374 if (!this._usingLayoutComponent && this._running) { 375 var widgetParent = this.getWidgetParent(); 376 var pSize = widgetParent ? widgetParent.getContentSize() : this._parent.getContentSize(); 377 this._sizePercent.x = (pSize.width > 0.0) ? locWidth / pSize.width : 0.0; 378 this._sizePercent.y = (pSize.height > 0.0) ? locHeight / pSize.height : 0.0; 379 } 380 this._onSizeChanged(); 381 }, 382 383 _setWidth: function (w) { 384 cc.Node.prototype._setWidth.call(this, w); 385 this._customSize.width = w; 386 if(this._unifySize){ 387 //unify size logic 388 } else if (this._ignoreSize){ 389 this._contentSize = this.getVirtualRendererSize(); 390 } 391 392 if (!this._usingLayoutComponent && this._running) { 393 var widgetParent = this.getWidgetParent(); 394 var locWidth = widgetParent ? widgetParent.width : this._parent.width; 395 this._sizePercent.x = locWidth > 0 ? this._customSize.width / locWidth : 0; 396 } 397 this._onSizeChanged(); 398 }, 399 _setHeight: function (h) { 400 cc.Node.prototype._setHeight.call(this, h); 401 this._customSize.height = h; 402 if(this._unifySize){ 403 //unify size logic 404 } else if (this._ignoreSize){ 405 this._contentSize = this.getVirtualRendererSize(); 406 } 407 408 if (!this._usingLayoutComponent && this._running) { 409 var widgetParent = this.getWidgetParent(); 410 var locH = widgetParent ? widgetParent.height : this._parent.height; 411 this._sizePercent.y = locH > 0 ? this._customSize.height / locH : 0; 412 } 413 this._onSizeChanged(); 414 }, 415 416 /** 417 * Changes the percent that is widget's percent size 418 * @param {cc.Point} percent that is widget's percent size, width and height value from 0 to 1. 419 */ 420 setSizePercent: function (percent) { 421 if(this._usingLayoutComponent){ 422 var component = this._getOrCreateLayoutComponent(); 423 component.setUsingPercentContentSize(true); 424 component.setPercentContentSize(percent); 425 component.refreshLayout(); 426 return; 427 } 428 429 this._sizePercent.x = percent.x; 430 this._sizePercent.y = percent.y; 431 var width = this._customSize.width, height = this._customSize.height; 432 if (this._running) { 433 var widgetParent = this.getWidgetParent(); 434 if (widgetParent) { 435 width = widgetParent.width * percent.x; 436 height = widgetParent.height * percent.y; 437 } else { 438 width = this._parent.width * percent.x; 439 height = this._parent.height * percent.y; 440 } 441 } 442 if (this._ignoreSize) 443 this.setContentSize(this.getVirtualRendererSize()); 444 else 445 this.setContentSize(width, height); 446 447 this._customSize.width = width; 448 this._customSize.height = height; 449 }, 450 451 _setWidthPercent: function (percent) { 452 this._sizePercent.x = percent; 453 var width = this._customSize.width; 454 if (this._running) { 455 var widgetParent = this.getWidgetParent(); 456 width = (widgetParent ? widgetParent.width : this._parent.width) * percent; 457 } 458 if (this._ignoreSize) 459 this._setWidth(this.getVirtualRendererSize().width); 460 else 461 this._setWidth(width); 462 this._customSize.width = width; 463 }, 464 _setHeightPercent: function (percent) { 465 this._sizePercent.y = percent; 466 var height = this._customSize.height; 467 if (this._running) { 468 var widgetParent = this.getWidgetParent(); 469 height = (widgetParent ? widgetParent.height : this._parent.height) * percent; 470 } 471 if (this._ignoreSize) 472 this._setHeight(this.getVirtualRendererSize().height); 473 else 474 this._setHeight(height); 475 this._customSize.height = height; 476 }, 477 478 /** 479 * updates its size by size type and its position by position type. 480 * @param {cc.Size} [parentSize] parent size 481 */ 482 updateSizeAndPosition: function (parentSize) { 483 if(!parentSize){ 484 var widgetParent = this.getWidgetParent(); 485 if(widgetParent) 486 parentSize = widgetParent.getLayoutSize(); 487 else 488 parentSize = this._parent.getContentSize(); 489 } 490 491 switch (this._sizeType) { 492 case ccui.Widget.SIZE_ABSOLUTE: 493 if(this._ignoreSize) 494 this.setContentSize(this.getVirtualRendererSize()); 495 else 496 this.setContentSize(this._customSize); 497 this._sizePercent.x = (parentSize.width > 0) ? this._customSize.width / parentSize.width : 0; 498 this._sizePercent.y = (parentSize.height > 0) ? this._customSize.height / parentSize.height : 0; 499 break; 500 case ccui.Widget.SIZE_PERCENT: 501 var cSize = cc.size(parentSize.width * this._sizePercent.x , parentSize.height * this._sizePercent.y); 502 if(this._ignoreSize) 503 this.setContentSize(this.getVirtualRendererSize()); 504 else 505 this.setContentSize(cSize); 506 this._customSize.width = cSize.width; 507 this._customSize.height = cSize.height; 508 break; 509 default: 510 break; 511 } 512 this._onSizeChanged(); 513 var absPos = this.getPosition(); 514 switch (this._positionType) { 515 case ccui.Widget.POSITION_ABSOLUTE: 516 if (parentSize.width <= 0 || parentSize.height <= 0) { 517 this._positionPercent.x = this._positionPercent.y = 0; 518 } else { 519 this._positionPercent.x = absPos.x / parentSize.width; 520 this._positionPercent.y = absPos.y / parentSize.height; 521 } 522 break; 523 case ccui.Widget.POSITION_PERCENT: 524 absPos = cc.p(parentSize.width * this._positionPercent.x, parentSize.height * this._positionPercent.y); 525 break; 526 default: 527 break; 528 } 529 if(this._parent instanceof ccui.ImageView){ 530 var renderer = this._parent._imageRenderer; 531 if(renderer && !renderer._textureLoaded) 532 return; 533 } 534 this.setPosition(absPos); 535 }, 536 537 /**TEXTURE_RES_TYPE 538 * Changes the size type of widget. 539 * @param {ccui.Widget.SIZE_ABSOLUTE|ccui.Widget.SIZE_PERCENT} type that is widget's size type 540 */ 541 setSizeType: function (type) { 542 this._sizeType = type; 543 if (this._usingLayoutComponent) { 544 var component = this._getOrCreateLayoutComponent(); 545 component.setUsingPercentContentSize(this._sizeType === ccui.SIZE_PERCENT); 546 } 547 }, 548 549 /** 550 * Gets the size type of widget. 551 * @returns {ccui.Widget.SIZE_ABSOLUTE|ccui.Widget.SIZE_PERCENT} that is widget's size type 552 */ 553 getSizeType: function () { 554 return this._sizeType; 555 }, 556 557 /** 558 * Ignore the widget size 559 * @param {Boolean} ignore true that widget will ignore it's size, use texture size, false otherwise. Default value is true. 560 */ 561 ignoreContentAdaptWithSize: function (ignore) { 562 if(this._unifySize){ 563 this.setContentSize(this._customSize); 564 return; 565 } 566 567 if(this._ignoreSize === ignore) 568 return; 569 570 this._ignoreSize = ignore; 571 this.setContentSize( ignore ? this.getVirtualRendererSize() : this._customSize ); 572 //this._onSizeChanged(); 573 }, 574 575 /** 576 * Gets whether ignore the content size (custom size) 577 * @returns {boolean} true that widget will ignore it's size, use texture size, false otherwise. 578 */ 579 isIgnoreContentAdaptWithSize: function () { 580 return this._ignoreSize; 581 }, 582 583 /** 584 * Get custom size of ccui.Widget 585 * @returns {cc.Size} 586 */ 587 getCustomSize: function () { 588 return cc.size(this._customSize); 589 }, 590 591 /** 592 * Gets layout size of ccui.Widget. 593 * @returns {cc.Size} 594 */ 595 getLayoutSize: function(){ 596 return cc.size(this._contentSize); 597 }, 598 599 /** 600 * Returns size percent of ccui.Widget 601 * @returns {cc.Point} 602 */ 603 getSizePercent: function () { 604 if(this._usingLayoutComponent){ 605 var component = this._getOrCreateLayoutComponent(); 606 this._sizePercent = component.getPercentContentSize(); 607 } 608 return this._sizePercent; 609 }, 610 _getWidthPercent: function () { 611 return this._sizePercent.x; 612 }, 613 _getHeightPercent: function () { 614 return this._sizePercent.y; 615 }, 616 617 /** 618 * Gets world position of ccui.Widget. 619 * @returns {cc.Point} world position of ccui.Widget. 620 */ 621 getWorldPosition: function () { 622 return this.convertToWorldSpace(cc.p(this._anchorPoint.x * this._contentSize.width, this._anchorPoint.y * this._contentSize.height)); 623 }, 624 625 /** 626 * Gets the Virtual Renderer of widget. 627 * @returns {ccui.Widget} 628 */ 629 getVirtualRenderer: function () { 630 return this; 631 }, 632 633 /** 634 * Gets the content size of widget. Content size is widget's texture size. 635 */ 636 getVirtualRendererSize:function(){ 637 return cc.size(this._contentSize); 638 }, 639 640 /** 641 * call back function called when size changed. 642 */ 643 _onSizeChanged: function () { 644 if(!this._usingLayoutComponent){ 645 var locChildren = this.getChildren(); 646 for (var i = 0, len = locChildren.length; i < len; i++) { 647 var child = locChildren[i]; 648 if(child instanceof ccui.Widget) 649 child.updateSizeAndPosition(); 650 } 651 } 652 }, 653 654 /** 655 * Sets whether the widget is touch enabled. The default value is false, a widget is default to touch disabled 656 * @param {Boolean} enable true if the widget is touch enabled, false if the widget is touch disabled. 657 */ 658 setTouchEnabled: function (enable) { 659 if (this._touchEnabled === enable) 660 return; 661 662 this._touchEnabled = enable; //TODO need consider remove and re-add. 663 if (this._touchEnabled) { 664 if(!this._touchListener) 665 this._touchListener = cc.EventListener.create({ 666 event: cc.EventListener.TOUCH_ONE_BY_ONE, 667 swallowTouches: true, 668 onTouchBegan: this.onTouchBegan.bind(this), 669 onTouchMoved: this.onTouchMoved.bind(this), 670 onTouchEnded: this.onTouchEnded.bind(this) 671 }); 672 cc.eventManager.addListener(this._touchListener, this); 673 } else { 674 cc.eventManager.removeListener(this._touchListener); 675 } 676 }, 677 678 /** 679 * Returns whether or not touch is enabled. 680 * @returns {boolean} true if the widget is touch enabled, false if the widget is touch disabled. 681 */ 682 isTouchEnabled: function () { 683 return this._touchEnabled; 684 }, 685 686 /** 687 * Determines if the widget is highlighted 688 * @returns {boolean} true if the widget is highlighted, false if the widget is not highlighted . 689 */ 690 isHighlighted: function(){ 691 return this._highlight; 692 }, 693 694 /** 695 * Sets whether the widget is highlighted. The default value is false, a widget is default to not highlighted 696 * @param highlight true if the widget is highlighted, false if the widget is not highlighted. 697 */ 698 setHighlighted:function(highlight){ 699 if (highlight === this._highlight) 700 return; 701 this._highlight = highlight; 702 if (this._bright) { 703 if (this._highlight) 704 this.setBrightStyle(ccui.Widget.BRIGHT_STYLE_HIGH_LIGHT); 705 else 706 this.setBrightStyle(ccui.Widget.BRIGHT_STYLE_NORMAL); 707 } else 708 this._onPressStateChangedToDisabled(); 709 }, 710 711 /** 712 * Determines if the widget is on focused 713 * @returns {boolean} whether the widget is focused or not 714 */ 715 isFocused: function () { 716 return this._focused; 717 }, 718 719 /** 720 * Sets whether the widget is on focused 721 * The default value is false, a widget is default to not on focused 722 * @param {boolean} focus pass true to let the widget get focus or pass false to let the widget lose focus 723 */ 724 setFocused: function (focus) { 725 this._focused = focus; 726 //make sure there is only one focusedWidget 727 if (focus){ 728 ccui.Widget._focusedWidget = this; 729 if(ccui.Widget._focusNavigationController) 730 ccui.Widget._focusNavigationController._setFirstFocsuedWidget(this); 731 } 732 }, 733 734 /** 735 * returns whether the widget could accept focus. 736 * @returns {boolean} true represent the widget could accept focus, false represent the widget couldn't accept focus 737 */ 738 isFocusEnabled: function(){ 739 return this._focusEnabled; 740 }, 741 742 /** 743 * sets whether the widget could accept focus. 744 * @param {Boolean} enable true represent the widget could accept focus, false represent the widget couldn't accept focus 745 */ 746 setFocusEnabled: function(enable){ 747 this._focusEnabled = enable; 748 }, 749 750 /** 751 * <p> 752 * When a widget is in a layout, you could call this method to get the next focused widget within a specified direction. <br/> 753 * If the widget is not in a layout, it will return itself 754 * </p> 755 * @param direction the direction to look for the next focused widget in a layout 756 * @param current the current focused widget 757 * @return the next focused widget in a layout 758 */ 759 findNextFocusedWidget: function( direction, current){ 760 if (null === this.onNextFocusedWidget || null == this.onNextFocusedWidget(direction) ) { 761 var isLayout = current instanceof ccui.Layout; 762 if (this.isFocused() || isLayout) { 763 var layout = this.getParent(); 764 if (null === layout || !(layout instanceof ccui.Layout)){ 765 //the outer layout's default behaviour is : loop focus 766 if (isLayout) 767 return current.findNextFocusedWidget(direction, current); 768 return current; 769 } else 770 return layout.findNextFocusedWidget(direction, current); 771 } else 772 return current; 773 } else { 774 var getFocusWidget = this.onNextFocusedWidget(direction); 775 this.dispatchFocusEvent(this, getFocusWidget); 776 return getFocusWidget; 777 } 778 }, 779 780 /** 781 * when a widget calls this method, it will get focus immediately. 782 */ 783 requestFocus: function(){ 784 if (this === ccui.Widget._focusedWidget) 785 return; 786 this.dispatchFocusEvent(ccui.Widget._focusedWidget, this); 787 }, 788 789 /** 790 * no matter what widget object you call this method on , it will return you the exact one focused widget 791 */ 792 getCurrentFocusedWidget: function(){ 793 return ccui.Widget._focusedWidget; 794 }, 795 796 /** 797 * <p> 798 * When a widget lose/get focus, this method will be called. Be Caution when you provide your own version, <br/> 799 * you must call widget.setFocused(true/false) to change the focus state of the current focused widget; 800 * </p> 801 */ 802 onFocusChanged: null, 803 804 /** 805 * use this function to manually specify the next focused widget regards to each direction 806 */ 807 onNextFocusedWidget: null, 808 809 /** 810 * Sends the touch event to widget's parent, its subclass will override it, e.g. ccui.ScrollView, ccui.PageView 811 * @param {Number} eventType 812 * @param {ccui.Widget} sender 813 * @param {cc.Touch} touch 814 */ 815 interceptTouchEvent: function(eventType, sender, touch){ 816 var widgetParent = this.getWidgetParent(); 817 if (widgetParent) 818 widgetParent.interceptTouchEvent(eventType,sender,touch); 819 }, 820 821 /** 822 * This method is called when a focus change event happens 823 * @param {ccui.Widget} widgetLostFocus 824 * @param {ccui.Widget} widgetGetFocus 825 */ 826 onFocusChange: function(widgetLostFocus, widgetGetFocus){ 827 //only change focus when there is indeed a get&lose happens 828 if (widgetLostFocus) 829 widgetLostFocus.setFocused(false); 830 if (widgetGetFocus) 831 widgetGetFocus.setFocused(true); 832 }, 833 834 /** 835 * Dispatch a EventFocus through a EventDispatcher 836 * @param {ccui.Widget} widgetLostFocus 837 * @param {ccui.Widget} widgetGetFocus 838 */ 839 dispatchFocusEvent: function(widgetLostFocus, widgetGetFocus){ 840 //if the widgetLoseFocus doesn't get focus, it will use the previous focused widget instead 841 if (widgetLostFocus && !widgetLostFocus.isFocused()) 842 widgetLostFocus = ccui.Widget._focusedWidget; 843 844 if (widgetGetFocus !== widgetLostFocus){ 845 if (widgetGetFocus && widgetGetFocus.onFocusChanged) 846 widgetGetFocus.onFocusChanged(widgetLostFocus, widgetGetFocus); 847 if (widgetLostFocus && widgetGetFocus.onFocusChanged) 848 widgetLostFocus.onFocusChanged(widgetLostFocus, widgetGetFocus); 849 cc.eventManager.dispatchEvent(new cc.EventFocus(widgetLostFocus, widgetGetFocus)); 850 } 851 }, 852 853 /** 854 * Sets whether the widget is bright. The default value is true, a widget is default to bright 855 * @param {Boolean} bright true if the widget is bright, false if the widget is dark. 856 */ 857 setBright: function (bright) { 858 this._bright = bright; 859 if (this._bright) { 860 this._brightStyle = ccui.Widget.BRIGHT_STYLE_NONE; 861 this.setBrightStyle(ccui.Widget.BRIGHT_STYLE_NORMAL); 862 } else 863 this._onPressStateChangedToDisabled(); 864 }, 865 866 /** 867 * To set the bright style of ccui.Widget. 868 * @param {Number} style BRIGHT_NORMAL the widget is normal state, BRIGHT_HIGHLIGHT the widget is height light state. 869 */ 870 setBrightStyle: function (style) { 871 if (this._brightStyle === style) 872 return; 873 874 style = style || ccui.Widget.BRIGHT_STYLE_NORMAL; 875 this._brightStyle = style; 876 switch (this._brightStyle) { 877 case ccui.Widget.BRIGHT_STYLE_NORMAL: 878 this._onPressStateChangedToNormal(); 879 break; 880 case ccui.Widget.BRIGHT_STYLE_HIGH_LIGHT: 881 this._onPressStateChangedToPressed(); 882 break; 883 default: 884 break; 885 } 886 }, 887 888 _onPressStateChangedToNormal: function () {}, 889 890 _onPressStateChangedToPressed: function () {}, 891 892 _onPressStateChangedToDisabled: function () {}, 893 894 _updateChildrenDisplayedRGBA: function(){ 895 this.setColor(this.getColor()); 896 this.setOpacity(this.getOpacity()); 897 }, 898 899 /** 900 * A call back function when widget lost of focus. 901 */ 902 didNotSelectSelf: function () {}, 903 904 /** 905 * <p> 906 * The callback of touch began event. <br/> 907 * If the bounding box of ccui.Widget contains the touch point, it will do the following things: <br/> 908 * 1. sets highlight state, <br/> 909 * 2. sends event to parent widget by interceptTouchEvent <br/> 910 * 3. calls the callback of touch began event. <br/> 911 * 4. returns true, <br/> 912 * otherwise returns false directly. <br/> 913 * </p> 914 * @override 915 * @param {cc.Touch} touch 916 * @param {cc.Event} event 917 * @returns {boolean} 918 */ 919 onTouchBegan: function (touch, event) { 920 this._hit = false; 921 if (this.isVisible() && this.isEnabled() && this._isAncestorsEnabled() && this._isAncestorsVisible(this) ){ 922 var touchPoint = touch.getLocation(); 923 this._touchBeganPosition.x = touchPoint.x; 924 this._touchBeganPosition.y = touchPoint.y; 925 if(this.hitTest(this._touchBeganPosition) && this.isClippingParentContainsPoint(this._touchBeganPosition)) 926 this._hit = true; 927 } 928 if (!this._hit) { 929 return false; 930 } 931 this.setHighlighted(true); 932 933 /* 934 * Propagate touch events to its parents 935 */ 936 if (this._propagateTouchEvents) { 937 this.propagateTouchEvent(ccui.Widget.TOUCH_BEGAN, this, touch); 938 } 939 940 this._pushDownEvent(); 941 return true; 942 }, 943 944 propagateTouchEvent: function(event, sender, touch){ 945 var widgetParent = this.getWidgetParent(); 946 if (widgetParent){ 947 widgetParent.interceptTouchEvent(event, sender, touch); 948 } 949 }, 950 951 /** 952 * <p> 953 * The callback of touch moved event. <br/> 954 * It sets the highlight state by touch, sends event to parent widget by interceptTouchEvent and calls the callback of touch moved event. 955 * </p> 956 * @param {cc.Touch} touch 957 * @param {cc.Event} event 958 */ 959 onTouchMoved: function (touch, event) { 960 var touchPoint = touch.getLocation(); 961 this._touchMovePosition.x = touchPoint.x; 962 this._touchMovePosition.y = touchPoint.y; 963 this.setHighlighted(this.hitTest(touchPoint)); 964 /* 965 * Propagate touch events to its parents 966 */ 967 if (this._propagateTouchEvents) 968 this.propagateTouchEvent(ccui.Widget.TOUCH_MOVED, this, touch); 969 this._moveEvent(); 970 }, 971 972 /** 973 * <p> 974 * The callback of touch end event 975 * It sends event to parent widget by interceptTouchEvent, 976 * calls the callback of touch end event (highlight= true) or touch canceled event (highlight= false). 977 * sets the highlight state to false , 978 * </p> 979 * @param touch 980 * @param event 981 */ 982 onTouchEnded: function (touch, event) { 983 var touchPoint = touch.getLocation(); 984 this._touchEndPosition.x = touchPoint.x; 985 this._touchEndPosition.y = touchPoint.y; 986 /* 987 * Propagate touch events to its parents 988 */ 989 if (this._propagateTouchEvents) 990 this.propagateTouchEvent(ccui.Widget.TOUCH_ENDED, this, touch); 991 992 var highlight = this._highlight; 993 this.setHighlighted(false); 994 if (highlight) 995 this._releaseUpEvent(); 996 else 997 this._cancelUpEvent(); 998 }, 999 1000 /** 1001 * A call back function called when widget is selected, and on touch canceled. 1002 * @param {cc.Point} touchPoint 1003 */ 1004 onTouchCancelled: function (touchPoint) { 1005 this.setHighlighted(false); 1006 this._cancelUpEvent(); 1007 }, 1008 1009 /** 1010 * A call back function called when widget is selected, and on touch long clicked. 1011 * @param {cc.Point} touchPoint 1012 */ 1013 onTouchLongClicked: function (touchPoint) { 1014 this.longClickEvent(); 1015 }, 1016 1017 //call back function called widget's state changed to dark. 1018 _pushDownEvent: function () { 1019 if (this._touchEventCallback) 1020 this._touchEventCallback(this, ccui.Widget.TOUCH_BEGAN); 1021 if (this._touchEventListener && this._touchEventSelector) 1022 this._touchEventSelector.call(this._touchEventListener, this, ccui.Widget.TOUCH_BEGAN); 1023 }, 1024 1025 _moveEvent: function () { 1026 if (this._touchEventCallback) 1027 this._touchEventCallback(this, ccui.Widget.TOUCH_MOVED); 1028 if (this._touchEventListener && this._touchEventSelector) 1029 this._touchEventSelector.call(this._touchEventListener, this, ccui.Widget.TOUCH_MOVED); 1030 }, 1031 1032 _releaseUpEvent: function () { 1033 if (this._touchEventCallback) 1034 this._touchEventCallback(this, ccui.Widget.TOUCH_ENDED); 1035 if (this._touchEventListener && this._touchEventSelector) 1036 this._touchEventSelector.call(this._touchEventListener, this, ccui.Widget.TOUCH_ENDED); 1037 if (this._clickEventListener) 1038 this._clickEventListener(this); 1039 }, 1040 1041 _cancelUpEvent: function () { 1042 if (this._touchEventCallback) 1043 this._touchEventCallback(this, ccui.Widget.TOUCH_CANCELED); 1044 if (this._touchEventListener && this._touchEventSelector) 1045 this._touchEventSelector.call(this._touchEventListener, this, ccui.Widget.TOUCH_CANCELED); 1046 }, 1047 1048 longClickEvent: function () { 1049 //TODO it will implement in v3.1 1050 }, 1051 1052 /** 1053 * Sets the touch event target/selector of the ccui.Widget 1054 * @param {Function} selector 1055 * @param {Object} target 1056 */ 1057 addTouchEventListener: function (selector, target) { 1058 if(target === undefined) 1059 this._touchEventCallback = selector; 1060 else { 1061 this._touchEventSelector = selector; 1062 this._touchEventListener = target; 1063 } 1064 }, 1065 1066 addClickEventListener: function(callback){ 1067 this._clickEventListener = callback; 1068 }, 1069 1070 /** 1071 * Checks a point if is in widget's space 1072 * @param {cc.Point} pt 1073 * @returns {boolean} true if the point is in widget's space, false otherwise. 1074 */ 1075 hitTest: function (pt) { 1076 var bb = cc.rect(0,0, this._contentSize.width, this._contentSize.height); 1077 return cc.rectContainsPoint(bb, this.convertToNodeSpace(pt)); 1078 }, 1079 1080 /** 1081 * returns whether clipping parent widget contains point. 1082 * @param {cc.Point} pt location point 1083 * @returns {Boolean} 1084 */ 1085 isClippingParentContainsPoint: function(pt){ 1086 this._affectByClipping = false; 1087 var parent = this.getParent(); 1088 var clippingParent = null; 1089 while (parent) { 1090 if (parent instanceof ccui.Layout) { 1091 if (parent.isClippingEnabled()) { 1092 this._affectByClipping = true; 1093 clippingParent = parent; 1094 break; 1095 } 1096 } 1097 parent = parent.getParent(); 1098 } 1099 1100 if (!this._affectByClipping) 1101 return true; 1102 1103 if (clippingParent) { 1104 if (clippingParent.hitTest(pt)) 1105 return clippingParent.isClippingParentContainsPoint(pt); 1106 return false; 1107 } 1108 return true; 1109 }, 1110 1111 /** 1112 * Calls the checkChildInfo of widget's parent, its subclass will override it. 1113 * @param {number} handleState 1114 * @param {ccui.Widget} sender 1115 * @param {cc.Point} touchPoint 1116 */ 1117 checkChildInfo: function (handleState, sender, touchPoint) { 1118 var widgetParent = this.getWidgetParent(); 1119 if (widgetParent) 1120 widgetParent.checkChildInfo(handleState, sender, touchPoint); 1121 }, 1122 1123 /** 1124 * Changes the position (x,y) of the widget . 1125 * The original point (0,0) is at the left-bottom corner of screen. 1126 * @override 1127 * @param {cc.Point|Number} pos 1128 * @param {Number} [posY] 1129 */ 1130 setPosition: function (pos, posY) { 1131 if (!this._usingLayoutComponent && this._running) { 1132 var widgetParent = this.getWidgetParent(); 1133 if (widgetParent) { 1134 var pSize = widgetParent.getContentSize(); 1135 if (pSize.width <= 0 || pSize.height <= 0) { 1136 this._positionPercent.x = 0; 1137 this._positionPercent.y = 0; 1138 } else { 1139 if (posY === undefined) { 1140 this._positionPercent.x = pos.x / pSize.width; 1141 this._positionPercent.y = pos.y / pSize.height; 1142 } else { 1143 this._positionPercent.x = pos / pSize.width; 1144 this._positionPercent.y = posY / pSize.height; 1145 } 1146 } 1147 } 1148 } 1149 1150 cc.Node.prototype.setPosition.call(this, pos, posY); 1151 //this._positionType = ccui.Widget.POSITION_ABSOLUTE; 1152 }, 1153 1154 setPositionX: function (x) { 1155 if (this._running) { 1156 var widgetParent = this.getWidgetParent(); 1157 if (widgetParent) { 1158 var pw = widgetParent.width; 1159 if (pw <= 0) 1160 this._positionPercent.x = 0; 1161 else 1162 this._positionPercent.x = x / pw; 1163 } 1164 } 1165 1166 cc.Node.prototype.setPositionX.call(this, x); 1167 }, 1168 setPositionY: function (y) { 1169 if (this._running) { 1170 var widgetParent = this.getWidgetParent(); 1171 if (widgetParent) { 1172 var ph = widgetParent.height; 1173 if (ph <= 0) 1174 this._positionPercent.y = 0; 1175 else 1176 this._positionPercent.y = y / ph; 1177 } 1178 } 1179 1180 cc.Node.prototype.setPositionY.call(this, y); 1181 }, 1182 1183 /** 1184 * Changes the position (x,y) of the widget 1185 * @param {cc.Point} percent 1186 */ 1187 setPositionPercent: function (percent) { 1188 if (this._usingLayoutComponent){ 1189 var component = this._getOrCreateLayoutComponent(); 1190 component.setPositionPercentX(percent.x); 1191 component.setPositionPercentY(percent.y); 1192 component.refreshLayout(); 1193 return; 1194 }else{ 1195 this._setXPercent(percent.x); 1196 this._setYPercent(percent.y); 1197 } 1198 this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty); 1199 }, 1200 _setXPercent: function (percent) { 1201 if (this._usingLayoutComponent){ 1202 var component = this._getOrCreateLayoutComponent(); 1203 component.setPositionPercentX(percent.x); 1204 component.refreshLayout(); 1205 return; 1206 } 1207 this._positionPercent.x = percent; 1208 }, 1209 _setYPercent: function (percent) { 1210 if (this._usingLayoutComponent){ 1211 var component = this._getOrCreateLayoutComponent(); 1212 component.setPositionPercentY(percent.x); 1213 component.refreshLayout(); 1214 return; 1215 } 1216 this._positionPercent.y = percent; 1217 }, 1218 1219 /** 1220 * Gets the percent (x,y) of the widget 1221 * @returns {cc.Point} The percent (x,y) of the widget in OpenGL coordinates 1222 */ 1223 getPositionPercent: function () { 1224 if (this._usingLayoutComponent) { 1225 var component = this._getOrCreateLayoutComponent(); 1226 this._positionPercent.x = component.getPositionPercentX(); 1227 this._positionPercent.y = component.getPositionPercentY(); 1228 } 1229 return cc.p(this._positionPercent); 1230 }, 1231 1232 _getXPercent: function () { 1233 if (this._usingLayoutComponent) { 1234 var component = this._getOrCreateLayoutComponent(); 1235 this._positionPercent.x = component.getPositionPercentX(); 1236 this._positionPercent.y = component.getPositionPercentY(); 1237 } 1238 return this._positionPercent.x; 1239 }, 1240 _getYPercent: function () { 1241 if (this._usingLayoutComponent) { 1242 var component = this._getOrCreateLayoutComponent(); 1243 this._positionPercent.x = component.getPositionPercentX(); 1244 this._positionPercent.y = component.getPositionPercentY(); 1245 } 1246 return this._positionPercent.y; 1247 }, 1248 1249 /** 1250 * Changes the position type of the widget 1251 * @param {Number} type the position type of widget 1252 */ 1253 setPositionType: function (type) { 1254 this._positionType = type; 1255 if(this._usingLayoutComponent){ 1256 var component = this._getOrCreateLayoutComponent(); 1257 if (type === ccui.POSITION_ABSOLUTE){ 1258 component.setPositionPercentXEnabled(false); 1259 component.setPositionPercentYEnabled(false); 1260 } else { 1261 component.setPositionPercentXEnabled(true); 1262 component.setPositionPercentYEnabled(true); 1263 } 1264 } 1265 this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty); 1266 }, 1267 1268 /** 1269 * Gets the position type of the widget 1270 * @returns {Number} the position type of widget 1271 */ 1272 getPositionType: function () { 1273 return this._positionType; 1274 }, 1275 1276 /** 1277 * Sets whether the widget should be flipped horizontally or not. 1278 * @param {Boolean} flipX true if the widget should be flipped horizontally, false otherwise. 1279 */ 1280 setFlippedX: function (flipX) { 1281 var realScale = this.getScaleX(); 1282 this._flippedX = flipX; 1283 this.setScaleX(realScale); 1284 }, 1285 1286 /** 1287 * <p> 1288 * Returns the flag which indicates whether the widget is flipped horizontally or not. <br/> 1289 * It only flips the texture of the widget, and not the texture of the widget's children. <br/> 1290 * Also, flipping the texture doesn't alter the anchorPoint. <br/> 1291 * If you want to flip the anchorPoint too, and/or to flip the children too use: <br/> 1292 * widget.setScaleX(sprite.getScaleX() * -1); 1293 * </p> 1294 * @returns {Boolean} true if the widget is flipped horizontally, false otherwise. 1295 */ 1296 isFlippedX: function () { 1297 return this._flippedX; 1298 }, 1299 1300 /** 1301 * Sets whether the widget should be flipped vertically or not. 1302 * @param {Boolean} flipY true if the widget should be flipped vertically, false otherwise. 1303 */ 1304 setFlippedY: function (flipY) { 1305 var realScale = this.getScaleY(); 1306 this._flippedY = flipY; 1307 this.setScaleY(realScale); 1308 }, 1309 1310 /** 1311 * <p> 1312 * Return the flag which indicates whether the widget is flipped vertically or not. <br/> 1313 * It only flips the texture of the widget, and not the texture of the widget's children. <br/> 1314 * Also, flipping the texture doesn't alter the anchorPoint. <br/> 1315 * If you want to flip the anchorPoint too, and/or to flip the children too use: <br/> 1316 * widget.setScaleY(widget.getScaleY() * -1); 1317 * </p> 1318 * @returns {Boolean} true if the widget is flipped vertically, false otherwise. 1319 */ 1320 isFlippedY: function () { 1321 return this._flippedY; 1322 }, 1323 1324 _adaptRenderers: function(){}, 1325 1326 /** 1327 * Determines if the widget is bright 1328 * @returns {boolean} true if the widget is bright, false if the widget is dark. 1329 */ 1330 isBright: function () { 1331 return this._bright; 1332 }, 1333 1334 /** 1335 * Determines if the widget is enabled 1336 * @returns {boolean} 1337 */ 1338 isEnabled: function () { 1339 return this._enabled; 1340 }, 1341 1342 /** 1343 * Gets the left boundary position of this widget. 1344 * @returns {number} 1345 */ 1346 getLeftBoundary: function () { 1347 return this.getPositionX() - this._getAnchorX() * this._contentSize.width; 1348 }, 1349 1350 /** 1351 * Gets the bottom boundary position of this widget. 1352 * @returns {number} 1353 */ 1354 getBottomBoundary: function () { 1355 return this.getPositionY() - this._getAnchorY() * this._contentSize.height; 1356 }, 1357 1358 /** 1359 * Gets the right boundary position of this widget. 1360 * @returns {number} 1361 */ 1362 getRightBoundary: function () { 1363 return this.getLeftBoundary() + this._contentSize.width; 1364 }, 1365 1366 /** 1367 * Gets the top boundary position of this widget. 1368 * @returns {number} 1369 */ 1370 getTopBoundary: function () { 1371 return this.getBottomBoundary() + this._contentSize.height; 1372 }, 1373 1374 /** 1375 * Gets the position of touch began event. 1376 * @returns {cc.Point} 1377 */ 1378 getTouchBeganPosition: function(){ 1379 return cc.p(this._touchBeganPosition); 1380 }, 1381 1382 /** 1383 * Gets the position of touch moved event 1384 * @returns {cc.Point} 1385 */ 1386 getTouchMovePosition: function(){ 1387 return cc.p(this._touchMovePosition); 1388 }, 1389 1390 /** 1391 * Gets the position of touch end event 1392 * @returns {cc.Point} 1393 */ 1394 getTouchEndPosition:function(){ 1395 return cc.p(this._touchEndPosition); 1396 }, 1397 1398 /** 1399 * get widget type 1400 * @returns {ccui.Widget.TYPE_WIDGET|ccui.Widget.TYPE_CONTAINER} 1401 */ 1402 getWidgetType: function () { 1403 return this._widgetType; 1404 }, 1405 1406 /** 1407 * Gets LayoutParameter of widget. 1408 * @param {ccui.LayoutParameter} parameter 1409 */ 1410 setLayoutParameter: function (parameter) { 1411 if(!parameter) 1412 return; 1413 this._layoutParameterDictionary[parameter.getLayoutType()] = parameter; 1414 this._layoutParameterType = parameter.getLayoutType(); 1415 }, 1416 1417 /** 1418 * Gets layout parameter 1419 * @param {ccui.LayoutParameter.NONE|ccui.LayoutParameter.LINEAR|ccui.LayoutParameter.RELATIVE} type 1420 * @returns {ccui.LayoutParameter} 1421 */ 1422 getLayoutParameter: function (type) { 1423 type = type || this._layoutParameterType; 1424 return this._layoutParameterDictionary[type]; 1425 }, 1426 1427 /** 1428 * Returns the "class name" of widget. 1429 * @returns {string} 1430 */ 1431 getDescription: function () { 1432 return "Widget"; 1433 }, 1434 1435 /** 1436 * Clones a new widget. 1437 * @returns {ccui.Widget} 1438 */ 1439 clone: function () { 1440 var clonedWidget = this._createCloneInstance(); 1441 clonedWidget._copyProperties(this); 1442 clonedWidget._copyClonedWidgetChildren(this); 1443 return clonedWidget; 1444 }, 1445 1446 _createCloneInstance: function () { 1447 return new ccui.Widget(); 1448 }, 1449 1450 _copyClonedWidgetChildren: function (model) { 1451 var widgetChildren = model.getChildren(); 1452 for (var i = 0; i < widgetChildren.length; i++) { 1453 var locChild = widgetChildren[i]; 1454 if (locChild instanceof ccui.Widget) 1455 this.addChild(locChild.clone()); 1456 } 1457 }, 1458 1459 _copySpecialProperties: function (model) {}, 1460 1461 _copyProperties: function (widget) { 1462 this.setEnabled(widget.isEnabled()); 1463 this.setVisible(widget.isVisible()); 1464 this.setBright(widget.isBright()); 1465 this.setTouchEnabled(widget.isTouchEnabled()); 1466 this.setLocalZOrder(widget.getLocalZOrder()); 1467 this.setTag(widget.getTag()); 1468 this.setName(widget.getName()); 1469 this.setActionTag(widget.getActionTag()); 1470 1471 this._ignoreSize = widget._ignoreSize; 1472 1473 this.setContentSize(widget._contentSize); 1474 this._customSize.width = widget._customSize.width; 1475 this._customSize.height = widget._customSize.height; 1476 1477 this._copySpecialProperties(widget); 1478 this._sizeType = widget.getSizeType(); 1479 this._sizePercent.x = widget._sizePercent.x; 1480 this._sizePercent.y = widget._sizePercent.y; 1481 1482 this._positionType = widget._positionType; 1483 this._positionPercent.x = widget._positionPercent.x; 1484 this._positionPercent.y = widget._positionPercent.y; 1485 1486 this.setPosition(widget.getPosition()); 1487 this.setAnchorPoint(widget.getAnchorPoint()); 1488 this.setScaleX(widget.getScaleX()); 1489 this.setScaleY(widget.getScaleY()); 1490 this.setRotation(widget.getRotation()); 1491 this.setRotationX(widget.getRotationX()); 1492 this.setRotationY(widget.getRotationY()); 1493 this.setFlippedX(widget.isFlippedX()); 1494 this.setFlippedY(widget.isFlippedY()); 1495 this.setColor(widget.getColor()); 1496 this.setOpacity(widget.getOpacity()); 1497 1498 this._touchEventCallback = widget._touchEventCallback; 1499 this._touchEventListener = widget._touchEventListener; 1500 this._touchEventSelector = widget._touchEventSelector; 1501 this._clickEventListener = widget._clickEventListener; 1502 this._focused = widget._focused; 1503 this._focusEnabled = widget._focusEnabled; 1504 this._propagateTouchEvents = widget._propagateTouchEvents; 1505 1506 for (var key in widget._layoutParameterDictionary) { 1507 var parameter = widget._layoutParameterDictionary[key]; 1508 if (parameter) 1509 this.setLayoutParameter(parameter.clone()); 1510 } 1511 this._onSizeChanged(); 1512 }, 1513 1514 /*temp action*/ 1515 setActionTag: function (tag) { 1516 this._actionTag = tag; 1517 }, 1518 1519 getActionTag: function () { 1520 return this._actionTag; 1521 }, 1522 1523 /** 1524 * Gets the left boundary position of this widget. 1525 * @deprecated since v3.0, please use getLeftBoundary instead. 1526 * @returns {number} 1527 */ 1528 getLeftInParent: function(){ 1529 cc.log("getLeftInParent is deprecated. Please use getLeftBoundary instead."); 1530 return this.getLeftBoundary(); 1531 }, 1532 1533 /** 1534 * Gets the bottom boundary position of this widget. 1535 * @deprecated since v3.0, please use getBottomBoundary instead. 1536 * @returns {number} 1537 */ 1538 getBottomInParent: function(){ 1539 cc.log("getBottomInParent is deprecated. Please use getBottomBoundary instead."); 1540 return this.getBottomBoundary(); 1541 }, 1542 1543 /** 1544 * Gets the right boundary position of this widget. 1545 * @deprecated since v3.0, please use getRightBoundary instead. 1546 * @returns {number} 1547 */ 1548 getRightInParent: function(){ 1549 cc.log("getRightInParent is deprecated. Please use getRightBoundary instead."); 1550 return this.getRightBoundary(); 1551 }, 1552 1553 /** 1554 * Gets the top boundary position of this widget. 1555 * @deprecated since v3.0, please use getTopBoundary instead. 1556 * @returns {number} 1557 */ 1558 getTopInParent: function(){ 1559 cc.log("getTopInParent is deprecated. Please use getTopBoundary instead."); 1560 return this.getTopBoundary(); 1561 }, 1562 1563 /** 1564 * Gets the touch end point of widget when widget is selected. 1565 * @deprecated since v3.0, please use getTouchEndPosition instead. 1566 * @returns {cc.Point} the touch end point. 1567 */ 1568 getTouchEndPos: function () { 1569 cc.log("getTouchEndPos is deprecated. Please use getTouchEndPosition instead."); 1570 return this.getTouchEndPosition(); 1571 }, 1572 1573 /** 1574 *Gets the touch move point of widget when widget is selected. 1575 * @deprecated since v3.0, please use getTouchMovePosition instead. 1576 * @returns {cc.Point} the touch move point. 1577 */ 1578 getTouchMovePos: function () { 1579 cc.log("getTouchMovePos is deprecated. Please use getTouchMovePosition instead."); 1580 return this.getTouchMovePosition(); 1581 }, 1582 1583 /** 1584 * Checks a point if in parent's area. 1585 * @deprecated since v3.0, please use isClippingParentContainsPoint instead. 1586 * @param {cc.Point} pt 1587 * @returns {Boolean} 1588 */ 1589 clippingParentAreaContainPoint: function (pt) { 1590 cc.log("clippingParentAreaContainPoint is deprecated. Please use isClippingParentContainsPoint instead."); 1591 this.isClippingParentContainsPoint(pt); 1592 }, 1593 1594 /** 1595 * Gets the touch began point of widget when widget is selected. 1596 * @deprecated since v3.0, please use getTouchBeganPosition instead. 1597 * @returns {cc.Point} the touch began point. 1598 */ 1599 getTouchStartPos: function () { 1600 cc.log("getTouchStartPos is deprecated. Please use getTouchBeganPosition instead."); 1601 return this.getTouchBeganPosition(); 1602 }, 1603 1604 /** 1605 * Changes the size that is widget's size 1606 * @deprecated since v3.0, please use setContentSize instead. 1607 * @param {cc.Size} size that is widget's size 1608 */ 1609 setSize: function (size) { 1610 this.setContentSize(size); 1611 }, 1612 1613 /** 1614 * Returns size of widget 1615 * @deprecated since v3.0, please use getContentSize instead. 1616 * @returns {cc.Size} 1617 */ 1618 getSize: function () { 1619 return this.getContentSize(); 1620 }, 1621 1622 /** 1623 * Adds a node for widget (this function is deleted in -x) 1624 * @param {cc.Node} node 1625 * @param {Number} zOrder 1626 * @param {Number} tag 1627 * @deprecated since v3.0, please use addChild instead. 1628 */ 1629 addNode: function (node, zOrder, tag) { 1630 if (node instanceof ccui.Widget) { 1631 cc.log("Please use addChild to add a Widget."); 1632 return; 1633 } 1634 cc.Node.prototype.addChild.call(this, node, zOrder, tag); 1635 this._nodes.push(node); 1636 }, 1637 1638 /** 1639 * Gets node by tag 1640 * @deprecated since v3.0, please use getChildByTag instead. 1641 * @param {Number} tag 1642 * @returns {cc.Node} 1643 */ 1644 getNodeByTag: function (tag) { 1645 var _nodes = this._nodes; 1646 for (var i = 0; i < _nodes.length; i++) { 1647 var node = _nodes[i]; 1648 if (node && node.getTag() === tag) { 1649 return node; 1650 } 1651 } 1652 return null; 1653 }, 1654 1655 /** 1656 * Returns all children. 1657 * @deprecated since v3.0, please use getChildren instead. 1658 * @returns {Array} 1659 */ 1660 getNodes: function () { 1661 return this._nodes; 1662 }, 1663 1664 /** 1665 * Removes a node from ccui.Widget 1666 * @deprecated since v3.0, please use removeChild instead. 1667 * @param {cc.Node} node 1668 * @param {Boolean} cleanup 1669 */ 1670 removeNode: function (node, cleanup) { 1671 cc.Node.prototype.removeChild.call(this, node, cleanup); 1672 cc.arrayRemoveObject(this._nodes, node); 1673 }, 1674 1675 /** 1676 * Removes node by tag 1677 * @deprecated since v3.0, please use removeChildByTag instead. 1678 * @param {Number} tag 1679 * @param {Boolean} [cleanup] 1680 */ 1681 removeNodeByTag: function (tag, cleanup) { 1682 var node = this.getChildByTag(tag); 1683 if (!node) 1684 cc.log("cocos2d: removeNodeByTag(tag = %d): child not found!", tag); 1685 else 1686 this.removeChild(node, cleanup); 1687 }, 1688 1689 /** 1690 * Removes all node 1691 * @deprecated since v3.0, please use removeAllChildren instead. 1692 */ 1693 removeAllNodes: function () { 1694 for (var i = 0; i < this._nodes.length; i++) { 1695 var node = this._nodes[i]; 1696 cc.Node.prototype.removeChild.call(this, node); 1697 } 1698 this._nodes.length = 0; 1699 }, 1700 1701 _findLayout: function(){ 1702 cc.renderer.childrenOrderDirty = true; 1703 var layout = this._parent; 1704 while(layout){ 1705 if(layout._doLayout){ 1706 layout._doLayoutDirty = true; 1707 break; 1708 }else 1709 layout = layout._parent; 1710 } 1711 }, 1712 1713 /** 1714 * @since v3.2 1715 * @returns {boolean} true represent the widget use Unify Size, false represent the widget couldn't use Unify Size 1716 */ 1717 isUnifySizeEnabled: function(){ 1718 return this._unifySize; 1719 }, 1720 1721 /** 1722 * @since v3.2 1723 * @param {Boolean} enable enable Unify Size of a widget 1724 */ 1725 setUnifySizeEnabled: function(enable){ 1726 this._unifySize = enable; 1727 }, 1728 1729 //v3.3 1730 _ccEventCallback: null, 1731 /** 1732 * Set a event handler to the widget in order to use cocostudio editor and framework 1733 * @since v3.3 1734 * @param {function} callback 1735 */ 1736 addCCSEventListener: function(callback){ 1737 this._ccEventCallback = callback; 1738 }, 1739 1740 //override the scale functions. 1741 setScaleX: function(scaleX){ 1742 if (this._flippedX) 1743 scaleX = scaleX * -1; 1744 cc.Node.prototype.setScaleX.call(this, scaleX); 1745 }, 1746 setScaleY: function(scaleY){ 1747 if (this._flippedY) 1748 scaleY = scaleY * -1; 1749 cc.Node.prototype.setScaleY.call(this, scaleY); 1750 }, 1751 setScale: function(scaleX, scaleY){ 1752 if(scaleY === undefined) 1753 scaleY = scaleX; 1754 this.setScaleX(scaleX); 1755 this.setScaleY(scaleY); 1756 }, 1757 1758 getScaleX: function(){ 1759 var originalScale = cc.Node.prototype.getScaleX.call(this); 1760 if (this._flippedX) 1761 originalScale = originalScale * -1.0; 1762 return originalScale; 1763 }, 1764 getScaleY: function(){ 1765 var originalScale = cc.Node.prototype.getScaleY.call(this); 1766 if (this._flippedY) 1767 originalScale = originalScale * -1.0; 1768 return originalScale; 1769 }, 1770 getScale: function(){ 1771 if(this.getScaleX() !== this.getScaleY()) 1772 cc.log("Widget#scale. ScaleX != ScaleY. Don't know which one to return"); 1773 return this.getScaleX(); 1774 }, 1775 1776 /** 1777 * Sets callback name to widget. 1778 * @since v3.3 1779 * @param {String} callbackName 1780 */ 1781 setCallbackName: function(callbackName){ 1782 this._callbackName = callbackName; 1783 }, 1784 1785 /** 1786 * Gets callback name of widget 1787 * @since v3.3 1788 * @returns {String|Null} 1789 */ 1790 getCallbackName: function(){ 1791 return this._callbackName; 1792 }, 1793 1794 /** 1795 * Sets callback type to widget 1796 * @since v3.3 1797 * @param {String} callbackType 1798 */ 1799 setCallbackType: function(callbackType){ 1800 this._callbackType = callbackType; 1801 }, 1802 1803 /** 1804 * Gets callback type of widget 1805 * @since v3.3 1806 * @returns {String|null} 1807 */ 1808 getCallbackType: function(){ 1809 return this._callbackType; 1810 }, 1811 1812 /** 1813 * Whether enable layout component of a widget 1814 * @since v3.3 1815 * @param {Boolean} enable enable layout Component of a widget 1816 */ 1817 setLayoutComponentEnabled: function(enable){ 1818 this._usingLayoutComponent = enable; 1819 }, 1820 1821 /** 1822 * Returns whether enable layout component of a widget 1823 * @return {Boolean} true represent the widget use Layout Component, false represent the widget couldn't use Layout Component. 1824 */ 1825 isLayoutComponentEnabled: function(){ 1826 return this._usingLayoutComponent; 1827 }, 1828 1829 1830 _createRenderCmd: function(){ 1831 if(cc._renderType === cc._RENDER_TYPE_WEBGL) 1832 return new ccui.Widget.WebGLRenderCmd(this); 1833 else 1834 return new ccui.Widget.CanvasRenderCmd(this); 1835 } 1836 }); 1837 1838 var _p = ccui.Widget.prototype; 1839 1840 // Extended properties 1841 /** @expose */ 1842 _p.xPercent; 1843 cc.defineGetterSetter(_p, "xPercent", _p._getXPercent, _p._setXPercent); 1844 /** @expose */ 1845 _p.yPercent; 1846 cc.defineGetterSetter(_p, "yPercent", _p._getYPercent, _p._setYPercent); 1847 /** @expose */ 1848 _p.widthPercent; 1849 cc.defineGetterSetter(_p, "widthPercent", _p._getWidthPercent, _p._setWidthPercent); 1850 /** @expose */ 1851 _p.heightPercent; 1852 cc.defineGetterSetter(_p, "heightPercent", _p._getHeightPercent, _p._setHeightPercent); 1853 /** @expose */ 1854 _p.widgetParent; 1855 cc.defineGetterSetter(_p, "widgetParent", _p.getWidgetParent); 1856 /** @expose */ 1857 _p.enabled; 1858 cc.defineGetterSetter(_p, "enabled", _p.isEnabled, _p.setEnabled); 1859 /** @expose */ 1860 _p.focused; 1861 cc.defineGetterSetter(_p, "focused", _p.isFocused, _p.setFocused); 1862 /** @expose */ 1863 _p.sizeType; 1864 cc.defineGetterSetter(_p, "sizeType", _p.getSizeType, _p.setSizeType); 1865 /** @expose */ 1866 _p.widgetType; 1867 cc.defineGetterSetter(_p, "widgetType", _p.getWidgetType); 1868 /** @expose */ 1869 _p.touchEnabled; 1870 cc.defineGetterSetter(_p, "touchEnabled", _p.isTouchEnabled, _p.setTouchEnabled); 1871 /** @expose */ 1872 _p.updateEnabled; 1873 cc.defineGetterSetter(_p, "updateEnabled", _p.isUpdateEnabled, _p.setUpdateEnabled); 1874 /** @expose */ 1875 _p.bright; 1876 cc.defineGetterSetter(_p, "bright", _p.isBright, _p.setBright); 1877 /** @expose */ 1878 _p.name; 1879 cc.defineGetterSetter(_p, "name", _p.getName, _p.setName); 1880 /** @expose */ 1881 _p.actionTag; 1882 cc.defineGetterSetter(_p, "actionTag", _p.getActionTag, _p.setActionTag); 1883 /** @expose */ 1884 _p.opacity; 1885 cc.defineGetterSetter(_p, "opacity", _p.getOpacity, _p.setOpacity); 1886 1887 _p = null; 1888 1889 /** 1890 * allocates and initializes a UIWidget. 1891 * @deprecated 1892 * @return {ccui.Widget} 1893 */ 1894 ccui.Widget.create = function () { 1895 return new ccui.Widget(); 1896 }; 1897 1898 ccui.Widget._focusedWidget = null; //both layout & widget will be stored in this variable 1899 ccui.Widget._focusNavigationController = null; 1900 1901 /** 1902 * call this method with parameter true to enable the Android Dpad focus navigation feature 1903 * @note it doesn't implemented on Web 1904 * @param {Boolean} enable set true to enable dpad focus navigation, otherwise disable dpad focus navigation 1905 */ 1906 ccui.Widget.enableDpadNavigation = function(enable){ 1907 if (enable){ 1908 if (null == ccui.Widget._focusNavigationController) { 1909 ccui.Widget._focusNavigationController = new ccui._FocusNavigationController(); 1910 if (ccui.Widget._focusedWidget) { 1911 ccui.Widget._focusNavigationController._setFirstFocsuedWidget(ccui.Widget._focusedWidget); 1912 } 1913 } 1914 ccui.Widget._focusNavigationController.enableFocusNavigation(true); 1915 } else { 1916 if(ccui.Widget._focusNavigationController){ 1917 ccui.Widget._focusNavigationController.enableFocusNavigation(false); 1918 ccui.Widget._focusNavigationController = null; 1919 } 1920 } 1921 }; 1922 1923 /** 1924 * Gets the focused widget of current stage. 1925 * @function 1926 * @returns {null|ccui.Widget} 1927 */ 1928 ccui.Widget.getCurrentFocusedWidget = function(){ 1929 return ccui.Widget._focusedWidget; 1930 }; 1931 1932 // Constants 1933 //bright style 1934 /** 1935 * None bright style of ccui.Widget. 1936 * @constant 1937 * @type {number} 1938 */ 1939 ccui.Widget.BRIGHT_STYLE_NONE = -1; 1940 /** 1941 * Normal bright style of ccui.Widget. 1942 * @constant 1943 * @type {number} 1944 */ 1945 ccui.Widget.BRIGHT_STYLE_NORMAL = 0; 1946 /** 1947 * Light bright style of ccui.Widget. 1948 * @constant 1949 * @type {number} 1950 */ 1951 ccui.Widget.BRIGHT_STYLE_HIGH_LIGHT = 1; 1952 1953 //widget type 1954 /** 1955 * The type code of Widget for ccui controls. 1956 * @constant 1957 * @type {number} 1958 */ 1959 ccui.Widget.TYPE_WIDGET = 0; 1960 /** 1961 * The type code of Container for ccui controls. 1962 * @constant 1963 * @type {number} 1964 */ 1965 ccui.Widget.TYPE_CONTAINER = 1; 1966 1967 //Focus Direction 1968 /** 1969 * The left of Focus direction for ccui.Widget 1970 * @constant 1971 * @type {number} 1972 */ 1973 ccui.Widget.LEFT = 0; 1974 /** 1975 * The right of Focus direction for ccui.Widget 1976 * @constant 1977 * @type {number} 1978 */ 1979 ccui.Widget.RIGHT = 1; 1980 /** 1981 * The up of Focus direction for ccui.Widget 1982 * @constant 1983 * @type {number} 1984 */ 1985 ccui.Widget.UP = 2; 1986 /** 1987 * The down of Focus direction for ccui.Widget 1988 * @constant 1989 * @type {number} 1990 */ 1991 ccui.Widget.DOWN = 3; 1992 1993 //texture resource type 1994 /** 1995 * The image file texture type of ccui.Widget loads. 1996 * @constant 1997 * @type {number} 1998 */ 1999 ccui.Widget.LOCAL_TEXTURE = 0; 2000 /** 2001 * The sprite frame texture type of ccui.Widget loads. 2002 * @constant 2003 * @type {number} 2004 */ 2005 ccui.Widget.PLIST_TEXTURE = 1; 2006 2007 //touch event type 2008 /** 2009 * The touch began type of ccui.Widget's touch event 2010 * @constant 2011 * @type {number} 2012 */ 2013 ccui.Widget.TOUCH_BEGAN = 0; 2014 /** 2015 * The touch moved type of ccui.Widget's touch event 2016 * @constant 2017 * @type {number} 2018 */ 2019 ccui.Widget.TOUCH_MOVED = 1; 2020 /** 2021 * The touch end type of ccui.Widget's touch event 2022 * @constant 2023 * @type {number} 2024 */ 2025 ccui.Widget.TOUCH_ENDED = 2; 2026 /** 2027 * The touch canceled type of ccui.Widget's touch event 2028 * @constant 2029 * @type {number} 2030 */ 2031 ccui.Widget.TOUCH_CANCELED = 3; 2032 2033 //size type 2034 /** 2035 * The absolute of ccui.Widget's size type. 2036 * @constant 2037 * @type {number} 2038 */ 2039 ccui.Widget.SIZE_ABSOLUTE = 0; 2040 /** 2041 * The percent of ccui.Widget's size type. 2042 * @constant 2043 * @type {number} 2044 */ 2045 ccui.Widget.SIZE_PERCENT = 1; 2046 2047 //position type 2048 /** 2049 * The absolute of ccui.Widget's position type. 2050 * @constant 2051 * @type {number} 2052 */ 2053 ccui.Widget.POSITION_ABSOLUTE = 0; 2054 /** 2055 * The percent of ccui.Widget's position type. 2056 * @constant 2057 * @type {number} 2058 */ 2059 ccui.Widget.POSITION_PERCENT = 1; 2060