Fit.html 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  5. <title>The source code</title>
  6. <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
  7. <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
  8. <style type="text/css">
  9. .highlight { display: block; background-color: #ddd; }
  10. </style>
  11. <script type="text/javascript">
  12. function highlight() {
  13. document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
  14. }
  15. </script>
  16. </head>
  17. <body onload="prettyPrint(); highlight();">
  18. <pre class="prettyprint lang-js"><span id='Ext-layout-container-Fit'>/**
  19. </span> * This is a base class for layouts that contain a single item that automatically expands to fill the layout's
  20. * container. This class is intended to be extended or created via the layout:'fit'
  21. * {@link Ext.container.Container#layout} config, and should generally not need to be created directly via the new keyword.
  22. *
  23. * Fit layout does not have any direct config options (other than inherited ones). To fit a panel to a container using
  24. * Fit layout, simply set `layout: 'fit'` on the container and add a single panel to it.
  25. *
  26. * @example
  27. * Ext.create('Ext.panel.Panel', {
  28. * title: 'Fit Layout',
  29. * width: 300,
  30. * height: 150,
  31. * layout:'fit',
  32. * items: {
  33. * title: 'Inner Panel',
  34. * html: 'This is the inner panel content',
  35. * bodyPadding: 20,
  36. * border: false
  37. * },
  38. * renderTo: Ext.getBody()
  39. * });
  40. *
  41. * If the container has multiple items, all of the items will all be equally sized. This is usually not
  42. * desired, so to avoid this, place only a **single** item in the container. This sizing of all items
  43. * can be used to provide a background {@link Ext.Img image} that is &quot;behind&quot; another item
  44. * such as a {@link Ext.view.View dataview} if you also absolutely position the items.
  45. */
  46. Ext.define('Ext.layout.container.Fit', {
  47. /* Begin Definitions */
  48. extend: 'Ext.layout.container.Container',
  49. alternateClassName: 'Ext.layout.FitLayout',
  50. alias: 'layout.fit',
  51. /* End Definitions */
  52. itemCls: Ext.baseCSSPrefix + 'fit-item',
  53. targetCls: Ext.baseCSSPrefix + 'layout-fit',
  54. type: 'fit',
  55. <span id='Ext-layout-container-Fit-cfg-defaultMargins'> /**
  56. </span> * @cfg {Object} defaultMargins
  57. * If the individual contained items do not have a margins property specified or margin specified via CSS, the
  58. * default margins from this property will be applied to each item.
  59. *
  60. * This property may be specified as an object containing margins to apply in the format:
  61. *
  62. * {
  63. * top: (top margin),
  64. * right: (right margin),
  65. * bottom: (bottom margin),
  66. * left: (left margin)
  67. * }
  68. *
  69. * This property may also be specified as a string containing space-separated, numeric margin values. The order of
  70. * the sides associated with each value matches the way CSS processes margin values:
  71. *
  72. * - If there is only one value, it applies to all sides.
  73. * - If there are two values, the top and bottom borders are set to the first value and the right and left are
  74. * set to the second.
  75. * - If there are three values, the top is set to the first value, the left and right are set to the second,
  76. * and the bottom is set to the third.
  77. * - If there are four values, they apply to the top, right, bottom, and left, respectively.
  78. *
  79. */
  80. defaultMargins: {
  81. top: 0,
  82. right: 0,
  83. bottom: 0,
  84. left: 0
  85. },
  86. manageMargins: true,
  87. sizePolicies: {
  88. 0: { setsWidth: 0, setsHeight: 0 },
  89. 1: { setsWidth: 1, setsHeight: 0 },
  90. 2: { setsWidth: 0, setsHeight: 1 },
  91. 3: { setsWidth: 1, setsHeight: 1 }
  92. },
  93. getItemSizePolicy: function (item, ownerSizeModel) {
  94. // this layout's sizePolicy is derived from its owner's sizeModel:
  95. var sizeModel = ownerSizeModel || this.owner.getSizeModel(),
  96. mode = (sizeModel.width.shrinkWrap ? 0 : 1) |
  97. (sizeModel.height.shrinkWrap ? 0 : 2);
  98. return this.sizePolicies[mode];
  99. },
  100. beginLayoutCycle: function (ownerContext, firstCycle) {
  101. var me = this,
  102. // determine these before the lastSizeModels get updated:
  103. resetHeight = me.lastHeightModel &amp;&amp; me.lastHeightModel.calculated,
  104. resetWidth = me.lastWidthModel &amp;&amp; me.lastWidthModel.calculated,
  105. resetSizes = resetWidth || resetHeight,
  106. maxChildMinHeight = 0, maxChildMinWidth = 0,
  107. c, childItems, i, item, length, margins, minHeight, minWidth, style, undef;
  108. me.callParent(arguments);
  109. // Clear any dimensions which we set before calculation, in case the current
  110. // settings affect the available size. This particularly effects self-sizing
  111. // containers such as fields, in which the target element is naturally sized,
  112. // and should not be stretched by a sized child item.
  113. if (resetSizes &amp;&amp; ownerContext.targetContext.el.dom.tagName.toUpperCase() != 'TD') {
  114. resetSizes = resetWidth = resetHeight = false;
  115. }
  116. childItems = ownerContext.childItems;
  117. length = childItems.length;
  118. for (i = 0; i &lt; length; ++i) {
  119. item = childItems[i];
  120. // On the firstCycle, we determine the max of the minWidth/Height of the items
  121. // since these can cause the container to grow scrollbars despite our attempts
  122. // to fit the child to the container.
  123. if (firstCycle) {
  124. c = item.target;
  125. minHeight = c.minHeight;
  126. minWidth = c.minWidth;
  127. if (minWidth || minHeight) {
  128. margins = item.marginInfo || item.getMarginInfo();
  129. // if the child item has undefined minWidth/Height, these will become
  130. // NaN by adding the margins...
  131. minHeight += margins.height;
  132. minWidth += margins.height;
  133. // if the child item has undefined minWidth/Height, these comparisons
  134. // will evaluate to false... that is, &quot;0 &lt; NaN&quot; == false...
  135. if (maxChildMinHeight &lt; minHeight) {
  136. maxChildMinHeight = minHeight;
  137. }
  138. if (maxChildMinWidth &lt; minWidth) {
  139. maxChildMinWidth = minWidth;
  140. }
  141. }
  142. }
  143. if (resetSizes) {
  144. style = item.el.dom.style;
  145. if (resetHeight) {
  146. style.height = '';
  147. }
  148. if (resetWidth) {
  149. style.width = '';
  150. }
  151. }
  152. }
  153. if (firstCycle) {
  154. ownerContext.maxChildMinHeight = maxChildMinHeight;
  155. ownerContext.maxChildMinWidth = maxChildMinWidth;
  156. }
  157. // Cache the overflowX/Y flags, but make them false in shrinkWrap mode (since we
  158. // won't be triggering overflow in that case) and false if we have no minSize (so
  159. // no child to trigger an overflow).
  160. c = ownerContext.target;
  161. ownerContext.overflowX = (!ownerContext.widthModel.shrinkWrap &amp;&amp;
  162. ownerContext.maxChildMinWidth &amp;&amp;
  163. (c.autoScroll || c.overflowX)) || undef;
  164. ownerContext.overflowY = (!ownerContext.heightModel.shrinkWrap &amp;&amp;
  165. ownerContext.maxChildMinHeight &amp;&amp;
  166. (c.autoScroll || c.overflowY)) || undef;
  167. },
  168. calculate : function (ownerContext) {
  169. var me = this,
  170. childItems = ownerContext.childItems,
  171. length = childItems.length,
  172. containerSize = me.getContainerSize(ownerContext),
  173. info = {
  174. length: length,
  175. ownerContext: ownerContext,
  176. targetSize: containerSize
  177. },
  178. shrinkWrapWidth = ownerContext.widthModel.shrinkWrap,
  179. shrinkWrapHeight = ownerContext.heightModel.shrinkWrap,
  180. overflowX = ownerContext.overflowX,
  181. overflowY = ownerContext.overflowY,
  182. scrollbars, scrollbarSize, padding, i, contentWidth, contentHeight;
  183. if (overflowX || overflowY) {
  184. // If we have children that have minHeight/Width, we may be forced to overflow
  185. // and gain scrollbars. If so, we want to remove their space from the other
  186. // axis so that we fit things inside the scrollbars rather than under them.
  187. scrollbars = me.getScrollbarsNeeded(
  188. overflowX &amp;&amp; containerSize.width, overflowY &amp;&amp; containerSize.height,
  189. ownerContext.maxChildMinWidth, ownerContext.maxChildMinHeight);
  190. if (scrollbars) {
  191. scrollbarSize = Ext.getScrollbarSize();
  192. if (scrollbars &amp; 1) { // if we need the hscrollbar, remove its height
  193. containerSize.height -= scrollbarSize.height;
  194. }
  195. if (scrollbars &amp; 2) { // if we need the vscrollbar, remove its width
  196. containerSize.width -= scrollbarSize.width;
  197. }
  198. }
  199. }
  200. // Size the child items to the container (if non-shrinkWrap):
  201. for (i = 0; i &lt; length; ++i) {
  202. info.index = i;
  203. me.fitItem(childItems[i], info);
  204. }
  205. if (shrinkWrapHeight || shrinkWrapWidth) {
  206. padding = ownerContext.targetContext.getPaddingInfo();
  207. if (shrinkWrapWidth) {
  208. if (overflowY &amp;&amp; !containerSize.gotHeight) {
  209. // if we might overflow vertically and don't have the container height,
  210. // we don't know if we will need a vscrollbar or not, so we must wait
  211. // for that height so that we can determine the contentWidth...
  212. me.done = false;
  213. } else {
  214. contentWidth = info.contentWidth + padding.width;
  215. // the scrollbar flag (if set) will indicate that an overflow exists on
  216. // the horz(1) or vert(2) axis... if not set, then there could never be
  217. // an overflow...
  218. if (scrollbars &amp; 2) { // if we need the vscrollbar, add its width
  219. contentWidth += scrollbarSize.width;
  220. }
  221. if (!ownerContext.setContentWidth(contentWidth)) {
  222. me.done = false;
  223. }
  224. }
  225. }
  226. if (shrinkWrapHeight) {
  227. if (overflowX &amp;&amp; !containerSize.gotWidth) {
  228. // if we might overflow horizontally and don't have the container width,
  229. // we don't know if we will need a hscrollbar or not, so we must wait
  230. // for that width so that we can determine the contentHeight...
  231. me.done = false;
  232. } else {
  233. contentHeight = info.contentHeight + padding.height;
  234. // the scrollbar flag (if set) will indicate that an overflow exists on
  235. // the horz(1) or vert(2) axis... if not set, then there could never be
  236. // an overflow...
  237. if (scrollbars &amp; 1) { // if we need the hscrollbar, add its height
  238. contentHeight += scrollbarSize.height;
  239. }
  240. if (!ownerContext.setContentHeight(contentHeight)) {
  241. me.done = false;
  242. }
  243. }
  244. }
  245. }
  246. },
  247. fitItem: function (itemContext, info) {
  248. var me = this;
  249. if (itemContext.invalid) {
  250. me.done = false;
  251. return;
  252. }
  253. info.margins = itemContext.getMarginInfo();
  254. info.needed = info.got = 0;
  255. me.fitItemWidth(itemContext, info);
  256. me.fitItemHeight(itemContext, info);
  257. // If not all required dimensions have been satisfied, we're not done.
  258. if (info.got != info.needed) {
  259. me.done = false;
  260. }
  261. },
  262. fitItemWidth: function (itemContext, info) {
  263. var contentWidth, width;
  264. // Attempt to set only dimensions that are being controlled, not shrinkWrap dimensions
  265. if (info.ownerContext.widthModel.shrinkWrap) {
  266. // contentWidth must include the margins to be consistent with setItemWidth
  267. width = itemContext.getProp('width') + info.margins.width;
  268. // because we add margins, width will be NaN or a number (not undefined)
  269. contentWidth = info.contentWidth;
  270. if (contentWidth === undefined) {
  271. info.contentWidth = width;
  272. } else {
  273. info.contentWidth = Math.max(contentWidth, width);
  274. }
  275. } else if (itemContext.widthModel.calculated) {
  276. ++info.needed;
  277. if (info.targetSize.gotWidth) {
  278. ++info.got;
  279. this.setItemWidth(itemContext, info);
  280. }
  281. }
  282. this.positionItemX(itemContext, info);
  283. },
  284. fitItemHeight: function (itemContext, info) {
  285. var contentHeight, height;
  286. if (info.ownerContext.heightModel.shrinkWrap) {
  287. // contentHeight must include the margins to be consistent with setItemHeight
  288. height = itemContext.getProp('height') + info.margins.height;
  289. // because we add margins, height will be NaN or a number (not undefined)
  290. contentHeight = info.contentHeight;
  291. if (contentHeight === undefined) {
  292. info.contentHeight = height;
  293. } else {
  294. info.contentHeight = Math.max(contentHeight, height);
  295. }
  296. } else if (itemContext.heightModel.calculated) {
  297. ++info.needed;
  298. if (info.targetSize.gotHeight) {
  299. ++info.got;
  300. this.setItemHeight(itemContext, info);
  301. }
  302. }
  303. this.positionItemY(itemContext, info);
  304. },
  305. positionItemX: function (itemContext, info) {
  306. var margins = info.margins;
  307. // Adjust position to account for configured margins or if we have multiple items
  308. // (all items should overlap):
  309. if (info.index || margins.left) {
  310. itemContext.setProp('x', margins.left);
  311. }
  312. if (margins.width) {
  313. // Need the margins for shrink-wrapping but old IE sometimes collapses the left margin into the padding
  314. itemContext.setProp('margin-right', margins.width);
  315. }
  316. },
  317. positionItemY: function (itemContext, info) {
  318. var margins = info.margins;
  319. if (info.index || margins.top) {
  320. itemContext.setProp('y', margins.top);
  321. }
  322. if (margins.height) {
  323. // Need the margins for shrink-wrapping but old IE sometimes collapses the top margin into the padding
  324. itemContext.setProp('margin-bottom', margins.height);
  325. }
  326. },
  327. setItemHeight: function (itemContext, info) {
  328. itemContext.setHeight(info.targetSize.height - info.margins.height);
  329. },
  330. setItemWidth: function (itemContext, info) {
  331. itemContext.setWidth(info.targetSize.width - info.margins.width);
  332. }
  333. });
  334. </pre>
  335. </body>
  336. </html>