]> git.proxmox.com Git - extjs.git/blame - extjs/modern/modern/src/Decorator.js
add extjs 6.0.1 sources
[extjs.git] / extjs / modern / modern / src / Decorator.js
CommitLineData
6527f429
DM
1/**\r
2 * @class Ext.Decorator\r
3 * @extends Ext.Component\r
4 *\r
5 * In a few words, a Decorator is a Component that wraps around another Component. A typical example of a Decorator is a\r
6 * {@link Ext.field.Field Field}. A form field is nothing more than a decorator around another component, and gives the\r
7 * component a label, as well as extra styling to make it look good in a form.\r
8 *\r
9 * A Decorator can be thought of as a lightweight Container that has only one child item, and no layout overhead.\r
10 * The look and feel of decorators can be styled purely in CSS.\r
11 *\r
12 * Another powerful feature that Decorator provides is config proxying. For example: all config items of a\r
13 * {@link Ext.slider.Slider Slider} also exist in a {@link Ext.field.Slider Slider Field} for API convenience.\r
14 * The {@link Ext.field.Slider Slider Field} simply proxies all corresponding getters and setters\r
15 * to the actual {@link Ext.slider.Slider Slider} instance. Writing out all the setters and getters to do that is a tedious task\r
16 * and a waste of code space. Instead, when you sub-class Ext.Decorator, all you need to do is to specify those config items\r
17 * that you want to proxy to the Component using a special 'proxyConfig' class property. Here's how it may look like\r
18 * in a Slider Field class:\r
19 *\r
20 * Ext.define('My.field.Slider', {\r
21 * extend: 'Ext.Decorator',\r
22 *\r
23 * config: {\r
24 * component: {\r
25 * xtype: 'slider'\r
26 * }\r
27 * },\r
28 *\r
29 * proxyConfig: {\r
30 * minValue: 0,\r
31 * maxValue: 100,\r
32 * increment: 1\r
33 * }\r
34 *\r
35 * // ...\r
36 * });\r
37 *\r
38 * Once `My.field.Slider` class is created, it will have all setters and getters methods for all items listed in `proxyConfig`\r
39 * automatically generated. These methods all proxy to the same method names that exist within the Component instance.\r
40 */\r
41Ext.define('Ext.Decorator', {\r
42 extend: 'Ext.Component',\r
43\r
44 isDecorator: true,\r
45\r
46 config: {\r
47 /**\r
48 * @cfg {Object} component The config object to factory the Component that this Decorator wraps around\r
49 */\r
50 component: {}\r
51 },\r
52\r
53 statics: {\r
54 generateProxySetter: function(name) {\r
55 return function(value) {\r
56 var component = this.getComponent();\r
57 component[name].call(component, value);\r
58\r
59 return this;\r
60 }\r
61 },\r
62 generateProxyGetter: function(name) {\r
63 return function() {\r
64 var component = this.getComponent();\r
65 return component[name].call(component);\r
66 }\r
67 }\r
68 },\r
69\r
70 onClassExtended: function(Class, members) {\r
71 if (!members.hasOwnProperty('proxyConfig')) {\r
72 return;\r
73 }\r
74\r
75 var ExtClass = Ext.Class,\r
76 proxyConfig = members.proxyConfig,\r
77 config = members.config;\r
78\r
79 members.config = (config) ? Ext.applyIf(config, proxyConfig) : proxyConfig;\r
80\r
81 var name, nameMap, setName, getName;\r
82\r
83 for (name in proxyConfig) {\r
84 if (proxyConfig.hasOwnProperty(name)) {\r
85 nameMap = Ext.Config.get(name).names;\r
86 setName = nameMap.set;\r
87 getName = nameMap.get;\r
88\r
89 members[setName] = this.generateProxySetter(setName);\r
90 members[getName] = this.generateProxyGetter(getName);\r
91 }\r
92 }\r
93 },\r
94\r
95 /**\r
96 * @private\r
97 */\r
98 applyComponent: function(config) {\r
99 return Ext.factory(config, Ext.Component);\r
100 },\r
101\r
102 /**\r
103 * @private\r
104 */\r
105 updateComponent: function(newComponent, oldComponent) {\r
106 var me = this;\r
107\r
108 if (oldComponent) {\r
109 if (me.isRendered() && oldComponent.setRendered(false)) {\r
110 oldComponent.fireEventedAction('renderedchange', [me, oldComponent, false],\r
111 me.doUnsetComponent, me, false);\r
112 } else {\r
113 me.doUnsetComponent(oldComponent);\r
114 }\r
115 }\r
116\r
117 if (newComponent) {\r
118 if (me.isRendered() && newComponent.setRendered(true)) {\r
119 newComponent.fireEventedAction('renderedchange', [me, newComponent, true],\r
120 me.doSetComponent, me, false);\r
121 } else {\r
122 me.doSetComponent(newComponent);\r
123 }\r
124 }\r
125 },\r
126\r
127 /**\r
128 * @private\r
129 */\r
130 doUnsetComponent: function(component) {\r
131 var dom = component.renderElement.dom;\r
132 if (dom) {\r
133 component.setLayoutSizeFlags(0);\r
134 this.innerElement.dom.removeChild(dom);\r
135 }\r
136 },\r
137\r
138 /**\r
139 * @private\r
140 */\r
141 doSetComponent: function(component) {\r
142 var dom = component.renderElement.dom;\r
143 if (dom) {\r
144 component.setLayoutSizeFlags(this.getSizeFlags());\r
145 this.innerElement.dom.appendChild(dom);\r
146 }\r
147 },\r
148\r
149 /**\r
150 * @private\r
151 */\r
152 setRendered: function(rendered) {\r
153 var component;\r
154\r
155 if (this.callParent(arguments)) {\r
156 component = this.getComponent();\r
157\r
158 if (component) {\r
159 component.setRendered(rendered);\r
160 }\r
161\r
162 return true;\r
163 }\r
164\r
165 return false;\r
166 },\r
167\r
168 /**\r
169 * @private\r
170 */\r
171 setDisabled: function(disabled) {\r
172 // @noOptimize.callParent\r
173 this.callParent(arguments);\r
174 // sencha cmd cannot tell that our superclass does indeed have a setDisabled\r
175 // method because it is an auto-generated config setter, so it complains that\r
176 // callParent has no target unless we tell it not to, hence the noOptimize comment\r
177 // above.\r
178 this.getComponent().setDisabled(disabled);\r
179 },\r
180\r
181 destroy: function() {\r
182 Ext.destroy(this.getComponent());\r
183 this.callParent();\r
184 }\r
185});\r