summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorshess@chromium.org <shess@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-04-06 22:51:11 +0000
committershess@chromium.org <shess@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-04-06 22:51:11 +0000
commit5856887365d0b2a48ed2c5d160b50904959edb59 (patch)
tree8684e18b08031dff4a953a3c07f63795bbbdb729 /chrome
parente713032402418e679b6ad93f75ac33e879b9ceee (diff)
downloadchromium_src-5856887365d0b2a48ed2c5d160b50904959edb59.zip
chromium_src-5856887365d0b2a48ed2c5d160b50904959edb59.tar.gz
chromium_src-5856887365d0b2a48ed2c5d160b50904959edb59.tar.bz2
Initial implemention of Mac Omnibox.
AutocompletePopupViewMac implements AutocompletePopupView in terms of a bare NSWindow containing an NSTableView. AutocompleteTableTarget implements an Obj-C class to bridge from appkit callbacks back to the popup view (and from there to the model which contains the data it needs). AutocompleteEditViewMac implements AutocompleteEditView in terms of an NSTextField, which is passed down from a nib owner. It works with the popup view to make sure the popup is positioned correctly. AutocompleteFieldDelegate is an internal Obj-C class to bridge from appkit callbacks back to the edit view (and then the edit model). LocationBarViewMac implements LocationBar for interacting with the rest of the browser, and AutocompleteEditController for managing the edit and popup views. It is mostly placeholder code stolen from the gtk implementation. --- I've tried to implement an amount of code which worked and was useful, but which didn't drag on and on into the future. So no tab to search or hints or anything, sometimes ugly, selection may be funky, etc. Review URL: http://codereview.chromium.org/50074 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@13201 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/app_controller_mac.mm16
-rw-r--r--chrome/browser/autocomplete/autocomplete_edit_view.h2
-rw-r--r--chrome/browser/autocomplete/autocomplete_edit_view_gtk.cc2
-rw-r--r--chrome/browser/autocomplete/autocomplete_edit_view_mac.h124
-rw-r--r--chrome/browser/autocomplete/autocomplete_edit_view_mac.mm309
-rw-r--r--chrome/browser/autocomplete/autocomplete_popup_view_mac.h97
-rw-r--r--chrome/browser/autocomplete/autocomplete_popup_view_mac.mm248
-rw-r--r--chrome/browser/cocoa/location_bar_view_mac.h71
-rw-r--r--chrome/browser/cocoa/location_bar_view_mac.mm120
-rw-r--r--chrome/browser/cocoa/tab_contents_controller.h5
-rw-r--r--chrome/browser/cocoa/tab_contents_controller.mm96
-rw-r--r--chrome/browser/cocoa/tab_strip_controller.mm15
-rw-r--r--chrome/chrome.gyp9
13 files changed, 1028 insertions, 86 deletions
diff --git a/chrome/browser/app_controller_mac.mm b/chrome/browser/app_controller_mac.mm
index 98ed64b..c042dd8 100644
--- a/chrome/browser/app_controller_mac.mm
+++ b/chrome/browser/app_controller_mac.mm
@@ -2,17 +2,17 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#import "app_controller_mac.h"
+#import "chrome/browser/app_controller_mac.h"
-#import "base/message_loop.h"
-#import "chrome/app/chrome_dll_resource.h"
-#import "chrome/browser/browser.h"
-#import "chrome/browser/browser_list.h"
+#include "base/message_loop.h"
+#include "chrome/app/chrome_dll_resource.h"
+#include "chrome/browser/browser.h"
+#include "chrome/browser/browser_list.h"
#include "chrome/browser/browser_shutdown.h"
#import "chrome/browser/cocoa/bookmark_menu_bridge.h"
-#import "chrome/browser/command_updater.h"
-#import "chrome/browser/profile_manager.h"
-#import "chrome/common/temp_scaffolding_stubs.h"
+#include "chrome/browser/command_updater.h"
+#include "chrome/browser/profile_manager.h"
+#include "chrome/common/temp_scaffolding_stubs.h"
@interface AppController(PRIVATE)
- (void)initMenuState;
diff --git a/chrome/browser/autocomplete/autocomplete_edit_view.h b/chrome/browser/autocomplete/autocomplete_edit_view.h
index 93982fe..27c28e7 100644
--- a/chrome/browser/autocomplete/autocomplete_edit_view.h
+++ b/chrome/browser/autocomplete/autocomplete_edit_view.h
@@ -3,7 +3,7 @@
// found in the LICENSE file.
// This file defines the interface class AutocompleteEditView. Each toolkit
-// will implement the edit view differently, so that code is inheriently
+// will implement the edit view differently, so that code is inherently
// platform specific. However, the AutocompleteEditModel needs to do some
// communication with the view. Since the model is shared between platforms,
// we need to define an interface that all view implementations will share.
diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_gtk.cc b/chrome/browser/autocomplete/autocomplete_edit_view_gtk.cc
index 277a965..69e8a9b 100644
--- a/chrome/browser/autocomplete/autocomplete_edit_view_gtk.cc
+++ b/chrome/browser/autocomplete/autocomplete_edit_view_gtk.cc
@@ -177,7 +177,7 @@ void AutocompleteEditViewGtk::OpenURL(const GURL& url,
model_->SendOpenNotification(selected_line, keyword);
if (disposition != NEW_BACKGROUND_TAB)
- RevertAll(); // Revert the box to its unedited state
+ RevertAll(); // Revert the box to its unedited state.
controller_->OnAutocompleteAccept(url, disposition, transition,
alternate_nav_url);
}
diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_mac.h b/chrome/browser/autocomplete/autocomplete_edit_view_mac.h
new file mode 100644
index 0000000..1d96a10
--- /dev/null
+++ b/chrome/browser/autocomplete/autocomplete_edit_view_mac.h
@@ -0,0 +1,124 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_AUTOCOMPLETE_AUTOCOMPLETE_EDIT_VIEW_MAC_H_
+#define CHROME_BROWSER_AUTOCOMPLETE_AUTOCOMPLETE_EDIT_VIEW_MAC_H_
+
+#import <Cocoa/Cocoa.h>
+
+#include "base/basictypes.h"
+#include "base/scoped_nsobject.h"
+#include "base/scoped_ptr.h"
+#include "chrome/browser/autocomplete/autocomplete.h"
+#include "chrome/browser/autocomplete/autocomplete_edit_view.h"
+#include "chrome/browser/toolbar_model.h"
+#include "chrome/common/page_transition_types.h"
+#include "webkit/glue/window_open_disposition.h"
+
+class AutocompleteEditController;
+@class AutocompleteEditHelper;
+class AutocompleteEditModel;
+class AutocompletePopupViewMac;
+class CommandUpdater;
+class Profile;
+class TabContents;
+class ToolbarModel;
+
+// Implements AutocompleteEditView on an NSTextField.
+
+class AutocompleteEditViewMac : public AutocompleteEditView {
+ public:
+ AutocompleteEditViewMac(AutocompleteEditController* controller,
+ ToolbarModel* toolbar_model,
+ Profile* profile,
+ CommandUpdater* command_updater);
+ virtual ~AutocompleteEditViewMac();
+
+ // Implement the AutocompleteEditView interface.
+ // TODO(shess): See if this couldn't be simplified to:
+ // virtual AEM* model() const { ... }
+ virtual AutocompleteEditModel* model() { return model_.get(); }
+ virtual const AutocompleteEditModel* model() const { return model_.get(); }
+
+ virtual void SaveStateToTab(TabContents* tab);
+ virtual void Update(const TabContents* tab_for_state_restoring) {
+ NOTIMPLEMENTED();
+ }
+
+ virtual void OpenURL(const GURL& url,
+ WindowOpenDisposition disposition,
+ PageTransition::Type transition,
+ const GURL& alternate_nav_url,
+ size_t selected_line,
+ const std::wstring& keyword);
+
+ virtual std::wstring GetText() const;
+ virtual void SetUserText(const std::wstring& text) { NOTIMPLEMENTED(); }
+ virtual void SetUserText(const std::wstring& text,
+ const std::wstring& display_text,
+ bool update_popup) { NOTIMPLEMENTED(); }
+
+ virtual void SetWindowTextAndCaretPos(const std::wstring& text,
+ size_t caret_pos);
+
+ virtual bool IsSelectAll() {
+ NOTIMPLEMENTED();
+ return false;
+ }
+
+ virtual void SelectAll(bool reversed);
+ virtual void RevertAll();
+ virtual void UpdatePopup();
+ virtual void ClosePopup();
+ void UpdateAndStyleText(const std::wstring& display_text,
+ size_t user_text_length);
+ virtual void OnTemporaryTextMaybeChanged(const std::wstring& display_text,
+ bool save_original_selection);
+ virtual bool OnInlineAutocompleteTextMaybeChanged(
+ const std::wstring& display_text, size_t user_text_length);
+ virtual void OnRevertTemporaryText();
+ virtual void OnBeforePossibleChange() { NOTIMPLEMENTED(); }
+ virtual bool OnAfterPossibleChange() { NOTIMPLEMENTED(); return false; }
+
+ // Helper functions which forward to our private: model_.
+ void OnUpOrDownKeyPressed(int dir);
+ void OnEscapeKeyPressed();
+ void OnSetFocus(bool f);
+ void OnKillFocus();
+ void AcceptInput(WindowOpenDisposition disposition, bool for_drop);
+ void OnAfterPossibleChange(const std::wstring& new_text,
+ bool selection_differs,
+ bool text_differs,
+ bool just_deleted_text,
+ bool at_end_of_edit);
+
+ // TODO(shess): Get rid of this. Right now it's needed because of
+ // the ordering of initialization in tab_contents_controller.mm.
+ void SetField(NSTextField* field);
+
+ // Helper for LocationBarBridge.
+ void FocusLocation();
+
+ private:
+ scoped_ptr<AutocompleteEditModel> model_;
+ scoped_ptr<AutocompletePopupViewMac> popup_view_;
+
+ AutocompleteEditController* controller_;
+ ToolbarModel* toolbar_model_;
+
+ // The object that handles additional command functionality exposed on the
+ // edit, such as invoking the keyword editor.
+ CommandUpdater* command_updater_;
+
+ NSTextField* field_; // owned by tab controller
+
+ // Objective-C object to bridge field_ delegate calls to C++.
+ scoped_nsobject<AutocompleteEditHelper> edit_helper_;
+
+ std::wstring saved_temporary_text_;
+
+ DISALLOW_COPY_AND_ASSIGN(AutocompleteEditViewMac);
+};
+
+#endif // CHROME_BROWSER_AUTOCOMPLETE_AUTOCOMPLETE_EDIT_VIEW_MAC_H_
diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_mac.mm b/chrome/browser/autocomplete/autocomplete_edit_view_mac.mm
new file mode 100644
index 0000000..cc0bffa
--- /dev/null
+++ b/chrome/browser/autocomplete/autocomplete_edit_view_mac.mm
@@ -0,0 +1,309 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/autocomplete/autocomplete_edit_view_mac.h"
+
+#include "base/sys_string_conversions.h"
+#include "chrome/browser/autocomplete/autocomplete_edit.h"
+#include "chrome/browser/autocomplete/autocomplete_popup_view_mac.h"
+
+// Thin Obj-C bridge class that is the delegate of the omnibox field.
+// It intercepts various control delegate methods and vectors them to
+// the edit view.
+
+@interface AutocompleteFieldDelegate : NSObject {
+ @private
+ AutocompleteEditViewMac* edit_view_; // weak, owns us.
+}
+- initWithEditView:(AutocompleteEditViewMac*)view;
+@end
+
+AutocompleteEditViewMac::AutocompleteEditViewMac(
+ AutocompleteEditController* controller,
+ ToolbarModel* toolbar_model,
+ Profile* profile,
+ CommandUpdater* command_updater)
+ : model_(new AutocompleteEditModel(this, controller, profile)),
+ popup_view_(new AutocompletePopupViewMac(this, model_.get(), profile)),
+ controller_(controller),
+ toolbar_model_(toolbar_model),
+ command_updater_(command_updater),
+ field_(nil),
+ edit_helper_([[AutocompleteFieldDelegate alloc] initWithEditView:this]) {
+ DCHECK(controller);
+ DCHECK(toolbar_model);
+ DCHECK(profile);
+ DCHECK(command_updater);
+}
+
+AutocompleteEditViewMac::~AutocompleteEditViewMac() {
+ // TODO(shess): Having to be aware of destructor ordering in this
+ // way seems brittle. There must be a better way.
+
+ // Destroy popup view before this object in case it tries to call us
+ // back in the destructor. Likewise for destroying the model before
+ // this object.
+ popup_view_.reset();
+ model_.reset();
+
+ // Disconnect field_ from edit_helper_ so that we don't get calls
+ // after destruction.
+ [field_ setDelegate:nil];
+}
+
+// TODO(shess): This is the minimal change which seems to unblock
+// getting the minimal Omnibox code checked in without making the
+// world worse. Browser::TabSelectedAt() calls this when the tab
+// changes, but that is only wired up for Windows. I do not yet
+// understand that code well enough to go for it. Once wired up, then
+// code can be removed at:
+// [TabContentsController defocusLocationBar]
+// [TabStripController selectTabWithContents:...]
+void AutocompleteEditViewMac::SaveStateToTab(TabContents* tab) {
+ // TODO(shess): Actually save the state to the tab area.
+
+ // Drop the popup before we change to another tab.
+ ClosePopup();
+}
+
+void AutocompleteEditViewMac::OpenURL(const GURL& url,
+ WindowOpenDisposition disposition,
+ PageTransition::Type transition,
+ const GURL& alternate_nav_url,
+ size_t selected_line,
+ const std::wstring& keyword) {
+ // TODO(shess): Why is the caller passing an invalid url in the
+ // first place? Make sure that case isn't being dropped on the
+ // floor.
+ if (!url.is_valid()) {
+ return;
+ }
+
+ model_->SendOpenNotification(selected_line, keyword);
+
+ if (disposition != NEW_BACKGROUND_TAB)
+ RevertAll(); // Revert the box to its unedited state.
+ controller_->OnAutocompleteAccept(url, disposition, transition,
+ alternate_nav_url);
+}
+
+std::wstring AutocompleteEditViewMac::GetText() const {
+ return base::SysNSStringToWide([field_ stringValue]);
+}
+
+void AutocompleteEditViewMac::SetWindowTextAndCaretPos(const std::wstring& text,
+ size_t caret_pos) {
+ UpdateAndStyleText(text, text.size());
+}
+
+void AutocompleteEditViewMac::SelectAll(bool reversed) {
+ // TODO(shess): Figure out what reversed implies. The gtk version
+ // has it imply inverting the selection front to back, but I don't
+ // even know if that makes sense for Mac.
+ UpdateAndStyleText(GetText(), 0);
+}
+
+void AutocompleteEditViewMac::RevertAll() {
+ ClosePopup();
+ model_->Revert();
+
+ std::wstring tt = GetText();
+ UpdateAndStyleText(tt, tt.size());
+ controller_->OnChanged();
+}
+
+void AutocompleteEditViewMac::UpdatePopup() {
+ model_->SetInputInProgress(true);
+ if (!model_->has_focus())
+ return;
+
+ // TODO(shess):
+ // Shouldn't inline autocomplete when the caret/selection isn't at
+ // the end of the text.
+ //
+ // One option would seem to be to check for a non-nil field
+ // editor, and check it's selected range against its length.
+ model_->StartAutocomplete(false);
+}
+
+void AutocompleteEditViewMac::ClosePopup() {
+ popup_view_->StopAutocomplete();
+}
+
+void AutocompleteEditViewMac::UpdateAndStyleText(
+ const std::wstring& display_text, size_t user_text_length) {
+ NSString* ss = base::SysWideToNSString(display_text);
+ NSMutableAttributedString* as =
+ [[[NSMutableAttributedString alloc] initWithString:ss] autorelease];
+
+ url_parse::Parsed parts;
+ AutocompleteInput::Parse(display_text, model_->GetDesiredTLD(),
+ &parts, NULL);
+ bool emphasize = model_->CurrentTextIsURL() && (parts.host.len > 0);
+ if (emphasize) {
+ // TODO(shess): Pull color out as a constant.
+ [as addAttribute:NSForegroundColorAttributeName
+ value:[NSColor greenColor]
+ range:NSMakeRange((NSInteger)parts.host.begin,
+ (NSInteger)parts.host.end())];
+ }
+
+ // TODO(shess): GTK has this as a member var, figure out why.
+ ToolbarModel::SecurityLevel scheme_security_level =
+ toolbar_model_->GetSchemeSecurityLevel();
+
+ // Emphasize the scheme for security UI display purposes (if necessary).
+ if (!model_->user_input_in_progress() && parts.scheme.is_nonempty() &&
+ (scheme_security_level != ToolbarModel::NORMAL)) {
+ // TODO(shess): Pull colors out as constants.
+ NSColor* color;
+ if (scheme_security_level == ToolbarModel::SECURE) {
+ color = [NSColor blueColor];
+ } else {
+ color = [NSColor blackColor];
+ }
+ [as addAttribute:NSForegroundColorAttributeName value:color
+ range:NSMakeRange((NSInteger)parts.scheme.begin,
+ (NSInteger)parts.scheme.end())];
+ }
+
+ // TODO(shess): Check that this updates the model's sense of focus
+ // correctly.
+ [field_ setObjectValue:as];
+ if (![field_ currentEditor]) {
+ [field_ becomeFirstResponder];
+ DCHECK_EQ(field_, [[field_ window] firstResponder]);
+ }
+
+ NSRange selected_range = NSMakeRange(user_text_length, [as length]);
+ // TODO(shess): What if it didn't get first responder, and there is
+ // no field editor? This will do nothing. Well, at least it won't
+ // crash. Think of something more productive to do, or prove that
+ // it cannot occur and DCHECK appropriately.
+ [[field_ currentEditor] setSelectedRange:selected_range];
+}
+
+void AutocompleteEditViewMac::OnTemporaryTextMaybeChanged(
+ const std::wstring& display_text, bool save_original_selection) {
+ // TODO(shess): I believe this is for when the user arrows around
+ // the popup, will be restored if they hit escape. Figure out if
+ // that is for certain it.
+ if (save_original_selection) {
+ saved_temporary_text_ = GetText();
+ }
+
+ UpdateAndStyleText(display_text, display_text.size());
+}
+
+bool AutocompleteEditViewMac::OnInlineAutocompleteTextMaybeChanged(
+ const std::wstring& display_text, size_t user_text_length) {
+ // TODO(shess): Make sure that this actually works. The round trip
+ // to native form and back may mean that it's the same but not the
+ // same.
+ if (display_text == GetText()) {
+ return false;
+ }
+
+ UpdateAndStyleText(display_text, user_text_length);
+ return true;
+}
+
+void AutocompleteEditViewMac::OnRevertTemporaryText() {
+ UpdateAndStyleText(saved_temporary_text_, saved_temporary_text_.size());
+ saved_temporary_text_.clear();
+}
+
+void AutocompleteEditViewMac::OnUpOrDownKeyPressed(int dir) {
+ model_->OnUpOrDownKeyPressed(dir);
+}
+void AutocompleteEditViewMac::OnEscapeKeyPressed() {
+ model_->OnEscapeKeyPressed();
+}
+void AutocompleteEditViewMac::OnSetFocus(bool f) {
+ model_->OnSetFocus(f);
+}
+void AutocompleteEditViewMac::OnKillFocus() {
+ model_->OnKillFocus();
+}
+void AutocompleteEditViewMac::AcceptInput(
+ WindowOpenDisposition disposition, bool for_drop) {
+ model_->AcceptInput(disposition, for_drop);
+}
+void AutocompleteEditViewMac::OnAfterPossibleChange(
+ const std::wstring& new_text,
+ bool selection_differs,
+ bool text_differs,
+ bool just_deleted_text,
+ bool at_end_of_edit) {
+ model_->OnAfterPossibleChange(new_text, selection_differs, text_differs,
+ just_deleted_text, at_end_of_edit);
+}
+void AutocompleteEditViewMac::SetField(NSTextField* field) {
+ field_ = field;
+ [field_ setDelegate:edit_helper_];
+
+ // The popup code needs the field for sizing and placement.
+ popup_view_->SetField(field_);
+}
+
+void AutocompleteEditViewMac::FocusLocation() {
+ [[field_ window] makeFirstResponder:field_];
+}
+
+@implementation AutocompleteFieldDelegate
+
+- initWithEditView:(AutocompleteEditViewMac*)view {
+ self = [super init];
+ if (self) {
+ edit_view_ = view;
+ }
+ return self;
+}
+
+- (BOOL)control:(NSControl*)control
+ textView:(NSTextView*)textView doCommandBySelector:(SEL)cmd {
+ if (cmd == @selector(moveDown:)) {
+ edit_view_->OnUpOrDownKeyPressed(1);
+ return YES;
+ }
+
+ if (cmd == @selector(moveUp:)) {
+ edit_view_->OnUpOrDownKeyPressed(-1);
+ return YES;
+ }
+
+ if (cmd == @selector(cancelOperation:)) {
+ edit_view_->OnEscapeKeyPressed();
+ return YES;
+ }
+
+ if (cmd == @selector(insertNewline:)) {
+ edit_view_->AcceptInput(CURRENT_TAB, false);
+ return YES;
+ }
+
+ return NO;
+}
+
+- (void)controlTextDidBeginEditing:(NSNotification*)aNotification {
+ edit_view_->OnSetFocus(false);
+}
+
+- (void)controlTextDidChange:(NSNotification*)aNotification {
+ // TODO(shess): Make this more efficient? Or not. For now, just
+ // pass in the current text, indicating that the text and
+ // selection differ, ignoring deletions, and assuming that we're
+ // at the end of the text.
+ edit_view_->OnAfterPossibleChange(edit_view_->GetText(),
+ true, true, false, true);
+}
+
+- (void)controlTextDidEndEditing:(NSNotification*)aNotification {
+ edit_view_->OnKillFocus();
+
+ // TODO(shess): Figure out where the selection belongs. On GTK,
+ // it's set to the start of the text.
+}
+
+@end
diff --git a/chrome/browser/autocomplete/autocomplete_popup_view_mac.h b/chrome/browser/autocomplete/autocomplete_popup_view_mac.h
new file mode 100644
index 0000000..defa04f
--- /dev/null
+++ b/chrome/browser/autocomplete/autocomplete_popup_view_mac.h
@@ -0,0 +1,97 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_AUTOCOMPLETE_AUTOCOMPLETE_POPUP_VIEW_MAC_H_
+#define CHROME_BROWSER_AUTOCOMPLETE_AUTOCOMPLETE_POPUP_VIEW_MAC_H_
+
+#import <Cocoa/Cocoa.h>
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/scoped_ptr.h"
+#include "base/scoped_nsobject.h"
+#include "chrome/browser/autocomplete/autocomplete.h"
+#include "chrome/browser/autocomplete/autocomplete_popup_view.h"
+#include "webkit/glue/window_open_disposition.h"
+
+class AutocompletePopupModel;
+class AutocompleteEditModel;
+class AutocompleteEditViewMac;
+@class AutocompleteTableTarget;
+class Profile;
+
+// Implements AutocompletePopupView using a raw NSWindow containing an
+// NSTableView.
+
+class AutocompletePopupViewMac : public AutocompletePopupView {
+ public:
+ AutocompletePopupViewMac(AutocompleteEditViewMac* edit_view,
+ AutocompleteEditModel* edit_model,
+ Profile* profile);
+ virtual ~AutocompletePopupViewMac();
+
+ // Implement the AutocompletePopupView interface.
+ virtual bool IsOpen() const;
+ virtual void InvalidateLine(size_t line) {
+ // TODO(shess): Verify that there is no need to implement this.
+ // This is currently used in two places in the model:
+ //
+ // When setting the selected line, the selected line is
+ // invalidated, then the selected line is changed, then the new
+ // selected line is invalidated, then PaintUpdatesNow() is called.
+ // For us PaintUpdatesNow() should be sufficient.
+ //
+ // Same thing happens when changing the hovered line, except with
+ // no call to PaintUpdatesNow(). Since this code does not
+ // currently support special display of the hovered line, there's
+ // nothing to do here.
+ //
+ // deanm indicates that this is an anti-flicker optimization,
+ // which we probably cannot utilize (and may not need) so long as
+ // we're using NSTableView to implement the popup contents. We
+ // may need to move away from NSTableView to implement hover,
+ // though.
+ }
+ virtual void UpdatePopupAppearance();
+ virtual void OnHoverEnabledOrDisabled(bool disabled) { NOTIMPLEMENTED(); }
+
+ // This is only called by model in SetSelectedLine() after updating
+ // everything. Popup should already be visible.
+ virtual void PaintUpdatesNow();
+
+ // Helpers which forward to model_, otherwise our Objective-C helper
+ // object would need model_ to be public:.
+ void StopAutocomplete();
+ size_t ResultRowCount();
+ const std::wstring& ResultContentsAt(size_t i);
+ bool ResultStarredAt(size_t i);
+ const std::wstring& ResultDescriptionAt(size_t i);
+ void AcceptInput(WindowOpenDisposition disposition, bool for_drop);
+
+ // TODO(shess): Get rid of this. Right now it's needed because of
+ // the ordering of initialization in tab_contents_controller.mm.
+ void SetField(NSTextField* field) {
+ field_ = field;
+ }
+
+ private:
+ // Create the popup_ instance if needed.
+ void CreatePopupIfNeeded();
+
+ scoped_ptr<AutocompletePopupModel> model_;
+ AutocompleteEditViewMac* edit_view_;
+
+ NSTextField* field_; // owned by tab controller
+
+ scoped_nsobject<AutocompleteTableTarget> table_target_;
+ // TODO(shess): Before checkin review implementation to make sure
+ // that popup_'s object hierarchy doesn't keep references to
+ // destructed objects.
+ scoped_nsobject<NSWindow> popup_;
+
+ DISALLOW_COPY_AND_ASSIGN(AutocompletePopupViewMac);
+};
+
+#endif // CHROME_BROWSER_AUTOCOMPLETE_AUTOCOMPLETE_POPUP_VIEW_MAC_H_
diff --git a/chrome/browser/autocomplete/autocomplete_popup_view_mac.mm b/chrome/browser/autocomplete/autocomplete_popup_view_mac.mm
new file mode 100644
index 0000000..d82e0a3
--- /dev/null
+++ b/chrome/browser/autocomplete/autocomplete_popup_view_mac.mm
@@ -0,0 +1,248 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/autocomplete/autocomplete_popup_view_mac.h"
+
+#include "base/sys_string_conversions.h"
+#include "chrome/browser/autocomplete/autocomplete_edit.h"
+#include "chrome/browser/autocomplete/autocomplete_edit_view_mac.h"
+#include "chrome/browser/autocomplete/autocomplete_popup_model.h"
+
+// Thin Obj-C bridge class between the target and data source of the
+// popup window's NSTableView and the AutocompletePopupView
+// implementation.
+
+@interface AutocompleteTableTarget : NSObject {
+ @private
+ AutocompletePopupViewMac* popup_view_; // weak, owns us.
+}
+- initWithPopupView:(AutocompletePopupViewMac*)view;
+
+// Tell popup model via popup_view_ about the selected row.
+- (void)select:sender;
+
+// NSTableDataSource methods, filled from data returned by
+// the popup model via popup_view_.
+- (NSInteger)numberOfRowsInTableView:(NSTableView*)aTableView;
+- (id)tableView:(NSTableView*)aTableView
+objectValueForTableColumn:(NSTableColumn*)aTableColumn
+ row:(int)ri;
+
+// Placeholder for finding the star image.
+- (NSImage*)starImage;
+@end
+
+AutocompletePopupViewMac::AutocompletePopupViewMac(
+ AutocompleteEditViewMac* edit_view,
+ AutocompleteEditModel* edit_model,
+ Profile* profile)
+ : model_(new AutocompletePopupModel(this, edit_model, profile)),
+ edit_view_(edit_view),
+ field_(nil),
+ table_target_([[AutocompleteTableTarget alloc] initWithPopupView:this]),
+ popup_(nil) {
+ DCHECK(edit_view);
+ DCHECK(edit_model);
+ DCHECK(profile);
+ edit_model->set_popup_model(model_.get());
+}
+
+AutocompletePopupViewMac::~AutocompletePopupViewMac() {
+ // TODO(shess): Having to be aware of destructor ordering in this
+ // way seems brittle. There must be a better way.
+
+ // Destroy the popup model before this object is destroyed, because
+ // it can call back to us in the destructor.
+ model_.reset();
+
+ // Break references to table_target_ before it is released.
+ NSTableView* table = [popup_ contentView];
+ [table setTarget:nil];
+ [table setDataSource:nil];
+}
+
+bool AutocompletePopupViewMac::IsOpen() const {
+ return [popup_ isVisible] ? true : false;
+}
+
+static NSTableColumn* MakeTableColumn(int tag, Class field_class) {
+ NSNumber* id = [NSNumber numberWithInt:tag];
+ NSTableColumn* col =
+ [[[NSTableColumn alloc] initWithIdentifier:id] autorelease];
+
+ [col setEditable:NO];
+ [col setResizingMask:NSTableColumnNoResizing];
+ [col setDataCell:[[[field_class alloc] init] autorelease]];
+
+ return col;
+}
+
+void AutocompletePopupViewMac::CreatePopupIfNeeded() {
+ if (!popup_) {
+ popup_.reset([[NSWindow alloc] initWithContentRect:NSZeroRect
+ styleMask:NSBorderlessWindowMask
+ backing:NSBackingStoreBuffered
+ defer:YES]);
+ [popup_ setMovableByWindowBackground:NO];
+ [popup_ setOpaque:YES];
+ [popup_ setHasShadow:YES];
+ [popup_ setLevel:NSNormalWindowLevel];
+
+ NSTableView* table =
+ [[[NSTableView alloc] initWithFrame:NSZeroRect] autorelease];
+ [popup_ setContentView:table];
+
+ [table setTarget:table_target_];
+ [table setAction:@selector(select:)];
+ [table setHeaderView:nil];
+ [table setDataSource:table_target_];
+ [table setIntercellSpacing:NSMakeSize(1.0, 0.0)];
+
+ [table addTableColumn:MakeTableColumn(0, [NSTextFieldCell class])];
+ [table addTableColumn:MakeTableColumn(1, [NSImageCell class])];
+ [table addTableColumn:MakeTableColumn(2, [NSTextFieldCell class])];
+ }
+}
+
+void AutocompletePopupViewMac::UpdatePopupAppearance() {
+ const AutocompleteResult& result = model_->result();
+ if (result.empty()) {
+ [[popup_ parentWindow] removeChildWindow:popup_];
+ [popup_ orderOut:nil];
+ return;
+ }
+
+ CreatePopupIfNeeded();
+
+ // Layout the popup and size it to land underneath the field.
+ // TODO(shess) Consider refactoring to remove this depenency,
+ // because the popup doesn't need any of the field-like aspects of
+ // field_. The edit view could expose helper methods for attaching
+ // the window to the field.
+ NSRect r = [field_ bounds];
+ r = [field_ convertRectToBase:r];
+ r.origin = [[field_ window] convertBaseToScreen:r.origin];
+
+ // TODO(shess): Derive this from the actual image size, once the
+ // image is in the project.
+ static const int kStarWidth = 25;
+
+ NSArray* cols = [[popup_ contentView] tableColumns];
+ [[cols objectAtIndex:0] setWidth:floor((r.size.width - kStarWidth) / 2)];
+ [[cols objectAtIndex:1] setWidth:kStarWidth];
+ [[cols objectAtIndex:2] setWidth:ceil((r.size.width - kStarWidth) / 2)];
+
+ [[popup_ contentView] reloadData];
+ [[popup_ contentView] tile];
+ r.size.height = [[popup_ contentView] frame].size.height;
+ r.origin.y -= r.size.height + 2;
+
+ // Update the selection.
+ PaintUpdatesNow();
+
+ [popup_ setFrame:r display:YES];
+
+ if (!IsOpen()) {
+ [[field_ window] addChildWindow:popup_ ordered:NSWindowAbove];
+ }
+}
+
+// This is only called by model in SetSelectedLine() after updating
+// everything. Popup should already be visible.
+void AutocompletePopupViewMac::PaintUpdatesNow() {
+ NSIndexSet* set = [NSIndexSet indexSetWithIndex:model_->selected_line()];
+ NSTableView* table = [popup_ contentView];
+ [table selectRowIndexes:set byExtendingSelection:NO];
+}
+
+void AutocompletePopupViewMac::StopAutocomplete() {
+ model_->StopAutocomplete();
+}
+
+size_t AutocompletePopupViewMac::ResultRowCount() {
+ return model_->result().size();
+}
+
+const std::wstring& AutocompletePopupViewMac::ResultContentsAt(size_t i) {
+ return model_->result().match_at(i).contents;
+}
+
+bool AutocompletePopupViewMac::ResultStarredAt(size_t i) {
+ return model_->result().match_at(i).starred;
+}
+
+const std::wstring& AutocompletePopupViewMac::ResultDescriptionAt(size_t i) {
+ return model_->result().match_at(i).description;
+}
+
+void AutocompletePopupViewMac::AcceptInput(
+ WindowOpenDisposition disposition, bool for_drop) {
+ edit_view_->AcceptInput(disposition, for_drop);
+}
+
+@implementation AutocompleteTableTarget
+
+- initWithPopupView:(AutocompletePopupViewMac*)view {
+ self = [super init];
+ if (self) {
+ popup_view_ = view;
+ }
+ return self;
+}
+
+- (NSImage*)starImage {
+ return [NSImage imageNamed:@"starred.pdf"];
+}
+
+- (NSInteger)numberOfRowsInTableView:(NSTableView*)aTableView {
+ DCHECK(popup_view_);
+ return static_cast<NSInteger>(popup_view_->ResultRowCount());
+}
+
+- (id)tableView:(NSTableView*)aTableView
+objectValueForTableColumn:(NSTableColumn*)aTableColumn
+ row:(int)ri {
+ int columnIndex = [[aTableColumn identifier] integerValue];
+ size_t rowIndex = static_cast<size_t>(ri);
+ DCHECK(popup_view_);
+ DCHECK_LT(rowIndex, popup_view_->ResultRowCount());
+ DCHECK_LT(columnIndex, 3);
+
+ if (columnIndex == 1) {
+ if (popup_view_->ResultStarredAt(rowIndex)) {
+ return [self starImage];
+ }
+ return nil;
+ }
+
+ NSString* s;
+ if (columnIndex == 0) {
+ s = base::SysWideToNSString(popup_view_->ResultContentsAt(rowIndex));
+ } else {
+ s = base::SysWideToNSString(popup_view_->ResultDescriptionAt(rowIndex));
+ }
+
+ NSMutableParagraphStyle* style =
+ [[[NSMutableParagraphStyle alloc] init] autorelease];
+ [style setLineBreakMode:NSLineBreakByTruncatingTail];
+
+ NSMutableAttributedString* as =
+ [[[NSMutableAttributedString alloc] initWithString:s] autorelease];
+ [as addAttribute:NSParagraphStyleAttributeName value:style
+ range:NSMakeRange(0, [s length])];
+
+ // TODO(shess): There is a ton more styling to be done, here, for
+ // instance URLs different from search suggestions different from secure
+ // URLs, etc. [See AutocompletePopupViewMac::UpdateAndStyleText().]
+ // Deferring in the interests of getting a minimal implementation in.
+
+ return as;
+}
+
+- (void)select:sender {
+ DCHECK(popup_view_);
+ popup_view_->AcceptInput(CURRENT_TAB, false);
+}
+
+@end
diff --git a/chrome/browser/cocoa/location_bar_view_mac.h b/chrome/browser/cocoa/location_bar_view_mac.h
new file mode 100644
index 0000000..f39ff25
--- /dev/null
+++ b/chrome/browser/cocoa/location_bar_view_mac.h
@@ -0,0 +1,71 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import <Cocoa/Cocoa.h>
+
+#include "base/scoped_ptr.h"
+#include "chrome/browser/autocomplete/autocomplete_edit.h"
+#include "chrome/browser/location_bar.h"
+
+class AutocompleteEditViewMac;
+class CommandUpdater;
+class ToolbarModel;
+
+// A C++ bridge class that represents the location bar UI element to
+// the portable code. Wires up an AutocompleteEditViewMac instance to
+// the location bar text field, which handles most of the work.
+
+class LocationBarViewMac : public AutocompleteEditController,
+ public LocationBar {
+ public:
+ LocationBarViewMac(CommandUpdater* command_updater,
+ ToolbarModel* toolbar_model);
+ virtual ~LocationBarViewMac();
+
+ void Init();
+
+ void SetField(NSTextField* field);
+
+ virtual void ShowFirstRunBubble() { NOTIMPLEMENTED(); }
+ virtual std::wstring GetInputString() const;
+ virtual WindowOpenDisposition GetWindowOpenDisposition() const;
+ virtual PageTransition::Type GetPageTransition() const;
+ virtual void AcceptInput() { NOTIMPLEMENTED(); }
+ virtual void AcceptInputWithDisposition(WindowOpenDisposition disposition)
+ { NOTIMPLEMENTED(); }
+ virtual void FocusLocation();
+ virtual void FocusSearch() { NOTIMPLEMENTED(); }
+ virtual void UpdateFeedIcon() { /* http://crbug.com/8832 */ }
+ virtual void SaveStateToContents(TabContents* contents);
+
+ virtual void OnAutocompleteAccept(const GURL& url,
+ WindowOpenDisposition disposition,
+ PageTransition::Type transition,
+ const GURL& alternate_nav_url);
+ virtual void OnChanged();
+ virtual void OnInputInProgress(bool in_progress);
+ virtual SkBitmap GetFavIcon() const;
+ virtual std::wstring GetTitle() const;
+
+ private:
+ scoped_ptr<AutocompleteEditViewMac> edit_view_;
+
+ // TODO(shess): Determine ownership of these. We definitely
+ // shouldn't.
+ CommandUpdater* command_updater_; // weak
+ ToolbarModel* toolbar_model_; // weak
+
+ // When we get an OnAutocompleteAccept notification from the autocomplete
+ // edit, we save the input string so we can give it back to the browser on
+ // the LocationBar interface via GetInputString().
+ std::wstring location_input_;
+
+ // The user's desired disposition for how their input should be opened
+ WindowOpenDisposition disposition_;
+
+ // The transition type to use for the navigation
+ PageTransition::Type transition_;
+
+ DISALLOW_COPY_AND_ASSIGN(LocationBarViewMac);
+};
diff --git a/chrome/browser/cocoa/location_bar_view_mac.mm b/chrome/browser/cocoa/location_bar_view_mac.mm
new file mode 100644
index 0000000..a70fd9c
--- /dev/null
+++ b/chrome/browser/cocoa/location_bar_view_mac.mm
@@ -0,0 +1,120 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "chrome/browser/cocoa/location_bar_view_mac.h"
+
+#include "base/string_util.h"
+#include "chrome/app/chrome_dll_resource.h"
+#include "chrome/browser/alternate_nav_url_fetcher.h"
+#import "chrome/browser/app_controller_mac.h"
+#import "chrome/browser/autocomplete/autocomplete_edit_view_mac.h"
+#include "chrome/browser/command_updater.h"
+#include "skia/include/SkBitmap.h"
+
+// TODO(shess): This code is mostly copied from the gtk
+// implementation. Make sure it's all appropriate and flesh it out.
+
+LocationBarViewMac::LocationBarViewMac(CommandUpdater* command_updater,
+ ToolbarModel* toolbar_model)
+ : command_updater_(command_updater),
+ toolbar_model_(toolbar_model),
+ disposition_(CURRENT_TAB),
+ transition_(PageTransition::TYPED) {
+}
+LocationBarViewMac::~LocationBarViewMac() { }
+
+void LocationBarViewMac::Init() {
+ // TODO(shess): deanm indicates that it's likely we will eventually
+ // get the profile somewhere between point of construction and
+ // Init(), so mirroring how the gtk code sets this up.
+ Profile* profile = [[NSApp delegate] defaultProfile];
+ edit_view_.reset(new AutocompleteEditViewMac(this,
+ toolbar_model_,
+ profile,
+ command_updater_));
+}
+
+// TODO(shess): Find a way to get this passed to the constructor.
+void LocationBarViewMac::SetField(NSTextField* field) {
+ edit_view_->SetField(field);
+}
+
+std::wstring LocationBarViewMac::GetInputString() const {
+ return location_input_;
+}
+
+WindowOpenDisposition LocationBarViewMac::GetWindowOpenDisposition() const {
+ return disposition_;
+}
+
+// TODO(shess): Verify that this TODO is TODONE.
+// TODO(rohitrao): Fix this to return different types once autocomplete and
+// the onmibar are implemented. For now, any URL that comes from the
+// LocationBar has to have been entered by the user, and thus is of type
+// PageTransition::TYPED.
+PageTransition::Type LocationBarViewMac::GetPageTransition() const {
+ return transition_;
+}
+
+void LocationBarViewMac::FocusLocation() {
+ edit_view_->FocusLocation();
+}
+
+void LocationBarViewMac::SaveStateToContents(TabContents* contents) {
+ // TODO(shess): Why SaveStateToContents vs SaveStateToTab?
+ edit_view_->SaveStateToTab(contents);
+}
+
+void LocationBarViewMac::OnAutocompleteAccept(const GURL& url,
+ WindowOpenDisposition disposition,
+ PageTransition::Type transition,
+ const GURL& alternate_nav_url) {
+ if (!url.is_valid())
+ return;
+
+ location_input_ = UTF8ToWide(url.spec());
+ disposition_ = disposition;
+ transition_ = transition;
+
+ if (!command_updater_)
+ return;
+
+ if (!alternate_nav_url.is_valid()) {
+ command_updater_->ExecuteCommand(IDC_OPEN_CURRENT_URL);
+ return;
+ }
+
+ scoped_ptr<AlternateNavURLFetcher> fetcher(
+ new AlternateNavURLFetcher(alternate_nav_url));
+ // The AlternateNavURLFetcher will listen for the pending navigation
+ // notification that will be issued as a result of the "open URL." It
+ // will automatically install itself into that navigation controller.
+ command_updater_->ExecuteCommand(IDC_OPEN_CURRENT_URL);
+ if (fetcher->state() == AlternateNavURLFetcher::NOT_STARTED) {
+ // I'm not sure this should be reachable, but I'm not also sure enough
+ // that it shouldn't to stick in a NOTREACHED(). In any case, this is
+ // harmless; we can simply let the fetcher get deleted here and it will
+ // clean itself up properly.
+ } else {
+ fetcher.release(); // The navigation controller will delete the fetcher.
+ }
+}
+
+void LocationBarViewMac::OnChanged() {
+ NOTIMPLEMENTED();
+}
+
+void LocationBarViewMac::OnInputInProgress(bool in_progress) {
+ NOTIMPLEMENTED();
+}
+
+SkBitmap LocationBarViewMac::GetFavIcon() const {
+ NOTIMPLEMENTED();
+ return SkBitmap();
+}
+
+std::wstring LocationBarViewMac::GetTitle() const {
+ NOTIMPLEMENTED();
+ return std::wstring();
+}
diff --git a/chrome/browser/cocoa/tab_contents_controller.h b/chrome/browser/cocoa/tab_contents_controller.h
index 3a39b5d..2960588 100644
--- a/chrome/browser/cocoa/tab_contents_controller.h
+++ b/chrome/browser/cocoa/tab_contents_controller.h
@@ -14,6 +14,7 @@
class BookmarkModel;
class CommandUpdater;
class LocationBar;
+class LocationBarViewMac;
class TabContents;
class TabContentsCommandObserver;
class TabStripModel;
@@ -37,7 +38,7 @@ class ToolbarModel;
@private
CommandUpdater* commands_; // weak, may be nil
TabContentsCommandObserver* observer_; // nil if |commands_| is nil
- LocationBar* locationBarBridge_;
+ LocationBarViewMac* locationBarView_;
TabContents* contents_; // weak
ToolbarModel* toolbarModel_; // weak, one per window
@@ -103,6 +104,8 @@ class ToolbarModel;
// state.
- (void)setIsLoading:(BOOL)isLoading;
+- (void)defocusLocationBar;
+
// Make the location bar the first responder, if possible.
- (void)focusLocationBar;
diff --git a/chrome/browser/cocoa/tab_contents_controller.mm b/chrome/browser/cocoa/tab_contents_controller.mm
index a6c1732..a621b0f 100644
--- a/chrome/browser/cocoa/tab_contents_controller.mm
+++ b/chrome/browser/cocoa/tab_contents_controller.mm
@@ -2,19 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "chrome/browser/cocoa/tab_contents_controller.h"
+#import "chrome/browser/cocoa/tab_contents_controller.h"
-#import "base/sys_string_conversions.h"
-#import "chrome/app/chrome_dll_resource.h"
-#import "chrome/browser/bookmarks/bookmark_model.h"
-#import "chrome/browser/command_updater.h"
-#import "chrome/browser/location_bar.h"
-#import "chrome/browser/tab_contents/tab_contents.h"
-#import "chrome/browser/toolbar_model.h"
-#import "chrome/browser/net/url_fixer_upper.h"
-
-// For now, tab_contents lives here. TODO(port):fix
-#include "chrome/common/temp_scaffolding_stubs.h"
+#include "base/sys_string_conversions.h"
+#include "chrome/app/chrome_dll_resource.h"
+#include "chrome/browser/bookmarks/bookmark_model.h"
+#import "chrome/browser/cocoa/location_bar_view_mac.h"
+#include "chrome/browser/command_updater.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/toolbar_model.h"
// Names of images in the bundle for the star icon (normal and 'starred').
static NSString* const kStarImageName = @"star";
@@ -24,11 +20,6 @@ static NSString* const kStarredImageName = @"starred";
- (void)enabledStateChangedForCommand:(NSInteger)command enabled:(BOOL)enabled;
@end
-@interface TabContentsController(LocationBar)
-- (NSString*)locationBarString;
-- (void)focusLocationBar;
-@end
-
@interface TabContentsController(Private)
- (void)updateToolbarCommandStatus;
- (void)applyContentsBoxOffset:(BOOL)apply;
@@ -50,36 +41,6 @@ class TabContentsCommandObserver : public CommandUpdater::CommandObserver {
CommandUpdater* commands_; // weak
};
-// A C++ bridge class that handles responding to requests from the
-// cross-platform code for information about the location bar. Just passes
-// everything back to the controller.
-class LocationBarBridge : public LocationBar {
- public:
- LocationBarBridge(TabContentsController* controller);
-
- // Overridden from LocationBar
- virtual void ShowFirstRunBubble() { NOTIMPLEMENTED(); }
- virtual std::wstring GetInputString() const;
- virtual WindowOpenDisposition GetWindowOpenDisposition() const
- { NOTIMPLEMENTED(); return CURRENT_TAB; }
- // TODO(rohitrao): Fix this to return different types once autocomplete and
- // the onmibar are implemented. For now, any URL that comes from the
- // LocationBar has to have been entered by the user, and thus is of type
- // PageTransition::TYPED.
- virtual PageTransition::Type GetPageTransition() const
- { NOTIMPLEMENTED(); return PageTransition::TYPED; }
- virtual void AcceptInput() { NOTIMPLEMENTED(); }
- virtual void AcceptInputWithDisposition(WindowOpenDisposition disposition)
- { NOTIMPLEMENTED(); }
- virtual void FocusLocation();
- virtual void FocusSearch() { NOTIMPLEMENTED(); }
- virtual void UpdateFeedIcon() { /* http://crbug.com/8832 */ }
- virtual void SaveStateToContents(TabContents* contents) { NOTIMPLEMENTED(); }
-
- private:
- TabContentsController* controller_; // weak, owns me
-};
-
@implementation TabContentsController
- (id)initWithNibName:(NSString*)name
@@ -92,7 +53,7 @@ class LocationBarBridge : public LocationBar {
commands_ = commands;
if (commands_)
observer_ = new TabContentsCommandObserver(self, commands);
- locationBarBridge_ = new LocationBarBridge(self);
+ locationBarView_ = new LocationBarViewMac(commands, toolbarModel);
contents_ = contents;
toolbarModel_ = toolbarModel;
bookmarkModel_ = bookmarkModel;
@@ -104,7 +65,7 @@ class LocationBarBridge : public LocationBar {
// make sure our contents have been removed from the window
[[self view] removeFromSuperview];
delete observer_;
- delete locationBarBridge_;
+ delete locationBarView_;
[super dealloc];
}
@@ -116,11 +77,18 @@ class LocationBarBridge : public LocationBar {
// doesn't change between tabs.
[self updateToolbarCommandStatus];
+ // TODO(shess): This code doesn't have locationBar_ when
+ // locationBarView_ is constructed, so we need the SetField() helper to
+ // pass in the object here. Consider refactoring to obsolete that
+ // helper, perhaps by not constructing locationBarView_ until we have
+ // locationBar_.
+ locationBarView_->Init();
+ locationBarView_->SetField(locationBar_);
[locationBar_ setStringValue:@"http://dev.chromium.org"];
}
- (LocationBar*)locationBar {
- return locationBarBridge_;
+ return locationBarView_;
}
// Returns YES if the tab represented by this controller is the front-most.
@@ -188,12 +156,12 @@ class LocationBarBridge : public LocationBar {
[contentsBox_ setContentView:contents_->GetNativeView()];
}
-- (NSString*)locationBarString {
- return [locationBar_ stringValue];
+- (void)defocusLocationBar {
+ locationBarView_->SaveStateToContents(NULL);
}
- (void)focusLocationBar {
- [[locationBar_ window] makeFirstResponder:locationBar_];
+ locationBarView_->FocusLocation();
}
- (void)updateToolbarWithContents:(TabContents*)tab {
@@ -202,6 +170,9 @@ class LocationBarBridge : public LocationBar {
// TODO(pinkerton): update the security lock icon and background color
+ // TODO(shess): Determine whether this should happen via
+ // locationBarView_, instead, in which case this class can
+ // potentially lose the locationBar_ reference.
NSString* urlString = base::SysWideToNSString(toolbarModel_->GetText());
[locationBar_ setStringValue:urlString];
}
@@ -312,22 +283,3 @@ void TabContentsCommandObserver::EnabledStateChangedForCommand(int command,
[controller_ enabledStateChangedForCommand:command
enabled:enabled ? YES : NO];
}
-
-//--------------------------------------------------------------------------
-
-LocationBarBridge::LocationBarBridge(TabContentsController* controller)
- : controller_(controller) {
-}
-
-std::wstring LocationBarBridge::GetInputString() const {
- // TODO(shess): This code is temporary until the omnibox code takes
- // over.
- std::wstring url = base::SysNSStringToWide([controller_ locationBarString]);
-
- // Try to flesh out the input to make a real URL.
- return URLFixerUpper::FixupURL(url, std::wstring());
-}
-
-void LocationBarBridge::FocusLocation() {
- [controller_ focusLocationBar];
-}
diff --git a/chrome/browser/cocoa/tab_strip_controller.mm b/chrome/browser/cocoa/tab_strip_controller.mm
index 46a98df..28678d7 100644
--- a/chrome/browser/cocoa/tab_strip_controller.mm
+++ b/chrome/browser/cocoa/tab_strip_controller.mm
@@ -295,6 +295,14 @@ class TabStripBridge : public TabStripModelObserver {
previousContents:(TabContents*)oldContents
atIndex:(NSInteger)index
userGesture:(bool)wasUserGesture {
+ int selectedIndex = 0;
+ for (TabController* current in tabArray_) {
+ if ([current selected]) {
+ break;
+ }
+ ++selectedIndex;
+ }
+
// De-select all other tabs and select the new tab.
int i = 0;
for (TabController* current in tabArray_) {
@@ -306,6 +314,13 @@ class TabStripBridge : public TabStripModelObserver {
NSView* selectedTab = [self viewAtIndex:index];
[tabView_ addSubview:selectedTab positioned:NSWindowAbove relativeTo:nil];
+ // Tell the current tab to lose focus.
+ if (selectedIndex < (int)[tabArray_ count]) {
+ TabContentsController* selectedController =
+ [tabContentsArray_ objectAtIndex:selectedIndex];
+ [selectedController defocusLocationBar];
+ }
+
// Tell the new tab contents it is about to become the selected tab. Here it
// can do things like make sure the toolbar is up to date.
TabContentsController* newController =
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp
index 939b49c..487d984 100644
--- a/chrome/chrome.gyp
+++ b/chrome/chrome.gyp
@@ -387,6 +387,8 @@
'browser/autocomplete/autocomplete_edit_view.h',
'browser/autocomplete/autocomplete_edit_view_gtk.cc',
'browser/autocomplete/autocomplete_edit_view_gtk.h',
+ 'browser/autocomplete/autocomplete_edit_view_mac.h',
+ 'browser/autocomplete/autocomplete_edit_view_mac.mm',
'browser/autocomplete/autocomplete_edit_view_win.cc',
'browser/autocomplete/autocomplete_edit_view_win.h',
'browser/autocomplete/autocomplete_popup_model.cc',
@@ -394,6 +396,8 @@
'browser/autocomplete/autocomplete_popup_view.h',
'browser/autocomplete/autocomplete_popup_view_gtk.cc',
'browser/autocomplete/autocomplete_popup_view_gtk.h',
+ 'browser/autocomplete/autocomplete_popup_view_mac.h',
+ 'browser/autocomplete/autocomplete_popup_view_mac.mm',
'browser/autocomplete/autocomplete_popup_view_win.cc',
'browser/autocomplete/autocomplete_popup_view_win.h',
'browser/autocomplete/history_contents_provider.cc',
@@ -516,6 +520,8 @@
'browser/cocoa/browser_window_controller.mm',
'browser/cocoa/grow_box_view.h',
'browser/cocoa/grow_box_view.m',
+ 'browser/cocoa/location_bar_view_mac.h',
+ 'browser/cocoa/location_bar_view_mac.mm',
'browser/cocoa/sad_tab_view.h',
'browser/cocoa/sad_tab_view.mm',
'browser/cocoa/shell_dialogs_mac.mm',
@@ -1265,9 +1271,6 @@
['include', '^browser/download/save_(file(_manager)?|item|package)\\.cc$'],
],
'sources!': [
- 'browser/autocomplete/autocomplete_edit.cc',
- 'browser/autocomplete/autocomplete_popup_model.cc',
- 'browser/automation/automation_provider_list_generic.cc',
'browser/bookmarks/bookmark_context_menu.cc',
'browser/bookmarks/bookmark_drop_info.cc',
'browser/debugger/debugger_shell_stubs.cc',