OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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" |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
50 "views/NativeTextfieldViews"; | 50 "views/NativeTextfieldViews"; |
51 | 51 |
52 NativeTextfieldViews::NativeTextfieldViews(Textfield* parent) | 52 NativeTextfieldViews::NativeTextfieldViews(Textfield* parent) |
53 : textfield_(parent), | 53 : textfield_(parent), |
54 model_(new TextfieldViewsModel()), | 54 model_(new TextfieldViewsModel()), |
55 text_border_(new TextfieldBorder()), | 55 text_border_(new TextfieldBorder()), |
56 text_offset_(0), | 56 text_offset_(0), |
57 insert_(true), | 57 insert_(true), |
58 is_cursor_visible_(false), | 58 is_cursor_visible_(false), |
59 ALLOW_THIS_IN_INITIALIZER_LIST(cursor_timer_(this)) { | 59 ALLOW_THIS_IN_INITIALIZER_LIST(cursor_timer_(this)) { |
60 SetFocusable(true); | |
61 set_border(text_border_); | 60 set_border(text_border_); |
62 | 61 |
63 // Multiline is not supported. | 62 // Multiline is not supported. |
64 DCHECK_NE(parent->style(), Textfield::STYLE_MULTILINE); | 63 DCHECK_NE(parent->style(), Textfield::STYLE_MULTILINE); |
65 // Lowercase is not supported. | 64 // Lowercase is not supported. |
66 DCHECK_NE(parent->style(), Textfield::STYLE_LOWERCASE); | 65 DCHECK_NE(parent->style(), Textfield::STYLE_LOWERCASE); |
67 } | 66 } |
68 | 67 |
69 NativeTextfieldViews::~NativeTextfieldViews() { | 68 NativeTextfieldViews::~NativeTextfieldViews() { |
70 } | 69 } |
71 | 70 |
72 //////////////////////////////////////////////////////////////////////////////// | 71 //////////////////////////////////////////////////////////////////////////////// |
73 // NativeTextfieldViews, View overrides: | 72 // NativeTextfieldViews, View overrides: |
74 | 73 |
75 bool NativeTextfieldViews::OnMousePressed(const views::MouseEvent& e) { | 74 bool NativeTextfieldViews::OnMousePressed(const views::MouseEvent& e) { |
76 RequestFocus(); | 75 textfield_->RequestFocus(); |
77 size_t pos = FindCursorPosition(e.location()); | 76 size_t pos = FindCursorPosition(e.location()); |
78 if (model_->MoveCursorTo(pos, false)) { | 77 if (model_->MoveCursorTo(pos, false)) { |
79 UpdateCursorBoundsAndTextOffset(); | 78 UpdateCursorBoundsAndTextOffset(); |
80 SchedulePaint(); | 79 SchedulePaint(); |
81 } | 80 } |
82 return true; | 81 return true; |
83 } | 82 } |
84 | 83 |
85 bool NativeTextfieldViews::OnMouseDragged(const views::MouseEvent& e) { | 84 bool NativeTextfieldViews::OnMouseDragged(const views::MouseEvent& e) { |
86 size_t pos = FindCursorPosition(e.location()); | 85 size_t pos = FindCursorPosition(e.location()); |
87 if (model_->MoveCursorTo(pos, true)) { | 86 if (model_->MoveCursorTo(pos, true)) { |
88 UpdateCursorBoundsAndTextOffset(); | 87 UpdateCursorBoundsAndTextOffset(); |
89 SchedulePaint(); | 88 SchedulePaint(); |
90 } | 89 } |
91 return true; | 90 return true; |
92 } | 91 } |
93 | 92 |
94 void NativeTextfieldViews::OnMouseReleased(const views::MouseEvent& e, | 93 void NativeTextfieldViews::OnMouseReleased(const views::MouseEvent& e, |
95 bool canceled) { | 94 bool canceled) { |
96 } | 95 } |
97 | 96 |
98 bool NativeTextfieldViews::OnKeyPressed(const views::KeyEvent& e) { | 97 bool NativeTextfieldViews::OnKeyPressed(const views::KeyEvent& e) { |
99 Textfield::Controller* controller = textfield_->GetController(); | 98 // OnKeyPressed/OnKeyReleased/WillGainFocus/DidGainFocus/WillLoseFocus |
100 bool handled = false; | 99 // will never be invoked on NativeTextfieldViews as it will never |
101 if (controller) | 100 // gain focus. |
102 handled = controller->HandleKeyEvent(textfield_, e); | 101 NOTREACHED(); |
103 return handled || HandleKeyEvent(e); | 102 return false; |
104 } | 103 } |
105 | 104 |
106 bool NativeTextfieldViews::OnKeyReleased(const views::KeyEvent& e) { | 105 bool NativeTextfieldViews::OnKeyReleased(const views::KeyEvent& e) { |
107 return true; | 106 NOTREACHED(); |
| 107 return false; |
108 } | 108 } |
109 | 109 |
110 void NativeTextfieldViews::Paint(gfx::Canvas* canvas) { | 110 void NativeTextfieldViews::Paint(gfx::Canvas* canvas) { |
111 text_border_->set_has_focus(HasFocus()); | 111 text_border_->set_has_focus(textfield_->HasFocus()); |
112 PaintBackground(canvas); | 112 PaintBackground(canvas); |
113 PaintTextAndCursor(canvas); | 113 PaintTextAndCursor(canvas); |
114 if (textfield_->draw_border()) | 114 if (textfield_->draw_border()) |
115 PaintBorder(canvas); | 115 PaintBorder(canvas); |
116 } | 116 } |
117 | 117 |
| 118 void NativeTextfieldViews::DidChangeBounds(const gfx::Rect& previous, |
| 119 const gfx::Rect& current) { |
| 120 UpdateCursorBoundsAndTextOffset(); |
| 121 } |
| 122 |
118 void NativeTextfieldViews::WillGainFocus() { | 123 void NativeTextfieldViews::WillGainFocus() { |
| 124 NOTREACHED(); |
119 } | 125 } |
120 | 126 |
121 void NativeTextfieldViews::DidGainFocus() { | 127 void NativeTextfieldViews::DidGainFocus() { |
122 is_cursor_visible_ = true; | 128 NOTREACHED(); |
123 SchedulePaint(); | |
124 // Start blinking cursor. | |
125 MessageLoop::current()->PostDelayedTask( | |
126 FROM_HERE, | |
127 cursor_timer_.NewRunnableMethod(&NativeTextfieldViews::UpdateCursor), | |
128 kCursorVisibleTimeMs); | |
129 } | 129 } |
130 | 130 |
131 void NativeTextfieldViews::WillLoseFocus() { | 131 void NativeTextfieldViews::WillLoseFocus() { |
132 // Stop blinking cursor. | 132 NOTREACHED(); |
133 cursor_timer_.RevokeAll(); | |
134 if (is_cursor_visible_) { | |
135 is_cursor_visible_ = false; | |
136 RepaintCursor(); | |
137 } | |
138 } | |
139 | |
140 void NativeTextfieldViews::DidChangeBounds(const gfx::Rect& previous, | |
141 const gfx::Rect& current) { | |
142 UpdateCursorBoundsAndTextOffset(); | |
143 } | 133 } |
144 | 134 |
145 ///////////////////////////////////////////////////////////////// | 135 ///////////////////////////////////////////////////////////////// |
146 // NativeTextfieldViews, NativeTextifieldWrapper overrides: | 136 // NativeTextfieldViews, NativeTextifieldWrapper overrides: |
147 | 137 |
148 string16 NativeTextfieldViews::GetText() const { | 138 string16 NativeTextfieldViews::GetText() const { |
149 return model_->text(); | 139 return model_->text(); |
150 } | 140 } |
151 | 141 |
152 void NativeTextfieldViews::UpdateText() { | 142 void NativeTextfieldViews::UpdateText() { |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
216 UpdateCursorBoundsAndTextOffset(); | 206 UpdateCursorBoundsAndTextOffset(); |
217 } | 207 } |
218 | 208 |
219 void NativeTextfieldViews::UpdateIsPassword() { | 209 void NativeTextfieldViews::UpdateIsPassword() { |
220 model_->set_is_password(textfield_->IsPassword()); | 210 model_->set_is_password(textfield_->IsPassword()); |
221 UpdateCursorBoundsAndTextOffset(); | 211 UpdateCursorBoundsAndTextOffset(); |
222 SchedulePaint(); | 212 SchedulePaint(); |
223 } | 213 } |
224 | 214 |
225 void NativeTextfieldViews::UpdateEnabled() { | 215 void NativeTextfieldViews::UpdateEnabled() { |
| 216 SetEnabled(textfield_->IsEnabled()); |
226 SchedulePaint(); | 217 SchedulePaint(); |
227 } | 218 } |
228 | 219 |
229 bool NativeTextfieldViews::IsPassword() { | |
230 // looks unnecessary. should we remove? | |
231 NOTREACHED(); | |
232 return false; | |
233 } | |
234 | |
235 gfx::Insets NativeTextfieldViews::CalculateInsets() { | 220 gfx::Insets NativeTextfieldViews::CalculateInsets() { |
236 return GetInsets(); | 221 return GetInsets(); |
237 } | 222 } |
238 | 223 |
239 void NativeTextfieldViews::UpdateHorizontalMargins() { | 224 void NativeTextfieldViews::UpdateHorizontalMargins() { |
240 int left, right; | 225 int left, right; |
241 if (!textfield_->GetHorizontalMargins(&left, &right)) | 226 if (!textfield_->GetHorizontalMargins(&left, &right)) |
242 return; | 227 return; |
243 gfx::Insets inset = GetInsets(); | 228 gfx::Insets inset = GetInsets(); |
244 | 229 |
245 text_border_->SetInsets(inset.top(), left, inset.bottom(), right); | 230 text_border_->SetInsets(inset.top(), left, inset.bottom(), right); |
246 UpdateCursorBoundsAndTextOffset(); | 231 UpdateCursorBoundsAndTextOffset(); |
247 } | 232 } |
248 | 233 |
249 void NativeTextfieldViews::UpdateVerticalMargins() { | 234 void NativeTextfieldViews::UpdateVerticalMargins() { |
250 int top, bottom; | 235 int top, bottom; |
251 if (!textfield_->GetVerticalMargins(&top, &bottom)) | 236 if (!textfield_->GetVerticalMargins(&top, &bottom)) |
252 return; | 237 return; |
253 gfx::Insets inset = GetInsets(); | 238 gfx::Insets inset = GetInsets(); |
254 | 239 |
255 text_border_->SetInsets(top, inset.left(), bottom, inset.right()); | 240 text_border_->SetInsets(top, inset.left(), bottom, inset.right()); |
256 UpdateCursorBoundsAndTextOffset(); | 241 UpdateCursorBoundsAndTextOffset(); |
257 } | 242 } |
258 | 243 |
259 void NativeTextfieldViews::SetFocus() { | 244 bool NativeTextfieldViews::SetFocus() { |
260 RequestFocus(); | 245 return false; |
261 } | 246 } |
262 | 247 |
263 View* NativeTextfieldViews::GetView() { | 248 View* NativeTextfieldViews::GetView() { |
264 return this; | 249 return this; |
265 } | 250 } |
266 | 251 |
267 gfx::NativeView NativeTextfieldViews::GetTestingHandle() const { | 252 gfx::NativeView NativeTextfieldViews::GetTestingHandle() const { |
268 NOTREACHED(); | 253 NOTREACHED(); |
269 return NULL; | 254 return NULL; |
270 } | 255 } |
271 | 256 |
272 bool NativeTextfieldViews::IsIMEComposing() const { | 257 bool NativeTextfieldViews::IsIMEComposing() const { |
273 return false; | 258 return false; |
274 } | 259 } |
275 | 260 |
| 261 bool NativeTextfieldViews::HandleKeyPressed(const views::KeyEvent& e) { |
| 262 Textfield::Controller* controller = textfield_->GetController(); |
| 263 bool handled = false; |
| 264 if (controller) { |
| 265 handled = controller->HandleKeyEvent(textfield_, e); |
| 266 } |
| 267 return handled || HandleKeyEvent(e); |
| 268 } |
| 269 |
| 270 bool NativeTextfieldViews::HandleKeyReleased(const views::KeyEvent& e) { |
| 271 return true; |
| 272 } |
| 273 |
| 274 void NativeTextfieldViews::HandleWillGainFocus() { |
| 275 } |
| 276 |
| 277 void NativeTextfieldViews::HandleDidGainFocus() { |
| 278 is_cursor_visible_ = true; |
| 279 SchedulePaint(); |
| 280 // Start blinking cursor. |
| 281 MessageLoop::current()->PostDelayedTask( |
| 282 FROM_HERE, |
| 283 cursor_timer_.NewRunnableMethod(&NativeTextfieldViews::UpdateCursor), |
| 284 kCursorVisibleTimeMs); |
| 285 } |
| 286 |
| 287 void NativeTextfieldViews::HandleWillLoseFocus() { |
| 288 // Stop blinking cursor. |
| 289 cursor_timer_.RevokeAll(); |
| 290 if (is_cursor_visible_) { |
| 291 is_cursor_visible_ = false; |
| 292 RepaintCursor(); |
| 293 } |
| 294 } |
| 295 |
276 // static | 296 // static |
277 bool NativeTextfieldViews::IsTextfieldViewsEnabled() { | 297 bool NativeTextfieldViews::IsTextfieldViewsEnabled() { |
278 #if defined(TOUCH_UI) | 298 #if defined(TOUCH_UI) |
279 return true; | 299 return true; |
280 #else | 300 #else |
281 return textfield_view_enabled || | 301 return textfield_view_enabled || |
282 CommandLine::ForCurrentProcess()->HasSwitch( | 302 CommandLine::ForCurrentProcess()->HasSwitch( |
283 kEnableViewsBasedTextfieldSwitch); | 303 kEnableViewsBasedTextfieldSwitch); |
284 #endif | 304 #endif |
285 } | 305 } |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
361 width() - insets.width(), height() - insets.height()); | 381 width() - insets.width(), height() - insets.height()); |
362 | 382 |
363 // TODO(oshima): bidi support | 383 // TODO(oshima): bidi support |
364 // TODO(varunjain): re-implement this so only that dirty text is painted. | 384 // TODO(varunjain): re-implement this so only that dirty text is painted. |
365 TextfieldViewsModel::TextFragments fragments; | 385 TextfieldViewsModel::TextFragments fragments; |
366 model_->GetFragments(&fragments); | 386 model_->GetFragments(&fragments); |
367 int x_offset = text_offset_ + insets.left(); | 387 int x_offset = text_offset_ + insets.left(); |
368 int y = insets.top(); | 388 int y = insets.top(); |
369 int text_height = height() - insets.height(); | 389 int text_height = height() - insets.height(); |
370 SkColor selection_color = | 390 SkColor selection_color = |
371 HasFocus() ? kFocusedSelectionColor : kUnfocusedSelectionColor; | 391 textfield_->HasFocus() ? |
| 392 kFocusedSelectionColor : kUnfocusedSelectionColor; |
372 SkColor text_color = | 393 SkColor text_color = |
373 textfield_->read_only() ? kReadonlyTextColor : GetTextColor(); | 394 textfield_->read_only() ? kReadonlyTextColor : GetTextColor(); |
374 | 395 |
375 for (TextfieldViewsModel::TextFragments::const_iterator iter = | 396 for (TextfieldViewsModel::TextFragments::const_iterator iter = |
376 fragments.begin(); | 397 fragments.begin(); |
377 iter != fragments.end(); | 398 iter != fragments.end(); |
378 iter++) { | 399 iter++) { |
379 string16 text = model_->GetVisibleText((*iter).begin, (*iter).end); | 400 string16 text = model_->GetVisibleText((*iter).begin, (*iter).end); |
380 // TODO(oshima): This does not give the accurate position due to | 401 // TODO(oshima): This does not give the accurate position due to |
381 // kerning. Figure out how webkit does this with skia. | 402 // kerning. Figure out how webkit does this with skia. |
(...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
693 } | 714 } |
694 | 715 |
695 void NativeTextfieldViews::TextfieldBorder::SetInsets(int top, | 716 void NativeTextfieldViews::TextfieldBorder::SetInsets(int top, |
696 int left, | 717 int left, |
697 int bottom, | 718 int bottom, |
698 int right) { | 719 int right) { |
699 insets_.Set(top, left, bottom, right); | 720 insets_.Set(top, left, bottom, right); |
700 } | 721 } |
701 | 722 |
702 } // namespace views | 723 } // namespace views |
OLD | NEW |