Upgrade to ExtJS 4.0.0 - Released 04/26/2011
[extjs.git] / src / layout / component / Button.js
1 /**
2  * Component layout for buttons
3  * @class Ext.layout.component.Button
4  * @extends Ext.layout.component.Component
5  * @private
6  */
7 Ext.define('Ext.layout.component.Button', {
8
9     /* Begin Definitions */
10
11     alias: ['layout.button'],
12
13     extend: 'Ext.layout.component.Component',
14
15     /* End Definitions */
16
17     type: 'button',
18
19     cellClsRE: /-btn-(tl|br)\b/,
20     htmlRE: /<.*>/,
21
22     beforeLayout: function() {
23         return this.callParent(arguments) || this.lastText !== this.owner.text;
24     },
25
26     /**
27      * Set the dimensions of the inner &lt;button&gt; element to match the
28      * component dimensions.
29      */
30     onLayout: function(width, height) {
31         var me = this,
32             isNum = Ext.isNumber,
33             owner = me.owner,
34             ownerEl = owner.el,
35             btnEl = owner.btnEl,
36             btnInnerEl = owner.btnInnerEl,
37             minWidth = owner.minWidth,
38             maxWidth = owner.maxWidth,
39             ownerWidth, btnFrameWidth, metrics;
40
41         me.getTargetInfo();
42         me.callParent(arguments);
43
44         btnInnerEl.unclip();
45         me.setTargetSize(width, height);
46
47         if (!isNum(width)) {
48             // In IE7 strict mode button elements with width:auto get strange extra side margins within
49             // the wrapping table cell, but they go away if the width is explicitly set. So we measure
50             // the size of the text and set the width to match.
51             if (owner.text && Ext.isIE7 && Ext.isStrict && btnEl && btnEl.getWidth() > 20) {
52                 btnFrameWidth = me.btnFrameWidth;
53                 metrics = Ext.util.TextMetrics.measure(btnInnerEl, owner.text);
54                 ownerEl.setWidth(metrics.width + btnFrameWidth + me.adjWidth);
55                 btnEl.setWidth(metrics.width + btnFrameWidth);
56                 btnInnerEl.setWidth(metrics.width + btnFrameWidth);
57             } else {
58                 // Remove any previous fixed widths
59                 ownerEl.setWidth(null);
60                 btnEl.setWidth(null);
61                 btnInnerEl.setWidth(null);
62             }
63
64             // Handle maxWidth/minWidth config
65             if (minWidth || maxWidth) {
66                 ownerWidth = ownerEl.getWidth();
67                 if (minWidth && (ownerWidth < minWidth)) {
68                     me.setTargetSize(minWidth, height);
69                 }
70                 else if (maxWidth && (ownerWidth > maxWidth)) {
71                     btnInnerEl.clip();
72                     me.setTargetSize(maxWidth, height);
73                 }
74             }
75         }
76
77         this.lastText = owner.text;
78     },
79
80     setTargetSize: function(width, height) {
81         var me = this,
82             owner = me.owner,
83             isNum = Ext.isNumber,
84             btnInnerEl = owner.btnInnerEl,
85             btnWidth = (isNum(width) ? width - me.adjWidth : width),
86             btnHeight = (isNum(height) ? height - me.adjHeight : height),
87             btnFrameHeight = me.btnFrameHeight,
88             text = owner.getText(),
89             textHeight;
90
91         me.callParent(arguments);
92         me.setElementSize(owner.btnEl, btnWidth, btnHeight);
93         me.setElementSize(btnInnerEl, btnWidth, btnHeight);
94         if (isNum(btnHeight)) {
95             btnInnerEl.setStyle('line-height', btnHeight - btnFrameHeight + 'px');
96         }
97
98         // Button text may contain markup that would force it to wrap to more than one line (e.g. 'Button<br>Label').
99         // When this happens, we cannot use the line-height set above for vertical centering; we instead reset the
100         // line-height to normal, measure the rendered text height, and add padding-top to center the text block
101         // vertically within the button's height. This is more expensive than the basic line-height approach so
102         // we only do it if the text contains markup.
103         if (text && this.htmlRE.test(text)) {
104             btnInnerEl.setStyle('line-height', 'normal');
105             textHeight = Ext.util.TextMetrics.measure(btnInnerEl, text).height;
106             btnInnerEl.setStyle('padding-top', me.btnFrameTop + Math.max(btnInnerEl.getHeight() - btnFrameHeight - textHeight, 0) / 2 + 'px');
107             me.setElementSize(btnInnerEl, btnWidth, btnHeight);
108         }
109     },
110
111     getTargetInfo: function() {
112         var me = this,
113             owner = me.owner,
114             ownerEl = owner.el,
115             frameSize = me.frameSize,
116             frameBody = owner.frameBody,
117             btnWrap = owner.btnWrap,
118             innerEl = owner.btnInnerEl;
119
120         if (!('adjWidth' in me)) {
121             Ext.apply(me, {
122                 // Width adjustment must take into account the arrow area. The btnWrap is the <em> which has padding to accommodate the arrow.
123                 adjWidth: frameSize.left + frameSize.right + ownerEl.getBorderWidth('lr') + ownerEl.getPadding('lr') +
124                           btnWrap.getPadding('lr') + (frameBody ? frameBody.getFrameWidth('lr') : 0),
125                 adjHeight: frameSize.top + frameSize.bottom + ownerEl.getBorderWidth('tb') + ownerEl.getPadding('tb') +
126                            btnWrap.getPadding('tb') + (frameBody ? frameBody.getFrameWidth('tb') : 0),
127                 btnFrameWidth: innerEl.getFrameWidth('lr'),
128                 btnFrameHeight: innerEl.getFrameWidth('tb'),
129                 btnFrameTop: innerEl.getFrameWidth('t')
130             });
131         }
132
133         return me.callParent();
134     }
135 });