Dock.html 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140
  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-component-Dock'>/**
  19. </span> * This ComponentLayout handles docking for Panels. It takes care of panels that are
  20. * part of a ContainerLayout that sets this Panel's size and Panels that are part of
  21. * an AutoContainerLayout in which this panel get his height based of the CSS or
  22. * or its content.
  23. * @private
  24. */
  25. Ext.define('Ext.layout.component.Dock', {
  26. /* Begin Definitions */
  27. extend: 'Ext.layout.component.Component',
  28. alias: 'layout.dock',
  29. alternateClassName: 'Ext.layout.component.AbstractDock',
  30. /* End Definitions */
  31. type: 'dock',
  32. initializedBorders: -1,
  33. horizontalCollapsePolicy: { width: true, x: true },
  34. verticalCollapsePolicy: { height: true, y: true },
  35. finishRender: function () {
  36. var me = this,
  37. target, items;
  38. me.callParent();
  39. target = me.getRenderTarget();
  40. items = me.getDockedItems();
  41. me.finishRenderItems(target, items);
  42. },
  43. isItemBoxParent: function (itemContext) {
  44. return true;
  45. },
  46. isItemShrinkWrap: function (item) {
  47. return true;
  48. },
  49. dockOpposites: {
  50. top: 'bottom',
  51. right: 'left',
  52. bottom: 'top',
  53. left: 'right'
  54. },
  55. handleItemBorders: function() {
  56. var me = this,
  57. owner = me.owner,
  58. borders, docked,
  59. oldBorders = me.borders,
  60. opposites = me.dockOpposites,
  61. currentGeneration = owner.dockedItems.generation,
  62. i, ln, item, dock, side, borderItem,
  63. collapsed = me.collapsed;
  64. if (me.initializedBorders == currentGeneration || (owner.border &amp;&amp; !owner.manageBodyBorders)) {
  65. return;
  66. }
  67. me.initializedBorders = currentGeneration;
  68. // Borders have to be calculated using expanded docked item collection.
  69. me.collapsed = false;
  70. docked = me.getLayoutItems();
  71. me.collapsed = collapsed;
  72. borders = { top: [], right: [], bottom: [], left: [] };
  73. for (i = 0, ln = docked.length; i &lt; ln; i++) {
  74. item = docked[i];
  75. dock = item.dock;
  76. if (item.ignoreBorderManagement) {
  77. continue;
  78. }
  79. if (!borders[dock].satisfied) {
  80. borders[dock].push(item);
  81. borders[dock].satisfied = true;
  82. }
  83. if (!borders.top.satisfied &amp;&amp; opposites[dock] !== 'top') {
  84. borders.top.push(item);
  85. }
  86. if (!borders.right.satisfied &amp;&amp; opposites[dock] !== 'right') {
  87. borders.right.push(item);
  88. }
  89. if (!borders.bottom.satisfied &amp;&amp; opposites[dock] !== 'bottom') {
  90. borders.bottom.push(item);
  91. }
  92. if (!borders.left.satisfied &amp;&amp; opposites[dock] !== 'left') {
  93. borders.left.push(item);
  94. }
  95. }
  96. if (oldBorders) {
  97. for (side in oldBorders) {
  98. if (oldBorders.hasOwnProperty(side)) {
  99. ln = oldBorders[side].length;
  100. if (!owner.manageBodyBorders) {
  101. for (i = 0; i &lt; ln; i++) {
  102. borderItem = oldBorders[side][i];
  103. if (!borderItem.isDestroyed) {
  104. borderItem.removeCls(Ext.baseCSSPrefix + 'docked-noborder-' + side);
  105. }
  106. }
  107. if (!oldBorders[side].satisfied &amp;&amp; !owner.bodyBorder) {
  108. owner.removeBodyCls(Ext.baseCSSPrefix + 'docked-noborder-' + side);
  109. }
  110. }
  111. else if (oldBorders[side].satisfied) {
  112. owner.setBodyStyle('border-' + side + '-width', '');
  113. }
  114. }
  115. }
  116. }
  117. for (side in borders) {
  118. if (borders.hasOwnProperty(side)) {
  119. ln = borders[side].length;
  120. if (!owner.manageBodyBorders) {
  121. for (i = 0; i &lt; ln; i++) {
  122. borders[side][i].addCls(Ext.baseCSSPrefix + 'docked-noborder-' + side);
  123. }
  124. if ((!borders[side].satisfied &amp;&amp; !owner.bodyBorder) || owner.bodyBorder === false) {
  125. owner.addBodyCls(Ext.baseCSSPrefix + 'docked-noborder-' + side);
  126. }
  127. }
  128. else if (borders[side].satisfied) {
  129. owner.setBodyStyle('border-' + side + '-width', '1px');
  130. }
  131. }
  132. }
  133. me.borders = borders;
  134. },
  135. beforeLayoutCycle: function (ownerContext) {
  136. var me = this,
  137. owner = me.owner,
  138. shrinkWrap = me.sizeModels.shrinkWrap,
  139. collapsedHorz, collapsedVert;
  140. if (owner.collapsed) {
  141. if (owner.collapsedVertical()) {
  142. collapsedVert = true;
  143. ownerContext.measureDimensions = 1;
  144. } else {
  145. collapsedHorz = true;
  146. ownerContext.measureDimensions = 2;
  147. }
  148. }
  149. ownerContext.collapsedVert = collapsedVert;
  150. ownerContext.collapsedHorz = collapsedHorz;
  151. // If we are collapsed, we want to auto-layout using the placeholder/expander
  152. // instead of the normal items/dockedItems. This must be done here since we could
  153. // be in a box layout w/stretchmax which sets the width/heightModel to allow it to
  154. // control the size.
  155. if (collapsedVert) {
  156. ownerContext.heightModel = shrinkWrap;
  157. } else if (collapsedHorz) {
  158. ownerContext.widthModel = shrinkWrap;
  159. }
  160. },
  161. beginLayout: function(ownerContext) {
  162. var me = this,
  163. owner = me.owner,
  164. docked = me.getLayoutItems(),
  165. layoutContext = ownerContext.context,
  166. dockedItemCount = docked.length,
  167. dockedItems, i, item, itemContext, offsets,
  168. collapsed;
  169. me.callParent(arguments);
  170. me.handleItemBorders();
  171. // Cache the children as ContextItems (like a Container). Also setup to handle
  172. // collapsed state:
  173. collapsed = owner.getCollapsed();
  174. if (collapsed !== me.lastCollapsedState &amp;&amp; Ext.isDefined(me.lastCollapsedState)) {
  175. // If we are collapsing...
  176. if (me.owner.collapsed) {
  177. ownerContext.isCollapsingOrExpanding = 1;
  178. // Add the collapsed class now, so that collapsed CSS rules are applied before measurements are taken by the layout.
  179. owner.addClsWithUI(owner.collapsedCls);
  180. } else {
  181. ownerContext.isCollapsingOrExpanding = 2;
  182. // Remove the collapsed class now, before layout calculations are done.
  183. owner.removeClsWithUI(owner.collapsedCls);
  184. ownerContext.lastCollapsedState = me.lastCollapsedState;
  185. }
  186. }
  187. me.lastCollapsedState = collapsed;
  188. ownerContext.dockedItems = dockedItems = [];
  189. for (i = 0; i &lt; dockedItemCount; i++) {
  190. item = docked[i];
  191. if (item.rendered) {
  192. itemContext = layoutContext.getCmp(item);
  193. itemContext.dockedAt = { x: 0, y: 0 };
  194. itemContext.offsets = offsets = Ext.Element.parseBox(item.offsets || {});
  195. offsets.width = offsets.left + offsets.right;
  196. offsets.height = offsets.top + offsets.bottom;
  197. dockedItems.push(itemContext);
  198. }
  199. }
  200. ownerContext.bodyContext = ownerContext.getEl('body');
  201. },
  202. beginLayoutCycle: function(ownerContext) {
  203. var me = this,
  204. docked = ownerContext.dockedItems,
  205. len = docked.length,
  206. owner = me.owner,
  207. frameBody = owner.frameBody,
  208. lastHeightModel = me.lastHeightModel,
  209. i, item, dock;
  210. me.callParent(arguments);
  211. if (lastHeightModel &amp;&amp; lastHeightModel.shrinkWrap &amp;&amp;
  212. !ownerContext.heightModel.shrinkWrap &amp;&amp; !me.owner.manageHeight) {
  213. owner.body.dom.style.marginBottom = '';
  214. }
  215. if (ownerContext.widthModel.auto) {
  216. if (ownerContext.widthModel.shrinkWrap) {
  217. owner.el.setWidth(null);
  218. }
  219. owner.body.setWidth(null);
  220. if (frameBody) {
  221. frameBody.setWidth(null);
  222. }
  223. }
  224. if (ownerContext.heightModel.auto) {
  225. owner.body.setHeight(null);
  226. //owner.el.setHeight(null); Disable this for now
  227. if (frameBody) {
  228. frameBody.setHeight(null);
  229. }
  230. }
  231. // Each time we begin (2nd+ would be due to invalidate) we need to publish the
  232. // known contentWidth/Height if we are collapsed:
  233. if (ownerContext.collapsedVert) {
  234. ownerContext.setContentHeight(0);
  235. } else if (ownerContext.collapsedHorz) {
  236. ownerContext.setContentWidth(0);
  237. }
  238. // dock: 'right' items, when a panel gets narrower get &quot;squished&quot;. Moving them to
  239. // left:0px avoids this!
  240. for (i = 0; i &lt; len; i++) {
  241. item = docked[i].target;
  242. dock = item.dock;
  243. if (dock == 'right') {
  244. item.el.setLeft(0);
  245. } else if (dock != 'left') {
  246. continue;
  247. }
  248. // TODO - clear width/height?
  249. }
  250. },
  251. calculate: function (ownerContext) {
  252. var me = this,
  253. measure = me.measureAutoDimensions(ownerContext, ownerContext.measureDimensions),
  254. state = ownerContext.state,
  255. horzDone = state.horzDone,
  256. vertDone = state.vertDone,
  257. bodyContext = ownerContext.bodyContext,
  258. horz, vert, forward, backward;
  259. // make sure we can use these value w/o calling methods to get them
  260. ownerContext.borderInfo || ownerContext.getBorderInfo();
  261. ownerContext.paddingInfo || ownerContext.getPaddingInfo();
  262. ownerContext.framingInfo || ownerContext.getFraming();
  263. bodyContext.borderInfo || bodyContext.getBorderInfo();
  264. bodyContext.paddingInfo || bodyContext.getPaddingInfo();
  265. // Start the axes so they are ready to proceed inwards (fixed-size) or outwards
  266. // (shrinkWrap) and stash key property names as well:
  267. horz = !horzDone &amp;&amp;
  268. me.createAxis(ownerContext, measure.contentWidth, ownerContext.widthModel,
  269. 'left', 'right', 'x', 'width', 'Width', ownerContext.collapsedHorz);
  270. vert = !vertDone &amp;&amp;
  271. me.createAxis(ownerContext, measure.contentHeight, ownerContext.heightModel,
  272. 'top', 'bottom', 'y', 'height', 'Height', ownerContext.collapsedVert);
  273. // We iterate forward and backward over the dockedItems at the same time based on
  274. // whether an axis is shrinkWrap or fixed-size. For a fixed-size axis, the outer box
  275. // axis is allocated to docked items in forward order and is reduced accordingly.
  276. // To handle a shrinkWrap axis, the box starts at the inner (body) size and is used to
  277. // size docked items in backwards order. This is because the last docked item shares
  278. // an edge with the body. The item size is used to adjust the shrinkWrap axis outwards
  279. // until the first docked item (at the outermost edge) is processed. This backwards
  280. // order ensures that docked items never get an incorrect size for any dimension.
  281. for (forward = 0, backward = ownerContext.dockedItems.length; backward--; ++forward) {
  282. if (horz) {
  283. me.dockChild(ownerContext, horz, backward, forward);
  284. }
  285. if (vert) {
  286. me.dockChild(ownerContext, vert, backward, forward);
  287. }
  288. }
  289. if (horz &amp;&amp; me.finishAxis(ownerContext, horz)) {
  290. state.horzDone = horzDone = horz;
  291. }
  292. if (vert &amp;&amp; me.finishAxis(ownerContext, vert)) {
  293. state.vertDone = vertDone = vert;
  294. }
  295. // Once all items are docked, the final size of the outer panel or inner body can
  296. // be determined. If we can determine both width and height, we are done.
  297. if (horzDone &amp;&amp; vertDone &amp;&amp; me.finishConstraints(ownerContext, horzDone, vertDone)) {
  298. // Size information is published as we dock items but position is hard to do
  299. // that way (while avoiding published multiple times) so we publish all the
  300. // positions at the end.
  301. me.finishPositions(ownerContext, horzDone, vertDone);
  302. } else {
  303. me.done = false;
  304. }
  305. },
  306. <span id='Ext-layout-component-Dock-method-createAxis'> /**
  307. </span> * Creates an axis object given the particulars.
  308. * @private
  309. */
  310. createAxis: function (ownerContext, contentSize, sizeModel, dockBegin, dockEnd, posProp,
  311. sizeProp, sizePropCap, collapsedAxis) {
  312. var begin = 0,
  313. owner = this.owner,
  314. maxSize = owner['max' + sizePropCap],
  315. minSize = owner['min' + sizePropCap] || 0,
  316. hasMaxSize = maxSize != null, // exactly the same as &quot;maxSize !== null &amp;&amp; maxSize !== undefined&quot;
  317. setSize = 'set' + sizePropCap,
  318. border, bodyContext, frameSize, padding, end;
  319. if (sizeModel.shrinkWrap) {
  320. // End position before adding docks around the content is content size plus the body borders in this axis.
  321. // If collapsed in this axis, the body borders will not be shown.
  322. if (collapsedAxis) {
  323. end = 0;
  324. } else {
  325. bodyContext = ownerContext.bodyContext;
  326. end = contentSize + bodyContext.borderInfo[sizeProp];
  327. }
  328. } else {
  329. border = ownerContext.borderInfo;
  330. frameSize = ownerContext.framingInfo;
  331. padding = ownerContext.paddingInfo;
  332. end = ownerContext.getProp(sizeProp);
  333. end -= border[dockEnd] + padding[dockEnd] + frameSize[dockEnd];
  334. begin = border[dockBegin] + padding[dockBegin] + frameSize[dockBegin];
  335. }
  336. return {
  337. shrinkWrap: sizeModel.shrinkWrap,
  338. sizeModel: sizeModel,
  339. // An axis tracks start and end+1 px positions. eg 0 to 10 for 10px high
  340. begin: begin,
  341. end: end,
  342. collapsed: collapsedAxis,
  343. horizontal: posProp == 'x',
  344. ignoreFrameBegin: false,
  345. ignoreFrameEnd: false,
  346. initialSize: end - begin,
  347. hasMinMaxConstraints: (minSize || hasMaxSize) &amp;&amp; sizeModel.shrinkWrap,
  348. minSize: minSize,
  349. maxSize: hasMaxSize ? maxSize : 1e9,
  350. bodyPosProp: this.owner.manageHeight ? posProp : ('margin-' + dockBegin), // 'margin-left' or 'margin-top'
  351. dockBegin: dockBegin, // 'left' or 'top'
  352. dockEnd: dockEnd, // 'right' or 'end'
  353. posProp: posProp, // 'x' or 'y'
  354. sizeProp: sizeProp, // 'width' or 'height'
  355. sizePropCap: sizePropCap, // 'Width' or 'Height'
  356. setSize: setSize,
  357. dockedPixelsEnd: 0
  358. };
  359. },
  360. <span id='Ext-layout-component-Dock-method-dockChild'> /**
  361. </span> * Docks a child item on the specified axis. This boils down to determining if the item
  362. * is docked at the &quot;beginning&quot; of the axis (&quot;left&quot; if horizontal, &quot;top&quot; if vertical),
  363. * the &quot;end&quot; of the axis (&quot;right&quot; if horizontal, &quot;bottom&quot; if vertical) or stretches
  364. * along the axis (&quot;top&quot; or &quot;bottom&quot; if horizontal, &quot;left&quot; or &quot;right&quot; if vertical). It
  365. * also has to differentiate between fixed and shrinkWrap sized dimensions.
  366. * @private
  367. */
  368. dockChild: function (ownerContext, axis, backward, forward) {
  369. var me = this,
  370. itemContext = ownerContext.dockedItems[axis.shrinkWrap ? backward : forward],
  371. item = itemContext.target,
  372. dock = item.dock, // left/top/right/bottom
  373. pos;
  374. if(item.ignoreParentFrame &amp;&amp; ownerContext.isCollapsingOrExpanding) {
  375. // collapsed window header margins may differ from expanded window header margins
  376. // so we need to make sure the old cached values are not used in axis calculations
  377. itemContext.clearMarginCache();
  378. }
  379. if (dock == axis.dockBegin) {
  380. if (axis.shrinkWrap) {
  381. pos = me.dockOutwardBegin(ownerContext, itemContext, item, axis);
  382. } else {
  383. pos = me.dockInwardBegin(ownerContext, itemContext, item, axis);
  384. }
  385. } else if (dock == axis.dockEnd) {
  386. if (axis.shrinkWrap) {
  387. pos = me.dockOutwardEnd(ownerContext, itemContext, item, axis);
  388. } else {
  389. pos = me.dockInwardEnd(ownerContext, itemContext, item, axis);
  390. }
  391. } else {
  392. pos = me.dockStretch(ownerContext, itemContext, item, axis);
  393. }
  394. itemContext.dockedAt[axis.posProp] = pos;
  395. },
  396. <span id='Ext-layout-component-Dock-method-dockInwardBegin'> /**
  397. </span> * Docks an item on a fixed-size axis at the &quot;beginning&quot;. The &quot;beginning&quot; of the horizontal
  398. * axis is &quot;left&quot; and the vertical is &quot;top&quot;. For a fixed-size axis, the size works from
  399. * the outer element (the panel) towards the body.
  400. * @private
  401. */
  402. dockInwardBegin: function (ownerContext, itemContext, item, axis) {
  403. var pos = axis.begin,
  404. sizeProp = axis.sizeProp,
  405. size,
  406. dock;
  407. if (item.ignoreParentFrame) {
  408. dock = item.dock;
  409. pos -= ownerContext.borderInfo[dock] + ownerContext.paddingInfo[dock] +
  410. ownerContext.framingInfo[dock];
  411. }
  412. if (!item.overlay) {
  413. size = itemContext.getProp(sizeProp) + itemContext.getMarginInfo()[sizeProp];
  414. axis.begin += size;
  415. }
  416. return pos;
  417. },
  418. <span id='Ext-layout-component-Dock-method-dockInwardEnd'> /**
  419. </span> * Docks an item on a fixed-size axis at the &quot;end&quot;. The &quot;end&quot; of the horizontal axis is
  420. * &quot;right&quot; and the vertical is &quot;bottom&quot;.
  421. * @private
  422. */
  423. dockInwardEnd: function (ownerContext, itemContext, item, axis) {
  424. var sizeProp = axis.sizeProp,
  425. size = itemContext.getProp(sizeProp) + itemContext.getMarginInfo()[sizeProp],
  426. pos = axis.end - size;
  427. if (!item.overlay) {
  428. axis.end = pos;
  429. }
  430. if (item.ignoreParentFrame) {
  431. pos += ownerContext.borderInfo[item.dock] + ownerContext.paddingInfo[item.dock] +
  432. ownerContext.framingInfo[item.dock];
  433. }
  434. return pos;
  435. },
  436. <span id='Ext-layout-component-Dock-method-dockOutwardBegin'> /**
  437. </span> * Docks an item on a shrinkWrap axis at the &quot;beginning&quot;. The &quot;beginning&quot; of the horizontal
  438. * axis is &quot;left&quot; and the vertical is &quot;top&quot;. For a shrinkWrap axis, the size works from
  439. * the body outward to the outermost element (the panel).
  440. *
  441. * During the docking process, coordinates are allowed to be negative. We start with the
  442. * body at (0,0) so items docked &quot;top&quot; or &quot;left&quot; will simply be assigned negative x/y. In
  443. * the {@link #finishPositions} method these are corrected and framing is added. This way
  444. * the correction is applied as a simple translation of delta x/y on all coordinates to
  445. * bring the origin back to (0,0).
  446. * @private
  447. */
  448. dockOutwardBegin: function (ownerContext, itemContext, item, axis) {
  449. var pos = axis.begin,
  450. sizeProp = axis.sizeProp,
  451. dock, size;
  452. if (axis.collapsed) {
  453. axis.ignoreFrameBegin = axis.ignoreFrameEnd = true;
  454. } else if (item.ignoreParentFrame) {
  455. dock = item.dock;
  456. pos -= ownerContext.borderInfo[dock] + ownerContext.paddingInfo[dock] +
  457. ownerContext.framingInfo[dock];
  458. axis.ignoreFrameBegin = true;
  459. }
  460. if (!item.overlay) {
  461. size = itemContext.getProp(sizeProp) + itemContext.getMarginInfo()[sizeProp];
  462. pos -= size;
  463. axis.begin = pos;
  464. }
  465. return pos;
  466. },
  467. <span id='Ext-layout-component-Dock-method-dockOutwardEnd'> /**
  468. </span> * Docks an item on a shrinkWrap axis at the &quot;end&quot;. The &quot;end&quot; of the horizontal axis is
  469. * &quot;right&quot; and the vertical is &quot;bottom&quot;.
  470. * @private
  471. */
  472. dockOutwardEnd: function (ownerContext, itemContext, item, axis) {
  473. var pos = axis.end,
  474. sizeProp = axis.sizeProp,
  475. dock, size;
  476. size = itemContext.getProp(sizeProp) + itemContext.getMarginInfo()[sizeProp];
  477. if (axis.collapsed) {
  478. axis.ignoreFrameBegin = axis.ignoreFrameEnd = true;
  479. } else if (item.ignoreParentFrame) {
  480. dock = item.dock;
  481. pos += ownerContext.borderInfo[dock] + ownerContext.paddingInfo[dock] +
  482. ownerContext.framingInfo[dock];
  483. axis.ignoreFrameEnd = true;
  484. }
  485. if (!item.overlay) {
  486. axis.end = pos + size;
  487. axis.dockedPixelsEnd += size;
  488. }
  489. return pos;
  490. },
  491. <span id='Ext-layout-component-Dock-method-dockStretch'> /**
  492. </span> * Docks an item that might stretch across an axis. This is done for dock &quot;top&quot; and
  493. * &quot;bottom&quot; items on the horizontal axis and dock &quot;left&quot; and &quot;right&quot; on the vertical.
  494. * @private
  495. */
  496. dockStretch: function (ownerContext, itemContext, item, axis) {
  497. var dock = item.dock, // left/top/right/bottom (also used to index padding/border)
  498. sizeProp = axis.sizeProp, // 'width' or 'height'
  499. horizontal = dock == 'top' || dock == 'bottom',
  500. offsets = itemContext.offsets,
  501. border = ownerContext.borderInfo,
  502. padding = ownerContext.paddingInfo,
  503. endProp = horizontal ? 'right' : 'bottom',
  504. startProp = horizontal ? 'left' : 'top',
  505. pos = axis.begin + offsets[startProp],
  506. margin, size, framing;
  507. if (item.stretch !== false) {
  508. size = axis.end - pos - offsets[endProp];
  509. if (item.ignoreParentFrame) {
  510. framing = ownerContext.framingInfo;
  511. pos -= border[startProp] + padding[startProp] + framing[startProp];
  512. size += border[sizeProp] + padding[sizeProp] + framing[sizeProp];
  513. }
  514. margin = itemContext.getMarginInfo();
  515. size -= margin[sizeProp];
  516. itemContext[axis.setSize](size);
  517. }
  518. return pos;
  519. },
  520. <span id='Ext-layout-component-Dock-method-finishAxis'> /**
  521. </span> * Finishes the calculation of an axis by determining its size. In non-shrink-wrap
  522. * cases, this is also where we set the body size.
  523. * @private
  524. */
  525. finishAxis: function (ownerContext, axis) {
  526. var size = axis.end - axis.begin,
  527. setSizeMethod = axis.setSize,
  528. beginName = axis.dockBegin, // left or top
  529. endName = axis.dockEnd, // right or bottom
  530. border = ownerContext.borderInfo,
  531. padding = ownerContext.paddingInfo,
  532. framing = ownerContext.framingInfo,
  533. frameSize = padding[beginName] + border[beginName] + framing[beginName],
  534. bodyContext = ownerContext.bodyContext,
  535. bodyPos, bodySize, dirty;
  536. if (axis.shrinkWrap) {
  537. // Since items docked left/top on a shrinkWrap axis go into negative coordinates,
  538. // we apply a delta to all coordinates to adjust their relative origin back to
  539. // (0,0).
  540. axis.delta = -axis.begin; // either 0 or a positive number
  541. bodySize = axis.initialSize;
  542. if (axis.ignoreFrameBegin) {
  543. axis.delta -= border[beginName];
  544. bodyPos = -axis.begin - frameSize;
  545. } else {
  546. size += frameSize;
  547. axis.delta += padding[beginName] + framing[beginName];
  548. bodyPos = -axis.begin;
  549. }
  550. if (!axis.ignoreFrameEnd) {
  551. size += padding[endName] + border[endName] + framing[endName];
  552. }
  553. axis.size = size; // we have to wait for min/maxWidth/Height processing
  554. if (!axis.horizontal &amp;&amp; !this.owner.manageHeight) {
  555. // the height of the bodyEl will give the proper height to the outerEl so
  556. // we don't need to set heights in the DOM
  557. dirty = false;
  558. }
  559. } else {
  560. // For a fixed-size axis, we started at the outer box and already have the
  561. // proper origin... almost... except for the owner's border.
  562. axis.delta = -border[axis.dockBegin]; // 'left' or 'top'
  563. // Body size is remaining space between ends of Axis.
  564. bodySize = size;
  565. bodyPos = axis.begin - frameSize;
  566. }
  567. bodyContext[setSizeMethod](bodySize, dirty);
  568. bodyContext.setProp(axis.bodyPosProp, bodyPos);
  569. return !isNaN(size);
  570. },
  571. <span id='Ext-layout-component-Dock-method-finishConstraints'> /**
  572. </span> * Finishes processing of each axis by applying the min/max size constraints.
  573. * @private
  574. */
  575. finishConstraints: function (ownerContext, horz, vert) {
  576. var sizeModels = this.sizeModels,
  577. publishWidth = horz.shrinkWrap,
  578. publishHeight = vert.shrinkWrap,
  579. dirty, height, width, heightModel, widthModel, size;
  580. if (publishWidth) {
  581. size = horz.size;
  582. if (size &lt; horz.minSize) {
  583. widthModel = sizeModels.constrainedMin;
  584. width = horz.minSize;
  585. } else if (size &gt; horz.maxSize) {
  586. widthModel = sizeModels.constrainedMax;
  587. width = horz.maxSize;
  588. } else {
  589. width = size;
  590. }
  591. }
  592. if (publishHeight) {
  593. size = vert.size;
  594. if (size &lt; vert.minSize) {
  595. heightModel = sizeModels.constrainedMin;
  596. height = vert.minSize;
  597. } else if (size &gt; vert.maxSize) {
  598. heightModel = sizeModels.constrainedMax;
  599. height = vert.maxSize;
  600. } else {
  601. if (!ownerContext.collapsedVert &amp;&amp; !this.owner.manageHeight) {
  602. // height of the outerEl is provided by the height (including margins)
  603. // of the bodyEl, so this value does not need to be written to the DOM
  604. dirty = false;
  605. // so long as we set top and bottom margins on the bodyEl!
  606. ownerContext.bodyContext.setProp('margin-bottom', vert.dockedPixelsEnd);
  607. }
  608. height = size;
  609. }
  610. }
  611. // Handle the constraints...
  612. if (widthModel || heightModel) {
  613. // See ContextItem#init for an analysis of why this case is special. Basically,
  614. // in this case, we only know the width and the height could be anything.
  615. if (widthModel &amp;&amp; heightModel &amp;&amp;
  616. widthModel.constrainedMax &amp;&amp; heightModel.constrainedMin) {
  617. ownerContext.invalidate({ widthModel: widthModel });
  618. return false;
  619. }
  620. // To process a width or height other than that to which we have shrinkWrapped,
  621. // we need to invalidate our component and carry forward w/these constrains...
  622. // unless the ownerLayout wants these results and will invalidate us anyway.
  623. if (!ownerContext.widthModel.calculatedFromShrinkWrap &amp;&amp;
  624. !ownerContext.heightModel.calculatedFromShrinkWrap) {
  625. // nope, just us to handle the constraint...
  626. ownerContext.invalidate({ widthModel: widthModel, heightModel: heightModel });
  627. return false;
  628. }
  629. // We have a constraint to deal with, so we just adjust the size models and
  630. // allow the ownerLayout to invalidate us with its contribution to our final
  631. // size...
  632. }
  633. // we only publish the sizes if we are not invalidating the result...
  634. if (publishWidth) {
  635. ownerContext.setWidth(width);
  636. if (widthModel) {
  637. ownerContext.widthModel = widthModel; // important to the ownerLayout
  638. }
  639. }
  640. if (publishHeight) {
  641. ownerContext.setHeight(height, dirty);
  642. if (heightModel) {
  643. ownerContext.heightModel = heightModel; // important to the ownerLayout
  644. }
  645. }
  646. return true;
  647. },
  648. <span id='Ext-layout-component-Dock-method-finishPositions'> /**
  649. </span> * Finishes the calculation by setting positions on the body and all of the items.
  650. * @private
  651. */
  652. finishPositions: function (ownerContext, horz, vert) {
  653. var dockedItems = ownerContext.dockedItems,
  654. length = dockedItems.length,
  655. deltaX = horz.delta,
  656. deltaY = vert.delta,
  657. index, itemContext;
  658. for (index = 0; index &lt; length; ++index) {
  659. itemContext = dockedItems[index];
  660. itemContext.setProp('x', deltaX + itemContext.dockedAt.x);
  661. itemContext.setProp('y', deltaY + itemContext.dockedAt.y);
  662. }
  663. },
  664. finishedLayout: function(ownerContext) {
  665. var me = this,
  666. target = ownerContext.target;
  667. me.callParent(arguments);
  668. if (!ownerContext.animatePolicy) {
  669. if (ownerContext.isCollapsingOrExpanding === 1) {
  670. target.afterCollapse(false);
  671. } else if (ownerContext.isCollapsingOrExpanding === 2) {
  672. target.afterExpand(false);
  673. }
  674. }
  675. },
  676. getAnimatePolicy: function(ownerContext) {
  677. var me = this,
  678. lastCollapsedState, policy;
  679. if (ownerContext.isCollapsingOrExpanding == 1) {
  680. lastCollapsedState = me.lastCollapsedState;
  681. } else if (ownerContext.isCollapsingOrExpanding == 2) {
  682. lastCollapsedState = ownerContext.lastCollapsedState;
  683. }
  684. if (lastCollapsedState == 'left' || lastCollapsedState == 'right') {
  685. policy = me.horizontalCollapsePolicy;
  686. } else if (lastCollapsedState == 'top' || lastCollapsedState == 'bottom') {
  687. policy = me.verticalCollapsePolicy;
  688. }
  689. return policy;
  690. },
  691. <span id='Ext-layout-component-Dock-method-getDockedItems'> /**
  692. </span> * Retrieve an ordered and/or filtered array of all docked Components.
  693. * @param {String} [order='render'] The desired ordering of the items ('render' or 'visual').
  694. * @param {Boolean} [beforeBody] An optional flag to limit the set of items to only those
  695. * before the body (true) or after the body (false). All components are returned by
  696. * default.
  697. * @return {Ext.Component[]} An array of components.
  698. * @protected
  699. */
  700. getDockedItems: function(order, beforeBody) {
  701. var me = this,
  702. renderedOnly = (order === 'visual'),
  703. all = renderedOnly ? Ext.ComponentQuery.query('[rendered]', me.owner.dockedItems.items) : me.owner.dockedItems.items,
  704. sort = all &amp;&amp; all.length &amp;&amp; order !== false,
  705. renderOrder,
  706. dock, dockedItems, i, isBefore, length;
  707. if (beforeBody == null) {
  708. dockedItems = sort &amp;&amp; !renderedOnly ? all.slice() : all;
  709. } else {
  710. dockedItems = [];
  711. for (i = 0, length = all.length; i &lt; length; ++i) {
  712. dock = all[i].dock;
  713. isBefore = (dock == 'top' || dock == 'left');
  714. if (beforeBody ? isBefore : !isBefore) {
  715. dockedItems.push(all[i]);
  716. }
  717. }
  718. sort = sort &amp;&amp; dockedItems.length;
  719. }
  720. if (sort) {
  721. renderOrder = (order = order || 'render') == 'render';
  722. Ext.Array.sort(dockedItems, function(a, b) {
  723. var aw,
  724. bw;
  725. // If the two items are on opposite sides of the body, they must not be sorted by any weight value:
  726. // For rendering purposes, left/top *always* sorts before right/bottom
  727. if (renderOrder &amp;&amp; ((aw = me.owner.dockOrder[a.dock]) !== (bw = me.owner.dockOrder[b.dock]))) {
  728. // The two dockOrder values cancel out when two items are on opposite sides.
  729. if (!(aw + bw)) {
  730. return aw - bw;
  731. }
  732. }
  733. aw = me.getItemWeight(a, order);
  734. bw = me.getItemWeight(b, order);
  735. if ((aw !== undefined) &amp;&amp; (bw !== undefined)) {
  736. return aw - bw;
  737. }
  738. return 0;
  739. });
  740. }
  741. return dockedItems || [];
  742. },
  743. getItemWeight: function (item, order) {
  744. var weight = item.weight || this.owner.defaultDockWeights[item.dock];
  745. return weight[order] || weight;
  746. },
  747. <span id='Ext-layout-component-Dock-method-getLayoutItems'> /**
  748. </span> * @protected
  749. * Returns an array containing all the **visible** docked items inside this layout's owner Panel
  750. * @return {Array} An array containing all the **visible** docked items of the Panel
  751. */
  752. getLayoutItems : function() {
  753. var me = this,
  754. items,
  755. itemCount,
  756. item,
  757. i,
  758. result;
  759. if (me.owner.collapsed) {
  760. result = me.owner.getCollapsedDockedItems();
  761. } else {
  762. items = me.getDockedItems('visual');
  763. itemCount = items.length;
  764. result = [];
  765. for (i = 0; i &lt; itemCount; i++) {
  766. item = items[i];
  767. if (!item.hidden) {
  768. result.push(item);
  769. }
  770. }
  771. }
  772. return result;
  773. },
  774. // Content size includes padding but not borders, so subtract them off
  775. measureContentWidth: function (ownerContext) {
  776. var bodyContext = ownerContext.bodyContext;
  777. return bodyContext.el.getWidth() - bodyContext.getBorderInfo().width;
  778. },
  779. measureContentHeight: function (ownerContext) {
  780. var bodyContext = ownerContext.bodyContext;
  781. return bodyContext.el.getHeight() - bodyContext.getBorderInfo().height;
  782. },
  783. redoLayout: function(ownerContext) {
  784. var me = this,
  785. owner = me.owner;
  786. // If we are collapsing...
  787. if (ownerContext.isCollapsingOrExpanding == 1) {
  788. if (owner.reExpander) {
  789. owner.reExpander.el.show();
  790. }
  791. // Add the collapsed class now, so that collapsed CSS rules are applied before measurements are taken by the layout.
  792. owner.addClsWithUI(owner.collapsedCls);
  793. ownerContext.redo(true);
  794. } else if (ownerContext.isCollapsingOrExpanding == 2) {
  795. // Remove the collapsed class now, before layout calculations are done.
  796. owner.removeClsWithUI(owner.collapsedCls);
  797. ownerContext.bodyContext.redo();
  798. }
  799. },
  800. // @private override inherited.
  801. // We need to render in the correct order, top/left before bottom/right
  802. renderChildren: function() {
  803. var me = this,
  804. items = me.getDockedItems(),
  805. target = me.getRenderTarget();
  806. me.renderItems(items, target);
  807. },
  808. <span id='Ext-layout-component-Dock-method-renderItems'> /**
  809. </span> * @protected
  810. * Render the top and left docked items before any existing DOM nodes in our render target,
  811. * and then render the right and bottom docked items after. This is important, for such things
  812. * as tab stops and ARIA readers, that the DOM nodes are in a meaningful order.
  813. * Our collection of docked items will already be ordered via Panel.getDockedItems().
  814. */
  815. renderItems: function(items, target) {
  816. var me = this,
  817. dockedItemCount = items.length,
  818. itemIndex = 0,
  819. correctPosition = 0,
  820. staticNodeCount = 0,
  821. targetNodes = me.getRenderTarget().dom.childNodes,
  822. targetChildCount = targetNodes.length,
  823. i, j, targetChildNode, item;
  824. // Calculate the number of DOM nodes in our target that are not our docked items
  825. for (i = 0, j = 0; i &lt; targetChildCount; i++) {
  826. targetChildNode = targetNodes[i];
  827. if (Ext.fly(targetChildNode).hasCls('x-resizable-handle')) {
  828. break;
  829. }
  830. for (j = 0; j &lt; dockedItemCount; j++) {
  831. item = items[j];
  832. if (item.rendered &amp;&amp; item.el.dom === targetChildNode) {
  833. break;
  834. }
  835. }
  836. // Walked off the end of the docked items without matching the found child node;
  837. // Then it's a static node.
  838. if (j === dockedItemCount) {
  839. staticNodeCount++;
  840. }
  841. }
  842. // Now we go through our docked items and render/move them
  843. for (; itemIndex &lt; dockedItemCount; itemIndex++, correctPosition++) {
  844. item = items[itemIndex];
  845. // If we're now at the first right/bottom docked item, we jump over the body element.
  846. //
  847. // TODO: This is affected if users provide custom weight values to their
  848. // docked items, which puts it out of (t,l,r,b) order. Avoiding a second
  849. // sort operation here, for now, in the name of performance. getDockedItems()
  850. // needs the sort operation not just for this layout-time rendering, but
  851. // also for getRefItems() to return a logical ordering (FocusManager, CQ, et al).
  852. if (itemIndex === correctPosition &amp;&amp; (item.dock === 'right' || item.dock === 'bottom')) {
  853. correctPosition += staticNodeCount;
  854. }
  855. // Same logic as Layout.renderItems()
  856. if (item &amp;&amp; !item.rendered) {
  857. me.renderItem(item, target, correctPosition);
  858. }
  859. else if (!me.isValidParent(item, target, correctPosition)) {
  860. me.moveItem(item, target, correctPosition);
  861. }
  862. }
  863. },
  864. undoLayout: function(ownerContext) {
  865. var me = this,
  866. owner = me.owner;
  867. // If we are collapsing...
  868. if (ownerContext.isCollapsingOrExpanding == 1) {
  869. // We do not want to see the re-expander header until the final collapse is complete
  870. if (owner.reExpander) {
  871. owner.reExpander.el.hide();
  872. }
  873. // Add the collapsed class now, so that collapsed CSS rules are applied before measurements are taken by the layout.
  874. owner.removeClsWithUI(owner.collapsedCls);
  875. ownerContext.undo(true);
  876. } else if (ownerContext.isCollapsingOrExpanding == 2) {
  877. // Remove the collapsed class now, before layout calculations are done.
  878. owner.addClsWithUI(owner.collapsedCls);
  879. ownerContext.bodyContext.undo();
  880. }
  881. },
  882. sizePolicy: {
  883. nostretch: {
  884. setsWidth: 0,
  885. setsHeight: 0
  886. },
  887. stretchH: {
  888. setsWidth: 1,
  889. setsHeight: 0
  890. },
  891. stretchV: {
  892. setsWidth: 0,
  893. setsHeight: 1
  894. },
  895. // Circular dependency with partial auto-sized panels:
  896. //
  897. // If we have an autoHeight docked item being stretched horizontally (top/bottom),
  898. // that stretching will determine its width and its width must be set before its
  899. // autoHeight can be determined. If that item is docked in an autoWidth panel, the
  900. // body will need its height set before it can determine its width, but the height
  901. // of the docked item is needed to subtract from the panel height in order to set
  902. // the body height.
  903. //
  904. // This same pattern occurs with autoHeight panels with autoWidth docked items on
  905. // left or right. If the panel is fully auto or fully fixed, these problems don't
  906. // come up because there is no dependency between the dimensions.
  907. //
  908. // Cutting the Gordian Knot: In these cases, we have to allow something to measure
  909. // itself without full context. This is OK as long as the managed dimension doesn't
  910. // effect the auto-dimension, which is often the case for things like toolbars. The
  911. // managed dimension only effects overflow handlers and such and does not change the
  912. // auto-dimension. To encourage the item to measure itself without waiting for the
  913. // managed dimension, we have to tell it that the layout will also be reading that
  914. // dimension. This is similar to how stretchmax works.
  915. autoStretchH: {
  916. readsWidth: 1,
  917. setsWidth: 1,
  918. setsHeight: 0
  919. },
  920. autoStretchV: {
  921. readsHeight: 1,
  922. setsWidth: 0,
  923. setsHeight: 1
  924. }
  925. },
  926. getItemSizePolicy: function (item) {
  927. var policy = this.sizePolicy,
  928. dock, vertical;
  929. if (item.stretch === false) {
  930. return policy.nostretch;
  931. }
  932. dock = item.dock;
  933. vertical = (dock == 'left' || dock == 'right');
  934. /*
  935. owner = this.owner;
  936. autoWidth = !owner.isFixedWidth();
  937. autoHeight = !owner.isFixedHeight();
  938. if (autoWidth !== autoHeight) { // if (partial auto)
  939. // see above...
  940. if (vertical) {
  941. if (autoHeight) {
  942. return policy.autoStretchV;
  943. }
  944. } else if (autoWidth) {
  945. return policy.autoStretchH;
  946. }
  947. }*/
  948. if (vertical) {
  949. return policy.stretchV;
  950. }
  951. return policy.stretchH;
  952. },
  953. <span id='Ext-layout-component-Dock-method-configureItem'> /**
  954. </span> * @protected
  955. * We are overriding the Ext.layout.Layout configureItem method to also add a class that
  956. * indicates the position of the docked item. We use the itemCls (x-docked) as a prefix.
  957. * An example of a class added to a dock: right item is x-docked-right
  958. * @param {Ext.Component} item The item we are configuring
  959. */
  960. configureItem : function(item, pos) {
  961. this.callParent(arguments);
  962. item.addCls(Ext.baseCSSPrefix + 'docked');
  963. item.addClsWithUI('docked-' + item.dock);
  964. },
  965. afterRemove : function(item) {
  966. this.callParent(arguments);
  967. if (this.itemCls) {
  968. item.el.removeCls(this.itemCls + '-' + item.dock);
  969. }
  970. var dom = item.el.dom;
  971. if (!item.destroying &amp;&amp; dom) {
  972. dom.parentNode.removeChild(dom);
  973. }
  974. this.childrenChanged = true;
  975. }
  976. });
  977. </pre>
  978. </body>
  979. </html>