new in-window bookmark manager.

This commit is contained in:
pinkerton%netscape.com 2003-03-24 02:10:08 +00:00
parent 1702517963
commit 96da93ef2f
20 changed files with 684 additions and 220 deletions

View File

@ -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;

View File

@ -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;

View File

@ -3,7 +3,7 @@
<plist version="1.0">
<dict>
<key>IBDocumentLocation</key>
<string>185 81 653 383 0 0 1280 832 </string>
<string>263 57 653 383 0 0 1280 832 </string>
<key>IBEditorPositions</key>
<dict>
<key>124</key>
@ -45,6 +45,7 @@
<array/>
<key>IBOpenObjects</key>
<array>
<integer>160</integer>
<integer>731</integer>
</array>
<key>IBSystem Version</key>

View File

@ -9,7 +9,7 @@
<key>266</key>
<string>644 623 277 90 0 0 1600 1002 </string>
<key>29</key>
<string>191 940 433 44 0 0 1280 1002 </string>
<string>191 773 433 44 0 0 1280 832 </string>
<key>494</key>
<string>569 607 185 78 0 0 1280 1002 </string>
</dict>

View File

@ -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]

View File

@ -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 <Cocoa/Cocoa.h>
@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 <NSDraggingInfo>)info proposedRow:(int)row proposedDropOperation:(NSTableViewDropOperation)op;
//- (BOOL)tableView:(NSTableView*)tv acceptDrop:(id <NSDraggingInfo>)info row:(int)row dropOperation:(NSTableViewDropOperation)op;
@end

View File

@ -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 = @"<Search result here>";
else
itemString = @"<URL result here>";
}
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

View File

@ -63,6 +63,7 @@
-(void) windowClosing;
-(void) ensureBookmarks;
- (void)restoreFolderExpandedStates;
-(IBAction)addBookmark:(id)aSender;
-(void)endAddBookmark: (int)aCode;

View File

@ -21,6 +21,7 @@
*
* Contributor(s):
* Simon Fraser <sfraser@netscape.com>
* Max Horn <max@quendi.de>
*
*
* 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];
}
}

View File

@ -24,8 +24,7 @@
#import <AppKit/AppKit.h>
#import "ExtendedOutlineView.h"
@interface BookmarksOutlineView : ExtendedOutlineView {
@interface BookmarksOutlineView : ExtendedOutlineView
{
}
@end

View File

@ -169,7 +169,7 @@ protected:
@interface BookmarkItem : NSObject
@interface BookmarkItem : NSObject <NSCopying>
{
nsIContent* mContentNode;
NSImage* mSiteIcon;

View File

@ -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,

View File

@ -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 <QuickTime/QuickTime.h>
#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

View File

@ -24,14 +24,20 @@
#import <AppKit/AppKit.h>
@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;

View File

@ -19,7 +19,7 @@
*
* Contributor(s):
* David Hyatt <hyatt@netscape.com> (Original Author)
* Max Horn <max@quendi.de> (Context menu & tooltip code)
* Max Horn <max@quendi.de> (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

View File

@ -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];

View File

@ -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;

View File

@ -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