diff --git a/camino/resources/localized/English.lproj/BrowserWindow.nib/classes.nib b/camino/resources/localized/English.lproj/BrowserWindow.nib/classes.nib
index 7ba20ff3498..7cc02cd2599 100644
--- a/camino/resources/localized/English.lproj/BrowserWindow.nib/classes.nib
+++ b/camino/resources/localized/English.lproj/BrowserWindow.nib/classes.nib
@@ -137,6 +137,7 @@
saveImageAs = id;
saveLinkAs = id;
savePageAs = id;
+ searchForSelection = id;
sendURL = id;
sendURLFromLink = id;
showBookmarksInfo = id;
@@ -164,7 +165,7 @@
mLinkMenu = NSMenu;
mLocationSheetURLField = NSTextField;
mLocationSheetWindow = NSWindow;
- mLocationToolbarView = NSSplitView;
+ mLocationToolbarView = ExtendedSplitView;
mMailToLinkMenu = NSMenu;
mPageMenu = NSMenu;
mPersonalToolbar = BookmarkToolbar;
@@ -188,6 +189,7 @@
SUPERCLASS = NSView;
},
{CLASS = ExtendedOutlineView; LANGUAGE = ObjC; SUPERCLASS = NSOutlineView; },
+ {CLASS = ExtendedSplitView; LANGUAGE = ObjC; SUPERCLASS = NSSplitView; },
{CLASS = ExtendedTableView; LANGUAGE = ObjC; SUPERCLASS = NSTableView; },
{
ACTIONS = {addBookmark = id; addBookmarkFolder = id; addBookmarkSeparator = id; };
diff --git a/camino/resources/localized/English.lproj/BrowserWindow.nib/info.nib b/camino/resources/localized/English.lproj/BrowserWindow.nib/info.nib
index 3eb4a3e10c8..6e429d44042 100644
--- a/camino/resources/localized/English.lproj/BrowserWindow.nib/info.nib
+++ b/camino/resources/localized/English.lproj/BrowserWindow.nib/info.nib
@@ -13,19 +13,19 @@
1058
318 439 135 80 0 0 1600 1002
1066
- 775 752 600 85 0 0 1920 1178
+ 775 772 370 64 0 0 1920 1178
297
- 558 586 213 306 0 0 1600 1002
+ 688 734 226 306 0 0 1920 1178
314
306 574 213 156 0 0 1600 1002
336
159 679 226 206 0 0 1600 1002
365
- 123 707 98 168 0 0 1600 1002
+ 149 856 98 168 0 0 1920 1178
463
348 489 213 275 0 0 1600 1002
56
- 951 593 314 64 0 0 1920 1178
+ 803 772 314 64 0 0 1920 1178
654
620 416 210 149 0 0 1600 1002
801
diff --git a/camino/resources/localized/English.lproj/BrowserWindow.nib/keyedobjects.nib b/camino/resources/localized/English.lproj/BrowserWindow.nib/keyedobjects.nib
index 6b01a3dfd9b..679f9eff50e 100644
Binary files a/camino/resources/localized/English.lproj/BrowserWindow.nib/keyedobjects.nib and b/camino/resources/localized/English.lproj/BrowserWindow.nib/keyedobjects.nib differ
diff --git a/camino/src/browser/BrowserWindowController.h b/camino/src/browser/BrowserWindowController.h
index 8a1b6d8d908..41d14b65e79 100644
--- a/camino/src/browser/BrowserWindowController.h
+++ b/camino/src/browser/BrowserWindowController.h
@@ -104,11 +104,13 @@ typedef enum
@class BrowserTabViewItem;
@class AutoCompleteTextField;
@class SearchTextField;
+@class ExtendedSplitView;
+
@interface BrowserWindowController : NSWindowController
{
IBOutlet BrowserTabView* mTabBrowser;
- IBOutlet NSSplitView* mLocationToolbarView; // parent splitter of location and search
+ IBOutlet ExtendedSplitView* mLocationToolbarView; // parent splitter of location and search, strong
IBOutlet AutoCompleteTextField* mURLBar;
IBOutlet NSTextField* mStatus;
IBOutlet NSProgressIndicator* mProgress; // STRONG reference
@@ -211,6 +213,7 @@ typedef enum
- (IBAction)printDocument:(id)aSender;
- (IBAction)pageSetup:(id)aSender;
- (IBAction)performSearch:(id)aSender;
+- (IBAction)searchForSelection:(id)aSender;
- (IBAction)sendURL:(id)aSender;
- (IBAction)sendURLFromLink:(id)aSender;
diff --git a/camino/src/browser/BrowserWindowController.mm b/camino/src/browser/BrowserWindowController.mm
index 8f8081a4a01..5b3f2f3ef89 100644
--- a/camino/src/browser/BrowserWindowController.mm
+++ b/camino/src/browser/BrowserWindowController.mm
@@ -66,6 +66,7 @@
#import "DraggableImageAndTextCell.h"
#import "MVPreferencesController.h"
#import "ViewCertificateDialogController.h"
+#import "ExtendedSplitView.h"
#import "wallet.h"
#include "nsString.h"
@@ -142,6 +143,7 @@ const float kMininumURLAndSearchBarWidth = 128.0;
static NSString* const NavigatorWindowFrameSaveName = @"NavigatorWindow";
static NSString* const NavigatorWindowSearchBarWidth = @"SearchBarWidth";
+static NSString* const NavigatorWindowSearchBarHidden = @"SearchBarHidden";
static NSString* const kViewSourceProtocolString = @"view-source:";
const unsigned long kNoToolbarsChromeMask = (nsIWebBrowserChrome::CHROME_ALL & ~(nsIWebBrowserChrome::CHROME_TOOLBAR |
@@ -588,10 +590,12 @@ enum BWCOpenDest {
if (mShouldAutosave) {
[[self window] saveFrameUsingName: NavigatorWindowFrameSaveName];
- // save the width of the search bar so it's consistent regardless of the
+ // save the width and visibility of the search bar so it's consistent regardless of the
// size of the next window we create
const float searchBarWidth = [mSearchBar frame].size.width;
[[NSUserDefaults standardUserDefaults] setFloat:searchBarWidth forKey:NavigatorWindowSearchBarWidth];
+ BOOL isCollapsed = [mLocationToolbarView isSubviewCollapsed:mSearchBar];
+ [[NSUserDefaults standardUserDefaults] setBool:isCollapsed forKey:NavigatorWindowSearchBarHidden];
}
}
@@ -714,6 +718,7 @@ enum BWCOpenDest {
[self stopThrobber];
[mThrobberImages release];
[mURLFieldEditor release];
+ [mLocationToolbarView release];
delete mDataOwner; // paranoia; should have been deleted in -windowWillClose
@@ -730,6 +735,15 @@ enum BWCOpenDest {
{
[super windowDidLoad];
+ // we shouldn't have to do this, yet for some reason removing it from
+ // the toolbar destroys the view. However, this also helps us by ensuring
+ // that we always have a search bar alive to do things with, like redirect
+ // context menu searches to.
+ [mLocationToolbarView retain];
+ // explicitly don't save the splitter position, we want to save it oursevles
+ // since we want a different behavior.
+ [mLocationToolbarView setAutosaveSplitterPosition:NO];
+
BOOL mustResizeChrome = NO;
// hide the resize control if specified by the chrome mask
@@ -805,17 +819,23 @@ enum BWCOpenDest {
[self setupToolbar];
- // set the size of the search bar to the width it was last time
- float searchBarWidth = [[NSUserDefaults standardUserDefaults] floatForKey:NavigatorWindowSearchBarWidth];
- if (searchBarWidth <= 0)
- searchBarWidth = kMininumURLAndSearchBarWidth;
- const float currentWidth = [mLocationToolbarView frame].size.width;
- float newDividerPosition = currentWidth - searchBarWidth - [mLocationToolbarView dividerThickness];
- if (newDividerPosition < kMininumURLAndSearchBarWidth)
- newDividerPosition = kMininumURLAndSearchBarWidth;
- [mLocationToolbarView setLeftWidth:newDividerPosition];
- [mLocationToolbarView adjustSubviews];
-
+ // set the size of the search bar to the width it was last time and hide it
+ // programmatically if it wasn't visible
+ BOOL searchBarHidden = [[NSUserDefaults standardUserDefaults] boolForKey:NavigatorWindowSearchBarHidden];
+ if (searchBarHidden)
+ [mLocationToolbarView collapseSubviewAtIndex:1];
+ else {
+ float searchBarWidth = [[NSUserDefaults standardUserDefaults] floatForKey:NavigatorWindowSearchBarWidth];
+ if (searchBarWidth <= 0)
+ searchBarWidth = kMininumURLAndSearchBarWidth;
+ const float currentWidth = [mLocationToolbarView frame].size.width;
+ float newDividerPosition = currentWidth - searchBarWidth - [mLocationToolbarView dividerThickness];
+ if (newDividerPosition < kMininumURLAndSearchBarWidth)
+ newDividerPosition = kMininumURLAndSearchBarWidth;
+ [mLocationToolbarView setLeftWidth:newDividerPosition];
+ [mLocationToolbarView adjustSubviews];
+ }
+
// set up autohide behavior on tab browser and register for changes on that pref. The
// default is for it to hide when only 1 tab is visible, so if no pref is found, it will
// be NO, and that works. However, if any of the JS chrome flags are set, we don't want
@@ -1379,12 +1399,12 @@ enum BWCOpenDest {
// -splitView:canCollapseSubview:
// NSSplitView delegate
//
-// We don't want to allow the user to collapse either the url bar or the search bar
+// Allow the user (read: smokey) to collapse the search bar but not the url bar.
//
- (BOOL)splitView:(NSSplitView *)sender canCollapseSubview:(NSView *)subview
{
if (sender == mLocationToolbarView)
- return NO;
+ return (subview == mSearchBar);
return YES;
}
@@ -1768,26 +1788,10 @@ enum BWCOpenDest {
//
- (void)performAppropriateSearchAction
{
- NSToolbar *toolbar = [[self window] toolbar];
- if ( [toolbar isVisible] )
- {
- if ( ([[[self window] toolbar] displayMode] == NSToolbarDisplayModeIconAndLabel) ||
- ([[[self window] toolbar] displayMode] == NSToolbarDisplayModeIconOnly) )
- {
- NSArray *itemsWeCanSee = [toolbar visibleItems];
-
- for (unsigned int i = 0; i < [itemsWeCanSee count]; i++)
- {
- if ([[[itemsWeCanSee objectAtIndex:i] itemIdentifier] isEqual:CombinedLocationToolbarItemIdentifier])
- {
- [self focusSearchBar];
- return;
- }
- }
- }
- }
-
- [self beginSearchSheet];
+ if ([mSearchBar window] && ![mLocationToolbarView isSubviewCollapsed:mSearchBar])
+ [self focusSearchBar];
+ else
+ [self beginSearchSheet];
}
- (void)focusSearchBar
@@ -2003,6 +2007,22 @@ enum BWCOpenDest {
[self performSearch:(SearchTextField *)aSender inView:kDestinationCurrentView inBackground:NO];
}
+//
+// -searchForSelection:
+//
+// Get the selection, stick it into the search bar, and do a search with the
+// currently selected search engine in the search bar. If there is no search
+// bar in the toolbar, that's still ok because we've guaranteed that we always
+// have a search bar even if it's not on a toolbar.
+//
+- (IBAction)searchForSelection:(id)aSender
+{
+ NSString* selection = [[mBrowserView getBrowserView] getSelection];
+ [mSearchBar becomeFirstResponder];
+ [mSearchBar setStringValue:selection];
+ [self performSearch:mSearchBar];
+}
+
//
// - performSearch:inView:inBackground
//
@@ -3259,7 +3279,9 @@ enum BWCOpenDest {
NSMenu* menuPrototype = nil;
int contextMenuFlags = mDataOwner->mContextMenuFlags;
-
+
+ BOOL hasSelection = [[mBrowserView getBrowserView] canCopy];
+
if ((contextMenuFlags & nsIContextMenuListener::CONTEXT_LINK) != 0)
{
NSString* emailAddress = [self getMailAddressFromContextMenuLinkNode];
@@ -3295,9 +3317,9 @@ enum BWCOpenDest {
menuPrototype = mPageMenu;
[mBackItem setEnabled: [[mBrowserView getBrowserView] canGoBack]];
[mForwardItem setEnabled: [[mBrowserView getBrowserView] canGoForward]];
- [mCopyItem setEnabled: [[mBrowserView getBrowserView] canCopy]];
+ [mCopyItem setEnabled:hasSelection];
}
-
+
if (mDataOwner->mContextMenuNode) {
nsCOMPtr ownerDoc;
mDataOwner->mContextMenuNode->GetOwnerDocument(getter_AddRefs(ownerDoc));
@@ -3315,8 +3337,17 @@ enum BWCOpenDest {
// our only copy of the menu
NSMenu* result = [[menuPrototype copy] autorelease];
- const int kFrameRelatedItemsTag = 100;
+ const int kFrameRelatedItemsTag = 100;
const int kFrameInapplicableItemsTag = 101;
+ const int kSelectionRelatedItemsTag = 102;
+
+ // if there's no selection or no search bar in the toolbar, hide the search item.
+ // We need a search item to know what the user's preferred search is.
+ if (!hasSelection) {
+ NSMenuItem* selectionItem;
+ while ((selectionItem = [result itemWithTag:kSelectionRelatedItemsTag]) != nil)
+ [result removeItem:selectionItem];
+ }
if (showFrameItems) {
NSMenuItem* frameItem;
diff --git a/camino/src/browser/SearchTextField.m b/camino/src/browser/SearchTextField.m
index 7f80a6ddcbc..1b9d0728f8f 100644
--- a/camino/src/browser/SearchTextField.m
+++ b/camino/src/browser/SearchTextField.m
@@ -153,6 +153,22 @@
[super textDidChange: aNotification];
}
+//
+// -setStringValue:
+//
+// Override to display the clear (x) when setting the search bar's text
+// programmatically.
+//
+- (void)setStringValue:(NSString*)inValue
+{
+ [super setStringValue:inValue];
+
+ // force the (x) to display when string changed programmatically. This
+ // has to come after our call to super otherwise the cell won't have the
+ // new value yet.
+ [[self cell] searchSubmittedFromView:self];
+}
+
- (NSString *)titleOfSelectedPopUpItem
{
return [[[self cell] popUpButtonCell] titleOfSelectedItem];
diff --git a/camino/src/embedding/CHBrowserView.h b/camino/src/embedding/CHBrowserView.h
index 53eaab5b0e6..1e8081e921e 100644
--- a/camino/src/embedding/CHBrowserView.h
+++ b/camino/src/embedding/CHBrowserView.h
@@ -225,6 +225,9 @@ typedef enum {
-(BOOL)canDelete;
-(IBAction)selectAll:(id)aSender;
+// Returns the currently selected text as a NSString.
+- (NSString*)getSelection;
+
-(IBAction)undo:(id)aSender;
-(IBAction)redo:(id)aSender;
diff --git a/camino/src/extensions/ExtendedSplitView.h b/camino/src/extensions/ExtendedSplitView.h
index 0ff25c68ad3..85ff585c4ac 100644
--- a/camino/src/extensions/ExtendedSplitView.h
+++ b/camino/src/extensions/ExtendedSplitView.h
@@ -41,8 +41,9 @@
@interface ExtendedSplitView : NSSplitView
{
- NSString* mAutosaveName; // owned
+ NSString* mAutosaveName; // owned
BOOL mAutosaveSplitterPosition;
+ NSMutableDictionary* mCollapsedSubviews; // owned
}
- (void)setAutosaveName:(NSString *)name;
@@ -51,4 +52,6 @@
- (BOOL)autosaveSplitterPosition;
- (void)setAutosaveSplitterPosition:(BOOL)inAutosave;
+- (void)collapseSubviewAtIndex:(int)inIndex;
+
@end
diff --git a/camino/src/extensions/ExtendedSplitView.m b/camino/src/extensions/ExtendedSplitView.m
index 2f504a8c6ea..8ea3be8ccde 100644
--- a/camino/src/extensions/ExtendedSplitView.m
+++ b/camino/src/extensions/ExtendedSplitView.m
@@ -60,6 +60,7 @@
{
// we'll default to saving (if we have an autosaveName)
mAutosaveSplitterPosition = YES;
+ mCollapsedSubviews = [[NSMutableDictionary alloc] init];
}
return self;
}
@@ -67,6 +68,7 @@
- (void)dealloc
{
[mAutosaveName release];
+ [mCollapsedSubviews release];
[super dealloc];
}
@@ -191,5 +193,81 @@
}
}
+//
+// -collapseSubviewAtIndex:
+//
+// Called to programmatically collapse the given subview. Removes it from the
+// view and we will manage it ourselves when it comes time to re-insert it into
+// the split view. Replaces it with a temporary view so we know what to look for.
+//
+- (void)collapseSubviewAtIndex:(int)inIndex
+{
+ // be lazy with the allocation, we generally will never need it
+ if (!mCollapsedSubviews)
+ mCollapsedSubviews = [[NSMutableDictionary alloc] init];
+
+ NSView* viewToCollapse = [[self subviews] objectAtIndex:inIndex];
+ NSView* placeholder = [[[NSView alloc] initWithFrame:NSZeroRect] autorelease];
+ [mCollapsedSubviews setObject:viewToCollapse forKey:[NSValue valueWithPointer:placeholder]];
+ [self replaceSubview:viewToCollapse with:placeholder];
+ [self adjustSubviews];
+}
+
+//
+// -drawDividerInRect:
+//
+// Watches for changes to the size of one of our temporary views that have
+// been hidden programmatically. When we notice one changing size, swap the
+// associated real view back in in its place.
+//
+- (void)drawDividerInRect:(NSRect)inRect
+{
+ if ([mCollapsedSubviews count]) {
+ // loop over all the the keys (the placeholder views) to see if they've changed size.
+ // if they have, swap back in the object at that key (the real view).
+ NSEnumerator* e = [mCollapsedSubviews keyEnumerator];
+ NSValue* key = nil;
+ while ((key = (NSValue*)[e nextObject])) {
+ NSView* placeholderView = (NSView*)[key pointerValue];
+ NSSize viewSize = [placeholderView frame].size;
+ BOOL isVertical = [self isVertical];
+ if ((isVertical && viewSize.width > 0) || (!isVertical && viewSize.height > 0)) {
+ // swap out the temp view if size changed with the view we cached
+ // in the collapse function
+ NSView* realView = [mCollapsedSubviews objectForKey:key];
+ [realView setFrameSize:viewSize];
+ [self replaceSubview:placeholderView with:realView];
+ [self adjustSubviews];
+ [mCollapsedSubviews removeObjectForKey:key];
+ }
+ }
+ }
+ [super drawDividerInRect:inRect];
+}
+
+//
+// -isSubviewCollapsed:
+//
+// Overridden to check our list of programmatically collapsed subviews if the base
+// class didn't find it as hidden already.
+//
+- (BOOL)isSubviewCollapsed:(NSView*)inView
+{
+ BOOL isCollapsed = [super isSubviewCollapsed:inView];
+ if (!isCollapsed) {
+ // check our list of hidden views to see if it's in that list
+ if ([mCollapsedSubviews count]) {
+ NSEnumerator* e = [mCollapsedSubviews objectEnumerator];
+ NSView* view = nil;
+ while ((view = (NSView*)[e nextObject])) {
+ if (view == inView) {
+ isCollapsed = YES;
+ break;
+ }
+ }
+ }
+ }
+ return isCollapsed;
+}
@end // ExtendedSplitView