зеркало из https://github.com/mozilla/gecko-dev.git
Fix a slew of bookmark dnd bugs in the sidebar and personal toolbar. (bug 143094)
This commit is contained in:
Родитель
c82c7b9aae
Коммит
6552d49b49
|
@ -45,6 +45,7 @@
|
|||
#import "CHBookmarksToolbar.h"
|
||||
#import "CHExtendedOutlineView.h"
|
||||
|
||||
@class BookmarkItem;
|
||||
class BookmarksService;
|
||||
class nsIAtom;
|
||||
|
||||
|
@ -93,6 +94,10 @@ class nsIAtom;
|
|||
- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item;
|
||||
- (void)outlineView:(NSOutlineView *)outlineView setObjectValue:(id)object forTableColumn:(NSTableColumn *)tableColumn byItem:(id)item;
|
||||
|
||||
- (BOOL)outlineView:(NSOutlineView *)ov writeItems:(NSArray*)items toPasteboard:(NSPasteboard*)pboard;
|
||||
- (NSDragOperation)outlineView:(NSOutlineView*)ov validateDrop:(id <NSDraggingInfo>)info proposedItem:(id)item proposedChildIndex:(int)index;
|
||||
- (BOOL)outlineView:(NSOutlineView*)ov acceptDrop:(id <NSDraggingInfo>)info item:(id)item childIndex:(int)index;
|
||||
|
||||
- (void)reloadDataForItem:(id)item reloadChildren: (BOOL)aReloadChildren;
|
||||
|
||||
// Delegate methods
|
||||
|
@ -106,8 +111,9 @@ class nsIAtom;
|
|||
nsIContent* mContentNode;
|
||||
}
|
||||
|
||||
-(nsIContent*)contentNode;
|
||||
-(void)setContentNode: (nsIContent*)aContentNode;
|
||||
- (nsIContent*)contentNode;
|
||||
- (void)setContentNode: (nsIContent*)aContentNode;
|
||||
- (NSNumber*)contentID;
|
||||
- (id)copyWithZone:(NSZone *)aZone;
|
||||
@end
|
||||
|
||||
|
@ -123,9 +129,9 @@ public:
|
|||
void AddObserver();
|
||||
void RemoveObserver();
|
||||
|
||||
static void BookmarkAdded(nsIContent* aContainer, nsIContent* aChild);
|
||||
static void BookmarkChanged(nsIContent* aItem);
|
||||
static void BookmarkRemoved(nsIContent* aContainer, nsIContent* aChild);
|
||||
static void BookmarkAdded(nsIContent* aContainer, nsIContent* aChild, bool shouldFlush = true);
|
||||
static void BookmarkChanged(nsIContent* aItem, bool shouldFlush = true);
|
||||
static void BookmarkRemoved(nsIContent* aContainer, nsIContent* aChild, bool shouldFlush = true);
|
||||
|
||||
static void AddBookmarkToFolder(nsString& aURL, nsString& aTitle, nsIDOMElement* aFolder, nsIDOMElement* aBeforeElt);
|
||||
static void MoveBookmarkToFolder(nsIDOMElement* aBookmark, nsIDOMElement* aFolder, nsIDOMElement* aBeforeElt);
|
||||
|
@ -133,7 +139,9 @@ public:
|
|||
|
||||
public:
|
||||
static void GetRootContent(nsIContent** aResult);
|
||||
static BookmarkItem* GetRootItem();
|
||||
static BookmarkItem* GetWrapperFor(nsIContent* aItem);
|
||||
static BookmarkItem* GetWrapperFor(PRUint32 contentID);
|
||||
static void FlushBookmarks();
|
||||
|
||||
static void ConstructBookmarksMenu(NSMenu* aMenu, nsIContent* aContent);
|
||||
|
@ -153,10 +161,12 @@ public:
|
|||
static NSString* ResolveKeyword(NSString* aKeyword);
|
||||
|
||||
static NSImage* CreateIconForBookmark(nsIDOMElement* aElement);
|
||||
|
||||
static BOOL DoAncestorsIncludeNode(BookmarkItem* bookmark, BookmarkItem* searchItem);
|
||||
static bool IsBookmarkDropValid(BookmarkItem* proposedParent, int index, NSArray* draggedIDs);
|
||||
static bool PerformBookmarkDrop(BookmarkItem* parent, int index, NSArray* draggedIDs);
|
||||
|
||||
static void DragBookmark(nsIDOMElement* aElement, NSView* aView, NSEvent* aEvent);
|
||||
static void CompleteBookmarkDrag(NSPasteboard* aPasteboard, nsIDOMElement* aFolderElt, nsIDOMElement* aBeforeElt, int aPosition);
|
||||
|
||||
static void DropURL(NSString* title, NSURL* url, BookmarkItem* parent, int index);
|
||||
|
||||
public:
|
||||
// Global counter and pointers to our singletons.
|
||||
|
|
|
@ -182,11 +182,11 @@
|
|||
NSPopUpButton* popup = [mBrowserWindowController getAddBookmarkFolder];
|
||||
BookmarksService::ConstructAddBookmarkFolderList(popup, item);
|
||||
|
||||
[NSApp beginSheet: [mBrowserWindowController getAddBookmarkSheetWindow]
|
||||
modalForWindow: [mBrowserWindowController window]
|
||||
modalDelegate: nil //self
|
||||
didEndSelector: nil //@selector(sheetDidEnd:)
|
||||
contextInfo: nil];
|
||||
[NSApp beginSheet: [mBrowserWindowController getAddBookmarkSheetWindow]
|
||||
modalForWindow: [mBrowserWindowController window]
|
||||
modalDelegate: nil //self
|
||||
didEndSelector: nil //@selector(sheetDidEnd:)
|
||||
contextInfo: nil];
|
||||
}
|
||||
|
||||
-(void)endAddBookmark: (int)aCode
|
||||
|
@ -299,10 +299,10 @@
|
|||
int count = [itemsToDelete count];
|
||||
for (int i = 0; i < count; i++) {
|
||||
BookmarkItem* item = [itemsToDelete objectAtIndex: i];
|
||||
[self deleteBookmark: item];
|
||||
[self deleteBookmark: item];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-(void)deleteBookmark:(id)aItem
|
||||
{
|
||||
|
@ -346,7 +346,7 @@
|
|||
content->GetAttr(kNameSpaceID_None, BookmarksService::gHrefAtom, href);
|
||||
if (!href.IsEmpty()) {
|
||||
NSString* url = [NSString stringWithCharacters: href.get() length: href.Length()];
|
||||
[[[mBrowserWindowController getBrowserWrapper] getBrowserView] loadURI:[NSURL URLWithString: url] flags: NSLoadFlagsNone];
|
||||
[[[mBrowserWindowController getBrowserWrapper] getBrowserView] loadURI:[NSURL URLWithString: url] flags: NSLoadFlagsNone];
|
||||
// Focus and activate our content area.
|
||||
[[[mBrowserWindowController getBrowserWrapper] getBrowserView] setActive: YES];
|
||||
}
|
||||
|
@ -367,7 +367,7 @@
|
|||
//
|
||||
- (BOOL)outlineView:(NSOutlineView *)outlineView shouldEditTableColumn:(NSTableColumn *)tableColumn item:(id)item
|
||||
{
|
||||
return NO;
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (id)outlineView:(NSOutlineView *)outlineView child:(int)index ofItem:(id)item
|
||||
|
@ -436,12 +436,12 @@
|
|||
|
||||
- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item
|
||||
{
|
||||
NSString *columnName = [tableColumn identifier];
|
||||
NSMutableAttributedString *cellValue = [[NSMutableAttributedString alloc] init];
|
||||
NSFileWrapper *fileWrapper = [[NSFileWrapper alloc] initRegularFileWithContents:nil];
|
||||
NSTextAttachment *textAttachment = [[NSTextAttachment alloc] initWithFileWrapper:fileWrapper];
|
||||
NSMutableAttributedString *attachmentAttrString = nil;
|
||||
NSCell *attachmentAttrStringCell;
|
||||
NSString *columnName = [tableColumn identifier];
|
||||
NSMutableAttributedString *cellValue = [[NSMutableAttributedString alloc] init];
|
||||
NSFileWrapper *fileWrapper = [[NSFileWrapper alloc] initRegularFileWithContents:nil];
|
||||
NSTextAttachment *textAttachment = [[NSTextAttachment alloc] initWithFileWrapper:fileWrapper];
|
||||
NSMutableAttributedString *attachmentAttrString = nil;
|
||||
NSCell *attachmentAttrStringCell;
|
||||
|
||||
if ([columnName isEqualToString: @"name"]) {
|
||||
nsIContent* content = [item contentNode];
|
||||
|
@ -449,8 +449,7 @@
|
|||
content->GetAttr(kNameSpaceID_None, BookmarksService::gNameAtom, nameAttr);
|
||||
|
||||
//Set cell's textual contents
|
||||
[cellValue replaceCharactersInRange:NSMakeRange(0, [cellValue length])
|
||||
withString:[NSString stringWithCharacters: nameAttr.get() length: nameAttr.Length()]];
|
||||
[cellValue replaceCharactersInRange:NSMakeRange(0, [cellValue length]) withString:[NSString stringWithCharacters: nameAttr.get() length: nameAttr.Length()]];
|
||||
|
||||
//Create an attributed string to hold the empty attachment, then release the components.
|
||||
attachmentAttrString = [[NSMutableAttributedString attributedStringWithAttachment:textAttachment] retain];
|
||||
|
@ -458,9 +457,7 @@
|
|||
[fileWrapper release];
|
||||
|
||||
//Get the cell of the text attachment.
|
||||
attachmentAttrStringCell = (NSCell *)[(NSTextAttachment *)[attachmentAttrString attribute:NSAttachmentAttributeName
|
||||
atIndex:0
|
||||
effectiveRange:nil] attachmentCell];
|
||||
attachmentAttrStringCell = (NSCell *)[(NSTextAttachment *)[attachmentAttrString attribute:NSAttachmentAttributeName atIndex:0 effectiveRange:nil] attachmentCell];
|
||||
//Figure out which image to add, and set the cell's image.
|
||||
// Use the bookmark groups image for groups.
|
||||
if ([self outlineView:outlineView isItemExpandable:item]) {
|
||||
|
@ -521,73 +518,97 @@
|
|||
#endif
|
||||
}
|
||||
|
||||
- (void)reloadDataForItem:(id)item reloadChildren: (BOOL)aReloadChildren
|
||||
{
|
||||
printf("Reloading?\n");
|
||||
if (!item)
|
||||
[mOutlineView reloadData];
|
||||
else if ([mOutlineView isItemExpanded: item])
|
||||
[mOutlineView reloadItem: item reloadChildren: aReloadChildren];
|
||||
}
|
||||
|
||||
- (BOOL)outlineView:(NSOutlineView*)outlineView acceptDrop:(id <NSDraggingInfo>)info item:(id)item childIndex:(int)index
|
||||
- (BOOL)outlineView:(NSOutlineView *)ov writeItems:(NSArray*)items toPasteboard:(NSPasteboard*)pboard
|
||||
{
|
||||
BookmarkItem* beforeItem = nil;
|
||||
nsCOMPtr<nsIDOMElement> beforeElt;
|
||||
nsCOMPtr<nsIDOMElement> folderElt;
|
||||
nsCOMPtr<nsIContent> folderContent;
|
||||
|
||||
if (index == NSOutlineViewDropOnItemIndex)
|
||||
if (!mBookmarks || [mOutlineView selectedRow] == -1) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
#ifdef FILTER_DESCENDANT_ON_DRAG
|
||||
NSArray *toDrag = BookmarksService::FilterOutDescendantsForDrag(items);
|
||||
#else
|
||||
NSArray *toDrag = items;
|
||||
#endif
|
||||
int count = [toDrag count];
|
||||
if (count > 0) {
|
||||
// Create Pasteboard Data
|
||||
NSMutableArray *draggedID = [NSMutableArray arrayWithCapacity: count];
|
||||
for (int i = 0; i < count; i++)
|
||||
[draggedID addObject: [[toDrag objectAtIndex: i] contentID]];
|
||||
[pboard declareTypes: [NSArray arrayWithObject: @"MozBookmarkType"] owner: self];
|
||||
[pboard setPropertyList: draggedID forType: @"MozBookmarkType"];
|
||||
return YES;
|
||||
}
|
||||
|
||||
// get the folder element
|
||||
if (!item)
|
||||
mBookmarks->GetRootContent(getter_AddRefs(folderContent));
|
||||
else
|
||||
folderContent = [item contentNode];
|
||||
folderElt = do_QueryInterface(folderContent);
|
||||
|
||||
// get the element to insert before, if there is one
|
||||
PRInt32 childCount = 0;
|
||||
folderContent->ChildCount(childCount);
|
||||
if (index < childCount)
|
||||
beforeItem = [[outlineView dataSource] outlineView:outlineView child:index ofItem:item];
|
||||
if (beforeItem)
|
||||
beforeElt = do_QueryInterface([beforeItem contentNode]);
|
||||
|
||||
// insert the dragged stuff into bookmarks
|
||||
BookmarksService::CompleteBookmarkDrag([info draggingPasteboard], folderElt, beforeElt,
|
||||
BookmarksService::CHInsertBefore);
|
||||
|
||||
return YES;
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (NSDragOperation)outlineView:(NSOutlineView*)outlineView validateDrop:(id <NSDraggingInfo>)info proposedItem:(id)item proposedChildIndex:(int)index
|
||||
|
||||
- (NSDragOperation)outlineView:(NSOutlineView*)ov validateDrop:(id <NSDraggingInfo>)info proposedItem:(id)item proposedChildIndex:(int)index
|
||||
{
|
||||
NSArray* types = [[info draggingPasteboard] types];
|
||||
|
||||
// if the index is -1, deny the drop
|
||||
if (index == NSOutlineViewDropOnItemIndex)
|
||||
return NSDragOperationNone;
|
||||
|
||||
return NSDragOperationGeneric;
|
||||
}
|
||||
|
||||
- (BOOL)outlineView:(NSOutlineView *)outlineView writeItems:(NSArray*)items toPasteboard:(NSPasteboard*)pboard
|
||||
{
|
||||
NSMutableArray* contentIds = [NSMutableArray array];
|
||||
|
||||
for (unsigned int i = 0; i < [items count]; ++i) {
|
||||
nsCOMPtr<nsIContent> content = [[items objectAtIndex:i] contentNode];
|
||||
PRUint32 contentId;
|
||||
content->GetContentID(&contentId);
|
||||
[contentIds addObject:[NSNumber numberWithInt:contentId]];
|
||||
if ([types containsObject: @"MozBookmarkType"]) {
|
||||
NSArray *draggedIDs = [[info draggingPasteboard] propertyListForType: @"MozBookmarkType"];
|
||||
BookmarkItem* parent;
|
||||
parent = (item) ? item : BookmarksService::GetRootItem();
|
||||
return (BookmarksService::IsBookmarkDropValid(parent, index, draggedIDs)) ? NSDragOperationGeneric : NSDragOperationNone;
|
||||
} else if ([types containsObject: @"MozURLType"]) {
|
||||
return NSDragOperationGeneric;
|
||||
}
|
||||
|
||||
[pboard declareTypes:[NSArray arrayWithObject:@"MozBookmarkType"] owner:outlineView];
|
||||
[pboard setPropertyList:contentIds forType:@"MozBookmarkType"];
|
||||
|
||||
return YES;
|
||||
return NSDragOperationNone;
|
||||
}
|
||||
|
||||
- (BOOL)outlineView:(NSOutlineView*)ov acceptDrop:(id <NSDraggingInfo>)info item:(id)item childIndex:(int)index {
|
||||
NSArray *types = [[info draggingPasteboard] types];
|
||||
BookmarkItem* parent = (item) ? item : BookmarksService::GetRootItem();
|
||||
|
||||
if ([types containsObject: @"MozBookmarkType"]) {
|
||||
NSArray *draggedItems = [[info draggingPasteboard] propertyListForType: @"MozBookmarkType"];
|
||||
BookmarksService::PerformBookmarkDrop(parent, index, draggedItems);
|
||||
return YES;
|
||||
} else if ([types containsObject: @"MozURLType"]) {
|
||||
NSDictionary* data = [[info draggingPasteboard] propertyListForType: @"MozURLType"];
|
||||
nsCOMPtr<nsIDOMElement> parentElt;
|
||||
parentElt = do_QueryInterface([parent contentNode]);
|
||||
|
||||
PRInt32 childCount = 0;
|
||||
[item contentNode]->ChildCount(childCount);
|
||||
|
||||
if (index >= childCount)
|
||||
return NO;
|
||||
|
||||
BookmarkItem* beforeItem;
|
||||
beforeItem = [[ov dataSource] outlineView:ov child:index ofItem:item];
|
||||
|
||||
if (!beforeItem)
|
||||
return NO;
|
||||
|
||||
nsCOMPtr<nsIDOMElement> beforeElt;
|
||||
beforeElt = do_QueryInterface([beforeItem contentNode]);
|
||||
|
||||
nsAutoString url; url.AssignWithConversion([[data objectForKey:@"url"] cString]);
|
||||
nsAutoString title; title.AssignWithConversion([[data objectForKey:@"title"] cString]);
|
||||
BookmarksService::AddBookmarkToFolder(url, title, parentElt, beforeElt);
|
||||
return YES;
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void)reloadDataForItem:(id)item reloadChildren: (BOOL)aReloadChildren
|
||||
{
|
||||
if (!item)
|
||||
[mOutlineView reloadData];
|
||||
else if ([mOutlineView isItemExpanded: item])
|
||||
[mOutlineView reloadItem: item reloadChildren: aReloadChildren];
|
||||
}
|
||||
|
||||
-(IBAction)openBookmarkInNewTab:(id)aSender
|
||||
{
|
||||
|
@ -711,19 +732,36 @@
|
|||
@implementation BookmarkItem
|
||||
-(nsIContent*)contentNode
|
||||
{
|
||||
return mContentNode;
|
||||
return mContentNode;
|
||||
}
|
||||
|
||||
- (NSNumber*)contentID
|
||||
{
|
||||
PRUint32 contentID = 0;
|
||||
mContentNode->GetContentID(&contentID);
|
||||
return [NSNumber numberWithInt: contentID];
|
||||
}
|
||||
|
||||
- (NSString *)description
|
||||
{
|
||||
nsCOMPtr<nsIContent> item = [self contentNode];
|
||||
nsCOMPtr<nsIDOMElement> element(do_QueryInterface(item));
|
||||
nsAutoString href;
|
||||
element->GetAttribute(NS_LITERAL_STRING("name"), href);
|
||||
NSString* info = [NSString stringWithCharacters: href.get() length: href.Length()];
|
||||
return [NSString stringWithFormat:@"<BookmarkItem, name = \"%@\">", info];
|
||||
}
|
||||
|
||||
-(void)setContentNode: (nsIContent*)aContentNode
|
||||
{
|
||||
mContentNode = aContentNode;
|
||||
mContentNode = aContentNode;
|
||||
}
|
||||
|
||||
- (id)copyWithZone:(NSZone *)aZone
|
||||
{
|
||||
BookmarkItem* copy = [[[self class] allocWithZone: aZone] init];
|
||||
[copy setContentNode: mContentNode];
|
||||
return copy;
|
||||
BookmarkItem* copy = [[[self class] allocWithZone: aZone] init];
|
||||
[copy setContentNode: mContentNode];
|
||||
return copy;
|
||||
}
|
||||
|
||||
@end
|
||||
|
@ -732,25 +770,26 @@
|
|||
static void
|
||||
StripWhitespaceNodes(nsIContent* aElement)
|
||||
{
|
||||
PRInt32 childCount;
|
||||
aElement->ChildCount(childCount);
|
||||
for (PRInt32 i = 0; i < childCount; i++) {
|
||||
nsCOMPtr<nsIContent> child;
|
||||
aElement->ChildAt(i, *getter_AddRefs(child));
|
||||
nsCOMPtr<nsITextContent> text = do_QueryInterface(child);
|
||||
if (text) {
|
||||
PRBool isEmpty;
|
||||
text->IsOnlyWhitespace(&isEmpty);
|
||||
if (isEmpty) {
|
||||
// This node contained nothing but whitespace.
|
||||
// Remove it from the content model.
|
||||
aElement->RemoveChildAt(i, PR_TRUE);
|
||||
i--; // Decrement our count, since we just removed this child.
|
||||
childCount--; // Also decrement our total count.
|
||||
}
|
||||
}
|
||||
else StripWhitespaceNodes(child);
|
||||
PRInt32 childCount = 0;
|
||||
aElement->ChildCount(childCount);
|
||||
for (PRInt32 i = 0; i < childCount; i++) {
|
||||
nsCOMPtr<nsIContent> child;
|
||||
aElement->ChildAt(i, *getter_AddRefs(child));
|
||||
nsCOMPtr<nsITextContent> text = do_QueryInterface(child);
|
||||
if (text) {
|
||||
PRBool isEmpty = PR_FALSE;
|
||||
text->IsOnlyWhitespace(&isEmpty);
|
||||
if (isEmpty) {
|
||||
// This node contained nothing but whitespace.
|
||||
// Remove it from the content model.
|
||||
aElement->RemoveChildAt(i, PR_TRUE);
|
||||
i--; // Decrement our count, since we just removed this child.
|
||||
childCount--; // Also decrement our total count.
|
||||
}
|
||||
}
|
||||
else
|
||||
StripWhitespaceNodes(child);
|
||||
}
|
||||
}
|
||||
|
||||
PRUint32 BookmarksService::gRefCnt = 0;
|
||||
|
@ -792,34 +831,50 @@ BookmarksService::~BookmarksService()
|
|||
void
|
||||
BookmarksService::GetRootContent(nsIContent** aResult)
|
||||
{
|
||||
*aResult = nsnull;
|
||||
if (gBookmarks) {
|
||||
nsCOMPtr<nsIDOMElement> elt;
|
||||
nsCOMPtr<nsIDOMDocument> domDoc(do_QueryInterface(gBookmarks));
|
||||
domDoc->GetDocumentElement(getter_AddRefs(elt));
|
||||
elt->QueryInterface(NS_GET_IID(nsIContent), (void**)aResult); // Addref happens here.
|
||||
}
|
||||
*aResult = nsnull;
|
||||
if (gBookmarks) {
|
||||
nsCOMPtr<nsIDOMDocument> domDoc(do_QueryInterface(gBookmarks));
|
||||
if (!domDoc) return;
|
||||
|
||||
nsCOMPtr<nsIDOMElement> elt;
|
||||
domDoc->GetDocumentElement(getter_AddRefs(elt));
|
||||
if (elt)
|
||||
elt->QueryInterface(NS_GET_IID(nsIContent), (void**)aResult); // Addref happens here.
|
||||
}
|
||||
}
|
||||
|
||||
BookmarkItem*
|
||||
BookmarksService::GetRootItem() {
|
||||
nsCOMPtr<nsIContent> rootContent;
|
||||
BookmarksService::GetRootContent(getter_AddRefs(rootContent));
|
||||
BookmarkItem* rootItem = BookmarksService::GetWrapperFor(rootContent);
|
||||
return rootItem;
|
||||
}
|
||||
|
||||
BookmarkItem*
|
||||
BookmarksService::GetWrapperFor(nsIContent* aContent)
|
||||
{
|
||||
if (!gDictionary)
|
||||
gDictionary = [[NSMutableDictionary alloc] initWithCapacity: 30];
|
||||
|
||||
PRUint32 contentID;
|
||||
aContent->GetContentID(&contentID);
|
||||
|
||||
BookmarkItem* item = [gDictionary objectForKey: [NSNumber numberWithInt: contentID]];
|
||||
if (item)
|
||||
return item;
|
||||
else {
|
||||
// Create an item.
|
||||
item = [[[BookmarkItem alloc] init] autorelease]; // The dictionary retains us.
|
||||
[item setContentNode: aContent];
|
||||
[gDictionary setObject: item forKey: [NSNumber numberWithInt: contentID]];
|
||||
}
|
||||
if (!gDictionary)
|
||||
gDictionary = [[NSMutableDictionary alloc] initWithCapacity: 30];
|
||||
|
||||
PRUint32 contentID = 0;
|
||||
aContent->GetContentID(&contentID);
|
||||
|
||||
BookmarkItem* item = [gDictionary objectForKey: [NSNumber numberWithInt: contentID]];
|
||||
if (item)
|
||||
return item;
|
||||
|
||||
// Create an item.
|
||||
item = [[[BookmarkItem alloc] init] autorelease]; // The dictionary retains us.
|
||||
[item setContentNode: aContent];
|
||||
[gDictionary setObject: item forKey: [NSNumber numberWithInt: contentID]];
|
||||
return item;
|
||||
}
|
||||
|
||||
BookmarkItem*
|
||||
BookmarksService::GetWrapperFor(PRUint32 contentID) {
|
||||
BookmarkItem* item = [gDictionary objectForKey: [NSNumber numberWithUnsignedInt: contentID]];
|
||||
return item;
|
||||
}
|
||||
|
||||
NSMenu*
|
||||
|
@ -841,7 +896,7 @@ BookmarksService::LocateMenu(nsIContent* aContent)
|
|||
}
|
||||
|
||||
void
|
||||
BookmarksService::BookmarkAdded(nsIContent* aContainer, nsIContent* aChild)
|
||||
BookmarksService::BookmarkAdded(nsIContent* aContainer, nsIContent* aChild, bool shouldFlush = true)
|
||||
{
|
||||
if (!gInstances || !gDictionary)
|
||||
return;
|
||||
|
@ -883,11 +938,12 @@ BookmarksService::BookmarkAdded(nsIContent* aContainer, nsIContent* aChild)
|
|||
}
|
||||
}
|
||||
|
||||
FlushBookmarks();
|
||||
if (shouldFlush)
|
||||
FlushBookmarks();
|
||||
}
|
||||
|
||||
void
|
||||
BookmarksService::BookmarkChanged(nsIContent* aItem)
|
||||
BookmarksService::BookmarkChanged(nsIContent* aItem, bool shouldFlush = true)
|
||||
{
|
||||
if (!gInstances || !gDictionary)
|
||||
return;
|
||||
|
@ -902,11 +958,12 @@ BookmarksService::BookmarkChanged(nsIContent* aItem)
|
|||
}
|
||||
}
|
||||
|
||||
FlushBookmarks();
|
||||
if (shouldFlush)
|
||||
FlushBookmarks();
|
||||
}
|
||||
|
||||
void
|
||||
BookmarksService::BookmarkRemoved(nsIContent* aContainer, nsIContent* aChild)
|
||||
BookmarksService::BookmarkRemoved(nsIContent* aContainer, nsIContent* aChild, bool shouldFlush = true)
|
||||
{
|
||||
if (!gInstances)
|
||||
return;
|
||||
|
@ -940,14 +997,15 @@ BookmarksService::BookmarkRemoved(nsIContent* aContainer, nsIContent* aChild)
|
|||
else {
|
||||
// We're the menu.
|
||||
NSMenu* menu = LocateMenu(aContainer);
|
||||
PRUint32 contentID;
|
||||
PRUint32 contentID = 0;
|
||||
aChild->GetContentID(&contentID);
|
||||
NSMenuItem* childItem = [menu itemWithTag: contentID];
|
||||
[menu removeItem: childItem];
|
||||
}
|
||||
}
|
||||
|
||||
FlushBookmarks();
|
||||
if (shouldFlush)
|
||||
FlushBookmarks();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -969,7 +1027,7 @@ BookmarksService::AddObserver()
|
|||
NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(profileDir));
|
||||
profileDir->Append(NS_LITERAL_STRING("bookmarks.xml"));
|
||||
|
||||
PRBool fileExists;
|
||||
PRBool fileExists = PR_FALSE;
|
||||
profileDir->Exists(&fileExists);
|
||||
|
||||
// If the bookmarks file does not exist, copy from the defaults so we don't
|
||||
|
@ -1119,9 +1177,10 @@ BookmarksService::FlushBookmarks()
|
|||
nsCOMPtr<nsIOutputStream> outputStream;
|
||||
NS_NewLocalFileOutputStream(getter_AddRefs(outputStream), bookmarksFile);
|
||||
|
||||
nsCOMPtr<nsIDOMDocument> domDoc(do_QueryInterface(gBookmarks));
|
||||
|
||||
nsCOMPtr<nsIDOMSerializer> domSerializer(do_CreateInstance(NS_XMLSERIALIZER_CONTRACTID));
|
||||
nsCOMPtr<nsIDOMDocument> domDoc(do_QueryInterface(gBookmarks));
|
||||
|
||||
nsCOMPtr<nsIDOMSerializer> domSerializer(do_CreateInstance(NS_XMLSERIALIZER_CONTRACTID));
|
||||
if (domSerializer)
|
||||
domSerializer->SerializeToStream(domDoc, outputStream, nsnull);
|
||||
}
|
||||
|
||||
|
@ -1592,63 +1651,160 @@ BookmarksService::CreateIconForBookmark(nsIDOMElement* aElement)
|
|||
return [NSImage imageNamed:@"groupbookmark"];
|
||||
}
|
||||
|
||||
void
|
||||
BookmarksService::DragBookmark(nsIDOMElement* aElement, NSView* aView, NSEvent* aEvent)
|
||||
{
|
||||
NSPasteboard *pboard;
|
||||
NSString* title;
|
||||
// Is searchItem equal to bookmark or bookmark's parent, grandparent, etc?
|
||||
BOOL
|
||||
BookmarksService::DoAncestorsIncludeNode(BookmarkItem* bookmark, BookmarkItem* searchItem) {
|
||||
nsCOMPtr<nsIContent> search = [searchItem contentNode];
|
||||
nsCOMPtr<nsIContent> current = [bookmark contentNode];
|
||||
nsCOMPtr<nsIContent> root;
|
||||
GetRootContent(getter_AddRefs(root));
|
||||
|
||||
// If the search item is the root node, return yes immediatly
|
||||
if (search == root)
|
||||
return YES;
|
||||
|
||||
// for each ancestor
|
||||
while (current) {
|
||||
// If this is the root node we can't search farther, and there was no match
|
||||
if (current == root)
|
||||
return NO;
|
||||
|
||||
// If the two nodes match, then the search term is an ancestor of the given bookmark
|
||||
if (search == current)
|
||||
return YES;
|
||||
|
||||
// If a match wasn't found, set up the next node to compare
|
||||
nsCOMPtr<nsIContent> oldCurrent = current;
|
||||
oldCurrent->GetParent(*getter_AddRefs(current));
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(aElement);
|
||||
PRUint32 contentId;
|
||||
content->GetContentID(&contentId);
|
||||
|
||||
pboard = [NSPasteboard pasteboardWithName:NSDragPboard];
|
||||
[pboard declareTypes:[NSArray arrayWithObject:@"MozBookmarkType"] owner:aView];
|
||||
[pboard setPropertyList:[NSArray arrayWithObject:[NSNumber numberWithInt:contentId]] forType:@"MozBookmarkType"];
|
||||
|
||||
nsAutoString nameStr;
|
||||
aElement->GetAttribute(NS_LITERAL_STRING("name"), nameStr);
|
||||
title = [NSString stringWithCharacters: nameStr.get() length: nameStr.Length()];
|
||||
|
||||
[aView dragImage: [MainController createImageForDragging: CreateIconForBookmark(aElement) title:title]
|
||||
at:NSMakePoint(0,0) offset:NSMakeSize(0,0)
|
||||
event:aEvent pasteboard:pboard source:aView slideBack:YES];
|
||||
return NO;
|
||||
}
|
||||
|
||||
void
|
||||
BookmarksService::CompleteBookmarkDrag(NSPasteboard* aPasteboard, nsIDOMElement* aFolderElt,
|
||||
nsIDOMElement* aBeforeElt, int aPosition)
|
||||
|
||||
#ifdef FILTER_DESCENDANT_ON_DRAG
|
||||
/*
|
||||
this has been disabled because it is too slow, and can cause a large
|
||||
delay when the user is dragging lots of items. this needs to get
|
||||
fixed someday.
|
||||
|
||||
It should filter out every node whose parent is also being dragged.
|
||||
*/
|
||||
|
||||
NSArray*
|
||||
BookmarksService::FilterOutDescendantsForDrag(NSArray* nodes)
|
||||
{
|
||||
NSArray* contentIds;
|
||||
|
||||
nsCOMPtr<nsIDOMElement> beforeElt = aBeforeElt;
|
||||
if (aPosition == BookmarksService::CHInsertAfter && aBeforeElt) {
|
||||
nsCOMPtr<nsIDOMNode> beforeNode;
|
||||
aBeforeElt->GetNextSibling(getter_AddRefs(beforeNode));
|
||||
beforeElt = do_QueryInterface(beforeNode);
|
||||
}
|
||||
|
||||
if (aPosition == BookmarksService::CHInsertInto) {
|
||||
aFolderElt = aBeforeElt;
|
||||
beforeElt = nsnull;
|
||||
}
|
||||
NSMutableArray *toDrag = [NSMutableArray arrayWithArray: nodes];
|
||||
unsigned int i = 0;
|
||||
|
||||
while (i < [toDrag count]) {
|
||||
BookmarkItem* item = [toDrag objectAtIndex: i];
|
||||
bool matchFound = false;
|
||||
|
||||
// check for recognized drag types
|
||||
contentIds = [aPasteboard propertyListForType: @"MozBookmarkType"];
|
||||
if (contentIds) {
|
||||
// drag type is chimera bookmarks
|
||||
for (unsigned int i = 0; i < [contentIds count]; ++i) {
|
||||
BookmarkItem* item = [gDictionary objectForKey: [contentIds objectAtIndex:i]];
|
||||
nsCOMPtr<nsIDOMElement> bookmarkElt = do_QueryInterface([item contentNode]);
|
||||
MoveBookmarkToFolder(bookmarkElt, aFolderElt, beforeElt);
|
||||
for (unsigned int j = 0; j < [toDrag count] && matchFound == NO; j++) {
|
||||
if (i != j) // Don't compare to self, will always match
|
||||
matchFound = BookmarksService::DoAncestorsIncludeNode(item, [toDrag objectAtIndex: j]);
|
||||
}
|
||||
} else {
|
||||
// add bookmark for chimera url type
|
||||
NSDictionary* data = [aPasteboard propertyListForType: @"MozURLType"];
|
||||
nsAutoString url; url.AssignWithConversion([[data objectForKey:@"url"] cString]);
|
||||
nsAutoString title; title.AssignWithConversion([[data objectForKey:@"title"] cString]);
|
||||
|
||||
AddBookmarkToFolder(url, title, aFolderElt, beforeElt);
|
||||
// if a match was found, remove the node from the array
|
||||
if (matchFound)
|
||||
[toDrag removeObjectAtIndex: i];
|
||||
else
|
||||
i++;
|
||||
}
|
||||
|
||||
return toDrag;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool
|
||||
BookmarksService::IsBookmarkDropValid(BookmarkItem* proposedParent, int index, NSArray* draggedIDs) {
|
||||
NSMutableArray *draggedItems = [NSMutableArray arrayWithCapacity: [draggedIDs count]];
|
||||
BOOL toolbarRootMoving = NO;
|
||||
|
||||
for (unsigned int i = 0; i < [draggedIDs count]; i++) {
|
||||
NSNumber* contentID = [draggedIDs objectAtIndex: i];
|
||||
BookmarkItem* bookmarkItem = BookmarksService::GetWrapperFor([contentID unsignedIntValue]);
|
||||
nsCOMPtr<nsIContent> itemContent = [bookmarkItem contentNode];
|
||||
nsCOMPtr<nsIDOMElement> itemElement(do_QueryInterface(itemContent));
|
||||
|
||||
if (itemElement == BookmarksService::gToolbarRoot)
|
||||
toolbarRootMoving = YES;
|
||||
|
||||
if (bookmarkItem)
|
||||
[draggedItems addObject: bookmarkItem];
|
||||
}
|
||||
|
||||
// If we are being dropped into the top level, allow it
|
||||
if ([proposedParent contentNode] == [BookmarksService::GetRootItem() contentNode])
|
||||
return true;
|
||||
|
||||
// If we are not being dropped on the top level, and the toolbar root is being moved, disallow
|
||||
if (toolbarRootMoving)
|
||||
return false;
|
||||
|
||||
// Make sure that we are not being dropped into one of our own children
|
||||
// If the proposed parent, or any of it's ancestors matches one of the nodes being dragged
|
||||
// then deny the drag.
|
||||
|
||||
for (unsigned int i = 0; i < [draggedItems count]; i++) {
|
||||
if (BookmarksService::DoAncestorsIncludeNode(proposedParent, [draggedItems objectAtIndex: i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BookmarksService::PerformBookmarkDrop(BookmarkItem* parent, int index, NSArray* draggedIDs) {
|
||||
NSEnumerator *enumerator = [draggedIDs reverseObjectEnumerator];
|
||||
NSNumber *contentID;
|
||||
|
||||
// for each item being dragged
|
||||
while ( (contentID = [enumerator nextObject]) ) {
|
||||
|
||||
// get dragged node
|
||||
nsCOMPtr<nsIContent> draggedNode = [GetWrapperFor([contentID unsignedIntValue]) contentNode];
|
||||
|
||||
// get the dragged nodes parent
|
||||
nsCOMPtr<nsIContent> draggedParent;
|
||||
if (draggedNode)
|
||||
draggedNode->GetParent(*getter_AddRefs(draggedParent));
|
||||
|
||||
// get the proposed parent
|
||||
nsCOMPtr<nsIContent> proposedParent = [parent contentNode];
|
||||
|
||||
PRInt32 existingIndex = 0;
|
||||
if (draggedParent)
|
||||
draggedParent->IndexOf(draggedNode, existingIndex);
|
||||
|
||||
// if the deleted nodes parent and the proposed parents are equal
|
||||
// and if the deleted point is eariler in the list than the inserted point
|
||||
if (proposedParent == draggedParent && existingIndex < index) {
|
||||
index--; // if so, move the inserted point up one to compensate
|
||||
}
|
||||
|
||||
// remove it from the tree
|
||||
if (draggedParent)
|
||||
draggedParent->RemoveChildAt(existingIndex, PR_TRUE);
|
||||
BookmarkRemoved(draggedParent, draggedNode, false);
|
||||
|
||||
// insert into new position
|
||||
if (proposedParent)
|
||||
proposedParent->InsertChildAt(draggedNode, index, PR_TRUE, PR_TRUE);
|
||||
BookmarkAdded(proposedParent, draggedNode, false);
|
||||
}
|
||||
|
||||
FlushBookmarks();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
BookmarksService::DropURL(NSString* title, NSURL* url, BookmarkItem* parent, int index)
|
||||
{
|
||||
NSLog(@"DropURL not implemented yet\n");
|
||||
}
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
if ( (self = [super initWithFrame:frame]) ) {
|
||||
mElement = nsnull;
|
||||
[self setBezelStyle: NSRegularSquareBezelStyle];
|
||||
[self setButtonType: NSMomentaryChangeButton];
|
||||
[self setBordered: NO];
|
||||
[self setImagePosition: NSImageLeft];
|
||||
[self setRefusesFirstResponder: YES];
|
||||
|
@ -138,7 +139,11 @@
|
|||
// XXX mouseDragged is never called because buttons cancel dragging while you mouse down
|
||||
// I have to fix this in an ugly way, by doing the "click" stuff myself and never relying
|
||||
// on the superclass for that. Bah!
|
||||
BookmarksService::DragBookmark(mElement, self, aEvent);
|
||||
|
||||
// perhaps you could just implement mouseUp to perform the action (which should be the case
|
||||
// things shouldn't happen on mouse down) Then does mouseDragged get overridden?
|
||||
|
||||
// BookmarksService::DragBookmark(mElement, self, aEvent);
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
if (operation == NSDragOperationDelete) {
|
||||
NSArray* contentIds = nil;
|
||||
NSPasteboard* pboard = [NSPasteboard pasteboardWithName:NSDragPboard];
|
||||
contentIds = [pboard propertyListForType:@"MozBookmarkType"];
|
||||
contentIds = [pboard propertyListForType: @"MozBookmarkType"];
|
||||
if (contentIds) {
|
||||
for (unsigned int i = 0; i < [contentIds count]; ++i) {
|
||||
BookmarkItem* item = [BookmarksService::gDictionary objectForKey: [contentIds objectAtIndex:i]];
|
||||
|
|
|
@ -309,18 +309,82 @@
|
|||
|
||||
- (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender
|
||||
{
|
||||
return YES;
|
||||
BookmarkItem* parent;
|
||||
int index = 0;
|
||||
NSArray *draggedItems = [[sender draggingPasteboard] propertyListForType: @"MozBookmarkType"];
|
||||
|
||||
// If we are dropping into a folder
|
||||
if (mDragInsertionPosition == BookmarksService::CHInsertInto) {
|
||||
nsCOMPtr<nsIDOMElement> parentElt = [mDragInsertionButton element];
|
||||
nsCOMPtr<nsIContent> parentContent(do_QueryInterface(parentElt));
|
||||
parent = BookmarksService::GetWrapperFor(parentContent);
|
||||
index = 0;
|
||||
}
|
||||
|
||||
// If we are dropping onto the toolbar directly
|
||||
else if (mDragInsertionPosition == BookmarksService::CHInsertBefore ||
|
||||
mDragInsertionPosition == BookmarksService::CHInsertAfter) {
|
||||
nsCOMPtr<nsIDOMElement> rootElt = BookmarksService::gToolbarRoot;
|
||||
nsCOMPtr<nsIContent> rootContent(do_QueryInterface(rootElt));
|
||||
parent = BookmarksService::GetWrapperFor(rootContent);
|
||||
index = [mButtons indexOfObject: mDragInsertionButton];
|
||||
if (index == NSNotFound)
|
||||
rootContent->ChildCount(index);
|
||||
else if (mDragInsertionPosition == BookmarksService::CHInsertAfter)
|
||||
index++;
|
||||
} else {
|
||||
mDragInsertionButton = nil;
|
||||
mDragInsertionPosition = BookmarksService::CHInsertNone;
|
||||
[self setNeedsDisplay:YES];
|
||||
return NO;
|
||||
}
|
||||
|
||||
bool valid = BookmarksService::IsBookmarkDropValid(parent, index, draggedItems);
|
||||
if (!valid) {
|
||||
mDragInsertionButton = nil;
|
||||
mDragInsertionPosition = BookmarksService::CHInsertNone;
|
||||
[self setNeedsDisplay:YES];
|
||||
}
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
||||
- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
|
||||
{
|
||||
BookmarksService::CompleteBookmarkDrag([sender draggingPasteboard], BookmarksService::gToolbarRoot,
|
||||
mDragInsertionButton ? [mDragInsertionButton element] : nil,
|
||||
mDragInsertionPosition);
|
||||
|
||||
BookmarkItem* parent;
|
||||
int index = 0;
|
||||
NSArray *draggedItems = [[sender draggingPasteboard] propertyListForType: @"MozBookmarkType"];
|
||||
|
||||
// If we are dropping into a folder
|
||||
if (mDragInsertionPosition == BookmarksService::CHInsertInto) {
|
||||
nsCOMPtr<nsIDOMElement> parentElt = [mDragInsertionButton element];
|
||||
nsCOMPtr<nsIContent> parentContent(do_QueryInterface(parentElt));
|
||||
parent = BookmarksService::GetWrapperFor(parentContent);
|
||||
index = 0;
|
||||
}
|
||||
|
||||
// If we are dropping onto the toolbar directly
|
||||
else if (mDragInsertionPosition == BookmarksService::CHInsertBefore ||
|
||||
mDragInsertionPosition == BookmarksService::CHInsertAfter) {
|
||||
nsCOMPtr<nsIDOMElement> rootElt = BookmarksService::gToolbarRoot;
|
||||
nsCOMPtr<nsIContent> rootContent(do_QueryInterface(rootElt));
|
||||
parent = BookmarksService::GetWrapperFor(rootContent);
|
||||
index = [mButtons indexOfObject: mDragInsertionButton];
|
||||
if (index == NSNotFound)
|
||||
rootContent->ChildCount(index);
|
||||
else if (mDragInsertionPosition == BookmarksService::CHInsertAfter)
|
||||
index++;
|
||||
} else {
|
||||
mDragInsertionButton = nil;
|
||||
mDragInsertionPosition = BookmarksService::CHInsertNone;
|
||||
[self setNeedsDisplay:YES];
|
||||
return NO;
|
||||
}
|
||||
|
||||
BookmarksService::PerformBookmarkDrop(parent, index, draggedItems);
|
||||
|
||||
mDragInsertionButton = nil;
|
||||
mDragInsertionPosition = BookmarksService::CHInsertNone;
|
||||
|
||||
[self setNeedsDisplay:YES];
|
||||
|
||||
return YES;
|
||||
|
@ -329,14 +393,11 @@
|
|||
- (NSRect)insertionRectForButton:(NSView*)aButton position:(int) aPosition
|
||||
{
|
||||
if (aPosition == BookmarksService::CHInsertInto) {
|
||||
return NSMakeRect([aButton frame].origin.x, [aButton frame].origin.y,
|
||||
[aButton frame].size.width, [aButton frame].size.height);
|
||||
return NSMakeRect([aButton frame].origin.x, [aButton frame].origin.y, [aButton frame].size.width, [aButton frame].size.height);
|
||||
} else if (aPosition == BookmarksService::CHInsertAfter) {
|
||||
return NSMakeRect([aButton frame].origin.x+[aButton frame].size.width, [aButton frame].origin.y,
|
||||
2, [aButton frame].size.height);
|
||||
return NSMakeRect([aButton frame].origin.x+[aButton frame].size.width, [aButton frame].origin.y, 2, [aButton frame].size.height);
|
||||
} else {// if (aPosition == BookmarksService::CHInsertBefore) {
|
||||
return NSMakeRect([aButton frame].origin.x - 2, [aButton frame].origin.y,
|
||||
2, [aButton frame].size.height);
|
||||
return NSMakeRect([aButton frame].origin.x - 2, [aButton frame].origin.y, 2, [aButton frame].size.height);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -104,7 +104,7 @@ static void FindOptionWithContentID(nsIDOMHTMLSelectElement* aSel, PRUint32 aID,
|
|||
|
||||
-(id)initWithSelect:(nsIDOMHTMLSelectElement*)aSel
|
||||
{
|
||||
if (self = [super init]) {
|
||||
if ( (self = [super init]) ) {
|
||||
mSelectElt = aSel;
|
||||
}
|
||||
return self;
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
if ( (self = [super initWithFrame:frame]) ) {
|
||||
mElement = nsnull;
|
||||
[self setBezelStyle: NSRegularSquareBezelStyle];
|
||||
[self setButtonType: NSMomentaryChangeButton];
|
||||
[self setBordered: NO];
|
||||
[self setImagePosition: NSImageLeft];
|
||||
[self setRefusesFirstResponder: YES];
|
||||
|
@ -138,7 +139,11 @@
|
|||
// XXX mouseDragged is never called because buttons cancel dragging while you mouse down
|
||||
// I have to fix this in an ugly way, by doing the "click" stuff myself and never relying
|
||||
// on the superclass for that. Bah!
|
||||
BookmarksService::DragBookmark(mElement, self, aEvent);
|
||||
|
||||
// perhaps you could just implement mouseUp to perform the action (which should be the case
|
||||
// things shouldn't happen on mouse down) Then does mouseDragged get overridden?
|
||||
|
||||
// BookmarksService::DragBookmark(mElement, self, aEvent);
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
if (operation == NSDragOperationDelete) {
|
||||
NSArray* contentIds = nil;
|
||||
NSPasteboard* pboard = [NSPasteboard pasteboardWithName:NSDragPboard];
|
||||
contentIds = [pboard propertyListForType:@"MozBookmarkType"];
|
||||
contentIds = [pboard propertyListForType: @"MozBookmarkType"];
|
||||
if (contentIds) {
|
||||
for (unsigned int i = 0; i < [contentIds count]; ++i) {
|
||||
BookmarkItem* item = [BookmarksService::gDictionary objectForKey: [contentIds objectAtIndex:i]];
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#import "CHBookmarksToolbar.h"
|
||||
#import "CHExtendedOutlineView.h"
|
||||
|
||||
@class BookmarkItem;
|
||||
class BookmarksService;
|
||||
class nsIAtom;
|
||||
|
||||
|
@ -93,6 +94,10 @@ class nsIAtom;
|
|||
- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item;
|
||||
- (void)outlineView:(NSOutlineView *)outlineView setObjectValue:(id)object forTableColumn:(NSTableColumn *)tableColumn byItem:(id)item;
|
||||
|
||||
- (BOOL)outlineView:(NSOutlineView *)ov writeItems:(NSArray*)items toPasteboard:(NSPasteboard*)pboard;
|
||||
- (NSDragOperation)outlineView:(NSOutlineView*)ov validateDrop:(id <NSDraggingInfo>)info proposedItem:(id)item proposedChildIndex:(int)index;
|
||||
- (BOOL)outlineView:(NSOutlineView*)ov acceptDrop:(id <NSDraggingInfo>)info item:(id)item childIndex:(int)index;
|
||||
|
||||
- (void)reloadDataForItem:(id)item reloadChildren: (BOOL)aReloadChildren;
|
||||
|
||||
// Delegate methods
|
||||
|
@ -106,8 +111,9 @@ class nsIAtom;
|
|||
nsIContent* mContentNode;
|
||||
}
|
||||
|
||||
-(nsIContent*)contentNode;
|
||||
-(void)setContentNode: (nsIContent*)aContentNode;
|
||||
- (nsIContent*)contentNode;
|
||||
- (void)setContentNode: (nsIContent*)aContentNode;
|
||||
- (NSNumber*)contentID;
|
||||
- (id)copyWithZone:(NSZone *)aZone;
|
||||
@end
|
||||
|
||||
|
@ -123,9 +129,9 @@ public:
|
|||
void AddObserver();
|
||||
void RemoveObserver();
|
||||
|
||||
static void BookmarkAdded(nsIContent* aContainer, nsIContent* aChild);
|
||||
static void BookmarkChanged(nsIContent* aItem);
|
||||
static void BookmarkRemoved(nsIContent* aContainer, nsIContent* aChild);
|
||||
static void BookmarkAdded(nsIContent* aContainer, nsIContent* aChild, bool shouldFlush = true);
|
||||
static void BookmarkChanged(nsIContent* aItem, bool shouldFlush = true);
|
||||
static void BookmarkRemoved(nsIContent* aContainer, nsIContent* aChild, bool shouldFlush = true);
|
||||
|
||||
static void AddBookmarkToFolder(nsString& aURL, nsString& aTitle, nsIDOMElement* aFolder, nsIDOMElement* aBeforeElt);
|
||||
static void MoveBookmarkToFolder(nsIDOMElement* aBookmark, nsIDOMElement* aFolder, nsIDOMElement* aBeforeElt);
|
||||
|
@ -133,7 +139,9 @@ public:
|
|||
|
||||
public:
|
||||
static void GetRootContent(nsIContent** aResult);
|
||||
static BookmarkItem* GetRootItem();
|
||||
static BookmarkItem* GetWrapperFor(nsIContent* aItem);
|
||||
static BookmarkItem* GetWrapperFor(PRUint32 contentID);
|
||||
static void FlushBookmarks();
|
||||
|
||||
static void ConstructBookmarksMenu(NSMenu* aMenu, nsIContent* aContent);
|
||||
|
@ -153,10 +161,12 @@ public:
|
|||
static NSString* ResolveKeyword(NSString* aKeyword);
|
||||
|
||||
static NSImage* CreateIconForBookmark(nsIDOMElement* aElement);
|
||||
|
||||
static BOOL DoAncestorsIncludeNode(BookmarkItem* bookmark, BookmarkItem* searchItem);
|
||||
static bool IsBookmarkDropValid(BookmarkItem* proposedParent, int index, NSArray* draggedIDs);
|
||||
static bool PerformBookmarkDrop(BookmarkItem* parent, int index, NSArray* draggedIDs);
|
||||
|
||||
static void DragBookmark(nsIDOMElement* aElement, NSView* aView, NSEvent* aEvent);
|
||||
static void CompleteBookmarkDrag(NSPasteboard* aPasteboard, nsIDOMElement* aFolderElt, nsIDOMElement* aBeforeElt, int aPosition);
|
||||
|
||||
static void DropURL(NSString* title, NSURL* url, BookmarkItem* parent, int index);
|
||||
|
||||
public:
|
||||
// Global counter and pointers to our singletons.
|
||||
|
|
|
@ -182,11 +182,11 @@
|
|||
NSPopUpButton* popup = [mBrowserWindowController getAddBookmarkFolder];
|
||||
BookmarksService::ConstructAddBookmarkFolderList(popup, item);
|
||||
|
||||
[NSApp beginSheet: [mBrowserWindowController getAddBookmarkSheetWindow]
|
||||
modalForWindow: [mBrowserWindowController window]
|
||||
modalDelegate: nil //self
|
||||
didEndSelector: nil //@selector(sheetDidEnd:)
|
||||
contextInfo: nil];
|
||||
[NSApp beginSheet: [mBrowserWindowController getAddBookmarkSheetWindow]
|
||||
modalForWindow: [mBrowserWindowController window]
|
||||
modalDelegate: nil //self
|
||||
didEndSelector: nil //@selector(sheetDidEnd:)
|
||||
contextInfo: nil];
|
||||
}
|
||||
|
||||
-(void)endAddBookmark: (int)aCode
|
||||
|
@ -299,10 +299,10 @@
|
|||
int count = [itemsToDelete count];
|
||||
for (int i = 0; i < count; i++) {
|
||||
BookmarkItem* item = [itemsToDelete objectAtIndex: i];
|
||||
[self deleteBookmark: item];
|
||||
[self deleteBookmark: item];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-(void)deleteBookmark:(id)aItem
|
||||
{
|
||||
|
@ -346,7 +346,7 @@
|
|||
content->GetAttr(kNameSpaceID_None, BookmarksService::gHrefAtom, href);
|
||||
if (!href.IsEmpty()) {
|
||||
NSString* url = [NSString stringWithCharacters: href.get() length: href.Length()];
|
||||
[[[mBrowserWindowController getBrowserWrapper] getBrowserView] loadURI:[NSURL URLWithString: url] flags: NSLoadFlagsNone];
|
||||
[[[mBrowserWindowController getBrowserWrapper] getBrowserView] loadURI:[NSURL URLWithString: url] flags: NSLoadFlagsNone];
|
||||
// Focus and activate our content area.
|
||||
[[[mBrowserWindowController getBrowserWrapper] getBrowserView] setActive: YES];
|
||||
}
|
||||
|
@ -367,7 +367,7 @@
|
|||
//
|
||||
- (BOOL)outlineView:(NSOutlineView *)outlineView shouldEditTableColumn:(NSTableColumn *)tableColumn item:(id)item
|
||||
{
|
||||
return NO;
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (id)outlineView:(NSOutlineView *)outlineView child:(int)index ofItem:(id)item
|
||||
|
@ -436,12 +436,12 @@
|
|||
|
||||
- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item
|
||||
{
|
||||
NSString *columnName = [tableColumn identifier];
|
||||
NSMutableAttributedString *cellValue = [[NSMutableAttributedString alloc] init];
|
||||
NSFileWrapper *fileWrapper = [[NSFileWrapper alloc] initRegularFileWithContents:nil];
|
||||
NSTextAttachment *textAttachment = [[NSTextAttachment alloc] initWithFileWrapper:fileWrapper];
|
||||
NSMutableAttributedString *attachmentAttrString = nil;
|
||||
NSCell *attachmentAttrStringCell;
|
||||
NSString *columnName = [tableColumn identifier];
|
||||
NSMutableAttributedString *cellValue = [[NSMutableAttributedString alloc] init];
|
||||
NSFileWrapper *fileWrapper = [[NSFileWrapper alloc] initRegularFileWithContents:nil];
|
||||
NSTextAttachment *textAttachment = [[NSTextAttachment alloc] initWithFileWrapper:fileWrapper];
|
||||
NSMutableAttributedString *attachmentAttrString = nil;
|
||||
NSCell *attachmentAttrStringCell;
|
||||
|
||||
if ([columnName isEqualToString: @"name"]) {
|
||||
nsIContent* content = [item contentNode];
|
||||
|
@ -449,8 +449,7 @@
|
|||
content->GetAttr(kNameSpaceID_None, BookmarksService::gNameAtom, nameAttr);
|
||||
|
||||
//Set cell's textual contents
|
||||
[cellValue replaceCharactersInRange:NSMakeRange(0, [cellValue length])
|
||||
withString:[NSString stringWithCharacters: nameAttr.get() length: nameAttr.Length()]];
|
||||
[cellValue replaceCharactersInRange:NSMakeRange(0, [cellValue length]) withString:[NSString stringWithCharacters: nameAttr.get() length: nameAttr.Length()]];
|
||||
|
||||
//Create an attributed string to hold the empty attachment, then release the components.
|
||||
attachmentAttrString = [[NSMutableAttributedString attributedStringWithAttachment:textAttachment] retain];
|
||||
|
@ -458,9 +457,7 @@
|
|||
[fileWrapper release];
|
||||
|
||||
//Get the cell of the text attachment.
|
||||
attachmentAttrStringCell = (NSCell *)[(NSTextAttachment *)[attachmentAttrString attribute:NSAttachmentAttributeName
|
||||
atIndex:0
|
||||
effectiveRange:nil] attachmentCell];
|
||||
attachmentAttrStringCell = (NSCell *)[(NSTextAttachment *)[attachmentAttrString attribute:NSAttachmentAttributeName atIndex:0 effectiveRange:nil] attachmentCell];
|
||||
//Figure out which image to add, and set the cell's image.
|
||||
// Use the bookmark groups image for groups.
|
||||
if ([self outlineView:outlineView isItemExpandable:item]) {
|
||||
|
@ -521,73 +518,97 @@
|
|||
#endif
|
||||
}
|
||||
|
||||
- (void)reloadDataForItem:(id)item reloadChildren: (BOOL)aReloadChildren
|
||||
{
|
||||
printf("Reloading?\n");
|
||||
if (!item)
|
||||
[mOutlineView reloadData];
|
||||
else if ([mOutlineView isItemExpanded: item])
|
||||
[mOutlineView reloadItem: item reloadChildren: aReloadChildren];
|
||||
}
|
||||
|
||||
- (BOOL)outlineView:(NSOutlineView*)outlineView acceptDrop:(id <NSDraggingInfo>)info item:(id)item childIndex:(int)index
|
||||
- (BOOL)outlineView:(NSOutlineView *)ov writeItems:(NSArray*)items toPasteboard:(NSPasteboard*)pboard
|
||||
{
|
||||
BookmarkItem* beforeItem = nil;
|
||||
nsCOMPtr<nsIDOMElement> beforeElt;
|
||||
nsCOMPtr<nsIDOMElement> folderElt;
|
||||
nsCOMPtr<nsIContent> folderContent;
|
||||
|
||||
if (index == NSOutlineViewDropOnItemIndex)
|
||||
if (!mBookmarks || [mOutlineView selectedRow] == -1) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
#ifdef FILTER_DESCENDANT_ON_DRAG
|
||||
NSArray *toDrag = BookmarksService::FilterOutDescendantsForDrag(items);
|
||||
#else
|
||||
NSArray *toDrag = items;
|
||||
#endif
|
||||
int count = [toDrag count];
|
||||
if (count > 0) {
|
||||
// Create Pasteboard Data
|
||||
NSMutableArray *draggedID = [NSMutableArray arrayWithCapacity: count];
|
||||
for (int i = 0; i < count; i++)
|
||||
[draggedID addObject: [[toDrag objectAtIndex: i] contentID]];
|
||||
[pboard declareTypes: [NSArray arrayWithObject: @"MozBookmarkType"] owner: self];
|
||||
[pboard setPropertyList: draggedID forType: @"MozBookmarkType"];
|
||||
return YES;
|
||||
}
|
||||
|
||||
// get the folder element
|
||||
if (!item)
|
||||
mBookmarks->GetRootContent(getter_AddRefs(folderContent));
|
||||
else
|
||||
folderContent = [item contentNode];
|
||||
folderElt = do_QueryInterface(folderContent);
|
||||
|
||||
// get the element to insert before, if there is one
|
||||
PRInt32 childCount = 0;
|
||||
folderContent->ChildCount(childCount);
|
||||
if (index < childCount)
|
||||
beforeItem = [[outlineView dataSource] outlineView:outlineView child:index ofItem:item];
|
||||
if (beforeItem)
|
||||
beforeElt = do_QueryInterface([beforeItem contentNode]);
|
||||
|
||||
// insert the dragged stuff into bookmarks
|
||||
BookmarksService::CompleteBookmarkDrag([info draggingPasteboard], folderElt, beforeElt,
|
||||
BookmarksService::CHInsertBefore);
|
||||
|
||||
return YES;
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (NSDragOperation)outlineView:(NSOutlineView*)outlineView validateDrop:(id <NSDraggingInfo>)info proposedItem:(id)item proposedChildIndex:(int)index
|
||||
|
||||
- (NSDragOperation)outlineView:(NSOutlineView*)ov validateDrop:(id <NSDraggingInfo>)info proposedItem:(id)item proposedChildIndex:(int)index
|
||||
{
|
||||
NSArray* types = [[info draggingPasteboard] types];
|
||||
|
||||
// if the index is -1, deny the drop
|
||||
if (index == NSOutlineViewDropOnItemIndex)
|
||||
return NSDragOperationNone;
|
||||
|
||||
return NSDragOperationGeneric;
|
||||
}
|
||||
|
||||
- (BOOL)outlineView:(NSOutlineView *)outlineView writeItems:(NSArray*)items toPasteboard:(NSPasteboard*)pboard
|
||||
{
|
||||
NSMutableArray* contentIds = [NSMutableArray array];
|
||||
|
||||
for (unsigned int i = 0; i < [items count]; ++i) {
|
||||
nsCOMPtr<nsIContent> content = [[items objectAtIndex:i] contentNode];
|
||||
PRUint32 contentId;
|
||||
content->GetContentID(&contentId);
|
||||
[contentIds addObject:[NSNumber numberWithInt:contentId]];
|
||||
if ([types containsObject: @"MozBookmarkType"]) {
|
||||
NSArray *draggedIDs = [[info draggingPasteboard] propertyListForType: @"MozBookmarkType"];
|
||||
BookmarkItem* parent;
|
||||
parent = (item) ? item : BookmarksService::GetRootItem();
|
||||
return (BookmarksService::IsBookmarkDropValid(parent, index, draggedIDs)) ? NSDragOperationGeneric : NSDragOperationNone;
|
||||
} else if ([types containsObject: @"MozURLType"]) {
|
||||
return NSDragOperationGeneric;
|
||||
}
|
||||
|
||||
[pboard declareTypes:[NSArray arrayWithObject:@"MozBookmarkType"] owner:outlineView];
|
||||
[pboard setPropertyList:contentIds forType:@"MozBookmarkType"];
|
||||
|
||||
return YES;
|
||||
return NSDragOperationNone;
|
||||
}
|
||||
|
||||
- (BOOL)outlineView:(NSOutlineView*)ov acceptDrop:(id <NSDraggingInfo>)info item:(id)item childIndex:(int)index {
|
||||
NSArray *types = [[info draggingPasteboard] types];
|
||||
BookmarkItem* parent = (item) ? item : BookmarksService::GetRootItem();
|
||||
|
||||
if ([types containsObject: @"MozBookmarkType"]) {
|
||||
NSArray *draggedItems = [[info draggingPasteboard] propertyListForType: @"MozBookmarkType"];
|
||||
BookmarksService::PerformBookmarkDrop(parent, index, draggedItems);
|
||||
return YES;
|
||||
} else if ([types containsObject: @"MozURLType"]) {
|
||||
NSDictionary* data = [[info draggingPasteboard] propertyListForType: @"MozURLType"];
|
||||
nsCOMPtr<nsIDOMElement> parentElt;
|
||||
parentElt = do_QueryInterface([parent contentNode]);
|
||||
|
||||
PRInt32 childCount = 0;
|
||||
[item contentNode]->ChildCount(childCount);
|
||||
|
||||
if (index >= childCount)
|
||||
return NO;
|
||||
|
||||
BookmarkItem* beforeItem;
|
||||
beforeItem = [[ov dataSource] outlineView:ov child:index ofItem:item];
|
||||
|
||||
if (!beforeItem)
|
||||
return NO;
|
||||
|
||||
nsCOMPtr<nsIDOMElement> beforeElt;
|
||||
beforeElt = do_QueryInterface([beforeItem contentNode]);
|
||||
|
||||
nsAutoString url; url.AssignWithConversion([[data objectForKey:@"url"] cString]);
|
||||
nsAutoString title; title.AssignWithConversion([[data objectForKey:@"title"] cString]);
|
||||
BookmarksService::AddBookmarkToFolder(url, title, parentElt, beforeElt);
|
||||
return YES;
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void)reloadDataForItem:(id)item reloadChildren: (BOOL)aReloadChildren
|
||||
{
|
||||
if (!item)
|
||||
[mOutlineView reloadData];
|
||||
else if ([mOutlineView isItemExpanded: item])
|
||||
[mOutlineView reloadItem: item reloadChildren: aReloadChildren];
|
||||
}
|
||||
|
||||
-(IBAction)openBookmarkInNewTab:(id)aSender
|
||||
{
|
||||
|
@ -711,19 +732,36 @@
|
|||
@implementation BookmarkItem
|
||||
-(nsIContent*)contentNode
|
||||
{
|
||||
return mContentNode;
|
||||
return mContentNode;
|
||||
}
|
||||
|
||||
- (NSNumber*)contentID
|
||||
{
|
||||
PRUint32 contentID = 0;
|
||||
mContentNode->GetContentID(&contentID);
|
||||
return [NSNumber numberWithInt: contentID];
|
||||
}
|
||||
|
||||
- (NSString *)description
|
||||
{
|
||||
nsCOMPtr<nsIContent> item = [self contentNode];
|
||||
nsCOMPtr<nsIDOMElement> element(do_QueryInterface(item));
|
||||
nsAutoString href;
|
||||
element->GetAttribute(NS_LITERAL_STRING("name"), href);
|
||||
NSString* info = [NSString stringWithCharacters: href.get() length: href.Length()];
|
||||
return [NSString stringWithFormat:@"<BookmarkItem, name = \"%@\">", info];
|
||||
}
|
||||
|
||||
-(void)setContentNode: (nsIContent*)aContentNode
|
||||
{
|
||||
mContentNode = aContentNode;
|
||||
mContentNode = aContentNode;
|
||||
}
|
||||
|
||||
- (id)copyWithZone:(NSZone *)aZone
|
||||
{
|
||||
BookmarkItem* copy = [[[self class] allocWithZone: aZone] init];
|
||||
[copy setContentNode: mContentNode];
|
||||
return copy;
|
||||
BookmarkItem* copy = [[[self class] allocWithZone: aZone] init];
|
||||
[copy setContentNode: mContentNode];
|
||||
return copy;
|
||||
}
|
||||
|
||||
@end
|
||||
|
@ -732,25 +770,26 @@
|
|||
static void
|
||||
StripWhitespaceNodes(nsIContent* aElement)
|
||||
{
|
||||
PRInt32 childCount;
|
||||
aElement->ChildCount(childCount);
|
||||
for (PRInt32 i = 0; i < childCount; i++) {
|
||||
nsCOMPtr<nsIContent> child;
|
||||
aElement->ChildAt(i, *getter_AddRefs(child));
|
||||
nsCOMPtr<nsITextContent> text = do_QueryInterface(child);
|
||||
if (text) {
|
||||
PRBool isEmpty;
|
||||
text->IsOnlyWhitespace(&isEmpty);
|
||||
if (isEmpty) {
|
||||
// This node contained nothing but whitespace.
|
||||
// Remove it from the content model.
|
||||
aElement->RemoveChildAt(i, PR_TRUE);
|
||||
i--; // Decrement our count, since we just removed this child.
|
||||
childCount--; // Also decrement our total count.
|
||||
}
|
||||
}
|
||||
else StripWhitespaceNodes(child);
|
||||
PRInt32 childCount = 0;
|
||||
aElement->ChildCount(childCount);
|
||||
for (PRInt32 i = 0; i < childCount; i++) {
|
||||
nsCOMPtr<nsIContent> child;
|
||||
aElement->ChildAt(i, *getter_AddRefs(child));
|
||||
nsCOMPtr<nsITextContent> text = do_QueryInterface(child);
|
||||
if (text) {
|
||||
PRBool isEmpty = PR_FALSE;
|
||||
text->IsOnlyWhitespace(&isEmpty);
|
||||
if (isEmpty) {
|
||||
// This node contained nothing but whitespace.
|
||||
// Remove it from the content model.
|
||||
aElement->RemoveChildAt(i, PR_TRUE);
|
||||
i--; // Decrement our count, since we just removed this child.
|
||||
childCount--; // Also decrement our total count.
|
||||
}
|
||||
}
|
||||
else
|
||||
StripWhitespaceNodes(child);
|
||||
}
|
||||
}
|
||||
|
||||
PRUint32 BookmarksService::gRefCnt = 0;
|
||||
|
@ -792,34 +831,50 @@ BookmarksService::~BookmarksService()
|
|||
void
|
||||
BookmarksService::GetRootContent(nsIContent** aResult)
|
||||
{
|
||||
*aResult = nsnull;
|
||||
if (gBookmarks) {
|
||||
nsCOMPtr<nsIDOMElement> elt;
|
||||
nsCOMPtr<nsIDOMDocument> domDoc(do_QueryInterface(gBookmarks));
|
||||
domDoc->GetDocumentElement(getter_AddRefs(elt));
|
||||
elt->QueryInterface(NS_GET_IID(nsIContent), (void**)aResult); // Addref happens here.
|
||||
}
|
||||
*aResult = nsnull;
|
||||
if (gBookmarks) {
|
||||
nsCOMPtr<nsIDOMDocument> domDoc(do_QueryInterface(gBookmarks));
|
||||
if (!domDoc) return;
|
||||
|
||||
nsCOMPtr<nsIDOMElement> elt;
|
||||
domDoc->GetDocumentElement(getter_AddRefs(elt));
|
||||
if (elt)
|
||||
elt->QueryInterface(NS_GET_IID(nsIContent), (void**)aResult); // Addref happens here.
|
||||
}
|
||||
}
|
||||
|
||||
BookmarkItem*
|
||||
BookmarksService::GetRootItem() {
|
||||
nsCOMPtr<nsIContent> rootContent;
|
||||
BookmarksService::GetRootContent(getter_AddRefs(rootContent));
|
||||
BookmarkItem* rootItem = BookmarksService::GetWrapperFor(rootContent);
|
||||
return rootItem;
|
||||
}
|
||||
|
||||
BookmarkItem*
|
||||
BookmarksService::GetWrapperFor(nsIContent* aContent)
|
||||
{
|
||||
if (!gDictionary)
|
||||
gDictionary = [[NSMutableDictionary alloc] initWithCapacity: 30];
|
||||
|
||||
PRUint32 contentID;
|
||||
aContent->GetContentID(&contentID);
|
||||
|
||||
BookmarkItem* item = [gDictionary objectForKey: [NSNumber numberWithInt: contentID]];
|
||||
if (item)
|
||||
return item;
|
||||
else {
|
||||
// Create an item.
|
||||
item = [[[BookmarkItem alloc] init] autorelease]; // The dictionary retains us.
|
||||
[item setContentNode: aContent];
|
||||
[gDictionary setObject: item forKey: [NSNumber numberWithInt: contentID]];
|
||||
}
|
||||
if (!gDictionary)
|
||||
gDictionary = [[NSMutableDictionary alloc] initWithCapacity: 30];
|
||||
|
||||
PRUint32 contentID = 0;
|
||||
aContent->GetContentID(&contentID);
|
||||
|
||||
BookmarkItem* item = [gDictionary objectForKey: [NSNumber numberWithInt: contentID]];
|
||||
if (item)
|
||||
return item;
|
||||
|
||||
// Create an item.
|
||||
item = [[[BookmarkItem alloc] init] autorelease]; // The dictionary retains us.
|
||||
[item setContentNode: aContent];
|
||||
[gDictionary setObject: item forKey: [NSNumber numberWithInt: contentID]];
|
||||
return item;
|
||||
}
|
||||
|
||||
BookmarkItem*
|
||||
BookmarksService::GetWrapperFor(PRUint32 contentID) {
|
||||
BookmarkItem* item = [gDictionary objectForKey: [NSNumber numberWithUnsignedInt: contentID]];
|
||||
return item;
|
||||
}
|
||||
|
||||
NSMenu*
|
||||
|
@ -841,7 +896,7 @@ BookmarksService::LocateMenu(nsIContent* aContent)
|
|||
}
|
||||
|
||||
void
|
||||
BookmarksService::BookmarkAdded(nsIContent* aContainer, nsIContent* aChild)
|
||||
BookmarksService::BookmarkAdded(nsIContent* aContainer, nsIContent* aChild, bool shouldFlush = true)
|
||||
{
|
||||
if (!gInstances || !gDictionary)
|
||||
return;
|
||||
|
@ -883,11 +938,12 @@ BookmarksService::BookmarkAdded(nsIContent* aContainer, nsIContent* aChild)
|
|||
}
|
||||
}
|
||||
|
||||
FlushBookmarks();
|
||||
if (shouldFlush)
|
||||
FlushBookmarks();
|
||||
}
|
||||
|
||||
void
|
||||
BookmarksService::BookmarkChanged(nsIContent* aItem)
|
||||
BookmarksService::BookmarkChanged(nsIContent* aItem, bool shouldFlush = true)
|
||||
{
|
||||
if (!gInstances || !gDictionary)
|
||||
return;
|
||||
|
@ -902,11 +958,12 @@ BookmarksService::BookmarkChanged(nsIContent* aItem)
|
|||
}
|
||||
}
|
||||
|
||||
FlushBookmarks();
|
||||
if (shouldFlush)
|
||||
FlushBookmarks();
|
||||
}
|
||||
|
||||
void
|
||||
BookmarksService::BookmarkRemoved(nsIContent* aContainer, nsIContent* aChild)
|
||||
BookmarksService::BookmarkRemoved(nsIContent* aContainer, nsIContent* aChild, bool shouldFlush = true)
|
||||
{
|
||||
if (!gInstances)
|
||||
return;
|
||||
|
@ -940,14 +997,15 @@ BookmarksService::BookmarkRemoved(nsIContent* aContainer, nsIContent* aChild)
|
|||
else {
|
||||
// We're the menu.
|
||||
NSMenu* menu = LocateMenu(aContainer);
|
||||
PRUint32 contentID;
|
||||
PRUint32 contentID = 0;
|
||||
aChild->GetContentID(&contentID);
|
||||
NSMenuItem* childItem = [menu itemWithTag: contentID];
|
||||
[menu removeItem: childItem];
|
||||
}
|
||||
}
|
||||
|
||||
FlushBookmarks();
|
||||
if (shouldFlush)
|
||||
FlushBookmarks();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -969,7 +1027,7 @@ BookmarksService::AddObserver()
|
|||
NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(profileDir));
|
||||
profileDir->Append(NS_LITERAL_STRING("bookmarks.xml"));
|
||||
|
||||
PRBool fileExists;
|
||||
PRBool fileExists = PR_FALSE;
|
||||
profileDir->Exists(&fileExists);
|
||||
|
||||
// If the bookmarks file does not exist, copy from the defaults so we don't
|
||||
|
@ -1119,9 +1177,10 @@ BookmarksService::FlushBookmarks()
|
|||
nsCOMPtr<nsIOutputStream> outputStream;
|
||||
NS_NewLocalFileOutputStream(getter_AddRefs(outputStream), bookmarksFile);
|
||||
|
||||
nsCOMPtr<nsIDOMDocument> domDoc(do_QueryInterface(gBookmarks));
|
||||
|
||||
nsCOMPtr<nsIDOMSerializer> domSerializer(do_CreateInstance(NS_XMLSERIALIZER_CONTRACTID));
|
||||
nsCOMPtr<nsIDOMDocument> domDoc(do_QueryInterface(gBookmarks));
|
||||
|
||||
nsCOMPtr<nsIDOMSerializer> domSerializer(do_CreateInstance(NS_XMLSERIALIZER_CONTRACTID));
|
||||
if (domSerializer)
|
||||
domSerializer->SerializeToStream(domDoc, outputStream, nsnull);
|
||||
}
|
||||
|
||||
|
@ -1592,63 +1651,160 @@ BookmarksService::CreateIconForBookmark(nsIDOMElement* aElement)
|
|||
return [NSImage imageNamed:@"groupbookmark"];
|
||||
}
|
||||
|
||||
void
|
||||
BookmarksService::DragBookmark(nsIDOMElement* aElement, NSView* aView, NSEvent* aEvent)
|
||||
{
|
||||
NSPasteboard *pboard;
|
||||
NSString* title;
|
||||
// Is searchItem equal to bookmark or bookmark's parent, grandparent, etc?
|
||||
BOOL
|
||||
BookmarksService::DoAncestorsIncludeNode(BookmarkItem* bookmark, BookmarkItem* searchItem) {
|
||||
nsCOMPtr<nsIContent> search = [searchItem contentNode];
|
||||
nsCOMPtr<nsIContent> current = [bookmark contentNode];
|
||||
nsCOMPtr<nsIContent> root;
|
||||
GetRootContent(getter_AddRefs(root));
|
||||
|
||||
// If the search item is the root node, return yes immediatly
|
||||
if (search == root)
|
||||
return YES;
|
||||
|
||||
// for each ancestor
|
||||
while (current) {
|
||||
// If this is the root node we can't search farther, and there was no match
|
||||
if (current == root)
|
||||
return NO;
|
||||
|
||||
// If the two nodes match, then the search term is an ancestor of the given bookmark
|
||||
if (search == current)
|
||||
return YES;
|
||||
|
||||
// If a match wasn't found, set up the next node to compare
|
||||
nsCOMPtr<nsIContent> oldCurrent = current;
|
||||
oldCurrent->GetParent(*getter_AddRefs(current));
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(aElement);
|
||||
PRUint32 contentId;
|
||||
content->GetContentID(&contentId);
|
||||
|
||||
pboard = [NSPasteboard pasteboardWithName:NSDragPboard];
|
||||
[pboard declareTypes:[NSArray arrayWithObject:@"MozBookmarkType"] owner:aView];
|
||||
[pboard setPropertyList:[NSArray arrayWithObject:[NSNumber numberWithInt:contentId]] forType:@"MozBookmarkType"];
|
||||
|
||||
nsAutoString nameStr;
|
||||
aElement->GetAttribute(NS_LITERAL_STRING("name"), nameStr);
|
||||
title = [NSString stringWithCharacters: nameStr.get() length: nameStr.Length()];
|
||||
|
||||
[aView dragImage: [MainController createImageForDragging: CreateIconForBookmark(aElement) title:title]
|
||||
at:NSMakePoint(0,0) offset:NSMakeSize(0,0)
|
||||
event:aEvent pasteboard:pboard source:aView slideBack:YES];
|
||||
return NO;
|
||||
}
|
||||
|
||||
void
|
||||
BookmarksService::CompleteBookmarkDrag(NSPasteboard* aPasteboard, nsIDOMElement* aFolderElt,
|
||||
nsIDOMElement* aBeforeElt, int aPosition)
|
||||
|
||||
#ifdef FILTER_DESCENDANT_ON_DRAG
|
||||
/*
|
||||
this has been disabled because it is too slow, and can cause a large
|
||||
delay when the user is dragging lots of items. this needs to get
|
||||
fixed someday.
|
||||
|
||||
It should filter out every node whose parent is also being dragged.
|
||||
*/
|
||||
|
||||
NSArray*
|
||||
BookmarksService::FilterOutDescendantsForDrag(NSArray* nodes)
|
||||
{
|
||||
NSArray* contentIds;
|
||||
|
||||
nsCOMPtr<nsIDOMElement> beforeElt = aBeforeElt;
|
||||
if (aPosition == BookmarksService::CHInsertAfter && aBeforeElt) {
|
||||
nsCOMPtr<nsIDOMNode> beforeNode;
|
||||
aBeforeElt->GetNextSibling(getter_AddRefs(beforeNode));
|
||||
beforeElt = do_QueryInterface(beforeNode);
|
||||
}
|
||||
|
||||
if (aPosition == BookmarksService::CHInsertInto) {
|
||||
aFolderElt = aBeforeElt;
|
||||
beforeElt = nsnull;
|
||||
}
|
||||
NSMutableArray *toDrag = [NSMutableArray arrayWithArray: nodes];
|
||||
unsigned int i = 0;
|
||||
|
||||
while (i < [toDrag count]) {
|
||||
BookmarkItem* item = [toDrag objectAtIndex: i];
|
||||
bool matchFound = false;
|
||||
|
||||
// check for recognized drag types
|
||||
contentIds = [aPasteboard propertyListForType: @"MozBookmarkType"];
|
||||
if (contentIds) {
|
||||
// drag type is chimera bookmarks
|
||||
for (unsigned int i = 0; i < [contentIds count]; ++i) {
|
||||
BookmarkItem* item = [gDictionary objectForKey: [contentIds objectAtIndex:i]];
|
||||
nsCOMPtr<nsIDOMElement> bookmarkElt = do_QueryInterface([item contentNode]);
|
||||
MoveBookmarkToFolder(bookmarkElt, aFolderElt, beforeElt);
|
||||
for (unsigned int j = 0; j < [toDrag count] && matchFound == NO; j++) {
|
||||
if (i != j) // Don't compare to self, will always match
|
||||
matchFound = BookmarksService::DoAncestorsIncludeNode(item, [toDrag objectAtIndex: j]);
|
||||
}
|
||||
} else {
|
||||
// add bookmark for chimera url type
|
||||
NSDictionary* data = [aPasteboard propertyListForType: @"MozURLType"];
|
||||
nsAutoString url; url.AssignWithConversion([[data objectForKey:@"url"] cString]);
|
||||
nsAutoString title; title.AssignWithConversion([[data objectForKey:@"title"] cString]);
|
||||
|
||||
AddBookmarkToFolder(url, title, aFolderElt, beforeElt);
|
||||
// if a match was found, remove the node from the array
|
||||
if (matchFound)
|
||||
[toDrag removeObjectAtIndex: i];
|
||||
else
|
||||
i++;
|
||||
}
|
||||
|
||||
return toDrag;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool
|
||||
BookmarksService::IsBookmarkDropValid(BookmarkItem* proposedParent, int index, NSArray* draggedIDs) {
|
||||
NSMutableArray *draggedItems = [NSMutableArray arrayWithCapacity: [draggedIDs count]];
|
||||
BOOL toolbarRootMoving = NO;
|
||||
|
||||
for (unsigned int i = 0; i < [draggedIDs count]; i++) {
|
||||
NSNumber* contentID = [draggedIDs objectAtIndex: i];
|
||||
BookmarkItem* bookmarkItem = BookmarksService::GetWrapperFor([contentID unsignedIntValue]);
|
||||
nsCOMPtr<nsIContent> itemContent = [bookmarkItem contentNode];
|
||||
nsCOMPtr<nsIDOMElement> itemElement(do_QueryInterface(itemContent));
|
||||
|
||||
if (itemElement == BookmarksService::gToolbarRoot)
|
||||
toolbarRootMoving = YES;
|
||||
|
||||
if (bookmarkItem)
|
||||
[draggedItems addObject: bookmarkItem];
|
||||
}
|
||||
|
||||
// If we are being dropped into the top level, allow it
|
||||
if ([proposedParent contentNode] == [BookmarksService::GetRootItem() contentNode])
|
||||
return true;
|
||||
|
||||
// If we are not being dropped on the top level, and the toolbar root is being moved, disallow
|
||||
if (toolbarRootMoving)
|
||||
return false;
|
||||
|
||||
// Make sure that we are not being dropped into one of our own children
|
||||
// If the proposed parent, or any of it's ancestors matches one of the nodes being dragged
|
||||
// then deny the drag.
|
||||
|
||||
for (unsigned int i = 0; i < [draggedItems count]; i++) {
|
||||
if (BookmarksService::DoAncestorsIncludeNode(proposedParent, [draggedItems objectAtIndex: i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BookmarksService::PerformBookmarkDrop(BookmarkItem* parent, int index, NSArray* draggedIDs) {
|
||||
NSEnumerator *enumerator = [draggedIDs reverseObjectEnumerator];
|
||||
NSNumber *contentID;
|
||||
|
||||
// for each item being dragged
|
||||
while ( (contentID = [enumerator nextObject]) ) {
|
||||
|
||||
// get dragged node
|
||||
nsCOMPtr<nsIContent> draggedNode = [GetWrapperFor([contentID unsignedIntValue]) contentNode];
|
||||
|
||||
// get the dragged nodes parent
|
||||
nsCOMPtr<nsIContent> draggedParent;
|
||||
if (draggedNode)
|
||||
draggedNode->GetParent(*getter_AddRefs(draggedParent));
|
||||
|
||||
// get the proposed parent
|
||||
nsCOMPtr<nsIContent> proposedParent = [parent contentNode];
|
||||
|
||||
PRInt32 existingIndex = 0;
|
||||
if (draggedParent)
|
||||
draggedParent->IndexOf(draggedNode, existingIndex);
|
||||
|
||||
// if the deleted nodes parent and the proposed parents are equal
|
||||
// and if the deleted point is eariler in the list than the inserted point
|
||||
if (proposedParent == draggedParent && existingIndex < index) {
|
||||
index--; // if so, move the inserted point up one to compensate
|
||||
}
|
||||
|
||||
// remove it from the tree
|
||||
if (draggedParent)
|
||||
draggedParent->RemoveChildAt(existingIndex, PR_TRUE);
|
||||
BookmarkRemoved(draggedParent, draggedNode, false);
|
||||
|
||||
// insert into new position
|
||||
if (proposedParent)
|
||||
proposedParent->InsertChildAt(draggedNode, index, PR_TRUE, PR_TRUE);
|
||||
BookmarkAdded(proposedParent, draggedNode, false);
|
||||
}
|
||||
|
||||
FlushBookmarks();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
BookmarksService::DropURL(NSString* title, NSURL* url, BookmarkItem* parent, int index)
|
||||
{
|
||||
NSLog(@"DropURL not implemented yet\n");
|
||||
}
|
||||
|
||||
|
|
|
@ -309,18 +309,82 @@
|
|||
|
||||
- (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender
|
||||
{
|
||||
return YES;
|
||||
BookmarkItem* parent;
|
||||
int index = 0;
|
||||
NSArray *draggedItems = [[sender draggingPasteboard] propertyListForType: @"MozBookmarkType"];
|
||||
|
||||
// If we are dropping into a folder
|
||||
if (mDragInsertionPosition == BookmarksService::CHInsertInto) {
|
||||
nsCOMPtr<nsIDOMElement> parentElt = [mDragInsertionButton element];
|
||||
nsCOMPtr<nsIContent> parentContent(do_QueryInterface(parentElt));
|
||||
parent = BookmarksService::GetWrapperFor(parentContent);
|
||||
index = 0;
|
||||
}
|
||||
|
||||
// If we are dropping onto the toolbar directly
|
||||
else if (mDragInsertionPosition == BookmarksService::CHInsertBefore ||
|
||||
mDragInsertionPosition == BookmarksService::CHInsertAfter) {
|
||||
nsCOMPtr<nsIDOMElement> rootElt = BookmarksService::gToolbarRoot;
|
||||
nsCOMPtr<nsIContent> rootContent(do_QueryInterface(rootElt));
|
||||
parent = BookmarksService::GetWrapperFor(rootContent);
|
||||
index = [mButtons indexOfObject: mDragInsertionButton];
|
||||
if (index == NSNotFound)
|
||||
rootContent->ChildCount(index);
|
||||
else if (mDragInsertionPosition == BookmarksService::CHInsertAfter)
|
||||
index++;
|
||||
} else {
|
||||
mDragInsertionButton = nil;
|
||||
mDragInsertionPosition = BookmarksService::CHInsertNone;
|
||||
[self setNeedsDisplay:YES];
|
||||
return NO;
|
||||
}
|
||||
|
||||
bool valid = BookmarksService::IsBookmarkDropValid(parent, index, draggedItems);
|
||||
if (!valid) {
|
||||
mDragInsertionButton = nil;
|
||||
mDragInsertionPosition = BookmarksService::CHInsertNone;
|
||||
[self setNeedsDisplay:YES];
|
||||
}
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
||||
- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
|
||||
{
|
||||
BookmarksService::CompleteBookmarkDrag([sender draggingPasteboard], BookmarksService::gToolbarRoot,
|
||||
mDragInsertionButton ? [mDragInsertionButton element] : nil,
|
||||
mDragInsertionPosition);
|
||||
|
||||
BookmarkItem* parent;
|
||||
int index = 0;
|
||||
NSArray *draggedItems = [[sender draggingPasteboard] propertyListForType: @"MozBookmarkType"];
|
||||
|
||||
// If we are dropping into a folder
|
||||
if (mDragInsertionPosition == BookmarksService::CHInsertInto) {
|
||||
nsCOMPtr<nsIDOMElement> parentElt = [mDragInsertionButton element];
|
||||
nsCOMPtr<nsIContent> parentContent(do_QueryInterface(parentElt));
|
||||
parent = BookmarksService::GetWrapperFor(parentContent);
|
||||
index = 0;
|
||||
}
|
||||
|
||||
// If we are dropping onto the toolbar directly
|
||||
else if (mDragInsertionPosition == BookmarksService::CHInsertBefore ||
|
||||
mDragInsertionPosition == BookmarksService::CHInsertAfter) {
|
||||
nsCOMPtr<nsIDOMElement> rootElt = BookmarksService::gToolbarRoot;
|
||||
nsCOMPtr<nsIContent> rootContent(do_QueryInterface(rootElt));
|
||||
parent = BookmarksService::GetWrapperFor(rootContent);
|
||||
index = [mButtons indexOfObject: mDragInsertionButton];
|
||||
if (index == NSNotFound)
|
||||
rootContent->ChildCount(index);
|
||||
else if (mDragInsertionPosition == BookmarksService::CHInsertAfter)
|
||||
index++;
|
||||
} else {
|
||||
mDragInsertionButton = nil;
|
||||
mDragInsertionPosition = BookmarksService::CHInsertNone;
|
||||
[self setNeedsDisplay:YES];
|
||||
return NO;
|
||||
}
|
||||
|
||||
BookmarksService::PerformBookmarkDrop(parent, index, draggedItems);
|
||||
|
||||
mDragInsertionButton = nil;
|
||||
mDragInsertionPosition = BookmarksService::CHInsertNone;
|
||||
|
||||
[self setNeedsDisplay:YES];
|
||||
|
||||
return YES;
|
||||
|
@ -329,14 +393,11 @@
|
|||
- (NSRect)insertionRectForButton:(NSView*)aButton position:(int) aPosition
|
||||
{
|
||||
if (aPosition == BookmarksService::CHInsertInto) {
|
||||
return NSMakeRect([aButton frame].origin.x, [aButton frame].origin.y,
|
||||
[aButton frame].size.width, [aButton frame].size.height);
|
||||
return NSMakeRect([aButton frame].origin.x, [aButton frame].origin.y, [aButton frame].size.width, [aButton frame].size.height);
|
||||
} else if (aPosition == BookmarksService::CHInsertAfter) {
|
||||
return NSMakeRect([aButton frame].origin.x+[aButton frame].size.width, [aButton frame].origin.y,
|
||||
2, [aButton frame].size.height);
|
||||
return NSMakeRect([aButton frame].origin.x+[aButton frame].size.width, [aButton frame].origin.y, 2, [aButton frame].size.height);
|
||||
} else {// if (aPosition == BookmarksService::CHInsertBefore) {
|
||||
return NSMakeRect([aButton frame].origin.x - 2, [aButton frame].origin.y,
|
||||
2, [aButton frame].size.height);
|
||||
return NSMakeRect([aButton frame].origin.x - 2, [aButton frame].origin.y, 2, [aButton frame].size.height);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -104,7 +104,7 @@ static void FindOptionWithContentID(nsIDOMHTMLSelectElement* aSel, PRUint32 aID,
|
|||
|
||||
-(id)initWithSelect:(nsIDOMHTMLSelectElement*)aSel
|
||||
{
|
||||
if (self = [super init]) {
|
||||
if ( (self = [super init]) ) {
|
||||
mSelectElt = aSel;
|
||||
}
|
||||
return self;
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#import "CHBookmarksToolbar.h"
|
||||
#import "CHExtendedOutlineView.h"
|
||||
|
||||
@class BookmarkItem;
|
||||
class BookmarksService;
|
||||
class nsIAtom;
|
||||
|
||||
|
@ -93,6 +94,10 @@ class nsIAtom;
|
|||
- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item;
|
||||
- (void)outlineView:(NSOutlineView *)outlineView setObjectValue:(id)object forTableColumn:(NSTableColumn *)tableColumn byItem:(id)item;
|
||||
|
||||
- (BOOL)outlineView:(NSOutlineView *)ov writeItems:(NSArray*)items toPasteboard:(NSPasteboard*)pboard;
|
||||
- (NSDragOperation)outlineView:(NSOutlineView*)ov validateDrop:(id <NSDraggingInfo>)info proposedItem:(id)item proposedChildIndex:(int)index;
|
||||
- (BOOL)outlineView:(NSOutlineView*)ov acceptDrop:(id <NSDraggingInfo>)info item:(id)item childIndex:(int)index;
|
||||
|
||||
- (void)reloadDataForItem:(id)item reloadChildren: (BOOL)aReloadChildren;
|
||||
|
||||
// Delegate methods
|
||||
|
@ -106,8 +111,9 @@ class nsIAtom;
|
|||
nsIContent* mContentNode;
|
||||
}
|
||||
|
||||
-(nsIContent*)contentNode;
|
||||
-(void)setContentNode: (nsIContent*)aContentNode;
|
||||
- (nsIContent*)contentNode;
|
||||
- (void)setContentNode: (nsIContent*)aContentNode;
|
||||
- (NSNumber*)contentID;
|
||||
- (id)copyWithZone:(NSZone *)aZone;
|
||||
@end
|
||||
|
||||
|
@ -123,9 +129,9 @@ public:
|
|||
void AddObserver();
|
||||
void RemoveObserver();
|
||||
|
||||
static void BookmarkAdded(nsIContent* aContainer, nsIContent* aChild);
|
||||
static void BookmarkChanged(nsIContent* aItem);
|
||||
static void BookmarkRemoved(nsIContent* aContainer, nsIContent* aChild);
|
||||
static void BookmarkAdded(nsIContent* aContainer, nsIContent* aChild, bool shouldFlush = true);
|
||||
static void BookmarkChanged(nsIContent* aItem, bool shouldFlush = true);
|
||||
static void BookmarkRemoved(nsIContent* aContainer, nsIContent* aChild, bool shouldFlush = true);
|
||||
|
||||
static void AddBookmarkToFolder(nsString& aURL, nsString& aTitle, nsIDOMElement* aFolder, nsIDOMElement* aBeforeElt);
|
||||
static void MoveBookmarkToFolder(nsIDOMElement* aBookmark, nsIDOMElement* aFolder, nsIDOMElement* aBeforeElt);
|
||||
|
@ -133,7 +139,9 @@ public:
|
|||
|
||||
public:
|
||||
static void GetRootContent(nsIContent** aResult);
|
||||
static BookmarkItem* GetRootItem();
|
||||
static BookmarkItem* GetWrapperFor(nsIContent* aItem);
|
||||
static BookmarkItem* GetWrapperFor(PRUint32 contentID);
|
||||
static void FlushBookmarks();
|
||||
|
||||
static void ConstructBookmarksMenu(NSMenu* aMenu, nsIContent* aContent);
|
||||
|
@ -153,10 +161,12 @@ public:
|
|||
static NSString* ResolveKeyword(NSString* aKeyword);
|
||||
|
||||
static NSImage* CreateIconForBookmark(nsIDOMElement* aElement);
|
||||
|
||||
static BOOL DoAncestorsIncludeNode(BookmarkItem* bookmark, BookmarkItem* searchItem);
|
||||
static bool IsBookmarkDropValid(BookmarkItem* proposedParent, int index, NSArray* draggedIDs);
|
||||
static bool PerformBookmarkDrop(BookmarkItem* parent, int index, NSArray* draggedIDs);
|
||||
|
||||
static void DragBookmark(nsIDOMElement* aElement, NSView* aView, NSEvent* aEvent);
|
||||
static void CompleteBookmarkDrag(NSPasteboard* aPasteboard, nsIDOMElement* aFolderElt, nsIDOMElement* aBeforeElt, int aPosition);
|
||||
|
||||
static void DropURL(NSString* title, NSURL* url, BookmarkItem* parent, int index);
|
||||
|
||||
public:
|
||||
// Global counter and pointers to our singletons.
|
||||
|
|
|
@ -182,11 +182,11 @@
|
|||
NSPopUpButton* popup = [mBrowserWindowController getAddBookmarkFolder];
|
||||
BookmarksService::ConstructAddBookmarkFolderList(popup, item);
|
||||
|
||||
[NSApp beginSheet: [mBrowserWindowController getAddBookmarkSheetWindow]
|
||||
modalForWindow: [mBrowserWindowController window]
|
||||
modalDelegate: nil //self
|
||||
didEndSelector: nil //@selector(sheetDidEnd:)
|
||||
contextInfo: nil];
|
||||
[NSApp beginSheet: [mBrowserWindowController getAddBookmarkSheetWindow]
|
||||
modalForWindow: [mBrowserWindowController window]
|
||||
modalDelegate: nil //self
|
||||
didEndSelector: nil //@selector(sheetDidEnd:)
|
||||
contextInfo: nil];
|
||||
}
|
||||
|
||||
-(void)endAddBookmark: (int)aCode
|
||||
|
@ -299,10 +299,10 @@
|
|||
int count = [itemsToDelete count];
|
||||
for (int i = 0; i < count; i++) {
|
||||
BookmarkItem* item = [itemsToDelete objectAtIndex: i];
|
||||
[self deleteBookmark: item];
|
||||
[self deleteBookmark: item];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-(void)deleteBookmark:(id)aItem
|
||||
{
|
||||
|
@ -346,7 +346,7 @@
|
|||
content->GetAttr(kNameSpaceID_None, BookmarksService::gHrefAtom, href);
|
||||
if (!href.IsEmpty()) {
|
||||
NSString* url = [NSString stringWithCharacters: href.get() length: href.Length()];
|
||||
[[[mBrowserWindowController getBrowserWrapper] getBrowserView] loadURI:[NSURL URLWithString: url] flags: NSLoadFlagsNone];
|
||||
[[[mBrowserWindowController getBrowserWrapper] getBrowserView] loadURI:[NSURL URLWithString: url] flags: NSLoadFlagsNone];
|
||||
// Focus and activate our content area.
|
||||
[[[mBrowserWindowController getBrowserWrapper] getBrowserView] setActive: YES];
|
||||
}
|
||||
|
@ -367,7 +367,7 @@
|
|||
//
|
||||
- (BOOL)outlineView:(NSOutlineView *)outlineView shouldEditTableColumn:(NSTableColumn *)tableColumn item:(id)item
|
||||
{
|
||||
return NO;
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (id)outlineView:(NSOutlineView *)outlineView child:(int)index ofItem:(id)item
|
||||
|
@ -436,12 +436,12 @@
|
|||
|
||||
- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item
|
||||
{
|
||||
NSString *columnName = [tableColumn identifier];
|
||||
NSMutableAttributedString *cellValue = [[NSMutableAttributedString alloc] init];
|
||||
NSFileWrapper *fileWrapper = [[NSFileWrapper alloc] initRegularFileWithContents:nil];
|
||||
NSTextAttachment *textAttachment = [[NSTextAttachment alloc] initWithFileWrapper:fileWrapper];
|
||||
NSMutableAttributedString *attachmentAttrString = nil;
|
||||
NSCell *attachmentAttrStringCell;
|
||||
NSString *columnName = [tableColumn identifier];
|
||||
NSMutableAttributedString *cellValue = [[NSMutableAttributedString alloc] init];
|
||||
NSFileWrapper *fileWrapper = [[NSFileWrapper alloc] initRegularFileWithContents:nil];
|
||||
NSTextAttachment *textAttachment = [[NSTextAttachment alloc] initWithFileWrapper:fileWrapper];
|
||||
NSMutableAttributedString *attachmentAttrString = nil;
|
||||
NSCell *attachmentAttrStringCell;
|
||||
|
||||
if ([columnName isEqualToString: @"name"]) {
|
||||
nsIContent* content = [item contentNode];
|
||||
|
@ -449,8 +449,7 @@
|
|||
content->GetAttr(kNameSpaceID_None, BookmarksService::gNameAtom, nameAttr);
|
||||
|
||||
//Set cell's textual contents
|
||||
[cellValue replaceCharactersInRange:NSMakeRange(0, [cellValue length])
|
||||
withString:[NSString stringWithCharacters: nameAttr.get() length: nameAttr.Length()]];
|
||||
[cellValue replaceCharactersInRange:NSMakeRange(0, [cellValue length]) withString:[NSString stringWithCharacters: nameAttr.get() length: nameAttr.Length()]];
|
||||
|
||||
//Create an attributed string to hold the empty attachment, then release the components.
|
||||
attachmentAttrString = [[NSMutableAttributedString attributedStringWithAttachment:textAttachment] retain];
|
||||
|
@ -458,9 +457,7 @@
|
|||
[fileWrapper release];
|
||||
|
||||
//Get the cell of the text attachment.
|
||||
attachmentAttrStringCell = (NSCell *)[(NSTextAttachment *)[attachmentAttrString attribute:NSAttachmentAttributeName
|
||||
atIndex:0
|
||||
effectiveRange:nil] attachmentCell];
|
||||
attachmentAttrStringCell = (NSCell *)[(NSTextAttachment *)[attachmentAttrString attribute:NSAttachmentAttributeName atIndex:0 effectiveRange:nil] attachmentCell];
|
||||
//Figure out which image to add, and set the cell's image.
|
||||
// Use the bookmark groups image for groups.
|
||||
if ([self outlineView:outlineView isItemExpandable:item]) {
|
||||
|
@ -521,73 +518,97 @@
|
|||
#endif
|
||||
}
|
||||
|
||||
- (void)reloadDataForItem:(id)item reloadChildren: (BOOL)aReloadChildren
|
||||
{
|
||||
printf("Reloading?\n");
|
||||
if (!item)
|
||||
[mOutlineView reloadData];
|
||||
else if ([mOutlineView isItemExpanded: item])
|
||||
[mOutlineView reloadItem: item reloadChildren: aReloadChildren];
|
||||
}
|
||||
|
||||
- (BOOL)outlineView:(NSOutlineView*)outlineView acceptDrop:(id <NSDraggingInfo>)info item:(id)item childIndex:(int)index
|
||||
- (BOOL)outlineView:(NSOutlineView *)ov writeItems:(NSArray*)items toPasteboard:(NSPasteboard*)pboard
|
||||
{
|
||||
BookmarkItem* beforeItem = nil;
|
||||
nsCOMPtr<nsIDOMElement> beforeElt;
|
||||
nsCOMPtr<nsIDOMElement> folderElt;
|
||||
nsCOMPtr<nsIContent> folderContent;
|
||||
|
||||
if (index == NSOutlineViewDropOnItemIndex)
|
||||
if (!mBookmarks || [mOutlineView selectedRow] == -1) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
#ifdef FILTER_DESCENDANT_ON_DRAG
|
||||
NSArray *toDrag = BookmarksService::FilterOutDescendantsForDrag(items);
|
||||
#else
|
||||
NSArray *toDrag = items;
|
||||
#endif
|
||||
int count = [toDrag count];
|
||||
if (count > 0) {
|
||||
// Create Pasteboard Data
|
||||
NSMutableArray *draggedID = [NSMutableArray arrayWithCapacity: count];
|
||||
for (int i = 0; i < count; i++)
|
||||
[draggedID addObject: [[toDrag objectAtIndex: i] contentID]];
|
||||
[pboard declareTypes: [NSArray arrayWithObject: @"MozBookmarkType"] owner: self];
|
||||
[pboard setPropertyList: draggedID forType: @"MozBookmarkType"];
|
||||
return YES;
|
||||
}
|
||||
|
||||
// get the folder element
|
||||
if (!item)
|
||||
mBookmarks->GetRootContent(getter_AddRefs(folderContent));
|
||||
else
|
||||
folderContent = [item contentNode];
|
||||
folderElt = do_QueryInterface(folderContent);
|
||||
|
||||
// get the element to insert before, if there is one
|
||||
PRInt32 childCount = 0;
|
||||
folderContent->ChildCount(childCount);
|
||||
if (index < childCount)
|
||||
beforeItem = [[outlineView dataSource] outlineView:outlineView child:index ofItem:item];
|
||||
if (beforeItem)
|
||||
beforeElt = do_QueryInterface([beforeItem contentNode]);
|
||||
|
||||
// insert the dragged stuff into bookmarks
|
||||
BookmarksService::CompleteBookmarkDrag([info draggingPasteboard], folderElt, beforeElt,
|
||||
BookmarksService::CHInsertBefore);
|
||||
|
||||
return YES;
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (NSDragOperation)outlineView:(NSOutlineView*)outlineView validateDrop:(id <NSDraggingInfo>)info proposedItem:(id)item proposedChildIndex:(int)index
|
||||
|
||||
- (NSDragOperation)outlineView:(NSOutlineView*)ov validateDrop:(id <NSDraggingInfo>)info proposedItem:(id)item proposedChildIndex:(int)index
|
||||
{
|
||||
NSArray* types = [[info draggingPasteboard] types];
|
||||
|
||||
// if the index is -1, deny the drop
|
||||
if (index == NSOutlineViewDropOnItemIndex)
|
||||
return NSDragOperationNone;
|
||||
|
||||
return NSDragOperationGeneric;
|
||||
}
|
||||
|
||||
- (BOOL)outlineView:(NSOutlineView *)outlineView writeItems:(NSArray*)items toPasteboard:(NSPasteboard*)pboard
|
||||
{
|
||||
NSMutableArray* contentIds = [NSMutableArray array];
|
||||
|
||||
for (unsigned int i = 0; i < [items count]; ++i) {
|
||||
nsCOMPtr<nsIContent> content = [[items objectAtIndex:i] contentNode];
|
||||
PRUint32 contentId;
|
||||
content->GetContentID(&contentId);
|
||||
[contentIds addObject:[NSNumber numberWithInt:contentId]];
|
||||
if ([types containsObject: @"MozBookmarkType"]) {
|
||||
NSArray *draggedIDs = [[info draggingPasteboard] propertyListForType: @"MozBookmarkType"];
|
||||
BookmarkItem* parent;
|
||||
parent = (item) ? item : BookmarksService::GetRootItem();
|
||||
return (BookmarksService::IsBookmarkDropValid(parent, index, draggedIDs)) ? NSDragOperationGeneric : NSDragOperationNone;
|
||||
} else if ([types containsObject: @"MozURLType"]) {
|
||||
return NSDragOperationGeneric;
|
||||
}
|
||||
|
||||
[pboard declareTypes:[NSArray arrayWithObject:@"MozBookmarkType"] owner:outlineView];
|
||||
[pboard setPropertyList:contentIds forType:@"MozBookmarkType"];
|
||||
|
||||
return YES;
|
||||
return NSDragOperationNone;
|
||||
}
|
||||
|
||||
- (BOOL)outlineView:(NSOutlineView*)ov acceptDrop:(id <NSDraggingInfo>)info item:(id)item childIndex:(int)index {
|
||||
NSArray *types = [[info draggingPasteboard] types];
|
||||
BookmarkItem* parent = (item) ? item : BookmarksService::GetRootItem();
|
||||
|
||||
if ([types containsObject: @"MozBookmarkType"]) {
|
||||
NSArray *draggedItems = [[info draggingPasteboard] propertyListForType: @"MozBookmarkType"];
|
||||
BookmarksService::PerformBookmarkDrop(parent, index, draggedItems);
|
||||
return YES;
|
||||
} else if ([types containsObject: @"MozURLType"]) {
|
||||
NSDictionary* data = [[info draggingPasteboard] propertyListForType: @"MozURLType"];
|
||||
nsCOMPtr<nsIDOMElement> parentElt;
|
||||
parentElt = do_QueryInterface([parent contentNode]);
|
||||
|
||||
PRInt32 childCount = 0;
|
||||
[item contentNode]->ChildCount(childCount);
|
||||
|
||||
if (index >= childCount)
|
||||
return NO;
|
||||
|
||||
BookmarkItem* beforeItem;
|
||||
beforeItem = [[ov dataSource] outlineView:ov child:index ofItem:item];
|
||||
|
||||
if (!beforeItem)
|
||||
return NO;
|
||||
|
||||
nsCOMPtr<nsIDOMElement> beforeElt;
|
||||
beforeElt = do_QueryInterface([beforeItem contentNode]);
|
||||
|
||||
nsAutoString url; url.AssignWithConversion([[data objectForKey:@"url"] cString]);
|
||||
nsAutoString title; title.AssignWithConversion([[data objectForKey:@"title"] cString]);
|
||||
BookmarksService::AddBookmarkToFolder(url, title, parentElt, beforeElt);
|
||||
return YES;
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void)reloadDataForItem:(id)item reloadChildren: (BOOL)aReloadChildren
|
||||
{
|
||||
if (!item)
|
||||
[mOutlineView reloadData];
|
||||
else if ([mOutlineView isItemExpanded: item])
|
||||
[mOutlineView reloadItem: item reloadChildren: aReloadChildren];
|
||||
}
|
||||
|
||||
-(IBAction)openBookmarkInNewTab:(id)aSender
|
||||
{
|
||||
|
@ -711,19 +732,36 @@
|
|||
@implementation BookmarkItem
|
||||
-(nsIContent*)contentNode
|
||||
{
|
||||
return mContentNode;
|
||||
return mContentNode;
|
||||
}
|
||||
|
||||
- (NSNumber*)contentID
|
||||
{
|
||||
PRUint32 contentID = 0;
|
||||
mContentNode->GetContentID(&contentID);
|
||||
return [NSNumber numberWithInt: contentID];
|
||||
}
|
||||
|
||||
- (NSString *)description
|
||||
{
|
||||
nsCOMPtr<nsIContent> item = [self contentNode];
|
||||
nsCOMPtr<nsIDOMElement> element(do_QueryInterface(item));
|
||||
nsAutoString href;
|
||||
element->GetAttribute(NS_LITERAL_STRING("name"), href);
|
||||
NSString* info = [NSString stringWithCharacters: href.get() length: href.Length()];
|
||||
return [NSString stringWithFormat:@"<BookmarkItem, name = \"%@\">", info];
|
||||
}
|
||||
|
||||
-(void)setContentNode: (nsIContent*)aContentNode
|
||||
{
|
||||
mContentNode = aContentNode;
|
||||
mContentNode = aContentNode;
|
||||
}
|
||||
|
||||
- (id)copyWithZone:(NSZone *)aZone
|
||||
{
|
||||
BookmarkItem* copy = [[[self class] allocWithZone: aZone] init];
|
||||
[copy setContentNode: mContentNode];
|
||||
return copy;
|
||||
BookmarkItem* copy = [[[self class] allocWithZone: aZone] init];
|
||||
[copy setContentNode: mContentNode];
|
||||
return copy;
|
||||
}
|
||||
|
||||
@end
|
||||
|
@ -732,25 +770,26 @@
|
|||
static void
|
||||
StripWhitespaceNodes(nsIContent* aElement)
|
||||
{
|
||||
PRInt32 childCount;
|
||||
aElement->ChildCount(childCount);
|
||||
for (PRInt32 i = 0; i < childCount; i++) {
|
||||
nsCOMPtr<nsIContent> child;
|
||||
aElement->ChildAt(i, *getter_AddRefs(child));
|
||||
nsCOMPtr<nsITextContent> text = do_QueryInterface(child);
|
||||
if (text) {
|
||||
PRBool isEmpty;
|
||||
text->IsOnlyWhitespace(&isEmpty);
|
||||
if (isEmpty) {
|
||||
// This node contained nothing but whitespace.
|
||||
// Remove it from the content model.
|
||||
aElement->RemoveChildAt(i, PR_TRUE);
|
||||
i--; // Decrement our count, since we just removed this child.
|
||||
childCount--; // Also decrement our total count.
|
||||
}
|
||||
}
|
||||
else StripWhitespaceNodes(child);
|
||||
PRInt32 childCount = 0;
|
||||
aElement->ChildCount(childCount);
|
||||
for (PRInt32 i = 0; i < childCount; i++) {
|
||||
nsCOMPtr<nsIContent> child;
|
||||
aElement->ChildAt(i, *getter_AddRefs(child));
|
||||
nsCOMPtr<nsITextContent> text = do_QueryInterface(child);
|
||||
if (text) {
|
||||
PRBool isEmpty = PR_FALSE;
|
||||
text->IsOnlyWhitespace(&isEmpty);
|
||||
if (isEmpty) {
|
||||
// This node contained nothing but whitespace.
|
||||
// Remove it from the content model.
|
||||
aElement->RemoveChildAt(i, PR_TRUE);
|
||||
i--; // Decrement our count, since we just removed this child.
|
||||
childCount--; // Also decrement our total count.
|
||||
}
|
||||
}
|
||||
else
|
||||
StripWhitespaceNodes(child);
|
||||
}
|
||||
}
|
||||
|
||||
PRUint32 BookmarksService::gRefCnt = 0;
|
||||
|
@ -792,34 +831,50 @@ BookmarksService::~BookmarksService()
|
|||
void
|
||||
BookmarksService::GetRootContent(nsIContent** aResult)
|
||||
{
|
||||
*aResult = nsnull;
|
||||
if (gBookmarks) {
|
||||
nsCOMPtr<nsIDOMElement> elt;
|
||||
nsCOMPtr<nsIDOMDocument> domDoc(do_QueryInterface(gBookmarks));
|
||||
domDoc->GetDocumentElement(getter_AddRefs(elt));
|
||||
elt->QueryInterface(NS_GET_IID(nsIContent), (void**)aResult); // Addref happens here.
|
||||
}
|
||||
*aResult = nsnull;
|
||||
if (gBookmarks) {
|
||||
nsCOMPtr<nsIDOMDocument> domDoc(do_QueryInterface(gBookmarks));
|
||||
if (!domDoc) return;
|
||||
|
||||
nsCOMPtr<nsIDOMElement> elt;
|
||||
domDoc->GetDocumentElement(getter_AddRefs(elt));
|
||||
if (elt)
|
||||
elt->QueryInterface(NS_GET_IID(nsIContent), (void**)aResult); // Addref happens here.
|
||||
}
|
||||
}
|
||||
|
||||
BookmarkItem*
|
||||
BookmarksService::GetRootItem() {
|
||||
nsCOMPtr<nsIContent> rootContent;
|
||||
BookmarksService::GetRootContent(getter_AddRefs(rootContent));
|
||||
BookmarkItem* rootItem = BookmarksService::GetWrapperFor(rootContent);
|
||||
return rootItem;
|
||||
}
|
||||
|
||||
BookmarkItem*
|
||||
BookmarksService::GetWrapperFor(nsIContent* aContent)
|
||||
{
|
||||
if (!gDictionary)
|
||||
gDictionary = [[NSMutableDictionary alloc] initWithCapacity: 30];
|
||||
|
||||
PRUint32 contentID;
|
||||
aContent->GetContentID(&contentID);
|
||||
|
||||
BookmarkItem* item = [gDictionary objectForKey: [NSNumber numberWithInt: contentID]];
|
||||
if (item)
|
||||
return item;
|
||||
else {
|
||||
// Create an item.
|
||||
item = [[[BookmarkItem alloc] init] autorelease]; // The dictionary retains us.
|
||||
[item setContentNode: aContent];
|
||||
[gDictionary setObject: item forKey: [NSNumber numberWithInt: contentID]];
|
||||
}
|
||||
if (!gDictionary)
|
||||
gDictionary = [[NSMutableDictionary alloc] initWithCapacity: 30];
|
||||
|
||||
PRUint32 contentID = 0;
|
||||
aContent->GetContentID(&contentID);
|
||||
|
||||
BookmarkItem* item = [gDictionary objectForKey: [NSNumber numberWithInt: contentID]];
|
||||
if (item)
|
||||
return item;
|
||||
|
||||
// Create an item.
|
||||
item = [[[BookmarkItem alloc] init] autorelease]; // The dictionary retains us.
|
||||
[item setContentNode: aContent];
|
||||
[gDictionary setObject: item forKey: [NSNumber numberWithInt: contentID]];
|
||||
return item;
|
||||
}
|
||||
|
||||
BookmarkItem*
|
||||
BookmarksService::GetWrapperFor(PRUint32 contentID) {
|
||||
BookmarkItem* item = [gDictionary objectForKey: [NSNumber numberWithUnsignedInt: contentID]];
|
||||
return item;
|
||||
}
|
||||
|
||||
NSMenu*
|
||||
|
@ -841,7 +896,7 @@ BookmarksService::LocateMenu(nsIContent* aContent)
|
|||
}
|
||||
|
||||
void
|
||||
BookmarksService::BookmarkAdded(nsIContent* aContainer, nsIContent* aChild)
|
||||
BookmarksService::BookmarkAdded(nsIContent* aContainer, nsIContent* aChild, bool shouldFlush = true)
|
||||
{
|
||||
if (!gInstances || !gDictionary)
|
||||
return;
|
||||
|
@ -883,11 +938,12 @@ BookmarksService::BookmarkAdded(nsIContent* aContainer, nsIContent* aChild)
|
|||
}
|
||||
}
|
||||
|
||||
FlushBookmarks();
|
||||
if (shouldFlush)
|
||||
FlushBookmarks();
|
||||
}
|
||||
|
||||
void
|
||||
BookmarksService::BookmarkChanged(nsIContent* aItem)
|
||||
BookmarksService::BookmarkChanged(nsIContent* aItem, bool shouldFlush = true)
|
||||
{
|
||||
if (!gInstances || !gDictionary)
|
||||
return;
|
||||
|
@ -902,11 +958,12 @@ BookmarksService::BookmarkChanged(nsIContent* aItem)
|
|||
}
|
||||
}
|
||||
|
||||
FlushBookmarks();
|
||||
if (shouldFlush)
|
||||
FlushBookmarks();
|
||||
}
|
||||
|
||||
void
|
||||
BookmarksService::BookmarkRemoved(nsIContent* aContainer, nsIContent* aChild)
|
||||
BookmarksService::BookmarkRemoved(nsIContent* aContainer, nsIContent* aChild, bool shouldFlush = true)
|
||||
{
|
||||
if (!gInstances)
|
||||
return;
|
||||
|
@ -940,14 +997,15 @@ BookmarksService::BookmarkRemoved(nsIContent* aContainer, nsIContent* aChild)
|
|||
else {
|
||||
// We're the menu.
|
||||
NSMenu* menu = LocateMenu(aContainer);
|
||||
PRUint32 contentID;
|
||||
PRUint32 contentID = 0;
|
||||
aChild->GetContentID(&contentID);
|
||||
NSMenuItem* childItem = [menu itemWithTag: contentID];
|
||||
[menu removeItem: childItem];
|
||||
}
|
||||
}
|
||||
|
||||
FlushBookmarks();
|
||||
if (shouldFlush)
|
||||
FlushBookmarks();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -969,7 +1027,7 @@ BookmarksService::AddObserver()
|
|||
NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(profileDir));
|
||||
profileDir->Append(NS_LITERAL_STRING("bookmarks.xml"));
|
||||
|
||||
PRBool fileExists;
|
||||
PRBool fileExists = PR_FALSE;
|
||||
profileDir->Exists(&fileExists);
|
||||
|
||||
// If the bookmarks file does not exist, copy from the defaults so we don't
|
||||
|
@ -1119,9 +1177,10 @@ BookmarksService::FlushBookmarks()
|
|||
nsCOMPtr<nsIOutputStream> outputStream;
|
||||
NS_NewLocalFileOutputStream(getter_AddRefs(outputStream), bookmarksFile);
|
||||
|
||||
nsCOMPtr<nsIDOMDocument> domDoc(do_QueryInterface(gBookmarks));
|
||||
|
||||
nsCOMPtr<nsIDOMSerializer> domSerializer(do_CreateInstance(NS_XMLSERIALIZER_CONTRACTID));
|
||||
nsCOMPtr<nsIDOMDocument> domDoc(do_QueryInterface(gBookmarks));
|
||||
|
||||
nsCOMPtr<nsIDOMSerializer> domSerializer(do_CreateInstance(NS_XMLSERIALIZER_CONTRACTID));
|
||||
if (domSerializer)
|
||||
domSerializer->SerializeToStream(domDoc, outputStream, nsnull);
|
||||
}
|
||||
|
||||
|
@ -1592,63 +1651,160 @@ BookmarksService::CreateIconForBookmark(nsIDOMElement* aElement)
|
|||
return [NSImage imageNamed:@"groupbookmark"];
|
||||
}
|
||||
|
||||
void
|
||||
BookmarksService::DragBookmark(nsIDOMElement* aElement, NSView* aView, NSEvent* aEvent)
|
||||
{
|
||||
NSPasteboard *pboard;
|
||||
NSString* title;
|
||||
// Is searchItem equal to bookmark or bookmark's parent, grandparent, etc?
|
||||
BOOL
|
||||
BookmarksService::DoAncestorsIncludeNode(BookmarkItem* bookmark, BookmarkItem* searchItem) {
|
||||
nsCOMPtr<nsIContent> search = [searchItem contentNode];
|
||||
nsCOMPtr<nsIContent> current = [bookmark contentNode];
|
||||
nsCOMPtr<nsIContent> root;
|
||||
GetRootContent(getter_AddRefs(root));
|
||||
|
||||
// If the search item is the root node, return yes immediatly
|
||||
if (search == root)
|
||||
return YES;
|
||||
|
||||
// for each ancestor
|
||||
while (current) {
|
||||
// If this is the root node we can't search farther, and there was no match
|
||||
if (current == root)
|
||||
return NO;
|
||||
|
||||
// If the two nodes match, then the search term is an ancestor of the given bookmark
|
||||
if (search == current)
|
||||
return YES;
|
||||
|
||||
// If a match wasn't found, set up the next node to compare
|
||||
nsCOMPtr<nsIContent> oldCurrent = current;
|
||||
oldCurrent->GetParent(*getter_AddRefs(current));
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(aElement);
|
||||
PRUint32 contentId;
|
||||
content->GetContentID(&contentId);
|
||||
|
||||
pboard = [NSPasteboard pasteboardWithName:NSDragPboard];
|
||||
[pboard declareTypes:[NSArray arrayWithObject:@"MozBookmarkType"] owner:aView];
|
||||
[pboard setPropertyList:[NSArray arrayWithObject:[NSNumber numberWithInt:contentId]] forType:@"MozBookmarkType"];
|
||||
|
||||
nsAutoString nameStr;
|
||||
aElement->GetAttribute(NS_LITERAL_STRING("name"), nameStr);
|
||||
title = [NSString stringWithCharacters: nameStr.get() length: nameStr.Length()];
|
||||
|
||||
[aView dragImage: [MainController createImageForDragging: CreateIconForBookmark(aElement) title:title]
|
||||
at:NSMakePoint(0,0) offset:NSMakeSize(0,0)
|
||||
event:aEvent pasteboard:pboard source:aView slideBack:YES];
|
||||
return NO;
|
||||
}
|
||||
|
||||
void
|
||||
BookmarksService::CompleteBookmarkDrag(NSPasteboard* aPasteboard, nsIDOMElement* aFolderElt,
|
||||
nsIDOMElement* aBeforeElt, int aPosition)
|
||||
|
||||
#ifdef FILTER_DESCENDANT_ON_DRAG
|
||||
/*
|
||||
this has been disabled because it is too slow, and can cause a large
|
||||
delay when the user is dragging lots of items. this needs to get
|
||||
fixed someday.
|
||||
|
||||
It should filter out every node whose parent is also being dragged.
|
||||
*/
|
||||
|
||||
NSArray*
|
||||
BookmarksService::FilterOutDescendantsForDrag(NSArray* nodes)
|
||||
{
|
||||
NSArray* contentIds;
|
||||
|
||||
nsCOMPtr<nsIDOMElement> beforeElt = aBeforeElt;
|
||||
if (aPosition == BookmarksService::CHInsertAfter && aBeforeElt) {
|
||||
nsCOMPtr<nsIDOMNode> beforeNode;
|
||||
aBeforeElt->GetNextSibling(getter_AddRefs(beforeNode));
|
||||
beforeElt = do_QueryInterface(beforeNode);
|
||||
}
|
||||
|
||||
if (aPosition == BookmarksService::CHInsertInto) {
|
||||
aFolderElt = aBeforeElt;
|
||||
beforeElt = nsnull;
|
||||
}
|
||||
NSMutableArray *toDrag = [NSMutableArray arrayWithArray: nodes];
|
||||
unsigned int i = 0;
|
||||
|
||||
while (i < [toDrag count]) {
|
||||
BookmarkItem* item = [toDrag objectAtIndex: i];
|
||||
bool matchFound = false;
|
||||
|
||||
// check for recognized drag types
|
||||
contentIds = [aPasteboard propertyListForType: @"MozBookmarkType"];
|
||||
if (contentIds) {
|
||||
// drag type is chimera bookmarks
|
||||
for (unsigned int i = 0; i < [contentIds count]; ++i) {
|
||||
BookmarkItem* item = [gDictionary objectForKey: [contentIds objectAtIndex:i]];
|
||||
nsCOMPtr<nsIDOMElement> bookmarkElt = do_QueryInterface([item contentNode]);
|
||||
MoveBookmarkToFolder(bookmarkElt, aFolderElt, beforeElt);
|
||||
for (unsigned int j = 0; j < [toDrag count] && matchFound == NO; j++) {
|
||||
if (i != j) // Don't compare to self, will always match
|
||||
matchFound = BookmarksService::DoAncestorsIncludeNode(item, [toDrag objectAtIndex: j]);
|
||||
}
|
||||
} else {
|
||||
// add bookmark for chimera url type
|
||||
NSDictionary* data = [aPasteboard propertyListForType: @"MozURLType"];
|
||||
nsAutoString url; url.AssignWithConversion([[data objectForKey:@"url"] cString]);
|
||||
nsAutoString title; title.AssignWithConversion([[data objectForKey:@"title"] cString]);
|
||||
|
||||
AddBookmarkToFolder(url, title, aFolderElt, beforeElt);
|
||||
// if a match was found, remove the node from the array
|
||||
if (matchFound)
|
||||
[toDrag removeObjectAtIndex: i];
|
||||
else
|
||||
i++;
|
||||
}
|
||||
|
||||
return toDrag;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool
|
||||
BookmarksService::IsBookmarkDropValid(BookmarkItem* proposedParent, int index, NSArray* draggedIDs) {
|
||||
NSMutableArray *draggedItems = [NSMutableArray arrayWithCapacity: [draggedIDs count]];
|
||||
BOOL toolbarRootMoving = NO;
|
||||
|
||||
for (unsigned int i = 0; i < [draggedIDs count]; i++) {
|
||||
NSNumber* contentID = [draggedIDs objectAtIndex: i];
|
||||
BookmarkItem* bookmarkItem = BookmarksService::GetWrapperFor([contentID unsignedIntValue]);
|
||||
nsCOMPtr<nsIContent> itemContent = [bookmarkItem contentNode];
|
||||
nsCOMPtr<nsIDOMElement> itemElement(do_QueryInterface(itemContent));
|
||||
|
||||
if (itemElement == BookmarksService::gToolbarRoot)
|
||||
toolbarRootMoving = YES;
|
||||
|
||||
if (bookmarkItem)
|
||||
[draggedItems addObject: bookmarkItem];
|
||||
}
|
||||
|
||||
// If we are being dropped into the top level, allow it
|
||||
if ([proposedParent contentNode] == [BookmarksService::GetRootItem() contentNode])
|
||||
return true;
|
||||
|
||||
// If we are not being dropped on the top level, and the toolbar root is being moved, disallow
|
||||
if (toolbarRootMoving)
|
||||
return false;
|
||||
|
||||
// Make sure that we are not being dropped into one of our own children
|
||||
// If the proposed parent, or any of it's ancestors matches one of the nodes being dragged
|
||||
// then deny the drag.
|
||||
|
||||
for (unsigned int i = 0; i < [draggedItems count]; i++) {
|
||||
if (BookmarksService::DoAncestorsIncludeNode(proposedParent, [draggedItems objectAtIndex: i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BookmarksService::PerformBookmarkDrop(BookmarkItem* parent, int index, NSArray* draggedIDs) {
|
||||
NSEnumerator *enumerator = [draggedIDs reverseObjectEnumerator];
|
||||
NSNumber *contentID;
|
||||
|
||||
// for each item being dragged
|
||||
while ( (contentID = [enumerator nextObject]) ) {
|
||||
|
||||
// get dragged node
|
||||
nsCOMPtr<nsIContent> draggedNode = [GetWrapperFor([contentID unsignedIntValue]) contentNode];
|
||||
|
||||
// get the dragged nodes parent
|
||||
nsCOMPtr<nsIContent> draggedParent;
|
||||
if (draggedNode)
|
||||
draggedNode->GetParent(*getter_AddRefs(draggedParent));
|
||||
|
||||
// get the proposed parent
|
||||
nsCOMPtr<nsIContent> proposedParent = [parent contentNode];
|
||||
|
||||
PRInt32 existingIndex = 0;
|
||||
if (draggedParent)
|
||||
draggedParent->IndexOf(draggedNode, existingIndex);
|
||||
|
||||
// if the deleted nodes parent and the proposed parents are equal
|
||||
// and if the deleted point is eariler in the list than the inserted point
|
||||
if (proposedParent == draggedParent && existingIndex < index) {
|
||||
index--; // if so, move the inserted point up one to compensate
|
||||
}
|
||||
|
||||
// remove it from the tree
|
||||
if (draggedParent)
|
||||
draggedParent->RemoveChildAt(existingIndex, PR_TRUE);
|
||||
BookmarkRemoved(draggedParent, draggedNode, false);
|
||||
|
||||
// insert into new position
|
||||
if (proposedParent)
|
||||
proposedParent->InsertChildAt(draggedNode, index, PR_TRUE, PR_TRUE);
|
||||
BookmarkAdded(proposedParent, draggedNode, false);
|
||||
}
|
||||
|
||||
FlushBookmarks();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
BookmarksService::DropURL(NSString* title, NSURL* url, BookmarkItem* parent, int index)
|
||||
{
|
||||
NSLog(@"DropURL not implemented yet\n");
|
||||
}
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
if ( (self = [super initWithFrame:frame]) ) {
|
||||
mElement = nsnull;
|
||||
[self setBezelStyle: NSRegularSquareBezelStyle];
|
||||
[self setButtonType: NSMomentaryChangeButton];
|
||||
[self setBordered: NO];
|
||||
[self setImagePosition: NSImageLeft];
|
||||
[self setRefusesFirstResponder: YES];
|
||||
|
@ -138,7 +139,11 @@
|
|||
// XXX mouseDragged is never called because buttons cancel dragging while you mouse down
|
||||
// I have to fix this in an ugly way, by doing the "click" stuff myself and never relying
|
||||
// on the superclass for that. Bah!
|
||||
BookmarksService::DragBookmark(mElement, self, aEvent);
|
||||
|
||||
// perhaps you could just implement mouseUp to perform the action (which should be the case
|
||||
// things shouldn't happen on mouse down) Then does mouseDragged get overridden?
|
||||
|
||||
// BookmarksService::DragBookmark(mElement, self, aEvent);
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
if (operation == NSDragOperationDelete) {
|
||||
NSArray* contentIds = nil;
|
||||
NSPasteboard* pboard = [NSPasteboard pasteboardWithName:NSDragPboard];
|
||||
contentIds = [pboard propertyListForType:@"MozBookmarkType"];
|
||||
contentIds = [pboard propertyListForType: @"MozBookmarkType"];
|
||||
if (contentIds) {
|
||||
for (unsigned int i = 0; i < [contentIds count]; ++i) {
|
||||
BookmarkItem* item = [BookmarksService::gDictionary objectForKey: [contentIds objectAtIndex:i]];
|
||||
|
|
|
@ -309,18 +309,82 @@
|
|||
|
||||
- (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender
|
||||
{
|
||||
return YES;
|
||||
BookmarkItem* parent;
|
||||
int index = 0;
|
||||
NSArray *draggedItems = [[sender draggingPasteboard] propertyListForType: @"MozBookmarkType"];
|
||||
|
||||
// If we are dropping into a folder
|
||||
if (mDragInsertionPosition == BookmarksService::CHInsertInto) {
|
||||
nsCOMPtr<nsIDOMElement> parentElt = [mDragInsertionButton element];
|
||||
nsCOMPtr<nsIContent> parentContent(do_QueryInterface(parentElt));
|
||||
parent = BookmarksService::GetWrapperFor(parentContent);
|
||||
index = 0;
|
||||
}
|
||||
|
||||
// If we are dropping onto the toolbar directly
|
||||
else if (mDragInsertionPosition == BookmarksService::CHInsertBefore ||
|
||||
mDragInsertionPosition == BookmarksService::CHInsertAfter) {
|
||||
nsCOMPtr<nsIDOMElement> rootElt = BookmarksService::gToolbarRoot;
|
||||
nsCOMPtr<nsIContent> rootContent(do_QueryInterface(rootElt));
|
||||
parent = BookmarksService::GetWrapperFor(rootContent);
|
||||
index = [mButtons indexOfObject: mDragInsertionButton];
|
||||
if (index == NSNotFound)
|
||||
rootContent->ChildCount(index);
|
||||
else if (mDragInsertionPosition == BookmarksService::CHInsertAfter)
|
||||
index++;
|
||||
} else {
|
||||
mDragInsertionButton = nil;
|
||||
mDragInsertionPosition = BookmarksService::CHInsertNone;
|
||||
[self setNeedsDisplay:YES];
|
||||
return NO;
|
||||
}
|
||||
|
||||
bool valid = BookmarksService::IsBookmarkDropValid(parent, index, draggedItems);
|
||||
if (!valid) {
|
||||
mDragInsertionButton = nil;
|
||||
mDragInsertionPosition = BookmarksService::CHInsertNone;
|
||||
[self setNeedsDisplay:YES];
|
||||
}
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
||||
- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
|
||||
{
|
||||
BookmarksService::CompleteBookmarkDrag([sender draggingPasteboard], BookmarksService::gToolbarRoot,
|
||||
mDragInsertionButton ? [mDragInsertionButton element] : nil,
|
||||
mDragInsertionPosition);
|
||||
|
||||
BookmarkItem* parent;
|
||||
int index = 0;
|
||||
NSArray *draggedItems = [[sender draggingPasteboard] propertyListForType: @"MozBookmarkType"];
|
||||
|
||||
// If we are dropping into a folder
|
||||
if (mDragInsertionPosition == BookmarksService::CHInsertInto) {
|
||||
nsCOMPtr<nsIDOMElement> parentElt = [mDragInsertionButton element];
|
||||
nsCOMPtr<nsIContent> parentContent(do_QueryInterface(parentElt));
|
||||
parent = BookmarksService::GetWrapperFor(parentContent);
|
||||
index = 0;
|
||||
}
|
||||
|
||||
// If we are dropping onto the toolbar directly
|
||||
else if (mDragInsertionPosition == BookmarksService::CHInsertBefore ||
|
||||
mDragInsertionPosition == BookmarksService::CHInsertAfter) {
|
||||
nsCOMPtr<nsIDOMElement> rootElt = BookmarksService::gToolbarRoot;
|
||||
nsCOMPtr<nsIContent> rootContent(do_QueryInterface(rootElt));
|
||||
parent = BookmarksService::GetWrapperFor(rootContent);
|
||||
index = [mButtons indexOfObject: mDragInsertionButton];
|
||||
if (index == NSNotFound)
|
||||
rootContent->ChildCount(index);
|
||||
else if (mDragInsertionPosition == BookmarksService::CHInsertAfter)
|
||||
index++;
|
||||
} else {
|
||||
mDragInsertionButton = nil;
|
||||
mDragInsertionPosition = BookmarksService::CHInsertNone;
|
||||
[self setNeedsDisplay:YES];
|
||||
return NO;
|
||||
}
|
||||
|
||||
BookmarksService::PerformBookmarkDrop(parent, index, draggedItems);
|
||||
|
||||
mDragInsertionButton = nil;
|
||||
mDragInsertionPosition = BookmarksService::CHInsertNone;
|
||||
|
||||
[self setNeedsDisplay:YES];
|
||||
|
||||
return YES;
|
||||
|
@ -329,14 +393,11 @@
|
|||
- (NSRect)insertionRectForButton:(NSView*)aButton position:(int) aPosition
|
||||
{
|
||||
if (aPosition == BookmarksService::CHInsertInto) {
|
||||
return NSMakeRect([aButton frame].origin.x, [aButton frame].origin.y,
|
||||
[aButton frame].size.width, [aButton frame].size.height);
|
||||
return NSMakeRect([aButton frame].origin.x, [aButton frame].origin.y, [aButton frame].size.width, [aButton frame].size.height);
|
||||
} else if (aPosition == BookmarksService::CHInsertAfter) {
|
||||
return NSMakeRect([aButton frame].origin.x+[aButton frame].size.width, [aButton frame].origin.y,
|
||||
2, [aButton frame].size.height);
|
||||
return NSMakeRect([aButton frame].origin.x+[aButton frame].size.width, [aButton frame].origin.y, 2, [aButton frame].size.height);
|
||||
} else {// if (aPosition == BookmarksService::CHInsertBefore) {
|
||||
return NSMakeRect([aButton frame].origin.x - 2, [aButton frame].origin.y,
|
||||
2, [aButton frame].size.height);
|
||||
return NSMakeRect([aButton frame].origin.x - 2, [aButton frame].origin.y, 2, [aButton frame].size.height);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -104,7 +104,7 @@ static void FindOptionWithContentID(nsIDOMHTMLSelectElement* aSel, PRUint32 aID,
|
|||
|
||||
-(id)initWithSelect:(nsIDOMHTMLSelectElement*)aSel
|
||||
{
|
||||
if (self = [super init]) {
|
||||
if ( (self = [super init]) ) {
|
||||
mSelectElt = aSel;
|
||||
}
|
||||
return self;
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
if ( (self = [super initWithFrame:frame]) ) {
|
||||
mElement = nsnull;
|
||||
[self setBezelStyle: NSRegularSquareBezelStyle];
|
||||
[self setButtonType: NSMomentaryChangeButton];
|
||||
[self setBordered: NO];
|
||||
[self setImagePosition: NSImageLeft];
|
||||
[self setRefusesFirstResponder: YES];
|
||||
|
@ -138,7 +139,11 @@
|
|||
// XXX mouseDragged is never called because buttons cancel dragging while you mouse down
|
||||
// I have to fix this in an ugly way, by doing the "click" stuff myself and never relying
|
||||
// on the superclass for that. Bah!
|
||||
BookmarksService::DragBookmark(mElement, self, aEvent);
|
||||
|
||||
// perhaps you could just implement mouseUp to perform the action (which should be the case
|
||||
// things shouldn't happen on mouse down) Then does mouseDragged get overridden?
|
||||
|
||||
// BookmarksService::DragBookmark(mElement, self, aEvent);
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
if (operation == NSDragOperationDelete) {
|
||||
NSArray* contentIds = nil;
|
||||
NSPasteboard* pboard = [NSPasteboard pasteboardWithName:NSDragPboard];
|
||||
contentIds = [pboard propertyListForType:@"MozBookmarkType"];
|
||||
contentIds = [pboard propertyListForType: @"MozBookmarkType"];
|
||||
if (contentIds) {
|
||||
for (unsigned int i = 0; i < [contentIds count]; ++i) {
|
||||
BookmarkItem* item = [BookmarksService::gDictionary objectForKey: [contentIds objectAtIndex:i]];
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#import "CHBookmarksToolbar.h"
|
||||
#import "CHExtendedOutlineView.h"
|
||||
|
||||
@class BookmarkItem;
|
||||
class BookmarksService;
|
||||
class nsIAtom;
|
||||
|
||||
|
@ -93,6 +94,10 @@ class nsIAtom;
|
|||
- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item;
|
||||
- (void)outlineView:(NSOutlineView *)outlineView setObjectValue:(id)object forTableColumn:(NSTableColumn *)tableColumn byItem:(id)item;
|
||||
|
||||
- (BOOL)outlineView:(NSOutlineView *)ov writeItems:(NSArray*)items toPasteboard:(NSPasteboard*)pboard;
|
||||
- (NSDragOperation)outlineView:(NSOutlineView*)ov validateDrop:(id <NSDraggingInfo>)info proposedItem:(id)item proposedChildIndex:(int)index;
|
||||
- (BOOL)outlineView:(NSOutlineView*)ov acceptDrop:(id <NSDraggingInfo>)info item:(id)item childIndex:(int)index;
|
||||
|
||||
- (void)reloadDataForItem:(id)item reloadChildren: (BOOL)aReloadChildren;
|
||||
|
||||
// Delegate methods
|
||||
|
@ -106,8 +111,9 @@ class nsIAtom;
|
|||
nsIContent* mContentNode;
|
||||
}
|
||||
|
||||
-(nsIContent*)contentNode;
|
||||
-(void)setContentNode: (nsIContent*)aContentNode;
|
||||
- (nsIContent*)contentNode;
|
||||
- (void)setContentNode: (nsIContent*)aContentNode;
|
||||
- (NSNumber*)contentID;
|
||||
- (id)copyWithZone:(NSZone *)aZone;
|
||||
@end
|
||||
|
||||
|
@ -123,9 +129,9 @@ public:
|
|||
void AddObserver();
|
||||
void RemoveObserver();
|
||||
|
||||
static void BookmarkAdded(nsIContent* aContainer, nsIContent* aChild);
|
||||
static void BookmarkChanged(nsIContent* aItem);
|
||||
static void BookmarkRemoved(nsIContent* aContainer, nsIContent* aChild);
|
||||
static void BookmarkAdded(nsIContent* aContainer, nsIContent* aChild, bool shouldFlush = true);
|
||||
static void BookmarkChanged(nsIContent* aItem, bool shouldFlush = true);
|
||||
static void BookmarkRemoved(nsIContent* aContainer, nsIContent* aChild, bool shouldFlush = true);
|
||||
|
||||
static void AddBookmarkToFolder(nsString& aURL, nsString& aTitle, nsIDOMElement* aFolder, nsIDOMElement* aBeforeElt);
|
||||
static void MoveBookmarkToFolder(nsIDOMElement* aBookmark, nsIDOMElement* aFolder, nsIDOMElement* aBeforeElt);
|
||||
|
@ -133,7 +139,9 @@ public:
|
|||
|
||||
public:
|
||||
static void GetRootContent(nsIContent** aResult);
|
||||
static BookmarkItem* GetRootItem();
|
||||
static BookmarkItem* GetWrapperFor(nsIContent* aItem);
|
||||
static BookmarkItem* GetWrapperFor(PRUint32 contentID);
|
||||
static void FlushBookmarks();
|
||||
|
||||
static void ConstructBookmarksMenu(NSMenu* aMenu, nsIContent* aContent);
|
||||
|
@ -153,10 +161,12 @@ public:
|
|||
static NSString* ResolveKeyword(NSString* aKeyword);
|
||||
|
||||
static NSImage* CreateIconForBookmark(nsIDOMElement* aElement);
|
||||
|
||||
static BOOL DoAncestorsIncludeNode(BookmarkItem* bookmark, BookmarkItem* searchItem);
|
||||
static bool IsBookmarkDropValid(BookmarkItem* proposedParent, int index, NSArray* draggedIDs);
|
||||
static bool PerformBookmarkDrop(BookmarkItem* parent, int index, NSArray* draggedIDs);
|
||||
|
||||
static void DragBookmark(nsIDOMElement* aElement, NSView* aView, NSEvent* aEvent);
|
||||
static void CompleteBookmarkDrag(NSPasteboard* aPasteboard, nsIDOMElement* aFolderElt, nsIDOMElement* aBeforeElt, int aPosition);
|
||||
|
||||
static void DropURL(NSString* title, NSURL* url, BookmarkItem* parent, int index);
|
||||
|
||||
public:
|
||||
// Global counter and pointers to our singletons.
|
||||
|
|
|
@ -182,11 +182,11 @@
|
|||
NSPopUpButton* popup = [mBrowserWindowController getAddBookmarkFolder];
|
||||
BookmarksService::ConstructAddBookmarkFolderList(popup, item);
|
||||
|
||||
[NSApp beginSheet: [mBrowserWindowController getAddBookmarkSheetWindow]
|
||||
modalForWindow: [mBrowserWindowController window]
|
||||
modalDelegate: nil //self
|
||||
didEndSelector: nil //@selector(sheetDidEnd:)
|
||||
contextInfo: nil];
|
||||
[NSApp beginSheet: [mBrowserWindowController getAddBookmarkSheetWindow]
|
||||
modalForWindow: [mBrowserWindowController window]
|
||||
modalDelegate: nil //self
|
||||
didEndSelector: nil //@selector(sheetDidEnd:)
|
||||
contextInfo: nil];
|
||||
}
|
||||
|
||||
-(void)endAddBookmark: (int)aCode
|
||||
|
@ -299,10 +299,10 @@
|
|||
int count = [itemsToDelete count];
|
||||
for (int i = 0; i < count; i++) {
|
||||
BookmarkItem* item = [itemsToDelete objectAtIndex: i];
|
||||
[self deleteBookmark: item];
|
||||
[self deleteBookmark: item];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-(void)deleteBookmark:(id)aItem
|
||||
{
|
||||
|
@ -346,7 +346,7 @@
|
|||
content->GetAttr(kNameSpaceID_None, BookmarksService::gHrefAtom, href);
|
||||
if (!href.IsEmpty()) {
|
||||
NSString* url = [NSString stringWithCharacters: href.get() length: href.Length()];
|
||||
[[[mBrowserWindowController getBrowserWrapper] getBrowserView] loadURI:[NSURL URLWithString: url] flags: NSLoadFlagsNone];
|
||||
[[[mBrowserWindowController getBrowserWrapper] getBrowserView] loadURI:[NSURL URLWithString: url] flags: NSLoadFlagsNone];
|
||||
// Focus and activate our content area.
|
||||
[[[mBrowserWindowController getBrowserWrapper] getBrowserView] setActive: YES];
|
||||
}
|
||||
|
@ -367,7 +367,7 @@
|
|||
//
|
||||
- (BOOL)outlineView:(NSOutlineView *)outlineView shouldEditTableColumn:(NSTableColumn *)tableColumn item:(id)item
|
||||
{
|
||||
return NO;
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (id)outlineView:(NSOutlineView *)outlineView child:(int)index ofItem:(id)item
|
||||
|
@ -436,12 +436,12 @@
|
|||
|
||||
- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item
|
||||
{
|
||||
NSString *columnName = [tableColumn identifier];
|
||||
NSMutableAttributedString *cellValue = [[NSMutableAttributedString alloc] init];
|
||||
NSFileWrapper *fileWrapper = [[NSFileWrapper alloc] initRegularFileWithContents:nil];
|
||||
NSTextAttachment *textAttachment = [[NSTextAttachment alloc] initWithFileWrapper:fileWrapper];
|
||||
NSMutableAttributedString *attachmentAttrString = nil;
|
||||
NSCell *attachmentAttrStringCell;
|
||||
NSString *columnName = [tableColumn identifier];
|
||||
NSMutableAttributedString *cellValue = [[NSMutableAttributedString alloc] init];
|
||||
NSFileWrapper *fileWrapper = [[NSFileWrapper alloc] initRegularFileWithContents:nil];
|
||||
NSTextAttachment *textAttachment = [[NSTextAttachment alloc] initWithFileWrapper:fileWrapper];
|
||||
NSMutableAttributedString *attachmentAttrString = nil;
|
||||
NSCell *attachmentAttrStringCell;
|
||||
|
||||
if ([columnName isEqualToString: @"name"]) {
|
||||
nsIContent* content = [item contentNode];
|
||||
|
@ -449,8 +449,7 @@
|
|||
content->GetAttr(kNameSpaceID_None, BookmarksService::gNameAtom, nameAttr);
|
||||
|
||||
//Set cell's textual contents
|
||||
[cellValue replaceCharactersInRange:NSMakeRange(0, [cellValue length])
|
||||
withString:[NSString stringWithCharacters: nameAttr.get() length: nameAttr.Length()]];
|
||||
[cellValue replaceCharactersInRange:NSMakeRange(0, [cellValue length]) withString:[NSString stringWithCharacters: nameAttr.get() length: nameAttr.Length()]];
|
||||
|
||||
//Create an attributed string to hold the empty attachment, then release the components.
|
||||
attachmentAttrString = [[NSMutableAttributedString attributedStringWithAttachment:textAttachment] retain];
|
||||
|
@ -458,9 +457,7 @@
|
|||
[fileWrapper release];
|
||||
|
||||
//Get the cell of the text attachment.
|
||||
attachmentAttrStringCell = (NSCell *)[(NSTextAttachment *)[attachmentAttrString attribute:NSAttachmentAttributeName
|
||||
atIndex:0
|
||||
effectiveRange:nil] attachmentCell];
|
||||
attachmentAttrStringCell = (NSCell *)[(NSTextAttachment *)[attachmentAttrString attribute:NSAttachmentAttributeName atIndex:0 effectiveRange:nil] attachmentCell];
|
||||
//Figure out which image to add, and set the cell's image.
|
||||
// Use the bookmark groups image for groups.
|
||||
if ([self outlineView:outlineView isItemExpandable:item]) {
|
||||
|
@ -521,73 +518,97 @@
|
|||
#endif
|
||||
}
|
||||
|
||||
- (void)reloadDataForItem:(id)item reloadChildren: (BOOL)aReloadChildren
|
||||
{
|
||||
printf("Reloading?\n");
|
||||
if (!item)
|
||||
[mOutlineView reloadData];
|
||||
else if ([mOutlineView isItemExpanded: item])
|
||||
[mOutlineView reloadItem: item reloadChildren: aReloadChildren];
|
||||
}
|
||||
|
||||
- (BOOL)outlineView:(NSOutlineView*)outlineView acceptDrop:(id <NSDraggingInfo>)info item:(id)item childIndex:(int)index
|
||||
- (BOOL)outlineView:(NSOutlineView *)ov writeItems:(NSArray*)items toPasteboard:(NSPasteboard*)pboard
|
||||
{
|
||||
BookmarkItem* beforeItem = nil;
|
||||
nsCOMPtr<nsIDOMElement> beforeElt;
|
||||
nsCOMPtr<nsIDOMElement> folderElt;
|
||||
nsCOMPtr<nsIContent> folderContent;
|
||||
|
||||
if (index == NSOutlineViewDropOnItemIndex)
|
||||
if (!mBookmarks || [mOutlineView selectedRow] == -1) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
#ifdef FILTER_DESCENDANT_ON_DRAG
|
||||
NSArray *toDrag = BookmarksService::FilterOutDescendantsForDrag(items);
|
||||
#else
|
||||
NSArray *toDrag = items;
|
||||
#endif
|
||||
int count = [toDrag count];
|
||||
if (count > 0) {
|
||||
// Create Pasteboard Data
|
||||
NSMutableArray *draggedID = [NSMutableArray arrayWithCapacity: count];
|
||||
for (int i = 0; i < count; i++)
|
||||
[draggedID addObject: [[toDrag objectAtIndex: i] contentID]];
|
||||
[pboard declareTypes: [NSArray arrayWithObject: @"MozBookmarkType"] owner: self];
|
||||
[pboard setPropertyList: draggedID forType: @"MozBookmarkType"];
|
||||
return YES;
|
||||
}
|
||||
|
||||
// get the folder element
|
||||
if (!item)
|
||||
mBookmarks->GetRootContent(getter_AddRefs(folderContent));
|
||||
else
|
||||
folderContent = [item contentNode];
|
||||
folderElt = do_QueryInterface(folderContent);
|
||||
|
||||
// get the element to insert before, if there is one
|
||||
PRInt32 childCount = 0;
|
||||
folderContent->ChildCount(childCount);
|
||||
if (index < childCount)
|
||||
beforeItem = [[outlineView dataSource] outlineView:outlineView child:index ofItem:item];
|
||||
if (beforeItem)
|
||||
beforeElt = do_QueryInterface([beforeItem contentNode]);
|
||||
|
||||
// insert the dragged stuff into bookmarks
|
||||
BookmarksService::CompleteBookmarkDrag([info draggingPasteboard], folderElt, beforeElt,
|
||||
BookmarksService::CHInsertBefore);
|
||||
|
||||
return YES;
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (NSDragOperation)outlineView:(NSOutlineView*)outlineView validateDrop:(id <NSDraggingInfo>)info proposedItem:(id)item proposedChildIndex:(int)index
|
||||
|
||||
- (NSDragOperation)outlineView:(NSOutlineView*)ov validateDrop:(id <NSDraggingInfo>)info proposedItem:(id)item proposedChildIndex:(int)index
|
||||
{
|
||||
NSArray* types = [[info draggingPasteboard] types];
|
||||
|
||||
// if the index is -1, deny the drop
|
||||
if (index == NSOutlineViewDropOnItemIndex)
|
||||
return NSDragOperationNone;
|
||||
|
||||
return NSDragOperationGeneric;
|
||||
}
|
||||
|
||||
- (BOOL)outlineView:(NSOutlineView *)outlineView writeItems:(NSArray*)items toPasteboard:(NSPasteboard*)pboard
|
||||
{
|
||||
NSMutableArray* contentIds = [NSMutableArray array];
|
||||
|
||||
for (unsigned int i = 0; i < [items count]; ++i) {
|
||||
nsCOMPtr<nsIContent> content = [[items objectAtIndex:i] contentNode];
|
||||
PRUint32 contentId;
|
||||
content->GetContentID(&contentId);
|
||||
[contentIds addObject:[NSNumber numberWithInt:contentId]];
|
||||
if ([types containsObject: @"MozBookmarkType"]) {
|
||||
NSArray *draggedIDs = [[info draggingPasteboard] propertyListForType: @"MozBookmarkType"];
|
||||
BookmarkItem* parent;
|
||||
parent = (item) ? item : BookmarksService::GetRootItem();
|
||||
return (BookmarksService::IsBookmarkDropValid(parent, index, draggedIDs)) ? NSDragOperationGeneric : NSDragOperationNone;
|
||||
} else if ([types containsObject: @"MozURLType"]) {
|
||||
return NSDragOperationGeneric;
|
||||
}
|
||||
|
||||
[pboard declareTypes:[NSArray arrayWithObject:@"MozBookmarkType"] owner:outlineView];
|
||||
[pboard setPropertyList:contentIds forType:@"MozBookmarkType"];
|
||||
|
||||
return YES;
|
||||
return NSDragOperationNone;
|
||||
}
|
||||
|
||||
- (BOOL)outlineView:(NSOutlineView*)ov acceptDrop:(id <NSDraggingInfo>)info item:(id)item childIndex:(int)index {
|
||||
NSArray *types = [[info draggingPasteboard] types];
|
||||
BookmarkItem* parent = (item) ? item : BookmarksService::GetRootItem();
|
||||
|
||||
if ([types containsObject: @"MozBookmarkType"]) {
|
||||
NSArray *draggedItems = [[info draggingPasteboard] propertyListForType: @"MozBookmarkType"];
|
||||
BookmarksService::PerformBookmarkDrop(parent, index, draggedItems);
|
||||
return YES;
|
||||
} else if ([types containsObject: @"MozURLType"]) {
|
||||
NSDictionary* data = [[info draggingPasteboard] propertyListForType: @"MozURLType"];
|
||||
nsCOMPtr<nsIDOMElement> parentElt;
|
||||
parentElt = do_QueryInterface([parent contentNode]);
|
||||
|
||||
PRInt32 childCount = 0;
|
||||
[item contentNode]->ChildCount(childCount);
|
||||
|
||||
if (index >= childCount)
|
||||
return NO;
|
||||
|
||||
BookmarkItem* beforeItem;
|
||||
beforeItem = [[ov dataSource] outlineView:ov child:index ofItem:item];
|
||||
|
||||
if (!beforeItem)
|
||||
return NO;
|
||||
|
||||
nsCOMPtr<nsIDOMElement> beforeElt;
|
||||
beforeElt = do_QueryInterface([beforeItem contentNode]);
|
||||
|
||||
nsAutoString url; url.AssignWithConversion([[data objectForKey:@"url"] cString]);
|
||||
nsAutoString title; title.AssignWithConversion([[data objectForKey:@"title"] cString]);
|
||||
BookmarksService::AddBookmarkToFolder(url, title, parentElt, beforeElt);
|
||||
return YES;
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void)reloadDataForItem:(id)item reloadChildren: (BOOL)aReloadChildren
|
||||
{
|
||||
if (!item)
|
||||
[mOutlineView reloadData];
|
||||
else if ([mOutlineView isItemExpanded: item])
|
||||
[mOutlineView reloadItem: item reloadChildren: aReloadChildren];
|
||||
}
|
||||
|
||||
-(IBAction)openBookmarkInNewTab:(id)aSender
|
||||
{
|
||||
|
@ -711,19 +732,36 @@
|
|||
@implementation BookmarkItem
|
||||
-(nsIContent*)contentNode
|
||||
{
|
||||
return mContentNode;
|
||||
return mContentNode;
|
||||
}
|
||||
|
||||
- (NSNumber*)contentID
|
||||
{
|
||||
PRUint32 contentID = 0;
|
||||
mContentNode->GetContentID(&contentID);
|
||||
return [NSNumber numberWithInt: contentID];
|
||||
}
|
||||
|
||||
- (NSString *)description
|
||||
{
|
||||
nsCOMPtr<nsIContent> item = [self contentNode];
|
||||
nsCOMPtr<nsIDOMElement> element(do_QueryInterface(item));
|
||||
nsAutoString href;
|
||||
element->GetAttribute(NS_LITERAL_STRING("name"), href);
|
||||
NSString* info = [NSString stringWithCharacters: href.get() length: href.Length()];
|
||||
return [NSString stringWithFormat:@"<BookmarkItem, name = \"%@\">", info];
|
||||
}
|
||||
|
||||
-(void)setContentNode: (nsIContent*)aContentNode
|
||||
{
|
||||
mContentNode = aContentNode;
|
||||
mContentNode = aContentNode;
|
||||
}
|
||||
|
||||
- (id)copyWithZone:(NSZone *)aZone
|
||||
{
|
||||
BookmarkItem* copy = [[[self class] allocWithZone: aZone] init];
|
||||
[copy setContentNode: mContentNode];
|
||||
return copy;
|
||||
BookmarkItem* copy = [[[self class] allocWithZone: aZone] init];
|
||||
[copy setContentNode: mContentNode];
|
||||
return copy;
|
||||
}
|
||||
|
||||
@end
|
||||
|
@ -732,25 +770,26 @@
|
|||
static void
|
||||
StripWhitespaceNodes(nsIContent* aElement)
|
||||
{
|
||||
PRInt32 childCount;
|
||||
aElement->ChildCount(childCount);
|
||||
for (PRInt32 i = 0; i < childCount; i++) {
|
||||
nsCOMPtr<nsIContent> child;
|
||||
aElement->ChildAt(i, *getter_AddRefs(child));
|
||||
nsCOMPtr<nsITextContent> text = do_QueryInterface(child);
|
||||
if (text) {
|
||||
PRBool isEmpty;
|
||||
text->IsOnlyWhitespace(&isEmpty);
|
||||
if (isEmpty) {
|
||||
// This node contained nothing but whitespace.
|
||||
// Remove it from the content model.
|
||||
aElement->RemoveChildAt(i, PR_TRUE);
|
||||
i--; // Decrement our count, since we just removed this child.
|
||||
childCount--; // Also decrement our total count.
|
||||
}
|
||||
}
|
||||
else StripWhitespaceNodes(child);
|
||||
PRInt32 childCount = 0;
|
||||
aElement->ChildCount(childCount);
|
||||
for (PRInt32 i = 0; i < childCount; i++) {
|
||||
nsCOMPtr<nsIContent> child;
|
||||
aElement->ChildAt(i, *getter_AddRefs(child));
|
||||
nsCOMPtr<nsITextContent> text = do_QueryInterface(child);
|
||||
if (text) {
|
||||
PRBool isEmpty = PR_FALSE;
|
||||
text->IsOnlyWhitespace(&isEmpty);
|
||||
if (isEmpty) {
|
||||
// This node contained nothing but whitespace.
|
||||
// Remove it from the content model.
|
||||
aElement->RemoveChildAt(i, PR_TRUE);
|
||||
i--; // Decrement our count, since we just removed this child.
|
||||
childCount--; // Also decrement our total count.
|
||||
}
|
||||
}
|
||||
else
|
||||
StripWhitespaceNodes(child);
|
||||
}
|
||||
}
|
||||
|
||||
PRUint32 BookmarksService::gRefCnt = 0;
|
||||
|
@ -792,34 +831,50 @@ BookmarksService::~BookmarksService()
|
|||
void
|
||||
BookmarksService::GetRootContent(nsIContent** aResult)
|
||||
{
|
||||
*aResult = nsnull;
|
||||
if (gBookmarks) {
|
||||
nsCOMPtr<nsIDOMElement> elt;
|
||||
nsCOMPtr<nsIDOMDocument> domDoc(do_QueryInterface(gBookmarks));
|
||||
domDoc->GetDocumentElement(getter_AddRefs(elt));
|
||||
elt->QueryInterface(NS_GET_IID(nsIContent), (void**)aResult); // Addref happens here.
|
||||
}
|
||||
*aResult = nsnull;
|
||||
if (gBookmarks) {
|
||||
nsCOMPtr<nsIDOMDocument> domDoc(do_QueryInterface(gBookmarks));
|
||||
if (!domDoc) return;
|
||||
|
||||
nsCOMPtr<nsIDOMElement> elt;
|
||||
domDoc->GetDocumentElement(getter_AddRefs(elt));
|
||||
if (elt)
|
||||
elt->QueryInterface(NS_GET_IID(nsIContent), (void**)aResult); // Addref happens here.
|
||||
}
|
||||
}
|
||||
|
||||
BookmarkItem*
|
||||
BookmarksService::GetRootItem() {
|
||||
nsCOMPtr<nsIContent> rootContent;
|
||||
BookmarksService::GetRootContent(getter_AddRefs(rootContent));
|
||||
BookmarkItem* rootItem = BookmarksService::GetWrapperFor(rootContent);
|
||||
return rootItem;
|
||||
}
|
||||
|
||||
BookmarkItem*
|
||||
BookmarksService::GetWrapperFor(nsIContent* aContent)
|
||||
{
|
||||
if (!gDictionary)
|
||||
gDictionary = [[NSMutableDictionary alloc] initWithCapacity: 30];
|
||||
|
||||
PRUint32 contentID;
|
||||
aContent->GetContentID(&contentID);
|
||||
|
||||
BookmarkItem* item = [gDictionary objectForKey: [NSNumber numberWithInt: contentID]];
|
||||
if (item)
|
||||
return item;
|
||||
else {
|
||||
// Create an item.
|
||||
item = [[[BookmarkItem alloc] init] autorelease]; // The dictionary retains us.
|
||||
[item setContentNode: aContent];
|
||||
[gDictionary setObject: item forKey: [NSNumber numberWithInt: contentID]];
|
||||
}
|
||||
if (!gDictionary)
|
||||
gDictionary = [[NSMutableDictionary alloc] initWithCapacity: 30];
|
||||
|
||||
PRUint32 contentID = 0;
|
||||
aContent->GetContentID(&contentID);
|
||||
|
||||
BookmarkItem* item = [gDictionary objectForKey: [NSNumber numberWithInt: contentID]];
|
||||
if (item)
|
||||
return item;
|
||||
|
||||
// Create an item.
|
||||
item = [[[BookmarkItem alloc] init] autorelease]; // The dictionary retains us.
|
||||
[item setContentNode: aContent];
|
||||
[gDictionary setObject: item forKey: [NSNumber numberWithInt: contentID]];
|
||||
return item;
|
||||
}
|
||||
|
||||
BookmarkItem*
|
||||
BookmarksService::GetWrapperFor(PRUint32 contentID) {
|
||||
BookmarkItem* item = [gDictionary objectForKey: [NSNumber numberWithUnsignedInt: contentID]];
|
||||
return item;
|
||||
}
|
||||
|
||||
NSMenu*
|
||||
|
@ -841,7 +896,7 @@ BookmarksService::LocateMenu(nsIContent* aContent)
|
|||
}
|
||||
|
||||
void
|
||||
BookmarksService::BookmarkAdded(nsIContent* aContainer, nsIContent* aChild)
|
||||
BookmarksService::BookmarkAdded(nsIContent* aContainer, nsIContent* aChild, bool shouldFlush = true)
|
||||
{
|
||||
if (!gInstances || !gDictionary)
|
||||
return;
|
||||
|
@ -883,11 +938,12 @@ BookmarksService::BookmarkAdded(nsIContent* aContainer, nsIContent* aChild)
|
|||
}
|
||||
}
|
||||
|
||||
FlushBookmarks();
|
||||
if (shouldFlush)
|
||||
FlushBookmarks();
|
||||
}
|
||||
|
||||
void
|
||||
BookmarksService::BookmarkChanged(nsIContent* aItem)
|
||||
BookmarksService::BookmarkChanged(nsIContent* aItem, bool shouldFlush = true)
|
||||
{
|
||||
if (!gInstances || !gDictionary)
|
||||
return;
|
||||
|
@ -902,11 +958,12 @@ BookmarksService::BookmarkChanged(nsIContent* aItem)
|
|||
}
|
||||
}
|
||||
|
||||
FlushBookmarks();
|
||||
if (shouldFlush)
|
||||
FlushBookmarks();
|
||||
}
|
||||
|
||||
void
|
||||
BookmarksService::BookmarkRemoved(nsIContent* aContainer, nsIContent* aChild)
|
||||
BookmarksService::BookmarkRemoved(nsIContent* aContainer, nsIContent* aChild, bool shouldFlush = true)
|
||||
{
|
||||
if (!gInstances)
|
||||
return;
|
||||
|
@ -940,14 +997,15 @@ BookmarksService::BookmarkRemoved(nsIContent* aContainer, nsIContent* aChild)
|
|||
else {
|
||||
// We're the menu.
|
||||
NSMenu* menu = LocateMenu(aContainer);
|
||||
PRUint32 contentID;
|
||||
PRUint32 contentID = 0;
|
||||
aChild->GetContentID(&contentID);
|
||||
NSMenuItem* childItem = [menu itemWithTag: contentID];
|
||||
[menu removeItem: childItem];
|
||||
}
|
||||
}
|
||||
|
||||
FlushBookmarks();
|
||||
if (shouldFlush)
|
||||
FlushBookmarks();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -969,7 +1027,7 @@ BookmarksService::AddObserver()
|
|||
NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(profileDir));
|
||||
profileDir->Append(NS_LITERAL_STRING("bookmarks.xml"));
|
||||
|
||||
PRBool fileExists;
|
||||
PRBool fileExists = PR_FALSE;
|
||||
profileDir->Exists(&fileExists);
|
||||
|
||||
// If the bookmarks file does not exist, copy from the defaults so we don't
|
||||
|
@ -1119,9 +1177,10 @@ BookmarksService::FlushBookmarks()
|
|||
nsCOMPtr<nsIOutputStream> outputStream;
|
||||
NS_NewLocalFileOutputStream(getter_AddRefs(outputStream), bookmarksFile);
|
||||
|
||||
nsCOMPtr<nsIDOMDocument> domDoc(do_QueryInterface(gBookmarks));
|
||||
|
||||
nsCOMPtr<nsIDOMSerializer> domSerializer(do_CreateInstance(NS_XMLSERIALIZER_CONTRACTID));
|
||||
nsCOMPtr<nsIDOMDocument> domDoc(do_QueryInterface(gBookmarks));
|
||||
|
||||
nsCOMPtr<nsIDOMSerializer> domSerializer(do_CreateInstance(NS_XMLSERIALIZER_CONTRACTID));
|
||||
if (domSerializer)
|
||||
domSerializer->SerializeToStream(domDoc, outputStream, nsnull);
|
||||
}
|
||||
|
||||
|
@ -1592,63 +1651,160 @@ BookmarksService::CreateIconForBookmark(nsIDOMElement* aElement)
|
|||
return [NSImage imageNamed:@"groupbookmark"];
|
||||
}
|
||||
|
||||
void
|
||||
BookmarksService::DragBookmark(nsIDOMElement* aElement, NSView* aView, NSEvent* aEvent)
|
||||
{
|
||||
NSPasteboard *pboard;
|
||||
NSString* title;
|
||||
// Is searchItem equal to bookmark or bookmark's parent, grandparent, etc?
|
||||
BOOL
|
||||
BookmarksService::DoAncestorsIncludeNode(BookmarkItem* bookmark, BookmarkItem* searchItem) {
|
||||
nsCOMPtr<nsIContent> search = [searchItem contentNode];
|
||||
nsCOMPtr<nsIContent> current = [bookmark contentNode];
|
||||
nsCOMPtr<nsIContent> root;
|
||||
GetRootContent(getter_AddRefs(root));
|
||||
|
||||
// If the search item is the root node, return yes immediatly
|
||||
if (search == root)
|
||||
return YES;
|
||||
|
||||
// for each ancestor
|
||||
while (current) {
|
||||
// If this is the root node we can't search farther, and there was no match
|
||||
if (current == root)
|
||||
return NO;
|
||||
|
||||
// If the two nodes match, then the search term is an ancestor of the given bookmark
|
||||
if (search == current)
|
||||
return YES;
|
||||
|
||||
// If a match wasn't found, set up the next node to compare
|
||||
nsCOMPtr<nsIContent> oldCurrent = current;
|
||||
oldCurrent->GetParent(*getter_AddRefs(current));
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(aElement);
|
||||
PRUint32 contentId;
|
||||
content->GetContentID(&contentId);
|
||||
|
||||
pboard = [NSPasteboard pasteboardWithName:NSDragPboard];
|
||||
[pboard declareTypes:[NSArray arrayWithObject:@"MozBookmarkType"] owner:aView];
|
||||
[pboard setPropertyList:[NSArray arrayWithObject:[NSNumber numberWithInt:contentId]] forType:@"MozBookmarkType"];
|
||||
|
||||
nsAutoString nameStr;
|
||||
aElement->GetAttribute(NS_LITERAL_STRING("name"), nameStr);
|
||||
title = [NSString stringWithCharacters: nameStr.get() length: nameStr.Length()];
|
||||
|
||||
[aView dragImage: [MainController createImageForDragging: CreateIconForBookmark(aElement) title:title]
|
||||
at:NSMakePoint(0,0) offset:NSMakeSize(0,0)
|
||||
event:aEvent pasteboard:pboard source:aView slideBack:YES];
|
||||
return NO;
|
||||
}
|
||||
|
||||
void
|
||||
BookmarksService::CompleteBookmarkDrag(NSPasteboard* aPasteboard, nsIDOMElement* aFolderElt,
|
||||
nsIDOMElement* aBeforeElt, int aPosition)
|
||||
|
||||
#ifdef FILTER_DESCENDANT_ON_DRAG
|
||||
/*
|
||||
this has been disabled because it is too slow, and can cause a large
|
||||
delay when the user is dragging lots of items. this needs to get
|
||||
fixed someday.
|
||||
|
||||
It should filter out every node whose parent is also being dragged.
|
||||
*/
|
||||
|
||||
NSArray*
|
||||
BookmarksService::FilterOutDescendantsForDrag(NSArray* nodes)
|
||||
{
|
||||
NSArray* contentIds;
|
||||
|
||||
nsCOMPtr<nsIDOMElement> beforeElt = aBeforeElt;
|
||||
if (aPosition == BookmarksService::CHInsertAfter && aBeforeElt) {
|
||||
nsCOMPtr<nsIDOMNode> beforeNode;
|
||||
aBeforeElt->GetNextSibling(getter_AddRefs(beforeNode));
|
||||
beforeElt = do_QueryInterface(beforeNode);
|
||||
}
|
||||
|
||||
if (aPosition == BookmarksService::CHInsertInto) {
|
||||
aFolderElt = aBeforeElt;
|
||||
beforeElt = nsnull;
|
||||
}
|
||||
NSMutableArray *toDrag = [NSMutableArray arrayWithArray: nodes];
|
||||
unsigned int i = 0;
|
||||
|
||||
while (i < [toDrag count]) {
|
||||
BookmarkItem* item = [toDrag objectAtIndex: i];
|
||||
bool matchFound = false;
|
||||
|
||||
// check for recognized drag types
|
||||
contentIds = [aPasteboard propertyListForType: @"MozBookmarkType"];
|
||||
if (contentIds) {
|
||||
// drag type is chimera bookmarks
|
||||
for (unsigned int i = 0; i < [contentIds count]; ++i) {
|
||||
BookmarkItem* item = [gDictionary objectForKey: [contentIds objectAtIndex:i]];
|
||||
nsCOMPtr<nsIDOMElement> bookmarkElt = do_QueryInterface([item contentNode]);
|
||||
MoveBookmarkToFolder(bookmarkElt, aFolderElt, beforeElt);
|
||||
for (unsigned int j = 0; j < [toDrag count] && matchFound == NO; j++) {
|
||||
if (i != j) // Don't compare to self, will always match
|
||||
matchFound = BookmarksService::DoAncestorsIncludeNode(item, [toDrag objectAtIndex: j]);
|
||||
}
|
||||
} else {
|
||||
// add bookmark for chimera url type
|
||||
NSDictionary* data = [aPasteboard propertyListForType: @"MozURLType"];
|
||||
nsAutoString url; url.AssignWithConversion([[data objectForKey:@"url"] cString]);
|
||||
nsAutoString title; title.AssignWithConversion([[data objectForKey:@"title"] cString]);
|
||||
|
||||
AddBookmarkToFolder(url, title, aFolderElt, beforeElt);
|
||||
// if a match was found, remove the node from the array
|
||||
if (matchFound)
|
||||
[toDrag removeObjectAtIndex: i];
|
||||
else
|
||||
i++;
|
||||
}
|
||||
|
||||
return toDrag;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool
|
||||
BookmarksService::IsBookmarkDropValid(BookmarkItem* proposedParent, int index, NSArray* draggedIDs) {
|
||||
NSMutableArray *draggedItems = [NSMutableArray arrayWithCapacity: [draggedIDs count]];
|
||||
BOOL toolbarRootMoving = NO;
|
||||
|
||||
for (unsigned int i = 0; i < [draggedIDs count]; i++) {
|
||||
NSNumber* contentID = [draggedIDs objectAtIndex: i];
|
||||
BookmarkItem* bookmarkItem = BookmarksService::GetWrapperFor([contentID unsignedIntValue]);
|
||||
nsCOMPtr<nsIContent> itemContent = [bookmarkItem contentNode];
|
||||
nsCOMPtr<nsIDOMElement> itemElement(do_QueryInterface(itemContent));
|
||||
|
||||
if (itemElement == BookmarksService::gToolbarRoot)
|
||||
toolbarRootMoving = YES;
|
||||
|
||||
if (bookmarkItem)
|
||||
[draggedItems addObject: bookmarkItem];
|
||||
}
|
||||
|
||||
// If we are being dropped into the top level, allow it
|
||||
if ([proposedParent contentNode] == [BookmarksService::GetRootItem() contentNode])
|
||||
return true;
|
||||
|
||||
// If we are not being dropped on the top level, and the toolbar root is being moved, disallow
|
||||
if (toolbarRootMoving)
|
||||
return false;
|
||||
|
||||
// Make sure that we are not being dropped into one of our own children
|
||||
// If the proposed parent, or any of it's ancestors matches one of the nodes being dragged
|
||||
// then deny the drag.
|
||||
|
||||
for (unsigned int i = 0; i < [draggedItems count]; i++) {
|
||||
if (BookmarksService::DoAncestorsIncludeNode(proposedParent, [draggedItems objectAtIndex: i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BookmarksService::PerformBookmarkDrop(BookmarkItem* parent, int index, NSArray* draggedIDs) {
|
||||
NSEnumerator *enumerator = [draggedIDs reverseObjectEnumerator];
|
||||
NSNumber *contentID;
|
||||
|
||||
// for each item being dragged
|
||||
while ( (contentID = [enumerator nextObject]) ) {
|
||||
|
||||
// get dragged node
|
||||
nsCOMPtr<nsIContent> draggedNode = [GetWrapperFor([contentID unsignedIntValue]) contentNode];
|
||||
|
||||
// get the dragged nodes parent
|
||||
nsCOMPtr<nsIContent> draggedParent;
|
||||
if (draggedNode)
|
||||
draggedNode->GetParent(*getter_AddRefs(draggedParent));
|
||||
|
||||
// get the proposed parent
|
||||
nsCOMPtr<nsIContent> proposedParent = [parent contentNode];
|
||||
|
||||
PRInt32 existingIndex = 0;
|
||||
if (draggedParent)
|
||||
draggedParent->IndexOf(draggedNode, existingIndex);
|
||||
|
||||
// if the deleted nodes parent and the proposed parents are equal
|
||||
// and if the deleted point is eariler in the list than the inserted point
|
||||
if (proposedParent == draggedParent && existingIndex < index) {
|
||||
index--; // if so, move the inserted point up one to compensate
|
||||
}
|
||||
|
||||
// remove it from the tree
|
||||
if (draggedParent)
|
||||
draggedParent->RemoveChildAt(existingIndex, PR_TRUE);
|
||||
BookmarkRemoved(draggedParent, draggedNode, false);
|
||||
|
||||
// insert into new position
|
||||
if (proposedParent)
|
||||
proposedParent->InsertChildAt(draggedNode, index, PR_TRUE, PR_TRUE);
|
||||
BookmarkAdded(proposedParent, draggedNode, false);
|
||||
}
|
||||
|
||||
FlushBookmarks();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
BookmarksService::DropURL(NSString* title, NSURL* url, BookmarkItem* parent, int index)
|
||||
{
|
||||
NSLog(@"DropURL not implemented yet\n");
|
||||
}
|
||||
|
||||
|
|
|
@ -309,18 +309,82 @@
|
|||
|
||||
- (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender
|
||||
{
|
||||
return YES;
|
||||
BookmarkItem* parent;
|
||||
int index = 0;
|
||||
NSArray *draggedItems = [[sender draggingPasteboard] propertyListForType: @"MozBookmarkType"];
|
||||
|
||||
// If we are dropping into a folder
|
||||
if (mDragInsertionPosition == BookmarksService::CHInsertInto) {
|
||||
nsCOMPtr<nsIDOMElement> parentElt = [mDragInsertionButton element];
|
||||
nsCOMPtr<nsIContent> parentContent(do_QueryInterface(parentElt));
|
||||
parent = BookmarksService::GetWrapperFor(parentContent);
|
||||
index = 0;
|
||||
}
|
||||
|
||||
// If we are dropping onto the toolbar directly
|
||||
else if (mDragInsertionPosition == BookmarksService::CHInsertBefore ||
|
||||
mDragInsertionPosition == BookmarksService::CHInsertAfter) {
|
||||
nsCOMPtr<nsIDOMElement> rootElt = BookmarksService::gToolbarRoot;
|
||||
nsCOMPtr<nsIContent> rootContent(do_QueryInterface(rootElt));
|
||||
parent = BookmarksService::GetWrapperFor(rootContent);
|
||||
index = [mButtons indexOfObject: mDragInsertionButton];
|
||||
if (index == NSNotFound)
|
||||
rootContent->ChildCount(index);
|
||||
else if (mDragInsertionPosition == BookmarksService::CHInsertAfter)
|
||||
index++;
|
||||
} else {
|
||||
mDragInsertionButton = nil;
|
||||
mDragInsertionPosition = BookmarksService::CHInsertNone;
|
||||
[self setNeedsDisplay:YES];
|
||||
return NO;
|
||||
}
|
||||
|
||||
bool valid = BookmarksService::IsBookmarkDropValid(parent, index, draggedItems);
|
||||
if (!valid) {
|
||||
mDragInsertionButton = nil;
|
||||
mDragInsertionPosition = BookmarksService::CHInsertNone;
|
||||
[self setNeedsDisplay:YES];
|
||||
}
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
||||
- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
|
||||
{
|
||||
BookmarksService::CompleteBookmarkDrag([sender draggingPasteboard], BookmarksService::gToolbarRoot,
|
||||
mDragInsertionButton ? [mDragInsertionButton element] : nil,
|
||||
mDragInsertionPosition);
|
||||
|
||||
BookmarkItem* parent;
|
||||
int index = 0;
|
||||
NSArray *draggedItems = [[sender draggingPasteboard] propertyListForType: @"MozBookmarkType"];
|
||||
|
||||
// If we are dropping into a folder
|
||||
if (mDragInsertionPosition == BookmarksService::CHInsertInto) {
|
||||
nsCOMPtr<nsIDOMElement> parentElt = [mDragInsertionButton element];
|
||||
nsCOMPtr<nsIContent> parentContent(do_QueryInterface(parentElt));
|
||||
parent = BookmarksService::GetWrapperFor(parentContent);
|
||||
index = 0;
|
||||
}
|
||||
|
||||
// If we are dropping onto the toolbar directly
|
||||
else if (mDragInsertionPosition == BookmarksService::CHInsertBefore ||
|
||||
mDragInsertionPosition == BookmarksService::CHInsertAfter) {
|
||||
nsCOMPtr<nsIDOMElement> rootElt = BookmarksService::gToolbarRoot;
|
||||
nsCOMPtr<nsIContent> rootContent(do_QueryInterface(rootElt));
|
||||
parent = BookmarksService::GetWrapperFor(rootContent);
|
||||
index = [mButtons indexOfObject: mDragInsertionButton];
|
||||
if (index == NSNotFound)
|
||||
rootContent->ChildCount(index);
|
||||
else if (mDragInsertionPosition == BookmarksService::CHInsertAfter)
|
||||
index++;
|
||||
} else {
|
||||
mDragInsertionButton = nil;
|
||||
mDragInsertionPosition = BookmarksService::CHInsertNone;
|
||||
[self setNeedsDisplay:YES];
|
||||
return NO;
|
||||
}
|
||||
|
||||
BookmarksService::PerformBookmarkDrop(parent, index, draggedItems);
|
||||
|
||||
mDragInsertionButton = nil;
|
||||
mDragInsertionPosition = BookmarksService::CHInsertNone;
|
||||
|
||||
[self setNeedsDisplay:YES];
|
||||
|
||||
return YES;
|
||||
|
@ -329,14 +393,11 @@
|
|||
- (NSRect)insertionRectForButton:(NSView*)aButton position:(int) aPosition
|
||||
{
|
||||
if (aPosition == BookmarksService::CHInsertInto) {
|
||||
return NSMakeRect([aButton frame].origin.x, [aButton frame].origin.y,
|
||||
[aButton frame].size.width, [aButton frame].size.height);
|
||||
return NSMakeRect([aButton frame].origin.x, [aButton frame].origin.y, [aButton frame].size.width, [aButton frame].size.height);
|
||||
} else if (aPosition == BookmarksService::CHInsertAfter) {
|
||||
return NSMakeRect([aButton frame].origin.x+[aButton frame].size.width, [aButton frame].origin.y,
|
||||
2, [aButton frame].size.height);
|
||||
return NSMakeRect([aButton frame].origin.x+[aButton frame].size.width, [aButton frame].origin.y, 2, [aButton frame].size.height);
|
||||
} else {// if (aPosition == BookmarksService::CHInsertBefore) {
|
||||
return NSMakeRect([aButton frame].origin.x - 2, [aButton frame].origin.y,
|
||||
2, [aButton frame].size.height);
|
||||
return NSMakeRect([aButton frame].origin.x - 2, [aButton frame].origin.y, 2, [aButton frame].size.height);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -104,7 +104,7 @@ static void FindOptionWithContentID(nsIDOMHTMLSelectElement* aSel, PRUint32 aID,
|
|||
|
||||
-(id)initWithSelect:(nsIDOMHTMLSelectElement*)aSel
|
||||
{
|
||||
if (self = [super init]) {
|
||||
if ( (self = [super init]) ) {
|
||||
mSelectElt = aSel;
|
||||
}
|
||||
return self;
|
||||
|
|
Загрузка…
Ссылка в новой задаче