diff options
Diffstat (limited to 'source/ShiftUI/Internal/Clipboard.cs')
| -rw-r--r-- | source/ShiftUI/Internal/Clipboard.cs | 433 |
1 files changed, 433 insertions, 0 deletions
diff --git a/source/ShiftUI/Internal/Clipboard.cs b/source/ShiftUI/Internal/Clipboard.cs new file mode 100644 index 0000000..9c832a8 --- /dev/null +++ b/source/ShiftUI/Internal/Clipboard.cs @@ -0,0 +1,433 @@ +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// Copyright (c) 2005 Novell, Inc. (http://www.novell.com) +// +// Authors: +// Peter Bartok ([email protected]) +// +// + +// COMPLETE + +using System; +using System.Drawing; +using System.IO; +using System.Runtime.InteropServices; +using System.Runtime.Serialization; +using System.Collections; +using System.Collections.Specialized; +using System.ComponentModel; +using System.Threading; + +namespace ShiftUI { + public sealed class Clipboard { + #region Local Variables + #endregion // Local Variables + + #region Constructors + private Clipboard() { + } + #endregion // Constructors + + #region Private Methods + private static bool ConvertToClipboardData(ref int type, object obj, out byte[] data) { + data = null; + return false; + } + + private static bool ConvertFromClipboardData(int type, IntPtr data, out object obj) { + obj = null; + if (data == IntPtr.Zero) { + return false; + } + return false; + } + #endregion // Private Methods + + #region Public Static Methods + public static void Clear () + { + IntPtr clipboard_handle; + + clipboard_handle = XplatUI.ClipboardOpen (false); + XplatUI.ClipboardStore (clipboard_handle, null, 0, null, false); + } + + public static bool ContainsAudio () + { + return ClipboardContainsFormat (DataFormats.WaveAudio); + } + + public static bool ContainsData (string format) + { + return ClipboardContainsFormat (format); + } + + public static bool ContainsFileDropList () + { + return ClipboardContainsFormat (DataFormats.FileDrop); + } + + public static bool ContainsImage () + { + return ClipboardContainsFormat (DataFormats.Bitmap); + } + + public static bool ContainsText () + { + return ClipboardContainsFormat (DataFormats.Text, DataFormats.UnicodeText); + } + + public static bool ContainsText (TextDataFormat format) + { + switch (format) { + case TextDataFormat.Text: + return ClipboardContainsFormat (DataFormats.Text); + case TextDataFormat.UnicodeText: + return ClipboardContainsFormat (DataFormats.UnicodeText); + case TextDataFormat.Rtf: + return ClipboardContainsFormat (DataFormats.Rtf); + case TextDataFormat.Html: + return ClipboardContainsFormat (DataFormats.Html); + case TextDataFormat.CommaSeparatedValue: + return ClipboardContainsFormat (DataFormats.CommaSeparatedValue); + } + + return false; + } + + public static Stream GetAudioStream () + { + IDataObject data = GetDataObject (); + + if (data == null) + return null; + + return (Stream)data.GetData (DataFormats.WaveAudio, true); + } + + public static Object GetData (string format) + { + IDataObject data = GetDataObject (); + + if (data == null) + return null; + + return data.GetData (format, true); + } + + public static IDataObject GetDataObject () + { + return GetDataObject (false); + } + + public static StringCollection GetFileDropList () + { + IDataObject data = GetDataObject (); + + if (data == null) + return null; + + return (StringCollection)data.GetData (DataFormats.FileDrop, true); + } + + public static Image GetImage () + { + IDataObject data = GetDataObject (); + + if (data == null) + return null; + + return (Image)data.GetData (DataFormats.Bitmap, true); + } + + public static string GetText () + { + return GetText (TextDataFormat.UnicodeText); + } + + public static string GetText (TextDataFormat format) + { + if (!Enum.IsDefined (typeof (TextDataFormat), format)) + throw new InvalidEnumArgumentException (string.Format ("Enum argument value '{0}' is not valid for TextDataFormat", format)); + + IDataObject data = GetDataObject (); + + if (data == null) + return string.Empty; + + string retval; + + switch (format) { + case TextDataFormat.Text: + default: + retval = (string)data.GetData (DataFormats.Text, true); + break; + case TextDataFormat.UnicodeText: + retval = (string)data.GetData (DataFormats.UnicodeText, true); + break; + case TextDataFormat.Rtf: + retval = (string)data.GetData (DataFormats.Rtf, true); + break; + case TextDataFormat.Html: + retval = (string)data.GetData (DataFormats.Html, true); + break; + case TextDataFormat.CommaSeparatedValue: + retval = (string)data.GetData (DataFormats.CommaSeparatedValue, true); + break; + } + + return retval == null ? string.Empty : retval; + } + + public static void SetAudio (byte[] audioBytes) + { + if (audioBytes == null) + throw new ArgumentNullException ("audioBytes"); + + MemoryStream ms = new MemoryStream (audioBytes); + + SetAudio (ms); + } + + public static void SetAudio (Stream audioStream) + { + if (audioStream == null) + throw new ArgumentNullException ("audioStream"); + + SetData (DataFormats.WaveAudio, audioStream); + } + + public static void SetData (string format, Object data) + { + if (data == null) + throw new ArgumentNullException ("data"); + + DataObject data_object = new DataObject (format, data); + SetDataObject (data_object); + } + + public static void SetDataObject(object data) { + SetDataObject(data, false); // MSDN says default behavior is to place non-persistent data to clipboard + } + + public static void SetDataObject(object data, bool copy) { + SetDataObject(data, copy, 10, 100); // MSDN says default behavior is to try 10 times with 100 ms delay + } + + internal static void SetDataObjectImpl(object data, bool copy) { + IntPtr clipboard_handle; + XplatUI.ObjectToClipboard converter; + int native_format; + DataFormats.Format item_format; + + converter = new XplatUI.ObjectToClipboard(ConvertToClipboardData); + + clipboard_handle = XplatUI.ClipboardOpen(false); + XplatUI.ClipboardStore(clipboard_handle, null, 0, null, copy); // Empty clipboard + + native_format = -1; + + if (data is IDataObject) { + string[] formats; + + IDataObject data_object = data as IDataObject; + formats = data_object.GetFormats(); + for (int i = 0; i < formats.Length; i++) { + item_format = DataFormats.GetFormat(formats[i]); + if ((item_format != null) && (item_format.Name != DataFormats.StringFormat)) { + native_format = item_format.Id; + } + + object obj = data_object.GetData (formats [i]); + + // this is used only by custom formats + if (IsDataSerializable (obj)) + item_format.is_serializable = true; + + XplatUI.ClipboardStore(clipboard_handle, obj, native_format, converter, copy); + } + } else { + item_format = DataFormats.Format.Find(data.GetType().FullName); + if ((item_format != null) && (item_format.Name != DataFormats.StringFormat)) { + native_format = item_format.Id; + } + + XplatUI.ClipboardStore(clipboard_handle, data, native_format, converter, copy); + } + XplatUI.ClipboardClose(clipboard_handle); + } + + static bool IsDataSerializable (object obj) + { + if (obj is ISerializable) + return true; + + AttributeCollection attrs = TypeDescriptor.GetAttributes (obj); + return attrs [typeof (SerializableAttribute)] != null; + } + + public static void SetDataObject(object data, bool copy, int retryTimes, int retryDelay) + { + if (data == null) + throw new ArgumentNullException("data"); + if (retryTimes < 0) + throw new ArgumentOutOfRangeException("retryTimes"); + if (retryDelay < 0) + throw new ArgumentOutOfRangeException("retryDelay"); + + // MS implementation actually puts data to clipboard even when retryTimes == 0 + bool retry = true; + do + { + retry = false; + --retryTimes; + try + { + SetDataObjectImpl(data, copy); + } catch (ExternalException) { + if (retryTimes <= 0) + throw; + retry = true; + Thread.Sleep(retryDelay); + } + } while (retry && retryTimes > 0); + } + + [MonoInternalNote ("Needs additional checks for valid paths, see MSDN")] + public static void SetFileDropList (StringCollection filePaths) + { + if (filePaths == null) + throw new ArgumentNullException ("filePaths"); + + SetData (DataFormats.FileDrop, filePaths); + } + + public static void SetImage (Image image) + { + if (image == null) + throw new ArgumentNullException ("image"); + + SetData (DataFormats.Bitmap, image); + } + + public static void SetText (string text) + { + if (string.IsNullOrEmpty (text)) + throw new ArgumentNullException ("text"); + + SetData (DataFormats.UnicodeText, text); + } + + public static void SetText (string text, TextDataFormat format) + { + if (string.IsNullOrEmpty (text)) + throw new ArgumentNullException ("text"); + if (!Enum.IsDefined (typeof (TextDataFormat), format)) + throw new InvalidEnumArgumentException (string.Format ("Enum argument value '{0}' is not valid for TextDataFormat", format)); + + switch (format) { + case TextDataFormat.Text: + SetData (DataFormats.Text, text); + break; + case TextDataFormat.UnicodeText: + SetData (DataFormats.UnicodeText, text); + break; + case TextDataFormat.Rtf: + SetData (DataFormats.Rtf, text); + break; + case TextDataFormat.Html: + SetData (DataFormats.Html, text); + break; + case TextDataFormat.CommaSeparatedValue: + SetData (DataFormats.CommaSeparatedValue, text); + break; + } + } + #endregion // Public Static Methods + + #region Internal Static Methods + internal static IDataObject GetDataObject (bool primary_selection) + { + DataObject clipboard; + IntPtr clipboard_handle; + int[] native_formats; + DataFormats.Format item_format; + object managed_clipboard_item; + XplatUI.ClipboardToObject converter; + + converter = new XplatUI.ClipboardToObject (ConvertFromClipboardData); + + clipboard_handle = XplatUI.ClipboardOpen (primary_selection); + native_formats = XplatUI.ClipboardAvailableFormats (clipboard_handle); + if (native_formats == null) { + return null; // Clipboard empty + } + + // Build the IDataObject + clipboard = new DataObject (); + for (int i = 0; i < native_formats.Length; i++) { + // We might get a format we don't understand or know + item_format = DataFormats.GetFormat (native_formats[i]); + + if (item_format != null) { + managed_clipboard_item = XplatUI.ClipboardRetrieve (clipboard_handle, native_formats[i], converter); + + if (managed_clipboard_item != null) { + clipboard.SetData (item_format.Name, managed_clipboard_item); + // We don't handle 'bitmap' since it involves handles, so we'll equate it to dib + if (item_format.Name == DataFormats.Dib) { + clipboard.SetData (DataFormats.Bitmap, managed_clipboard_item); + } + } + } + } + + XplatUI.ClipboardClose (clipboard_handle); + + return clipboard; + } + + internal static bool ClipboardContainsFormat (params string[] formats) + { + IntPtr clipboard_handle; + int[] native_formats; + DataFormats.Format item_format; + + clipboard_handle = XplatUI.ClipboardOpen (false); + native_formats = XplatUI.ClipboardAvailableFormats (clipboard_handle); + + if (native_formats == null) + return false; + + foreach (int i in native_formats) { + // We might get a format we don't understand or know + item_format = DataFormats.GetFormat (i); + + if (item_format != null) + if (((IList)formats).Contains (item_format.Name)) + return true; + } + + return false; + } + #endregion + } +} |
