Mercurial > projects > dwt-mac
comparison dwt/dnd/Clipboard.d @ 45:d8635bb48c7c
Merge with SWT 3.5
author | Jacob Carlborg <doob@me.com> |
---|---|
date | Mon, 01 Dec 2008 17:07:00 +0100 |
parents | e831403a80a9 |
children | a7e41c09df9e |
comparison
equal
deleted
inserted
replaced
44:ca5e494f2bbf | 45:d8635bb48c7c |
---|---|
1 /******************************************************************************* | 1 /******************************************************************************* |
2 * Copyright (c) 2000, 2007 IBM Corporation and others. | 2 * Copyright (c) 2000, 2008 IBM Corporation and others. |
3 * All rights reserved. This program and the accompanying materials | 3 * All rights reserved. This program and the accompanying materials |
4 * are made available under the terms of the Eclipse Public License v1.0 | 4 * are made available under the terms of the Eclipse Public License v1.0 |
5 * which accompanies this distribution, and is available at | 5 * which accompanies this distribution, and is available at |
6 * http://www.eclipse.org/legal/epl-v10.html | 6 * http://www.eclipse.org/legal/epl-v10.html |
7 * | 7 * |
8 * Contributors: | 8 * Contributors: |
9 * IBM Corporation - initial API and implementation | 9 * IBM Corporation - initial API and implementation |
10 *******************************************************************************/ | 10 *******************************************************************************/ |
11 module dwt.dnd; | 11 module dwt.dnd.Clipboard; |
12 | 12 |
13 | 13 import dwt.dwthelper.utils; |
14 import dwt.*; | 14 |
15 import dwt.widgets.*; | 15 |
16 import dwt.DWT; | |
17 import dwt.DWTError; | |
18 import dwt.DWTException; | |
19 import dwt.internal.cocoa.NSArray; | |
20 import dwt.internal.cocoa.NSData; | |
21 import dwt.internal.cocoa.NSMutableArray; | |
22 import dwt.internal.cocoa.NSObject; | |
23 import dwt.internal.cocoa.NSPasteboard; | |
24 import dwt.internal.cocoa.NSString; | |
25 import dwt.internal.cocoa.NSURL; | |
16 import dwt.internal.cocoa.OS; | 26 import dwt.internal.cocoa.OS; |
27 import dwt.widgets.Display; | |
17 | 28 |
18 /** | 29 /** |
19 * The <code>Clipboard</code> provides a mechanism for transferring data from one | 30 * The <code>Clipboard</code> provides a mechanism for transferring data from one |
20 * application to another or within an application. | 31 * application to another or within an application. |
21 * | 32 * |
22 * <p>IMPORTANT: This class is <em>not</em> intended to be subclassed.</p> | 33 * <p>IMPORTANT: This class is <em>not</em> intended to be subclassed.</p> |
34 * | |
35 * @see <a href="http://www.eclipse.org/swt/snippets/#clipboard">Clipboard snippets</a> | |
36 * @see <a href="http://www.eclipse.org/swt/examples.php">DWT Example: ClipboardExample</a> | |
37 * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a> | |
23 */ | 38 */ |
24 public class Clipboard { | 39 public class Clipboard { |
25 | 40 |
26 Display display; | 41 Display display; |
27 int scrap = 0; | |
28 | 42 |
29 /** | 43 /** |
30 * Constructs a new instance of this class. Creating an instance of a Clipboard | 44 * Constructs a new instance of this class. Creating an instance of a Clipboard |
31 * may cause system resources to be allocated depending on the platform. It is therefore | 45 * may cause system resources to be allocated depending on the platform. It is therefore |
32 * mandatory that the Clipboard instance be disposed when no longer required. | 46 * mandatory that the Clipboard instance be disposed when no longer required. |
39 * </ul> | 53 * </ul> |
40 * | 54 * |
41 * @see Clipboard#dispose | 55 * @see Clipboard#dispose |
42 * @see Clipboard#checkSubclass | 56 * @see Clipboard#checkSubclass |
43 */ | 57 */ |
44 public this(Display display) { | 58 public Clipboard(Display display) { |
45 checkSubclass (); | 59 checkSubclass (); |
46 if (display is null) { | 60 if (display is null) { |
47 display = Display.getCurrent(); | 61 display = Display.getCurrent(); |
48 if (display is null) { | 62 if (display is null) { |
49 display = Display.getDefault(); | 63 display = Display.getDefault(); |
83 * </ul> | 97 * </ul> |
84 */ | 98 */ |
85 protected void checkSubclass () { | 99 protected void checkSubclass () { |
86 String name = getClass().getName (); | 100 String name = getClass().getName (); |
87 String validName = Clipboard.class.getName(); | 101 String validName = Clipboard.class.getName(); |
88 if (!validName.opEquals(name)) { | 102 if (!validName.equals(name)) { |
89 DND.error (DWT.ERROR_INVALID_SUBCLASS); | 103 DND.error (DWT.ERROR_INVALID_SUBCLASS); |
90 } | 104 } |
91 } | 105 } |
92 /** | 106 /** |
93 * Throws an <code>DWTException</code> if the receiver can not | 107 * Throws an <code>DWTException</code> if the receiver can not |
162 * | 176 * |
163 * @since 3.1 | 177 * @since 3.1 |
164 */ | 178 */ |
165 public void clearContents(int clipboards) { | 179 public void clearContents(int clipboards) { |
166 checkWidget(); | 180 checkWidget(); |
167 if ((clipboards & DND.CLIPBOARD) is 0 || scrap is 0) return; | 181 if ((clipboards & DND.CLIPBOARD) is 0) return; |
168 int oldScrap = scrap; | 182 NSPasteboard pasteboard = NSPasteboard.generalPasteboard(); |
169 scrap = 0; | 183 pasteboard.declareTypes(NSMutableArray.arrayWithCapacity(0), null); |
170 int[] currentScrap = new int[1]; | |
171 if (OS.GetCurrentScrap(currentScrap) !is OS.noErr) return; | |
172 if (currentScrap[0] is oldScrap) { | |
173 OS.ClearCurrentScrap(); | |
174 } | |
175 } | 184 } |
176 | 185 |
177 /** | 186 /** |
178 * Disposes of the operating system resources associated with the clipboard. | 187 * Disposes of the operating system resources associated with the clipboard. |
179 * The data will still be available on the system clipboard after the dispose | 188 * The data will still be available on the system clipboard after the dispose |
201 * clipboard:</p> | 210 * clipboard:</p> |
202 * | 211 * |
203 * <code><pre> | 212 * <code><pre> |
204 * Clipboard clipboard = new Clipboard(display); | 213 * Clipboard clipboard = new Clipboard(display); |
205 * TextTransfer textTransfer = TextTransfer.getInstance(); | 214 * TextTransfer textTransfer = TextTransfer.getInstance(); |
206 * String textData = cast(String)clipboard.getContents(textTransfer); | 215 * String textData = (String)clipboard.getContents(textTransfer); |
207 * if (textData !is null) System.out.println("Text is "+textData); | 216 * if (textData !is null) System.out.println("Text is "+textData); |
208 * RTFTransfer rtfTransfer = RTFTransfer.getInstance(); | 217 * RTFTransfer rtfTransfer = RTFTransfer.getInstance(); |
209 * String rtfData = cast(String)clipboard.getContents(rtfTransfer); | 218 * String rtfData = (String)clipboard.getContents(rtfTransfer); |
210 * if (rtfData !is null) System.out.println("RTF Text is "+rtfData); | 219 * if (rtfData !is null) System.out.println("RTF Text is "+rtfData); |
211 * clipboard.dispose(); | 220 * clipboard.dispose(); |
212 * </code></pre> | 221 * </code></pre> |
213 * | 222 * |
214 * @param transfer the transfer agent for the type of data being requested | 223 * @param transfer the transfer agent for the type of data being requested |
237 * clipboard:</p> | 246 * clipboard:</p> |
238 * | 247 * |
239 * <code><pre> | 248 * <code><pre> |
240 * Clipboard clipboard = new Clipboard(display); | 249 * Clipboard clipboard = new Clipboard(display); |
241 * TextTransfer textTransfer = TextTransfer.getInstance(); | 250 * TextTransfer textTransfer = TextTransfer.getInstance(); |
242 * String textData = cast(String)clipboard.getContents(textTransfer); | 251 * String textData = (String)clipboard.getContents(textTransfer); |
243 * if (textData !is null) System.out.println("Text is "+textData); | 252 * if (textData !is null) System.out.println("Text is "+textData); |
244 * RTFTransfer rtfTransfer = RTFTransfer.getInstance(); | 253 * RTFTransfer rtfTransfer = RTFTransfer.getInstance(); |
245 * String rtfData = cast(String)clipboard.getContents(rtfTransfer, DND.CLIPBOARD); | 254 * String rtfData = (String)clipboard.getContents(rtfTransfer, DND.CLIPBOARD); |
246 * if (rtfData !is null) System.out.println("RTF Text is "+rtfData); | 255 * if (rtfData !is null) System.out.println("RTF Text is "+rtfData); |
247 * clipboard.dispose(); | 256 * clipboard.dispose(); |
248 * </code></pre> | 257 * </code></pre> |
249 * | 258 * |
250 * <p>The clipboards value is either one of the clipboard constants defined in | 259 * <p>The clipboards value is either one of the clipboard constants defined in |
273 */ | 282 */ |
274 public Object getContents(Transfer transfer, int clipboards) { | 283 public Object getContents(Transfer transfer, int clipboards) { |
275 checkWidget(); | 284 checkWidget(); |
276 if (transfer is null) DND.error(DWT.ERROR_NULL_ARGUMENT); | 285 if (transfer is null) DND.error(DWT.ERROR_NULL_ARGUMENT); |
277 if ((clipboards & DND.CLIPBOARD) is 0) return null; | 286 if ((clipboards & DND.CLIPBOARD) is 0) return null; |
278 int[] scrap = new int[1]; | 287 NSPasteboard pasteboard = NSPasteboard.generalPasteboard(); |
279 if (OS.GetCurrentScrap(scrap) !is OS.noErr) return null; | 288 String[] typeNames = transfer.getTypeNames(); |
280 int[] typeIds = transfer.getTypeIds(); | 289 NSMutableArray types = NSMutableArray.arrayWithCapacity(typeNames.length); |
281 int[] size = new int[1]; | 290 for (int i = 0; i < typeNames.length; i++) { |
282 // get data from system clipboard | 291 types.addObject(NSString.stringWith(typeNames[i])); |
283 for (int i=0; i<typeIds.length; i++) { | 292 } |
284 int type = typeIds[i]; | 293 NSString type = pasteboard.availableTypeFromArray(types); |
285 size[0] = 0; | 294 if (type !is null) { |
286 if (OS.GetScrapFlavorSize(scrap[0], type, size) is OS.noErr && size[0] > 0) { | 295 TransferData tdata = new TransferData(); |
287 byte[] buffer = new byte[size[0]]; | 296 tdata.type = Transfer.registerType(type.getString()); |
288 if (OS.GetScrapFlavorData(scrap[0], type, size, buffer) is OS.noErr) { | 297 if (type.isEqual(OS.NSStringPboardType) || |
289 TransferData tdata = new TransferData(); | 298 type.isEqual(OS.NSRTFPboardType) || |
290 tdata.type = type; | 299 type.isEqual(OS.NSHTMLPboardType)) { |
291 tdata.data = new byte[1][]; | 300 tdata.data = pasteboard.stringForType(type); |
292 tdata.data[0] = buffer; | 301 } else if (type.isEqual(OS.NSFilenamesPboardType)) { |
293 return transfer.nativeToJava(tdata); | 302 tdata.data = new NSArray(pasteboard.propertyListForType(type).id); |
294 } | 303 } else if (type.isEqual(OS.NSURLPboardType)) { |
304 tdata.data = NSURL.URLFromPasteboard(pasteboard); | |
305 } else { | |
306 tdata.data = pasteboard.dataForType(type); | |
295 } | 307 } |
296 } | 308 if (tdata.data !is null) { |
297 return null; // No data available for this transfer | 309 return transfer.nativeToJava(tdata); |
310 } | |
311 } | |
312 return null; | |
298 } | 313 } |
299 | 314 |
300 /** | 315 /** |
301 * Returns <code>true</code> if the clipboard has been disposed, | 316 * Returns <code>true</code> if the clipboard has been disposed, |
302 * and <code>false</code> otherwise. | 317 * and <code>false</code> otherwise. |
433 if (data[i] is null || dataTypes[i] is null || !dataTypes[i].validate(data[i])) { | 448 if (data[i] is null || dataTypes[i] is null || !dataTypes[i].validate(data[i])) { |
434 DND.error(DWT.ERROR_INVALID_ARGUMENT); | 449 DND.error(DWT.ERROR_INVALID_ARGUMENT); |
435 } | 450 } |
436 } | 451 } |
437 if ((clipboards & DND.CLIPBOARD) is 0) return; | 452 if ((clipboards & DND.CLIPBOARD) is 0) return; |
438 if (OS.ClearCurrentScrap() !is OS.noErr) { | 453 NSPasteboard pasteboard = NSPasteboard.generalPasteboard(); |
454 if (pasteboard is null) { | |
439 DND.error(DND.ERROR_CANNOT_SET_CLIPBOARD); | 455 DND.error(DND.ERROR_CANNOT_SET_CLIPBOARD); |
440 } | 456 } |
441 scrap = 0; | 457 pasteboard.declareTypes(NSMutableArray.arrayWithCapacity(0), null); |
442 int[] currentScrap = new int[1]; | |
443 if (OS.GetCurrentScrap(currentScrap) !is OS.noErr) { | |
444 DND.error(DND.ERROR_CANNOT_SET_CLIPBOARD); | |
445 } | |
446 scrap = currentScrap[0]; | |
447 // copy data directly over to System clipboard (not deferred) | |
448 for (int i=0; i<dataTypes.length; i++) { | 458 for (int i=0; i<dataTypes.length; i++) { |
449 int[] typeIds = dataTypes[i].getTypeIds(); | 459 String[] typeNames = dataTypes[i].getTypeNames(); |
450 for (int j=0; j<typeIds.length; j++) { | 460 for (int j=0; j<typeNames.length; j++) { |
451 TransferData transferData = new TransferData(); | 461 TransferData transferData = new TransferData(); |
452 transferData.type = typeIds[j]; | 462 transferData.type = Transfer.registerType(typeNames[j]); |
453 dataTypes[i].javaToNative(data[i], transferData); | 463 dataTypes[i].javaToNative(data[i], transferData); |
454 if (transferData.result !is OS.noErr) { | 464 NSObject tdata = transferData.data; |
455 DND.error(DND.ERROR_CANNOT_SET_CLIPBOARD); | 465 NSString dataType = NSString.stringWith(typeNames[j]); |
456 } | 466 pasteboard.addTypes(NSArray.arrayWithObject(dataType), null); |
457 //Drag and Drop can handle multiple items in one transfer but the | 467 if (dataType.isEqual(OS.NSStringPboardType) || |
458 //Clipboard can not. | 468 dataType.isEqual(OS.NSRTFPboardType) || |
459 byte[] datum = transferData.data[0]; | 469 dataType.isEqual(OS.NSHTMLPboardType)) { |
460 if (OS.PutScrapFlavor(scrap, transferData.type, 0, datum.length, datum) !is OS.noErr){ | 470 pasteboard.setString((NSString) tdata, dataType); |
461 DND.error(DND.ERROR_CANNOT_SET_CLIPBOARD); | 471 } else if (dataType.isEqual(OS.NSURLPboardType)) { |
472 NSURL url = (NSURL) tdata; | |
473 url.writeToPasteboard(pasteboard); | |
474 } else if (dataType.isEqual(OS.NSFilenamesPboardType)) { | |
475 pasteboard.setPropertyList((NSArray) tdata, dataType); | |
476 } else { | |
477 pasteboard.setData((NSData) tdata, dataType); | |
462 } | 478 } |
463 } | 479 } |
464 } | 480 } |
465 } | 481 } |
466 | 482 |
506 * | 522 * |
507 * @since 3.1 | 523 * @since 3.1 |
508 */ | 524 */ |
509 public TransferData[] getAvailableTypes(int clipboards) { | 525 public TransferData[] getAvailableTypes(int clipboards) { |
510 checkWidget(); | 526 checkWidget(); |
511 if ((clipboards & DND.CLIPBOARD) is 0) return new TransferData[0]; | 527 if ((clipboards & DND.CLIPBOARD) is 0) return new TransferData[0]; |
512 int[] types = _getAvailableTypes(); | 528 NSPasteboard pasteboard = NSPasteboard.generalPasteboard(); |
513 TransferData[] result = new TransferData[types.length]; | 529 NSArray types = pasteboard.types(); |
514 for (int i = 0; i < types.length; i++) { | 530 int count = (int)/*64*/types.count(); |
531 TransferData[] result = new TransferData[count]; | |
532 for (int i = 0; i < count; i++) { | |
515 result[i] = new TransferData(); | 533 result[i] = new TransferData(); |
516 result[i].type = types[i]; | 534 result[i].type = Transfer.registerType(new NSString(types.objectAtIndex(i)).getString()); |
517 } | 535 } |
518 return result; | 536 return result; |
519 } | 537 } |
520 | 538 |
521 /** | 539 /** |
534 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 552 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
535 * </ul> | 553 * </ul> |
536 */ | 554 */ |
537 public String[] getAvailableTypeNames() { | 555 public String[] getAvailableTypeNames() { |
538 checkWidget(); | 556 checkWidget(); |
539 int[] types = _getAvailableTypes(); | 557 NSPasteboard pasteboard = NSPasteboard.generalPasteboard(); |
540 String[] names = new String[types.length]; | 558 NSArray types = pasteboard.types(); |
541 for (int i = 0; i < types.length; i++) { | 559 int count = (int)/*64*/types.count(); |
542 int type = types[i]; | 560 String[] result = new String[count]; |
543 StringBuffer sb = new StringBuffer(); | 561 for (int i = 0; i < count; i++) { |
544 sb.append(cast(wchar)((type & 0xff000000) >> 24)); | 562 result[i] = new NSString(types.objectAtIndex(i)).getString(); |
545 sb.append(cast(wchar)((type & 0x00ff0000) >> 16)); | 563 } |
546 sb.append(cast(wchar)((type & 0x0000ff00) >> 8)); | 564 return result; |
547 sb.append(cast(wchar)((type & 0x000000ff) >> 0)); | 565 } |
548 names[i] = sb.toString(); | 566 } |
549 } | |
550 return names; | |
551 } | |
552 | |
553 int[] _getAvailableTypes() { | |
554 int[] types = new int[0]; | |
555 int[] scrap = new int[1]; | |
556 if (OS.GetCurrentScrap(scrap) !is OS.noErr) return types; | |
557 int[] count = new int[1]; | |
558 if (OS.GetScrapFlavorCount(scrap[0], count) !is OS.noErr || count[0] is 0) return types; | |
559 int[] info = new int[count[0] * 2]; | |
560 if (OS.GetScrapFlavorInfoList(scrap[0], count, info) !is OS.noErr) return types; | |
561 types = new int[count[0]]; | |
562 for (int i= 0; i < count [0]; i++) { | |
563 types[i] = info[i*2]; | |
564 } | |
565 return types; | |
566 } | |
567 } |