From 96da93ef2f2bf90fe6d5a4dc752b5ffea818b11d Mon Sep 17 00:00:00 2001 From: "pinkerton%netscape.com" Date: Mon, 24 Mar 2003 02:10:08 +0000 Subject: [PATCH] new in-window bookmark manager. --- camino/Chimera.pbproj/project.pbxproj | 86 ++++++ .../BrowserWindow.nib/classes.nib | 8 +- .../English.lproj/BrowserWindow.nib/info.nib | 3 +- .../BrowserWindow.nib/objects.nib | Bin 22864 -> 23498 bytes .../English.lproj/MainMenu.nib/info.nib | 2 +- .../English.lproj/MainMenu.nib/objects.nib | Bin 15481 -> 15005 bytes camino/src/application/MainController.mm | 2 +- camino/src/bookmarks/BookmarksController.h | 106 ++++++++ camino/src/bookmarks/BookmarksController.mm | 244 ++++++++++++++++++ camino/src/bookmarks/BookmarksDataSource.h | 1 + camino/src/bookmarks/BookmarksDataSource.mm | 90 ++++--- camino/src/bookmarks/BookmarksOutlineView.h | 5 +- camino/src/bookmarks/BookmarksService.h | 2 +- camino/src/browser/BrowserWindowController.h | 30 +-- camino/src/browser/BrowserWindowController.mm | 117 ++------- camino/src/extensions/ExtendedOutlineView.h | 8 +- camino/src/extensions/ExtendedOutlineView.mm | 144 ++++++++++- .../extensions/RDFOutlineViewDataSource.mm | 7 +- camino/src/history/HistoryDataSource.h | 1 + camino/src/history/HistoryDataSource.mm | 48 +--- 20 files changed, 684 insertions(+), 220 deletions(-) create mode 100644 camino/src/bookmarks/BookmarksController.h create mode 100644 camino/src/bookmarks/BookmarksController.mm diff --git a/camino/Chimera.pbproj/project.pbxproj b/camino/Chimera.pbproj/project.pbxproj index ef30e30589ea..ce6243b4e2c8 100644 --- a/camino/Chimera.pbproj/project.pbxproj +++ b/camino/Chimera.pbproj/project.pbxproj @@ -732,6 +732,8 @@ F583E3C303B8228F01A80166, F5F415CB03B9223E01A80166, F527C90403BCD43601A80166, + 3F2CF8CD042A88B7005FD42F, + 3F2CF8D2042A8B30005FD42F, ); isa = PBXHeadersBuildPhase; runOnlyForDeploymentPostprocessing = 0; @@ -886,6 +888,8 @@ F583E3C003B8228701A80166, F5F415CC03B9223E01A80166, F527C90503BCD43601A80166, + 3F2CF8CE042A88B7005FD42F, + 3F2CF8D5042A8C47005FD42F, ); isa = PBXSourcesBuildPhase; runOnlyForDeploymentPostprocessing = 0; @@ -1031,6 +1035,80 @@ settings = { }; }; + 3F2CF8CB042A88B7005FD42F = { + fileEncoding = 30; + isa = PBXFileReference; + path = ImageAndTextCell.h; + refType = 2; + }; + 3F2CF8CC042A88B7005FD42F = { + fileEncoding = 30; + isa = PBXFileReference; + path = ImageAndTextCell.m; + refType = 2; + }; + 3F2CF8CD042A88B7005FD42F = { + fileRef = 3F2CF8CB042A88B7005FD42F; + isa = PBXBuildFile; + settings = { + }; + }; + 3F2CF8CE042A88B7005FD42F = { + fileRef = 3F2CF8CC042A88B7005FD42F; + isa = PBXBuildFile; + settings = { + }; + }; + 3F2CF8CF042A88B7005FD42F = { + fileRef = 3F2CF8CB042A88B7005FD42F; + isa = PBXBuildFile; + settings = { + }; + }; + 3F2CF8D0042A88B7005FD42F = { + fileRef = 3F2CF8CC042A88B7005FD42F; + isa = PBXBuildFile; + settings = { + }; + }; + 3F2CF8D1042A8B30005FD42F = { + fileEncoding = 4; + isa = PBXFileReference; + name = BookmarksController.h; + path = src/bookmarks/BookmarksController.h; + refType = 4; + }; + 3F2CF8D2042A8B30005FD42F = { + fileRef = 3F2CF8D1042A8B30005FD42F; + isa = PBXBuildFile; + settings = { + }; + }; + 3F2CF8D3042A8B30005FD42F = { + fileRef = 3F2CF8D1042A8B30005FD42F; + isa = PBXBuildFile; + settings = { + }; + }; + 3F2CF8D4042A8C47005FD42F = { + fileEncoding = 4; + isa = PBXFileReference; + name = BookmarksController.mm; + path = src/bookmarks/BookmarksController.mm; + refType = 4; + }; + 3F2CF8D5042A8C47005FD42F = { + fileRef = 3F2CF8D4042A8C47005FD42F; + isa = PBXBuildFile; + settings = { + }; + }; + 3F2CF8D6042A8C47005FD42F = { + fileRef = 3F2CF8D4042A8C47005FD42F; + isa = PBXBuildFile; + settings = { + }; + }; //3F0 //3F1 //3F2 @@ -2504,6 +2582,7 @@ }; F51842F30206168101A966FE = { children = ( + 3F2CF8D1042A8B30005FD42F, F5C8D55203A2A42401A8016F, F5F94B900332532801026D5D, F5DE10E60209DC0601A967DF, @@ -6344,6 +6423,7 @@ F57074BA026BFD0101A80166, F53E012C02AEE93601A967F3, 2EEC3E62028138714B000102, + 3F2CF8D4042A8C47005FD42F, ); isa = PBXGroup; name = Bookmarks; @@ -6996,6 +7076,7 @@ }; F5B950BA030C833301A96654 = { children = ( + 3F2CF8CB042A88B7005FD42F, F5FDF166031AF47301DE816D, F5D98EBC031AC38601A96654, F558099D02F22168015DF512, @@ -7025,6 +7106,7 @@ F541495B02711A8301A80166, F541495F02711B0001A80166, F5FDF167031AF47301DE816D, + 3F2CF8CC042A88B7005FD42F, ); isa = PBXGroup; name = Source; @@ -7385,6 +7467,8 @@ F583E3C403B8228F01A80166, F5F415CD03B9223E01A80166, F527C90603BCD43601A80166, + 3F2CF8CF042A88B7005FD42F, + 3F2CF8D3042A8B30005FD42F, ); isa = PBXHeadersBuildPhase; runOnlyForDeploymentPostprocessing = 0; @@ -7540,6 +7624,8 @@ F583E3C103B8228701A80166, F5F415CE03B9223E01A80166, F527C90703BCD43601A80166, + 3F2CF8D0042A88B7005FD42F, + 3F2CF8D6042A8C47005FD42F, ); isa = PBXSourcesBuildPhase; runOnlyForDeploymentPostprocessing = 0; diff --git a/camino/resources/localized/English.lproj/BrowserWindow.nib/classes.nib b/camino/resources/localized/English.lproj/BrowserWindow.nib/classes.nib index a0d4d6ad3a05..3c968efd841f 100644 --- a/camino/resources/localized/English.lproj/BrowserWindow.nib/classes.nib +++ b/camino/resources/localized/English.lproj/BrowserWindow.nib/classes.nib @@ -11,13 +11,18 @@ {CLASS = BookmarkItem; LANGUAGE = ObjC; SUPERCLASS = NSObject; }, {CLASS = BookmarkManagerView; LANGUAGE = ObjC; SUPERCLASS = NSView; }, { + ACTIONS = {changeContainer = id; }; CLASS = BookmarksController; LANGUAGE = ObjC; OUTLETS = { mAddFolderButton = NSButton; mAddItemButton = NSButton; + mBookmarksSource = BookmarksDataSource; + mContainerPane = NSTableView; mContainersSplit = NSSplitView; - mItemPane = NSOutlineView; + mHistorySource = HistoryDataSource; + mInfoButton = NSButton; + mItemPane = ExtendedOutlineView; mItemSearchSplit = NSSplitView; mSearchPane = NSTableView; }; @@ -184,6 +189,7 @@ }, {CLASS = LocationBar; LANGUAGE = ObjC; SUPERCLASS = NSView; }, {CLASS = MainController; LANGUAGE = ObjC; SUPERCLASS = NSObject; }, + {CLASS = NSObject; LANGUAGE = ObjC; }, {CLASS = PageProxyIcon; LANGUAGE = ObjC; SUPERCLASS = NSImageView; }, { CLASS = RDFOutlineViewDataSource; diff --git a/camino/resources/localized/English.lproj/BrowserWindow.nib/info.nib b/camino/resources/localized/English.lproj/BrowserWindow.nib/info.nib index 4908f4f2f1b1..9875db86e65c 100644 --- a/camino/resources/localized/English.lproj/BrowserWindow.nib/info.nib +++ b/camino/resources/localized/English.lproj/BrowserWindow.nib/info.nib @@ -3,7 +3,7 @@ IBDocumentLocation - 185 81 653 383 0 0 1280 832 + 263 57 653 383 0 0 1280 832 IBEditorPositions 124 @@ -45,6 +45,7 @@ IBOpenObjects + 160 731 IBSystem Version diff --git a/camino/resources/localized/English.lproj/BrowserWindow.nib/objects.nib b/camino/resources/localized/English.lproj/BrowserWindow.nib/objects.nib index 967aee9666b1a9bdcc24d4c661428504244d3e00..35067bebc261e9c17e2bc865d368c09b7b8cf21f 100644 GIT binary patch literal 23498 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 Ky2A7^>i-YSN^UU# literal 22864 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 E2A;K6F8}}l diff --git a/camino/resources/localized/English.lproj/MainMenu.nib/info.nib b/camino/resources/localized/English.lproj/MainMenu.nib/info.nib index 4d48db02e053..d37589959086 100644 --- a/camino/resources/localized/English.lproj/MainMenu.nib/info.nib +++ b/camino/resources/localized/English.lproj/MainMenu.nib/info.nib @@ -9,7 +9,7 @@ 266 644 623 277 90 0 0 1600 1002 29 - 191 940 433 44 0 0 1280 1002 + 191 773 433 44 0 0 1280 832 494 569 607 185 78 0 0 1280 1002 diff --git a/camino/resources/localized/English.lproj/MainMenu.nib/objects.nib b/camino/resources/localized/English.lproj/MainMenu.nib/objects.nib index cdc33147b2460ba6c09521f62914e02a402319e1..c0439d51bf6954f3960cdbde5f8491465024326b 100644 GIT binary patch literal 15005 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 literal 15481 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 N1pWsb`g}E$`9Hs&{mB3T diff --git a/camino/src/application/MainController.mm b/camino/src/application/MainController.mm index f5edd4fd9688..20a9d388de6f 100644 --- a/camino/src/application/MainController.mm +++ b/camino/src/application/MainController.mm @@ -193,7 +193,7 @@ const int kReuseWindowOnAE = 2; [mBookmarksMenu setAutoenablesItems: NO]; // menubar bookmarks - int firstBookmarkItem = [mBookmarksMenu indexOfItemWithTag:kBookmarksDividerTag]; + int firstBookmarkItem = [mBookmarksMenu indexOfItemWithTag:kBookmarksDividerTag] + 1; mMenuBookmarks = [[BookmarksMenu alloc] initWithMenu: mBookmarksMenu firstItem: firstBookmarkItem rootContent: [bmManager getRootContent] diff --git a/camino/src/bookmarks/BookmarksController.h b/camino/src/bookmarks/BookmarksController.h new file mode 100644 index 000000000000..dae0e54bfbc4 --- /dev/null +++ b/camino/src/bookmarks/BookmarksController.h @@ -0,0 +1,106 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 2002 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#import + +@class BookmarksDataSource; +@class HistoryDataSource; +@class ExtendedOutlineView; + +enum { kBookmarksMenuContainer, kHistoryContainer }; + +// +// BookmarksController +// +// A controller that handles everything that goes on w/in the embedded +// bookmarks manager. +// +@interface BookmarksController : NSObject +{ + IBOutlet NSButton* mAddItemButton; + IBOutlet NSButton* mAddFolderButton; + IBOutlet NSButton* mInfoButton; + + IBOutlet NSSplitView* mContainersSplit; // vertical split + IBOutlet NSSplitView* mItemSearchSplit; // horizontal split + + IBOutlet NSTableView* mContainerPane; + IBOutlet ExtendedOutlineView* mItemPane; + IBOutlet NSTableView* mSearchPane; // shows search results, can be hidden + + // data sources we can swap between depending on what the user clicks on + IBOutlet BookmarksDataSource* mBookmarksSource; + IBOutlet HistoryDataSource* mHistorySource; +} + +// Set focus to something in the bookmark manager view +- (void) focus; + +- (void) windowDidLoad; + +// called when someone clicks a row on the container table. Changes the +// data in the item outline. +- (IBAction) changeContainer:(id)aSender; + +// select either a particular container or the container that was previously +// selected the last time the manager was displayed. +- (void) selectContainer:(int)inRowIndex; +- (void) selectLastContainer; + +// NSSplitView delegate methods +//- (void)splitView:(NSSplitView *)sender resizeSubviewsWithOldSize:(NSSize)oldSize; +- (float)splitView:(NSSplitView *)sender constrainMinCoordinate:(float)proposedCoord ofSubviewAt:(int)offset; +//- (float)splitView:(NSSplitView *)sender constrainMaxCoordinate:(float)proposedCoord ofSubviewAt:(int)offset; +//- (void)splitViewWillResizeSubviews:(NSNotification *)notification; +- (void)splitViewDidResizeSubviews:(NSNotification *)notification; +- (BOOL)splitView:(NSSplitView *)sender canCollapseSubview:(NSView *)subview; +//- (float)splitView:(NSSplitView *)splitView constrainSplitPosition:(float)proposedPosition ofSubviewAt:(int)index; + +// NSTableView delegate methods +- (void)tableView:(NSTableView *)aTableView willDisplayCell:(id)aCell forTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex; + +// NSTableView data source for the container pane and search pane. +- (int)numberOfRowsInTableView:(NSTableView *)tableView; +- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(int)row; +// optional +//- (void)tableView:(NSTableView *)tableView setObjectValue:(id)object forTableColumn:(NSTableColumn *)tableColumn row:(int)row; +// optional - drag and drop support +//- (BOOL)tableView:(NSTableView *)tv writeRows:(NSArray*)rows toPasteboard:(NSPasteboard*)pboard; +//- (NSDragOperation)tableView:(NSTableView*)tv validateDrop:(id )info proposedRow:(int)row proposedDropOperation:(NSTableViewDropOperation)op; +//- (BOOL)tableView:(NSTableView*)tv acceptDrop:(id )info row:(int)row dropOperation:(NSTableViewDropOperation)op; + +@end diff --git a/camino/src/bookmarks/BookmarksController.mm b/camino/src/bookmarks/BookmarksController.mm new file mode 100644 index 000000000000..da2620b04ef6 --- /dev/null +++ b/camino/src/bookmarks/BookmarksController.mm @@ -0,0 +1,244 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 2002 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#import "BookmarksController.h" +#import "ImageAndTextCell.h" +#import "BookmarksDataSource.h" +#import "HistoryDataSource.h" + + +@interface BookmarksController(PRIVATE) +- (void) setCanEditSelectedContainerContents:(BOOL)inCanEdit; +@end + + +@implementation BookmarksController + +#if 0 +- (id) init +{ + if ( self = [super init] ) + { + mAddItemButton = nil; + } + return self; +} +#endif + +// +// - windowDidLoad +// +// Perform some extra initialization when the window finishes loading +// that we can't do in IB. +// +- (void)windowDidLoad +{ + // hide the search panel + + // the standard table item doesn't handle text and icons. Replace it + // with a custom cell that does. + ImageAndTextCell* imageAndTextCell = [[[ImageAndTextCell alloc] init] autorelease]; + [imageAndTextCell setEditable: YES]; + [imageAndTextCell setWraps: NO]; + NSTableColumn* itemNameColumn = [mItemPane tableColumnWithIdentifier: @"Name"]; + [itemNameColumn setDataCell:imageAndTextCell]; + NSTableColumn* containerNameColumn = [mContainerPane tableColumnWithIdentifier: @"Name"]; + [containerNameColumn setDataCell:imageAndTextCell]; + + // set up the font on the item view to be smaller + NSArray* columns = [mItemPane tableColumns]; + if ( columns ) { + int numColumns = [columns count]; + NSFont* smallerFont = [NSFont systemFontOfSize:11]; + for ( int i = 0; i < numColumns; ++i ) + [[[columns objectAtIndex:i] dataCell] setFont:smallerFont]; + } +} + +// +// - splitViewDidResizeSubviews: +// +// Called when one of the views got resized. We want to ensure that the "add bookmark +// item" button gets lined up with the left edge of the item panel. If the container/item +// split was the one that changed, move it accordingly +// +- (void)splitViewDidResizeSubviews:(NSNotification *)notification +{ + const int kButtonGutter = 8; + + if ( [notification object] == mContainersSplit ) { + // get the position of the item view relative to the window and set the button + // to that X value. Yes, this will fall down if the bookmark view is inset from the window + // but i think we can safely assume it won't be. + NSRect windowRect = [mItemPane convertRect:[mItemPane bounds] toView:nil]; + NSRect newButtonLocation = [mAddItemButton frame]; + newButtonLocation.origin.x = windowRect.origin.x; + [mAddItemButton setFrame:newButtonLocation]; + [mAddItemButton setNeedsDisplay:YES]; + + // offset by the width of the button and the gutter and we've got the location + // of the add folder button next to it. + newButtonLocation.origin.x += newButtonLocation.size.width + kButtonGutter; + [mAddFolderButton setFrame:newButtonLocation]; + [mAddFolderButton setNeedsDisplay:YES]; + } +} + +// +// - splitView:canCollapseSubview: +// +// Called when appkit wants to ask if it can collapse a subview. The only subview +// of our splits that we allow to be hidden is the search panel. +// +- (BOOL)splitView:(NSSplitView *)sender canCollapseSubview:(NSView *)subview +{ + BOOL retVal = NO; + // subview will be a NSScrollView, so we have to get the superview of the + // search pane for comparison. + if ( sender == mItemSearchSplit && subview == [mSearchPane superview] ) + retVal = YES; + return retVal; +} + + +- (float)splitView:(NSSplitView *)sender constrainMinCoordinate:(float)proposedCoord ofSubviewAt:(int)offset +{ + const int kMinimumContainerSplitWidth = 150; + float retVal = proposedCoord; + if ( sender == mContainersSplit ) + retVal = kMinimumContainerSplitWidth; + return retVal; +} + +- (void) focus +{ + [[mItemPane window] makeFirstResponder:mItemPane]; +} + + +- (int)numberOfRowsInTableView:(NSTableView *)tableView +{ + int numRows = 0; + if ( tableView == mContainerPane ) { + // hack for now, history and bookmarks + numRows = 2; + } + else if ( tableView == mSearchPane ) { + // hack just to display something. + numRows = 5; + } + return numRows; +} + +- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(int)row +{ + id itemString = nil; + if ( tableView == mContainerPane ) { + if ( row == kBookmarksMenuContainer ) + itemString = NSLocalizedString(@"Bookmarks Menu", @"Bookmarks Menu"); + else + itemString = NSLocalizedString(@"History", @"History"); + } + else if ( tableView == mSearchPane ) { + if ( [[tableColumn identifier] isEqualToString:@"Name"] ) + itemString = @""; + else + itemString = @""; + } + return itemString; +} + + +- (void)tableView:(NSTableView *)inTableView willDisplayCell:(id)inCell forTableColumn:(NSTableColumn *)inTableColumn row:(int)inRowIndex +{ + if ( inTableView == mContainerPane ) { + if ( inRowIndex == kBookmarksMenuContainer ) + [inCell setImage:[NSImage imageNamed:@"bookicon"]]; + else if ( inRowIndex == kHistoryContainer ) + [inCell setImage:[NSImage imageNamed:@"historyicon"]]; + } +} + +- (IBAction) changeContainer:(id)aSender +{ + [self selectContainer:[aSender clickedRow]]; +} + +- (void) setCanEditSelectedContainerContents:(BOOL)inCanEdit +{ + [mItemPane setAllowsEditing:inCanEdit]; + + // update buttons + [mAddItemButton setEnabled:inCanEdit]; + [mAddFolderButton setEnabled:inCanEdit]; + [mInfoButton setEnabled:inCanEdit]; +} + +- (void) selectContainer:(int)inRowIndex +{ + [mContainerPane selectRow:inRowIndex byExtendingSelection:NO]; + if ( inRowIndex == kBookmarksMenuContainer ) { + [mItemPane setDataSource:mBookmarksSource]; + [mItemPane setDelegate:mBookmarksSource]; + [mBookmarksSource ensureBookmarks]; + [mBookmarksSource restoreFolderExpandedStates]; + [self setCanEditSelectedContainerContents:YES]; + + [mItemPane setDoubleAction: @selector(openBookmark:)]; + [mItemPane setDeleteAction: @selector(deleteBookmarks:)]; + } + else if ( inRowIndex == kHistoryContainer ) { + [mItemPane setDataSource:mHistorySource]; + [mItemPane setDelegate:mHistorySource]; + [mHistorySource ensureDataSourceLoaded]; + [mItemPane reloadData]; + [self setCanEditSelectedContainerContents:NO]; + + [mItemPane setDoubleAction: @selector(openHistoryItem:)]; + [mItemPane setDeleteAction: @selector(deleteHistoryItems:)]; + } +} + +- (void) selectLastContainer +{ + // we need to call selectContainer: in order to get all the appropriate + // stuff hooked up. + [self selectContainer:[mContainerPane selectedRow]]; +} + +@end + diff --git a/camino/src/bookmarks/BookmarksDataSource.h b/camino/src/bookmarks/BookmarksDataSource.h index 06723bd108fb..4d988edc530d 100644 --- a/camino/src/bookmarks/BookmarksDataSource.h +++ b/camino/src/bookmarks/BookmarksDataSource.h @@ -63,6 +63,7 @@ -(void) windowClosing; -(void) ensureBookmarks; +- (void)restoreFolderExpandedStates; -(IBAction)addBookmark:(id)aSender; -(void)endAddBookmark: (int)aCode; diff --git a/camino/src/bookmarks/BookmarksDataSource.mm b/camino/src/bookmarks/BookmarksDataSource.mm index e0211ec9f149..52e36d7ebf35 100644 --- a/camino/src/bookmarks/BookmarksDataSource.mm +++ b/camino/src/bookmarks/BookmarksDataSource.mm @@ -21,6 +21,7 @@ * * Contributor(s): * Simon Fraser + * Max Horn * * * Alternatively, the contents of this file may be used under the terms of @@ -42,6 +43,7 @@ #import "BookmarksDataSource.h" #import "BookmarkInfoController.h" #import "SiteIconProvider.h" +#import "ImageAndTextCell.h" #include "nsCOMPtr.h" #include "nsIContent.h" @@ -52,7 +54,6 @@ @interface BookmarksDataSource(Private) -- (void)restoreFolderExpandedStates; - (void)refreshChildrenOfItem:(nsIContent*)item; @end @@ -78,6 +79,19 @@ const int kBookmarksRootItemTag = -2; -(void) awakeFromNib { + NSTableColumn *tableColumn = nil; + NSButtonCell *imageAndTextCell = nil; + + // Insert custom cell types into the table view, the standard one does text only. +//XXX take this out when we switch to the in-window bookmarks because it's +//XXX done by the BookmarksController (as it should be) + tableColumn = [mOutlineView tableColumnWithIdentifier: @"Name"]; + imageAndTextCell = [[[ImageAndTextCell alloc] init] autorelease]; + [imageAndTextCell setEditable: YES]; + [imageAndTextCell setWraps: NO]; + [tableColumn setDataCell:imageAndTextCell]; + [tableColumn setEditable: YES]; + // make sure these are disabled at the start since the outliner // starts off with no selection. [mEditBookmarkButton setEnabled:NO]; @@ -523,8 +537,8 @@ const int kBookmarksRootItemTag = -2; // outlineView:shouldEditTableColumn:item: (delegate method) // // Called by the outliner to determine whether or not we should allow the -// user to edit this item. We're leaving it off for now, becaue there are -// some usability issues with inline editing (no undo, Escape doesn't work). +// user to edit this item. We always return NO, because we invoke the +// edit methods manually. // - (BOOL)outlineView:(NSOutlineView *)outlineView shouldEditTableColumn:(NSTableColumn *)tableColumn item:(id)item { @@ -579,58 +593,50 @@ const int kBookmarksRootItemTag = -2; { if (!mRegisteredClient) return nil; - NSString *columnName = [tableColumn identifier]; id retValue = nil; - if ([columnName isEqualToString: @"name"]) - { - NSFileWrapper *fileWrapper = [[NSFileWrapper alloc] initRegularFileWithContents:nil]; - NSTextAttachment *textAttachment = [[NSTextAttachment alloc] initWithFileWrapper:fileWrapper]; - - //Set cell's textual contents - //[cellValue replaceCharactersInRange:NSMakeRange(0, [cellValue length]) withString:[NSString stringWith_nsAString: nameAttr]]; - NSMutableAttributedString* cellValue = [[[NSMutableAttributedString alloc] initWithString:[item name]] autorelease]; - - //Create an attributed string to hold the empty attachment, then release the components. - NSMutableAttributedString* attachmentAttrString = [NSMutableAttributedString attributedStringWithAttachment:textAttachment]; - [textAttachment release]; - [fileWrapper release]; - - //Get the cell of the text attachment. - NSCell* attachmentAttrStringCell = (NSCell *)[(NSTextAttachment *)[attachmentAttrString attribute:NSAttachmentAttributeName atIndex:0 effectiveRange:nil] attachmentCell]; - - NSImage* bookmarkImage = [[BookmarksManager sharedBookmarksManager] createIconForBookmarkItem:item useSiteIcon:NO]; - [attachmentAttrStringCell setImage:bookmarkImage]; - - //Insert the image - [cellValue replaceCharactersInRange:NSMakeRange(0, 0) withAttributedString:attachmentAttrString]; - - //Tweak the baseline to vertically center the text. - [cellValue addAttribute:NSBaselineOffsetAttributeName - value:[NSNumber numberWithFloat:-3.0] - range:NSMakeRange(0, 1)]; - retValue = cellValue; + NSString *columnName = [tableColumn identifier]; + if ([columnName isEqualToString: @"Name"]) { + // Return data as an NSString. We'll deal with the icon later. + retValue = [item name]; } - else if ([columnName isEqualToString: @"url"]) - { + else if ([columnName isEqualToString: @"URL"]) { + if ([item isFolder]) { +#if 0 + int numKids = [item getNumberOfChildren]; + NSString* itemCountStr = [NSString stringWithFormat:NSLocalizedString(@"Contains Items", @"%d Items"), + numKids]; + NSMutableDictionary* colorAttributes = nil; //XXXX fill in color attribute + retValue = [[NSAttributedString alloc] initWithString:itemCountStr attributes:colorAttributes]; +#endif + } + else retValue = [item url]; } return retValue; } +- (void)outlineView:(NSOutlineView *)outlineView willDisplayCell:(NSCell *)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item +{ + // set the image on the name column. the url column doesn't have an image. + if ([[tableColumn identifier] isEqualToString: @"Name"]) { + NSImage* image = [[BookmarksManager sharedBookmarksManager] createIconForBookmarkItem:item useSiteIcon:YES]; + [cell setImage:image]; + } +} + - (void)outlineView:(NSOutlineView *)outlineView setObjectValue:(id)object forTableColumn:(NSTableColumn *)tableColumn byItem:(id)item { // object is really an NSString, even though objectValueForTableColumn returns NSAttributedStrings. + BookmarkItem* bmItem = (BookmarkItem*)item; NSString *columnName = [tableColumn identifier]; - if ( [columnName isEqualTo:@"name"] ) + if ( [columnName isEqualTo:@"Name"] ) { - const unichar kAttachmentCharacter = NSAttachmentCharacter; - - NSMutableString* mutableString = [NSMutableString stringWithString:object]; - [mutableString replaceOccurrencesOfString:[NSString stringWithCharacters:&kAttachmentCharacter length:1] withString:@"" options:0 range:NSMakeRange(0, [mutableString length])]; - - BookmarkItem* bmItem = (BookmarkItem*)item; - [bmItem setName:mutableString]; + [bmItem setName:object]; + [bmItem itemChanged:YES]; + } + else if ( [columnName isEqualTo:@"URL"] ) { + [bmItem setUrl:object]; [bmItem itemChanged:YES]; } } diff --git a/camino/src/bookmarks/BookmarksOutlineView.h b/camino/src/bookmarks/BookmarksOutlineView.h index 9df77d511194..4589b36ef9af 100644 --- a/camino/src/bookmarks/BookmarksOutlineView.h +++ b/camino/src/bookmarks/BookmarksOutlineView.h @@ -24,8 +24,7 @@ #import #import "ExtendedOutlineView.h" -@interface BookmarksOutlineView : ExtendedOutlineView { - +@interface BookmarksOutlineView : ExtendedOutlineView +{ } - @end diff --git a/camino/src/bookmarks/BookmarksService.h b/camino/src/bookmarks/BookmarksService.h index 9ef26ceb72fa..95551832d90c 100644 --- a/camino/src/bookmarks/BookmarksService.h +++ b/camino/src/bookmarks/BookmarksService.h @@ -169,7 +169,7 @@ protected: -@interface BookmarkItem : NSObject +@interface BookmarkItem : NSObject { nsIContent* mContentNode; NSImage* mSiteIcon; diff --git a/camino/src/browser/BrowserWindowController.h b/camino/src/browser/BrowserWindowController.h index da2a3995c415..e3f661bb1575 100644 --- a/camino/src/browser/BrowserWindowController.h +++ b/camino/src/browser/BrowserWindowController.h @@ -47,6 +47,7 @@ class nsIBrowserHistory; class nsIDOMEvent; class nsIDOMNode; +@class BookmarksController; // // ThrobberHandler @@ -80,35 +81,6 @@ class nsIDOMNode; #pragma mark - -@interface BookmarksController : NSObject -{ - IBOutlet NSButton* mAddItemButton; - IBOutlet NSButton* mAddFolderButton; - - IBOutlet NSSplitView* mContainersSplit; // vertical split - IBOutlet NSSplitView* mItemSearchSplit; // horizontal split - IBOutlet NSOutlineView* mItemPane; - IBOutlet NSTableView* mSearchPane; // shows search results, can be hidden -} - -// Set focus to something in the bookmark manager view -- (void) focus; - -- (void) windowDidLoad; - -// NSSplitView delegate methods -//- (void)splitView:(NSSplitView *)sender resizeSubviewsWithOldSize:(NSSize)oldSize; -- (float)splitView:(NSSplitView *)sender constrainMinCoordinate:(float)proposedCoord ofSubviewAt:(int)offset; -//- (float)splitView:(NSSplitView *)sender constrainMaxCoordinate:(float)proposedCoord ofSubviewAt:(int)offset; -//- (void)splitViewWillResizeSubviews:(NSNotification *)notification; -- (void)splitViewDidResizeSubviews:(NSNotification *)notification; -- (BOOL)splitView:(NSSplitView *)sender canCollapseSubview:(NSView *)subview; -//- (float)splitView:(NSSplitView *)splitView constrainSplitPosition:(float)proposedPosition ofSubviewAt:(int)index; - -@end - -#pragma mark - - typedef enum { eNewTabEmpty, diff --git a/camino/src/browser/BrowserWindowController.mm b/camino/src/browser/BrowserWindowController.mm index ae9c5f7f9870..5ed671bb7302 100644 --- a/camino/src/browser/BrowserWindowController.mm +++ b/camino/src/browser/BrowserWindowController.mm @@ -48,6 +48,7 @@ #import "UserDefaults.h" #import "PageProxyIcon.h" #import "AutoCompleteTextField.h" +#import "BookmarksController.h" #include "nsIWebNavigation.h" #include "nsIDOMDocument.h" @@ -78,7 +79,10 @@ #include -#define USE_DRAWER_FOR_BOOKMARKS 1 +#define USE_DRAWER_FOR_BOOKMARKS 0 +#if USE_DRAWER_FOR_BOOKMARKS +#import "ImageAndTextCell.h" +#endif static NSString *BrowserToolbarIdentifier = @"Browser Window Toolbar"; static NSString *BackToolbarItemIdentifier = @"Back Toolbar Item"; @@ -933,18 +937,18 @@ static NSArray* sToolbarDefaults = nil; -(IBAction)manageBookmarks: (id)aSender { - if ([mSidebarDrawer state] == NSDrawerClosedState) - [self toggleSidebar: self]; + if ( ![mContentView isBookmarkManagerVisible] ) + [self toggleBookmarkManager: self]; - [mSidebarTabView selectFirstTabViewItem:self]; + [mBookmarksController selectContainer:kBookmarksMenuContainer]; } -(IBAction)manageHistory: (id)aSender { - if ([mSidebarDrawer state] == NSDrawerClosedState) - [self toggleSidebar: self]; + if ( ![mContentView isBookmarkManagerVisible] ) + [self toggleBookmarkManager: self]; - [mSidebarTabView selectTabViewItemAtIndex:1]; + [mBookmarksController selectContainer:kHistoryContainer]; } - (void)importBookmarks: (NSString*)aURLSpec @@ -2150,9 +2154,14 @@ static NSArray* sToolbarDefaults = nil; // swap out between content and bookmarks. [mContentView toggleBookmarkManager:sender]; + +#if !USE_DRAWER_FOR_BOOKMARKS //XXXXXX needed until we can turn this on full time, since it's a nib change. mSidebarBookmarksDataSource->mOutlineView = mBookmarksController->mItemPane; - [mSidebarBookmarksDataSource ensureBookmarks]; +mHistoryDataSource->mOutlineView = mBookmarksController->mItemPane; +#endif + + [mBookmarksController selectLastContainer]; // if we're now showing the bm manager, force it to have focus, // otherwise give focus back to gecko. @@ -2298,95 +2307,3 @@ static Boolean movieControllerFilter(MovieController mc, short action, void *par } @end - -#pragma mark - - -@implementation BookmarksController - -#if 0 -- (id) init -{ - if ( self = [super init] ) - { - mAddItemButton = nil; - } - return self; -} -#endif - -// -// - splitViewDidResizeSubviews: -// -// Called when one of the views got resized. We want to ensure that the "add bookmark -// item" button gets lined up with the left edge of the item panel. If the container/item -// split was the one that changed, move it accordingly -// -- (void)splitViewDidResizeSubviews:(NSNotification *)notification -{ - const int kButtonGutter = 8; - - if ( [notification object] == mContainersSplit ) { - // get the position of the item view relative to the window and set the button - // to that X value. Yes, this will fall down if the bookmark view is inset from the window - // but i think we can safely assume it won't be. - NSRect windowRect = [mItemPane convertRect:[mItemPane bounds] toView:nil]; - NSRect newButtonLocation = [mAddItemButton frame]; - newButtonLocation.origin.x = windowRect.origin.x; - [mAddItemButton setFrame:newButtonLocation]; - [mAddItemButton setNeedsDisplay:YES]; - - // offset by the width of the button and the gutter and we've got the location - // of the add folder button next to it. - newButtonLocation.origin.x += newButtonLocation.size.width + kButtonGutter; - [mAddFolderButton setFrame:newButtonLocation]; - [mAddFolderButton setNeedsDisplay:YES]; - } -} - -// -// - splitView:canCollapseSubview: -// -// Called when appkit wants to ask if it can collapse a subview. The only subview -// of our splits that we allow to be hidden is the search panel. -// -- (BOOL)splitView:(NSSplitView *)sender canCollapseSubview:(NSView *)subview -{ - BOOL retVal = NO; - // subview will be a NSScrollView, so we have to get the superview of the - // search pane for comparison. - if ( sender == mItemSearchSplit && subview == [mSearchPane superview] ) - retVal = YES; - return retVal; -} - -- (void)windowDidLoad -{ - // hide the search panel - - // set up the font on the item view to be smaller - NSArray* columns = [mItemPane tableColumns]; - if ( columns ) { - int numColumns = [columns count]; - NSFont* smallerFont = [NSFont systemFontOfSize:11]; - for ( int i = 0; i < numColumns; ++i ) - [[[columns objectAtIndex:i] dataCell] setFont:smallerFont]; - } -} - - -- (float)splitView:(NSSplitView *)sender constrainMinCoordinate:(float)proposedCoord ofSubviewAt:(int)offset -{ - const int kMinimumContainerSplitWidth = 150; - float retVal = proposedCoord; - if ( sender == mContainersSplit ) - retVal = kMinimumContainerSplitWidth; - return retVal; -} - -- (void) focus -{ - [[mItemPane window] makeFirstResponder:mItemPane]; -} - -@end - diff --git a/camino/src/extensions/ExtendedOutlineView.h b/camino/src/extensions/ExtendedOutlineView.h index edbde3aaffaa..2b9ec4b02a91 100644 --- a/camino/src/extensions/ExtendedOutlineView.h +++ b/camino/src/extensions/ExtendedOutlineView.h @@ -24,14 +24,20 @@ #import -@interface ExtendedOutlineView : NSOutlineView { +@interface ExtendedOutlineView : NSOutlineView +{ SEL mDeleteAction; NSRect mOldFrameRect; int mOldRows; BOOL mDelegateTooltipStringForItem; + + int mRowToBeEdited, mColumnToBeEdited; + BOOL mAllowsEditing; } +-(void)setAllowsEditing:(BOOL)inAllow; + -(void)keyDown:(NSEvent*)aEvent; -(void)setDeleteAction: (SEL)deleteAction; diff --git a/camino/src/extensions/ExtendedOutlineView.mm b/camino/src/extensions/ExtendedOutlineView.mm index 2c75ec481c15..82796eb5352f 100644 --- a/camino/src/extensions/ExtendedOutlineView.mm +++ b/camino/src/extensions/ExtendedOutlineView.mm @@ -19,7 +19,7 @@ * * Contributor(s): * David Hyatt (Original Author) -* Max Horn (Context menu & tooltip code) +* Max Horn (Context menu, tooltip code, and editing) */ #import "ExtendedOutlineView.h" @@ -33,7 +33,10 @@ - (id)initWithFrame:(NSRect)frame { if ( (self = [super initWithFrame:frame]) ) { - mDeleteAction = 0; + mDeleteAction = nil; + mAllowsEditing = YES; + mRowToBeEdited = mColumnToBeEdited = 0; + // FIXME - this method is *never* called for items that are archived in a nib! // Luckily, object memory is zeroed, so mDeleteAction will be 0 anyway. // I recommend that this method just be removed. @@ -41,7 +44,8 @@ return self; } -- (void)awakeFromNib { +- (void)awakeFromNib +{ // Setup the initial NSToolTipRects [self _updateToolTipRect]; } @@ -189,6 +193,140 @@ return [self menu]; } + +- (void)textDidEndEditing:(NSNotification *)aNotification +{ + // Fake our own notification. We pretend that the editing was canceled due to a + // mouse click. This prevents outlineviw from selecting another cell for editing. + NSDictionary *userInfo = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:NSIllegalTextMovement] forKey:@"NSTextMovement"]; + NSNotification *fakeNotification = [NSNotification notificationWithName:[aNotification name] object:[aNotification object] userInfo:userInfo]; + + [super textDidEndEditing:fakeNotification]; + + // Make ourself first responder again + [[self window] makeFirstResponder:self]; +} + + +- (void)_cancelEditItem +{ + mRowToBeEdited = -1; + [[self class] cancelPreviousPerformRequestsWithTarget:self selector:@selector(editItem:) object:nil]; +} + + +// +// Start editing a given item. Used to start editing delayed. +// +- (void)_editItem:(id)dummy +{ + int row = mRowToBeEdited; + + // Cancel any other scheduled edits+ [self _cancelEditItem]; + + // Only start the editing if the selection didn't change in the meantime + // (e.g. because arrow keys were used to change it). + if (row > 0 && row == [self selectedRow]) + [self editColumn:mColumnToBeEdited row:row withEvent:nil select:YES]; +} + +/* + * Handle mouse clicks, allowing them to start inline editing. + * We start editing under two conditions: + * 1) For clicks together with the alt/option modifier key immediatly + * 2) For clicks on already selected items after a short delay + * Rule 2 only is enabled if the outline view is first responder of the main + * window, otherwise odd behaviour takes placed when the user clicks into + * a background window on a selected item - editing would start, which is + * not the correct result (at least if we want to match Finder). + * + * There are some other catchfalls and quirks we have to consider, for details + * read the comments in the code. + */ +- (void)mouseDown:(NSEvent *)theEvent +{ + // the data isn't always allowed to be edited (eg, rendevous or history). Bail + // if we've been told to not allow editing. + if ( !mAllowsEditing ) { + [super mouseDown:theEvent]; + return; + } + + // Record some state information before calling the super implementation, + // as these might change. E.g. if we are not yet first repsonder, the click + // might make us first responder. + BOOL wasFirstResponder = ([[self window] firstResponder] == self); + BOOL wasMainWindow = [[self window] isMainWindow]; + BOOL wasClickInTextPartOfCell = NO; + int oldEditRow = [self editedRow]; + int oldRow = ([self numberOfSelectedRows] == 1) ? [self selectedRow] : -1; + + // Now call the super implementation. It will only return after the mouseUp + // occured, since it does drag&drop handling etc. + [super mouseDown:theEvent]; + + // If this was a double click, we cancel any scheduled edit requests and return + if ([theEvent clickCount] > 1) { + [self _cancelEditItem]; + return; + } + + // Detect if the selection changed (ignoring multi-selections) + int newRow = ([self numberOfSelectedRows] == 1) ? [self selectedRow] : -1; + + // If the selection did change, we need to cancel any scheduled edit requests. + if (oldRow != newRow && oldRow != -1) + [self _cancelEditItem]; + + // Little trick: if editing was already in progress, then the field editor + // will be first responder. For our purposes this is the same as if we + // were first responder, so pretend it were so. + if (oldEditRow >= 0) + wasFirstResponder = YES; + + // If we already were first responder of the main window, and the click was + // inside a row and it was the left mouse button, then we investigate further + // and check if we need to start editing. + if (wasFirstResponder && wasMainWindow && newRow >= 0 && ([theEvent type] == NSLeftMouseDown)) { + + // Check whether the click was inside the text part of a cell. For now, we do + // this a bit hackishly and assume the cell image is set and has width 20, + // and there is a gap of 3 pixels between image and label. + NSPoint point = [self convertPoint:[theEvent locationInWindow] fromView:nil]; + int clickedRow = [self rowAtPoint:point]; + mColumnToBeEdited = [self columnAtPoint:point]; + if (clickedRow >= 0 && mColumnToBeEdited >= 0) + { + NSRect rect = [self frameOfCellAtColumn:mColumnToBeEdited row:clickedRow]; + rect.size.width = 20.0 + 3.0; + wasClickInTextPartOfCell = ! NSPointInRect(point, rect); + } + + // Do not start editing for clicks on the icon part (to match Finder's behaviour). + if (wasClickInTextPartOfCell) { + + if ([theEvent modifierFlags] & NSAlternateKeyMask) + { + // If the alt key was pressed, start editing right away + mRowToBeEdited = newRow; + [self _editItem:nil]; + } + else if (oldRow == newRow) { + // If the click was into an already selected row, start editing + // after a short (1 second) delay - unless it gets canceled before + // of course, e.g. by a click someplace else. + mRowToBeEdited = newRow; + [self performSelector:@selector(_editItem:) withObject:nil afterDelay:1.0]; + } + } + } +} + +-(void)setAllowsEditing:(BOOL)inAllow +{ + mAllowsEditing = inAllow; +} + @end diff --git a/camino/src/extensions/RDFOutlineViewDataSource.mm b/camino/src/extensions/RDFOutlineViewDataSource.mm index f20bee4dd950..c3dbd4e58ed5 100644 --- a/camino/src/extensions/RDFOutlineViewDataSource.mm +++ b/camino/src/extensions/RDFOutlineViewDataSource.mm @@ -331,9 +331,10 @@ if (!mDataSource || !aItem) return nil; - // The table column's identifier is the RDF Resource URI of the property being displayed in - // that column, e.g. "http://home.netscape.com/NC-rdf#Name" - NSString* columnPropertyURI = [aTableColumn identifier]; + // The table column's identifier is the last part of the RDF Resource URI of the property + // being displayed in that column, e.g. "http://home.netscape.com/NC-rdf#Name" + NSString* columnPropertyURI = [NSString stringWithFormat:@"http://home.netscape.com/NC-rdf#%@", + [aTableColumn identifier]]; NSString* propString = [self getPropertyString:columnPropertyURI forItem:aItem]; return [self createCellContents:propString withColumn:columnPropertyURI byItem:aItem]; diff --git a/camino/src/history/HistoryDataSource.h b/camino/src/history/HistoryDataSource.h index 1fb186b49223..0c3180ffaac9 100644 --- a/camino/src/history/HistoryDataSource.h +++ b/camino/src/history/HistoryDataSource.h @@ -57,6 +57,7 @@ class HistoryDataSourceObserver; - (id)createCellContents:(NSString*)inValue withColumn:(NSString*)inColumn byItem:(id) inItem; - (NSString *)outlineView:(NSOutlineView *)outlineView tooltipStringForItem:(id)inItem; +- (void)outlineView:(NSOutlineView *)outlineView willDisplayCell:(NSCell *)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item; - (void)enableObserver; - (void)disableObserver; diff --git a/camino/src/history/HistoryDataSource.mm b/camino/src/history/HistoryDataSource.mm index 52b7c441fec7..86f80a2be0e5 100644 --- a/camino/src/history/HistoryDataSource.mm +++ b/camino/src/history/HistoryDataSource.mm @@ -260,45 +260,14 @@ HistoryDataSourceObserver::OnChange(nsIRDFDataSource*, nsIRDFResource*, // // createCellContents:withColumn:byItem // -// override to create an NSAttributedString instead of just the string with the -// given text. We add an icon and adjust the positioning of the text w/in the cell +// override to look up the URL if the name is empty. We'll obviously always have a +// name. // -(id) createCellContents:(NSString*)inValue withColumn:(NSString*)inColumn byItem:(id) inItem { if ([inValue length] == 0) inValue = [self getPropertyString:@"http://home.netscape.com/NC-rdf#URL" forItem:inItem]; - - NSMutableAttributedString *cellValue = [[[NSMutableAttributedString alloc] initWithString:inValue] autorelease]; - - if ([inColumn isEqualToString:@"http://home.netscape.com/NC-rdf#Name"]) - { - NSFileWrapper *fileWrapper = [[NSFileWrapper alloc] initRegularFileWithContents:nil]; - NSTextAttachment *textAttachment = [[NSTextAttachment alloc] initWithFileWrapper:fileWrapper]; - - // Create an attributed string to hold the empty attachment, then release the components. - NSMutableAttributedString *attachmentAttrString = [NSMutableAttributedString attributedStringWithAttachment:textAttachment]; - [textAttachment release]; - [fileWrapper release]; - - //Get the cell of the text attachment. - NSCell* attachmentAttrStringCell = (NSCell *)[(NSTextAttachment *)[attachmentAttrString attribute: - NSAttachmentAttributeName atIndex:0 effectiveRange:nil] attachmentCell]; - - if ([self outlineView:mOutlineView isItemExpandable:inItem]) - [attachmentAttrStringCell setImage:[NSImage imageNamed:@"folder"]]; - else - [attachmentAttrStringCell setImage:[NSImage imageNamed:@"smallbookmark"]]; - - //Insert the image - [cellValue replaceCharactersInRange:NSMakeRange(0, 0) withAttributedString:attachmentAttrString]; - - //Tweak the baseline to vertically center the text. - [cellValue addAttribute:NSBaselineOffsetAttributeName - value:[NSNumber numberWithFloat:-5.0] - range:NSMakeRange(0, 1)]; - } - - return cellValue; + return inValue; } @@ -457,4 +426,15 @@ HistoryDataSourceObserver::OnChange(nsIRDFDataSource*, nsIRDFResource*, return nil; } +- (void)outlineView:(NSOutlineView *)outlineView willDisplayCell:(NSCell *)inCell forTableColumn:(NSTableColumn *)tableColumn item:(id)item +{ + // set the image on the name column. the url column doesn't have an image. + if ([[tableColumn identifier] isEqualToString: @"Name"]) { + if ( [outlineView isExpandable: item] ) + [inCell setImage:[NSImage imageNamed:@"folder"]]; + else + [inCell setImage:[NSImage imageNamed:@"globe_ico"]]; + } +} + @end