![]() |
API 0.9.5
|
00001 /* 00002 * CPPasteboard.j 00003 * AppKit 00004 * 00005 * Created by Francisco Tolmasky. 00006 * Copyright 2008, 280 North, Inc. 00007 * 00008 * This library is free software; you can redistribute it and/or 00009 * modify it under the terms of the GNU Lesser General Public 00010 * License as published by the Free Software Foundation; either 00011 * version 2.1 of the License, or (at your option) any later version. 00012 * 00013 * This library is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 * Lesser General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU Lesser General Public 00019 * License along with this library; if not, write to the Free Software 00020 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00021 */ 00022 00023 00024 00025 CPGeneralPboard = @"CPGeneralPboard"; 00026 CPFontPboard = @"CPFontPboard"; 00027 CPRulerPboard = @"CPRulerPboard"; 00028 CPFindPboard = @"CPFindPboard"; 00029 CPDragPboard = @"CPDragPboard"; 00030 00031 CPColorPboardType = @"CPColorPboardType"; 00032 CPFilenamesPboardType = @"CPFilenamesPboardType"; 00033 CPFontPboardType = @"CPFontPboardType"; 00034 CPHTMLPboardType = @"CPHTMLPboardType"; 00035 CPStringPboardType = @"CPStringPboardType"; 00036 CPURLPboardType = @"CPURLPboardType"; 00037 CPImagesPboardType = @"CPImagesPboardType"; 00038 CPVideosPboardType = @"CPVideosPboardType"; 00039 00040 UTF8PboardType = @"public.utf8-plain-text"; 00041 00042 // Deprecated 00043 CPImagePboardType = @"CPImagePboardType"; 00044 00045 00046 var CPPasteboards = nil, 00047 supportsNativePasteboard = NO; 00048 00055 @implementation CPPasteboard : CPObject 00056 { 00057 CPArray _types; 00058 CPDictionary _owners; 00059 CPDictionary _provided; 00060 00061 unsigned _changeCount; 00062 CPString _stateUID; 00063 00064 WebScriptObject _nativePasteboard; 00065 } 00066 00067 /* 00068 @ignore 00069 */ 00070 + (void)initialize 00071 { 00072 if (self != [CPPasteboard class]) 00073 return; 00074 00075 [self setVersion:1.0]; 00076 00077 CPPasteboards = [CPDictionary dictionary]; 00078 00079 if (typeof window.cpPasteboardWithName !== "undefined") 00080 supportsNativePasteboard = YES; 00081 } 00082 00086 + (id)generalPasteboard 00087 { 00088 return [CPPasteboard pasteboardWithName:CPGeneralPboard]; 00089 } 00090 00096 + (id)pasteboardWithName:(CPString)aName 00097 { 00098 var pasteboard = [CPPasteboards objectForKey:aName]; 00099 00100 if (pasteboard) 00101 return pasteboard; 00102 00103 pasteboard = [[CPPasteboard alloc] _initWithName:aName]; 00104 [CPPasteboards setObject:pasteboard forKey:aName]; 00105 00106 return pasteboard; 00107 } 00108 00109 /* @ignore */ 00110 - (id)_initWithName:(CPString)aName 00111 { 00112 self = [super init]; 00113 00114 if (self) 00115 { 00116 _name = aName; 00117 _types = []; 00118 00119 _owners = [CPDictionary dictionary]; 00120 _provided = [CPDictionary dictionary]; 00121 00122 _changeCount = 0; 00123 00124 if (supportsNativePasteboard) 00125 { 00126 _nativePasteboard = window.cpPasteboardWithName(aName); 00127 [self _synchronizePasteboard]; 00128 } 00129 } 00130 00131 return self; 00132 } 00133 00140 - (unsigned)addTypes:(CPArray)types owner:(id)anOwner 00141 { 00142 var i = 0, 00143 count = types.length; 00144 00145 for (; i < count; ++i) 00146 { 00147 var type = types[i]; 00148 00149 if (![_owners objectForKey:type]) 00150 { 00151 [_types addObject:type]; 00152 [_provided removeObjectForKey:type]; 00153 } 00154 00155 [_owners setObject:anOwner forKey:type]; 00156 } 00157 00158 if (_nativePasteboard) 00159 { 00160 var nativeTypes = [types copy]; 00161 if ([types containsObject:CPStringPboardType]) 00162 nativeTypes.push(UTF8PboardType); 00163 00164 _nativePasteboard.addTypes_(nativeTypes); 00165 } 00166 00167 return ++_changeCount; 00168 } 00169 00176 - (unsigned)declareTypes:(CPArray)types owner:(id)anOwner 00177 { 00178 [self _declareTypes:types owner:anOwner updateNativePasteboard:YES]; 00179 } 00180 00182 - (unsigned)_declareTypes:(CPArray)types owner:(id)anOwner updateNativePasteboard:(BOOL)shouldUpdate 00183 { 00184 [_types setArray:types]; 00185 00186 _owners = [CPDictionary dictionary]; 00187 _provided = [CPDictionary dictionary]; 00188 00189 var count = _types.length; 00190 00191 while (count--) 00192 [_owners setObject:anOwner forKey:_types[count]]; 00193 00194 if (_nativePasteboard && shouldUpdate) 00195 { 00196 var nativeTypes = [types copy]; 00197 if ([types containsObject:CPStringPboardType]) 00198 nativeTypes.push(UTF8PboardType); 00199 00200 _nativePasteboard.declareTypes_(nativeTypes); 00201 _changeCount = _nativePasteboard.changeCount(); 00202 } 00203 return ++_changeCount; 00204 } 00205 00212 - (BOOL)setData:(CPData)aData forType:(CPString)aType 00213 { 00214 [_provided setObject:aData forKey:aType]; 00215 00216 if (aType === CPStringPboardType) 00217 [self setData:aData forType:UTF8PboardType]; 00218 00219 return YES; 00220 } 00221 00228 - (BOOL)setPropertyList:(id)aPropertyList forType:(CPString)aType 00229 { 00230 return [self setData:[CPPropertyListSerialization dataFromPropertyList:aPropertyList format:CPPropertyList280NorthFormat_v1_0] forType:aType]; 00231 } 00232 00239 - (void)setString:(CPString)aString forType:(CPString)aType 00240 { 00241 [self setPropertyList:aString forType:aType]; 00242 } 00243 00244 // Determining Types 00251 - (CPString)availableTypeFromArray:(CPArray)anArray 00252 { 00253 return [[self types] firstObjectCommonWithArray:anArray]; 00254 } 00255 00259 - (CPArray)types 00260 { 00261 [self _synchronizePasteboard]; 00262 return _types; 00263 } 00264 00265 // Reading data 00269 - (unsigned)changeCount 00270 { 00271 return _changeCount; 00272 } 00273 00279 - (CPData)dataForType:(CPString)aType 00280 { 00281 var data = [_provided objectForKey:aType]; 00282 00283 if (data) 00284 return data; 00285 00286 var owner = [_owners objectForKey:aType]; 00287 00288 if (owner) 00289 { 00290 [owner pasteboard:self provideDataForType:aType]; 00291 return [_provided objectForKey:aType]; 00292 } 00293 00294 if (aType === CPStringPboardType) 00295 return [self dataForType:UTF8PboardType]; 00296 00297 return nil; 00298 } 00299 00300 - (void)_synchronizePasteboard 00301 { 00302 if (_nativePasteboard && _nativePasteboard.changeCount() > _changeCount) 00303 { 00304 var nativeTypes = [_nativePasteboard.types() copy]; 00305 if ([nativeTypes containsObject:UTF8PboardType]) 00306 nativeTypes.push(CPStringPboardType); 00307 00308 [self _declareTypes:nativeTypes owner:self updateNativePasteboard:NO]; 00309 00310 _changeCount = _nativePasteboard.changeCount(); 00311 } 00312 } 00313 00317 - (void)pasteboard:(CPPasteboard)aPasteboard provideDataForType:(CPString)aType 00318 { 00319 if (aType === CPStringPboardType) 00320 { 00321 var string = _nativePasteboard.stringForType_(UTF8PboardType); 00322 00323 [self setString:string forType:CPStringPboardType]; 00324 [self setString:string forType:UTF8PboardType]; 00325 } 00326 else 00327 [self setString:_nativePasteboard.stringForType_(aType) forType:aType]; 00328 } 00329 00335 - (id)propertyListForType:(CPString)aType 00336 { 00337 var data = [self dataForType:aType]; 00338 00339 if (data) 00340 return [CPPropertyListSerialization propertyListFromData:data format:CPPropertyList280NorthFormat_v1_0]; 00341 00342 return nil; 00343 } 00344 00350 - (CPString)stringForType:(CPString)aType 00351 { 00352 return [self propertyListForType:aType]; 00353 } 00354 00355 /* @ignore */ 00356 - (CPString)_generateStateUID 00357 { 00358 var bits = 32; 00359 00360 _stateUID = @""; 00361 00362 while (bits--) 00363 _stateUID += FLOOR(RAND() * 16.0).toString(16).toUpperCase(); 00364 00365 return _stateUID; 00366 } 00367 00368 /* @ignore */ 00369 - (CPString)_stateUID 00370 { 00371 return _stateUID; 00372 } 00373 00374 @end 00375 00376 #if PLATFORM(DOM) 00377 00378 var DOMDataTransferPasteboard = nil; 00379 00380 @implementation _CPDOMDataTransferPasteboard : CPPasteboard 00381 { 00382 DataTransfer _dataTransfer; 00383 } 00384 00385 + (_CPDOMDataTransferPasteboard)DOMDataTransferPasteboard 00386 { 00387 if (!DOMDataTransferPasteboard) 00388 DOMDataTransferPasteboard = [[_CPDOMDataTransferPasteboard alloc] init]; 00389 00390 return DOMDataTransferPasteboard; 00391 } 00392 00393 - (void)_setDataTransfer:(DataTransfer)aDataTransfer 00394 { 00395 _dataTransfer = aDataTransfer; 00396 } 00397 00398 - (void)_setPasteboard:(CPPasteboard)aPasteboard 00399 { 00400 _dataTransfer.clearData(); 00401 00402 var types = [aPasteboard types], 00403 count = types.length; 00404 00405 while (count--) 00406 { 00407 var type = types[count]; 00408 00409 if (type === CPStringPboardType) 00410 _dataTransfer.setData(type, [aPasteboard stringForType:type]); 00411 else 00412 _dataTransfer.setData(type, [[aPasteboard dataForType:type] rawString]); 00413 } 00414 } 00415 00416 - (CPArray)types 00417 { 00418 return Array.prototype.slice.apply(_dataTransfer.types); 00419 } 00420 00421 - (CPData)dataForType:(CPString)aType 00422 { 00423 var dataString = _dataTransfer.getData(aType); 00424 00425 if (aType === CPStringPboardType) 00426 return [CPData dataFromPropertyList:dataString format:kCFPropertyList280NorthFormat_v1_0]; 00427 00428 return [CPData dataWithRawString:dataString]; 00429 } 00430 00431 - (id)propertyListForType:(CPString)aType 00432 { 00433 if (aType === CPStringPboardType) 00434 return _dataTransfer.getData(aType); 00435 00436 return [CPPropertyListSerialization propertyListFromData:[self dataForType:aType] format:CPPropertyListUnknownFormat]; 00437 } 00438 00439 @end 00440 00441 #endif