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 |