Index: chrome/browser/autocomplete/autocomplete_edit_view_mac.mm |
diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_mac.mm b/chrome/browser/autocomplete/autocomplete_edit_view_mac.mm |
index c9ca5fca1ffbec63bd88593eb117a9517b15826a..e1a2a53e0ad72fd57de753eb2fc785b11674b643 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; |
pink (ping after 24hrs)
2009/05/08 21:18:26
how does this work with multiple windows if there'
Scott Hess - ex-Googler
2009/05/08 22:50:21
Oh, I hope I don't hurt myself, here ... brief sum
pink (ping after 24hrs)
2009/05/11 13:50:11
I figured it was something like this. Maybe a comm
|
+ 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 |