/ext-4.0.7/src/layout/component/Component.js

https://bitbucket.org/srogerf/javascript · JavaScript · 289 lines · 184 code · 39 blank · 66 comment · 60 complexity · 471fd859f781d4459c81a5eed6097a86 MD5 · raw file

  1. /*
  2. This file is part of Ext JS 4
  3. Copyright (c) 2011 Sencha Inc
  4. Contact: http://www.sencha.com/contact
  5. GNU General Public License Usage
  6. This file may be used under the terms of the GNU General Public License version 3.0 as published by the Free Software Foundation and appearing in the file LICENSE included in the packaging of this file. Please review the following information to ensure the GNU General Public License version 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
  7. If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.
  8. */
  9. /**
  10. * @class Ext.layout.component.Component
  11. * @extends Ext.layout.Layout
  12. *
  13. * This class is intended to be extended or created via the {@link Ext.Component#componentLayout layout}
  14. * configuration property. See {@link Ext.Component#componentLayout} for additional details.
  15. *
  16. * @private
  17. */
  18. Ext.define('Ext.layout.component.Component', {
  19. /* Begin Definitions */
  20. extend: 'Ext.layout.Layout',
  21. /* End Definitions */
  22. type: 'component',
  23. monitorChildren: true,
  24. initLayout : function() {
  25. var me = this,
  26. owner = me.owner,
  27. ownerEl = owner.el;
  28. if (!me.initialized) {
  29. if (owner.frameSize) {
  30. me.frameSize = owner.frameSize;
  31. }
  32. else {
  33. owner.frameSize = me.frameSize = {
  34. top: 0,
  35. left: 0,
  36. bottom: 0,
  37. right: 0
  38. };
  39. }
  40. }
  41. me.callParent(arguments);
  42. },
  43. beforeLayout : function(width, height, isSetSize, callingContainer) {
  44. this.callParent(arguments);
  45. var me = this,
  46. owner = me.owner,
  47. ownerCt = owner.ownerCt,
  48. layout = owner.layout,
  49. isVisible = owner.isVisible(true),
  50. ownerElChild = owner.el.child,
  51. layoutCollection;
  52. // Cache the size we began with so we can see if there has been any effect.
  53. me.previousComponentSize = me.lastComponentSize;
  54. // Do not allow autoing of any dimensions which are fixed
  55. if (!isSetSize
  56. && ((!Ext.isNumber(width) && owner.isFixedWidth()) ||
  57. (!Ext.isNumber(height) && owner.isFixedHeight()))
  58. // unless we are being told to do so by the ownerCt's layout
  59. && callingContainer && callingContainer !== ownerCt) {
  60. me.doContainerLayout();
  61. return false;
  62. }
  63. // If an ownerCt is hidden, add my reference onto the layoutOnShow stack. Set the needsLayout flag.
  64. // If the owner itself is a directly hidden floater, set the needsLayout object on that for when it is shown.
  65. if (!isVisible && (owner.hiddenAncestor || owner.floating)) {
  66. if (owner.hiddenAncestor) {
  67. layoutCollection = owner.hiddenAncestor.layoutOnShow;
  68. layoutCollection.remove(owner);
  69. layoutCollection.add(owner);
  70. }
  71. owner.needsLayout = {
  72. width: width,
  73. height: height,
  74. isSetSize: false
  75. };
  76. }
  77. if (isVisible && this.needsLayout(width, height)) {
  78. return owner.beforeComponentLayout(width, height, isSetSize, callingContainer);
  79. }
  80. else {
  81. return false;
  82. }
  83. },
  84. /**
  85. * Check if the new size is different from the current size and only
  86. * trigger a layout if it is necessary.
  87. * @param {Number} width The new width to set.
  88. * @param {Number} height The new height to set.
  89. */
  90. needsLayout : function(width, height) {
  91. var me = this,
  92. widthBeingChanged,
  93. heightBeingChanged;
  94. me.lastComponentSize = me.lastComponentSize || {
  95. width: -Infinity,
  96. height: -Infinity
  97. };
  98. // If autoWidthing, or an explicitly different width is passed, then the width is being changed.
  99. widthBeingChanged = !Ext.isDefined(width) || me.lastComponentSize.width !== width;
  100. // If autoHeighting, or an explicitly different height is passed, then the height is being changed.
  101. heightBeingChanged = !Ext.isDefined(height) || me.lastComponentSize.height !== height;
  102. // isSizing flag added to prevent redundant layouts when going up the layout chain
  103. return !me.isSizing && (me.childrenChanged || widthBeingChanged || heightBeingChanged);
  104. },
  105. /**
  106. * Set the size of any element supporting undefined, null, and values.
  107. * @param {Number} width The new width to set.
  108. * @param {Number} height The new height to set.
  109. */
  110. setElementSize: function(el, width, height) {
  111. if (width !== undefined && height !== undefined) {
  112. el.setSize(width, height);
  113. }
  114. else if (height !== undefined) {
  115. el.setHeight(height);
  116. }
  117. else if (width !== undefined) {
  118. el.setWidth(width);
  119. }
  120. },
  121. /**
  122. * Returns the owner component's resize element.
  123. * @return {Ext.Element}
  124. */
  125. getTarget : function() {
  126. return this.owner.el;
  127. },
  128. /**
  129. * <p>Returns the element into which rendering must take place. Defaults to the owner Component's encapsulating element.</p>
  130. * May be overridden in Component layout managers which implement an inner element.
  131. * @return {Ext.Element}
  132. */
  133. getRenderTarget : function() {
  134. return this.owner.el;
  135. },
  136. /**
  137. * Set the size of the target element.
  138. * @param {Number} width The new width to set.
  139. * @param {Number} height The new height to set.
  140. */
  141. setTargetSize : function(width, height) {
  142. var me = this;
  143. me.setElementSize(me.owner.el, width, height);
  144. if (me.owner.frameBody) {
  145. var targetInfo = me.getTargetInfo(),
  146. padding = targetInfo.padding,
  147. border = targetInfo.border,
  148. frameSize = me.frameSize;
  149. me.setElementSize(me.owner.frameBody,
  150. Ext.isNumber(width) ? (width - frameSize.left - frameSize.right - padding.left - padding.right - border.left - border.right) : width,
  151. Ext.isNumber(height) ? (height - frameSize.top - frameSize.bottom - padding.top - padding.bottom - border.top - border.bottom) : height
  152. );
  153. }
  154. me.autoSized = {
  155. width: !Ext.isNumber(width),
  156. height: !Ext.isNumber(height)
  157. };
  158. me.lastComponentSize = {
  159. width: width,
  160. height: height
  161. };
  162. },
  163. getTargetInfo : function() {
  164. if (!this.targetInfo) {
  165. var target = this.getTarget(),
  166. body = this.owner.getTargetEl();
  167. this.targetInfo = {
  168. padding: {
  169. top: target.getPadding('t'),
  170. right: target.getPadding('r'),
  171. bottom: target.getPadding('b'),
  172. left: target.getPadding('l')
  173. },
  174. border: {
  175. top: target.getBorderWidth('t'),
  176. right: target.getBorderWidth('r'),
  177. bottom: target.getBorderWidth('b'),
  178. left: target.getBorderWidth('l')
  179. },
  180. bodyMargin: {
  181. top: body.getMargin('t'),
  182. right: body.getMargin('r'),
  183. bottom: body.getMargin('b'),
  184. left: body.getMargin('l')
  185. }
  186. };
  187. }
  188. return this.targetInfo;
  189. },
  190. // Start laying out UP the ownerCt's layout when flagged to do so.
  191. doOwnerCtLayouts: function() {
  192. var owner = this.owner,
  193. ownerCt = owner.ownerCt,
  194. ownerCtComponentLayout, ownerCtContainerLayout,
  195. curSize = this.lastComponentSize,
  196. prevSize = this.previousComponentSize,
  197. widthChange = (prevSize && curSize && Ext.isNumber(curSize.width )) ? curSize.width !== prevSize.width : true,
  198. heightChange = (prevSize && curSize && Ext.isNumber(curSize.height)) ? curSize.height !== prevSize.height : true;
  199. // If size has not changed, do not inform upstream layouts
  200. if (!ownerCt || (!widthChange && !heightChange)) {
  201. return;
  202. }
  203. ownerCtComponentLayout = ownerCt.componentLayout;
  204. ownerCtContainerLayout = ownerCt.layout;
  205. if (!owner.floating && ownerCtComponentLayout && ownerCtComponentLayout.monitorChildren && !ownerCtComponentLayout.layoutBusy) {
  206. if (!ownerCt.suspendLayout && ownerCtContainerLayout && !ownerCtContainerLayout.layoutBusy) {
  207. // If the owning Container may be adjusted in any of the the dimension which have changed, perform its Component layout
  208. if (((widthChange && !ownerCt.isFixedWidth()) || (heightChange && !ownerCt.isFixedHeight()))) {
  209. // Set the isSizing flag so that the upstream Container layout (called after a Component layout) can omit this component from sizing operations
  210. this.isSizing = true;
  211. ownerCt.doComponentLayout();
  212. this.isSizing = false;
  213. }
  214. // Execute upstream Container layout
  215. else if (ownerCtContainerLayout.bindToOwnerCtContainer === true) {
  216. ownerCtContainerLayout.layout();
  217. }
  218. }
  219. }
  220. },
  221. doContainerLayout: function() {
  222. var me = this,
  223. owner = me.owner,
  224. ownerCt = owner.ownerCt,
  225. layout = owner.layout,
  226. ownerCtComponentLayout;
  227. // Run the container layout if it exists (layout for child items)
  228. // **Unless automatic laying out is suspended, or the layout is currently running**
  229. if (!owner.suspendLayout && layout && layout.isLayout && !layout.layoutBusy && !layout.isAutoDock) {
  230. layout.layout();
  231. }
  232. // Tell the ownerCt that it's child has changed and can be re-layed by ignoring the lastComponentSize cache.
  233. if (ownerCt && ownerCt.componentLayout) {
  234. ownerCtComponentLayout = ownerCt.componentLayout;
  235. if (!owner.floating && ownerCtComponentLayout.monitorChildren && !ownerCtComponentLayout.layoutBusy) {
  236. ownerCtComponentLayout.childrenChanged = true;
  237. }
  238. }
  239. },
  240. afterLayout : function(width, height, isSetSize, layoutOwner) {
  241. this.doContainerLayout();
  242. this.owner.afterComponentLayout(width, height, isSetSize, layoutOwner);
  243. }
  244. });