Landing changes by Bruce Davidson <Bruce.Davidson@iplbath.com> to get Cut/Copy/Paste to work for bookmarks (bug 155484), and to fix the pasteboard string identifiers in the code (bug 287118). I made three changes to the patch:

Change CHBrowserView to no longer accept bookmark types (kCaminoBookmarkListPBoardType, kWebURLsWithTitlesPboardType), because gecko can't handle them. Instead, a parent view will now handle the drop (and correctly load tabs etc).

NSPastboard+Utils
-containsURLData changed to test for a scheme on the NSURL. Otherwise, any random text would be accepted as url data.

BookmarkViewController:
-pasteBookmarks:intoFolder:index:copying fixed to keep an array of newly created bookmark items when copying, so we can correctly reveal those new items.
This commit is contained in:
smfr%smfr.org 2005-04-13 05:35:27 +00:00
Родитель 5c40815762
Коммит 7f428391f2
17 изменённых файлов: 516 добавлений и 200 удалений

Просмотреть файл

@ -41,6 +41,8 @@
#import "Bookmark.h"
#import "BookmarkManager.h"
#import "BookmarkViewController.h"
#import "AddBookmarkDialogController.h"
@ -254,7 +256,7 @@ NSString* const kAddBookmarkItemPrimaryTabKey = @"primary";
}
}
[mBookmarkViewController revealItem:newItem selecting:YES];
[mBookmarkViewController revealItem:newItem scrollIntoView:YES selecting:YES byExtendingSelection:NO];
[[BookmarkManager sharedBookmarkManager] setLastUsedBookmarkFolder:parentFolder];
}

Просмотреть файл

@ -273,18 +273,19 @@
NSString *title = [item title];
if (isSingleBookmark)
{
[pboard declareURLPasteboardWithAdditionalTypes:[NSArray arrayWithObject:@"MozBookmarkType"] owner:self];
[pboard declareURLPasteboardWithAdditionalTypes:[NSArray arrayWithObject:kCaminoBookmarkListPBoardType] owner:self];
NSString *url = [(Bookmark *)item url];
NSString *cleanedTitle = [title stringByReplacingCharactersInSet:[NSCharacterSet controlCharacterSet] withString:@" "];
[pboard setDataForURL:url title:cleanedTitle];
}
else
{
[pboard declareTypes:[NSArray arrayWithObject:@"MozBookmarkType"] owner:self];
[pboard declareTypes:[NSArray arrayWithObject:kCaminoBookmarkListPBoardType] owner:self];
}
// MozBookmarkType
// kCaminoBookmarkListPBoardType
NSArray *pointerArray = [BookmarkManager serializableArrayWithBookmarkItems:[NSArray arrayWithObject:item]];
[pboard setPropertyList:pointerArray forType: @"MozBookmarkType"];
[pboard setPropertyList:pointerArray forType: kCaminoBookmarkListPBoardType];
[self dragImage: [MainController createImageForDragging:[self image] title:title]
at: NSMakePoint(0,NSHeight([self bounds])) offset: NSMakeSize(0,0)
event: aEvent pasteboard: pboard source: self slideBack: YES];
@ -295,7 +296,7 @@
if (operation == NSDragOperationDelete)
{
NSPasteboard* pboard = [NSPasteboard pasteboardWithName:NSDragPboard];
NSArray* bookmarks = [BookmarkManager bookmarkItemsFromSerializableArray:[pboard propertyListForType: @"MozBookmarkType"]];
NSArray* bookmarks = [BookmarkManager bookmarkItemsFromSerializableArray:[pboard propertyListForType: kCaminoBookmarkListPBoardType]];
if (bookmarks)
{
for (unsigned int i = 0; i < [bookmarks count]; ++i)

Просмотреть файл

@ -99,7 +99,8 @@ enum {
-(void) insertChild:(BookmarkItem *)aChild;
-(void) insertChild:(BookmarkItem *)aChild atIndex:(unsigned)aIndex isMove:(BOOL)aBool;
-(void) moveChild:(BookmarkItem *)aChild toBookmarkFolder:(BookmarkFolder *)aNewParent atIndex:(unsigned)aIndex;
-(void) copyChild:(BookmarkItem *)aChild toBookmarkFolder:(BookmarkFolder *)aNewParent atIndex:(unsigned)aIndex;
// returns the new child
-(BookmarkItem*) copyChild:(BookmarkItem *)aChild toBookmarkFolder:(BookmarkFolder *)aNewParent atIndex:(unsigned)aIndex;
// Used for deleting bookmarks/bookmark arrays
-(BOOL) deleteChild:(BookmarkItem *)aChild;

Просмотреть файл

@ -541,10 +541,11 @@ NSString* const BookmarkFolderDockMenuChangeNotificaton = @"bf_dmc";
[undoManager setActionName:NSLocalizedString(@"Move Separator",@"Move Separator")];
}
-(void) copyChild:(BookmarkItem *)aChild toBookmarkFolder:(BookmarkFolder *)aNewParent atIndex:(unsigned)aIndex
-(BookmarkItem*) copyChild:(BookmarkItem *)aChild toBookmarkFolder:(BookmarkFolder *)aNewParent atIndex:(unsigned)aIndex
{
if ([aNewParent isRoot] && [aChild isKindOfClass:[Bookmark class]])
return;
return nil;
BookmarkItem *copiedChild = [aChild copyWithZone:nil];
if (copiedChild) {
[aNewParent insertChild:copiedChild atIndex:aIndex isMove:NO];
@ -555,6 +556,7 @@ NSString* const BookmarkFolderDockMenuChangeNotificaton = @"bf_dmc";
else
[undoManager setActionName:NSLocalizedString(@"Copy Bookmark",@"Copy Bookmark")];
}
return copiedChild;
}
//

Просмотреть файл

@ -44,4 +44,9 @@
@interface BookmarkOutlineView : ExtendedOutlineView
{
}
// Actions for the edit menu
-(BOOL)validateMenuItem:(id)aMenuItem;
-(IBAction)delete:(id)aSender;
@end

Просмотреть файл

@ -43,13 +43,13 @@
#import "BookmarkFolder.h"
#import "Bookmark.h"
#import "BookmarkManager.h"
#import "NSPasteboard+Utils.h"
@implementation BookmarkOutlineView
- (void)awakeFromNib
{
[self registerForDraggedTypes:[NSArray arrayWithObjects:@"MozURLType", @"MozBookmarkType", NSStringPboardType, NSURLPboardType, nil]];
[self registerForDraggedTypes:[NSArray arrayWithObjects:kCaminoBookmarkListPBoardType, kWebURLsWithTitlesPboardType, NSStringPboardType, NSURLPboardType, nil]];
}
-(NSMenu*)menu
@ -73,7 +73,7 @@
{
if (operation == NSDragOperationDelete) {
NSPasteboard* pboard = [NSPasteboard pasteboardWithName:NSDragPboard];
NSArray* bookmarks = [BookmarkManager bookmarkItemsFromSerializableArray:[pboard propertyListForType: @"MozBookmarkType"]];
NSArray* bookmarks = [BookmarkManager bookmarkItemsFromSerializableArray:[pboard propertyListForType: kCaminoBookmarkListPBoardType]];
if (bookmarks) {
for (unsigned int i = 0; i < [bookmarks count]; ++i) {
BookmarkItem* item = [bookmarks objectAtIndex:i];
@ -110,4 +110,32 @@
return (NSDragOperationDelete | NSDragOperationGeneric);
}
//
// Override implementation in ExtendedOutlineView so we can check whether an
// item is selected or whether appropriate data is available on the clipboard.
//
- (BOOL)validateMenuItem:(id)aMenuItem
{
SEL action = [aMenuItem action];
if (action == @selector(delete:))
return [[self delegate] numberOfSelectedRows] > 0;
if (action == @selector(copy:))
return [super validateMenuItem:aMenuItem] && [[self delegate] numberOfSelectedRows] > 0;
if (action == @selector(paste:))
return [super validateMenuItem:aMenuItem] && [[self delegate] canPasteFromPasteboard:[NSPasteboard generalPasteboard]];
if (action == @selector(cut:))
return NO; // XXX fix me [super validateMenuItem:aMenuItem] && [[self delegate] numberOfSelectedRows] > 0;
return YES;
}
- (IBAction)delete:(id)aSender
{
[[self delegate] deleteBookmarks:aSender];
}
@end

Просмотреть файл

@ -76,7 +76,7 @@ static const int kBMBarScanningStep = 5;
mDragInsertionButton = nil;
mDragInsertionPosition = CHInsertNone;
mDrawBorder = YES;
[self registerForDraggedTypes:[NSArray arrayWithObjects:@"MozURLType", @"MozBookmarkType", NSStringPboardType, NSURLPboardType, nil]];
[self registerForDraggedTypes:[NSArray arrayWithObjects: kCaminoBookmarkListPBoardType, kWebURLsWithTitlesPboardType, NSStringPboardType, NSURLPboardType, nil]];
mIsShowing = YES;
// Generic notifications for Bookmark Client
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
@ -465,8 +465,8 @@ static const int kBMBarScanningStep = 5;
if (!toolbar)
return NO;
if ([types containsObject: @"MozBookmarkType"]) {
NSArray *draggedItems = [BookmarkManager bookmarkItemsFromSerializableArray:[draggingPasteboard propertyListForType: @"MozBookmarkType"]];
if ([types containsObject: kCaminoBookmarkListPBoardType]) {
NSArray *draggedItems = [BookmarkManager bookmarkItemsFromSerializableArray:[draggingPasteboard propertyListForType: kCaminoBookmarkListPBoardType]];
BookmarkItem* destItem = nil;
if (mDragInsertionButton == nil) {
@ -483,13 +483,9 @@ static const int kBMBarScanningStep = 5;
if (![bmManager isDropValid:draggedItems toFolder:destItem])
return NO;
}
else if ([types containsObject:NSStringPboardType]) {
// validate the string is a real url before allowing
NSURL* testURL = [NSURL URLWithString:[draggingPasteboard stringForType:NSStringPboardType]];
return (testURL != nil);
}
else
return [draggingPasteboard containsURLData];
return YES;
}
// NSDraggingDestination ///////////
@ -587,8 +583,8 @@ static const int kBMBarScanningStep = 5;
NSArray *draggedTypes = [[sender draggingPasteboard] types];
if ([draggedTypes containsObject:@"MozBookmarkType"]) {
NSArray *draggedItems = [BookmarkManager bookmarkItemsFromSerializableArray:[[sender draggingPasteboard] propertyListForType: @"MozBookmarkType"]];
if ([draggedTypes containsObject:kCaminoBookmarkListPBoardType]) {
NSArray *draggedItems = [BookmarkManager bookmarkItemsFromSerializableArray:[[sender draggingPasteboard] propertyListForType: kCaminoBookmarkListPBoardType]];
// added sequentially, so use reverse object enumerator to preserve order.
NSEnumerator *enumerator = [draggedItems reverseObjectEnumerator];
id aKid;
@ -600,27 +596,17 @@ static const int kBMBarScanningStep = 5;
}
dropHandled = YES;
}
else if ([draggedTypes containsObject:@"MozURLType"]) {
NSDictionary* proxy = [[sender draggingPasteboard] propertyListForType: @"MozURLType"];
[toolbar addBookmark:[proxy objectForKey:@"title"] url:[proxy objectForKey:@"url"] inPosition:index isSeparator:NO];
dropHandled = YES;
}
else if ([draggedTypes containsObject:NSStringPboardType]) {
NSString* draggedText = [[sender draggingPasteboard] stringForType:NSStringPboardType];
NSString* urlTitle = nil;
if ([draggedTypes containsObject:kCorePasteboardFlavorType_urld])
urlTitle = [[sender draggingPasteboard] stringForType:kCorePasteboardFlavorType_urld];
[toolbar addBookmark:(urlTitle ? urlTitle : draggedText) url:draggedText inPosition:index isSeparator:NO];
dropHandled = YES;
}
else if ([draggedTypes containsObject: NSURLPboardType]) {
NSURL* urlData = [NSURL URLFromPasteboard:[sender draggingPasteboard]];
NSString* urlTitle = nil;
if ([draggedTypes containsObject:kCorePasteboardFlavorType_urld])
urlTitle = [[sender draggingPasteboard] stringForType:kCorePasteboardFlavorType_urld];
[toolbar addBookmark:(urlTitle ? urlTitle : [urlData absoluteString]) url:[urlData absoluteString] inPosition:index isSeparator:NO];
else if ([[sender draggingPasteboard] containsURLData]) {
NSArray* urls = nil;
NSArray* titles = nil;
[[sender draggingPasteboard] getURLs:&urls andTitles:&titles];
// Add in reverse order to preserve order
for ( int i = [urls count] - 1; i >= 0; --i )
[toolbar addBookmark:[titles objectAtIndex:i] url:[urls objectAtIndex:i] inPosition:index isSeparator:NO];
dropHandled = YES;
}
mDragInsertionButton = nil;
mDragInsertionPosition = CHInsertNone;
[self setNeedsDisplay:YES];

Просмотреть файл

@ -104,8 +104,8 @@
BOOL mBookmarkUpdatesDisabled;
NSMutableDictionary* mExpandedStatus;
NSString* mCachedHref;
NSMutableDictionary* mExpandedStates;
BookmarkFolder* mActiveRootCollection;
BookmarkFolder* mRootBookmarks;
NSArray* mSearchResultArray;
@ -133,6 +133,10 @@
-(IBAction) deleteBookmarks:(id)aSender;
-(IBAction) showBookmarkInfo:(id)aSender;
-(IBAction) locateBookmark:(id)aSender;
-(IBAction) cut:(id)aSender;
-(IBAction) copy:(id)aSender;
-(IBAction) paste:(id)aSender;
-(IBAction) delete:(id)aSender;
-(IBAction) quicksearchPopupChanged:(id)aSender;
- (void)resetSearchField;
@ -147,8 +151,8 @@
-(void) setActiveCollection:(BookmarkFolder *)aFolder;
-(BookmarkFolder *)activeCollection;
-(BookmarkFolder *)selectedItemFolderAndIndex:(int*)outIndex;
-(void)revealItem:(BookmarkItem*)item selecting:(BOOL)inSelectItem;
- (BookmarkFolder *)selectedItemFolderAndIndex:(int*)outIndex;
- (void)revealItem:(BookmarkItem*)item scrollIntoView:(BOOL)inScroll selecting:(BOOL)inSelectItem byExtendingSelection:(BOOL)inExtendSelection;
- (void)setItemToRevealOnLoad:(BookmarkItem*)inItem;
@ -157,4 +161,7 @@
-(void)completeSetup;
-(void)ensureBookmarks;
-(BOOL) canPasteFromPasteboard:(NSPasteboard*)aPasteboard;
-(void) copyBookmarks:(NSArray*)bookmarkItemsToCopy toPasteboard:(NSPasteboard*)aPasteboard;
@end

Просмотреть файл

@ -25,6 +25,7 @@
* David Haas <haasd@cae.wisc.edu>
* Simon Woodside <sbwoodside@yahoo.com>
* Josh Aas <josha@mac.com>
* Bruce Davidson <Bruce.Davidson@ipl.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@ -82,6 +83,8 @@
#define kGetInfoContextMenuItemTag 9
static NSString* const kExpandedBookmarksStatesDefaultsKey = @"bookmarks_expand_state";
// minimum sizes for the search panel
const long kMinContainerSplitWidth = 150;
const long kMinSearchPaneHeight = 80;
@ -123,6 +126,7 @@ static const int kDisabledQuicksearchPopupItemTag = 9999;
- (NSMutableDictionary *)expandedStateDictionary;
- (void)restoreFolderExpandedStates;
- (void)saveExpandedStateDictionary;
- (BOOL)hasExpandedState:(id)anItem;
- (void)setStateOfItem:(BookmarkFolder *)anItem toExpanded:(BOOL)aBool;
@ -133,6 +137,8 @@ static const int kDisabledQuicksearchPopupItemTag = 9999;
- (NSDragOperation)preferredDragOperationForSourceMask:(NSDragOperation)srcMask;
-(void)pasteBookmarks:(NSPasteboard*)aPasteboard intoFolder:(BookmarkFolder *)dropFolder index:(int)index copying:(BOOL)isCopy;
-(void)pasteBookmarksFromURLsAndTitles:(NSPasteboard*)aPasteboard intoFolder:(BookmarkFolder*)dropFolder index:(int)index;
@end
@ -172,6 +178,8 @@ static const int kDisabledQuicksearchPopupItemTag = 9999;
[[NSNotificationCenter defaultCenter] removeObserver:self];
[self saveExpandedStateDictionary];
// balance the extra retains
[mBookmarksHostView release];
[mHistoryHostView release];
@ -196,8 +204,7 @@ static const int kDisabledQuicksearchPopupItemTag = 9999;
// release data
[mItemToReveal release];
[mCachedHref release];
[mExpandedStatus release];
[mExpandedStates release];
[mActiveRootCollection release];
[mRootBookmarks release];
[mSearchResultArray release];
@ -267,7 +274,7 @@ static const int kDisabledQuicksearchPopupItemTag = 9999;
[nc addObserver:self selector:@selector(managerStarted:) name:[BookmarkManager managerStartedNotification] object:nil];
// register for dragged types
[mContainersTableView registerForDraggedTypes:[NSArray arrayWithObjects:@"MozBookmarkType", @"MozURLType", NSURLPboardType, NSStringPboardType, nil]];
[mContainersTableView registerForDraggedTypes:[NSArray arrayWithObjects:kCaminoBookmarkListPBoardType, kWebURLsWithTitlesPboardType, NSURLPboardType, NSStringPboardType, nil]];
[self ensureBookmarks];
@ -582,6 +589,75 @@ static const int kDisabledQuicksearchPopupItemTag = 9999;
[mBookmarksOutlineView selectRow:[mBookmarksOutlineView rowForItem:item] byExtendingSelection:NO];
}
-(IBAction) cut:(id)aSender
{
// XXX write me. We'll need to write to the pasteboard something other than an array of UUIDs,
// because we need to rip the bookmark items out of the tree.
}
- (IBAction)copy:(id)aSender
{
// Get the list of bookmark items that are selected
NSMutableArray *bookmarkItemsToCopy = [NSMutableArray array];
NSEnumerator* selRows = [mBookmarksOutlineView selectedRowEnumerator];
id curSelectedRow;
while ((curSelectedRow = [selRows nextObject])) {
[bookmarkItemsToCopy addObject: [mBookmarksOutlineView itemAtRow:[curSelectedRow intValue]]];
}
[self copyBookmarks:bookmarkItemsToCopy toPasteboard:[NSPasteboard generalPasteboard]];
}
//
// Paste bookmark(s) from the general pasteboard into the user's bookmarks file
// We use the view to work out where to paste the bookmark
// If no items are selected in the view : at the end of the bookmark menu folder
// If a folder is selected: at the end of that folder
// If a bookmark is selected: immediately after that bookmark, under the same parent
// XXX: At the moment if multiple items are selected we only examine the first one
//
-(IBAction) paste:(id)aSender
{
NSArray* types = [[NSPasteboard generalPasteboard] types];
int pasteDestinationIndex = 0;
BookmarkFolder* pasteDestinationFolder = nil;
// Work out what the selected item is and therefore where to paste the bookmark(s)
NSEnumerator* selRows = [mBookmarksOutlineView selectedRowEnumerator];
id curSelectedRow = [selRows nextObject];
if (curSelectedRow) {
BookmarkItem* item = [mBookmarksOutlineView itemAtRow:[curSelectedRow intValue]];
if ([item isKindOfClass:[BookmarkFolder class]]) {
pasteDestinationFolder = (BookmarkFolder*) item;
pasteDestinationIndex = [pasteDestinationFolder count];
} else if ([item isKindOfClass:[Bookmark class]]) {
pasteDestinationFolder = (BookmarkFolder*) [item parent];
pasteDestinationIndex = [pasteDestinationFolder indexOfObject:item] + 1;
}
}
// If we don't have a destination use the end of the bookmark menu
if (!pasteDestinationFolder) {
pasteDestinationFolder = [[BookmarkManager sharedBookmarkManager] bookmarkMenuFolder];
pasteDestinationIndex = [pasteDestinationFolder count];
}
// Do the actual copy based on the type available on the clipboard
if ([types containsObject: kCaminoBookmarkListPBoardType])
[self pasteBookmarks:[NSPasteboard generalPasteboard] intoFolder:pasteDestinationFolder index:pasteDestinationIndex copying:YES];
else if ([[NSPasteboard generalPasteboard] containsURLData])
[self pasteBookmarksFromURLsAndTitles:[NSPasteboard generalPasteboard] intoFolder:pasteDestinationFolder index:pasteDestinationIndex];
}
-(IBAction) delete:(id)aSender
{
[self deleteBookmarks:aSender];
}
-(IBAction)quicksearchPopupChanged:(id)aSender
{
// do the search again (we'll pick up the new popup item tag)
@ -692,7 +768,7 @@ static const int kDisabledQuicksearchPopupItemTag = 9999;
mItemToReveal = [inItem retain];
}
-(void)revealItem:(BookmarkItem*)item selecting:(BOOL)inSelectItem
-(void)revealItem:(BookmarkItem*)item scrollIntoView:(BOOL)inScroll selecting:(BOOL)inSelectItem byExtendingSelection:(BOOL)inExtendSelection
{
BookmarkManager* bmManager = [BookmarkManager sharedBookmarkManager];
@ -774,9 +850,100 @@ static const int kDisabledQuicksearchPopupItemTag = 9999;
- (NSMutableDictionary *)expandedStateDictionary
{
if (!mExpandedStatus)
mExpandedStatus = [[NSMutableDictionary alloc] initWithCapacity:20];
return mExpandedStatus;
if (!mExpandedStates)
{
// We can't save BM expanded states to user defaults, because we don't have a persisent per-bookmark ID.
// mExpandedStates = [[[NSUserDefaults standardUserDefaults] dictionaryForKey:kExpandedBookmarksStatesDefaultsKey] mutableCopy];
// if (!mExpandedStates)
mExpandedStates = [[NSMutableDictionary alloc] initWithCapacity:20];
}
return mExpandedStates;
}
- (void)saveExpandedStateDictionary
{
// We can't save BM expanded states to user defaults, because we don't have a persisent per-bookmark ID.
// if (mExpandedStates)
// [[NSUserDefaults standardUserDefaults] setObject:mExpandedStates forKey:kExpandedBookmarksStatesDefaultsKey];
}
-(void)pasteBookmarks:(NSPasteboard*)aPasteboard intoFolder:(BookmarkFolder *)dropFolder index:(int)index copying:(BOOL)isCopy
{
NSArray* mozBookmarkList = [BookmarkManager bookmarkItemsFromSerializableArray:[aPasteboard propertyListForType: kCaminoBookmarkListPBoardType]];
NSMutableArray* newBookmarks = [[NSMutableArray alloc] initWithCapacity:[mozBookmarkList count]];
if (!isCopy)
[newBookmarks addObjectsFromArray:mozBookmarkList];
// turn off updates to avoid lots of reloadData with multiple items
mBookmarkUpdatesDisabled = YES;
// make sure we re-enable updates
NS_DURING
NSEnumerator *enumerator = [mozBookmarkList objectEnumerator];
id aKid;
while ((aKid = [enumerator nextObject]))
{
if (isCopy)
{
BookmarkItem* newItem = [[aKid parent] copyChild:aKid toBookmarkFolder:dropFolder atIndex:index];
[newBookmarks addObject:newItem];
++index;
}
else
{
// need to be careful to adjust index as we insert items to avoid
// inserting in reverse order
if ([aKid parent] == dropFolder)
{
int kidIndex = [dropFolder indexOfObject:aKid];
[[aKid parent] moveChild:aKid toBookmarkFolder:dropFolder atIndex:index];
if (kidIndex > index)
++index;
}
else
{
[[aKid parent] moveChild:aKid toBookmarkFolder:dropFolder atIndex:index];
++index;
}
}
}
NS_HANDLER
NS_ENDHANDLER
mBookmarkUpdatesDisabled = NO;
[self reloadDataForItem:nil reloadChildren:YES];
[self selectItems:newBookmarks expandingContainers:YES scrollIntoView:YES];
[newBookmarks release];
}
-(void)pasteBookmarksFromURLsAndTitles:(NSPasteboard*)aPasteboard intoFolder:(BookmarkFolder *)dropFolder index:(int)index
{
NSArray* urls = nil;
NSArray* titles = nil;
[aPasteboard getURLs:&urls andTitles:&titles];
// turn off updates to avoid lots of reloadData with multiple items
mBookmarkUpdatesDisabled = YES;
NSMutableArray* newBookmarks = [NSMutableArray arrayWithCapacity:[urls count]];
// make sure we re-enable updates
NS_DURING
for ( unsigned int i = 0; i < [urls count]; ++i ) {
NSString* title = [titles objectAtIndex:i];
if ([title length] == 0)
title = [urls objectAtIndex:i];
[newBookmarks addObject:[dropFolder addBookmark:title url:[urls objectAtIndex:i] inPosition:(index + i) isSeparator:NO]];
}
NS_HANDLER
NS_ENDHANDLER
mBookmarkUpdatesDisabled = NO;
[self reloadDataForItem:nil reloadChildren:YES];
[self selectItems:newBookmarks expandingContainers:NO scrollIntoView:YES];
}
//
@ -790,83 +957,17 @@ static const int kDisabledQuicksearchPopupItemTag = 9999;
NSArray* types = [[info draggingPasteboard] types];
BOOL isCopy = ([info draggingSourceOperationMask] == NSDragOperationCopy);
if ([types containsObject: @"MozBookmarkType"])
if ([types containsObject: kCaminoBookmarkListPBoardType])
{
NSArray *draggedItems = [BookmarkManager bookmarkItemsFromSerializableArray:[[info draggingPasteboard] propertyListForType: @"MozBookmarkType"]];
// turn off updates to avoid lots of reloadData with multiple items
mBookmarkUpdatesDisabled = YES;
// make sure we re-enable updates
NS_DURING
NSEnumerator *enumerator = [draggedItems objectEnumerator];
id aKid;
while ((aKid = [enumerator nextObject]))
{
if (isCopy)
{
[[aKid parent] copyChild:aKid toBookmarkFolder:dropFolder atIndex:index];
++index;
}
else
{
// need to be careful to adjust index as we insert items to avoid
// inserting in reverse order
if ([aKid parent] == dropFolder)
{
int kidIndex = [dropFolder indexOfObject:aKid];
[[aKid parent] moveChild:aKid toBookmarkFolder:dropFolder atIndex:index];
if (kidIndex > index)
++index;
}
else
{
[[aKid parent] moveChild:aKid toBookmarkFolder:dropFolder atIndex:index];
++index;
}
}
}
NS_HANDLER
NS_ENDHANDLER
mBookmarkUpdatesDisabled = NO;
[self reloadDataForItem:nil reloadChildren:YES];
[self selectItems:draggedItems expandingContainers:NO scrollIntoView:NO];
[self pasteBookmarks:[info draggingPasteboard] intoFolder:dropFolder index:index copying:isCopy];
return YES;
}
else if ([types containsObject: @"MozURLType"])
if ([[info draggingPasteboard] containsURLData])
{
NSDictionary* proxy = [[info draggingPasteboard] propertyListForType: @"MozURLType"];
Bookmark* newBookmark = [dropFolder addBookmark:[proxy objectForKey:@"title"] url:[proxy objectForKey:@"url"] inPosition:index isSeparator:NO];
[self selectItem:newBookmark expandingContainers:NO scrollIntoView:NO byExtendingSelection:NO];
[self pasteBookmarksFromURLsAndTitles:[info draggingPasteboard] intoFolder:dropFolder index:index];
return YES;
}
else if ([types containsObject: NSURLPboardType])
{
NSURL* urlData = [NSURL URLFromPasteboard:[info draggingPasteboard]];
NSString* urlTitle = nil;
if ([types containsObject:kCorePasteboardFlavorType_urld])
urlTitle = [[info draggingPasteboard] stringForType:kCorePasteboardFlavorType_urld];
Bookmark* newBookmark = [dropFolder addBookmark:(urlTitle ? urlTitle : [urlData absoluteString]) url:[urlData absoluteString] inPosition:index isSeparator:NO];
[self selectItem:newBookmark expandingContainers:NO scrollIntoView:NO byExtendingSelection:NO];
return YES;
}
else if ([types containsObject: NSStringPboardType])
{
NSString* draggedText = [[info draggingPasteboard] stringForType:NSStringPboardType];
NSURL *testURL = [NSURL URLWithString:draggedText];
NSString* urlTitle = nil;
if ([types containsObject:kCorePasteboardFlavorType_urld])
urlTitle = [[info draggingPasteboard] stringForType:kCorePasteboardFlavorType_urld];
if (testURL)
{
Bookmark* newBookmark = [dropFolder addBookmark:(urlTitle ? urlTitle : draggedText) url:draggedText inPosition:index isSeparator:NO];
[self selectItem:newBookmark expandingContainers:NO scrollIntoView:NO byExtendingSelection:NO];
return YES;
}
}
return NO;
}
@ -883,6 +984,39 @@ static const int kDisabledQuicksearchPopupItemTag = 9999;
return NSDragOperationNone;
}
//
// Copy a set of bookmarks (an NSArray containing the BookmarkItem and BookmarkFolder objects)
// to the specified pasteboard, in all the available formats
//
- (void) copyBookmarks:(NSArray*)bookmarkItemsToCopy toPasteboard:(NSPasteboard*)aPasteboard
{
// Copy these items to the general pasteboard as an internal list so we can
// paste back to ourselves with no information loss
NSArray *bookmarkUUIDArray = [BookmarkManager serializableArrayWithBookmarkItems:bookmarkItemsToCopy];
[aPasteboard declareTypes:[NSArray arrayWithObject:kCaminoBookmarkListPBoardType] owner:self];
[aPasteboard setPropertyList:bookmarkUUIDArray forType:kCaminoBookmarkListPBoardType];
// Now add copies in formats useful to other applications. Our pasteboard
// category takes care of working out what formats to write.
NSMutableArray* urlList = [NSMutableArray array];
NSMutableArray* titleList = [NSMutableArray array];
for ( unsigned int i = 0; i < [bookmarkItemsToCopy count]; ++i ) {
BookmarkItem* bookmarkItem = [bookmarkItemsToCopy objectAtIndex:i];
if ([bookmarkItem isKindOfClass:[Bookmark class]]) {
Bookmark* bookmark = (Bookmark*) bookmarkItem;
[urlList addObject:[bookmark url]];
[titleList addObject:[bookmark title]];
}
}
[aPasteboard setURLs:urlList withTitles:titleList];
}
-(BOOL) canPasteFromPasteboard:(NSPasteboard*)aPasteboard
{
return [[aPasteboard types] containsObject:kCaminoBookmarkListPBoardType]
|| [aPasteboard containsURLData];
}
#pragma mark -
//
@ -1016,11 +1150,9 @@ static const int kDisabledQuicksearchPopupItemTag = 9999;
[itemArray release];
return NO;
}
// Pack pointers to bookmark items into this array
NSArray *pointerArray = [BookmarkManager serializableArrayWithBookmarkItems:itemArray];
[self copyBookmarks:itemArray toPasteboard:pboard];
[itemArray release];
[pboard declareTypes:[NSArray arrayWithObject:@"MozBookmarkType"] owner:self];
[pboard setPropertyList:pointerArray forType:@"MozBookmarkType"];
return YES;
}
@ -1048,22 +1180,16 @@ static const int kDisabledQuicksearchPopupItemTag = 9999;
}
if (dropFolder) {
// special check if we're moving pointers around
if ([types containsObject:@"MozBookmarkType"])
if ([types containsObject:kCaminoBookmarkListPBoardType])
{
NSArray *draggedItems = [BookmarkManager bookmarkItemsFromSerializableArray:[[info draggingPasteboard] propertyListForType: @"MozBookmarkType"]];
NSArray *draggedItems = [BookmarkManager bookmarkItemsFromSerializableArray:[[info draggingPasteboard] propertyListForType: kCaminoBookmarkListPBoardType]];
BOOL isOK = [manager isDropValid:draggedItems toFolder:dropFolder];
return (isOK) ? dragOp : NSDragOperationNone;
}
else if ([types containsObject:@"MozURLType"] || [types containsObject:NSURLPboardType])
else if ([[info draggingPasteboard] containsURLData])
{
return (dropFolder == mRootBookmarks) ? NSDragOperationNone : dragOp;
}
else if ([types containsObject:NSStringPboardType])
{
NSURL* testURL = [NSURL URLWithString:[[info draggingPasteboard] stringForType:NSStringPboardType]];
if (testURL)
return (dropFolder == mRootBookmarks) ? NSDragOperationNone : dragOp;
}
}
}
// nope
@ -1207,20 +1333,7 @@ static const int kDisabledQuicksearchPopupItemTag = 9999;
return NO;
// Pack pointers to bookmark items into this array.
NSArray *pointerArray = [BookmarkManager serializableArrayWithBookmarkItems:items];
if (count == 1) {
id aBookmark = [items objectAtIndex:0];
if ([aBookmark isKindOfClass:[Bookmark class]]) {
[pboard declareURLPasteboardWithAdditionalTypes:[NSArray arrayWithObject:@"MozBookmarkType"] owner:self];
[pboard setDataForURL:[aBookmark url] title:[aBookmark title]];
[pboard setPropertyList:pointerArray forType:@"MozBookmarkType"];
return YES;
}
}
// it's either a folder or we've got more than 1 thing. ship it
// out as MozBookmarkType
[pboard declareTypes:[NSArray arrayWithObject:@"MozBookmarkType"] owner: self];
[pboard setPropertyList: pointerArray forType:@"MozBookmarkType"];
[self copyBookmarks:items toPasteboard:pboard];
return YES;
}
@ -1233,22 +1346,16 @@ static const int kDisabledQuicksearchPopupItemTag = 9999;
if (index == NSOutlineViewDropOnItemIndex)
return NSDragOperationNone;
if ([types containsObject: @"MozBookmarkType"]) {
NSArray *draggedItems = [BookmarkManager bookmarkItemsFromSerializableArray:[[info draggingPasteboard] propertyListForType: @"MozBookmarkType"]];
if ([types containsObject: kCaminoBookmarkListPBoardType]) {
NSArray *draggedItems = [BookmarkManager bookmarkItemsFromSerializableArray:[[info draggingPasteboard] propertyListForType: kCaminoBookmarkListPBoardType]];
BookmarkFolder* parent = (item) ? item : [self itemTreeRootContainer];
BOOL isOK = [[BookmarkManager sharedBookmarkManager] isDropValid:draggedItems toFolder:parent];
return (isOK) ? dragOp : NSDragOperationNone;
}
if ([types containsObject: NSURLPboardType] || [types containsObject: @"MozURLType"] )
if ([[info draggingPasteboard] containsURLData])
return dragOp;
// see if we can turn a string into a URL. If so, accept it. If not, punt.
if ([types containsObject: NSStringPboardType]) {
NSURL* testURL = [NSURL URLWithString:[[info draggingPasteboard] stringForType:NSStringPboardType]];
if (testURL)
return dragOp;
}
return NSDragOperationNone;
}
@ -1483,6 +1590,8 @@ static const int kDisabledQuicksearchPopupItemTag = 9999;
// share code with revealItem:selecting:
- (void)selectItem:(BookmarkItem*)item expandingContainers:(BOOL)expandContainers scrollIntoView:(BOOL)scroll byExtendingSelection:(BOOL)extendSelection
{
[self revealItem:item scrollIntoView:scroll selecting:YES byExtendingSelection:extendSelection];
#if 0
int itemRow = [mBookmarksOutlineView rowForItem:item];
if (itemRow == -1)
{
@ -1496,6 +1605,7 @@ static const int kDisabledQuicksearchPopupItemTag = 9999;
[mBookmarksOutlineView selectRow:itemRow byExtendingSelection:extendSelection];
if (scroll)
[mBookmarksOutlineView scrollRowToVisible:itemRow];
#endif
}
- (id)itemTreeRootContainer
@ -1680,7 +1790,7 @@ static const int kDisabledQuicksearchPopupItemTag = 9999;
if (mItemToReveal)
{
[self revealItem:mItemToReveal selecting:YES];
[self revealItem:mItemToReveal scrollIntoView:YES selecting:YES byExtendingSelection:NO];
[mItemToReveal release];
mItemToReveal = nil;
}

Просмотреть файл

@ -39,6 +39,7 @@
#import "BrowserTabBarView.h"
#import "BrowserTabViewItem.h"
#import "TabButtonCell.h"
#import "NSPasteboard+Utils.h"
@interface BrowserTabBarView (PRIVATE)
-(void)layoutButtons;
@ -81,8 +82,12 @@ static const int kOverflowButtonMargin = 1;
mVisible = YES;
// this will not likely have any result here
[self rebuildTabBar];
[self registerForDraggedTypes:[NSArray arrayWithObjects: @"MozURLType", @"MozBookmarkType", NSStringPboardType,
NSFilenamesPboardType, NSURLPboardType, nil]];
[self registerForDraggedTypes:[NSArray arrayWithObjects: kCaminoBookmarkListPBoardType,
kWebURLsWithTitlesPboardType,
NSStringPboardType,
NSFilenamesPboardType,
NSURLPboardType,
nil]];
}
return self;
}

Просмотреть файл

@ -91,7 +91,8 @@
mVisible = YES;
[self showOrHideTabsAsAppropriate];
[self registerForDraggedTypes:[NSArray arrayWithObjects:
@"MozURLType", @"MozBookmarkType", NSStringPboardType, NSFilenamesPboardType, NSURLPboardType, nil]];
kCaminoBookmarkListPBoardType, kWebURLsWithTitlesPboardType,
NSStringPboardType, NSFilenamesPboardType, NSURLPboardType, nil]];
}
/******************************************/
@ -367,8 +368,8 @@
// if there's no tabviewitem at the point within our view, check the tabbar as well.
overTabViewItem = [mTabBar tabViewItemAtPoint:[sender draggingLocation]];
if ([pasteBoardTypes containsObject:@"MozBookmarkType"]) {
NSArray *draggedItems = [BookmarkManager bookmarkItemsFromSerializableArray:[[sender draggingPasteboard] propertyListForType: @"MozBookmarkType"]];
if ([pasteBoardTypes containsObject:kCaminoBookmarkListPBoardType]) {
NSArray *draggedItems = [BookmarkManager bookmarkItemsFromSerializableArray:[[sender draggingPasteboard] propertyListForType: kCaminoBookmarkListPBoardType]];
if (draggedItems) {
id aBookmark;
if ([draggedItems count] == 1) {
@ -393,13 +394,25 @@
}
}
}
else if ([pasteBoardTypes containsObject:@"MozURLType"]) {
// drag type is MozURLType
NSDictionary *data = [[sender draggingPasteboard] propertyListForType:@"MozURLType"];
if (data) {
NSString *urlString = [data objectForKey:@"url"];
return [self handleDropOnTab:overTabViewItem overContent:overContentArea withURL:urlString];
else if ([[sender draggingPasteboard] containsURLData]) {
// Pasteboard contains a collection of URLs, handle in the same way we handle a collection of files
NSArray* urls;
NSArray* titles;
[[sender draggingPasteboard] getURLs:&urls andTitles:&titles];
for (unsigned int i = 0; i < [urls count]; ++i) {
if (i == 0) {
// if we're over the content area, just load the first one
if (overContentArea)
return [self handleDropOnTab:overTabViewItem overContent:YES withURL:[urls objectAtIndex:i]];
// otherwise load the first in the tab, and keep going
[self handleDropOnTab:overTabViewItem overContent:NO withURL:[urls objectAtIndex:i]];
}
else {
// for subsequent items, make new tabs
[self handleDropOnTab:nil overContent:NO withURL:[urls objectAtIndex:i]];
}
}
return YES;
} // check for NSFilenamesPboardType next so we always handle multiple filenames when we should
else if ([pasteBoardTypes containsObject:NSFilenamesPboardType]) {
NSArray *files = [[sender draggingPasteboard] propertyListForType:NSFilenamesPboardType];
@ -433,14 +446,6 @@
}
return YES;
}
else if ([pasteBoardTypes containsObject:NSStringPboardType]) {
NSString *urlString = [[sender draggingPasteboard] stringForType: NSStringPboardType];
return [self handleDropOnTab:overTabViewItem overContent:overContentArea withURL:urlString];
}
else if ([pasteBoardTypes containsObject:NSURLPboardType]) {
NSURL *urlData = [NSURL URLFromPasteboard:[sender draggingPasteboard]];
return [self handleDropOnTab:overTabViewItem overContent:overContentArea withURL:[urlData absoluteString]];
}
return NO;
}

Просмотреть файл

@ -98,7 +98,8 @@ const int kMenuTruncationChars = 60;
mTabButtonCell = [[TabButtonCell alloc] initFromTabViewItem:mTabViewItem];
[self registerForDraggedTypes:[NSArray arrayWithObjects:
@"MozURLType", @"MozBookmarkType", NSStringPboardType, NSFilenamesPboardType, NSURLPboardType, nil]];
kCaminoBookmarkListPBoardType, kWebURLsWithTitlesPboardType,
NSStringPboardType, NSFilenamesPboardType, NSURLPboardType, nil]];
}
return self;
}

Просмотреть файл

@ -95,13 +95,13 @@ typedef unsigned int DragReference;
// Cut/copy/paste
#include "nsIClipboardCommands.h"
#include "nsIInterfaceRequestorUtils.h"
#import "NSPasteboard+Utils.h"
// Undo/redo
#include "nsICommandManager.h"
#include "nsICommandParams.h"
const char kPersistContractID[] = "@mozilla.org/embedding/browser/nsWebBrowserPersist;1";
const char kDirServiceContractID[] = "@mozilla.org/file/directory_service;1";
@ -160,7 +160,7 @@ const char kDirServiceContractID[] = "@mozilla.org/file/directory_service;1";
// register the view as a drop site for text, files, and urls.
[self registerForDraggedTypes: [NSArray arrayWithObjects:
@"MozURLType", NSStringPboardType, NSURLPboardType, NSFilenamesPboardType, nil]];
NSStringPboardType, NSURLPboardType, NSFilenamesPboardType, nil]];
// The value of mUseGlobalPrintSettings can't change during our lifetime.
nsCOMPtr<nsIPrefBranch> pref(do_GetService("@mozilla.org/preferences-service;1"));

Просмотреть файл

@ -81,6 +81,13 @@
- (void)setAutosaveTableSort:(BOOL)autosave;
- (BOOL)autosaveTableSort;
// Clipboard functions
-(BOOL) validateMenuItem:(id)aMenuItem;
-(IBAction) copy:(id)aSender;
-(IBAction) delete:(id)aSender;
-(IBAction) paste:(id)aSender;
-(IBAction) cut:(id)aSender;
@end
@interface NSObject (CHOutlineViewDataSourceToolTips)

Просмотреть файл

@ -572,4 +572,48 @@ static NSString* const kAutosaveSortDirectionKey = @"sort_descending";
oldFrameRect = frameRect;
}
#pragma mark -
// Support clipboard actions if our delegate implements them
-(BOOL) validateMenuItem:(id)aMenuItem
{
SEL action = [aMenuItem action];
// XXX we should probably try to call validateMenuItem: on the delegate too
if (action == @selector(delete:))
return [[self delegate] respondsToSelector:@selector(delete:)];
else if (action == @selector(copy:))
return [[self delegate] respondsToSelector:@selector(copy:)];
else if (action == @selector(paste:))
return [[self delegate] respondsToSelector:@selector(paste:)];
else if (action == @selector(cut:))
return [[self delegate] respondsToSelector:@selector(cut:)];
return YES;
}
-(IBAction) copy:(id)aSender
{
if ([[self delegate] respondsToSelector:@selector(copy:)])
[[self delegate] copy:aSender];
}
-(IBAction) paste:(id)aSender
{
if ([[self delegate] respondsToSelector:@selector(paste:)])
[[self delegate] paste:aSender];
}
-(IBAction) delete:(id)aSender
{
if ([[self delegate] respondsToSelector:@selector(delete:)])
[[self delegate] delete:aSender];
}
-(IBAction) cut:(id)aSender
{
if ([[self delegate] respondsToSelector:@selector(cut:)])
[[self delegate] cut:aSender];
}
@end

Просмотреть файл

@ -20,6 +20,7 @@
*
* Contributor(s):
* Simon Fraser <sfraser@netscape.com>
* Bruce Davidson <Bruce.Davidson@ipl.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@ -41,11 +42,17 @@ extern NSString* const kCorePasteboardFlavorType_url;
extern NSString* const kCorePasteboardFlavorType_urln;
extern NSString* const kCorePasteboardFlavorType_urld;
extern NSString* const kCaminoBookmarkListPBoardType;
extern NSString* const kWebURLsWithTitlesPboardType;
@interface NSPasteboard(ChimeraPasteboardURLUtils)
- (int)declareURLPasteboardWithAdditionalTypes:(NSArray*)additionalTypes owner:(id)newOwner;
- (void)setDataForURL:(NSString*)url title:(NSString*)title;
- (int) declareURLPasteboardWithAdditionalTypes:(NSArray*)additionalTypes owner:(id)newOwner;
- (void) setDataForURL:(NSString*)url title:(NSString*)title;
- (void) setURLs:(NSArray*)inUrls withTitles:(NSArray*)inTitles;
- (void) getURLs:(NSArray**)outUrls andTitles:(NSArray**)outTitles;
- (BOOL) containsURLData;
@end

Просмотреть файл

@ -20,6 +20,7 @@
*
* Contributor(s):
* Simon Fraser <sfraser@netscape.com>
* Bruce Davidson <Bruce.Davidson@ipl.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@ -41,13 +42,16 @@ NSString* const kCorePasteboardFlavorType_url = @"CorePasteboardFlavorType 0x75
NSString* const kCorePasteboardFlavorType_urln = @"CorePasteboardFlavorType 0x75726C6E"; // 'urln' title
NSString* const kCorePasteboardFlavorType_urld = @"CorePasteboardFlavorType 0x75726C64"; // 'urld' URL description
NSString* const kCaminoBookmarkListPBoardType = @"MozBookmarkType"; // list of Camino bookmark UIDs
NSString* const kWebURLsWithTitlesPboardType = @"WebURLsWithTitlesPboardType"; // Safari-compatible URL + title arrays
@implementation NSPasteboard(ChimeraPasteboardURLUtils)
- (int)declareURLPasteboardWithAdditionalTypes:(NSArray*)additionalTypes owner:(id)newOwner
{
NSArray* allTypes = [additionalTypes arrayByAddingObjectsFromArray:
[NSArray arrayWithObjects:
@"MozURLType",
kWebURLsWithTitlesPboardType,
NSURLPboardType,
NSStringPboardType,
kCorePasteboardFlavorType_url,
@ -56,24 +60,125 @@ NSString* const kCorePasteboardFlavorType_urld = @"CorePasteboardFlavorType 0x75
return [self declareTypes:allTypes owner:newOwner];
}
//
// Copy a single URL (with an optional title) to the clipboard in all relevant
// formats. Convinience methods for clients that can only ever deal with one
// URL and shouldn't have to build up the arrays for setURLs:withTitles:.
//
- (void)setDataForURL:(NSString*)url title:(NSString*)title
{
NSDictionary *data = [NSDictionary dictionaryWithObjectsAndKeys:
url, @"url",
title, @"title",
nil];
[self setPropertyList:data forType: @"MozURLType"];
[[NSURL URLWithString:url] writeToPasteboard: self];
[self setString:url forType: NSStringPboardType];
const char* tempCString = [url UTF8String];
[self setData:[NSData dataWithBytes:tempCString length:strlen(tempCString)] forType: kCorePasteboardFlavorType_url];
NSArray* urlList = [NSArray arrayWithObject:url];
NSArray* titleList = nil;
if (title)
tempCString = [title UTF8String];
[self setData:[NSData dataWithBytes:tempCString length:strlen(tempCString)] forType: kCorePasteboardFlavorType_urln];
titleList = [NSArray arrayWithObject:title];
[self setURLs:urlList withTitles:titleList];
}
//
// Copy a set of URLs, each of which may have a title, to the pasteboard
// using all the available formats.
// The title array should be nil, or must have the same length as the URL array.
//
- (void) setURLs:(NSArray*)inUrls withTitles:(NSArray*)inTitles
{
// Best format that we know about is Safari's URL + title arrays - build these up
NSMutableArray* tmpTitleArray = inTitles;
if (!inTitles) {
tmpTitleArray = [NSMutableArray array];
for ( unsigned int i = 0; i < [inUrls count]; ++i )
[tmpTitleArray addObject:@""];
}
NSMutableArray* clipboardData = [NSMutableArray array];
[clipboardData addObject:[NSArray arrayWithArray:inUrls]];
[clipboardData addObject:tmpTitleArray];
[self setPropertyList:clipboardData forType:kWebURLsWithTitlesPboardType];
if ([inUrls count] == 1) {
NSString* title = @"";
if (inTitles)
title = [inTitles objectAtIndex:0];
NSString* url = [inUrls objectAtIndex:0];
[[NSURL URLWithString:url] writeToPasteboard: self];
[self setString:url forType: NSStringPboardType];
const char* tempCString = [url UTF8String];
[self setData:[NSData dataWithBytes:tempCString length:strlen(tempCString)] forType: kCorePasteboardFlavorType_url];
if (inTitles)
tempCString = [title UTF8String];
[self setData:[NSData dataWithBytes:tempCString length:strlen(tempCString)] forType: kCorePasteboardFlavorType_urln];
} else {
// With multiple URLs there aren't many other formats we can use
// Just write a string of each URL (ignoring titles) on a separate line
[self setString:[inUrls componentsJoinedByString:@"\n"] forType:NSStringPboardType];
}
}
//
// Get the set of URLs and their corresponding titles from the clipboards
// If there are no URLs in a format we understand on the pasteboard empty
// arrays will be returned. The two arrays will always be the same size.
// The arrays returned are on the auto release pool.
//
- (void) getURLs:(NSArray**)outUrls andTitles:(NSArray**)outTitles
{
NSArray* types = [self types];
if ([types containsObject:kWebURLsWithTitlesPboardType]) {
NSArray* urlAndTitleContainer = [self propertyListForType:kWebURLsWithTitlesPboardType];
*outUrls = [urlAndTitleContainer objectAtIndex:0];
*outTitles = [urlAndTitleContainer objectAtIndex:1];
} else if ([types containsObject:NSURLPboardType]) {
*outUrls = [NSArray arrayWithObject:[NSURL URLFromPasteboard:self]];
if ([types containsObject:kCorePasteboardFlavorType_urld])
*outTitles = [NSArray arrayWithObject:[self stringForType:kCorePasteboardFlavorType_urld]];
else
*outTitles = [NSArray arrayWithObject:@""];
} else if ([types containsObject:NSStringPboardType]) {
NSURL* testURL = [NSURL URLWithString:[self stringForType:NSStringPboardType]];
if (testURL) {
*outUrls = [NSArray arrayWithObject:[self stringForType:NSStringPboardType]];
if ([types containsObject:kCorePasteboardFlavorType_urld])
*outTitles = [NSArray arrayWithObject:[self stringForType:kCorePasteboardFlavorType_urld]];
else
*outTitles = [NSArray arrayWithObject:@""];
} else {
// The string doesn't look like a URL - return empty arrays
*outUrls = [NSArray array];
*outTitles = [NSArray array];
}
} else {
// We don't recognise any of these formats - return empty arrays
*outUrls = [NSArray array];
*outTitles = [NSArray array];
}
}
//
// Indicates if this pasteboard contains URL data that we understand
// Deals with all our URL formats. Only strings that are valid URLs count.
// If this returns YES it is safe to use getURLs:andTitles: to retrieve the data.
//
// NB: Does not consider our internal bookmark list format, because callers
// usually need to deal with this separately because it can include folders etc.
//
- (BOOL) containsURLData
{
NSArray* types = [self types];
if ( [types containsObject:kWebURLsWithTitlesPboardType]
|| [types containsObject:NSURLPboardType] )
return YES;
if ([types containsObject:NSStringPboardType]) {
NSURL* testURL = [NSURL URLWithString:[self stringForType:NSStringPboardType]];
return (testURL != nil) && ([[testURL scheme] length] > 0);
}
return NO;
}
@end