summaryrefslogtreecommitdiffstats
path: root/chrome/browser/autocomplete
diff options
context:
space:
mode:
authorshess@chromium.org <shess@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-05-11 21:47:01 +0000
committershess@chromium.org <shess@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-05-11 21:47:01 +0000
commit394aa59248445297e01bf09acc40c2ff0fb34999 (patch)
treee9549ea2649db32eba6ddb39e277ddbd3e34b492 /chrome/browser/autocomplete
parent2afc8336851ae77cfc681c8823d1c478364a4cd3 (diff)
downloadchromium_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.h10
-rw-r--r--chrome/browser/autocomplete/autocomplete_edit_view_mac.mm131
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