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

Side by Side Diff: views/controls/textfield/native_textfield_views.cc

Issue 6675005: Integrate the new input method API for Views into Chromium. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix Windows build. Created 9 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "views/controls/textfield/native_textfield_views.h" 5 #include "views/controls/textfield/native_textfield_views.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/command_line.h" 9 #include "base/command_line.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "base/message_loop.h" 11 #include "base/message_loop.h"
12 #include "base/utf_string_conversions.h" 12 #include "base/utf_string_conversions.h"
13 #include "grit/app_strings.h" 13 #include "grit/app_strings.h"
14 #include "ui/base/clipboard/clipboard.h" 14 #include "ui/base/clipboard/clipboard.h"
15 #include "ui/base/range/range.h" 15 #include "ui/base/range/range.h"
16 #include "ui/gfx/canvas.h" 16 #include "ui/gfx/canvas.h"
17 #include "ui/gfx/canvas_skia.h" 17 #include "ui/gfx/canvas_skia.h"
18 #include "ui/gfx/insets.h" 18 #include "ui/gfx/insets.h"
19 #include "views/background.h" 19 #include "views/background.h"
20 #include "views/border.h" 20 #include "views/border.h"
21 #include "views/controls/menu/menu_2.h" 21 #include "views/controls/menu/menu_2.h"
22 #include "views/controls/textfield/textfield.h" 22 #include "views/controls/textfield/textfield.h"
23 #include "views/controls/textfield/textfield_controller.h" 23 #include "views/controls/textfield/textfield_controller.h"
24 #include "views/controls/textfield/textfield_views_model.h" 24 #include "views/controls/textfield/textfield_views_model.h"
25 #include "views/events/event.h" 25 #include "views/events/event.h"
26 #include "views/ime/input_method.h"
26 #include "views/metrics.h" 27 #include "views/metrics.h"
27 #include "views/views_delegate.h" 28 #include "views/views_delegate.h"
28 29
29 #if defined(OS_LINUX) 30 #if defined(OS_LINUX)
30 #include "ui/gfx/gtk_util.h" 31 #include "ui/gfx/gtk_util.h"
31 #endif 32 #endif
32 33
33 namespace { 34 namespace {
34 35
35 // A global flag to switch the Textfield wrapper to TextfieldViews. 36 // A global flag to switch the Textfield wrapper to TextfieldViews.
(...skipping 18 matching lines...) Expand all
54 const char kEnableViewsBasedTextfieldSwitch[] = "enable-textfield-views"; 55 const char kEnableViewsBasedTextfieldSwitch[] = "enable-textfield-views";
55 } // namespace 56 } // namespace
56 57
57 namespace views { 58 namespace views {
58 59
59 const char NativeTextfieldViews::kViewClassName[] = 60 const char NativeTextfieldViews::kViewClassName[] =
60 "views/NativeTextfieldViews"; 61 "views/NativeTextfieldViews";
61 62
62 NativeTextfieldViews::NativeTextfieldViews(Textfield* parent) 63 NativeTextfieldViews::NativeTextfieldViews(Textfield* parent)
63 : textfield_(parent), 64 : textfield_(parent),
64 model_(new TextfieldViewsModel()), 65 ALLOW_THIS_IN_INITIALIZER_LIST(model_(new TextfieldViewsModel(this))),
65 text_border_(new TextfieldBorder()), 66 text_border_(new TextfieldBorder()),
66 text_offset_(0), 67 text_offset_(0),
67 insert_(true), 68 insert_(true),
68 is_cursor_visible_(false), 69 is_cursor_visible_(false),
70 skip_input_method_cancel_composition_(false),
69 ALLOW_THIS_IN_INITIALIZER_LIST(cursor_timer_(this)), 71 ALLOW_THIS_IN_INITIALIZER_LIST(cursor_timer_(this)),
70 last_mouse_press_time_(base::Time::FromInternalValue(0)), 72 last_mouse_press_time_(base::Time::FromInternalValue(0)),
71 click_state_(NONE) { 73 click_state_(NONE) {
72 set_border(text_border_); 74 set_border(text_border_);
73 75
74 // Multiline is not supported. 76 // Multiline is not supported.
75 DCHECK_NE(parent->style(), Textfield::STYLE_MULTILINE); 77 DCHECK_NE(parent->style(), Textfield::STYLE_MULTILINE);
76 // Lowercase is not supported. 78 // Lowercase is not supported.
77 DCHECK_NE(parent->style(), Textfield::STYLE_LOWERCASE); 79 DCHECK_NE(parent->style(), Textfield::STYLE_LOWERCASE);
78 80
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
153 } 155 }
154 156
155 ///////////////////////////////////////////////////////////////// 157 /////////////////////////////////////////////////////////////////
156 // NativeTextfieldViews, NativeTextifieldWrapper overrides: 158 // NativeTextfieldViews, NativeTextifieldWrapper overrides:
157 159
158 string16 NativeTextfieldViews::GetText() const { 160 string16 NativeTextfieldViews::GetText() const {
159 return model_->text(); 161 return model_->text();
160 } 162 }
161 163
162 void NativeTextfieldViews::UpdateText() { 164 void NativeTextfieldViews::UpdateText() {
163 bool changed = model_->SetText(textfield_->text()); 165 model_->SetText(textfield_->text());
164 UpdateCursorBoundsAndTextOffset(); 166 UpdateCursorBoundsAndTextOffset();
165 SchedulePaint(); 167 SchedulePaint();
166 if (changed) {
167 TextfieldController* controller = textfield_->GetController();
168 if (controller)
169 controller->ContentsChanged(textfield_, GetText());
170 }
171 } 168 }
172 169
173 void NativeTextfieldViews::AppendText(const string16& text) { 170 void NativeTextfieldViews::AppendText(const string16& text) {
174 if (text.empty()) 171 if (text.empty())
175 return; 172 return;
176 model_->Append(text); 173 model_->Append(text);
177 UpdateCursorBoundsAndTextOffset(); 174 UpdateCursorBoundsAndTextOffset();
178 SchedulePaint(); 175 SchedulePaint();
179
180 TextfieldController* controller = textfield_->GetController();
181 if (controller)
182 controller->ContentsChanged(textfield_, GetText());
183 } 176 }
184 177
185 string16 NativeTextfieldViews::GetSelectedText() const { 178 string16 NativeTextfieldViews::GetSelectedText() const {
186 return model_->GetSelectedText(); 179 return model_->GetSelectedText();
187 } 180 }
188 181
189 void NativeTextfieldViews::SelectAll() { 182 void NativeTextfieldViews::SelectAll() {
190 model_->SelectAll(); 183 model_->SelectAll();
191 SchedulePaint(); 184 SchedulePaint();
192 } 185 }
(...skipping 20 matching lines...) Expand all
213 206
214 void NativeTextfieldViews::UpdateBackgroundColor() { 207 void NativeTextfieldViews::UpdateBackgroundColor() {
215 // TODO(oshima): Background has to match the border's shape. 208 // TODO(oshima): Background has to match the border's shape.
216 set_background( 209 set_background(
217 Background::CreateSolidBackground(textfield_->background_color())); 210 Background::CreateSolidBackground(textfield_->background_color()));
218 SchedulePaint(); 211 SchedulePaint();
219 } 212 }
220 213
221 void NativeTextfieldViews::UpdateReadOnly() { 214 void NativeTextfieldViews::UpdateReadOnly() {
222 SchedulePaint(); 215 SchedulePaint();
216 OnTextInputTypeChanged();
223 } 217 }
224 218
225 void NativeTextfieldViews::UpdateFont() { 219 void NativeTextfieldViews::UpdateFont() {
226 UpdateCursorBoundsAndTextOffset(); 220 UpdateCursorBoundsAndTextOffset();
227 } 221 }
228 222
229 void NativeTextfieldViews::UpdateIsPassword() { 223 void NativeTextfieldViews::UpdateIsPassword() {
230 model_->set_is_password(textfield_->IsPassword()); 224 model_->set_is_password(textfield_->IsPassword());
231 UpdateCursorBoundsAndTextOffset(); 225 UpdateCursorBoundsAndTextOffset();
232 SchedulePaint(); 226 SchedulePaint();
227 OnTextInputTypeChanged();
233 } 228 }
234 229
235 void NativeTextfieldViews::UpdateEnabled() { 230 void NativeTextfieldViews::UpdateEnabled() {
236 SetEnabled(textfield_->IsEnabled()); 231 SetEnabled(textfield_->IsEnabled());
237 SchedulePaint(); 232 SchedulePaint();
233 OnTextInputTypeChanged();
238 } 234 }
239 235
240 gfx::Insets NativeTextfieldViews::CalculateInsets() { 236 gfx::Insets NativeTextfieldViews::CalculateInsets() {
241 return GetInsets(); 237 return GetInsets();
242 } 238 }
243 239
244 void NativeTextfieldViews::UpdateHorizontalMargins() { 240 void NativeTextfieldViews::UpdateHorizontalMargins() {
245 int left, right; 241 int left, right;
246 if (!textfield_->GetHorizontalMargins(&left, &right)) 242 if (!textfield_->GetHorizontalMargins(&left, &right))
247 return; 243 return;
(...skipping 20 matching lines...) Expand all
268 View* NativeTextfieldViews::GetView() { 264 View* NativeTextfieldViews::GetView() {
269 return this; 265 return this;
270 } 266 }
271 267
272 gfx::NativeView NativeTextfieldViews::GetTestingHandle() const { 268 gfx::NativeView NativeTextfieldViews::GetTestingHandle() const {
273 NOTREACHED(); 269 NOTREACHED();
274 return NULL; 270 return NULL;
275 } 271 }
276 272
277 bool NativeTextfieldViews::IsIMEComposing() const { 273 bool NativeTextfieldViews::IsIMEComposing() const {
278 return false; 274 return model_->HasCompositionText();
279 } 275 }
280 276
281 void NativeTextfieldViews::GetSelectedRange(ui::Range* range) const { 277 void NativeTextfieldViews::GetSelectedRange(ui::Range* range) const {
282 model_->GetSelectedRange(range); 278 model_->GetSelectedRange(range);
283 } 279 }
284 280
285 void NativeTextfieldViews::SelectRange(const ui::Range& range) { 281 void NativeTextfieldViews::SelectRange(const ui::Range& range) {
286 model_->SelectRange(range); 282 model_->SelectRange(range);
287 UpdateCursorBoundsAndTextOffset(); 283 UpdateCursorBoundsAndTextOffset();
288 SchedulePaint(); 284 SchedulePaint();
(...skipping 11 matching lines...) Expand all
300 return handled || HandleKeyEvent(e); 296 return handled || HandleKeyEvent(e);
301 } 297 }
302 298
303 bool NativeTextfieldViews::HandleKeyReleased(const views::KeyEvent& e) { 299 bool NativeTextfieldViews::HandleKeyReleased(const views::KeyEvent& e) {
304 return true; 300 return true;
305 } 301 }
306 302
307 void NativeTextfieldViews::HandleFocus() { 303 void NativeTextfieldViews::HandleFocus() {
308 is_cursor_visible_ = true; 304 is_cursor_visible_ = true;
309 SchedulePaint(); 305 SchedulePaint();
306 OnCaretBoundsChanged();
310 // Start blinking cursor. 307 // Start blinking cursor.
311 MessageLoop::current()->PostDelayedTask( 308 MessageLoop::current()->PostDelayedTask(
312 FROM_HERE, 309 FROM_HERE,
313 cursor_timer_.NewRunnableMethod(&NativeTextfieldViews::UpdateCursor), 310 cursor_timer_.NewRunnableMethod(&NativeTextfieldViews::UpdateCursor),
314 kCursorVisibleTimeMs); 311 kCursorVisibleTimeMs);
315 } 312 }
316 313
317 void NativeTextfieldViews::HandleBlur() { 314 void NativeTextfieldViews::HandleBlur() {
318 // Stop blinking cursor. 315 // Stop blinking cursor.
319 cursor_timer_.RevokeAll(); 316 cursor_timer_.RevokeAll();
320 if (is_cursor_visible_) { 317 if (is_cursor_visible_) {
321 is_cursor_visible_ = false; 318 is_cursor_visible_ = false;
322 RepaintCursor(); 319 RepaintCursor();
323 } 320 }
324 } 321 }
325 322
323 TextInputClient* NativeTextfieldViews::GetTextInputClient() {
324 return textfield_->read_only() ? NULL : this;
325 }
326
326 ///////////////////////////////////////////////////////////////// 327 /////////////////////////////////////////////////////////////////
327 // NativeTextfieldViews, ui::SimpleMenuModel::Delegate overrides: 328 // NativeTextfieldViews, ui::SimpleMenuModel::Delegate overrides:
328 329
329 bool NativeTextfieldViews::IsCommandIdChecked(int command_id) const { 330 bool NativeTextfieldViews::IsCommandIdChecked(int command_id) const {
330 return true; 331 return true;
331 } 332 }
332 333
333 bool NativeTextfieldViews::IsCommandIdEnabled(int command_id) const { 334 bool NativeTextfieldViews::IsCommandIdEnabled(int command_id) const {
334 bool editable = !textfield_->read_only(); 335 bool editable = !textfield_->read_only();
335 string16 result; 336 string16 result;
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
405 void NativeTextfieldViews::SetEnableTextfieldViews(bool enabled) { 406 void NativeTextfieldViews::SetEnableTextfieldViews(bool enabled) {
406 textfield_view_enabled = enabled; 407 textfield_view_enabled = enabled;
407 } 408 }
408 409
409 void NativeTextfieldViews::OnBoundsChanged(const gfx::Rect& previous_bounds) { 410 void NativeTextfieldViews::OnBoundsChanged(const gfx::Rect& previous_bounds) {
410 UpdateCursorBoundsAndTextOffset(); 411 UpdateCursorBoundsAndTextOffset();
411 } 412 }
412 413
413 414
414 /////////////////////////////////////////////////////////////////////////////// 415 ///////////////////////////////////////////////////////////////////////////////
415 // NativeTextfieldViews private: 416 // NativeTextfieldViews, TextInputClient implementation, private:
417
418 void NativeTextfieldViews::SetCompositionText(
419 const ui::CompositionText& composition) {
420 if (GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE)
421 return;
422
423 OnBeforeUserAction();
424 skip_input_method_cancel_composition_ = true;
425 model_->SetCompositionText(composition);
426 skip_input_method_cancel_composition_ = false;
427 UpdateAfterChange(true, true);
428 OnAfterUserAction();
429 }
430
431 void NativeTextfieldViews::ConfirmCompositionText() {
432 if (!model_->HasCompositionText())
433 return;
434
435 OnBeforeUserAction();
436 skip_input_method_cancel_composition_ = true;
437 model_->ConfirmCompositionText();
438 skip_input_method_cancel_composition_ = false;
439 UpdateAfterChange(true, true);
440 OnAfterUserAction();
441 }
442
443 void NativeTextfieldViews::ClearCompositionText() {
444 if (!model_->HasCompositionText())
445 return;
446
447 OnBeforeUserAction();
448 skip_input_method_cancel_composition_ = true;
449 model_->ClearCompositionText();
450 skip_input_method_cancel_composition_ = false;
451 UpdateAfterChange(true, true);
452 OnAfterUserAction();
453 }
454
455 void NativeTextfieldViews::InsertText(const string16& text) {
456 // TODO(suzhe): Filter invalid characters.
457 if (GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE || text.empty())
458 return;
459
460 OnBeforeUserAction();
461 skip_input_method_cancel_composition_ = true;
462 if (insert_)
463 model_->InsertText(text);
464 else
465 model_->ReplaceText(text);
466 skip_input_method_cancel_composition_ = false;
467 UpdateAfterChange(true, true);
468 OnAfterUserAction();
469 }
470
471 void NativeTextfieldViews::InsertChar(char16 ch, int flags) {
472 if (GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE ||
473 !ShouldInsertChar(ch, flags)) {
474 return;
475 }
476
477 OnBeforeUserAction();
478 skip_input_method_cancel_composition_ = true;
479 if (insert_)
480 model_->InsertChar(ch);
481 else
482 model_->ReplaceChar(ch);
483 skip_input_method_cancel_composition_ = false;
484 UpdateAfterChange(true, true);
485 OnAfterUserAction();
486 }
487
488 ui::TextInputType NativeTextfieldViews::GetTextInputType() {
489 if (textfield_->read_only() || !textfield_->IsEnabled())
490 return ui::TEXT_INPUT_TYPE_NONE;
491 else if (textfield_->IsPassword())
492 return ui::TEXT_INPUT_TYPE_PASSWORD;
493 return ui::TEXT_INPUT_TYPE_TEXT;
494 }
495
496 gfx::Rect NativeTextfieldViews::GetCaretBounds() {
497 return cursor_bounds_;
498 }
499
500 bool NativeTextfieldViews::HasCompositionText() {
501 return model_->HasCompositionText();
502 }
503
504 bool NativeTextfieldViews::GetTextRange(ui::Range* range) {
505 // We don't allow the input method to retrieve or delete content from a
506 // password box.
507 if (GetTextInputType() != ui::TEXT_INPUT_TYPE_TEXT)
508 return false;
509
510 model_->GetTextRange(range);
511 return true;
512 }
513
514 bool NativeTextfieldViews::GetCompositionTextRange(ui::Range* range) {
515 if (GetTextInputType() != ui::TEXT_INPUT_TYPE_TEXT)
516 return false;
517
518 model_->GetCompositionTextRange(range);
519 return true;
520 }
521
522 bool NativeTextfieldViews::GetSelectionRange(ui::Range* range) {
523 if (GetTextInputType() != ui::TEXT_INPUT_TYPE_TEXT)
524 return false;
525
526 model_->GetSelectedRange(range);
527 return true;
528 }
529
530 bool NativeTextfieldViews::SetSelectionRange(const ui::Range& range) {
531 if (GetTextInputType() != ui::TEXT_INPUT_TYPE_TEXT || !range.IsValid())
532 return false;
533
534 OnBeforeUserAction();
535 SelectRange(range);
536 OnAfterUserAction();
537 return true;
538 }
539
540 bool NativeTextfieldViews::DeleteRange(const ui::Range& range) {
541 if (GetTextInputType() != ui::TEXT_INPUT_TYPE_TEXT || range.is_empty())
542 return false;
543
544 OnBeforeUserAction();
545 model_->SelectRange(range);
546 if (model_->HasSelection()) {
547 model_->DeleteSelection();
548 UpdateAfterChange(true, true);
549 }
550 OnAfterUserAction();
551 return true;
552 }
553
554 bool NativeTextfieldViews::GetTextFromRange(
555 const ui::Range& range,
556 const base::Callback<void(const string16&)>& callback) {
557 if (GetTextInputType() != ui::TEXT_INPUT_TYPE_TEXT || range.is_empty())
558 return false;
559
560 callback.Run(model_->GetTextFromRange(range));
561 return true;
562 }
563
564 void NativeTextfieldViews::OnInputMethodChanged() {
565 NOTIMPLEMENTED();
566 }
567
568 bool NativeTextfieldViews::ChangeTextDirectionAndLayoutAlignment(
569 base::i18n::TextDirection direction) {
570 NOTIMPLEMENTED();
571 return false;
572 }
573
574 View* NativeTextfieldViews::GetOwnerViewOfTextInputClient() {
575 return textfield_;
576 }
577
578 void NativeTextfieldViews::OnCompositionTextConfirmedOrCleared() {
579 if (skip_input_method_cancel_composition_)
580 return;
581 DCHECK(textfield_->GetInputMethod());
582 textfield_->GetInputMethod()->CancelComposition(textfield_);
583 }
416 584
417 const gfx::Font& NativeTextfieldViews::GetFont() const { 585 const gfx::Font& NativeTextfieldViews::GetFont() const {
418 return textfield_->font(); 586 return textfield_->font();
419 } 587 }
420 588
421 SkColor NativeTextfieldViews::GetTextColor() const { 589 SkColor NativeTextfieldViews::GetTextColor() const {
422 return textfield_->text_color(); 590 return textfield_->text_color();
423 } 591 }
424 592
425 void NativeTextfieldViews::UpdateCursor() { 593 void NativeTextfieldViews::UpdateCursor() {
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
468 text_offset_ = -cursor_bounds_.x(); 636 text_offset_ = -cursor_bounds_.x();
469 } else if (full_width > width && text_offset_ + full_width < width) { 637 } else if (full_width > width && text_offset_ + full_width < width) {
470 // when the cursor moves within the textfield with the text 638 // when the cursor moves within the textfield with the text
471 // longer than the field. 639 // longer than the field.
472 text_offset_ = width - full_width; 640 text_offset_ = width - full_width;
473 } else { 641 } else {
474 // move cursor freely. 642 // move cursor freely.
475 } 643 }
476 // shift cursor bounds to fit insets. 644 // shift cursor bounds to fit insets.
477 cursor_bounds_.set_x(cursor_bounds_.x() + text_offset_ + insets.left()); 645 cursor_bounds_.set_x(cursor_bounds_.x() + text_offset_ + insets.left());
646
647 OnCaretBoundsChanged();
478 } 648 }
479 649
480 void NativeTextfieldViews::PaintTextAndCursor(gfx::Canvas* canvas) { 650 void NativeTextfieldViews::PaintTextAndCursor(gfx::Canvas* canvas) {
481 gfx::Insets insets = GetInsets(); 651 gfx::Insets insets = GetInsets();
482 652
483 canvas->Save(); 653 canvas->Save();
484 canvas->ClipRectInt(insets.left(), insets.top(), 654 canvas->ClipRectInt(insets.left(), insets.top(),
485 width() - insets.width(), height() - insets.height()); 655 width() - insets.width(), height() - insets.height());
486 656
487 // TODO(oshima): bidi support 657 // TODO(oshima): bidi support
488 // TODO(varunjain): re-implement this so only that dirty text is painted. 658 // TODO(varunjain): re-implement this so only that dirty text is painted.
489 TextfieldViewsModel::TextFragments fragments; 659 TextfieldViewsModel::TextFragments fragments;
490 model_->GetFragments(&fragments); 660 model_->GetFragments(&fragments);
491 int x_offset = text_offset_ + insets.left(); 661 int x_offset = text_offset_ + insets.left();
492 int y = insets.top(); 662 int y = insets.top();
493 int text_height = height() - insets.height(); 663 int text_height = height() - insets.height();
494 SkColor selection_color = 664 SkColor selection_color =
495 textfield_->HasFocus() ? 665 textfield_->HasFocus() ?
496 kFocusedSelectionColor : kUnfocusedSelectionColor; 666 kFocusedSelectionColor : kUnfocusedSelectionColor;
497 SkColor text_color = 667 SkColor text_color =
498 textfield_->read_only() ? kReadonlyTextColor : GetTextColor(); 668 textfield_->read_only() ? kReadonlyTextColor : GetTextColor();
499 669
500 for (TextfieldViewsModel::TextFragments::const_iterator iter = 670 for (TextfieldViewsModel::TextFragments::const_iterator iter =
501 fragments.begin(); 671 fragments.begin();
502 iter != fragments.end(); 672 iter != fragments.end();
503 iter++) { 673 iter++) {
504 string16 text = model_->GetVisibleText((*iter).begin, (*iter).end); 674 string16 text = model_->GetVisibleText(iter->start, iter->end);
675
676 gfx::Font font = GetFont();
677 if (iter->underline)
678 font = font.DeriveFont(0, font.GetStyle() | gfx::Font::UNDERLINED);
679
505 // TODO(oshima): This does not give the accurate position due to 680 // TODO(oshima): This does not give the accurate position due to
506 // kerning. Figure out how webkit does this with skia. 681 // kerning. Figure out how webkit does this with skia.
507 int width = GetFont().GetStringWidth(text); 682 int width = font.GetStringWidth(text);
508 683
509 if ((*iter).selected) { 684 if (iter->selected) {
510 canvas->FillRectInt(selection_color, x_offset, y, width, text_height); 685 canvas->FillRectInt(selection_color, x_offset, y, width, text_height);
511 canvas->DrawStringInt(text, GetFont(), kSelectedTextColor, 686 canvas->DrawStringInt(text, font, kSelectedTextColor,
512 x_offset, y, width, text_height); 687 x_offset, y, width, text_height);
513 } else { 688 } else {
514 canvas->DrawStringInt(text, GetFont(), text_color, 689 canvas->DrawStringInt(text, font, text_color,
515 x_offset, y, width, text_height); 690 x_offset, y, width, text_height);
516 } 691 }
517 x_offset += width; 692 x_offset += width;
518 } 693 }
519 canvas->Restore(); 694 canvas->Restore();
520 695
521 if (textfield_->IsEnabled() && is_cursor_visible_ && 696 if (textfield_->IsEnabled() && is_cursor_visible_ &&
522 !model_->HasSelection()) { 697 !model_->HasSelection()) {
523 // Paint Cursor. Replace cursor is drawn as rectangle for now. 698 // Paint Cursor. Replace cursor is drawn as rectangle for now.
524 canvas->DrawRectInt(kCursorColor, 699 canvas->DrawRectInt(kCursorColor,
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
570 case ui::VKEY_LEFT: 745 case ui::VKEY_LEFT:
571 control ? model_->MoveCursorToPreviousWord(selection) 746 control ? model_->MoveCursorToPreviousWord(selection)
572 : model_->MoveCursorLeft(selection); 747 : model_->MoveCursorLeft(selection);
573 cursor_changed = true; 748 cursor_changed = true;
574 break; 749 break;
575 case ui::VKEY_END: 750 case ui::VKEY_END:
576 model_->MoveCursorToEnd(selection); 751 model_->MoveCursorToEnd(selection);
577 cursor_changed = true; 752 cursor_changed = true;
578 break; 753 break;
579 case ui::VKEY_HOME: 754 case ui::VKEY_HOME:
580 model_->MoveCursorToStart(selection); 755 model_->MoveCursorToHome(selection);
581 cursor_changed = true; 756 cursor_changed = true;
582 break; 757 break;
583 case ui::VKEY_BACK: 758 case ui::VKEY_BACK:
584 if (!editable) 759 if (!editable)
585 break; 760 break;
586 if (!model_->HasSelection()) { 761 if (!model_->HasSelection()) {
587 if (selection && control) { 762 if (selection && control) {
588 // If both shift and control are pressed, then erase upto the 763 // If both shift and control are pressed, then erase upto the
589 // beginning of the buffer in ChromeOS. In windows, do nothing. 764 // beginning of the buffer in ChromeOS. In windows, do nothing.
590 #if defined(OS_WIN) 765 #if defined(OS_WIN)
591 break; 766 break;
592 #else 767 #else
593 model_->MoveCursorToStart(true); 768 model_->MoveCursorToHome(true);
594 #endif 769 #endif
595 } else if (control) { 770 } else if (control) {
596 // If only control is pressed, then erase the previous word. 771 // If only control is pressed, then erase the previous word.
597 model_->MoveCursorToPreviousWord(true); 772 model_->MoveCursorToPreviousWord(true);
598 } 773 }
599 } 774 }
600 text_changed = model_->Backspace(); 775 text_changed = model_->Backspace();
601 cursor_changed = true; 776 cursor_changed = true;
602 break; 777 break;
603 case ui::VKEY_DELETE: 778 case ui::VKEY_DELETE:
(...skipping 15 matching lines...) Expand all
619 } 794 }
620 cursor_changed = text_changed = model_->Delete(); 795 cursor_changed = text_changed = model_->Delete();
621 break; 796 break;
622 case ui::VKEY_INSERT: 797 case ui::VKEY_INSERT:
623 insert_ = !insert_; 798 insert_ = !insert_;
624 cursor_changed = true; 799 cursor_changed = true;
625 break; 800 break;
626 default: 801 default:
627 break; 802 break;
628 } 803 }
629 char16 ch = key_event.GetCharacter(); 804
630 if (editable && ShouldInsertChar(ch, key_event.flags())) { 805 // We must have input method in order to support text input.
631 if (insert_) 806 DCHECK(textfield_->GetInputMethod());
632 model_->Insert(ch);
633 else
634 model_->Replace(ch);
635 text_changed = true;
636 }
637 807
638 UpdateAfterChange(text_changed, cursor_changed); 808 UpdateAfterChange(text_changed, cursor_changed);
639 OnAfterUserAction(); 809 OnAfterUserAction();
640 return (text_changed || cursor_changed); 810 return (text_changed || cursor_changed);
641 } 811 }
642 return false; 812 return false;
643 } 813 }
644 814
645 size_t NativeTextfieldViews::FindCursorPosition(const gfx::Point& point) const { 815 size_t NativeTextfieldViews::FindCursorPosition(const gfx::Point& point) const {
646 // TODO(oshima): BIDI/i18n support. 816 // TODO(oshima): BIDI/i18n support.
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
710 880
711 void NativeTextfieldViews::SetCursorForMouseClick(const views::MouseEvent& e) { 881 void NativeTextfieldViews::SetCursorForMouseClick(const views::MouseEvent& e) {
712 size_t pos = FindCursorPosition(e.location()); 882 size_t pos = FindCursorPosition(e.location());
713 if (model_->MoveCursorTo(pos, false)) { 883 if (model_->MoveCursorTo(pos, false)) {
714 UpdateCursorBoundsAndTextOffset(); 884 UpdateCursorBoundsAndTextOffset();
715 } 885 }
716 } 886 }
717 887
718 void NativeTextfieldViews::PropagateTextChange() { 888 void NativeTextfieldViews::PropagateTextChange() {
719 textfield_->SyncText(); 889 textfield_->SyncText();
720 TextfieldController* controller = textfield_->GetController();
721 if (controller)
722 controller->ContentsChanged(textfield_, GetText());
723 } 890 }
724 891
725 void NativeTextfieldViews::UpdateAfterChange(bool text_changed, 892 void NativeTextfieldViews::UpdateAfterChange(bool text_changed,
726 bool cursor_changed) { 893 bool cursor_changed) {
727 if (text_changed) 894 if (text_changed)
728 PropagateTextChange(); 895 PropagateTextChange();
729 if (cursor_changed) { 896 if (cursor_changed) {
730 is_cursor_visible_ = true; 897 is_cursor_visible_ = true;
731 RepaintCursor(); 898 RepaintCursor();
732 } 899 }
(...skipping 10 matching lines...) Expand all
743 context_menu_contents_->AddItemWithStringId(IDS_APP_CUT, IDS_APP_CUT); 910 context_menu_contents_->AddItemWithStringId(IDS_APP_CUT, IDS_APP_CUT);
744 context_menu_contents_->AddItemWithStringId(IDS_APP_COPY, IDS_APP_COPY); 911 context_menu_contents_->AddItemWithStringId(IDS_APP_COPY, IDS_APP_COPY);
745 context_menu_contents_->AddItemWithStringId(IDS_APP_PASTE, IDS_APP_PASTE); 912 context_menu_contents_->AddItemWithStringId(IDS_APP_PASTE, IDS_APP_PASTE);
746 context_menu_contents_->AddItemWithStringId(IDS_APP_DELETE, IDS_APP_DELETE); 913 context_menu_contents_->AddItemWithStringId(IDS_APP_DELETE, IDS_APP_DELETE);
747 context_menu_contents_->AddSeparator(); 914 context_menu_contents_->AddSeparator();
748 context_menu_contents_->AddItemWithStringId(IDS_APP_SELECT_ALL, 915 context_menu_contents_->AddItemWithStringId(IDS_APP_SELECT_ALL,
749 IDS_APP_SELECT_ALL); 916 IDS_APP_SELECT_ALL);
750 context_menu_menu_.reset(new Menu2(context_menu_contents_.get())); 917 context_menu_menu_.reset(new Menu2(context_menu_contents_.get()));
751 } 918 }
752 919
920 void NativeTextfieldViews::OnTextInputTypeChanged() {
921 DCHECK(textfield_->GetInputMethod());
922 textfield_->GetInputMethod()->OnTextInputTypeChanged(textfield_);
923 }
924
925 void NativeTextfieldViews::OnCaretBoundsChanged() {
926 DCHECK(textfield_->GetInputMethod());
927 textfield_->GetInputMethod()->OnCaretBoundsChanged(textfield_);
928 }
929
753 void NativeTextfieldViews::OnBeforeUserAction() { 930 void NativeTextfieldViews::OnBeforeUserAction() {
754 TextfieldController* controller = textfield_->GetController(); 931 TextfieldController* controller = textfield_->GetController();
755 if (controller) 932 if (controller)
756 controller->OnBeforeUserAction(textfield_); 933 controller->OnBeforeUserAction(textfield_);
757 } 934 }
758 935
759 void NativeTextfieldViews::OnAfterUserAction() { 936 void NativeTextfieldViews::OnAfterUserAction() {
760 TextfieldController* controller = textfield_->GetController(); 937 TextfieldController* controller = textfield_->GetController();
761 if (controller) 938 if (controller)
762 controller->OnAfterUserAction(textfield_); 939 controller->OnAfterUserAction(textfield_);
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
821 } 998 }
822 999
823 void NativeTextfieldViews::TextfieldBorder::SetInsets(int top, 1000 void NativeTextfieldViews::TextfieldBorder::SetInsets(int top,
824 int left, 1001 int left,
825 int bottom, 1002 int bottom,
826 int right) { 1003 int right) {
827 insets_.Set(top, left, bottom, right); 1004 insets_.Set(top, left, bottom, right);
828 } 1005 }
829 1006
830 } // namespace views 1007 } // namespace views
OLDNEW
« no previous file with comments | « views/controls/textfield/native_textfield_views.h ('k') | views/controls/textfield/native_textfield_views_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698