Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5)

Side by Side Diff: chrome/browser/autocomplete/autocomplete_edit_view_mac.mm

Issue 50074: Initial implemention of Mac Omnibox. (Closed)
Patch Set: Disable LocationBarViewMacTest. Created 11 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/autocomplete/autocomplete_edit_view_mac.h"
6
7 #include "base/sys_string_conversions.h"
8 #include "chrome/browser/autocomplete/autocomplete_edit.h"
9 #include "chrome/browser/autocomplete/autocomplete_popup_view_mac.h"
10
11 // Thin Obj-C bridge class that is the delegate of the omnibox field.
12 // It intercepts various control delegate methods and vectors them to
13 // the edit view.
14
15 @interface AutocompleteFieldDelegate : NSObject {
16 @private
17 AutocompleteEditViewMac* edit_view_; // weak, owns us.
18 }
19 - initWithEditView:(AutocompleteEditViewMac*)view;
20 @end
21
22 AutocompleteEditViewMac::AutocompleteEditViewMac(
23 AutocompleteEditController* controller,
24 ToolbarModel* toolbar_model,
25 Profile* profile,
26 CommandUpdater* command_updater)
27 : model_(new AutocompleteEditModel(this, controller, profile)),
28 popup_view_(new AutocompletePopupViewMac(this, model_.get(), profile)),
29 controller_(controller),
30 toolbar_model_(toolbar_model),
31 command_updater_(command_updater),
32 field_(nil),
33 edit_helper_([[AutocompleteFieldDelegate alloc] initWithEditView:this]) {
34 DCHECK(controller);
35 DCHECK(toolbar_model);
36 DCHECK(profile);
37 DCHECK(command_updater);
38 }
39
40 AutocompleteEditViewMac::~AutocompleteEditViewMac() {
41 // TODO(shess): Having to be aware of destructor ordering in this
42 // way seems brittle. There must be a better way.
43
44 // Destroy popup view before this object in case it tries to call us
45 // back in the destructor. Likewise for destroying the model before
46 // this object.
47 popup_view_.reset();
48 model_.reset();
49
50 // Disconnect field_ from edit_helper_ so that we don't get calls
51 // after destruction.
52 [field_ setDelegate:nil];
53 }
54
55 // TODO(shess): This is the minimal change which seems to unblock
56 // getting the minimal Omnibox code checked in without making the
57 // world worse. Browser::TabSelectedAt() calls this when the tab
58 // changes, but that is only wired up for Windows. I do not yet
59 // understand that code well enough to go for it. Once wired up, then
60 // code can be removed at:
61 // [TabContentsController defocusLocationBar]
62 // [TabStripController selectTabWithContents:...]
63 void AutocompleteEditViewMac::SaveStateToTab(TabContents* tab) {
64 // TODO(shess): Actually save the state to the tab area.
65
66 // Drop the popup before we change to another tab.
67 ClosePopup();
68 }
69
70 void AutocompleteEditViewMac::OpenURL(const GURL& url,
71 WindowOpenDisposition disposition,
72 PageTransition::Type transition,
73 const GURL& alternate_nav_url,
74 size_t selected_line,
75 const std::wstring& keyword) {
76 // TODO(shess): Why is the caller passing an invalid url in the
77 // first place? Make sure that case isn't being dropped on the
78 // floor.
79 if (!url.is_valid()) {
80 return;
81 }
82
83 model_->SendOpenNotification(selected_line, keyword);
84
85 if (disposition != NEW_BACKGROUND_TAB)
86 RevertAll(); // Revert the box to its unedited state.
87 controller_->OnAutocompleteAccept(url, disposition, transition,
88 alternate_nav_url);
89 }
90
91 std::wstring AutocompleteEditViewMac::GetText() const {
92 return base::SysNSStringToWide([field_ stringValue]);
93 }
94
95 void AutocompleteEditViewMac::SetWindowTextAndCaretPos(const std::wstring& text,
96 size_t caret_pos) {
97 UpdateAndStyleText(text, text.size());
98 }
99
100 void AutocompleteEditViewMac::SelectAll(bool reversed) {
101 // TODO(shess): Figure out what reversed implies. The gtk version
102 // has it imply inverting the selection front to back, but I don't
103 // even know if that makes sense for Mac.
104 UpdateAndStyleText(GetText(), 0);
105 }
106
107 void AutocompleteEditViewMac::RevertAll() {
108 ClosePopup();
109 model_->Revert();
110
111 std::wstring tt = GetText();
112 UpdateAndStyleText(tt, tt.size());
113 controller_->OnChanged();
114 }
115
116 void AutocompleteEditViewMac::UpdatePopup() {
117 model_->SetInputInProgress(true);
118 if (!model_->has_focus())
119 return;
120
121 // TODO(shess):
122 // Shouldn't inline autocomplete when the caret/selection isn't at
123 // the end of the text.
124 //
125 // One option would seem to be to check for a non-nil field
126 // editor, and check it's selected range against its length.
127 model_->StartAutocomplete(false);
128 }
129
130 void AutocompleteEditViewMac::ClosePopup() {
131 popup_view_->StopAutocomplete();
132 }
133
134 void AutocompleteEditViewMac::UpdateAndStyleText(
135 const std::wstring& display_text, size_t user_text_length) {
136 NSString* ss = base::SysWideToNSString(display_text);
137 NSMutableAttributedString* as =
138 [[[NSMutableAttributedString alloc] initWithString:ss] autorelease];
139
140 url_parse::Parsed parts;
141 AutocompleteInput::Parse(display_text, model_->GetDesiredTLD(),
142 &parts, NULL);
143 bool emphasize = model_->CurrentTextIsURL() && (parts.host.len > 0);
144 if (emphasize) {
145 // TODO(shess): Pull color out as a constant.
146 [as addAttribute:NSForegroundColorAttributeName
147 value:[NSColor greenColor]
148 range:NSMakeRange((NSInteger)parts.host.begin,
149 (NSInteger)parts.host.end())];
150 }
151
152 // TODO(shess): GTK has this as a member var, figure out why.
153 ToolbarModel::SecurityLevel scheme_security_level =
154 toolbar_model_->GetSchemeSecurityLevel();
155
156 // Emphasize the scheme for security UI display purposes (if necessary).
157 if (!model_->user_input_in_progress() && parts.scheme.is_nonempty() &&
158 (scheme_security_level != ToolbarModel::NORMAL)) {
159 // TODO(shess): Pull colors out as constants.
160 NSColor* color;
161 if (scheme_security_level == ToolbarModel::SECURE) {
162 color = [NSColor blueColor];
163 } else {
164 color = [NSColor blackColor];
165 }
166 [as addAttribute:NSForegroundColorAttributeName value:color
167 range:NSMakeRange((NSInteger)parts.scheme.begin,
168 (NSInteger)parts.scheme.end())];
169 }
170
171 // TODO(shess): Check that this updates the model's sense of focus
172 // correctly.
173 [field_ setObjectValue:as];
174 if (![field_ currentEditor]) {
175 [field_ becomeFirstResponder];
176 DCHECK_EQ(field_, [[field_ window] firstResponder]);
177 }
178
179 NSRange selected_range = NSMakeRange(user_text_length, [as length]);
180 // TODO(shess): What if it didn't get first responder, and there is
181 // no field editor? This will do nothing. Well, at least it won't
182 // crash. Think of something more productive to do, or prove that
183 // it cannot occur and DCHECK appropriately.
184 [[field_ currentEditor] setSelectedRange:selected_range];
185 }
186
187 void AutocompleteEditViewMac::OnTemporaryTextMaybeChanged(
188 const std::wstring& display_text, bool save_original_selection) {
189 // TODO(shess): I believe this is for when the user arrows around
190 // the popup, will be restored if they hit escape. Figure out if
191 // that is for certain it.
192 if (save_original_selection) {
193 saved_temporary_text_ = GetText();
194 }
195
196 UpdateAndStyleText(display_text, display_text.size());
197 }
198
199 bool AutocompleteEditViewMac::OnInlineAutocompleteTextMaybeChanged(
200 const std::wstring& display_text, size_t user_text_length) {
201 // TODO(shess): Make sure that this actually works. The round trip
202 // to native form and back may mean that it's the same but not the
203 // same.
204 if (display_text == GetText()) {
205 return false;
206 }
207
208 UpdateAndStyleText(display_text, user_text_length);
209 return true;
210 }
211
212 void AutocompleteEditViewMac::OnRevertTemporaryText() {
213 UpdateAndStyleText(saved_temporary_text_, saved_temporary_text_.size());
214 saved_temporary_text_.clear();
215 }
216
217 void AutocompleteEditViewMac::OnUpOrDownKeyPressed(int dir) {
218 model_->OnUpOrDownKeyPressed(dir);
219 }
220 void AutocompleteEditViewMac::OnEscapeKeyPressed() {
221 model_->OnEscapeKeyPressed();
222 }
223 void AutocompleteEditViewMac::OnSetFocus(bool f) {
224 model_->OnSetFocus(f);
225 }
226 void AutocompleteEditViewMac::OnKillFocus() {
227 model_->OnKillFocus();
228 }
229 void AutocompleteEditViewMac::AcceptInput(
230 WindowOpenDisposition disposition, bool for_drop) {
231 model_->AcceptInput(disposition, for_drop);
232 }
233 void AutocompleteEditViewMac::OnAfterPossibleChange(
234 const std::wstring& new_text,
235 bool selection_differs,
236 bool text_differs,
237 bool just_deleted_text,
238 bool at_end_of_edit) {
239 model_->OnAfterPossibleChange(new_text, selection_differs, text_differs,
240 just_deleted_text, at_end_of_edit);
241 }
242 void AutocompleteEditViewMac::SetField(NSTextField* field) {
243 field_ = field;
244 [field_ setDelegate:edit_helper_];
245
246 // The popup code needs the field for sizing and placement.
247 popup_view_->SetField(field_);
248 }
249
250 void AutocompleteEditViewMac::FocusLocation() {
251 [[field_ window] makeFirstResponder:field_];
252 }
253
254 @implementation AutocompleteFieldDelegate
255
256 - initWithEditView:(AutocompleteEditViewMac*)view {
257 self = [super init];
258 if (self) {
259 edit_view_ = view;
260 }
261 return self;
262 }
263
264 - (BOOL)control:(NSControl*)control
265 textView:(NSTextView*)textView doCommandBySelector:(SEL)cmd {
266 if (cmd == @selector(moveDown:)) {
267 edit_view_->OnUpOrDownKeyPressed(1);
268 return YES;
269 }
270
271 if (cmd == @selector(moveUp:)) {
272 edit_view_->OnUpOrDownKeyPressed(-1);
273 return YES;
274 }
275
276 if (cmd == @selector(cancelOperation:)) {
277 edit_view_->OnEscapeKeyPressed();
278 return YES;
279 }
280
281 if (cmd == @selector(insertNewline:)) {
282 edit_view_->AcceptInput(CURRENT_TAB, false);
283 return YES;
284 }
285
286 return NO;
287 }
288
289 - (void)controlTextDidBeginEditing:(NSNotification*)aNotification {
290 edit_view_->OnSetFocus(false);
291 }
292
293 - (void)controlTextDidChange:(NSNotification*)aNotification {
294 // TODO(shess): Make this more efficient? Or not. For now, just
295 // pass in the current text, indicating that the text and
296 // selection differ, ignoring deletions, and assuming that we're
297 // at the end of the text.
298 edit_view_->OnAfterPossibleChange(edit_view_->GetText(),
299 true, true, false, true);
300 }
301
302 - (void)controlTextDidEndEditing:(NSNotification*)aNotification {
303 edit_view_->OnKillFocus();
304
305 // TODO(shess): Figure out where the selection belongs. On GTK,
306 // it's set to the start of the text.
307 }
308
309 @end
OLDNEW
« no previous file with comments | « chrome/browser/autocomplete/autocomplete_edit_view_mac.h ('k') | chrome/browser/autocomplete/autocomplete_popup_view_mac.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698