--- chimera/BookmarksService.mm 2002/03/10 08:14:36 1.17 +++ chimera/BookmarksService.mm 2002/04/17 23:55:25 1.24 @@ -60,20 +60,22 @@ { [super init]; mBookmarks = nsnull; + mCachedParent = nsnull; + mCachedHref = nil; return self; } -(void) dealloc { - [super dealloc]; + [super dealloc]; } -(void) windowClosing { - if (mBookmarks) { - mBookmarks->RemoveObserver(); - delete mBookmarks; - } + if (mBookmarks) { + mBookmarks->RemoveObserver(); + delete mBookmarks; + } } -(void) ensureBookmarks @@ -91,59 +93,117 @@ -(IBAction)addBookmark:(id)aSender { - if (!mBookmarks) - return; - - nsCOMPtr content; + [self addBookmark: aSender useSelection: YES isFolder: NO]; +} + +-(IBAction)addFolder:(id)aSender +{ + [self addBookmark: aSender useSelection: YES isFolder: YES]; +} + +-(void)addBookmark:(id)aSender useSelection:(BOOL)aUseSel isFolder:(BOOL)aIsFolder +{ + if (!mBookmarks) + return; + + nsCOMPtr content; + if (aUseSel) { int index = [mOutlineView selectedRow]; - + if (index >= 0) { - BookmarkItem* item = [mOutlineView itemAtRow: index]; - if ([mOutlineView isExpandable: item]) - content = [item contentNode]; + BookmarkItem* item = [mOutlineView itemAtRow: index]; + if ([mOutlineView isExpandable: item]) + content = [item contentNode]; } - - if (!content) - mBookmarks->GetRootContent(getter_AddRefs(content)); - - nsCOMPtr domDoc(do_QueryInterface(mBookmarks->gBookmarks)); - nsCOMPtr elt; - domDoc->CreateElementNS(NS_LITERAL_STRING("http://chimera.mozdev.org/bookmarks"), - NS_LITERAL_STRING("bookmark"), - getter_AddRefs(elt)); - - // Fetch the title of the current page and the URL. - nsCOMPtr webBrowser = getter_AddRefs([[[mBrowserWindowController getMyBrowserView] getBrowserView] getWebBrowser]); + } + + if (!content) + mBookmarks->GetRootContent(getter_AddRefs(content)); + + mCachedParent = content; + + nsCOMPtr domDoc(do_QueryInterface(mBookmarks->gBookmarks)); + + // Fetch the title of the current page and the URL. + nsAutoString title; + if (!aIsFolder) { + nsCOMPtr webBrowser = getter_AddRefs([[[mBrowserWindowController getMyBrowserView] + getBrowserView] getWebBrowser]); nsCOMPtr window; webBrowser->GetContentDOMWindow(getter_AddRefs(window)); nsCOMPtr htmlDoc; window->GetDocument(getter_AddRefs(htmlDoc)); nsCOMPtr pageDoc(do_QueryInterface(htmlDoc)); - - nsAutoString href; + + nsAutoString href; if (pageDoc) { - nsCOMPtr url; - pageDoc->GetDocumentURL(getter_AddRefs(url)); - nsCAutoString spec; - url->GetSpec(spec); - href.AssignWithConversion(spec.get()); + nsCOMPtr url; + pageDoc->GetDocumentURL(getter_AddRefs(url)); + nsCAutoString spec; + url->GetSpec(spec); + href.AssignWithConversion(spec.get()); } - - nsAutoString title; + + mCachedHref = [NSString stringWithCharacters: href.get() length: nsCRT::strlen(href.get())]; + [mCachedHref retain]; + nsCOMPtr htmlDocument(do_QueryInterface(htmlDoc)); if (htmlDocument) - htmlDocument->GetTitle(title); + htmlDocument->GetTitle(title); if (title.IsEmpty()) - title = href; - - elt->SetAttribute(NS_LITERAL_STRING("name"), title); - elt->SetAttribute(NS_LITERAL_STRING("href"), href); - - nsCOMPtr parent(do_QueryInterface(content)); - nsCOMPtr dummy; - parent->AppendChild(elt, getter_AddRefs(dummy)); + title = href; + } + else { + mCachedHref = nil; + title = NS_LITERAL_STRING("New Folder"); + } + + NSTextField* textField = [mBrowserWindowController getAddBookmarkTitle]; + [textField setStringValue: [NSString stringWithCharacters: title.get() length: nsCRT::strlen(title.get())]]; - mBookmarks->NotifyObservers(content, PR_TRUE); + [mBrowserWindowController cacheBookmarkDS: self]; + + [NSApp beginSheet: [mBrowserWindowController getAddBookmarkSheetWindow] + modalForWindow: [mBrowserWindowController window] + modalDelegate: nil //self + didEndSelector: nil //@selector(sheetDidEnd:) + contextInfo: nil]; +} + +-(void)endAddBookmark: (int)aCode +{ + if (aCode == 0) + return; + + const char* titleC = [[[mBrowserWindowController getAddBookmarkTitle] stringValue] cString]; + nsAutoString title; title.AssignWithConversion(titleC); + + nsAutoString tagName; + if (mCachedHref) + tagName = NS_LITERAL_STRING("bookmark"); + else + tagName = NS_LITERAL_STRING("folder"); + + nsCOMPtr domDoc(do_QueryInterface(mBookmarks->gBookmarks)); + nsCOMPtr elt; + domDoc->CreateElementNS(NS_LITERAL_STRING("http://chimera.mozdev.org/bookmarks/"), + tagName, + getter_AddRefs(elt)); + + elt->SetAttribute(NS_LITERAL_STRING("name"), title); + + if (mCachedHref) { + nsAutoString href; href.AssignWithConversion([mCachedHref cString]); + [mCachedHref release]; + elt->SetAttribute(NS_LITERAL_STRING("href"), href); + } + + nsCOMPtr parent(do_QueryInterface(mCachedParent)); + nsCOMPtr dummy; + parent->AppendChild(elt, getter_AddRefs(dummy)); + + nsCOMPtr childContent(do_QueryInterface(elt)); + mBookmarks->BookmarkAdded(mCachedParent, childContent); } -(IBAction)deleteBookmark: (id)aSender @@ -160,10 +220,10 @@ nsCOMPtr child(do_QueryInterface(content)); nsCOMPtr parent; child->GetParentNode(getter_AddRefs(parent)); + nsCOMPtr parentContent(do_QueryInterface(parent)); nsCOMPtr dummy; parent->RemoveChild(child, getter_AddRefs(dummy)); - nsCOMPtr parentContent(do_QueryInterface(parent)); - mBookmarks->NotifyObservers(parentContent, PR_TRUE); + mBookmarks->BookmarkRemoved(parentContent, content); int total = [mOutlineView numberOfRows]; if (index == total) @@ -196,6 +256,8 @@ nsCAutoString cstr; cstr.AssignWithConversion(href); NSString* url = [NSString stringWithCString: cstr.get()]; [[[mBrowserWindowController getMyBrowserView] getBrowserView] loadURI:[NSURL URLWithString: url] flags:NSLoadFlagsNone]; + // Focus and activate our content area. + [[[mBrowserWindowController getMyBrowserView] getBrowserView] setActive: YES]; } } } @@ -362,6 +424,8 @@ PRUint32 BookmarksService::gRefCnt = 0; nsIDocument* BookmarksService::gBookmarks = nsnull; NSMutableDictionary* BookmarksService::gDictionary = nil; MainController* BookmarksService::gMainController = nil; +NSMenu* BookmarksService::gBookmarksMenu = nil; +nsIDOMElement* BookmarksService::gToolbarRoot = nsnull; nsIAtom* BookmarksService::gFolderAtom = nsnull; nsIAtom* BookmarksService::gBookmarkAtom = nsnull; nsIAtom* BookmarksService::gHrefAtom = nsnull; @@ -370,7 +434,14 @@ nsVoidArray* BookmarksService::gInstance BookmarksService::BookmarksService(BookmarksDataSource* aDataSource) { - mDataSource = aDataSource; + mDataSource = aDataSource; + mToolbar = nil; +} + +BookmarksService::BookmarksService(BookmarksToolbar* aToolbar) +{ + mDataSource = nil; + mToolbar = aToolbar; } BookmarksService::~BookmarksService() @@ -410,37 +481,132 @@ BookmarksService::GetWrapperFor(nsIConte return item; } +NSMenu* +BookmarksService::LocateMenu(nsIContent* aContent) +{ + nsCOMPtr parent; + aContent->GetParent(*getter_AddRefs(parent)); + if (!parent) { + return BookmarksService::gBookmarksMenu; + } + + NSMenu* parentMenu = LocateMenu(parent); + + PRUint32 contentID; + aContent->GetContentID(&contentID); + + NSMenuItem* childMenu = [parentMenu itemWithTag: contentID]; + return [childMenu submenu]; +} + void -BookmarksService::NotifyObservers(nsIContent* aContainer, PRBool aReloadChildren) +BookmarksService::BookmarkAdded(nsIContent* aContainer, nsIContent* aChild) { - if (!gInstances) - return; - - PRInt32 count = gInstances->Count(); - for (PRInt32 i = 0; i < count; i++) { - BookmarksService* instance = (BookmarksService*)gInstances->ElementAt(i); - instance->NotifyObserver(aContainer, aReloadChildren); + if (!gInstances || !gDictionary) + return; + + PRInt32 count = gInstances->Count(); + for (PRInt32 i = 0; i < count; i++) { + BookmarksService* instance = (BookmarksService*)gInstances->ElementAt(i); + + if (instance->mDataSource) { + // We're a tree view. + nsCOMPtr parent; + aContainer->GetParent(*getter_AddRefs(parent)); + + BookmarkItem* item = nil; + if (parent) + // We're not the root. + item = GetWrapperFor(aContainer); + + [(instance->mDataSource) reloadDataForItem: item reloadChildren: YES]; } - - FlushBookmarks(); + else if (instance->mToolbar) { + // We're a personal toolbar. + nsCOMPtr parentElt(do_QueryInterface(aContainer)); + if (parentElt == gToolbarRoot) { + // We only care about changes that occur to the personal toolbar's immediate + // children. + PRInt32 index = -1; + aContainer->IndexOf(aChild, index); + nsCOMPtr elt(do_QueryInterface(aChild)); + [(instance->mToolbar) addButton: elt atIndex: index]; + } + } + else { + // We're the menu. + PRInt32 index = -1; + aContainer->IndexOf(aChild, index); + NSMenu* menu = LocateMenu(aContainer); + AddMenuBookmark(menu, aContainer, aChild, index); + } + } + + FlushBookmarks(); } - void -BookmarksService::NotifyObserver(nsIContent* aContainer, PRBool aReloadChildren) +BookmarksService::BookmarkChanged(nsIContent* aItem) { - if (!gDictionary) - return; + if (!gInstances || !gDictionary) + return; + + PRInt32 count = gInstances->Count(); + for (PRInt32 i = 0; i < count; i++) { + BookmarksService* instance = (BookmarksService*)gInstances->ElementAt(i); - nsCOMPtr parent; - aContainer->GetParent(*getter_AddRefs(parent)); - - BookmarkItem* item = nil; - if (parent) + if (instance->mDataSource) { + BookmarkItem* item = GetWrapperFor(aItem); + [(instance->mDataSource) reloadDataForItem: item reloadChildren: NO]; + } + } + + FlushBookmarks(); +} + +void +BookmarksService::BookmarkRemoved(nsIContent* aContainer, nsIContent* aChild) +{ + if (!gInstances) + return; + + PRInt32 count = gInstances->Count(); + for (PRInt32 i = 0; i < count; i++) { + BookmarksService* instance = (BookmarksService*)gInstances->ElementAt(i); + + if (instance->mDataSource) { + // We're a tree view. + nsCOMPtr parent; + aContainer->GetParent(*getter_AddRefs(parent)); + + BookmarkItem* item = nil; + if (parent) // We're not the root. item = GetWrapperFor(aContainer); - - [mDataSource reloadDataForItem: item reloadChildren: aReloadChildren]; + + [(instance->mDataSource) reloadDataForItem: item reloadChildren: YES]; + } + else if (instance->mToolbar) { + // We're a personal toolbar. + nsCOMPtr parentElt(do_QueryInterface(aContainer)); + if (parentElt == gToolbarRoot) { + // We only care about changes that occur to the personal toolbar's immediate + // children. + nsCOMPtr childElt(do_QueryInterface(aChild)); + [(instance->mToolbar) removeButton: childElt]; + } + } + else { + // We're the menu. + NSMenu* menu = LocateMenu(aContainer); + PRUint32 contentID; + aChild->GetContentID(&contentID); + NSMenuItem* childItem = [menu itemWithTag: contentID]; + [menu removeItem: childItem]; + } + } + + FlushBookmarks(); } void @@ -510,6 +676,47 @@ BookmarksService::FlushBookmarks() domSerializer->SerializeToStream(domDoc, outputStream, nsnull); } +void BookmarksService::EnsureToolbarRoot() +{ + if (gToolbarRoot) + return; + + nsCOMPtr domDoc(do_QueryInterface(gBookmarks)); + nsCOMPtr rootElt; + domDoc->GetDocumentElement(getter_AddRefs(rootElt)); + + nsCOMPtr child; + rootElt->GetFirstChild(getter_AddRefs(child)); + nsAutoString typeValue; + while (child) { + nsCOMPtr childElt(do_QueryInterface(child)); + if (childElt) { + childElt->GetAttribute(NS_LITERAL_STRING("type"), typeValue); + if (typeValue.Equals(NS_LITERAL_STRING("toolbar"))) + gToolbarRoot = childElt; + } + + nsCOMPtr temp; + child->GetNextSibling(getter_AddRefs(temp)); + child = temp; + } + + if (!gToolbarRoot) { + printf("Repairing personal toolbar.\n"); + nsCOMPtr elt; + domDoc->CreateElementNS(NS_LITERAL_STRING("http://chimera.mozdev.org/bookmarks/"), + NS_LITERAL_STRING("folder"), + getter_AddRefs(elt)); + + elt->SetAttribute(NS_LITERAL_STRING("name"), NS_LITERAL_STRING("Toolbar Bookmarks")); + elt->SetAttribute(NS_LITERAL_STRING("type"), NS_LITERAL_STRING("toolbar")); + + nsCOMPtr dummy; + rootElt->AppendChild(elt, getter_AddRefs(dummy)); + gToolbarRoot = elt; + } +} + void BookmarksService::ConstructBookmarksMenu(NSMenu* aMenu, nsIContent* aContent) { @@ -517,6 +724,7 @@ BookmarksService::ConstructBookmarksMenu if (!content) { GetRootContent(getter_AddRefs(content)); GetWrapperFor(content); + gBookmarksMenu = aMenu; } // Now walk our children, and for folders also recur into them. @@ -524,40 +732,48 @@ BookmarksService::ConstructBookmarksMenu content->ChildCount(childCount); for (PRInt32 i = 0; i < childCount; i++) { - nsCOMPtr child; - content->ChildAt(i, *getter_AddRefs(child)); - - // Obtain our name attribute. - nsAutoString name; - child->GetAttr(kNameSpaceID_None, gNameAtom, name); - nsCAutoString nameCStr; nameCStr.AssignWithConversion(name); - NSString* title = [NSString stringWithCString: nameCStr.get()]; - - // Create a menu or menu item for the child. - NSMenuItem* menuItem = [[[NSMenuItem alloc] initWithTitle: title action: NULL keyEquivalent: @""] autorelease]; - GetWrapperFor(child); - [aMenu addItem: menuItem]; - - nsCOMPtr tag; - child->GetTag(*getter_AddRefs(tag)); - - if (tag == gFolderAtom) { - NSMenu* menu = [[[NSMenu alloc] initWithTitle: title] autorelease]; - [aMenu setSubmenu: menu forItem: menuItem]; - [menu setAutoenablesItems: NO]; - ConstructBookmarksMenu(menu, child); - } - else { - [menuItem setTarget: gMainController]; - [menuItem setAction: @selector(openMenuBookmark:)]; - } - - PRUint32 contentID; - child->GetContentID(&contentID); - [menuItem setTag: contentID]; + nsCOMPtr child; + content->ChildAt(i, *getter_AddRefs(child)); + AddMenuBookmark(aMenu, content, child, -1); } } +void +BookmarksService::AddMenuBookmark(NSMenu* aMenu, nsIContent* aParent, nsIContent* aChild, PRInt32 aIndex) +{ + nsAutoString name; + aChild->GetAttr(kNameSpaceID_None, gNameAtom, name); + nsCAutoString nameCStr; nameCStr.AssignWithConversion(name); + NSString* title = [NSString stringWithCString: nameCStr.get()]; + + // Create a menu or menu item for the child. + NSMenuItem* menuItem = [[[NSMenuItem alloc] initWithTitle: title action: NULL keyEquivalent: @""] autorelease]; + GetWrapperFor(aChild); + + if (aIndex == -1) + [aMenu addItem: menuItem]; + else + [aMenu insertItem: menuItem atIndex: aIndex]; + + nsCOMPtr tagName; + aChild->GetTag(*getter_AddRefs(tagName)); + + if (tagName == gFolderAtom) { + NSMenu* menu = [[[NSMenu alloc] initWithTitle: title] autorelease]; + [aMenu setSubmenu: menu forItem: menuItem]; + [menu setAutoenablesItems: NO]; + ConstructBookmarksMenu(menu, aChild); + } + else { + [menuItem setTarget: gMainController]; + [menuItem setAction: @selector(openMenuBookmark:)]; + } + + PRUint32 contentID; + aChild->GetContentID(&contentID); + [menuItem setTag: contentID]; +} + void BookmarksService::OpenMenuBookmark(BrowserWindowController* aController, id aMenuItem) { @@ -578,4 +794,7 @@ BookmarksService::OpenMenuBookmark(Brows // Now load the URL in the window. [aController loadURL:[NSURL URLWithString: url]]; + + // Focus and activate our content area. + [[[aController getMyBrowserView] getBrowserView] setActive: YES]; } \ No newline at end of file