Merge pull request #5668 from kumpera/wasm-work-p4
[mono.git] / mcs / class / System.Drawing / System.Drawing.Design / ToolboxItem.cs
1 //\r
2 // System.Drawing.Design.ToolboxItem.cs\r
3 //\r
4 // Authors:\r
5 //   Alejandro Sánchez Acosta\r
6 //   Andreas Nahr (ClassDevelopment@A-SoftTech.com)\r
7 //   Jordi Mas i Hernandez, jordimash@gmail.com\r
8 //   Sebastien Pouliot  <sebastien@ximian.com>\r
9 //\r
10 // (C) Alejandro Sánchez Acosta\r
11 // (C) 2003 Andreas Nahr\r
12 // Copyright (C) 2004-2006 Novell, Inc (http://www.novell.com)\r
13 //\r
14 // Permission is hereby granted, free of charge, to any person obtaining\r
15 // a copy of this software and associated documentation files (the\r
16 // "Software"), to deal in the Software without restriction, including\r
17 // without limitation the rights to use, copy, modify, merge, publish,\r
18 // distribute, sublicense, and/or sell copies of the Software, and to\r
19 // permit persons to whom the Software is furnished to do so, subject to\r
20 // the following conditions:\r
21 // \r
22 // The above copyright notice and this permission notice shall be\r
23 // included in all copies or substantial portions of the Software.\r
24 // \r
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
26 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
27 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
28 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\r
29 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\r
30 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\r
31 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
32 //\r
33 \r
34 using System.Collections;\r
35 using System.ComponentModel;\r
36 using System.ComponentModel.Design;\r
37 using System.Reflection;\r
38 using System.Runtime.Serialization;\r
39 using System.Security.Permissions;\r
40 \r
41 namespace System.Drawing.Design \r
42 {\r
43         [Serializable]\r
44         [PermissionSet (SecurityAction.LinkDemand, Unrestricted = true)]\r
45         [PermissionSet (SecurityAction.InheritanceDemand, Unrestricted = true)]\r
46         [MonoTODO ("Implementation is incomplete.")]\r
47         public class ToolboxItem : ISerializable {\r
48 \r
49                 private bool locked = false;\r
50                 private Hashtable properties = new Hashtable ();\r
51                 \r
52                 public ToolboxItem ()\r
53                 {\r
54                 }\r
55 \r
56                 public ToolboxItem (Type toolType)\r
57                 {\r
58                         Initialize (toolType);\r
59                 }\r
60 \r
61                 public AssemblyName AssemblyName {\r
62                         get { return (AssemblyName) properties["AssemblyName"]; }\r
63                         set { SetValue ("AssemblyName", value); }\r
64                 }\r
65 \r
66                 public Bitmap Bitmap {\r
67                         get { return (Bitmap) properties["Bitmap"]; }\r
68                         set { SetValue ("Bitmap", value); }\r
69                 }\r
70 \r
71                 public string DisplayName {\r
72                         get { return GetValue ("DisplayName"); }\r
73                         set { SetValue ("DisplayName", value); }\r
74                 }\r
75 \r
76                 public ICollection Filter {\r
77                         get {\r
78                                 ICollection filter = (ICollection) properties["Filter"];\r
79                                 if (filter == null)\r
80                                         filter = new ToolboxItemFilterAttribute[0];\r
81                                 return filter;\r
82                         }\r
83                         set { SetValue ("Filter", value); }\r
84                 }\r
85                 public virtual bool Locked {\r
86                         get { return locked; }\r
87                 }\r
88 \r
89                 public string TypeName {\r
90                         get { return GetValue ("TypeName"); }\r
91                         set { SetValue ("TypeName", value); }\r
92                 }\r
93                 public string Company {\r
94                         get { return (string) properties["Company"]; }\r
95                         set { SetValue ("Company", value); }\r
96                 }\r
97 \r
98                 public virtual string ComponentType {\r
99                         get { return ".NET Component"; }\r
100                 }\r
101 \r
102                 public AssemblyName[] DependentAssemblies {\r
103                         get { return (AssemblyName[]) properties["DependentAssemblies"]; }\r
104                         set {\r
105                                 AssemblyName[] names = new AssemblyName [value.Length];\r
106                                 for (int i=0; i < names.Length; i++)\r
107                                         names [i] = value [i];\r
108                                 SetValue ("DependentAssemblies", names);\r
109                         }\r
110                 }\r
111 \r
112                 public string Description {\r
113                         get { return (string) properties["Description"]; }\r
114                         set { SetValue ("Description", value); }\r
115                 }\r
116 \r
117                 public bool IsTransient {                       \r
118                         get {\r
119                                 object o = properties ["IsTransient"];\r
120                                 return (o == null) ? false : (bool) o;\r
121                         }\r
122                         set { SetValue ("IsTransient", value); }\r
123                 }\r
124 \r
125                 public IDictionary Properties {\r
126                          get { return properties; }\r
127                 }\r
128 \r
129                 public virtual string Version { \r
130                         get { return string.Empty; }\r
131                 }                               \r
132 \r
133                 protected void CheckUnlocked ()\r
134                 {\r
135                         if (locked)\r
136                                 throw new InvalidOperationException ("The ToolboxItem is locked");\r
137                 }\r
138 \r
139                 public IComponent[] CreateComponents () \r
140                 {\r
141                         return CreateComponents (null);\r
142                 }\r
143 \r
144                 public IComponent[] CreateComponents (IDesignerHost host)\r
145                 {\r
146                         OnComponentsCreating (new ToolboxComponentsCreatingEventArgs (host));\r
147                         IComponent[] Comp = CreateComponentsCore (host);\r
148                         OnComponentsCreated (new ToolboxComponentsCreatedEventArgs (Comp));\r
149                         return Comp;\r
150                 }\r
151 \r
152                 // FIXME - get error handling logic correct\r
153                 protected virtual IComponent[] CreateComponentsCore (IDesignerHost host)\r
154                 {\r
155                         if (host == null)\r
156                                 throw new ArgumentNullException("host");\r
157                         \r
158                         IComponent[] components;\r
159                         Type type = GetType(host, AssemblyName, TypeName, true);\r
160                         if (type == null)\r
161                                 components = new IComponent[] { };\r
162                         else\r
163                                 components = new IComponent[] { host.CreateComponent(type) };\r
164 \r
165                         return components;\r
166                 }\r
167 \r
168                 protected virtual IComponent[] CreateComponentsCore (IDesignerHost host, IDictionary defaultValues)\r
169                 {\r
170                         IComponent[] components = CreateComponentsCore (host);\r
171                         foreach (Component c in components) {\r
172                                 IComponentInitializer initializer = host.GetDesigner (c) as IComponentInitializer;\r
173                                 initializer.InitializeNewComponent (defaultValues);\r
174                         }\r
175                         return components;\r
176                 } \r
177 \r
178                 public IComponent[] CreateComponents (IDesignerHost host, IDictionary defaultValues)\r
179                 {\r
180                         OnComponentsCreating (new ToolboxComponentsCreatingEventArgs (host));\r
181                         IComponent[] components = CreateComponentsCore (host,  defaultValues);\r
182                         OnComponentsCreated (new ToolboxComponentsCreatedEventArgs (components));\r
183 \r
184                         return components;\r
185                 } \r
186 \r
187                 protected virtual object FilterPropertyValue (string propertyName, object value)\r
188                 {\r
189                         switch (propertyName) {\r
190                         case "AssemblyName":\r
191                                 return (value == null) ? null : (value as ICloneable).Clone ();\r
192                         case "DisplayName":\r
193                         case "TypeName":\r
194                                 return (value == null) ? String.Empty : value;\r
195                         case "Filter":\r
196                                 return (value == null) ? new ToolboxItemFilterAttribute [0] : value;\r
197                         default:\r
198                                 return value;\r
199                         }\r
200                 }\r
201 \r
202                 protected virtual void Deserialize (SerializationInfo info, StreamingContext context)\r
203                 {                       \r
204                         AssemblyName = (AssemblyName)info.GetValue ("AssemblyName", typeof (AssemblyName));\r
205                         Bitmap = (Bitmap)info.GetValue ("Bitmap", typeof (Bitmap));\r
206                         Filter = (ICollection)info.GetValue ("Filter", typeof (ICollection));\r
207                         DisplayName = info.GetString ("DisplayName");\r
208                         locked = info.GetBoolean ("Locked");\r
209                         TypeName = info.GetString ("TypeName");\r
210                 }\r
211 \r
212                 // FIXME: too harsh??\r
213                 public override bool Equals (object obj)\r
214                 {\r
215                         ToolboxItem ti = (obj as ToolboxItem);\r
216                         if (ti == null)\r
217                                 return false;\r
218                         if (obj == this)\r
219                                 return true;\r
220                         return (ti.AssemblyName.Equals (AssemblyName) &&\r
221                                 ti.Locked.Equals (locked) &&\r
222                                 ti.TypeName.Equals (TypeName) &&\r
223                                 ti.DisplayName.Equals (DisplayName) &&\r
224                                 ti.Bitmap.Equals (Bitmap));\r
225                 }\r
226                 \r
227                 public override int GetHashCode ()\r
228                 {\r
229                         // FIXME: other algorithm?\r
230                         return string.Concat (TypeName, DisplayName).GetHashCode ();\r
231                 }\r
232 \r
233                 public Type GetType (IDesignerHost host)\r
234                 {\r
235                         return GetType (host, this.AssemblyName,  this.TypeName,  false);\r
236                 }\r
237 \r
238                 protected virtual Type GetType (IDesignerHost host, AssemblyName assemblyName, string typeName, bool reference)\r
239                 {\r
240                         if (typeName == null)\r
241                                 throw new ArgumentNullException ("typeName");\r
242 \r
243                         if (host == null)\r
244                                 return null;\r
245 \r
246                         //get ITypeResolutionService from host, as we have no other IServiceProvider here\r
247                         ITypeResolutionService typeRes = host.GetService (typeof (ITypeResolutionService)) as ITypeResolutionService;\r
248                         Type type = null;\r
249                         if (typeRes != null) {\r
250                                 //TODO: Using Assembly loader to throw errors. Silent fail and return null?\r
251                                 typeRes.GetAssembly (assemblyName, true);\r
252                                 if (reference)\r
253                                         typeRes.ReferenceAssembly (assemblyName);\r
254                                 type = typeRes.GetType (typeName, true);\r
255                         } else {\r
256                                 Assembly assembly = Assembly.Load (assemblyName);\r
257                                 if (assembly != null)\r
258                                         type = assembly.GetType (typeName);\r
259                         }\r
260                         return type;\r
261                 }\r
262 \r
263                 // FIXME - Should we be returning empty bitmap, or null?\r
264                 public virtual void Initialize (Type type) \r
265                 {\r
266                         CheckUnlocked ();\r
267                         if (type == null)\r
268                                 return;\r
269 \r
270                         AssemblyName = type.Assembly.GetName();\r
271                         DisplayName = type.Name;\r
272                         TypeName = type.FullName;\r
273                         \r
274                         // seems to be a right place to create the bitmap\r
275                         System.Drawing.Image image = null;\r
276                         foreach (object attribute in type.GetCustomAttributes(true)) {\r
277                                 ToolboxBitmapAttribute tba = attribute as ToolboxBitmapAttribute;\r
278                                 if (tba != null) {\r
279                                         image = tba.GetImage (type);\r
280                                         break;\r
281                                 }\r
282                         }\r
283                         //fallback: check for image even if not attribute\r
284                         if (image == null)\r
285                                 image = ToolboxBitmapAttribute.GetImageFromResource (type, null, false);\r
286                         \r
287                         if (image != null) {\r
288                                 Bitmap = (image as Bitmap);\r
289                                 if (Bitmap == null)\r
290                                         Bitmap = new Bitmap (image);\r
291                         }\r
292 \r
293                         Filter = type.GetCustomAttributes (typeof (ToolboxItemFilterAttribute), true);\r
294                 }\r
295                         \r
296                 void ISerializable.GetObjectData (SerializationInfo info, StreamingContext context)\r
297                 {\r
298                         Serialize (info, context);\r
299                 }\r
300 \r
301                 public virtual void Lock () \r
302                 {\r
303                         locked = true;\r
304                 }\r
305 \r
306                 protected virtual void OnComponentsCreated (ToolboxComponentsCreatedEventArgs args)\r
307                 {\r
308                         if (ComponentsCreated != null)\r
309                                 this.ComponentsCreated (this, args);\r
310                 }\r
311 \r
312                 protected virtual void OnComponentsCreating (ToolboxComponentsCreatingEventArgs args)\r
313                 {\r
314                         if (ComponentsCreating != null)\r
315                                 this.ComponentsCreating (this, args);\r
316                 }\r
317 \r
318                 protected virtual void Serialize (SerializationInfo info, StreamingContext context)\r
319                 {\r
320                         info.AddValue ("AssemblyName", AssemblyName);\r
321                         info.AddValue ("Bitmap", Bitmap);\r
322                         info.AddValue ("Filter", Filter);\r
323                         info.AddValue ("DisplayName", DisplayName);\r
324                         info.AddValue ("Locked", locked);\r
325                         info.AddValue ("TypeName", TypeName);\r
326                 }\r
327 \r
328                 public override string ToString()\r
329                 {\r
330                         return DisplayName;\r
331                 }\r
332 \r
333                 protected void ValidatePropertyType (string propertyName, object value, Type expectedType, bool allowNull)\r
334                 {\r
335                         if (!allowNull && (value == null))\r
336                                 throw new ArgumentNullException ("value");\r
337 \r
338                         if ((value != null) && !expectedType.Equals (value.GetType ())) {\r
339                                 string msg = Locale.GetText ("Type mismatch between value ({0}) and expected type ({1}).",\r
340                                         value.GetType (), expectedType);\r
341                                 throw new ArgumentException (msg, "value");\r
342                         }\r
343                 }\r
344 \r
345                 protected virtual object ValidatePropertyValue (string propertyName, object value)\r
346                 {\r
347                         switch (propertyName) {\r
348                         case "AssemblyName":\r
349                                 ValidatePropertyType (propertyName, value, typeof (AssemblyName), true);\r
350                                 break;\r
351                         case "Bitmap":\r
352                                 ValidatePropertyType (propertyName, value, typeof (Bitmap), true);\r
353                                 break;\r
354                         case "Company":\r
355                         case "Description":\r
356                         case "DisplayName":\r
357                         case "TypeName":\r
358                                 ValidatePropertyType (propertyName, value, typeof (string), true);\r
359                                 if (value == null)\r
360                                         value = String.Empty;\r
361                                 break;\r
362                         case "IsTransient":\r
363                                 ValidatePropertyType (propertyName, value, typeof (bool), false);\r
364                                 break;\r
365                         case "Filter":\r
366                                 ValidatePropertyType (propertyName, value, typeof (ToolboxItemFilterAttribute[]), true);\r
367                                 if (value == null)\r
368                                         value = new ToolboxItemFilterAttribute [0];\r
369                                 break;\r
370                         case "DependentAssemblies":\r
371                                 ValidatePropertyType (propertyName, value, typeof (AssemblyName[]), true);\r
372                                 break;\r
373                         default:\r
374                                 break;\r
375                         }\r
376                         return value;\r
377                 }\r
378 \r
379                 private void SetValue (string propertyName, object value)\r
380                 {\r
381                         CheckUnlocked ();\r
382                         properties [propertyName] = ValidatePropertyValue (propertyName, value);\r
383                 }\r
384                 private string GetValue (string propertyName)\r
385                 {\r
386                         string s = (string) properties [propertyName];\r
387                         return (s == null) ? String.Empty : s;\r
388                 }\r
389 \r
390                 public event ToolboxComponentsCreatedEventHandler ComponentsCreated;\r
391 \r
392                 public event ToolboxComponentsCreatingEventHandler ComponentsCreating;\r
393         }\r
394 }\r