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 "ui/views/ime/mock_input_method.h"
6
7#include "base/basictypes.h"
8#include "base/logging.h"
9#include "ui/base/ime/text_input_client.h"
10#include "ui/events/event.h"
11#include "ui/events/keycodes/keyboard_codes.h"
12#include "ui/views/widget/widget.h"
13
14namespace views {
15
16MockInputMethod::MockInputMethod()
17    : composition_changed_(false),
18      focus_changed_(false),
19      untranslated_ime_message_called_(false),
20      text_input_type_changed_(false),
21      caret_bounds_changed_(false),
22      cancel_composition_called_(false),
23      input_locale_changed_(false),
24      locale_("en-US"),
25      direction_(base::i18n::LEFT_TO_RIGHT),
26      active_(true) {
27}
28
29MockInputMethod::MockInputMethod(internal::InputMethodDelegate* delegate)
30    : composition_changed_(false),
31      focus_changed_(false),
32      untranslated_ime_message_called_(false),
33      text_input_type_changed_(false),
34      caret_bounds_changed_(false),
35      cancel_composition_called_(false),
36      input_locale_changed_(false),
37      locale_("en-US"),
38      direction_(base::i18n::LEFT_TO_RIGHT),
39      active_(true) {
40  SetDelegate(delegate);
41}
42
43MockInputMethod::~MockInputMethod() {
44}
45
46void MockInputMethod::Init(Widget* widget) {
47  InputMethodBase::Init(widget);
48}
49
50void MockInputMethod::OnFocus() {}
51
52void MockInputMethod::OnBlur() {}
53
54bool MockInputMethod::OnUntranslatedIMEMessage(
55    const base::NativeEvent& event,
56    NativeEventResult* result) {
57  untranslated_ime_message_called_ = true;
58  if (result)
59    *result = InputMethod::NativeEventResult();
60  return false;
61}
62
63void MockInputMethod::DispatchKeyEvent(const ui::KeyEvent& key) {
64  bool handled = (composition_changed_ || result_text_.length()) &&
65      !IsTextInputTypeNone();
66
67  ClearStates();
68  if (handled) {
69    ui::KeyEvent mock_key(ui::ET_KEY_PRESSED,
70                          ui::VKEY_PROCESSKEY,
71                          key.flags(),
72                          key.is_char());
73    DispatchKeyEventPostIME(mock_key);
74  } else {
75    DispatchKeyEventPostIME(key);
76  }
77
78  if (focus_changed_)
79    return;
80
81  ui::TextInputClient* client = GetTextInputClient();
82  if (client) {
83    if (handled) {
84      if (result_text_.length())
85        client->InsertText(result_text_);
86      if (composition_changed_) {
87        if (composition_.text.length())
88          client->SetCompositionText(composition_);
89        else
90          client->ClearCompositionText();
91      }
92    } else if (key.type() == ui::ET_KEY_PRESSED) {
93      char16 ch = key.GetCharacter();
94      client->InsertChar(ch, key.flags());
95    }
96  }
97
98  ClearResult();
99}
100
101void MockInputMethod::OnTextInputTypeChanged(View* view) {
102  if (IsViewFocused(view))
103    text_input_type_changed_ = true;
104  InputMethodBase::OnTextInputTypeChanged(view);
105}
106
107void MockInputMethod::OnCaretBoundsChanged(View* view) {
108  if (IsViewFocused(view))
109    caret_bounds_changed_ = true;
110}
111
112void MockInputMethod::CancelComposition(View* view) {
113  if (IsViewFocused(view)) {
114    cancel_composition_called_ = true;
115    ClearResult();
116  }
117}
118
119void MockInputMethod::OnInputLocaleChanged() {
120  input_locale_changed_ = true;
121}
122
123std::string MockInputMethod::GetInputLocale() {
124  return locale_;
125}
126
127base::i18n::TextDirection MockInputMethod::GetInputTextDirection() {
128  return direction_;
129}
130
131bool MockInputMethod::IsActive() {
132  return active_;
133}
134
135bool MockInputMethod::IsCandidatePopupOpen() const {
136  return false;
137}
138
139bool MockInputMethod::IsMock() const {
140  return true;
141}
142
143void MockInputMethod::OnWillChangeFocus(View* focused_before, View* focused)  {
144  ui::TextInputClient* client = GetTextInputClient();
145  if (client && client->HasCompositionText())
146    client->ConfirmCompositionText();
147  focus_changed_ = true;
148  ClearResult();
149}
150
151void MockInputMethod::Clear() {
152  ClearStates();
153  ClearResult();
154}
155
156void MockInputMethod::SetCompositionTextForNextKey(
157    const ui::CompositionText& composition) {
158  composition_changed_ = true;
159  composition_ = composition;
160}
161
162void MockInputMethod::SetResultTextForNextKey(const string16& result) {
163  result_text_ = result;
164}
165
166void MockInputMethod::SetInputLocale(const std::string& locale) {
167  if (locale_ != locale) {
168    locale_ = locale;
169    OnInputMethodChanged();
170  }
171}
172
173void MockInputMethod::SetInputTextDirection(
174    base::i18n::TextDirection direction) {
175  if (direction_ != direction) {
176    direction_ = direction;
177    OnInputMethodChanged();
178  }
179}
180
181void MockInputMethod::SetActive(bool active) {
182  if (active_ != active) {
183    active_ = active;
184    OnInputMethodChanged();
185  }
186}
187
188void MockInputMethod::ClearStates() {
189  focus_changed_ = false;
190  untranslated_ime_message_called_ = false;
191  text_input_type_changed_ = false;
192  caret_bounds_changed_ = false;
193  cancel_composition_called_ = false;
194  input_locale_changed_ = false;
195}
196
197void MockInputMethod::ClearResult() {
198  composition_.Clear();
199  composition_changed_ = false;
200  result_text_.clear();
201}
202
203}  // namespace views
204