Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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 "chrome/views/text_field.h" | 5 #include "chrome/views/text_field.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 <tom.h> // For ITextDocument, a COM interface to CRichEditCtrl | 11 #include <tom.h> // For ITextDocument, a COM interface to CRichEditCtrl |
| 12 #include <vsstyle.h> | 12 #include <vsstyle.h> |
| 13 | 13 |
| 14 #include "base/gfx/skia_utils.h" | |
|
Finnur
2008/11/12 22:57:39
s is after n in the alphabet. :)
| |
| 14 #include "base/gfx/native_theme.h" | 15 #include "base/gfx/native_theme.h" |
| 15 #include "base/scoped_clipboard_writer.h" | 16 #include "base/scoped_clipboard_writer.h" |
| 16 #include "base/string_util.h" | 17 #include "base/string_util.h" |
| 17 #include "base/win_util.h" | 18 #include "base/win_util.h" |
| 18 #include "chrome/browser/browser_process.h" | 19 #include "chrome/browser/browser_process.h" |
| 19 #include "chrome/common/clipboard_service.h" | 20 #include "chrome/common/clipboard_service.h" |
| 20 #include "chrome/common/gfx/insets.h" | 21 #include "chrome/common/gfx/insets.h" |
| 21 #include "chrome/common/l10n_util.h" | 22 #include "chrome/common/l10n_util.h" |
| 22 #include "chrome/common/logging_chrome.h" | 23 #include "chrome/common/logging_chrome.h" |
| 23 #include "chrome/common/win_util.h" | 24 #include "chrome/common/win_util.h" |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 54 void SelectAll(); | 55 void SelectAll(); |
| 55 | 56 |
| 56 // Clears the selection within the edit field and sets the caret to the end. | 57 // Clears the selection within the edit field and sets the caret to the end. |
| 57 void ClearSelection(); | 58 void ClearSelection(); |
| 58 | 59 |
| 59 // Removes the border. | 60 // Removes the border. |
| 60 void RemoveBorder(); | 61 void RemoveBorder(); |
| 61 | 62 |
| 62 void SetEnabled(bool enabled); | 63 void SetEnabled(bool enabled); |
| 63 | 64 |
| 65 void SetBackgroundColor(COLORREF bg_color); | |
| 66 | |
| 64 // CWindowImpl | 67 // CWindowImpl |
| 65 BEGIN_MSG_MAP(Edit) | 68 BEGIN_MSG_MAP(Edit) |
| 66 MSG_WM_CHAR(OnChar) | 69 MSG_WM_CHAR(OnChar) |
| 67 MSG_WM_CONTEXTMENU(OnContextMenu) | 70 MSG_WM_CONTEXTMENU(OnContextMenu) |
| 68 MSG_WM_COPY(OnCopy) | 71 MSG_WM_COPY(OnCopy) |
| 69 MSG_WM_CUT(OnCut) | 72 MSG_WM_CUT(OnCut) |
| 70 MESSAGE_HANDLER_EX(WM_IME_STARTCOMPOSITION, OnImeStartComposition) | 73 MESSAGE_HANDLER_EX(WM_IME_STARTCOMPOSITION, OnImeStartComposition) |
| 71 MESSAGE_HANDLER_EX(WM_IME_COMPOSITION, OnImeComposition) | 74 MESSAGE_HANDLER_EX(WM_IME_COMPOSITION, OnImeComposition) |
| 72 MSG_WM_KEYDOWN(OnKeyDown) | 75 MSG_WM_KEYDOWN(OnKeyDown) |
| 73 MSG_WM_LBUTTONDBLCLK(OnLButtonDblClk) | 76 MSG_WM_LBUTTONDBLCLK(OnLButtonDblClk) |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 189 // This interface is useful for accessing the CRichEditCtrl at a low level. | 192 // This interface is useful for accessing the CRichEditCtrl at a low level. |
| 190 mutable CComQIPtr<ITextDocument> text_object_model_; | 193 mutable CComQIPtr<ITextDocument> text_object_model_; |
| 191 | 194 |
| 192 // The position and the length of the ongoing composition string. | 195 // The position and the length of the ongoing composition string. |
| 193 // These values are used for removing a composition string from a search | 196 // These values are used for removing a composition string from a search |
| 194 // text to emulate Firefox. | 197 // text to emulate Firefox. |
| 195 bool ime_discard_composition_; | 198 bool ime_discard_composition_; |
| 196 int ime_composition_start_; | 199 int ime_composition_start_; |
| 197 int ime_composition_length_; | 200 int ime_composition_length_; |
| 198 | 201 |
| 202 COLORREF bg_color_; | |
| 203 | |
| 199 DISALLOW_EVIL_CONSTRUCTORS(Edit); | 204 DISALLOW_EVIL_CONSTRUCTORS(Edit); |
|
Finnur
2008/11/12 22:57:39
DISALLOW_COPY_AND_ASSIGN. Sorry, didn't mean to sh
| |
| 200 }; | 205 }; |
| 201 | 206 |
| 202 /////////////////////////////////////////////////////////////////////////////// | 207 /////////////////////////////////////////////////////////////////////////////// |
| 203 // Helper classes | 208 // Helper classes |
| 204 | 209 |
| 205 TextField::Edit::ScopedFreeze::ScopedFreeze(TextField::Edit* edit, | 210 TextField::Edit::ScopedFreeze::ScopedFreeze(TextField::Edit* edit, |
| 206 ITextDocument* text_object_model) | 211 ITextDocument* text_object_model) |
| 207 : edit_(edit), | 212 : edit_(edit), |
| 208 text_object_model_(text_object_model) { | 213 text_object_model_(text_object_model) { |
| 209 // Freeze the screen. | 214 // Freeze the screen. |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 235 | 240 |
| 236 TextField::Edit::Edit(TextField* parent, bool draw_border) | 241 TextField::Edit::Edit(TextField* parent, bool draw_border) |
| 237 : parent_(parent), | 242 : parent_(parent), |
| 238 tracking_double_click_(false), | 243 tracking_double_click_(false), |
| 239 double_click_time_(0), | 244 double_click_time_(0), |
| 240 can_discard_mousemove_(false), | 245 can_discard_mousemove_(false), |
| 241 contains_mouse_(false), | 246 contains_mouse_(false), |
| 242 draw_border_(draw_border), | 247 draw_border_(draw_border), |
| 243 ime_discard_composition_(false), | 248 ime_discard_composition_(false), |
| 244 ime_composition_start_(0), | 249 ime_composition_start_(0), |
| 245 ime_composition_length_(0) { | 250 ime_composition_length_(0), |
| 251 bg_color_(0) { | |
| 246 if (!did_load_library_) | 252 if (!did_load_library_) |
| 247 did_load_library_ = !!LoadLibrary(L"riched20.dll"); | 253 did_load_library_ = !!LoadLibrary(L"riched20.dll"); |
| 248 | 254 |
| 249 DWORD style = kDefaultEditStyle; | 255 DWORD style = kDefaultEditStyle; |
| 250 if (parent->GetStyle() & TextField::STYLE_PASSWORD) | 256 if (parent->GetStyle() & TextField::STYLE_PASSWORD) |
| 251 style |= ES_PASSWORD; | 257 style |= ES_PASSWORD; |
| 252 | 258 |
| 253 if (parent->read_only_) | 259 if (parent->read_only_) |
| 254 style |= ES_READONLY; | 260 style |= ES_READONLY; |
| 255 | 261 |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 334 SetWindowPos(NULL, 0, 0, 0, 0, | 340 SetWindowPos(NULL, 0, 0, 0, 0, |
| 335 SWP_NOMOVE | SWP_FRAMECHANGED | SWP_NOACTIVATE | | 341 SWP_NOMOVE | SWP_FRAMECHANGED | SWP_NOACTIVATE | |
| 336 SWP_NOOWNERZORDER | SWP_NOSIZE); | 342 SWP_NOOWNERZORDER | SWP_NOSIZE); |
| 337 } | 343 } |
| 338 | 344 |
| 339 void TextField::Edit::SetEnabled(bool enabled) { | 345 void TextField::Edit::SetEnabled(bool enabled) { |
| 340 SendMessage(parent_->GetNativeComponent(), WM_ENABLE, | 346 SendMessage(parent_->GetNativeComponent(), WM_ENABLE, |
| 341 static_cast<WPARAM>(enabled), 0); | 347 static_cast<WPARAM>(enabled), 0); |
| 342 } | 348 } |
| 343 | 349 |
| 350 void TextField::Edit::SetBackgroundColor(COLORREF bg_color) { | |
| 351 CRichEditCtrl::SetBackgroundColor(bg_color); | |
| 352 bg_color_ = bg_color; | |
| 353 } | |
| 354 | |
| 344 bool TextField::Edit::IsCommandEnabled(int id) const { | 355 bool TextField::Edit::IsCommandEnabled(int id) const { |
| 345 switch (id) { | 356 switch (id) { |
| 346 case IDS_UNDO: return !parent_->IsReadOnly() && !!CanUndo(); | 357 case IDS_UNDO: return !parent_->IsReadOnly() && !!CanUndo(); |
| 347 case IDS_CUT: return !parent_->IsReadOnly() && !!CanCut(); | 358 case IDS_CUT: return !parent_->IsReadOnly() && !!CanCut(); |
| 348 case IDS_COPY: return !!CanCopy(); | 359 case IDS_COPY: return !!CanCopy(); |
| 349 case IDS_PASTE: return !parent_->IsReadOnly() && !!CanPaste(); | 360 case IDS_PASTE: return !parent_->IsReadOnly() && !!CanPaste(); |
| 350 case IDS_SELECTALL: return !!CanSelectAll(); | 361 case IDS_SELECTALL: return !!CanSelectAll(); |
| 351 default: NOTREACHED(); | 362 default: NOTREACHED(); |
| 352 return false; | 363 return false; |
| 353 } | 364 } |
| (...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 656 GetWindowRect(&window_rect); | 667 GetWindowRect(&window_rect); |
| 657 // Convert to be relative to 0x0. | 668 // Convert to be relative to 0x0. |
| 658 window_rect.MoveToXY(0, 0); | 669 window_rect.MoveToXY(0, 0); |
| 659 | 670 |
| 660 ExcludeClipRect(hdc, | 671 ExcludeClipRect(hdc, |
| 661 window_rect.left + content_insets_.left(), | 672 window_rect.left + content_insets_.left(), |
| 662 window_rect.top + content_insets_.top(), | 673 window_rect.top + content_insets_.top(), |
| 663 window_rect.right - content_insets_.right(), | 674 window_rect.right - content_insets_.right(), |
| 664 window_rect.bottom - content_insets_.bottom()); | 675 window_rect.bottom - content_insets_.bottom()); |
| 665 | 676 |
| 666 FillRect(hdc, &window_rect, (HBRUSH) (COLOR_WINDOW+1)); | 677 HBRUSH brush = CreateSolidBrush(bg_color_); |
| 678 FillRect(hdc, &window_rect, brush); | |
| 679 DeleteObject(brush); | |
| 667 | 680 |
| 668 int part; | 681 int part; |
| 669 int state; | 682 int state; |
| 670 | 683 |
| 671 if (win_util::GetWinVersion() < win_util::WINVERSION_VISTA) { | 684 if (win_util::GetWinVersion() < win_util::WINVERSION_VISTA) { |
| 672 part = EP_EDITTEXT; | 685 part = EP_EDITTEXT; |
| 673 | 686 |
| 674 if (!parent_->IsEnabled()) | 687 if (!parent_->IsEnabled()) |
| 675 state = ETS_DISABLED; | 688 state = ETS_DISABLED; |
| 676 else if (parent_->IsReadOnly()) | 689 else if (parent_->IsReadOnly()) |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 690 state = EPSHV_HOT; | 703 state = EPSHV_HOT; |
| 691 else | 704 else |
| 692 state = EPSHV_NORMAL; | 705 state = EPSHV_NORMAL; |
| 693 // Vista doesn't appear to have a unique state for readonly. | 706 // Vista doesn't appear to have a unique state for readonly. |
| 694 } | 707 } |
| 695 | 708 |
| 696 int classic_state = | 709 int classic_state = |
| 697 (!parent_->IsEnabled() || parent_->IsReadOnly()) ? DFCS_INACTIVE : 0; | 710 (!parent_->IsEnabled() || parent_->IsReadOnly()) ? DFCS_INACTIVE : 0; |
| 698 | 711 |
| 699 NativeTheme::instance()->PaintTextField(hdc, part, state, classic_state, | 712 NativeTheme::instance()->PaintTextField(hdc, part, state, classic_state, |
| 700 &window_rect, NULL, false, true); | 713 &window_rect, bg_color_, false, |
| 714 true); | |
| 701 | 715 |
| 702 // NOTE: I tried checking the transparent property of the theme and invoking | 716 // NOTE: I tried checking the transparent property of the theme and invoking |
| 703 // drawParentBackground, but it didn't seem to make a difference. | 717 // drawParentBackground, but it didn't seem to make a difference. |
| 704 | 718 |
| 705 ReleaseDC(hdc); | 719 ReleaseDC(hdc); |
| 706 } | 720 } |
| 707 | 721 |
| 708 void TextField::Edit::OnNonLButtonDown(UINT keys, const CPoint& point) { | 722 void TextField::Edit::OnNonLButtonDown(UINT keys, const CPoint& point) { |
| 709 // Interestingly, the edit doesn't seem to cancel triple clicking when the | 723 // Interestingly, the edit doesn't seem to cancel triple clicking when the |
| 710 // x-buttons (which usually means "thumb buttons") are pressed, so we only | 724 // x-buttons (which usually means "thumb buttons") are pressed, so we only |
| (...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 891 delete edit_; | 905 delete edit_; |
| 892 edit_ = NULL; | 906 edit_ = NULL; |
| 893 } | 907 } |
| 894 | 908 |
| 895 if (!edit_) { | 909 if (!edit_) { |
| 896 edit_ = new Edit(this, draw_border_); | 910 edit_ = new Edit(this, draw_border_); |
| 897 edit_->SetFont(font_.hfont()); | 911 edit_->SetFont(font_.hfont()); |
| 898 native_view_->Attach(*edit_); | 912 native_view_->Attach(*edit_); |
| 899 if (!text_.empty()) | 913 if (!text_.empty()) |
| 900 edit_->SetText(text_); | 914 edit_->SetText(text_); |
| 901 if (!use_default_background_color_) | 915 UpdateEditBackgroundColor(); |
| 902 SetBackgroundColor(background_color_); | |
| 903 Layout(); | 916 Layout(); |
| 904 } | 917 } |
| 905 } else if (!is_add && edit_ && IsWindow(edit_->m_hWnd)) { | 918 } else if (!is_add && edit_ && IsWindow(edit_->m_hWnd)) { |
| 906 edit_->SetParent(NULL); | 919 edit_->SetParent(NULL); |
| 907 } | 920 } |
| 908 } | 921 } |
| 909 | 922 |
| 910 void TextField::Layout() { | 923 void TextField::Layout() { |
| 911 if (native_view_) { | 924 if (native_view_) { |
| 912 native_view_->SetBounds(GetLocalBounds(true)); | 925 native_view_->SetBounds(GetLocalBounds(true)); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 961 | 974 |
| 962 bool TextField::IsReadOnly() const { | 975 bool TextField::IsReadOnly() const { |
| 963 return edit_ ? ((edit_->GetStyle() & ES_READONLY) != 0) : read_only_; | 976 return edit_ ? ((edit_->GetStyle() & ES_READONLY) != 0) : read_only_; |
| 964 } | 977 } |
| 965 | 978 |
| 966 bool TextField::IsMultiLine() const { | 979 bool TextField::IsMultiLine() const { |
| 967 return (style_ & STYLE_MULTILINE) != 0; | 980 return (style_ & STYLE_MULTILINE) != 0; |
| 968 } | 981 } |
| 969 | 982 |
| 970 void TextField::SetReadOnly(bool read_only) { | 983 void TextField::SetReadOnly(bool read_only) { |
| 971 if (edit_) | 984 read_only_ = read_only; |
| 985 if (edit_) { | |
| 972 edit_->SetReadOnly(read_only); | 986 edit_->SetReadOnly(read_only); |
| 973 else | 987 UpdateEditBackgroundColor(); |
| 974 read_only_ = read_only; | 988 } |
| 975 } | 989 } |
| 976 | 990 |
| 977 | |
| 978 void TextField::Focus() { | 991 void TextField::Focus() { |
| 979 ::SetFocus(native_view_->GetHWND()); | 992 ::SetFocus(native_view_->GetHWND()); |
| 980 } | 993 } |
| 981 | 994 |
| 982 void TextField::SelectAll() { | 995 void TextField::SelectAll() { |
| 983 if (edit_) | 996 if (edit_) |
| 984 edit_->SelectAll(); | 997 edit_->SelectAll(); |
| 985 } | 998 } |
| 986 | 999 |
| 987 void TextField::ClearSelection() const { | 1000 void TextField::ClearSelection() const { |
| 988 if (edit_) | 1001 if (edit_) |
| 989 edit_->ClearSelection(); | 1002 edit_->ClearSelection(); |
| 990 } | 1003 } |
| 991 | 1004 |
| 992 HWND TextField::GetNativeComponent() { | 1005 HWND TextField::GetNativeComponent() { |
| 993 return native_view_->GetHWND(); | 1006 return native_view_->GetHWND(); |
| 994 } | 1007 } |
| 995 | 1008 |
| 996 void TextField::SetBackgroundColor(SkColor color) { | 1009 void TextField::SetBackgroundColor(SkColor color) { |
| 997 background_color_ = color; | 1010 background_color_ = color; |
| 998 use_default_background_color_ = false; | 1011 use_default_background_color_ = false; |
| 999 if (edit_) { | 1012 UpdateEditBackgroundColor(); |
| 1000 edit_->SetBackgroundColor(RGB(SkColorGetR(color), | |
| 1001 SkColorGetG(color), | |
| 1002 SkColorGetB(color))); | |
| 1003 } | |
| 1004 } | 1013 } |
| 1005 | 1014 |
| 1006 void TextField::SetDefaultBackgroundColor() { | 1015 void TextField::SetDefaultBackgroundColor() { |
| 1007 use_default_background_color_ = true; | 1016 use_default_background_color_ = true; |
| 1008 if (edit_) | 1017 UpdateEditBackgroundColor(); |
| 1009 edit_->SetBackgroundColor(); | |
| 1010 } | 1018 } |
| 1011 | 1019 |
| 1012 void TextField::SetFont(const ChromeFont& font) { | 1020 void TextField::SetFont(const ChromeFont& font) { |
| 1013 font_ = font; | 1021 font_ = font; |
| 1014 if (edit_) | 1022 if (edit_) |
| 1015 edit_->SetFont(font.hfont()); | 1023 edit_->SetFont(font.hfont()); |
| 1016 } | 1024 } |
| 1017 | 1025 |
| 1018 ChromeFont TextField::GetFont() const { | 1026 ChromeFont TextField::GetFont() const { |
| 1019 return font_; | 1027 return font_; |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 1038 if (!draw_border_) | 1046 if (!draw_border_) |
| 1039 return; | 1047 return; |
| 1040 | 1048 |
| 1041 draw_border_ = false; | 1049 draw_border_ = false; |
| 1042 if (edit_) | 1050 if (edit_) |
| 1043 edit_->RemoveBorder(); | 1051 edit_->RemoveBorder(); |
| 1044 } | 1052 } |
| 1045 | 1053 |
| 1046 void TextField::SetEnabled(bool enabled) { | 1054 void TextField::SetEnabled(bool enabled) { |
| 1047 View::SetEnabled(enabled); | 1055 View::SetEnabled(enabled); |
| 1048 SetReadOnly(!enabled); | |
| 1049 edit_->SetEnabled(enabled); | 1056 edit_->SetEnabled(enabled); |
| 1050 } | 1057 } |
| 1051 | 1058 |
| 1052 bool TextField::IsFocusable() const { | 1059 bool TextField::IsFocusable() const { |
| 1053 return IsEnabled() && !IsReadOnly(); | 1060 return IsEnabled() && !IsReadOnly(); |
| 1054 } | 1061 } |
| 1055 | 1062 |
| 1056 void TextField::AboutToRequestFocusFromTabTraversal(bool reverse) { | 1063 void TextField::AboutToRequestFocusFromTabTraversal(bool reverse) { |
| 1057 SelectAll(); | 1064 SelectAll(); |
| 1058 } | 1065 } |
| 1059 | 1066 |
| 1060 // We don't translate accelerators for ALT + numpad digit, they are used for | 1067 // We don't translate accelerators for ALT + numpad digit, they are used for |
| 1061 // entering special characters. | 1068 // entering special characters. |
| 1062 bool TextField::ShouldLookupAccelerators(const KeyEvent& e) { | 1069 bool TextField::ShouldLookupAccelerators(const KeyEvent& e) { |
| 1063 if (!e.IsAltDown()) | 1070 if (!e.IsAltDown()) |
| 1064 return true; | 1071 return true; |
| 1065 | 1072 |
| 1066 return !win_util::IsNumPadDigit(e.GetCharacter(), e.IsExtendedKey()); | 1073 return !win_util::IsNumPadDigit(e.GetCharacter(), e.IsExtendedKey()); |
| 1067 } | 1074 } |
| 1068 | 1075 |
| 1076 void TextField::UpdateEditBackgroundColor() { | |
| 1077 if (!edit_) | |
| 1078 return; | |
| 1079 | |
| 1080 COLORREF bg_color; | |
| 1081 if (!use_default_background_color_) | |
| 1082 bg_color = gfx::SkColorToCOLORREF(background_color_); | |
| 1083 else | |
| 1084 bg_color = GetSysColor(read_only_ ? COLOR_3DFACE : COLOR_WINDOW); | |
| 1085 edit_->SetBackgroundColor(bg_color); | |
| 1086 } | |
| 1087 | |
| 1069 } // namespace views | 1088 } // namespace views |
| 1070 | |
| OLD | NEW |