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

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

Issue 115825: Move text_field.cc and rename the class to Textfield in preparation for porti... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 11 years, 7 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
« no previous file with comments | « views/controls/textfield/textfield.h ('k') | views/focus/focus_manager_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2009 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/text_field.h" 5 #include "views/controls/textfield/textfield.h"
6 6
7 #include <atlbase.h> 7 #include <atlbase.h>
8 #include <atlapp.h> 8 #include <atlapp.h>
9 #include <atlcrack.h> 9 #include <atlcrack.h>
10 #include <atlctrls.h> 10 #include <atlctrls.h>
11 #include <atlmisc.h> 11 #include <atlmisc.h>
12 #include <tom.h> // For ITextDocument, a COM interface to CRichEditCtrl 12 #include <tom.h> // For ITextDocument, a COM interface to CRichEditCtrl
13 #include <vsstyle.h> 13 #include <vsstyle.h>
14 14
15 #include "app/gfx/insets.h" 15 #include "app/gfx/insets.h"
(...skipping 12 matching lines...) Expand all
28 #include "views/focus/focus_util_win.h" 28 #include "views/focus/focus_util_win.h"
29 #include "views/views_delegate.h" 29 #include "views/views_delegate.h"
30 #include "views/widget/widget.h" 30 #include "views/widget/widget.h"
31 31
32 using gfx::NativeTheme; 32 using gfx::NativeTheme;
33 33
34 namespace views { 34 namespace views {
35 35
36 static const int kDefaultEditStyle = WS_CHILD | WS_VISIBLE; 36 static const int kDefaultEditStyle = WS_CHILD | WS_VISIBLE;
37 37
38 class TextField::Edit 38 class Textfield::Edit
39 : public CWindowImpl<TextField::Edit, CRichEditCtrl, 39 : public CWindowImpl<Textfield::Edit, CRichEditCtrl,
40 CWinTraits<kDefaultEditStyle> >, 40 CWinTraits<kDefaultEditStyle> >,
41 public CRichEditCommands<TextField::Edit>, 41 public CRichEditCommands<Textfield::Edit>,
42 public Menu::Delegate { 42 public Menu::Delegate {
43 public: 43 public:
44 DECLARE_WND_CLASS(L"ChromeViewsTextFieldEdit"); 44 DECLARE_WND_CLASS(L"ChromeViewsTextfieldEdit");
45 45
46 Edit(TextField* parent, bool draw_border); 46 Edit(Textfield* parent, bool draw_border);
47 ~Edit(); 47 ~Edit();
48 48
49 std::wstring GetText() const; 49 std::wstring GetText() const;
50 void SetText(const std::wstring& text); 50 void SetText(const std::wstring& text);
51 void AppendText(const std::wstring& text); 51 void AppendText(const std::wstring& text);
52 52
53 std::wstring GetSelectedText() const; 53 std::wstring GetSelectedText() const;
54 54
55 // Selects all the text in the edit. Use this in place of SetSelAll() to 55 // Selects all the text in the edit. Use this in place of SetSelAll() to
56 // avoid selecting the "phantom newline" at the end of the edit. 56 // avoid selecting the "phantom newline" at the end of the edit.
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
179 bool can_discard_mousemove_; 179 bool can_discard_mousemove_;
180 180
181 // The text of this control before a possible change. 181 // The text of this control before a possible change.
182 std::wstring text_before_change_; 182 std::wstring text_before_change_;
183 183
184 // If true, the mouse is over the edit. 184 // If true, the mouse is over the edit.
185 bool contains_mouse_; 185 bool contains_mouse_;
186 186
187 static bool did_load_library_; 187 static bool did_load_library_;
188 188
189 TextField* parent_; 189 Textfield* parent_;
190 190
191 // The context menu for the edit. 191 // The context menu for the edit.
192 scoped_ptr<Menu> context_menu_; 192 scoped_ptr<Menu> context_menu_;
193 193
194 // Border insets. 194 // Border insets.
195 gfx::Insets content_insets_; 195 gfx::Insets content_insets_;
196 196
197 // Whether the border is drawn. 197 // Whether the border is drawn.
198 bool draw_border_; 198 bool draw_border_;
199 199
200 // This interface is useful for accessing the CRichEditCtrl at a low level. 200 // This interface is useful for accessing the CRichEditCtrl at a low level.
201 mutable CComQIPtr<ITextDocument> text_object_model_; 201 mutable CComQIPtr<ITextDocument> text_object_model_;
202 202
203 // The position and the length of the ongoing composition string. 203 // The position and the length of the ongoing composition string.
204 // These values are used for removing a composition string from a search 204 // These values are used for removing a composition string from a search
205 // text to emulate Firefox. 205 // text to emulate Firefox.
206 bool ime_discard_composition_; 206 bool ime_discard_composition_;
207 int ime_composition_start_; 207 int ime_composition_start_;
208 int ime_composition_length_; 208 int ime_composition_length_;
209 209
210 COLORREF bg_color_; 210 COLORREF bg_color_;
211 211
212 DISALLOW_COPY_AND_ASSIGN(Edit); 212 DISALLOW_COPY_AND_ASSIGN(Edit);
213 }; 213 };
214 214
215 /////////////////////////////////////////////////////////////////////////////// 215 ///////////////////////////////////////////////////////////////////////////////
216 // Helper classes 216 // Helper classes
217 217
218 TextField::Edit::ScopedFreeze::ScopedFreeze(TextField::Edit* edit, 218 Textfield::Edit::ScopedFreeze::ScopedFreeze(Textfield::Edit* edit,
219 ITextDocument* text_object_model) 219 ITextDocument* text_object_model)
220 : edit_(edit), 220 : edit_(edit),
221 text_object_model_(text_object_model) { 221 text_object_model_(text_object_model) {
222 // Freeze the screen. 222 // Freeze the screen.
223 if (text_object_model_) { 223 if (text_object_model_) {
224 long count; 224 long count;
225 text_object_model_->Freeze(&count); 225 text_object_model_->Freeze(&count);
226 } 226 }
227 } 227 }
228 228
229 TextField::Edit::ScopedFreeze::~ScopedFreeze() { 229 Textfield::Edit::ScopedFreeze::~ScopedFreeze() {
230 // Unfreeze the screen. 230 // Unfreeze the screen.
231 if (text_object_model_) { 231 if (text_object_model_) {
232 long count; 232 long count;
233 text_object_model_->Unfreeze(&count); 233 text_object_model_->Unfreeze(&count);
234 if (count == 0) { 234 if (count == 0) {
235 // We need to UpdateWindow() here instead of InvalidateRect() because, as 235 // We need to UpdateWindow() here instead of InvalidateRect() because, as
236 // far as I can tell, the edit likes to synchronously erase its background 236 // far as I can tell, the edit likes to synchronously erase its background
237 // when unfreezing, thus requiring us to synchronously redraw if we don't 237 // when unfreezing, thus requiring us to synchronously redraw if we don't
238 // want flicker. 238 // want flicker.
239 edit_->UpdateWindow(); 239 edit_->UpdateWindow();
240 } 240 }
241 } 241 }
242 } 242 }
243 243
244 /////////////////////////////////////////////////////////////////////////////// 244 ///////////////////////////////////////////////////////////////////////////////
245 // TextField::Edit 245 // Textfield::Edit
246 246
247 bool TextField::Edit::did_load_library_ = false; 247 bool Textfield::Edit::did_load_library_ = false;
248 248
249 TextField::Edit::Edit(TextField* parent, bool draw_border) 249 Textfield::Edit::Edit(Textfield* parent, bool draw_border)
250 : parent_(parent), 250 : parent_(parent),
251 tracking_double_click_(false), 251 tracking_double_click_(false),
252 double_click_time_(0), 252 double_click_time_(0),
253 can_discard_mousemove_(false), 253 can_discard_mousemove_(false),
254 contains_mouse_(false), 254 contains_mouse_(false),
255 draw_border_(draw_border), 255 draw_border_(draw_border),
256 ime_discard_composition_(false), 256 ime_discard_composition_(false),
257 ime_composition_start_(0), 257 ime_composition_start_(0),
258 ime_composition_length_(0), 258 ime_composition_length_(0),
259 bg_color_(0) { 259 bg_color_(0) {
260 if (!did_load_library_) 260 if (!did_load_library_)
261 did_load_library_ = !!LoadLibrary(L"riched20.dll"); 261 did_load_library_ = !!LoadLibrary(L"riched20.dll");
262 262
263 DWORD style = kDefaultEditStyle; 263 DWORD style = kDefaultEditStyle;
264 if (parent->GetStyle() & TextField::STYLE_PASSWORD) 264 if (parent->GetStyle() & Textfield::STYLE_PASSWORD)
265 style |= ES_PASSWORD; 265 style |= ES_PASSWORD;
266 266
267 if (parent->read_only_) 267 if (parent->read_only_)
268 style |= ES_READONLY; 268 style |= ES_READONLY;
269 269
270 if (parent->GetStyle() & TextField::STYLE_MULTILINE) 270 if (parent->GetStyle() & Textfield::STYLE_MULTILINE)
271 style |= ES_MULTILINE | ES_WANTRETURN | ES_AUTOVSCROLL; 271 style |= ES_MULTILINE | ES_WANTRETURN | ES_AUTOVSCROLL;
272 else 272 else
273 style |= ES_AUTOHSCROLL; 273 style |= ES_AUTOHSCROLL;
274 // Make sure we apply RTL related extended window styles if necessary. 274 // Make sure we apply RTL related extended window styles if necessary.
275 DWORD ex_style = l10n_util::GetExtendedStyles(); 275 DWORD ex_style = l10n_util::GetExtendedStyles();
276 276
277 RECT r = {0, 0, parent_->width(), parent_->height()}; 277 RECT r = {0, 0, parent_->width(), parent_->height()};
278 Create(parent_->GetWidget()->GetNativeView(), r, NULL, style, ex_style); 278 Create(parent_->GetWidget()->GetNativeView(), r, NULL, style, ex_style);
279 279
280 if (parent->GetStyle() & TextField::STYLE_LOWERCASE) { 280 if (parent->GetStyle() & Textfield::STYLE_LOWERCASE) {
281 DCHECK((parent->GetStyle() & TextField::STYLE_PASSWORD) == 0); 281 DCHECK((parent->GetStyle() & Textfield::STYLE_PASSWORD) == 0);
282 SetEditStyle(SES_LOWERCASE, SES_LOWERCASE); 282 SetEditStyle(SES_LOWERCASE, SES_LOWERCASE);
283 } 283 }
284 284
285 // Set up the text_object_model_. 285 // Set up the text_object_model_.
286 CComPtr<IRichEditOle> ole_interface; 286 CComPtr<IRichEditOle> ole_interface;
287 ole_interface.Attach(GetOleInterface()); 287 ole_interface.Attach(GetOleInterface());
288 text_object_model_ = ole_interface; 288 text_object_model_ = ole_interface;
289 289
290 context_menu_.reset(new MenuWin(this, Menu::TOPLEFT, m_hWnd)); 290 context_menu_.reset(new MenuWin(this, Menu::TOPLEFT, m_hWnd));
291 context_menu_->AppendMenuItemWithLabel(IDS_APP_UNDO, 291 context_menu_->AppendMenuItemWithLabel(IDS_APP_UNDO,
292 l10n_util::GetString(IDS_APP_UNDO)); 292 l10n_util::GetString(IDS_APP_UNDO));
293 context_menu_->AppendSeparator(); 293 context_menu_->AppendSeparator();
294 context_menu_->AppendMenuItemWithLabel(IDS_APP_CUT, 294 context_menu_->AppendMenuItemWithLabel(IDS_APP_CUT,
295 l10n_util::GetString(IDS_APP_CUT)); 295 l10n_util::GetString(IDS_APP_CUT));
296 context_menu_->AppendMenuItemWithLabel(IDS_APP_COPY, 296 context_menu_->AppendMenuItemWithLabel(IDS_APP_COPY,
297 l10n_util::GetString(IDS_APP_COPY)); 297 l10n_util::GetString(IDS_APP_COPY));
298 context_menu_->AppendMenuItemWithLabel(IDS_APP_PASTE, 298 context_menu_->AppendMenuItemWithLabel(IDS_APP_PASTE,
299 l10n_util::GetString(IDS_APP_PASTE)); 299 l10n_util::GetString(IDS_APP_PASTE));
300 context_menu_->AppendSeparator(); 300 context_menu_->AppendSeparator();
301 context_menu_->AppendMenuItemWithLabel(IDS_APP_SELECT_ALL, 301 context_menu_->AppendMenuItemWithLabel(IDS_APP_SELECT_ALL,
302 l10n_util::GetString(IDS_APP_SELECT_ALL )); 302 l10n_util::GetString(IDS_APP_SELECT_ALL ));
303 } 303 }
304 304
305 TextField::Edit::~Edit() { 305 Textfield::Edit::~Edit() {
306 } 306 }
307 307
308 std::wstring TextField::Edit::GetText() const { 308 std::wstring Textfield::Edit::GetText() const {
309 int len = GetTextLength() + 1; 309 int len = GetTextLength() + 1;
310 std::wstring str; 310 std::wstring str;
311 GetWindowText(WriteInto(&str, len), len); 311 GetWindowText(WriteInto(&str, len), len);
312 return str; 312 return str;
313 } 313 }
314 314
315 void TextField::Edit::SetText(const std::wstring& text) { 315 void Textfield::Edit::SetText(const std::wstring& text) {
316 // Adjusting the string direction before setting the text in order to make 316 // Adjusting the string direction before setting the text in order to make
317 // sure both RTL and LTR strings are displayed properly. 317 // sure both RTL and LTR strings are displayed properly.
318 std::wstring text_to_set; 318 std::wstring text_to_set;
319 if (!l10n_util::AdjustStringForLocaleDirection(text, &text_to_set)) 319 if (!l10n_util::AdjustStringForLocaleDirection(text, &text_to_set))
320 text_to_set = text; 320 text_to_set = text;
321 if (parent_->GetStyle() & STYLE_LOWERCASE) 321 if (parent_->GetStyle() & STYLE_LOWERCASE)
322 text_to_set = l10n_util::ToLower(text_to_set); 322 text_to_set = l10n_util::ToLower(text_to_set);
323 SetWindowText(text_to_set.c_str()); 323 SetWindowText(text_to_set.c_str());
324 } 324 }
325 325
326 void TextField::Edit::AppendText(const std::wstring& text) { 326 void Textfield::Edit::AppendText(const std::wstring& text) {
327 int text_length = GetWindowTextLength(); 327 int text_length = GetWindowTextLength();
328 ::SendMessage(m_hWnd, TBM_SETSEL, true, MAKELPARAM(text_length, text_length)); 328 ::SendMessage(m_hWnd, TBM_SETSEL, true, MAKELPARAM(text_length, text_length));
329 ::SendMessage(m_hWnd, EM_REPLACESEL, false, 329 ::SendMessage(m_hWnd, EM_REPLACESEL, false,
330 reinterpret_cast<LPARAM>(text.c_str())); 330 reinterpret_cast<LPARAM>(text.c_str()));
331 } 331 }
332 332
333 std::wstring TextField::Edit::GetSelectedText() const { 333 std::wstring Textfield::Edit::GetSelectedText() const {
334 // Figure out the length of the selection. 334 // Figure out the length of the selection.
335 long start; 335 long start;
336 long end; 336 long end;
337 GetSel(start, end); 337 GetSel(start, end);
338 338
339 // Grab the selected text. 339 // Grab the selected text.
340 std::wstring str; 340 std::wstring str;
341 GetSelText(WriteInto(&str, end - start + 1)); 341 GetSelText(WriteInto(&str, end - start + 1));
342 342
343 return str; 343 return str;
344 } 344 }
345 345
346 void TextField::Edit::SelectAll() { 346 void Textfield::Edit::SelectAll() {
347 // Select from the end to the front so that the first part of the text is 347 // Select from the end to the front so that the first part of the text is
348 // always visible. 348 // always visible.
349 SetSel(GetTextLength(), 0); 349 SetSel(GetTextLength(), 0);
350 } 350 }
351 351
352 void TextField::Edit::ClearSelection() { 352 void Textfield::Edit::ClearSelection() {
353 SetSel(GetTextLength(), GetTextLength()); 353 SetSel(GetTextLength(), GetTextLength());
354 } 354 }
355 355
356 void TextField::Edit::RemoveBorder() { 356 void Textfield::Edit::RemoveBorder() {
357 if (!draw_border_) 357 if (!draw_border_)
358 return; 358 return;
359 359
360 draw_border_ = false; 360 draw_border_ = false;
361 SetWindowPos(NULL, 0, 0, 0, 0, 361 SetWindowPos(NULL, 0, 0, 0, 0,
362 SWP_NOMOVE | SWP_FRAMECHANGED | SWP_NOACTIVATE | 362 SWP_NOMOVE | SWP_FRAMECHANGED | SWP_NOACTIVATE |
363 SWP_NOOWNERZORDER | SWP_NOSIZE); 363 SWP_NOOWNERZORDER | SWP_NOSIZE);
364 } 364 }
365 365
366 void TextField::Edit::SetEnabled(bool enabled) { 366 void Textfield::Edit::SetEnabled(bool enabled) {
367 SendMessage(parent_->GetNativeComponent(), WM_ENABLE, 367 SendMessage(parent_->GetNativeComponent(), WM_ENABLE,
368 static_cast<WPARAM>(enabled), 0); 368 static_cast<WPARAM>(enabled), 0);
369 } 369 }
370 370
371 // static 371 // static
372 bool TextField::IsKeystrokeEnter(const Keystroke& key) { 372 bool Textfield::IsKeystrokeEnter(const Keystroke& key) {
373 return key.key == VK_RETURN; 373 return key.key == VK_RETURN;
374 } 374 }
375 375
376 // static 376 // static
377 bool TextField::IsKeystrokeEscape(const Keystroke& key) { 377 bool Textfield::IsKeystrokeEscape(const Keystroke& key) {
378 return key.key == VK_ESCAPE; 378 return key.key == VK_ESCAPE;
379 } 379 }
380 380
381 void TextField::Edit::SetBackgroundColor(COLORREF bg_color) { 381 void Textfield::Edit::SetBackgroundColor(COLORREF bg_color) {
382 CRichEditCtrl::SetBackgroundColor(bg_color); 382 CRichEditCtrl::SetBackgroundColor(bg_color);
383 bg_color_ = bg_color; 383 bg_color_ = bg_color;
384 } 384 }
385 385
386 bool TextField::Edit::IsCommandEnabled(int id) const { 386 bool Textfield::Edit::IsCommandEnabled(int id) const {
387 switch (id) { 387 switch (id) {
388 case IDS_APP_UNDO: return !parent_->IsReadOnly() && !!CanUndo(); 388 case IDS_APP_UNDO: return !parent_->IsReadOnly() && !!CanUndo();
389 case IDS_APP_CUT: return !parent_->IsReadOnly() && 389 case IDS_APP_CUT: return !parent_->IsReadOnly() &&
390 !parent_->IsPassword() && !!CanCut(); 390 !parent_->IsPassword() && !!CanCut();
391 case IDS_APP_COPY: return !!CanCopy() && !parent_->IsPassword(); 391 case IDS_APP_COPY: return !!CanCopy() && !parent_->IsPassword();
392 case IDS_APP_PASTE: return !parent_->IsReadOnly() && !!CanPaste(); 392 case IDS_APP_PASTE: return !parent_->IsReadOnly() && !!CanPaste();
393 case IDS_APP_SELECT_ALL: return !!CanSelectAll(); 393 case IDS_APP_SELECT_ALL: return !!CanSelectAll();
394 default: NOTREACHED(); 394 default: NOTREACHED();
395 return false; 395 return false;
396 } 396 }
397 } 397 }
398 398
399 void TextField::Edit::ExecuteCommand(int id) { 399 void Textfield::Edit::ExecuteCommand(int id) {
400 ScopedFreeze freeze(this, GetTextObjectModel()); 400 ScopedFreeze freeze(this, GetTextObjectModel());
401 OnBeforePossibleChange(); 401 OnBeforePossibleChange();
402 switch (id) { 402 switch (id) {
403 case IDS_APP_UNDO: Undo(); break; 403 case IDS_APP_UNDO: Undo(); break;
404 case IDS_APP_CUT: Cut(); break; 404 case IDS_APP_CUT: Cut(); break;
405 case IDS_APP_COPY: Copy(); break; 405 case IDS_APP_COPY: Copy(); break;
406 case IDS_APP_PASTE: Paste(); break; 406 case IDS_APP_PASTE: Paste(); break;
407 case IDS_APP_SELECT_ALL: SelectAll(); break; 407 case IDS_APP_SELECT_ALL: SelectAll(); break;
408 default: NOTREACHED(); break; 408 default: NOTREACHED(); break;
409 } 409 }
410 OnAfterPossibleChange(); 410 OnAfterPossibleChange();
411 } 411 }
412 412
413 void TextField::Edit::OnChar(TCHAR ch, UINT repeat_count, UINT flags) { 413 void Textfield::Edit::OnChar(TCHAR ch, UINT repeat_count, UINT flags) {
414 HandleKeystroke(GetCurrentMessage()->message, ch, repeat_count, flags); 414 HandleKeystroke(GetCurrentMessage()->message, ch, repeat_count, flags);
415 } 415 }
416 416
417 void TextField::Edit::OnContextMenu(HWND window, const CPoint& point) { 417 void Textfield::Edit::OnContextMenu(HWND window, const CPoint& point) {
418 CPoint p(point); 418 CPoint p(point);
419 if (point.x == -1 || point.y == -1) { 419 if (point.x == -1 || point.y == -1) {
420 GetCaretPos(&p); 420 GetCaretPos(&p);
421 MapWindowPoints(HWND_DESKTOP, &p, 1); 421 MapWindowPoints(HWND_DESKTOP, &p, 1);
422 } 422 }
423 context_menu_->RunMenuAt(p.x, p.y); 423 context_menu_->RunMenuAt(p.x, p.y);
424 } 424 }
425 425
426 void TextField::Edit::OnCopy() { 426 void Textfield::Edit::OnCopy() {
427 if (parent_->IsPassword()) 427 if (parent_->IsPassword())
428 return; 428 return;
429 429
430 const std::wstring text(GetSelectedText()); 430 const std::wstring text(GetSelectedText());
431 431
432 if (!text.empty() && ViewsDelegate::views_delegate) { 432 if (!text.empty() && ViewsDelegate::views_delegate) {
433 ScopedClipboardWriter scw(ViewsDelegate::views_delegate->GetClipboard()); 433 ScopedClipboardWriter scw(ViewsDelegate::views_delegate->GetClipboard());
434 scw.WriteText(text); 434 scw.WriteText(text);
435 } 435 }
436 } 436 }
437 437
438 void TextField::Edit::OnCut() { 438 void Textfield::Edit::OnCut() {
439 if (parent_->IsReadOnly() || parent_->IsPassword()) 439 if (parent_->IsReadOnly() || parent_->IsPassword())
440 return; 440 return;
441 441
442 OnCopy(); 442 OnCopy();
443 443
444 // This replace selection will have no effect (even on the undo stack) if the 444 // This replace selection will have no effect (even on the undo stack) if the
445 // current selection is empty. 445 // current selection is empty.
446 ReplaceSel(L"", true); 446 ReplaceSel(L"", true);
447 } 447 }
448 448
449 LRESULT TextField::Edit::OnImeChar(UINT message, WPARAM wparam, LPARAM lparam) { 449 LRESULT Textfield::Edit::OnImeChar(UINT message, WPARAM wparam, LPARAM lparam) {
450 // http://crbug.com/7707: a rich-edit control may crash when it receives a 450 // http://crbug.com/7707: a rich-edit control may crash when it receives a
451 // WM_IME_CHAR message while it is processing a WM_IME_COMPOSITION message. 451 // WM_IME_CHAR message while it is processing a WM_IME_COMPOSITION message.
452 // Since view controls don't need WM_IME_CHAR messages, we prevent WM_IME_CHAR 452 // Since view controls don't need WM_IME_CHAR messages, we prevent WM_IME_CHAR
453 // messages from being dispatched to view controls via the CallWindowProc() 453 // messages from being dispatched to view controls via the CallWindowProc()
454 // call. 454 // call.
455 return 0; 455 return 0;
456 } 456 }
457 457
458 LRESULT TextField::Edit::OnImeStartComposition(UINT message, 458 LRESULT Textfield::Edit::OnImeStartComposition(UINT message,
459 WPARAM wparam, 459 WPARAM wparam,
460 LPARAM lparam) { 460 LPARAM lparam) {
461 // Users may press alt+shift or control+shift keys to change their keyboard 461 // Users may press alt+shift or control+shift keys to change their keyboard
462 // layouts. So, we retrieve the input locale identifier everytime we start 462 // layouts. So, we retrieve the input locale identifier everytime we start
463 // an IME composition. 463 // an IME composition.
464 int language_id = PRIMARYLANGID(GetKeyboardLayout(0)); 464 int language_id = PRIMARYLANGID(GetKeyboardLayout(0));
465 ime_discard_composition_ = 465 ime_discard_composition_ =
466 language_id == LANG_JAPANESE || language_id == LANG_CHINESE; 466 language_id == LANG_JAPANESE || language_id == LANG_CHINESE;
467 ime_composition_start_ = 0; 467 ime_composition_start_ = 0;
468 ime_composition_length_ = 0; 468 ime_composition_length_ = 0;
469 469
470 return DefWindowProc(message, wparam, lparam); 470 return DefWindowProc(message, wparam, lparam);
471 } 471 }
472 472
473 LRESULT TextField::Edit::OnImeComposition(UINT message, 473 LRESULT Textfield::Edit::OnImeComposition(UINT message,
474 WPARAM wparam, 474 WPARAM wparam,
475 LPARAM lparam) { 475 LPARAM lparam) {
476 text_before_change_.clear(); 476 text_before_change_.clear();
477 LRESULT result = DefWindowProc(message, wparam, lparam); 477 LRESULT result = DefWindowProc(message, wparam, lparam);
478 478
479 ime_composition_start_ = 0; 479 ime_composition_start_ = 0;
480 ime_composition_length_ = 0; 480 ime_composition_length_ = 0;
481 if (ime_discard_composition_) { 481 if (ime_discard_composition_) {
482 // Call IMM32 functions to retrieve the position and the length of the 482 // Call IMM32 functions to retrieve the position and the length of the
483 // ongoing composition string and notify the OnAfterPossibleChange() 483 // ongoing composition string and notify the OnAfterPossibleChange()
(...skipping 15 matching lines...) Expand all
499 ime_composition_length_ = composition_size / sizeof(wchar_t); 499 ime_composition_length_ = composition_size / sizeof(wchar_t);
500 500
501 ImmReleaseContext(m_hWnd, imm_context); 501 ImmReleaseContext(m_hWnd, imm_context);
502 } 502 }
503 } 503 }
504 504
505 OnAfterPossibleChange(); 505 OnAfterPossibleChange();
506 return result; 506 return result;
507 } 507 }
508 508
509 LRESULT TextField::Edit::OnImeEndComposition(UINT message, 509 LRESULT Textfield::Edit::OnImeEndComposition(UINT message,
510 WPARAM wparam, 510 WPARAM wparam,
511 LPARAM lparam) { 511 LPARAM lparam) {
512 // Bug 11863: Korean IMEs send a WM_IME_ENDCOMPOSITION message without 512 // Bug 11863: Korean IMEs send a WM_IME_ENDCOMPOSITION message without
513 // sending any WM_IME_COMPOSITION messages when a user deletes all 513 // sending any WM_IME_COMPOSITION messages when a user deletes all
514 // composition characters, i.e. a composition string becomes empty. To handle 514 // composition characters, i.e. a composition string becomes empty. To handle
515 // this case, we need to update the find results when a composition is 515 // this case, we need to update the find results when a composition is
516 // finished or canceled. 516 // finished or canceled.
517 parent_->SyncText(); 517 parent_->SyncText();
518 if (parent_->GetController()) 518 if (parent_->GetController())
519 parent_->GetController()->ContentsChanged(parent_, GetText()); 519 parent_->GetController()->ContentsChanged(parent_, GetText());
520 return DefWindowProc(message, wparam, lparam); 520 return DefWindowProc(message, wparam, lparam);
521 } 521 }
522 522
523 void TextField::Edit::OnKeyDown(TCHAR key, UINT repeat_count, UINT flags) { 523 void Textfield::Edit::OnKeyDown(TCHAR key, UINT repeat_count, UINT flags) {
524 // NOTE: Annoyingly, ctrl-alt-<key> generates WM_KEYDOWN rather than 524 // NOTE: Annoyingly, ctrl-alt-<key> generates WM_KEYDOWN rather than
525 // WM_SYSKEYDOWN, so we need to check (flags & KF_ALTDOWN) in various places 525 // WM_SYSKEYDOWN, so we need to check (flags & KF_ALTDOWN) in various places
526 // in this function even with a WM_SYSKEYDOWN handler. 526 // in this function even with a WM_SYSKEYDOWN handler.
527 527
528 switch (key) { 528 switch (key) {
529 case VK_RETURN: 529 case VK_RETURN:
530 // If we are multi-line, we want to let returns through so they start a 530 // If we are multi-line, we want to let returns through so they start a
531 // new line. 531 // new line.
532 if (parent_->IsMultiLine()) 532 if (parent_->IsMultiLine())
533 break; 533 break;
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
592 // We ignore this event because an IME sends WM_IME_COMPOSITION messages 592 // We ignore this event because an IME sends WM_IME_COMPOSITION messages
593 // when it updates the CRichEditCtrl text. 593 // when it updates the CRichEditCtrl text.
594 return; 594 return;
595 } 595 }
596 596
597 // CRichEditCtrl changes its text on WM_KEYDOWN instead of WM_CHAR for many 597 // CRichEditCtrl changes its text on WM_KEYDOWN instead of WM_CHAR for many
598 // different keys (backspace, ctrl-v, ...), so we call this in both cases. 598 // different keys (backspace, ctrl-v, ...), so we call this in both cases.
599 HandleKeystroke(GetCurrentMessage()->message, key, repeat_count, flags); 599 HandleKeystroke(GetCurrentMessage()->message, key, repeat_count, flags);
600 } 600 }
601 601
602 void TextField::Edit::OnLButtonDblClk(UINT keys, const CPoint& point) { 602 void Textfield::Edit::OnLButtonDblClk(UINT keys, const CPoint& point) {
603 // Save the double click info for later triple-click detection. 603 // Save the double click info for later triple-click detection.
604 tracking_double_click_ = true; 604 tracking_double_click_ = true;
605 double_click_point_ = point; 605 double_click_point_ = point;
606 double_click_time_ = GetCurrentMessage()->time; 606 double_click_time_ = GetCurrentMessage()->time;
607 607
608 ScopedFreeze freeze(this, GetTextObjectModel()); 608 ScopedFreeze freeze(this, GetTextObjectModel());
609 OnBeforePossibleChange(); 609 OnBeforePossibleChange();
610 DefWindowProc(WM_LBUTTONDBLCLK, keys, 610 DefWindowProc(WM_LBUTTONDBLCLK, keys,
611 MAKELPARAM(ClipXCoordToVisibleText(point.x, false), point.y)); 611 MAKELPARAM(ClipXCoordToVisibleText(point.x, false), point.y));
612 OnAfterPossibleChange(); 612 OnAfterPossibleChange();
613 } 613 }
614 614
615 void TextField::Edit::OnLButtonDown(UINT keys, const CPoint& point) { 615 void Textfield::Edit::OnLButtonDown(UINT keys, const CPoint& point) {
616 // Check for triple click, then reset tracker. Should be safe to subtract 616 // Check for triple click, then reset tracker. Should be safe to subtract
617 // double_click_time_ from the current message's time even if the timer has 617 // double_click_time_ from the current message's time even if the timer has
618 // wrapped in between. 618 // wrapped in between.
619 const bool is_triple_click = tracking_double_click_ && 619 const bool is_triple_click = tracking_double_click_ &&
620 win_util::IsDoubleClick(double_click_point_, point, 620 win_util::IsDoubleClick(double_click_point_, point,
621 GetCurrentMessage()->time - double_click_time_); 621 GetCurrentMessage()->time - double_click_time_);
622 tracking_double_click_ = false; 622 tracking_double_click_ = false;
623 623
624 ScopedFreeze freeze(this, GetTextObjectModel()); 624 ScopedFreeze freeze(this, GetTextObjectModel());
625 OnBeforePossibleChange(); 625 OnBeforePossibleChange();
626 DefWindowProc(WM_LBUTTONDOWN, keys, 626 DefWindowProc(WM_LBUTTONDOWN, keys,
627 MAKELPARAM(ClipXCoordToVisibleText(point.x, is_triple_click), 627 MAKELPARAM(ClipXCoordToVisibleText(point.x, is_triple_click),
628 point.y)); 628 point.y));
629 OnAfterPossibleChange(); 629 OnAfterPossibleChange();
630 } 630 }
631 631
632 void TextField::Edit::OnLButtonUp(UINT keys, const CPoint& point) { 632 void Textfield::Edit::OnLButtonUp(UINT keys, const CPoint& point) {
633 ScopedFreeze freeze(this, GetTextObjectModel()); 633 ScopedFreeze freeze(this, GetTextObjectModel());
634 OnBeforePossibleChange(); 634 OnBeforePossibleChange();
635 DefWindowProc(WM_LBUTTONUP, keys, 635 DefWindowProc(WM_LBUTTONUP, keys,
636 MAKELPARAM(ClipXCoordToVisibleText(point.x, false), point.y)); 636 MAKELPARAM(ClipXCoordToVisibleText(point.x, false), point.y));
637 OnAfterPossibleChange(); 637 OnAfterPossibleChange();
638 } 638 }
639 639
640 void TextField::Edit::OnMouseLeave() { 640 void Textfield::Edit::OnMouseLeave() {
641 SetContainsMouse(false); 641 SetContainsMouse(false);
642 } 642 }
643 643
644 LRESULT TextField::Edit::OnMouseWheel(UINT message, 644 LRESULT Textfield::Edit::OnMouseWheel(UINT message,
645 WPARAM w_param, LPARAM l_param) { 645 WPARAM w_param, LPARAM l_param) {
646 // Reroute the mouse-wheel to the window under the mouse pointer if 646 // Reroute the mouse-wheel to the window under the mouse pointer if
647 // applicable. 647 // applicable.
648 if (views::RerouteMouseWheel(m_hWnd, w_param, l_param)) 648 if (views::RerouteMouseWheel(m_hWnd, w_param, l_param))
649 return 0; 649 return 0;
650 return DefWindowProc(message, w_param, l_param);; 650 return DefWindowProc(message, w_param, l_param);;
651 } 651 }
652 652
653 void TextField::Edit::OnMouseMove(UINT keys, const CPoint& point) { 653 void Textfield::Edit::OnMouseMove(UINT keys, const CPoint& point) {
654 SetContainsMouse(true); 654 SetContainsMouse(true);
655 // Clamp the selection to the visible text so the user can't drag to select 655 // Clamp the selection to the visible text so the user can't drag to select
656 // the "phantom newline". In theory we could achieve this by clipping the X 656 // the "phantom newline". In theory we could achieve this by clipping the X
657 // coordinate, but in practice the edit seems to behave nondeterministically 657 // coordinate, but in practice the edit seems to behave nondeterministically
658 // with similar sequences of clipped input coordinates fed to it. Maybe it's 658 // with similar sequences of clipped input coordinates fed to it. Maybe it's
659 // reading the mouse cursor position directly? 659 // reading the mouse cursor position directly?
660 // 660 //
661 // This solution has a minor visual flaw, however: if there's a visible 661 // This solution has a minor visual flaw, however: if there's a visible
662 // cursor at the edge of the text (only true when there's no selection), 662 // cursor at the edge of the text (only true when there's no selection),
663 // dragging the mouse around outside that edge repaints the cursor on every 663 // dragging the mouse around outside that edge repaints the cursor on every
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
697 // just a few pixels vertically end up selecting the "phantom newline"... 697 // just a few pixels vertically end up selecting the "phantom newline"...
698 // sometimes. 698 // sometimes.
699 RECT r; 699 RECT r;
700 GetRect(&r); 700 GetRect(&r);
701 DefWindowProc(WM_MOUSEMOVE, keys, 701 DefWindowProc(WM_MOUSEMOVE, keys,
702 MAKELPARAM(point.x, (r.bottom - r.top) / 2)); 702 MAKELPARAM(point.x, (r.bottom - r.top) / 2));
703 OnAfterPossibleChange(); 703 OnAfterPossibleChange();
704 } 704 }
705 } 705 }
706 706
707 int TextField::Edit::OnNCCalcSize(BOOL w_param, LPARAM l_param) { 707 int Textfield::Edit::OnNCCalcSize(BOOL w_param, LPARAM l_param) {
708 content_insets_.Set(0, 0, 0, 0); 708 content_insets_.Set(0, 0, 0, 0);
709 parent_->CalculateInsets(&content_insets_); 709 parent_->CalculateInsets(&content_insets_);
710 if (w_param) { 710 if (w_param) {
711 NCCALCSIZE_PARAMS* nc_params = 711 NCCALCSIZE_PARAMS* nc_params =
712 reinterpret_cast<NCCALCSIZE_PARAMS*>(l_param); 712 reinterpret_cast<NCCALCSIZE_PARAMS*>(l_param);
713 nc_params->rgrc[0].left += content_insets_.left(); 713 nc_params->rgrc[0].left += content_insets_.left();
714 nc_params->rgrc[0].right -= content_insets_.right(); 714 nc_params->rgrc[0].right -= content_insets_.right();
715 nc_params->rgrc[0].top += content_insets_.top(); 715 nc_params->rgrc[0].top += content_insets_.top();
716 nc_params->rgrc[0].bottom -= content_insets_.bottom(); 716 nc_params->rgrc[0].bottom -= content_insets_.bottom();
717 } else { 717 } else {
718 RECT* rect = reinterpret_cast<RECT*>(l_param); 718 RECT* rect = reinterpret_cast<RECT*>(l_param);
719 rect->left += content_insets_.left(); 719 rect->left += content_insets_.left();
720 rect->right -= content_insets_.right(); 720 rect->right -= content_insets_.right();
721 rect->top += content_insets_.top(); 721 rect->top += content_insets_.top();
722 rect->bottom -= content_insets_.bottom(); 722 rect->bottom -= content_insets_.bottom();
723 } 723 }
724 return 0; 724 return 0;
725 } 725 }
726 726
727 void TextField::Edit::OnNCPaint(HRGN region) { 727 void Textfield::Edit::OnNCPaint(HRGN region) {
728 if (!draw_border_) 728 if (!draw_border_)
729 return; 729 return;
730 730
731 HDC hdc = GetWindowDC(); 731 HDC hdc = GetWindowDC();
732 732
733 CRect window_rect; 733 CRect window_rect;
734 GetWindowRect(&window_rect); 734 GetWindowRect(&window_rect);
735 // Convert to be relative to 0x0. 735 // Convert to be relative to 0x0.
736 window_rect.MoveToXY(0, 0); 736 window_rect.MoveToXY(0, 0);
737 737
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
779 NativeTheme::instance()->PaintTextField(hdc, part, state, classic_state, 779 NativeTheme::instance()->PaintTextField(hdc, part, state, classic_state,
780 &window_rect, bg_color_, false, 780 &window_rect, bg_color_, false,
781 true); 781 true);
782 782
783 // NOTE: I tried checking the transparent property of the theme and invoking 783 // NOTE: I tried checking the transparent property of the theme and invoking
784 // drawParentBackground, but it didn't seem to make a difference. 784 // drawParentBackground, but it didn't seem to make a difference.
785 785
786 ReleaseDC(hdc); 786 ReleaseDC(hdc);
787 } 787 }
788 788
789 void TextField::Edit::OnNonLButtonDown(UINT keys, const CPoint& point) { 789 void Textfield::Edit::OnNonLButtonDown(UINT keys, const CPoint& point) {
790 // Interestingly, the edit doesn't seem to cancel triple clicking when the 790 // Interestingly, the edit doesn't seem to cancel triple clicking when the
791 // x-buttons (which usually means "thumb buttons") are pressed, so we only 791 // x-buttons (which usually means "thumb buttons") are pressed, so we only
792 // call this for M and R down. 792 // call this for M and R down.
793 tracking_double_click_ = false; 793 tracking_double_click_ = false;
794 SetMsgHandled(false); 794 SetMsgHandled(false);
795 } 795 }
796 796
797 void TextField::Edit::OnPaste() { 797 void Textfield::Edit::OnPaste() {
798 if (parent_->IsReadOnly() || !ViewsDelegate::views_delegate) 798 if (parent_->IsReadOnly() || !ViewsDelegate::views_delegate)
799 return; 799 return;
800 800
801 Clipboard* clipboard = ViewsDelegate::views_delegate->GetClipboard(); 801 Clipboard* clipboard = ViewsDelegate::views_delegate->GetClipboard();
802 802
803 if (!clipboard->IsFormatAvailable(Clipboard::GetPlainTextWFormatType())) 803 if (!clipboard->IsFormatAvailable(Clipboard::GetPlainTextWFormatType()))
804 return; 804 return;
805 805
806 std::wstring clipboard_str; 806 std::wstring clipboard_str;
807 clipboard->ReadText(&clipboard_str); 807 clipboard->ReadText(&clipboard_str);
808 if (!clipboard_str.empty()) { 808 if (!clipboard_str.empty()) {
809 std::wstring collapsed(CollapseWhitespace(clipboard_str, false)); 809 std::wstring collapsed(CollapseWhitespace(clipboard_str, false));
810 if (parent_->GetStyle() & STYLE_LOWERCASE) 810 if (parent_->GetStyle() & STYLE_LOWERCASE)
811 collapsed = l10n_util::ToLower(collapsed); 811 collapsed = l10n_util::ToLower(collapsed);
812 // Force a Paste operation to trigger OnContentsChanged, even if identical 812 // Force a Paste operation to trigger OnContentsChanged, even if identical
813 // contents are pasted into the text box. 813 // contents are pasted into the text box.
814 text_before_change_.clear(); 814 text_before_change_.clear();
815 ReplaceSel(collapsed.c_str(), true); 815 ReplaceSel(collapsed.c_str(), true);
816 } 816 }
817 } 817 }
818 818
819 void TextField::Edit::OnSysChar(TCHAR ch, UINT repeat_count, UINT flags) { 819 void Textfield::Edit::OnSysChar(TCHAR ch, UINT repeat_count, UINT flags) {
820 // Nearly all alt-<xxx> combos result in beeping rather than doing something 820 // Nearly all alt-<xxx> combos result in beeping rather than doing something
821 // useful, so we discard most. Exceptions: 821 // useful, so we discard most. Exceptions:
822 // * ctrl-alt-<xxx>, which is sometimes important, generates WM_CHAR instead 822 // * ctrl-alt-<xxx>, which is sometimes important, generates WM_CHAR instead
823 // of WM_SYSCHAR, so it doesn't need to be handled here. 823 // of WM_SYSCHAR, so it doesn't need to be handled here.
824 // * alt-space gets translated by the default WM_SYSCHAR handler to a 824 // * alt-space gets translated by the default WM_SYSCHAR handler to a
825 // WM_SYSCOMMAND to open the application context menu, so we need to allow 825 // WM_SYSCOMMAND to open the application context menu, so we need to allow
826 // it through. 826 // it through.
827 if (ch == VK_SPACE) 827 if (ch == VK_SPACE)
828 SetMsgHandled(false); 828 SetMsgHandled(false);
829 } 829 }
830 830
831 void TextField::Edit::HandleKeystroke(UINT message, 831 void Textfield::Edit::HandleKeystroke(UINT message,
832 TCHAR key, 832 TCHAR key,
833 UINT repeat_count, 833 UINT repeat_count,
834 UINT flags) { 834 UINT flags) {
835 ScopedFreeze freeze(this, GetTextObjectModel()); 835 ScopedFreeze freeze(this, GetTextObjectModel());
836 836
837 TextField::Controller* controller = parent_->GetController(); 837 Textfield::Controller* controller = parent_->GetController();
838 bool handled = false; 838 bool handled = false;
839 if (controller) { 839 if (controller) {
840 handled = controller->HandleKeystroke(parent_, 840 handled = controller->HandleKeystroke(parent_,
841 TextField::Keystroke(message, key, repeat_count, flags)); 841 Textfield::Keystroke(message, key, repeat_count, flags));
842 } 842 }
843 843
844 if (!handled) { 844 if (!handled) {
845 OnBeforePossibleChange(); 845 OnBeforePossibleChange();
846 DefWindowProc(message, key, MAKELPARAM(repeat_count, flags)); 846 DefWindowProc(message, key, MAKELPARAM(repeat_count, flags));
847 OnAfterPossibleChange(); 847 OnAfterPossibleChange();
848 } 848 }
849 } 849 }
850 850
851 void TextField::Edit::OnBeforePossibleChange() { 851 void Textfield::Edit::OnBeforePossibleChange() {
852 // Record our state. 852 // Record our state.
853 text_before_change_ = GetText(); 853 text_before_change_ = GetText();
854 } 854 }
855 855
856 void TextField::Edit::OnAfterPossibleChange() { 856 void Textfield::Edit::OnAfterPossibleChange() {
857 // Prevent the user from selecting the "phantom newline" at the end of the 857 // Prevent the user from selecting the "phantom newline" at the end of the
858 // edit. If they try, we just silently move the end of the selection back to 858 // edit. If they try, we just silently move the end of the selection back to
859 // the end of the real text. 859 // the end of the real text.
860 CHARRANGE new_sel; 860 CHARRANGE new_sel;
861 GetSel(new_sel); 861 GetSel(new_sel);
862 const int length = GetTextLength(); 862 const int length = GetTextLength();
863 if (new_sel.cpMax > length) { 863 if (new_sel.cpMax > length) {
864 new_sel.cpMax = length; 864 new_sel.cpMax = length;
865 if (new_sel.cpMin > length) 865 if (new_sel.cpMin > length)
866 new_sel.cpMin = length; 866 new_sel.cpMin = length;
(...skipping 12 matching lines...) Expand all
879 ime_composition_length_ = 0; 879 ime_composition_length_ = 0;
880 if (new_text.empty()) 880 if (new_text.empty())
881 return; 881 return;
882 } 882 }
883 parent_->SyncText(); 883 parent_->SyncText();
884 if (parent_->GetController()) 884 if (parent_->GetController())
885 parent_->GetController()->ContentsChanged(parent_, new_text); 885 parent_->GetController()->ContentsChanged(parent_, new_text);
886 } 886 }
887 } 887 }
888 888
889 LONG TextField::Edit::ClipXCoordToVisibleText(LONG x, 889 LONG Textfield::Edit::ClipXCoordToVisibleText(LONG x,
890 bool is_triple_click) const { 890 bool is_triple_click) const {
891 // Clip the X coordinate to the left edge of the text. Careful: 891 // Clip the X coordinate to the left edge of the text. Careful:
892 // PosFromChar(0) may return a negative X coordinate if the beginning of the 892 // PosFromChar(0) may return a negative X coordinate if the beginning of the
893 // text has scrolled off the edit, so don't go past the clip rect's edge. 893 // text has scrolled off the edit, so don't go past the clip rect's edge.
894 PARAFORMAT2 pf2; 894 PARAFORMAT2 pf2;
895 GetParaFormat(pf2); 895 GetParaFormat(pf2);
896 // Calculation of the clipped coordinate is more complicated if the paragraph 896 // Calculation of the clipped coordinate is more complicated if the paragraph
897 // layout is RTL layout, or if there is RTL characters inside the LTR layout 897 // layout is RTL layout, or if there is RTL characters inside the LTR layout
898 // paragraph. 898 // paragraph.
899 bool ltr_text_in_ltr_layout = true; 899 bool ltr_text_in_ltr_layout = true;
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
935 // the end of the text, but triple-click will still work. 935 // the end of the text, but triple-click will still work.
936 if (x < left_bound) { 936 if (x < left_bound) {
937 return (is_triple_click && ltr_text_in_ltr_layout) ? left_bound - 1 : 937 return (is_triple_click && ltr_text_in_ltr_layout) ? left_bound - 1 :
938 left_bound; 938 left_bound;
939 } 939 }
940 if ((length == 0) || (x < right_bound)) 940 if ((length == 0) || (x < right_bound))
941 return x; 941 return x;
942 return is_triple_click ? (right_bound - 1) : right_bound; 942 return is_triple_click ? (right_bound - 1) : right_bound;
943 } 943 }
944 944
945 void TextField::Edit::SetContainsMouse(bool contains_mouse) { 945 void Textfield::Edit::SetContainsMouse(bool contains_mouse) {
946 if (contains_mouse == contains_mouse_) 946 if (contains_mouse == contains_mouse_)
947 return; 947 return;
948 948
949 contains_mouse_ = contains_mouse; 949 contains_mouse_ = contains_mouse;
950 950
951 if (!draw_border_) 951 if (!draw_border_)
952 return; 952 return;
953 953
954 if (contains_mouse_) { 954 if (contains_mouse_) {
955 // Register for notification when the mouse leaves. Need to do this so 955 // Register for notification when the mouse leaves. Need to do this so
956 // that we can reset contains mouse properly. 956 // that we can reset contains mouse properly.
957 TRACKMOUSEEVENT tme; 957 TRACKMOUSEEVENT tme;
958 tme.cbSize = sizeof(tme); 958 tme.cbSize = sizeof(tme);
959 tme.dwFlags = TME_LEAVE; 959 tme.dwFlags = TME_LEAVE;
960 tme.hwndTrack = m_hWnd; 960 tme.hwndTrack = m_hWnd;
961 tme.dwHoverTime = 0; 961 tme.dwHoverTime = 0;
962 TrackMouseEvent(&tme); 962 TrackMouseEvent(&tme);
963 } 963 }
964 RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_FRAME); 964 RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_FRAME);
965 } 965 }
966 966
967 ITextDocument* TextField::Edit::GetTextObjectModel() const { 967 ITextDocument* Textfield::Edit::GetTextObjectModel() const {
968 if (!text_object_model_) { 968 if (!text_object_model_) {
969 CComPtr<IRichEditOle> ole_interface; 969 CComPtr<IRichEditOle> ole_interface;
970 ole_interface.Attach(GetOleInterface()); 970 ole_interface.Attach(GetOleInterface());
971 text_object_model_ = ole_interface; 971 text_object_model_ = ole_interface;
972 } 972 }
973 return text_object_model_; 973 return text_object_model_;
974 } 974 }
975 975
976 ///////////////////////////////////////////////////////////////////////////// 976 /////////////////////////////////////////////////////////////////////////////
977 // TextField 977 // Textfield
978 978
979 TextField::~TextField() { 979 Textfield::~Textfield() {
980 if (edit_) { 980 if (edit_) {
981 // If the edit hwnd still exists, we need to destroy it explicitly. 981 // If the edit hwnd still exists, we need to destroy it explicitly.
982 if (*edit_) 982 if (*edit_)
983 edit_->DestroyWindow(); 983 edit_->DestroyWindow();
984 delete edit_; 984 delete edit_;
985 } 985 }
986 } 986 }
987 987
988 void TextField::ViewHierarchyChanged(bool is_add, View* parent, View* child) { 988 void Textfield::ViewHierarchyChanged(bool is_add, View* parent, View* child) {
989 Widget* widget; 989 Widget* widget;
990 990
991 if (is_add && (widget = GetWidget())) { 991 if (is_add && (widget = GetWidget())) {
992 // This notification is called from the AddChildView call below. Ignore it. 992 // This notification is called from the AddChildView call below. Ignore it.
993 if (native_view_ && !edit_) 993 if (native_view_ && !edit_)
994 return; 994 return;
995 995
996 if (!native_view_) { 996 if (!native_view_) {
997 native_view_ = new HWNDView(); // Deleted from our superclass destructor 997 native_view_ = new HWNDView(); // Deleted from our superclass destructor
998 AddChildView(native_view_); 998 AddChildView(native_view_);
(...skipping 16 matching lines...) Expand all
1015 if (!text_.empty()) 1015 if (!text_.empty())
1016 edit_->SetText(text_); 1016 edit_->SetText(text_);
1017 UpdateEditBackgroundColor(); 1017 UpdateEditBackgroundColor();
1018 Layout(); 1018 Layout();
1019 } 1019 }
1020 } else if (!is_add && edit_ && IsWindow(edit_->m_hWnd)) { 1020 } else if (!is_add && edit_ && IsWindow(edit_->m_hWnd)) {
1021 edit_->SetParent(NULL); 1021 edit_->SetParent(NULL);
1022 } 1022 }
1023 } 1023 }
1024 1024
1025 void TextField::Layout() { 1025 void Textfield::Layout() {
1026 if (native_view_) { 1026 if (native_view_) {
1027 native_view_->SetBounds(GetLocalBounds(true)); 1027 native_view_->SetBounds(GetLocalBounds(true));
1028 native_view_->Layout(); 1028 native_view_->Layout();
1029 } 1029 }
1030 } 1030 }
1031 1031
1032 gfx::Size TextField::GetPreferredSize() { 1032 gfx::Size Textfield::GetPreferredSize() {
1033 gfx::Insets insets; 1033 gfx::Insets insets;
1034 CalculateInsets(&insets); 1034 CalculateInsets(&insets);
1035 return gfx::Size(font_.GetExpectedTextWidth(default_width_in_chars_) + 1035 return gfx::Size(font_.GetExpectedTextWidth(default_width_in_chars_) +
1036 insets.width(), 1036 insets.width(),
1037 num_lines_ * font_.height() + insets.height()); 1037 num_lines_ * font_.height() + insets.height());
1038 } 1038 }
1039 1039
1040 std::wstring TextField::GetText() const { 1040 std::wstring Textfield::GetText() const {
1041 return text_; 1041 return text_;
1042 } 1042 }
1043 1043
1044 void TextField::SetText(const std::wstring& text) { 1044 void Textfield::SetText(const std::wstring& text) {
1045 text_ = text; 1045 text_ = text;
1046 if (edit_) 1046 if (edit_)
1047 edit_->SetText(text); 1047 edit_->SetText(text);
1048 } 1048 }
1049 1049
1050 void TextField::AppendText(const std::wstring& text) { 1050 void Textfield::AppendText(const std::wstring& text) {
1051 text_ += text; 1051 text_ += text;
1052 if (edit_) 1052 if (edit_)
1053 edit_->AppendText(text); 1053 edit_->AppendText(text);
1054 } 1054 }
1055 1055
1056 void TextField::CalculateInsets(gfx::Insets* insets) { 1056 void Textfield::CalculateInsets(gfx::Insets* insets) {
1057 DCHECK(insets); 1057 DCHECK(insets);
1058 1058
1059 if (!draw_border_) 1059 if (!draw_border_)
1060 return; 1060 return;
1061 1061
1062 // NOTE: One would think GetThemeMargins would return the insets we should 1062 // NOTE: One would think GetThemeMargins would return the insets we should
1063 // use, but it doesn't. The margins returned by GetThemeMargins are always 1063 // use, but it doesn't. The margins returned by GetThemeMargins are always
1064 // 0. 1064 // 0.
1065 1065
1066 // This appears to be the insets used by Windows. 1066 // This appears to be the insets used by Windows.
1067 insets->Set(3, 3, 3, 3); 1067 insets->Set(3, 3, 3, 3);
1068 } 1068 }
1069 1069
1070 void TextField::SyncText() { 1070 void Textfield::SyncText() {
1071 if (edit_) 1071 if (edit_)
1072 text_ = edit_->GetText(); 1072 text_ = edit_->GetText();
1073 } 1073 }
1074 1074
1075 void TextField::SetController(Controller* controller) { 1075 void Textfield::SetController(Controller* controller) {
1076 controller_ = controller; 1076 controller_ = controller;
1077 } 1077 }
1078 1078
1079 TextField::Controller* TextField::GetController() const { 1079 Textfield::Controller* Textfield::GetController() const {
1080 return controller_; 1080 return controller_;
1081 } 1081 }
1082 1082
1083 bool TextField::IsReadOnly() const { 1083 bool Textfield::IsReadOnly() const {
1084 return edit_ ? ((edit_->GetStyle() & ES_READONLY) != 0) : read_only_; 1084 return edit_ ? ((edit_->GetStyle() & ES_READONLY) != 0) : read_only_;
1085 } 1085 }
1086 1086
1087 bool TextField::IsPassword() const { 1087 bool Textfield::IsPassword() const {
1088 return GetStyle() & TextField::STYLE_PASSWORD; 1088 return GetStyle() & Textfield::STYLE_PASSWORD;
1089 } 1089 }
1090 1090
1091 bool TextField::IsMultiLine() const { 1091 bool Textfield::IsMultiLine() const {
1092 return (style_ & STYLE_MULTILINE) != 0; 1092 return (style_ & STYLE_MULTILINE) != 0;
1093 } 1093 }
1094 1094
1095 void TextField::SetReadOnly(bool read_only) { 1095 void Textfield::SetReadOnly(bool read_only) {
1096 read_only_ = read_only; 1096 read_only_ = read_only;
1097 if (edit_) { 1097 if (edit_) {
1098 edit_->SetReadOnly(read_only); 1098 edit_->SetReadOnly(read_only);
1099 UpdateEditBackgroundColor(); 1099 UpdateEditBackgroundColor();
1100 } 1100 }
1101 } 1101 }
1102 1102
1103 void TextField::Focus() { 1103 void Textfield::Focus() {
1104 ::SetFocus(native_view_->GetHWND()); 1104 ::SetFocus(native_view_->GetHWND());
1105 } 1105 }
1106 1106
1107 void TextField::SelectAll() { 1107 void Textfield::SelectAll() {
1108 if (edit_) 1108 if (edit_)
1109 edit_->SelectAll(); 1109 edit_->SelectAll();
1110 } 1110 }
1111 1111
1112 void TextField::ClearSelection() const { 1112 void Textfield::ClearSelection() const {
1113 if (edit_) 1113 if (edit_)
1114 edit_->ClearSelection(); 1114 edit_->ClearSelection();
1115 } 1115 }
1116 1116
1117 HWND TextField::GetNativeComponent() { 1117 HWND Textfield::GetNativeComponent() {
1118 return native_view_->GetHWND(); 1118 return native_view_->GetHWND();
1119 } 1119 }
1120 1120
1121 void TextField::SetBackgroundColor(SkColor color) { 1121 void Textfield::SetBackgroundColor(SkColor color) {
1122 background_color_ = color; 1122 background_color_ = color;
1123 use_default_background_color_ = false; 1123 use_default_background_color_ = false;
1124 UpdateEditBackgroundColor(); 1124 UpdateEditBackgroundColor();
1125 } 1125 }
1126 1126
1127 void TextField::SetDefaultBackgroundColor() { 1127 void Textfield::SetDefaultBackgroundColor() {
1128 use_default_background_color_ = true; 1128 use_default_background_color_ = true;
1129 UpdateEditBackgroundColor(); 1129 UpdateEditBackgroundColor();
1130 } 1130 }
1131 1131
1132 void TextField::SetFont(const gfx::Font& font) { 1132 void Textfield::SetFont(const gfx::Font& font) {
1133 font_ = font; 1133 font_ = font;
1134 if (edit_) 1134 if (edit_)
1135 edit_->SetFont(font.hfont()); 1135 edit_->SetFont(font.hfont());
1136 } 1136 }
1137 1137
1138 gfx::Font TextField::GetFont() const { 1138 gfx::Font Textfield::GetFont() const {
1139 return font_; 1139 return font_;
1140 } 1140 }
1141 1141
1142 bool TextField::SetHorizontalMargins(int left, int right) { 1142 bool Textfield::SetHorizontalMargins(int left, int right) {
1143 // SendMessage expects the two values to be packed into one using MAKELONG 1143 // SendMessage expects the two values to be packed into one using MAKELONG
1144 // so we truncate to 16 bits if necessary. 1144 // so we truncate to 16 bits if necessary.
1145 return ERROR_SUCCESS == SendMessage(GetNativeComponent(), 1145 return ERROR_SUCCESS == SendMessage(GetNativeComponent(),
1146 (UINT) EM_SETMARGINS, 1146 (UINT) EM_SETMARGINS,
1147 (WPARAM) EC_LEFTMARGIN | EC_RIGHTMARGIN, 1147 (WPARAM) EC_LEFTMARGIN | EC_RIGHTMARGIN,
1148 (LPARAM) MAKELONG(left & 0xFFFF, 1148 (LPARAM) MAKELONG(left & 0xFFFF,
1149 right & 0xFFFF)); 1149 right & 0xFFFF));
1150 } 1150 }
1151 1151
1152 void TextField::SetHeightInLines(int num_lines) { 1152 void Textfield::SetHeightInLines(int num_lines) {
1153 DCHECK(IsMultiLine()); 1153 DCHECK(IsMultiLine());
1154 num_lines_ = num_lines; 1154 num_lines_ = num_lines;
1155 } 1155 }
1156 1156
1157 void TextField::RemoveBorder() { 1157 void Textfield::RemoveBorder() {
1158 if (!draw_border_) 1158 if (!draw_border_)
1159 return; 1159 return;
1160 1160
1161 draw_border_ = false; 1161 draw_border_ = false;
1162 if (edit_) 1162 if (edit_)
1163 edit_->RemoveBorder(); 1163 edit_->RemoveBorder();
1164 } 1164 }
1165 1165
1166 void TextField::SetEnabled(bool enabled) { 1166 void Textfield::SetEnabled(bool enabled) {
1167 View::SetEnabled(enabled); 1167 View::SetEnabled(enabled);
1168 edit_->SetEnabled(enabled); 1168 edit_->SetEnabled(enabled);
1169 } 1169 }
1170 1170
1171 bool TextField::IsFocusable() const { 1171 bool Textfield::IsFocusable() const {
1172 return IsEnabled() && !IsReadOnly(); 1172 return IsEnabled() && !IsReadOnly();
1173 } 1173 }
1174 1174
1175 void TextField::AboutToRequestFocusFromTabTraversal(bool reverse) { 1175 void Textfield::AboutToRequestFocusFromTabTraversal(bool reverse) {
1176 SelectAll(); 1176 SelectAll();
1177 } 1177 }
1178 1178
1179 bool TextField::SkipDefaultKeyEventProcessing(const KeyEvent& e) { 1179 bool Textfield::SkipDefaultKeyEventProcessing(const KeyEvent& e) {
1180 // TODO(hamaji): Figure out which keyboard combinations we need to add here, 1180 // TODO(hamaji): Figure out which keyboard combinations we need to add here,
1181 // similar to LocationBarView::SkipDefaultKeyEventProcessing. 1181 // similar to LocationBarView::SkipDefaultKeyEventProcessing.
1182 if (e.GetCharacter() == VK_BACK) 1182 if (e.GetCharacter() == VK_BACK)
1183 return true; // We'll handle BackSpace ourselves. 1183 return true; // We'll handle BackSpace ourselves.
1184 1184
1185 // We don't translate accelerators for ALT + NumPad digit, they are used for 1185 // We don't translate accelerators for ALT + NumPad digit, they are used for
1186 // entering special characters. 1186 // entering special characters.
1187 if (e.IsAltDown() && 1187 if (e.IsAltDown() &&
1188 win_util::IsNumPadDigit(e.GetCharacter(), e.IsExtendedKey())) 1188 win_util::IsNumPadDigit(e.GetCharacter(), e.IsExtendedKey()))
1189 return true; 1189 return true;
1190 1190
1191 return false; 1191 return false;
1192 } 1192 }
1193 1193
1194 void TextField::UpdateEditBackgroundColor() { 1194 void Textfield::UpdateEditBackgroundColor() {
1195 if (!edit_) 1195 if (!edit_)
1196 return; 1196 return;
1197 1197
1198 COLORREF bg_color; 1198 COLORREF bg_color;
1199 if (!use_default_background_color_) 1199 if (!use_default_background_color_)
1200 bg_color = skia::SkColorToCOLORREF(background_color_); 1200 bg_color = skia::SkColorToCOLORREF(background_color_);
1201 else 1201 else
1202 bg_color = GetSysColor(read_only_ ? COLOR_3DFACE : COLOR_WINDOW); 1202 bg_color = GetSysColor(read_only_ ? COLOR_3DFACE : COLOR_WINDOW);
1203 edit_->SetBackgroundColor(bg_color); 1203 edit_->SetBackgroundColor(bg_color);
1204 } 1204 }
1205 1205
1206 } // namespace views 1206 } // namespace views
OLDNEW
« no previous file with comments | « views/controls/textfield/textfield.h ('k') | views/focus/focus_manager_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698