OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2011 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_views.h" | |
6 | |
7 #include "app/l10n_util.h" | |
8 #include "base/logging.h" | |
9 #include "base/string_util.h" | |
10 #include "base/utf_string_conversions.h" | |
11 #include "chrome/app/chrome_command_ids.h" | |
12 #include "chrome/browser/autocomplete/autocomplete_edit.h" | |
13 #include "chrome/browser/autocomplete/autocomplete_match.h" | |
14 #include "chrome/browser/autocomplete/autocomplete_popup_model.h" | |
15 #include "chrome/browser/command_updater.h" | |
16 #include "chrome/browser/tab_contents/tab_contents.h" | |
17 #include "chrome/browser/ui/views/autocomplete/autocomplete_popup_contents_view. h" | |
18 #include "chrome/browser/ui/views/location_bar/location_bar_view.h" | |
19 #include "chrome/common/notification_service.h" | |
20 #include "gfx/font.h" | |
21 #include "googleurl/src/gurl.h" | |
22 #include "grit/generated_resources.h" | |
23 #include "net/base/escape.h" | |
24 #include "views/border.h" | |
25 #include "views/fill_layout.h" | |
26 | |
27 namespace { | |
28 | |
29 // Textfield for autocomplete that intercepts events that are necessary | |
30 // for AutocompleteEditViewViews. | |
31 class AutocompleteTextfield : public views::Textfield { | |
32 public: | |
33 explicit AutocompleteTextfield( | |
34 AutocompleteEditViewViews* autocomplete_edit_view) | |
35 : views::Textfield(views::Textfield::STYLE_DEFAULT), | |
36 autocomplete_edit_view_(autocomplete_edit_view) { | |
37 DCHECK(autocomplete_edit_view_); | |
38 RemoveBorder(); | |
39 } | |
40 | |
41 // views::View implementation | |
42 virtual void DidGainFocus() { | |
43 views::Textfield::DidGainFocus(); | |
44 autocomplete_edit_view_->HandleFocusIn(); | |
45 } | |
46 | |
47 virtual void WillLoseFocus() { | |
48 views::Textfield::WillLoseFocus(); | |
49 autocomplete_edit_view_->HandleFocusOut(); | |
50 } | |
51 | |
52 virtual bool OnKeyPressed(const views::KeyEvent& e) { | |
53 bool handled = views::Textfield::OnKeyPressed(e); | |
54 return autocomplete_edit_view_->HandleAfterKeyEvent(e, handled) || handled; | |
55 } | |
56 | |
57 virtual bool OnKeyReleased(const views::KeyEvent& e) { | |
58 return autocomplete_edit_view_->HandleKeyReleaseEvent(e); | |
59 } | |
60 | |
61 virtual bool IsFocusable() const { | |
62 // Bypass Textfield::IsFocusable. The omnibox in popup window requires | |
63 // focus in order for text selection to work. | |
64 return views::View::IsFocusable(); | |
65 } | |
66 | |
67 private: | |
68 AutocompleteEditViewViews* autocomplete_edit_view_; | |
69 | |
70 DISALLOW_COPY_AND_ASSIGN(AutocompleteTextfield); | |
71 }; | |
72 | |
73 // Stores omnibox state for each tab. | |
74 struct ViewState { | |
75 explicit ViewState(const views::TextRange& selection_range) | |
76 : selection_range(selection_range) { | |
77 } | |
78 | |
79 // Range of selected text. | |
80 views::TextRange selection_range; | |
81 }; | |
82 | |
83 struct AutocompleteEditState { | |
84 AutocompleteEditState(const AutocompleteEditModel::State& model_state, | |
85 const ViewState& view_state) | |
86 : model_state(model_state), | |
87 view_state(view_state) { | |
88 } | |
89 | |
90 const AutocompleteEditModel::State model_state; | |
91 const ViewState view_state; | |
92 }; | |
93 | |
94 // Returns a lazily initialized property bag accessor for saving our state in a | |
95 // TabContents. | |
96 PropertyAccessor<AutocompleteEditState>* GetStateAccessor() { | |
97 static PropertyAccessor<AutocompleteEditState> state; | |
98 return &state; | |
99 } | |
100 | |
101 const int kAutocompleteVerticalMargin = 4; | |
102 | |
103 } // namespace | |
104 | |
105 AutocompleteEditViewViews::AutocompleteEditViewViews( | |
106 AutocompleteEditController* controller, | |
107 ToolbarModel* toolbar_model, | |
108 Profile* profile, | |
109 CommandUpdater* command_updater, | |
110 bool popup_window_mode, | |
111 const views::View* location_bar) | |
112 : model_(new AutocompleteEditModel(this, controller, profile)), | |
113 popup_view_(new AutocompletePopupContentsView( | |
114 gfx::Font(), this, model_.get(), profile, location_bar)), | |
115 controller_(controller), | |
116 toolbar_model_(toolbar_model), | |
117 command_updater_(command_updater), | |
118 popup_window_mode_(popup_window_mode), | |
119 security_level_(ToolbarModel::NONE), | |
120 delete_was_pressed_(false), | |
121 delete_at_end_pressed_(false) { | |
122 model_->SetPopupModel(popup_view_->GetModel()); | |
123 set_border(views::Border::CreateEmptyBorder(kAutocompleteVerticalMargin, | |
Peter Kasting
2011/01/20 19:44:37
Nit: Just put the zeros on the ends of the other t
oshima
2011/01/20 21:35:48
Done.
| |
124 0, | |
125 kAutocompleteVerticalMargin, | |
126 0)); | |
127 } | |
128 | |
129 AutocompleteEditViewViews::~AutocompleteEditViewViews() { | |
130 NotificationService::current()->Notify( | |
131 NotificationType::AUTOCOMPLETE_EDIT_DESTROYED, | |
132 Source<AutocompleteEditViewViews>(this), | |
133 NotificationService::NoDetails()); | |
134 // Explicitly teardown members which have a reference to us. Just to be safe | |
135 // we want them to be destroyed before destroying any other internal state. | |
136 popup_view_.reset(); | |
137 model_.reset(); | |
138 } | |
139 | |
140 //////////////////////////////////////////////////////////////////////////////// | |
141 // AutocompleteEditViewViews public: | |
142 | |
143 void AutocompleteEditViewViews::Init() { | |
144 // The height of the text view is going to change based on the font used. We | |
145 // don't want to stretch the height, and we want it vertically centered. | |
146 // TODO(oshima): make sure the above happens with views. | |
147 textfield_ = new AutocompleteTextfield(this); | |
148 textfield_->SetController(this); | |
149 | |
150 if (popup_window_mode_) | |
151 textfield_->SetReadOnly(true); | |
152 | |
153 // Manually invoke SetBaseColor() because TOOLKIT_VIEWS doesn't observe | |
154 // themes. | |
155 SetBaseColor(); | |
156 } | |
157 | |
158 void AutocompleteEditViewViews::SetBaseColor() { | |
159 // TODO(oshima): Implment style change. | |
160 NOTIMPLEMENTED(); | |
161 } | |
162 | |
163 bool AutocompleteEditViewViews::HandleAfterKeyEvent( | |
164 const views::KeyEvent& event, | |
165 bool handled) { | |
166 handling_key_press_ = false; | |
167 if (content_maybe_changed_by_key_press_) | |
168 OnAfterPossibleChange(); | |
169 | |
170 if (event.GetKeyCode() == ui::VKEY_RETURN) { | |
171 bool alt_held = event.IsAltDown(); | |
172 model_->AcceptInput(alt_held ? NEW_FOREGROUND_TAB : CURRENT_TAB, false); | |
173 handled = true; | |
174 } else if (!handled && event.GetKeyCode() == ui::VKEY_ESCAPE) { | |
175 // We can handle the Escape key if textfield did not handle it. | |
176 // If it's not handled by us, then we need to propagate it up to the parent | |
177 // widgets, so that Escape accelerator can still work. | |
178 handled = model_->OnEscapeKeyPressed(); | |
179 } else if (event.GetKeyCode() == ui::VKEY_CONTROL) { | |
180 // Omnibox2 can switch its contents while pressing a control key. To switch | |
181 // the contents of omnibox2, we notify the AutocompleteEditModel class when | |
182 // the control-key state is changed. | |
183 model_->OnControlKeyChanged(true); | |
184 } else if (!text_changed_ && event.GetKeyCode() == ui::VKEY_DELETE && | |
185 event.IsShiftDown()) { | |
186 // If shift+del didn't change the text, we let this delete an entry from | |
187 // the popup. We can't check to see if the IME handled it because even if | |
188 // nothing is selected, the IME or the TextView still report handling it. | |
189 AutocompletePopupModel* popup_model = popup_view_->GetModel(); | |
190 if (popup_model->IsOpen()) | |
191 popup_model->TryDeletingCurrentItem(); | |
192 } else if (!handled && event.GetKeyCode() == ui::VKEY_UP) { | |
193 model_->OnUpOrDownKeyPressed(-1); | |
194 handled = true; | |
195 } else if (!handled && event.GetKeyCode() == ui::VKEY_DOWN) { | |
196 model_->OnUpOrDownKeyPressed(1); | |
197 handled = true; | |
198 } else if (!handled && | |
199 event.GetKeyCode() == ui::VKEY_TAB && | |
200 !event.IsShiftDown() && | |
201 !event.IsControlDown()) { | |
202 if (model_->is_keyword_hint() && !model_->keyword().empty()) { | |
203 model_->AcceptKeyword(); | |
204 handled = true; | |
205 } else { | |
206 // TODO(Oshima): handle instant | |
207 } | |
208 } | |
209 // TODO(oshima): page up & down | |
210 | |
211 return handled; | |
212 } | |
213 | |
214 bool AutocompleteEditViewViews::HandleKeyReleaseEvent( | |
215 const views::KeyEvent& event) { | |
216 // Omnibox2 can switch its contents while pressing a control key. To switch | |
217 // the contents of omnibox2, we notify the AutocompleteEditModel class when | |
218 // the control-key state is changed. | |
219 if (event.GetKeyCode() == ui::VKEY_CONTROL) { | |
220 // TODO(oshima): investigate if we need to support keyboard with two | |
221 // controls. See autocomplete_edit_view_gtk.cc. | |
222 model_->OnControlKeyChanged(false); | |
223 return true; | |
224 } | |
225 return false; | |
226 } | |
227 | |
228 void AutocompleteEditViewViews::HandleFocusIn() { | |
229 // TODO(oshima): Get control key state. | |
230 model_->OnSetFocus(false); | |
231 // Don't call controller_->OnSetFocus as this view has already | |
232 // acquired the focus. | |
233 } | |
234 | |
235 void AutocompleteEditViewViews::HandleFocusOut() { | |
236 // TODO(oshima): we don't have native view. This requires | |
237 // further refactoring. | |
238 controller_->OnAutocompleteLosingFocus(NULL); | |
239 // Close the popup. | |
240 ClosePopup(); | |
241 // Tell the model to reset itself. | |
242 model_->OnKillFocus(); | |
243 controller_->OnKillFocus(); | |
244 } | |
245 | |
246 //////////////////////////////////////////////////////////////////////////////// | |
247 // AutocompleteEditViewViews, views::View implementation: | |
248 | |
249 bool AutocompleteEditViewViews::OnMousePressed( | |
250 const views::MouseEvent& event) { | |
251 if (event.IsLeftMouseButton()) { | |
252 // Button press event may change the selection, we need to record the change | |
253 // and report it to |model_| later when button is released. | |
254 OnBeforePossibleChange(); | |
255 } | |
256 // pass the event through to TextfieldViews. | |
Peter Kasting
2011/01/20 19:44:37
Nit: pass -> Pass
oshima
2011/01/20 21:35:48
Done.
| |
257 return false; | |
258 } | |
259 | |
260 //////////////////////////////////////////////////////////////////////////////// | |
261 // AutocompleteEditViewViews, AutocopmleteEditView implementation: | |
262 | |
263 AutocompleteEditModel* AutocompleteEditViewViews::model() { | |
264 return model_.get(); | |
265 } | |
266 | |
267 const AutocompleteEditModel* AutocompleteEditViewViews::model() const { | |
268 return model_.get(); | |
269 } | |
270 | |
271 void AutocompleteEditViewViews::SaveStateToTab(TabContents* tab) { | |
272 DCHECK(tab); | |
273 | |
274 // NOTE: GetStateForTabSwitch may affect GetSelection, so order is important. | |
275 AutocompleteEditModel::State model_state = model_->GetStateForTabSwitch(); | |
276 views::TextRange selection; | |
277 textfield_->GetSelectedRange(&selection); | |
278 GetStateAccessor()->SetProperty( | |
279 tab->property_bag(), | |
280 AutocompleteEditState(model_state, ViewState(selection))); | |
281 } | |
282 | |
283 void AutocompleteEditViewViews::Update(const TabContents* contents) { | |
284 // NOTE: We're getting the URL text here from the ToolbarModel. | |
285 bool visibly_changed_permanent_text = | |
286 model_->UpdatePermanentText(toolbar_model_->GetText()); | |
287 | |
288 ToolbarModel::SecurityLevel security_level = | |
289 toolbar_model_->GetSecurityLevel(); | |
290 bool changed_security_level = (security_level != security_level_); | |
291 security_level_ = security_level; | |
292 | |
293 // TODO(oshima): Copied from gtk implementation which is | |
294 // slightly different from WIN impl. Find out the correct implementation | |
295 // for views-implementation. | |
296 if (contents) { | |
297 RevertAll(); | |
298 const AutocompleteEditState* state = | |
299 GetStateAccessor()->GetProperty(contents->property_bag()); | |
300 if (state) { | |
301 model_->RestoreState(state->model_state); | |
302 | |
303 // Move the marks for the cursor and the other end of the selection to | |
304 // the previously-saved offsets (but preserve PRIMARY). | |
305 textfield_->SelectRange(state->view_state.selection_range); | |
306 } | |
307 } else if (visibly_changed_permanent_text) { | |
308 RevertAll(); | |
309 } else if (changed_security_level) { | |
310 EmphasizeURLComponents(); | |
311 } | |
312 } | |
313 | |
314 void AutocompleteEditViewViews::OpenURL(const GURL& url, | |
315 WindowOpenDisposition disposition, | |
316 PageTransition::Type transition, | |
317 const GURL& alternate_nav_url, | |
318 size_t selected_line, | |
319 const std::wstring& keyword) { | |
320 if (!url.is_valid()) | |
321 return; | |
322 | |
323 model_->OpenURL(url, disposition, transition, alternate_nav_url, | |
324 selected_line, keyword); | |
325 } | |
326 | |
327 std::wstring AutocompleteEditViewViews::GetText() const { | |
328 // TODO(oshima): IME support | |
329 return UTF16ToWide(textfield_->text()); | |
330 } | |
331 | |
332 bool AutocompleteEditViewViews::IsEditingOrEmpty() const { | |
333 return model_->user_input_in_progress() || (GetTextLength() == 0); | |
334 } | |
335 | |
336 int AutocompleteEditViewViews::GetIcon() const { | |
337 return IsEditingOrEmpty() ? | |
338 AutocompleteMatch::TypeToIcon(model_->CurrentTextType()) : | |
339 toolbar_model_->GetIcon(); | |
340 } | |
341 | |
342 void AutocompleteEditViewViews::SetUserText(const std::wstring& text) { | |
343 SetUserText(text, text, true); | |
344 } | |
345 | |
346 void AutocompleteEditViewViews::SetUserText(const std::wstring& text, | |
347 const std::wstring& display_text, | |
348 bool update_popup) { | |
349 model_->SetUserText(text); | |
350 SetWindowTextAndCaretPos(display_text, display_text.length()); | |
351 if (update_popup) | |
352 UpdatePopup(); | |
353 TextChanged(); | |
354 } | |
355 | |
356 void AutocompleteEditViewViews::SetWindowTextAndCaretPos( | |
357 const std::wstring& text, | |
358 size_t caret_pos) { | |
359 const views::TextRange range(caret_pos, caret_pos); | |
360 SetTextAndSelectedRange(text, range); | |
361 } | |
362 | |
363 void AutocompleteEditViewViews::SetForcedQuery() { | |
364 const std::wstring current_text(GetText()); | |
365 const size_t start = current_text.find_first_not_of(kWhitespaceWide); | |
366 if (start == std::wstring::npos || (current_text[start] != '?')) { | |
367 SetUserText(L"?"); | |
368 } else { | |
369 SelectRange(current_text.size(), start + 1); | |
370 } | |
371 } | |
372 | |
373 bool AutocompleteEditViewViews::IsSelectAll() { | |
374 // TODO(oshima): IME support. | |
375 return textfield_->text() == textfield_->GetSelectedText(); | |
376 } | |
377 | |
378 bool AutocompleteEditViewViews::DeleteAtEndPressed() { | |
379 return delete_at_end_pressed_; | |
380 } | |
381 | |
382 void AutocompleteEditViewViews::GetSelectionBounds( | |
383 std::wstring::size_type* start, | |
384 std::wstring::size_type* end) { | |
385 views::TextRange range; | |
386 textfield_->GetSelectedRange(&range); | |
387 // TODO(oshima): | |
388 // gtk imlp uses bounds (end) as start and caret (start) as end and | |
Peter Kasting
2011/01/20 19:44:37
Nit: This comment can go away now, right?
oshima
2011/01/20 21:35:48
Done.
| |
389 // win's behavior seem to be the same. Figure out why and fix if necessary. | |
390 *start = static_cast<size_t>(range.end()); | |
391 *end = static_cast<size_t>(range.start()); | |
392 } | |
393 | |
394 void AutocompleteEditViewViews::SelectAll(bool reversed) { | |
395 if (reversed) { | |
Peter Kasting
2011/01/20 19:44:37
Nit: No {}
oshima
2011/01/20 21:35:48
Done.
| |
396 SelectRange(GetTextLength(), 0); | |
397 } else { | |
398 SelectRange(0, GetTextLength()); | |
399 } | |
400 } | |
401 | |
402 void AutocompleteEditViewViews::RevertAll() { | |
403 ClosePopup(); | |
404 model_->Revert(); | |
405 TextChanged(); | |
406 } | |
407 | |
408 void AutocompleteEditViewViews::UpdatePopup() { | |
409 model_->SetInputInProgress(true); | |
410 if (!model_->has_focus()) | |
411 return; | |
412 | |
413 // Don't inline autocomplete when the caret/selection isn't at the end of | |
414 // the text, or in the middle of composition. | |
415 views::TextRange sel; | |
416 textfield_->GetSelectedRange(&sel); | |
417 bool no_inline_autocomplete = sel.GetMax() < GetTextLength(); | |
418 | |
419 // TODO(oshima): Support IME. Don't show autocomplete if IME has some text. | |
420 model_->StartAutocomplete(!sel.is_empty(), no_inline_autocomplete); | |
421 } | |
422 | |
423 void AutocompleteEditViewViews::ClosePopup() { | |
424 if (popup_view_->GetModel()->IsOpen()) | |
425 controller_->OnAutocompleteWillClosePopup(); | |
426 | |
427 popup_view_->GetModel()->StopAutocomplete(); | |
428 } | |
429 | |
430 void AutocompleteEditViewViews::SetFocus() { | |
431 // In views-implementation, the focus is on textfield rather than | |
432 // AutocompleteEditView. | |
433 textfield_->RequestFocus(); | |
434 } | |
435 | |
436 void AutocompleteEditViewViews::OnTemporaryTextMaybeChanged( | |
437 const std::wstring& display_text, | |
438 bool save_original_selection) { | |
439 if (save_original_selection) | |
440 textfield_->GetSelectedRange(&saved_temporary_selection_); | |
441 | |
442 SetWindowTextAndCaretPos(display_text, display_text.length()); | |
443 TextChanged(); | |
444 } | |
445 | |
446 bool AutocompleteEditViewViews::OnInlineAutocompleteTextMaybeChanged( | |
447 const std::wstring& display_text, | |
448 size_t user_text_length) { | |
449 if (display_text == GetText()) | |
450 return false; | |
451 views::TextRange range(display_text.size(), user_text_length); | |
452 SetTextAndSelectedRange(display_text, range); | |
453 TextChanged(); | |
454 return true; | |
455 } | |
456 | |
457 void AutocompleteEditViewViews::OnRevertTemporaryText() { | |
458 textfield_->SelectRange(saved_temporary_selection_); | |
459 TextChanged(); | |
460 } | |
461 | |
462 void AutocompleteEditViewViews::OnBeforePossibleChange() { | |
463 // Record our state. | |
464 text_before_change_ = GetText(); | |
465 textfield_->GetSelectedRange(&sel_before_change_); | |
466 } | |
467 | |
468 bool AutocompleteEditViewViews::OnAfterPossibleChange() { | |
469 // OnAfterPossibleChange should be called once per modification, | |
470 // and we should ignore if this is called while a key event is being handled | |
471 // because OnAfterPossibleChagne will be called after the key event is | |
472 // actually handled. | |
473 if (handling_key_press_) { | |
474 content_maybe_changed_by_key_press_ = true; | |
475 return false; | |
476 } | |
477 views::TextRange new_sel; | |
478 textfield_->GetSelectedRange(&new_sel); | |
479 | |
480 size_t length = GetTextLength(); | |
481 bool at_end_of_edit = (new_sel.start() == length && new_sel.end() == length); | |
482 | |
483 // See if the text or selection have changed since OnBeforePossibleChange(). | |
484 std::wstring new_text = GetText(); | |
485 text_changed_ = (new_text != text_before_change_); | |
486 bool selection_differs = !sel_before_change_.Equals(new_sel); | |
487 | |
488 // When the user has deleted text, we don't allow inline autocomplete. Make | |
489 // sure to not flag cases like selecting part of the text and then pasting | |
490 // (or typing) the prefix of that selection. (We detect these by making | |
491 // sure the caret, which should be after any insertion, hasn't moved | |
492 // forward of the old selection start.) | |
493 bool just_deleted_text = | |
494 (text_before_change_.length() > new_text.length()) && | |
495 (new_sel.start() <= sel_before_change_.GetMin()); | |
496 | |
497 delete_at_end_pressed_ = false; | |
498 | |
499 bool something_changed = model_->OnAfterPossibleChange(new_text, | |
500 selection_differs, text_changed_, just_deleted_text, at_end_of_edit); | |
501 | |
502 // If only selection was changed, we don't need to call |controller_|'s | |
503 // OnChanged() method, which is called in TextChanged(). | |
504 // But we still need to call EmphasizeURLComponents() to make sure the text | |
505 // attributes are updated correctly. | |
506 if (something_changed && text_changed_) { | |
507 TextChanged(); | |
508 } else if (selection_differs) { | |
509 EmphasizeURLComponents(); | |
510 } else if (delete_was_pressed_ && at_end_of_edit) { | |
511 delete_at_end_pressed_ = true; | |
512 controller_->OnChanged(); | |
513 } | |
514 delete_was_pressed_ = false; | |
515 | |
516 return something_changed; | |
517 } | |
518 | |
519 gfx::NativeView AutocompleteEditViewViews::GetNativeView() const { | |
520 return GetWidget()->GetNativeView(); | |
521 } | |
522 | |
523 CommandUpdater* AutocompleteEditViewViews::GetCommandUpdater() { | |
524 return command_updater_; | |
525 } | |
526 | |
527 views::View* AutocompleteEditViewViews::AddToView(views::View* parent) { | |
528 parent->AddChildView(this); | |
529 AddChildView(textfield_); | |
530 SetLayoutManager(new views::FillLayout(true /* exlucde insets*/)); | |
531 return this; | |
532 } | |
533 | |
534 int AutocompleteEditViewViews::TextWidth() const { | |
535 // TODO(oshima): add horizontal margin. | |
536 return textfield_->font().GetStringWidth(textfield_->text()); | |
537 } | |
538 | |
539 bool AutocompleteEditViewViews::IsImeComposing() const { | |
540 return false; | |
541 } | |
542 | |
543 bool AutocompleteEditViewViews::CommitInstantSuggestion( | |
544 const std::wstring& typed_text, | |
545 const std::wstring& suggested_text) { | |
546 model_->FinalizeInstantQuery(typed_text, suggested_text); | |
547 return true; | |
548 } | |
549 | |
550 void AutocompleteEditViewViews::SetInstantSuggestion(const string16& input) { | |
551 NOTIMPLEMENTED(); | |
552 } | |
553 | |
554 //////////////////////////////////////////////////////////////////////////////// | |
555 // AutocompleteEditViewViews, NotificationObserver implementation: | |
556 | |
557 void AutocompleteEditViewViews::Observe(NotificationType type, | |
558 const NotificationSource& source, | |
559 const NotificationDetails& details) { | |
560 DCHECK(type == NotificationType::BROWSER_THEME_CHANGED); | |
561 SetBaseColor(); | |
562 } | |
563 | |
564 //////////////////////////////////////////////////////////////////////////////// | |
565 // AutocompleteEditViewViews, Textfield::Controller implementation: | |
566 | |
567 void AutocompleteEditViewViews::ContentsChanged(views::Textfield* sender, | |
568 const string16& new_contents) { | |
569 if (handling_key_press_) | |
570 content_maybe_changed_by_key_press_ = true; | |
571 } | |
572 | |
573 bool AutocompleteEditViewViews::HandleKeyEvent( | |
574 views::Textfield* textfield, | |
575 const views::KeyEvent& event) { | |
576 delete_was_pressed_ = event.GetKeyCode() == ui::VKEY_DELETE; | |
577 | |
578 // Reset |text_changed_| before passing the key event on to the text view. | |
579 text_changed_ = false; | |
580 OnBeforePossibleChange(); | |
581 handling_key_press_ = true; | |
582 content_maybe_changed_by_key_press_ = false; | |
583 | |
584 if (event.GetKeyCode() == ui::VKEY_BACK) { | |
585 // Checks if it's currently in keyword search mode. | |
586 if (model_->is_keyword_hint() || model_->keyword().empty()) | |
Peter Kasting
2011/01/20 19:44:37
Nit: Could simplify all this to
if (!model_->is
| |
587 return false; | |
588 // If there is selection, let textfield handle the backspace. | |
589 if (!textfield_->GetSelectedText().empty()) | |
590 return false; | |
591 // If not at the begining of the text, let textfield handle the backspace. | |
592 if (textfield_->GetCursorPosition()) | |
593 return false; | |
594 model_->ClearKeyword(GetText()); | |
595 return true; | |
596 } | |
597 | |
598 return false; | |
599 } | |
600 | |
601 //////////////////////////////////////////////////////////////////////////////// | |
602 // AutocompleteEditViewViews, private: | |
603 | |
604 size_t AutocompleteEditViewViews::GetTextLength() const { | |
605 // TODO(oshima): Support instant, IME. | |
606 return textfield_->text().length(); | |
607 } | |
608 | |
609 void AutocompleteEditViewViews::EmphasizeURLComponents() { | |
610 // TODO(oshima): Update URL visual style | |
611 NOTIMPLEMENTED(); | |
612 } | |
613 | |
614 void AutocompleteEditViewViews::TextChanged() { | |
615 EmphasizeURLComponents(); | |
616 controller_->OnChanged(); | |
617 } | |
618 | |
619 void AutocompleteEditViewViews::SetTextAndSelectedRange( | |
620 const std::wstring& text, | |
621 const views::TextRange& range) { | |
622 if (text != GetText()) { | |
Peter Kasting
2011/01/20 19:44:37
Nit: No {}
oshima
2011/01/20 21:35:48
Done.
| |
623 textfield_->SetText(WideToUTF16(text)); | |
624 } | |
625 textfield_->SelectRange(range); | |
626 } | |
627 | |
628 string16 AutocompleteEditViewViews::GetSelectedText() const { | |
629 // TODO(oshima): Support instant, IME. | |
630 return textfield_->GetSelectedText(); | |
631 } | |
632 | |
633 void AutocompleteEditViewViews::SelectRange(size_t caret, size_t end) { | |
634 const views::TextRange range(caret, end); | |
635 textfield_->SelectRange(range); | |
636 } | |
OLD | NEW |