1fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch// Copyright 2013 The Chromium Authors. All rights reserved. 2fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch// Use of this source code is governed by a BSD-style license that can be 3fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch// found in the LICENSE file. 4fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch 5fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch#include "ui/views/controls/prefix_selector.h" 6fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch 7fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch#include "base/i18n/case_conversion.h" 8fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch#include "ui/base/ime/text_input_type.h" 958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "ui/gfx/range/range.h" 10fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch#include "ui/views/controls/prefix_delegate.h" 11fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch#include "ui/views/widget/widget.h" 12fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch 13fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdochnamespace views { 14fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch 15fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdochnamespace { 16fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch 17fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdochconst int64 kTimeBeforeClearingMS = 1000; 18fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch 19fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdochvoid ConvertRectToScreen(const views::View* src, gfx::Rect* r) { 20fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch DCHECK(src); 21fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch 22fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch gfx::Point new_origin = r->origin(); 23fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch views::View::ConvertPointToScreen(src, &new_origin); 24fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch r->set_origin(new_origin); 25fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch} 26fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch 27fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch} // namespace 28fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch 29fb250657ef40d7500f20882d5c9909c1013367d3Ben MurdochPrefixSelector::PrefixSelector(PrefixDelegate* delegate) 30fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch : prefix_delegate_(delegate) { 31fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch} 32fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch 33fb250657ef40d7500f20882d5c9909c1013367d3Ben MurdochPrefixSelector::~PrefixSelector() { 34fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch} 35fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch 36fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdochvoid PrefixSelector::OnViewBlur() { 37fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch ClearText(); 38fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch} 39fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch 40fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdochvoid PrefixSelector::SetCompositionText( 41fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch const ui::CompositionText& composition) { 42fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch} 43fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch 44fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdochvoid PrefixSelector::ConfirmCompositionText() { 45fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch} 46fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch 47fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdochvoid PrefixSelector::ClearCompositionText() { 48fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch} 49fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch 505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PrefixSelector::InsertText(const base::string16& text) { 51fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch OnTextInput(text); 52fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch} 53fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch 545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PrefixSelector::InsertChar(base::char16 ch, int flags) { 555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OnTextInput(base::string16(1, ch)); 56fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch} 57fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch 58fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdochgfx::NativeWindow PrefixSelector::GetAttachedWindow() const { 59fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch return prefix_delegate_->GetWidget()->GetNativeWindow(); 60fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch} 61fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch 62fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdochui::TextInputType PrefixSelector::GetTextInputType() const { 63fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch return ui::TEXT_INPUT_TYPE_TEXT; 64fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch} 65fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch 66ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochui::TextInputMode PrefixSelector::GetTextInputMode() const { 67ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return ui::TEXT_INPUT_MODE_DEFAULT; 68ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} 69ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 70fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdochbool PrefixSelector::CanComposeInline() const { 71fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch return false; 72fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch} 73fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch 748bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)gfx::Rect PrefixSelector::GetCaretBounds() const { 75fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch gfx::Rect rect(prefix_delegate_->GetVisibleBounds().origin(), gfx::Size()); 76fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch // TextInputClient::GetCaretBounds is expected to return a value in screen 77fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch // coordinates. 78fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch ConvertRectToScreen(prefix_delegate_, &rect); 79fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch return rect; 80fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch} 81fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch 82fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdochbool PrefixSelector::GetCompositionCharacterBounds(uint32 index, 838bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) gfx::Rect* rect) const { 84fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch // TextInputClient::GetCompositionCharacterBounds is expected to fill |rect| 85fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch // in screen coordinates and GetCaretBounds returns screen coordinates. 86fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch *rect = GetCaretBounds(); 87fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch return false; 88fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch} 89fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch 908bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)bool PrefixSelector::HasCompositionText() const { 91fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch return false; 92fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch} 93fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch 948bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)bool PrefixSelector::GetTextRange(gfx::Range* range) const { 9558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) *range = gfx::Range(); 96fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch return false; 97fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch} 98fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch 998bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)bool PrefixSelector::GetCompositionTextRange(gfx::Range* range) const { 10058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) *range = gfx::Range(); 101fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch return false; 102fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch} 103fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch 1048bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)bool PrefixSelector::GetSelectionRange(gfx::Range* range) const { 10558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) *range = gfx::Range(); 106fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch return false; 107fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch} 108fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch 10958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)bool PrefixSelector::SetSelectionRange(const gfx::Range& range) { 110fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch return false; 111fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch} 112fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch 11358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)bool PrefixSelector::DeleteRange(const gfx::Range& range) { 114fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch return false; 115fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch} 116fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch 11758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)bool PrefixSelector::GetTextFromRange(const gfx::Range& range, 1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::string16* text) const { 119fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch return false; 120fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch} 121fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch 122fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdochvoid PrefixSelector::OnInputMethodChanged() { 123fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch ClearText(); 124fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch} 125fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch 126fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdochbool PrefixSelector::ChangeTextDirectionAndLayoutAlignment( 127fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch base::i18n::TextDirection direction) { 128fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch return true; 129fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch} 130fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch 131fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdochvoid PrefixSelector::ExtendSelectionAndDelete(size_t before, size_t after) { 132fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch} 133fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch 134fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdochvoid PrefixSelector::EnsureCaretInRect(const gfx::Rect& rect) { 135fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch} 136fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch 137f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void PrefixSelector::OnCandidateWindowShown() { 138f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 139f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 140f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void PrefixSelector::OnCandidateWindowUpdated() { 141f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 142f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 143f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void PrefixSelector::OnCandidateWindowHidden() { 144f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 145f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 14646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)bool PrefixSelector::IsEditingCommandEnabled(int command_id) { 14746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return false; 14846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 14946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 15046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void PrefixSelector::ExecuteEditingCommand(int command_id) { 15146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 15246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PrefixSelector::OnTextInput(const base::string16& text) { 15468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // Small hack to filter out 'tab' and 'enter' input, as the expectation is 15568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // that they are control characters and will not affect the currently-active 15668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // prefix. 15768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (text.length() == 1 && 15868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) (text[0] == L'\t' || text[0] == L'\r' || text[0] == L'\n')) 159fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch return; 160fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch 161fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch const int row_count = prefix_delegate_->GetRowCount(); 162fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch if (row_count == 0) 163fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch return; 164fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch 165fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch // Search for |text| if it has been a while since the user typed, otherwise 166fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch // append |text| to |current_text_| and search for that. If it has been a 167fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch // while search after the current row, otherwise search starting from the 168fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch // current row. 169fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch int row = std::max(0, prefix_delegate_->GetSelectedRow()); 170fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch const base::TimeTicks now(base::TimeTicks::Now()); 171fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch if ((now - time_of_last_key_).InMilliseconds() < kTimeBeforeClearingMS) { 172fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch current_text_ += text; 173fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch } else { 174fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch current_text_ = text; 175fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch if (prefix_delegate_->GetSelectedRow() >= 0) 176fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch row = (row + 1) % row_count; 177fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch } 178fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch time_of_last_key_ = now; 179fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch 180fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch const int start_row = row; 1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::string16 lower_text(base::i18n::ToLower(current_text_)); 182fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch do { 1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (TextAtRowMatchesText(row, lower_text)) { 184fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch prefix_delegate_->SetSelectedRow(row); 185fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch return; 186fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch } 187fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch row = (row + 1) % row_count; 188fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch } while (row != start_row); 189fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch} 190fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch 191fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdochbool PrefixSelector::TextAtRowMatchesText(int row, 1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::string16& lower_text) { 1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::string16 model_text( 194fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch base::i18n::ToLower(prefix_delegate_->GetTextForRow(row))); 195fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch return (model_text.size() >= lower_text.size()) && 196fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch (model_text.compare(0, lower_text.size(), lower_text) == 0); 197fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch} 198fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch 199fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdochvoid PrefixSelector::ClearText() { 200fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch current_text_.clear(); 201fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch time_of_last_key_ = base::TimeTicks(); 202fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch} 203fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch 204fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch} // namespace views 205