]> git.proxmox.com Git - extjs.git/blame - extjs/modern/modern/src/Panel.js
add extjs 6.0.1 sources
[extjs.git] / extjs / modern / modern / src / Panel.js
CommitLineData
6527f429
DM
1/**\r
2 * Panels are most useful as Overlays - containers that float over your application. They contain extra styling such\r
3 * that when you {@link #showBy} another component, the container will appear in a rounded black box with a 'tip'\r
4 * pointing to a reference component.\r
5 *\r
6 * If you don't need this extra functionality, you should use {@link Ext.Container} instead. See the\r
7 * [Overlays example](#!/example/overlays) for more use cases.\r
8 *\r
9 * @example miniphone preview\r
10 *\r
11 * var button = Ext.create('Ext.Button', {\r
12 * text: 'Button',\r
13 * id: 'rightButton'\r
14 * });\r
15 *\r
16 * Ext.create('Ext.Container', {\r
17 * fullscreen: true,\r
18 * items: [\r
19 * {\r
20 * docked: 'top',\r
21 * xtype: 'titlebar',\r
22 * items: [\r
23 * button\r
24 * ]\r
25 * }\r
26 * ]\r
27 * });\r
28 *\r
29 * Ext.create('Ext.Panel', {\r
30 * html: 'Floating Panel',\r
31 * left: 0,\r
32 * padding: 10\r
33 * }).showBy(button);\r
34 *\r
35 */\r
36Ext.define('Ext.Panel', {\r
37 extend: 'Ext.Container',\r
38 xtype: 'panel',\r
39\r
40 requires: [\r
41 'Ext.util.LineSegment'\r
42 ],\r
43\r
44 alternateClassName: 'Ext.panel.Panel',\r
45\r
46 defaultBindProperty: 'title',\r
47\r
48 isPanel: true,\r
49\r
50 config: {\r
51 baseCls: Ext.baseCSSPrefix + 'panel',\r
52\r
53 /**\r
54 * @cfg border\r
55 * @inheritdoc\r
56 */\r
57 border: false,\r
58\r
59 /**\r
60 * @cfg {Number/Boolean/String} bodyPadding\r
61 * A shortcut for setting a padding style on the body element. The value can either be\r
62 * a number to be applied to all sides, or a normal CSS string describing padding.\r
63 */\r
64 bodyPadding: null,\r
65\r
66 /**\r
67 * @cfg {Boolean} bodyBorder\r
68 * - `true` to enable the border around the panel body (as defined by the theme)\r
69 * Note that even when enabled, the bodyBorder is only visible when there are docked\r
70 * items around the edges of the panel. Where the bodyBorder touches the panel's outer\r
71 * border it is automatically collapsed into a single border.\r
72 *\r
73 * - `false` to disable the body border\r
74 *\r
75 * - `null` - use the value of {@link #border} as the value for bodyBorder\r
76 */\r
77 bodyBorder: null,\r
78\r
79 header: null,\r
80\r
81 icon: null,\r
82\r
83 iconCls: null,\r
84\r
85 title: null,\r
86\r
87 tools: null\r
88 },\r
89\r
90 manageBorders: true,\r
91\r
92 getElementConfig: function() {\r
93 return {\r
94 reference: 'element',\r
95 classList: ['x-container', 'x-unsized'],\r
96 children: [\r
97 {\r
98 reference: 'innerElement',\r
99 className: 'x-inner'\r
100 },\r
101 {\r
102 reference: 'tipElement',\r
103 className: 'x-anchor',\r
104 hidden: true\r
105 }\r
106 ]\r
107 };\r
108 },\r
109\r
110 /**\r
111 * Adds a CSS class to the body element. If not rendered, the class will\r
112 * be added when the panel is rendered.\r
113 * @param {String} cls The class to add\r
114 * @return {Ext.panel.Panel} this\r
115 */\r
116 addBodyCls: function(cls) {\r
117 this.innerElement.addCls(cls);\r
118 return this;\r
119 },\r
120\r
121 /**\r
122 * Removes a CSS class from the body element.\r
123 * @param {String} cls The class to remove\r
124 * @return {Ext.panel.Panel} this\r
125 */\r
126 removeBodyCls: function(cls) {\r
127 this.innerElement.removeCls(cls);\r
128 return this;\r
129 },\r
130\r
131 applyBodyPadding: function(bodyPadding) {\r
132 if (bodyPadding === true) {\r
133 bodyPadding = 5;\r
134 }\r
135\r
136 if (bodyPadding) {\r
137 bodyPadding = Ext.dom.Element.unitizeBox(bodyPadding);\r
138 }\r
139\r
140 return bodyPadding;\r
141 },\r
142\r
143 addTool: function (tool) {\r
144 var header = this.ensureHeader(), // creates if header !== false\r
145 items;\r
146\r
147 if (header) {\r
148 items = header.createTools(Ext.Array.from(tool), this);\r
149\r
150 if (items && items.length) {\r
151 items = header.add(items);\r
152 }\r
153 }\r
154\r
155 return items;\r
156 },\r
157\r
158 applyHeader: function (newHeader, oldHeader) {\r
159 var me = this,\r
160 header = oldHeader;\r
161\r
162 if (newHeader === false) {\r
163 if (header) {\r
164 me.remove(header);\r
165 header = null;\r
166 }\r
167 } else if (newHeader) {\r
168 if (header) {\r
169 if (newHeader !== true) {\r
170 header.setConfig(newHeader);\r
171 }\r
172 } else {\r
173 // add() will ensure we sort the header to the front by its "weight"\r
174\r
175 header = me.add(me.createHeader(newHeader));\r
176 }\r
177 }\r
178\r
179 return header || null;\r
180 },\r
181\r
182 applyTools: function (tools) {\r
183 var header = this.ensureHeader(), // creates if header !== false\r
184 items;\r
185\r
186 if (header) {\r
187 // Remove all tools (since we are the impl of a setTools([...]) call)\r
188 header.clearTools();\r
189\r
190 items = header.createTools(tools, this);\r
191\r
192 if (items && items.length) {\r
193 header.add(items);\r
194 }\r
195 }\r
196\r
197 // we don't return anything since the tools are "stored" on the Header\r
198 },\r
199\r
200 createHeader: function (config) {\r
201 var me = this,\r
202 ret = {\r
203 xtype: 'panelheader',\r
204 docked: 'top',\r
205 ui: me.getUi()\r
206 },\r
207 icon, title;\r
208\r
209 if (config && config !== true) {\r
210 Ext.merge(ret, config);\r
211 }\r
212\r
213 if (me.initialized) {\r
214 // Only attempt to configure title if we are not currently initializing.\r
215 // During initialization the updater for title will run if present and apply\r
216 // it to the header so there is no work to be done here.\r
217 title = me.getTitle();\r
218\r
219 if (title != null) {\r
220 if (typeof title === 'string') {\r
221 title = {\r
222 text: title\r
223 };\r
224 }\r
225\r
226 Ext.merge(ret, {\r
227 title: title\r
228 });\r
229 }\r
230\r
231 icon = me.getIconCls();\r
232 if (icon != null) {\r
233 ret.iconCls = icon;\r
234 } else {\r
235 icon = me.getIcon();\r
236 if (icon != null) {\r
237 ret.icon = icon;\r
238 }\r
239 }\r
240 }\r
241\r
242 return ret;\r
243 },\r
244\r
245 updateBorder: function(border, oldBorder) {\r
246 this.callParent([ border, oldBorder ]);\r
247\r
248 if (this.getBodyBorder() === null) {\r
249 this.setBodyBorderEnabled(border !== false);\r
250 }\r
251 },\r
252\r
253 updateBodyPadding: function(newBodyPadding) {\r
254 this.innerElement.setStyle('padding', newBodyPadding);\r
255 },\r
256\r
257 updateBodyBorder: function(bodyBorder) {\r
258 var border = (bodyBorder === null) ? this.getBorder() : bodyBorder;\r
259\r
260 this.setBodyBorderEnabled(bodyBorder !== false);\r
261 },\r
262\r
263 updateIcon: function (icon) {\r
264 var header = this.ensureHeader(); // creates if header !== false\r
265\r
266 if (header) {\r
267 header.setIcon(icon);\r
268 }\r
269 },\r
270\r
271 updateIconCls: function (icon) {\r
272 var header = this.ensureHeader(); // creates if header !== false\r
273\r
274 if (header) {\r
275 header.setIconCls(icon);\r
276 }\r
277 },\r
278\r
279 updateTitle: function (title) {\r
280 var header = this.ensureHeader(); // creates if header !== false\r
281\r
282 if (header) {\r
283 header.setTitle(title);\r
284 }\r
285 },\r
286\r
287 updateUi: function(ui, oldUi) {\r
288 var me = this,\r
289 suffix = 'x-panel-inner-',\r
290 innerElement = me.innerElement,\r
291 // Let the header initter get the ui since ui is a cached config and\r
292 // should not pull in non-cached cfgs at this early stage\r
293 header = !me.isConfiguring && me.ensureHeader();\r
294\r
295 if (oldUi) {\r
296 innerElement.removeCls(suffix + oldUi);\r
297 }\r
298\r
299 if (ui) {\r
300 innerElement.addCls(suffix + ui);\r
301 }\r
302\r
303 if (header) {\r
304 me.getTitle();\r
305 header.setUi(ui);\r
306 }\r
307\r
308 me.callParent([ui, oldUi]);\r
309 },\r
310\r
311 alignTo: function(component, alignment) {\r
312 var alignmentInfo = this.getAlignmentInfo(component, alignment);\r
313 if(alignmentInfo.isAligned) return;\r
314 var tipElement = this.tipElement;\r
315\r
316 tipElement.hide();\r
317\r
318 if (this.currentTipPosition) {\r
319 tipElement.removeCls('x-anchor-' + this.currentTipPosition);\r
320 }\r
321\r
322 this.callParent(arguments);\r
323\r
324 var LineSegment = Ext.util.LineSegment,\r
325 alignToElement = component.isComponent ? component.renderElement : component,\r
326 element = this.renderElement,\r
327 alignToBox = alignToElement.getBox(),\r
328 box = element.getBox(),\r
329 left = box.left,\r
330 top = box.top,\r
331 right = box.right,\r
332 bottom = box.bottom,\r
333 centerX = left + (box.width / 2),\r
334 centerY = top + (box.height / 2),\r
335 leftTopPoint = { x: left, y: top },\r
336 rightTopPoint = { x: right, y: top },\r
337 leftBottomPoint = { x: left, y: bottom },\r
338 rightBottomPoint = { x: right, y: bottom },\r
339 boxCenterPoint = { x: centerX, y: centerY },\r
340 alignToCenterX = alignToBox.left + (alignToBox.width / 2),\r
341 alignToCenterY = alignToBox.top + (alignToBox.height / 2),\r
342 alignToBoxCenterPoint = { x: alignToCenterX, y: alignToCenterY },\r
343 centerLineSegment = new LineSegment(boxCenterPoint, alignToBoxCenterPoint),\r
344 offsetLeft = 0,\r
345 offsetTop = 0,\r
346 tipSize, tipWidth, tipHeight, tipPosition, tipX, tipY;\r
347\r
348 tipElement.setVisibility(false);\r
349 tipElement.show();\r
350 tipSize = tipElement.getSize();\r
351 tipWidth = tipSize.width;\r
352 tipHeight = tipSize.height;\r
353\r
354 if (centerLineSegment.intersects(new LineSegment(leftTopPoint, rightTopPoint))) {\r
355 tipX = Math.min(Math.max(alignToCenterX, left + tipWidth), right - (tipWidth));\r
356 tipY = top;\r
357 offsetTop = tipHeight + 10;\r
358 tipPosition = 'top';\r
359 }\r
360 else if (centerLineSegment.intersects(new LineSegment(leftTopPoint, leftBottomPoint))) {\r
361 tipX = left;\r
362 tipY = Math.min(Math.max(alignToCenterY + (tipWidth / 2), tipWidth * 1.6), bottom - (tipWidth / 2.2));\r
363 offsetLeft = tipHeight + 10;\r
364 tipPosition = 'left';\r
365 }\r
366 else if (centerLineSegment.intersects(new LineSegment(leftBottomPoint, rightBottomPoint))) {\r
367 tipX = Math.min(Math.max(alignToCenterX, left + tipWidth), right - tipWidth);\r
368 tipY = bottom;\r
369 offsetTop = -tipHeight - 10;\r
370 tipPosition = 'bottom';\r
371 }\r
372 else if (centerLineSegment.intersects(new LineSegment(rightTopPoint, rightBottomPoint))) {\r
373 tipX = right;\r
374 tipY = Math.max(Math.min(alignToCenterY - tipHeight, bottom - tipWidth * 1.3), tipWidth / 2);\r
375 offsetLeft = -tipHeight - 10;\r
376 tipPosition = 'right';\r
377 }\r
378\r
379 if (tipX || tipY) {\r
380 this.currentTipPosition = tipPosition;\r
381 tipElement.addCls('x-anchor-' + tipPosition);\r
382 tipElement.setLeft(tipX - left);\r
383 tipElement.setTop(tipY - top);\r
384 tipElement.setVisibility(true);\r
385\r
386 this.setLeft(this.getLeft() + offsetLeft);\r
387 this.setTop(this.getTop() + offsetTop);\r
388 }\r
389 },\r
390\r
391 privates: {\r
392 ensureHeader: function () {\r
393 var me = this,\r
394 header;\r
395\r
396 me.getViewModel();\r
397 me.getItems();\r
398\r
399 header = me.getHeader();\r
400\r
401 if (!header && header !== false) {\r
402 me.setHeader(true);\r
403 header = me.getHeader();\r
404 }\r
405\r
406 return header;\r
407 },\r
408\r
409 setBodyBorderEnabled: function(enabled) {\r
410 this.innerElement.setStyle('border-width', enabled ? '' : '0');\r
411 }\r
412 }\r
413});\r