Merge pull request #1275 from ranma42/fix-lib64
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / DataObject.cs
1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
8 // 
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
11 // 
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19 //
20 // Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
21 //
22 // Authors:
23 //      Peter Bartok    (pbartok@novell.com)
24 //
25 //
26
27 // COMPLETE
28
29 using System;
30 using System.IO;
31 using System.Drawing;
32 using System.Collections;
33 using System.Collections.Specialized;
34 using System.ComponentModel;
35 using System.Runtime.InteropServices;
36
37 namespace System.Windows.Forms {
38         [ClassInterface(ClassInterfaceType.None)]
39         public class DataObject : IDataObject, System.Runtime.InteropServices.ComTypes.IDataObject
40          {
41                 #region DataObject.Entry Class
42                 private class Entry {
43                         #region Local Variables
44                         private string  type;
45                         private object  data;
46                         private bool    autoconvert;
47                         internal Entry  next;
48                         #endregion      // Local Variables
49
50                         #region Constructors
51                         internal Entry(string type, object data, bool autoconvert) {
52                                 this.type = type;
53                                 this.data = data;
54                                 this.autoconvert = autoconvert;
55                         }
56                         #endregion      // Constructors
57
58                         #region Properties
59                         public object Data {
60                                 get {
61                                         return data;
62                                 }
63
64                                 set {
65                                         data = value;
66                                 }
67                         }
68                         public bool AutoConvert {
69                                 get { 
70                                         return autoconvert;
71                                 }
72                                 set {
73                                         autoconvert = value;
74                                 }
75                         }
76                         #endregion      // Properties
77
78                         #region Methods
79                         public static int Count(Entry entries) {
80                                 int     result;
81
82                                 result = 0;
83
84                                 while (entries != null) {
85                                         result++;
86                                         entries = entries.next;
87                                 }
88
89                                 return result;
90                         }
91
92                         public static Entry Find (Entry entries, string type) {
93                                 return Find (entries, type, false);
94                         }
95
96                         public static Entry Find(Entry entries, string type, bool only_convertible) {
97                                 while (entries != null) {
98                                         bool available = true;
99                                         if (only_convertible && !entries.autoconvert)
100                                                 available = false;
101                                         if (available && String.Compare (entries.type, type, true) == 0) {
102                                                 return entries;
103                                         }
104                                         entries = entries.next;
105                                 }
106
107                                 return null;
108                         }
109
110                         public static Entry FindConvertible(Entry entries, string type) {
111                                 Entry e;
112
113                                 e = Find(entries, type);
114                                 if (e != null) {
115                                         return e;
116                                 }
117
118                                 // map to *any* other text format if needed
119                                 if (type == DataFormats.StringFormat || type == DataFormats.Text || type == DataFormats.UnicodeText) {
120                                         e = entries;
121                                         while (e != null) {
122                                                 if (e.type == DataFormats.StringFormat || e.type == DataFormats.Text || e.type == DataFormats.UnicodeText)
123                                                         return e;
124
125                                                 e = e.next;
126                                         }
127                                 }
128
129                                 return null;
130                         }
131
132                         public static string[] Entries(Entry entries, bool convertible) {
133                                 Entry           e;
134                                 ArrayList       list;
135                                 string[]        result;
136
137                                 // Initially store into something that we can grow easily
138                                 list = new ArrayList(Entry.Count(entries));
139                                 e = entries;
140
141                                 if (convertible) {
142                                         // Add the convertibles
143                                         Entry text_entry = Entry.Find (entries, DataFormats.Text);
144                                         Entry utext_entry = Entry.Find (entries, DataFormats.UnicodeText);
145                                         Entry string_entry = Entry.Find (entries, DataFormats.StringFormat);
146                                         bool text_convertible = text_entry != null && text_entry.AutoConvert;
147                                         bool utext_convertible = utext_entry != null && utext_entry.AutoConvert;
148                                         bool string_convertible = string_entry != null && string_entry.AutoConvert;
149
150                                         if (text_convertible || utext_convertible || string_convertible) {
151                                                 list.Add (DataFormats.StringFormat);
152                                                 list.Add (DataFormats.UnicodeText);
153                                                 list.Add (DataFormats.Text);
154                                         }
155                                 }
156
157                                 while (e != null) {
158                                         if (!list.Contains (e.type))
159                                                 list.Add (e.type);
160                                         e = e.next;
161                                 }
162
163                                 // Copy the results into a string array
164                                 result = new string[list.Count];
165                                 for (int i = 0; i < list.Count; i++) {
166                                         result[i] = (string)list[i];
167                                 }
168
169                                 return result;
170                         }
171                         #endregion      // Methods
172                 }
173                 #endregion      // DataObject.Entry class
174
175                 #region Local Variables
176                 private Entry   entries;
177                 #endregion      // Local Variables
178
179                 #region Public Constructors
180                 public DataObject() {
181                         entries = null;
182                 }
183
184                 public DataObject(object data) {
185                         SetData(data);
186                 }
187
188                 public DataObject(string format, object data) {
189                         SetData(format, data);
190                 }
191                 #endregion      // Public Constructors
192
193                 #region Public Instance Methods
194                 public virtual bool ContainsAudio ()
195                 {
196                         return GetDataPresent (DataFormats.WaveAudio, true);
197                 }
198                 
199                 public virtual bool ContainsFileDropList ()
200                 {
201                         return GetDataPresent (DataFormats.FileDrop, true);
202                 }
203                 
204                 public virtual bool ContainsImage ()
205                 {
206                         return GetDataPresent (DataFormats.Bitmap, true);
207                 }
208                 
209                 public virtual bool ContainsText ()
210                 {
211                         return GetDataPresent (DataFormats.UnicodeText, true);
212                 }
213                 
214                 public virtual bool ContainsText (TextDataFormat format)
215                 {
216                         if (!Enum.IsDefined (typeof (TextDataFormat), format))
217                                 throw new InvalidEnumArgumentException (string.Format ("Enum argument value '{0}' is not valid for TextDataFormat", format));
218
219                         return GetDataPresent (TextFormatToDataFormat (format), true);
220                 }
221                 
222                 public virtual Stream GetAudioStream ()
223                 {
224                         return (Stream)GetData (DataFormats.WaveAudio, true);
225                 }
226
227                 public virtual object GetData(string format) {
228                         return GetData(format, true);
229                 }
230
231                 public virtual object GetData(string format, bool autoConvert) {
232                         Entry e;
233                         if (autoConvert) {
234                                 e = Entry.FindConvertible(entries, format);
235                         } else {
236                                 e = Entry.Find(entries, format);
237                         }
238                         if (e == null)
239                                 return null;
240                         return e.Data;
241                 }
242
243                 public virtual object GetData(Type format) {
244                         return GetData(format.FullName, true);
245                 }
246
247                 public virtual bool GetDataPresent(string format) {
248                         return GetDataPresent(format, true);
249                 }
250
251                 public virtual bool GetDataPresent(string format, bool autoConvert) {
252                         if (autoConvert) {
253                                 return Entry.FindConvertible(entries, format) != null;
254                         } else {
255                                 return Entry.Find(entries, format) != null;
256                         }
257                 }
258
259                 public virtual bool GetDataPresent(Type format) {
260                         return GetDataPresent(format.FullName, true);
261                 }
262
263                 public virtual StringCollection GetFileDropList ()
264                 {
265                         return (StringCollection)GetData (DataFormats.FileDrop, true);
266                 }
267                 public virtual string[] GetFormats() {
268                         return GetFormats(true);
269                 }
270
271                 public virtual string[] GetFormats(bool autoConvert) {
272                         return Entry.Entries(entries, autoConvert);
273                 }
274
275                 public virtual Image GetImage ()
276                 {
277                         return (Image)GetData (DataFormats.Bitmap, true);
278                 }
279
280                 public virtual string GetText ()
281                 {
282                         return (string)GetData (DataFormats.UnicodeText, true);
283                 }
284
285                 public virtual string GetText (TextDataFormat format)
286                 {
287                         if (!Enum.IsDefined (typeof (TextDataFormat), format))
288                                 throw new InvalidEnumArgumentException (string.Format ("Enum argument value '{0}' is not valid for TextDataFormat", format));
289
290                         return (string)GetData (TextFormatToDataFormat (format), false);
291                 }
292
293                 public virtual void SetAudio (byte[] audioBytes)
294                 {
295                         if (audioBytes == null)
296                                 throw new ArgumentNullException ("audioBytes");
297
298                         MemoryStream ms = new MemoryStream (audioBytes);
299
300                         SetAudio (ms);
301                 }
302
303                 public virtual void SetAudio (Stream audioStream)
304                 {
305                         if (audioStream == null)
306                                 throw new ArgumentNullException ("audioStream");
307
308                         SetData (DataFormats.WaveAudio, audioStream);
309                 }
310
311                 public virtual void SetData(object data) {
312                         SetData(data.GetType(), data); 
313                 }
314
315                 public virtual void SetData(string format, bool autoConvert, object data) {
316                         Entry   entry;
317                         Entry   e;
318
319                         entry = Entry.Find(entries, format);
320
321                         if (entry == null) {
322                                 entry = new DataObject.Entry(format, data, autoConvert);
323                         } else {
324                                 entry.Data = data;
325                                 return;
326                         }
327
328                         lock (this) {
329                                 if (entries == null) {
330                                         entries = entry;
331                                 } else {
332                                         // Insert into the list of known/defined formats
333                                         e = entries;
334
335                                         while (e.next != null) {
336                                                 e = e.next;
337                                         }
338                                         e.next = entry;
339                                 }
340                         }
341                 }
342
343                 public virtual void SetData(string format, object data) {
344                         SetData(format, true, data);
345                 }
346
347                 public virtual void SetData(Type format, object data) {
348                         SetData(EnsureFormat(format), true, data);
349                 }
350                 
351                 [MonoInternalNote ("Needs additional checks for valid paths, see MSDN")]
352                 public virtual void SetFileDropList (StringCollection filePaths)
353                 {
354                         if (filePaths == null)
355                                 throw new ArgumentNullException ("filePaths");
356
357                         SetData (DataFormats.FileDrop, filePaths);
358                 }
359
360                 public virtual void SetImage (Image image)
361                 {
362                         if (image == null)
363                                 throw new ArgumentNullException ("image");
364
365                         SetData (DataFormats.Bitmap, image);
366                 }
367
368                 public virtual void SetText (string textData)
369                 {
370                         if (string.IsNullOrEmpty (textData))
371                                 throw new ArgumentNullException ("text");
372
373                         SetData (DataFormats.UnicodeText, textData);
374                 }
375
376                 public virtual void SetText (string textData, TextDataFormat format)
377                 {
378                         if (string.IsNullOrEmpty (textData))
379                                 throw new ArgumentNullException ("text");
380                         if (!Enum.IsDefined (typeof (TextDataFormat), format))
381                                 throw new InvalidEnumArgumentException (string.Format ("Enum argument value '{0}' is not valid for TextDataFormat", format));
382
383                         switch (format) {
384                                 case TextDataFormat.Text:
385                                         SetData (DataFormats.Text, textData);
386                                         break;
387                                 case TextDataFormat.UnicodeText:
388                                         SetData (DataFormats.UnicodeText, textData);
389                                         break;
390                                 case TextDataFormat.Rtf:
391                                         SetData (DataFormats.Rtf, textData);
392                                         break;
393                                 case TextDataFormat.Html:
394                                         SetData (DataFormats.Html, textData);
395                                         break;
396                                 case TextDataFormat.CommaSeparatedValue:
397                                         SetData (DataFormats.CommaSeparatedValue, textData);
398                                         break;
399                         }
400                 }
401                 #endregion      // Public Instance Methods
402
403                 #region Private Methods
404                 internal string EnsureFormat(string name) {
405                         DataFormats.Format f;
406
407                         f = DataFormats.Format.Find(name);
408                         if (f == null) {
409                                 // Register the format
410                                 f = DataFormats.Format.Add(name);
411                         }
412
413                         return f.Name;
414                 }
415
416                 internal string EnsureFormat(Type type) {
417                         return EnsureFormat(type.FullName);
418                 }
419
420                 private string TextFormatToDataFormat (TextDataFormat format)
421                 {
422                         switch (format) {
423                                 case TextDataFormat.Text:
424                                 default:
425                                         return DataFormats.Text;
426                                 case TextDataFormat.UnicodeText:
427                                         return DataFormats.UnicodeText;
428                                 case TextDataFormat.Rtf:
429                                         return DataFormats.Rtf;
430                                 case TextDataFormat.Html:
431                                         return DataFormats.Html;
432                                 case TextDataFormat.CommaSeparatedValue:
433                                         return DataFormats.CommaSeparatedValue;
434                         }
435                 }
436                 #endregion      // Private Methods
437
438                 #region IDataObject Members
439                 int System.Runtime.InteropServices.ComTypes.IDataObject.DAdvise (ref System.Runtime.InteropServices.ComTypes.FORMATETC pFormatetc, System.Runtime.InteropServices.ComTypes.ADVF advf, System.Runtime.InteropServices.ComTypes.IAdviseSink adviseSink, out int connection)
440                 {
441                         throw new NotImplementedException ();
442                 }
443
444                 void System.Runtime.InteropServices.ComTypes.IDataObject.DUnadvise (int connection)
445                 {
446                         throw new NotImplementedException ();
447                 }
448
449                 int System.Runtime.InteropServices.ComTypes.IDataObject.EnumDAdvise (out System.Runtime.InteropServices.ComTypes.IEnumSTATDATA enumAdvise)
450                 {
451                         throw new NotImplementedException ();
452                 }
453
454                 System.Runtime.InteropServices.ComTypes.IEnumFORMATETC System.Runtime.InteropServices.ComTypes.IDataObject.EnumFormatEtc (System.Runtime.InteropServices.ComTypes.DATADIR direction)
455                 {
456                         throw new NotImplementedException ();
457                 }
458
459                 int System.Runtime.InteropServices.ComTypes.IDataObject.GetCanonicalFormatEtc (ref System.Runtime.InteropServices.ComTypes.FORMATETC formatIn, out System.Runtime.InteropServices.ComTypes.FORMATETC formatOut)
460                 {
461                         throw new NotImplementedException ();
462                 }
463
464                 void System.Runtime.InteropServices.ComTypes.IDataObject.GetData (ref System.Runtime.InteropServices.ComTypes.FORMATETC format, out System.Runtime.InteropServices.ComTypes.STGMEDIUM medium)
465                 {
466                         throw new NotImplementedException ();
467                 }
468
469                 void System.Runtime.InteropServices.ComTypes.IDataObject.GetDataHere (ref System.Runtime.InteropServices.ComTypes.FORMATETC format, ref System.Runtime.InteropServices.ComTypes.STGMEDIUM medium)
470                 {
471                         throw new NotImplementedException ();
472                 }
473
474                 int System.Runtime.InteropServices.ComTypes.IDataObject.QueryGetData (ref System.Runtime.InteropServices.ComTypes.FORMATETC format)
475                 {
476                         throw new NotImplementedException ();
477                 }
478
479                 void System.Runtime.InteropServices.ComTypes.IDataObject.SetData (ref System.Runtime.InteropServices.ComTypes.FORMATETC formatIn, ref System.Runtime.InteropServices.ComTypes.STGMEDIUM medium, bool release)
480                 {
481                         throw new NotImplementedException ();
482                 }
483                 #endregion
484          }
485 }