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:
Родитель
5c40815762
Коммит
7f428391f2
|
@ -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
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче