diff options
author | shess@chromium.org <shess@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-05-11 21:47:01 +0000 |
---|---|---|
committer | shess@chromium.org <shess@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-05-11 21:47:01 +0000 |
commit | 394aa59248445297e01bf09acc40c2ff0fb34999 (patch) | |
tree | e9549ea2649db32eba6ddb39e277ddbd3e34b492 /chrome/browser/autocomplete | |
parent | 2afc8336851ae77cfc681c8823d1c478364a4cd3 (diff) | |
download | chromium_src-394aa59248445297e01bf09acc40c2ff0fb34999.zip chromium_src-394aa59248445297e01bf09acc40c2ff0fb34999.tar.gz chromium_src-394aa59248445297e01bf09acc40c2ff0fb34999.tar.bz2 |
Use Chrome facilities for omnibox state save and restore on Mac.
TabContents has a facility for storing a bag of stuff across
current-tab changes. Wire up AutocompleteEditViewMac to use that
facility. Unfork some code in Browser::TabSelectedAt() so that the
new code gets used, and straighten up the Mac code along the code path
between there and AutocompleteEditViewMac.
This overall change also exposed a couple bugs/mis-features in the
AutocompleteEditViewMac code.
TEST=Text field maintains contents and selection across tab changes, even when edited.
Review URL: http://codereview.chromium.org/114017
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@15790 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/autocomplete')
-rw-r--r-- | chrome/browser/autocomplete/autocomplete_edit_view_mac.h | 10 | ||||
-rw-r--r-- | chrome/browser/autocomplete/autocomplete_edit_view_mac.mm | 131 |
2 files changed, 120 insertions, 21 deletions
diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_mac.h b/chrome/browser/autocomplete/autocomplete_edit_view_mac.h index 521f590..a693841 100644 --- a/chrome/browser/autocomplete/autocomplete_edit_view_mac.h +++ b/chrome/browser/autocomplete/autocomplete_edit_view_mac.h @@ -43,9 +43,7 @@ class AutocompleteEditViewMac : public AutocompleteEditView { 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 Update(const TabContents* tab_for_state_restoring); virtual void OpenURL(const GURL& url, WindowOpenDisposition disposition, @@ -55,10 +53,12 @@ class AutocompleteEditViewMac : public AutocompleteEditView { const std::wstring& keyword); virtual std::wstring GetText() const; - virtual void SetUserText(const std::wstring& text) { NOTIMPLEMENTED(); } + virtual void SetUserText(const std::wstring& text) { + SetUserText(text, text, true); + } virtual void SetUserText(const std::wstring& text, const std::wstring& display_text, - bool update_popup) { NOTIMPLEMENTED(); } + bool update_popup); virtual void SetWindowTextAndCaretPos(const std::wstring& text, size_t caret_pos); diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_mac.mm b/chrome/browser/autocomplete/autocomplete_edit_view_mac.mm index c9ca5fc..e1a2a53 100644 --- a/chrome/browser/autocomplete/autocomplete_edit_view_mac.mm +++ b/chrome/browser/autocomplete/autocomplete_edit_view_mac.mm @@ -8,6 +8,41 @@ #include "chrome/browser/autocomplete/autocomplete_edit.h" #include "chrome/browser/autocomplete/autocomplete_popup_model.h" #include "chrome/browser/autocomplete/autocomplete_popup_view_mac.h" +#include "chrome/browser/tab_contents/tab_contents.h" + +namespace { + +// Store's the model and view state across tab switches. +struct AutocompleteEditViewMacState { + AutocompleteEditViewMacState(const AutocompleteEditModel::State model_state, + const bool has_focus, const NSRange& selection) + : model_state(model_state), + has_focus(has_focus), + selection(selection) { + } + + const AutocompleteEditModel::State model_state; + const bool has_focus; + const NSRange selection; +}; + +// Returns a lazily initialized property bag accessor for saving our +// state in a TabContents. +PropertyAccessor<AutocompleteEditViewMacState>* GetStateAccessor() { + static PropertyAccessor<AutocompleteEditViewMacState> state; + return &state; +} + +// Accessors for storing and getting the state from the tab. +void StoreStateToTab(TabContents* tab, + const AutocompleteEditViewMacState& state) { + GetStateAccessor()->SetProperty(tab->property_bag(), state); +} +const AutocompleteEditViewMacState* GetStateFromTab(const TabContents* tab) { + return GetStateAccessor()->GetProperty(tab->property_bag()); +} + +} // namespace // Thin Obj-C bridge class that is the delegate of the omnibox field. // It intercepts various control delegate methods and vectors them to @@ -57,19 +92,68 @@ AutocompleteEditViewMac::~AutocompleteEditViewMac() { [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. + DCHECK(tab); + + NSRange range; + if (model_->has_focus()) { + range = GetSelectedRange(); + } else { + // If we are not focussed, there is no selection. Manufacture + // something reasonable in case it starts to matter in the future. + range = NSMakeRange(0, [[field_ stringValue] length]); + } - // Drop the popup before we change to another tab. - ClosePopup(); + AutocompleteEditViewMacState state(model_->GetStateForTabSwitch(), + model_->has_focus(), range); + StoreStateToTab(tab, state); +} + +void AutocompleteEditViewMac::Update( + const TabContents* tab_for_state_restoring) { + // TODO(shess): It seems like if the tab is non-NULL, then this code + // shouldn't need to be called at all. When coded that way, I find + // that the field isn't always updated correctly. Figure out why + // this is. Maybe this method should be refactored into more + // specific cases. + const std::wstring text = toolbar_model_->GetText(); + const bool user_visible = model_->UpdatePermanentText(text); + + if (tab_for_state_restoring) { + RevertAll(); + + const AutocompleteEditViewMacState* state = + GetStateFromTab(tab_for_state_restoring); + if (state) { + // Should restore the user's text via SetUserText(). + model_->RestoreState(state->model_state); + + // Restore user's selection. + // TODO(shess): The model_ does not restore the focus state. If + // field_ was in focus when we switched away, I presume it + // should be in focus when we switch back. Figure out if model_ + // not restoring focus is an oversight, or intentional for some + // subtle reason. + if (state->has_focus) { + FocusLocation(); + DCHECK([field_ currentEditor]); + [[field_ currentEditor] setSelectedRange:state->selection]; + } + } + } else if (user_visible) { + // Restore everything to the baseline look. + RevertAll(); + // TODO(shess): Figure out how this case is used, to make sure + // we're getting the selection and popup right. + + } else { + // TODO(shess): Figure out how this case is used, to make sure + // we're getting the selection and popup right. + // UpdateAndStyleText() approximates the inner part of Revertall() + // which under GTK is called EmphasizeURLComponents(), and is + // expected to change when I start feeding in the styling code. + UpdateAndStyleText(text, 0); + } } void AutocompleteEditViewMac::OpenURL(const GURL& url, @@ -97,6 +181,16 @@ std::wstring AutocompleteEditViewMac::GetText() const { return base::SysNSStringToWide([field_ stringValue]); } +void AutocompleteEditViewMac::SetUserText(const std::wstring& text, + const std::wstring& display_text, + bool update_popup) { + model_->SetUserText(text); + UpdateAndStyleText(display_text, display_text.size()); + if (update_popup) { + UpdatePopup(); + } +} + NSRange AutocompleteEditViewMac::GetSelectedRange() const { DCHECK([field_ currentEditor]); return [[field_ currentEditor] selectedRange]; @@ -119,7 +213,7 @@ void AutocompleteEditViewMac::RevertAll() { model_->Revert(); std::wstring tt = GetText(); - UpdateAndStyleText(tt, tt.size()); + UpdateAndStyleText(tt, 0); controller_->OnChanged(); } @@ -156,7 +250,7 @@ void AutocompleteEditViewMac::UpdateAndStyleText( [as addAttribute:NSForegroundColorAttributeName value:[NSColor greenColor] range:NSMakeRange((NSInteger)parts.host.begin, - (NSInteger)parts.host.end())]; + (NSInteger)parts.host.len)]; } // TODO(shess): GTK has this as a member var, figure out why. @@ -175,7 +269,7 @@ void AutocompleteEditViewMac::UpdateAndStyleText( } [as addAttribute:NSForegroundColorAttributeName value:color range:NSMakeRange((NSInteger)parts.scheme.begin, - (NSInteger)parts.scheme.end())]; + (NSInteger)parts.scheme.len)]; } // TODO(shess): Check that this updates the model's sense of focus @@ -183,7 +277,7 @@ void AutocompleteEditViewMac::UpdateAndStyleText( [field_ setObjectValue:as]; if (![field_ currentEditor]) { [field_ becomeFirstResponder]; - DCHECK_EQ(field_, [[field_ window] firstResponder]); + DCHECK_EQ([field_ currentEditor], [[field_ window] firstResponder]); } NSRange selected_range = NSMakeRange(user_text_length, [as length]); @@ -281,7 +375,12 @@ void AutocompleteEditViewMac::AcceptInput( } void AutocompleteEditViewMac::FocusLocation() { - [[field_ window] makeFirstResponder:field_]; + // -makeFirstResponder: will select the entire field_. If we're + // already firstResponder, it's likely that we want to retain the + // current selection. + if (![field_ currentEditor]) { + [[field_ window] makeFirstResponder:field_]; + } } @implementation AutocompleteFieldDelegate |