API  0.9.6
 All Classes Files Functions Variables Macros Groups Pages
CPPasteboard.j
Go to the documentation of this file.
1 /*
2  * CPPasteboard.j
3  * AppKit
4  *
5  * Created by Francisco Tolmasky.
6  * Copyright 2008, 280 North, Inc.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22 
23 
24 
25 CPGeneralPboard = @"CPGeneralPboard";
26 CPFontPboard = @"CPFontPboard";
27 CPRulerPboard = @"CPRulerPboard";
28 CPFindPboard = @"CPFindPboard";
29 CPDragPboard = @"CPDragPboard";
30 
31 CPColorPboardType = @"CPColorPboardType";
32 CPFilenamesPboardType = @"CPFilenamesPboardType";
33 CPFontPboardType = @"CPFontPboardType";
34 CPHTMLPboardType = @"CPHTMLPboardType";
35 CPStringPboardType = @"CPStringPboardType";
36 CPURLPboardType = @"CPURLPboardType";
37 CPImagesPboardType = @"CPImagesPboardType";
38 CPVideosPboardType = @"CPVideosPboardType";
39 
40 UTF8PboardType = @"public.utf8-plain-text";
41 
42 // Deprecated
43 CPImagePboardType = @"CPImagePboardType";
44 
45 
46 var CPPasteboards = nil,
48 
55 @implementation CPPasteboard : CPObject
56 {
57  CPArray _types;
58  CPDictionary _owners;
59  CPDictionary _provided;
60 
61  unsigned _changeCount;
62  CPString _stateUID;
63 
64  WebScriptObject _nativePasteboard;
65 }
66 
67 /*
68  @ignore
69 */
70 + (void)initialize
71 {
72  if (self !== [CPPasteboard class])
73  return;
74 
75  [self setVersion:1.0];
76 
78 
79  if (typeof window.cpPasteboardWithName !== "undefined")
81 }
82 
86 + (id)generalPasteboard
87 {
88  return [CPPasteboard pasteboardWithName:CPGeneralPboard];
89 }
90 
96 + (id)pasteboardWithName:(CPString)aName
97 {
98  var pasteboard = [CPPasteboards objectForKey:aName];
99 
100  if (pasteboard)
101  return pasteboard;
102 
103  pasteboard = [[CPPasteboard alloc] _initWithName:aName];
104  [CPPasteboards setObject:pasteboard forKey:aName];
105 
106  return pasteboard;
107 }
108 
109 /* @ignore */
110 - (id)_initWithName:(CPString)aName
111 {
112  self = [super init];
113 
114  if (self)
115  {
116  _name = aName;
117  _types = [];
118 
119  _owners = [CPDictionary dictionary];
120  _provided = [CPDictionary dictionary];
121 
122  _changeCount = 0;
123 
125  {
126  _nativePasteboard = window.cpPasteboardWithName(aName);
127  [self _synchronizePasteboard];
128  }
129  }
130 
131  return self;
132 }
133 
140 - (unsigned)addTypes:(CPArray)types owner:(id)anOwner
141 {
142  var i = 0,
143  count = types.length;
144 
145  for (; i < count; ++i)
146  {
147  var type = types[i];
148 
149  if (![_owners objectForKey:type])
150  {
151  [_types addObject:type];
152  [_provided removeObjectForKey:type];
153  }
154 
155  [_owners setObject:anOwner forKey:type];
156  }
157 
158  if (_nativePasteboard)
159  {
160  var nativeTypes = [types copy];
161  if ([types containsObject:CPStringPboardType])
162  nativeTypes.push(UTF8PboardType);
163 
164  _nativePasteboard.addTypes_(nativeTypes);
165  }
166 
167  return ++_changeCount;
168 }
169 
176 - (unsigned)declareTypes:(CPArray)types owner:(id)anOwner
177 {
178  [self _declareTypes:types owner:anOwner updateNativePasteboard:YES];
179 }
180 
182 - (unsigned)_declareTypes:(CPArray)types owner:(id)anOwner updateNativePasteboard:(BOOL)shouldUpdate
183 {
184  [_types setArray:types];
185 
186  _owners = [CPDictionary dictionary];
187  _provided = [CPDictionary dictionary];
188 
189  var count = _types.length;
190 
191  while (count--)
192  [_owners setObject:anOwner forKey:_types[count]];
193 
194  if (_nativePasteboard && shouldUpdate)
195  {
196  var nativeTypes = [types copy];
197  if ([types containsObject:CPStringPboardType])
198  nativeTypes.push(UTF8PboardType);
199 
200  _nativePasteboard.declareTypes_(nativeTypes);
201  _changeCount = _nativePasteboard.changeCount();
202  }
203  return ++_changeCount;
204 }
205 
212 - (BOOL)setData:(CPData)aData forType:(CPString)aType
213 {
214  [_provided setObject:aData forKey:aType];
215 
216  if (aType === CPStringPboardType)
217  [self setData:aData forType:UTF8PboardType];
218 
219  return YES;
220 }
221 
228 - (BOOL)setPropertyList:(id)aPropertyList forType:(CPString)aType
229 {
230  return [self setData:[CPPropertyListSerialization dataFromPropertyList:aPropertyList format:CPPropertyList280NorthFormat_v1_0] forType:aType];
231 }
232 
239 - (void)setString:(CPString)aString forType:(CPString)aType
240 {
241  [self setPropertyList:aString forType:aType];
242 }
243 
244 // Determining Types
251 - (CPString)availableTypeFromArray:(CPArray)anArray
252 {
253  return [[self types] firstObjectCommonWithArray:anArray];
254 }
255 
259 - (CPArray)types
260 {
261  [self _synchronizePasteboard];
262  return _types;
263 }
264 
265 // Reading data
269 - (unsigned)changeCount
270 {
271  return _changeCount;
272 }
273 
279 - (CPData)dataForType:(CPString)aType
280 {
281  var data = [_provided objectForKey:aType];
282 
283  if (data)
284  return data;
285 
286  var owner = [_owners objectForKey:aType];
287 
288  if (owner)
289  {
290  [owner pasteboard:self provideDataForType:aType];
291  return [_provided objectForKey:aType];
292  }
293 
294  if (aType === CPStringPboardType)
295  return [self dataForType:UTF8PboardType];
296 
297  return nil;
298 }
299 
300 - (void)_synchronizePasteboard
301 {
302  if (_nativePasteboard && _nativePasteboard.changeCount() > _changeCount)
303  {
304  var nativeTypes = [_nativePasteboard.types() copy];
305  if ([nativeTypes containsObject:UTF8PboardType])
306  nativeTypes.push(CPStringPboardType);
307 
308  [self _declareTypes:nativeTypes owner:self updateNativePasteboard:NO];
309 
310  _changeCount = _nativePasteboard.changeCount();
311  }
312 }
313 
317 - (void)pasteboard:(CPPasteboard)aPasteboard provideDataForType:(CPString)aType
318 {
319  if (aType === CPStringPboardType)
320  {
321  var string = _nativePasteboard.stringForType_(UTF8PboardType);
322 
323  [self setString:string forType:CPStringPboardType];
324  [self setString:string forType:UTF8PboardType];
325  }
326  else
327  [self setString:_nativePasteboard.stringForType_(aType) forType:aType];
328 }
329 
335 - (id)propertyListForType:(CPString)aType
336 {
337  var data = [self dataForType:aType];
338 
339  if (data)
340  return [CPPropertyListSerialization propertyListFromData:data format:CPPropertyList280NorthFormat_v1_0];
341 
342  return nil;
343 }
344 
350 - (CPString)stringForType:(CPString)aType
351 {
352  return [self propertyListForType:aType];
353 }
354 
355 /* @ignore */
356 - (CPString)_generateStateUID
357 {
358  var bits = 32;
359 
360  _stateUID = @"";
361 
362  while (bits--)
363  _stateUID += FLOOR(RAND() * 16.0).toString(16).toUpperCase();
364 
365  return _stateUID;
366 }
367 
368 /* @ignore */
369 - (CPString)_stateUID
370 {
371  return _stateUID;
372 }
373 
374 @end
375 
376 #if PLATFORM(DOM)
377 
378 var DOMDataTransferPasteboard = nil;
379 
380 @implementation _CPDOMDataTransferPasteboard : CPPasteboard
381 {
382  DataTransfer _dataTransfer;
383 }
384 
385 + (_CPDOMDataTransferPasteboard)DOMDataTransferPasteboard
386 {
387  if (!DOMDataTransferPasteboard)
388  DOMDataTransferPasteboard = [[_CPDOMDataTransferPasteboard alloc] init];
389 
390  return DOMDataTransferPasteboard;
391 }
392 
393 - (void)_setDataTransfer:(DataTransfer)aDataTransfer
394 {
395  _dataTransfer = aDataTransfer;
396 }
397 
398 - (void)_setPasteboard:(CPPasteboard)aPasteboard
399 {
400  _dataTransfer.clearData();
401 
402  var types = [aPasteboard types],
403  count = types.length;
404 
405  while (count--)
406  {
407  var type = types[count];
408 
409  if (type === CPStringPboardType)
410  _dataTransfer.setData(type, [aPasteboard stringForType:type]);
411  else
412  _dataTransfer.setData(type, [[aPasteboard dataForType:type] rawString]);
413  }
414 }
415 
416 - (CPArray)types
417 {
418  return Array.prototype.slice.apply(_dataTransfer.types);
419 }
420 
421 - (CPData)dataForType:(CPString)aType
422 {
423  var dataString = _dataTransfer.getData(aType);
424 
425  if (aType === CPStringPboardType)
426  return [CPData dataFromPropertyList:dataString format:kCFPropertyList280NorthFormat_v1_0];
427 
428  return [CPData dataWithRawString:dataString];
429 }
430 
431 - (id)propertyListForType:(CPString)aType
432 {
433  if (aType === CPStringPboardType)
434  return _dataTransfer.getData(aType);
435 
436  return [CPPropertyListSerialization propertyListFromData:[self dataForType:aType] format:CPPropertyListUnknownFormat];
437 }
438 
439 @end
440 
441 #endif