59 internal ClipboardSettings ClipboardSettings {
get;
set; }
62 private const int ATTEMPTS = 10;
65 private const int BETWEEN_ATTEMPTS = 100;
67 internal GPALClipboard()
69 ClipboardSettings =
new ClipboardSettings(
this);
84 ClipboardSettings.InputText = text;
96 ClipboardSettings.InputGrid = grid;
108 ClipboardSettings.InputFile = file;
119 ClipboardSettings.ClipboardType = clipboardType;
121 string text = InputAsText();
123 if (
null == text &&
null == ClipboardSettings.InputFile)
124 GPAL.
PublishSimpleEvent(GPALEventType.ERROR,
"Nothing said what to put on the clipboard. Use .WithInput first",
this, GPALObjectType.Other);
126 OnStaThread(() => Write(text));
139 ClipboardSettings.ClipboardType = clipboardType;
153 if (ClipboardType.Image == ClipboardSettings.ClipboardType)
154 OnStaThread(() => read = ReadImageAsBase64());
156 OnStaThread(() => read = Read());
170 IGPALGrid<string> retVal =
GPAL.
Grid.ToGPALObject();
173 OnStaThread(() => read = Read());
175 if (
false ==
string.IsNullOrEmpty(read))
176 foreach (
string line
in read.Replace(
"\r\n",
"\n").TrimEnd(
'\n').Split(
'\n'))
177 retVal.AddRow(
new List<string>(line.Split(
'\t')));
190 if (ClipboardType.Image == ClipboardSettings.ClipboardType)
191 OnStaThread(() => WriteImageFile(file));
196 OnStaThread(() => read = Read());
199 GPAL.
PublishSimpleEvent(GPALEventType.WARNING, $
"The clipboard holds nothing of type [{ClipboardSettings.ClipboardType}], so [{file?.Filename}] was not written",
this, GPALObjectType.Other);
201 File.WriteAllText(file.
Filename, read);
213 OnStaThread(() => Attempt(() => System.Windows.Forms.Clipboard.Clear(),
"clear the clipboard"));
224 private string InputAsText()
226 string retVal = ClipboardSettings.InputText;
228 if (
null == retVal &&
null != ClipboardSettings.InputGrid)
230 var lines =
new List<string>();
232 foreach (List<string> row
in ClipboardSettings.InputGrid)
233 lines.Add(
string.Join(
"\t", row));
235 retVal =
string.Join(Environment.NewLine, lines);
238 if (
null == retVal &&
null != ClipboardSettings.InputFile
239 && ClipboardType.FileList != ClipboardSettings.ClipboardType
240 && ClipboardType.Image != ClipboardSettings.ClipboardType)
241 retVal = File.ReadAllText(ClipboardSettings.InputFile.Filename);
250 private void Write(
string text)
252 var data =
new System.Windows.Forms.DataObject();
254 if (ClipboardType.Image == ClipboardSettings.ClipboardType)
258 if (
null != ClipboardSettings.InputFile)
259 Attempt(() => System.Windows.Forms.Clipboard.SetImage(Image.FromFile(ClipboardSettings.InputFile.Filename)),
"put an image on the clipboard");
260 else if (
false ==
string.IsNullOrWhiteSpace(text))
261 Attempt(() => System.Windows.Forms.Clipboard.SetImage(ImageHelper.Base64ToImage(text)),
"put an image on the clipboard");
263 GPAL.PublishSimpleEvent(GPALEventType.ERROR,
"An image goes on the clipboard from a file or from base64. Use .WithInput with a GPALFile or with the encoded string",
this, GPALObjectType.Other);
268 if (ClipboardType.FileList == ClipboardSettings.ClipboardType)
270 var files =
new StringCollection();
271 files.Add(ClipboardSettings.InputFile.Filename);
272 data.SetFileDropList(files);
275 data.SetData(FormatFor(ClipboardSettings.ClipboardType), text);
277 Attempt(() => System.Windows.Forms.Clipboard.SetDataObject(data,
true, ATTEMPTS, BETWEEN_ATTEMPTS),
"put data on the clipboard");
284 private string Read()
286 string retVal =
null;
290 if (ClipboardType.FileList == ClipboardSettings.ClipboardType)
292 StringCollection files = System.Windows.Forms.Clipboard.GetFileDropList();
293 var names =
new List<string>();
295 foreach (
string name
in files)
298 retVal = 0 == names.Count ? null :
string.Join(Environment.NewLine, names);
302 string format = FormatFor(ClipboardSettings.ClipboardType);
304 if (
true == System.Windows.Forms.Clipboard.ContainsData(format))
305 retVal = System.Windows.Forms.Clipboard.GetData(format) as string;
307 },
"read the clipboard");
323 private string ReadImageAsBase64()
325 string retVal =
null;
329 Image image = System.Windows.Forms.Clipboard.GetImage();
332 GPAL.PublishSimpleEvent(GPALEventType.WARNING,
"The clipboard holds no image, so nothing was encoded",
this, GPALObjectType.Other);
335 using (var stream =
new MemoryStream())
337 image.Save(stream, System.Drawing.Imaging.ImageFormat.Png);
338 retVal = Convert.ToBase64String(stream.ToArray());
341 },
"read an image from the clipboard");
346 private void WriteImageFile(GPALFile file)
350 Image image = System.Windows.Forms.Clipboard.GetImage();
353 GPAL.PublishSimpleEvent(GPALEventType.WARNING, $
"The clipboard holds no image, so [{file?.Filename}] was not written",
this, GPALObjectType.Other);
355 image.Save(file.Filename, ImageHelper.FormatForFile(file.Filename));
356 },
"read an image from the clipboard");
364 private static string FormatFor(ClipboardType clipboardType)
368 switch (clipboardType)
370 case ClipboardType.Html:
371 retVal = System.Windows.Forms.DataFormats.Html;
373 case ClipboardType.Rtf:
374 retVal = System.Windows.Forms.DataFormats.Rtf;
376 case ClipboardType.Csv:
377 retVal = System.Windows.Forms.DataFormats.CommaSeparatedValue;
380 retVal = System.Windows.Forms.DataFormats.UnicodeText;
392 private static void OnStaThread(Action work)
394 if (ApartmentState.STA == Thread.CurrentThread.GetApartmentState())
398 Thread staThread =
new Thread(() => work());
400 staThread.SetApartmentState(ApartmentState.STA);
413 private static void Attempt(Action work,
string what)
415 Exception last =
null;
418 for (
int attempt = 0; attempt < ATTEMPTS &&
false == done; attempt++)
428 Thread.Sleep(BETWEEN_ATTEMPTS);
433 GPAL.PublishSimpleEvent(GPALEventType.EXCEPTION, $
"Unable to {what} after [{ATTEMPTS}] attempts. Another process is holding it.",
null, GPALObjectType.Other, last);