]>
git.proxmox.com Git - extjs.git/blob - extjs/classic/classic/src/layout/container/Fit.js
2 * This is a base class for layouts that contain a single item that automatically expands to fill the layout's
3 * container. This class is intended to be extended or created via the layout:'fit'
4 * {@link Ext.container.Container#layout} config, and should generally not need to be created directly via the new keyword.
6 * Fit layout does not have any direct config options (other than inherited ones). To fit a panel to a container using
7 * Fit layout, simply set `layout: 'fit'` on the container and add a single panel to it.
10 * Ext.create('Ext.panel.Panel', {
11 * title: 'Fit Layout',
16 * title: 'Inner Panel',
17 * html: 'This is the inner panel content',
21 * renderTo: Ext.getBody()
24 * If the container has multiple items, all of the items will all be equally sized. This is usually not
25 * desired, so to avoid this, place only a **single** item in the container. This sizing of all items
26 * can be used to provide a background {@link Ext.Img image} that is "behind" another item
27 * such as a {@link Ext.view.View dataview} if you also absolutely position the items.
29 Ext
.define('Ext.layout.container.Fit', {
31 /* Begin Definitions */
32 extend
: 'Ext.layout.container.Container',
33 alternateClassName
: 'Ext.layout.FitLayout',
40 * @inheritdoc Ext.layout.container.Container#cfg-itemCls
42 itemCls
: Ext
.baseCSSPrefix
+ 'fit-item',
48 0: { readsWidth
: 1, readsHeight
: 1, setsWidth
: 0, setsHeight
: 0 },
49 1: { readsWidth
: 0, readsHeight
: 1, setsWidth
: 1, setsHeight
: 0 },
50 2: { readsWidth
: 1, readsHeight
: 0, setsWidth
: 0, setsHeight
: 1 },
51 3: { readsWidth
: 0, readsHeight
: 0, setsWidth
: 1, setsHeight
: 1 }
54 getItemSizePolicy: function (item
, ownerSizeModel
) {
55 // this layout's sizePolicy is derived from its owner's sizeModel:
56 var sizeModel
= ownerSizeModel
|| this.owner
.getSizeModel(),
57 mode
= (sizeModel
.width
.shrinkWrap
? 0 : 1) | // jshint ignore:line
58 (sizeModel
.height
.shrinkWrap
? 0 : 2);
60 return this.sizePolicies
[mode
];
63 beginLayoutCycle: function (ownerContext
, firstCycle
) {
65 // determine these before the lastSizeModels get updated:
66 resetHeight
= me
.lastHeightModel
&& me
.lastHeightModel
.calculated
,
67 resetWidth
= me
.lastWidthModel
&& me
.lastWidthModel
.calculated
,
68 resetSizes
= resetWidth
|| resetHeight
,
69 maxChildMinHeight
= 0, maxChildMinWidth
= 0,
70 c
, childItems
, i
, item
, length
, margins
, minHeight
, minWidth
, style
, undef
;
72 me
.callParent(arguments
);
74 // Clear any dimensions which we set before calculation, in case the current
75 // settings affect the available size. This particularly effects self-sizing
76 // containers such as fields, in which the target element is naturally sized,
77 // and should not be stretched by a sized child item.
78 if (resetSizes
&& ownerContext
.targetContext
.el
.dom
.tagName
.toUpperCase() !== 'TD') {
79 resetSizes
= resetWidth
= resetHeight
= false;
82 childItems
= ownerContext
.childItems
;
83 length
= childItems
.length
;
85 for (i
= 0; i
< length
; ++i
) {
88 // On the firstCycle, we determine the max of the minWidth/Height of the items
89 // since these can cause the container to grow scrollbars despite our attempts
90 // to fit the child to the container.
93 minHeight
= c
.minHeight
;
94 minWidth
= c
.minWidth
;
96 if (minWidth
|| minHeight
) {
97 margins
= item
.marginInfo
|| item
.getMarginInfo();
98 // if the child item has undefined minWidth/Height, these will become
99 // NaN by adding the margins...
100 minHeight
+= margins
.height
;
101 minWidth
+= margins
.height
;
103 // if the child item has undefined minWidth/Height, these comparisons
104 // will evaluate to false... that is, "0 < NaN" == false...
105 if (maxChildMinHeight
< minHeight
) {
106 maxChildMinHeight
= minHeight
;
108 if (maxChildMinWidth
< minWidth
) {
109 maxChildMinWidth
= minWidth
;
115 style
= item
.el
.dom
.style
;
127 ownerContext
.maxChildMinHeight
= maxChildMinHeight
;
128 ownerContext
.maxChildMinWidth
= maxChildMinWidth
;
131 // Cache the overflowX/Y flags, but make them false in shrinkWrap mode (since we
132 // won't be triggering overflow in that case) and false if we have no minSize (so
133 // no child to trigger an overflow).
134 c
= ownerContext
.target
;
135 ownerContext
.overflowX
= (!ownerContext
.widthModel
.shrinkWrap
&&
136 ownerContext
.maxChildMinWidth
&&
137 c
.scrollFlags
.x
) || undef
;
139 ownerContext
.overflowY
= (!ownerContext
.heightModel
.shrinkWrap
&&
140 ownerContext
.maxChildMinHeight
&&
141 c
.scrollFlags
.y
) || undef
;
144 calculate: function (ownerContext
) {
146 childItems
= ownerContext
.childItems
,
147 length
= childItems
.length
,
148 containerSize
= me
.getContainerSize(ownerContext
),
151 ownerContext
: ownerContext
,
152 targetSize
: containerSize
154 shrinkWrapWidth
= ownerContext
.widthModel
.shrinkWrap
,
155 shrinkWrapHeight
= ownerContext
.heightModel
.shrinkWrap
,
156 overflowX
= ownerContext
.overflowX
,
157 overflowY
= ownerContext
.overflowY
,
158 scrollbars
, scrollbarSize
, padding
, i
, contentWidth
, contentHeight
;
160 ownerContext
.state
.info
= info
;
161 if (overflowX
|| overflowY
) {
162 // If we have children that have minHeight/Width, we may be forced to overflow
163 // and gain scrollbars. If so, we want to remove their space from the other
164 // axis so that we fit things inside the scrollbars rather than under them.
165 scrollbars
= me
.getScrollbarsNeeded(
166 overflowX
&& containerSize
.width
, overflowY
&& containerSize
.height
,
167 ownerContext
.maxChildMinWidth
, ownerContext
.maxChildMinHeight
);
170 scrollbarSize
= Ext
.getScrollbarSize();
171 if (scrollbars
& 1) { // jshint ignore:line
172 // if we need the hscrollbar, remove its height
173 containerSize
.height
-= scrollbarSize
.height
;
175 if (scrollbars
& 2) { // jshint ignore:line
176 // if we need the vscrollbar, remove its width
177 containerSize
.width
-= scrollbarSize
.width
;
182 // If length === 0, it means we either have no child items, or the children are hidden
184 // Size the child items to the container (if non-shrinkWrap):
185 for (i
= 0; i
< length
; ++i
) {
187 me
.fitItem(childItems
[i
], info
);
190 info
.contentWidth
= info
.contentHeight
= 0;
193 if (shrinkWrapHeight
|| shrinkWrapWidth
) {
194 padding
= ownerContext
.targetContext
.getPaddingInfo();
196 if (shrinkWrapWidth
) {
197 if (overflowY
&& !containerSize
.gotHeight
) {
198 // if we might overflow vertically and don't have the container height,
199 // we don't know if we will need a vscrollbar or not, so we must wait
200 // for that height so that we can determine the contentWidth...
203 contentWidth
= info
.contentWidth
+ padding
.width
;
204 // the scrollbar flag (if set) will indicate that an overflow exists on
205 // the horz(1) or vert(2) axis... if not set, then there could never be
207 if (scrollbars
& 2) { // jshint ignore:line
208 // if we need the vscrollbar, add its width
209 contentWidth
+= scrollbarSize
.width
;
211 if (!ownerContext
.setContentWidth(contentWidth
)) {
217 if (shrinkWrapHeight
) {
218 if (overflowX
&& !containerSize
.gotWidth
) {
219 // if we might overflow horizontally and don't have the container width,
220 // we don't know if we will need a hscrollbar or not, so we must wait
221 // for that width so that we can determine the contentHeight...
224 contentHeight
= info
.contentHeight
+ padding
.height
;
225 // the scrollbar flag (if set) will indicate that an overflow exists on
226 // the horz(1) or vert(2) axis... if not set, then there could never be
228 if (scrollbars
& 1) { // jshint ignore:line
229 // if we need the hscrollbar, add its height
230 contentHeight
+= scrollbarSize
.height
;
232 if (!ownerContext
.setContentHeight(contentHeight
)) {
240 fitItem: function (itemContext
, info
) {
243 if (itemContext
.invalid
) {
248 info
.margins
= itemContext
.getMarginInfo();
249 info
.needed
= info
.got
= 0;
251 me
.fitItemWidth(itemContext
, info
);
252 me
.fitItemHeight(itemContext
, info
);
254 // If not all required dimensions have been satisfied, we're not done.
255 if (info
.got
!== info
.needed
) {
260 fitItemWidth: function (itemContext
, info
) {
261 var contentWidth
, width
;
262 // Attempt to set only dimensions that are being controlled, not shrinkWrap dimensions
263 if (info
.ownerContext
.widthModel
.shrinkWrap
) {
264 // contentWidth must include the margins to be consistent with setItemWidth
265 width
= itemContext
.getProp('width') + info
.margins
.width
;
266 // because we add margins, width will be NaN or a number (not undefined)
268 contentWidth
= info
.contentWidth
;
269 if (contentWidth
=== undefined) {
270 info
.contentWidth
= width
;
272 info
.contentWidth
= Math
.max(contentWidth
, width
);
274 } else if (itemContext
.widthModel
.calculated
) {
276 if (info
.targetSize
.gotWidth
) {
278 this.setItemWidth(itemContext
, info
);
280 // Too early to position
285 this.positionItemX(itemContext
, info
);
288 fitItemHeight: function (itemContext
, info
) {
289 var contentHeight
, height
;
290 if (info
.ownerContext
.heightModel
.shrinkWrap
) {
291 // contentHeight must include the margins to be consistent with setItemHeight
292 height
= itemContext
.getProp('height') + info
.margins
.height
;
293 // because we add margins, height will be NaN or a number (not undefined)
295 contentHeight
= info
.contentHeight
;
296 if (contentHeight
=== undefined) {
297 info
.contentHeight
= height
;
299 info
.contentHeight
= Math
.max(contentHeight
, height
);
301 } else if (itemContext
.heightModel
.calculated
) {
303 if (info
.targetSize
.gotHeight
) {
305 this.setItemHeight(itemContext
, info
);
307 // Too early to position
312 this.positionItemY(itemContext
, info
);
315 positionItemX: function (itemContext
, info
) {
316 var margins
= info
.margins
;
318 // Adjust position to account for configured margins or if we have multiple items
319 // (all items should overlap):
320 if (info
.index
|| margins
.left
) {
321 itemContext
.setProp('x', margins
.left
);
324 if (margins
.width
&& info
.ownerContext
.widthModel
.shrinkWrap
) {
325 // Need the margins for shrink-wrapping but old IE sometimes collapses the left margin into the padding
326 itemContext
.setProp('margin-right', margins
.width
);
330 positionItemY: function (itemContext
, info
) {
331 var margins
= info
.margins
;
333 if (info
.index
|| margins
.top
) {
334 itemContext
.setProp('y', margins
.top
);
337 if (margins
.height
&& info
.ownerContext
.heightModel
.shrinkWrap
) {
338 // Need the margins for shrink-wrapping but old IE sometimes collapses the top margin into the padding
339 itemContext
.setProp('margin-bottom', margins
.height
);
343 setItemHeight: function (itemContext
, info
) {
344 itemContext
.setHeight(info
.targetSize
.height
- info
.margins
.height
);
347 setItemWidth: function (itemContext
, info
) {
348 itemContext
.setWidth(info
.targetSize
.width
- info
.margins
.width
);