OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "views/controls/link.h" | 5 #include "views/controls/link.h" |
6 | 6 |
7 #include "build/build_config.h" | 7 #include "build/build_config.h" |
8 | 8 |
9 #if defined(TOOLKIT_USES_GTK) | 9 #if defined(TOOLKIT_USES_GTK) |
10 #include <gdk/gdk.h> | 10 #include <gdk/gdk.h> |
11 #endif | 11 #endif |
12 | 12 |
13 #include "base/logging.h" | 13 #include "base/logging.h" |
14 #include "base/utf_string_conversions.h" | 14 #include "base/utf_string_conversions.h" |
15 #include "ui/base/accessibility/accessible_view_state.h" | 15 #include "ui/base/accessibility/accessible_view_state.h" |
16 #include "ui/base/keycodes/keyboard_codes.h" | 16 #include "ui/base/keycodes/keyboard_codes.h" |
17 #include "ui/gfx/color_utils.h" | 17 #include "ui/gfx/color_utils.h" |
18 #include "ui/gfx/font.h" | 18 #include "ui/gfx/font.h" |
19 #include "views/controls/link_listener.h" | 19 #include "views/controls/link_listener.h" |
20 #include "views/events/event.h" | 20 #include "views/events/event.h" |
21 | 21 |
22 #if defined(TOOLKIT_USES_GTK) | 22 #if defined(TOOLKIT_USES_GTK) |
23 #include "ui/gfx/gtk_util.h" | 23 #include "ui/gfx/gtk_util.h" |
24 #endif | 24 #endif |
25 | 25 |
26 namespace { | |
27 | |
28 void GetColors(const SkColor* background_color, // NULL means "use default" | |
29 SkColor* highlighted_color, | |
30 SkColor* disabled_color, | |
31 SkColor* normal_color) { | |
32 static SkColor kHighlightedColor, kDisabledColor, kNormalColor; | |
33 static bool initialized = false; | |
34 if (!initialized) { | |
35 #if defined(OS_WIN) | |
36 kHighlightedColor = color_utils::GetReadableColor( | |
37 SkColorSetRGB(200, 0, 0), color_utils::GetSysSkColor(COLOR_WINDOW)); | |
38 kDisabledColor = color_utils::GetSysSkColor(COLOR_WINDOWTEXT); | |
39 kNormalColor = color_utils::GetSysSkColor(COLOR_HOTLIGHT); | |
40 #else | |
41 // TODO(beng): source from theme provider. | |
42 kHighlightedColor = SK_ColorRED; | |
43 kDisabledColor = SK_ColorBLACK; | |
44 kNormalColor = SkColorSetRGB(0, 51, 153); | |
45 #endif | |
46 | |
47 initialized = true; | |
48 } | |
49 | |
50 if (background_color) { | |
51 *highlighted_color = color_utils::GetReadableColor(kHighlightedColor, | |
52 *background_color); | |
53 *disabled_color = color_utils::GetReadableColor(kDisabledColor, | |
54 *background_color); | |
55 *normal_color = color_utils::GetReadableColor(kNormalColor, | |
56 *background_color); | |
57 } else { | |
58 *highlighted_color = kHighlightedColor; | |
59 *disabled_color = kDisabledColor; | |
60 *normal_color = kNormalColor; | |
61 } | |
62 } | |
63 } | |
64 | |
65 namespace views { | 26 namespace views { |
66 | 27 |
67 const char Link::kViewClassName[] = "views/Link"; | 28 const char Link::kViewClassName[] = "views/Link"; |
68 | 29 |
69 Link::Link() : Label(string16()), | 30 Link::Link() : Label(string16()) { |
70 listener_(NULL), | |
71 highlighted_(false) { | |
72 Init(); | 31 Init(); |
73 set_focusable(true); | |
74 } | 32 } |
75 | 33 |
76 Link::Link(const string16& title) : Label(title), | 34 Link::Link(const string16& title) : Label(title) { |
77 listener_(NULL), | |
78 highlighted_(false) { | |
79 Init(); | 35 Init(); |
80 set_focusable(true); | |
81 } | |
82 | |
83 void Link::Init() { | |
84 GetColors(NULL, &highlighted_color_, &disabled_color_, &normal_color_); | |
85 SetColor(normal_color_); | |
86 ValidateStyle(); | |
87 } | 36 } |
88 | 37 |
89 Link::~Link() { | 38 Link::~Link() { |
90 } | 39 } |
91 | 40 |
92 void Link::OnEnabledChanged() { | 41 void Link::OnEnabledChanged() { |
93 ValidateStyle(); | 42 RecalculateFont(); |
94 View::OnEnabledChanged(); | 43 View::OnEnabledChanged(); |
95 } | 44 } |
96 | 45 |
97 std::string Link::GetClassName() const { | 46 std::string Link::GetClassName() const { |
98 return kViewClassName; | 47 return kViewClassName; |
99 } | 48 } |
100 | 49 |
101 gfx::NativeCursor Link::GetCursor(const MouseEvent& event) { | 50 gfx::NativeCursor Link::GetCursor(const MouseEvent& event) { |
102 if (!IsEnabled()) | 51 if (!IsEnabled()) |
103 return gfx::kNullCursor; | 52 return gfx::kNullCursor; |
(...skipping 11 matching lines...) Expand all Loading... |
115 bool Link::HitTest(const gfx::Point& l) const { | 64 bool Link::HitTest(const gfx::Point& l) const { |
116 // We need to allow clicks on the link. So we override the implementation in | 65 // We need to allow clicks on the link. So we override the implementation in |
117 // Label and use the default implementation of View. | 66 // Label and use the default implementation of View. |
118 return View::HitTest(l); | 67 return View::HitTest(l); |
119 } | 68 } |
120 | 69 |
121 bool Link::OnMousePressed(const MouseEvent& event) { | 70 bool Link::OnMousePressed(const MouseEvent& event) { |
122 if (!IsEnabled() || | 71 if (!IsEnabled() || |
123 (!event.IsLeftMouseButton() && !event.IsMiddleMouseButton())) | 72 (!event.IsLeftMouseButton() && !event.IsMiddleMouseButton())) |
124 return false; | 73 return false; |
125 SetHighlighted(true); | 74 SetPressed(true); |
126 return true; | 75 return true; |
127 } | 76 } |
128 | 77 |
129 bool Link::OnMouseDragged(const MouseEvent& event) { | 78 bool Link::OnMouseDragged(const MouseEvent& event) { |
130 SetHighlighted(IsEnabled() && | 79 SetPressed(IsEnabled() && |
131 (event.IsLeftMouseButton() || event.IsMiddleMouseButton()) && | 80 (event.IsLeftMouseButton() || event.IsMiddleMouseButton()) && |
132 HitTest(event.location())); | 81 HitTest(event.location())); |
133 return true; | 82 return true; |
134 } | 83 } |
135 | 84 |
136 void Link::OnMouseReleased(const MouseEvent& event) { | 85 void Link::OnMouseReleased(const MouseEvent& event) { |
137 // Change the highlight first just in case this instance is deleted | 86 // Change the highlight first just in case this instance is deleted |
138 // while calling the controller | 87 // while calling the controller |
139 OnMouseCaptureLost(); | 88 OnMouseCaptureLost(); |
140 if (IsEnabled() && | 89 if (IsEnabled() && |
141 (event.IsLeftMouseButton() || event.IsMiddleMouseButton()) && | 90 (event.IsLeftMouseButton() || event.IsMiddleMouseButton()) && |
142 HitTest(event.location())) { | 91 HitTest(event.location())) { |
143 // Focus the link on click. | 92 // Focus the link on click. |
144 RequestFocus(); | 93 RequestFocus(); |
145 | 94 |
146 if (listener_) | 95 if (listener_) |
147 listener_->LinkClicked(this, event.flags()); | 96 listener_->LinkClicked(this, event.flags()); |
148 } | 97 } |
149 } | 98 } |
150 | 99 |
151 void Link::OnMouseCaptureLost() { | 100 void Link::OnMouseCaptureLost() { |
152 SetHighlighted(false); | 101 SetPressed(false); |
153 } | 102 } |
154 | 103 |
155 bool Link::OnKeyPressed(const KeyEvent& event) { | 104 bool Link::OnKeyPressed(const KeyEvent& event) { |
156 bool activate = ((event.key_code() == ui::VKEY_SPACE) || | 105 bool activate = ((event.key_code() == ui::VKEY_SPACE) || |
157 (event.key_code() == ui::VKEY_RETURN)); | 106 (event.key_code() == ui::VKEY_RETURN)); |
158 if (!activate) | 107 if (!activate) |
159 return false; | 108 return false; |
160 | 109 |
161 SetHighlighted(false); | 110 SetPressed(false); |
162 | 111 |
163 // Focus the link on key pressed. | 112 // Focus the link on key pressed. |
164 RequestFocus(); | 113 RequestFocus(); |
165 | 114 |
166 if (listener_) | 115 if (listener_) |
167 listener_->LinkClicked(this, event.flags()); | 116 listener_->LinkClicked(this, event.flags()); |
168 | 117 |
169 return true; | 118 return true; |
170 } | 119 } |
171 | 120 |
172 bool Link::SkipDefaultKeyEventProcessing(const KeyEvent& event) { | 121 bool Link::SkipDefaultKeyEventProcessing(const KeyEvent& event) { |
173 // Make sure we don't process space or enter as accelerators. | 122 // Make sure we don't process space or enter as accelerators. |
174 return (event.key_code() == ui::VKEY_SPACE) || | 123 return (event.key_code() == ui::VKEY_SPACE) || |
175 (event.key_code() == ui::VKEY_RETURN); | 124 (event.key_code() == ui::VKEY_RETURN); |
176 } | 125 } |
177 | 126 |
178 void Link::GetAccessibleState(ui::AccessibleViewState* state) { | 127 void Link::GetAccessibleState(ui::AccessibleViewState* state) { |
179 Label::GetAccessibleState(state); | 128 Label::GetAccessibleState(state); |
180 state->role = ui::AccessibilityTypes::ROLE_LINK; | 129 state->role = ui::AccessibilityTypes::ROLE_LINK; |
181 } | 130 } |
182 | 131 |
183 void Link::SetFont(const gfx::Font& font) { | 132 void Link::SetFont(const gfx::Font& font) { |
184 Label::SetFont(font); | 133 Label::SetFont(font); |
185 ValidateStyle(); | 134 RecalculateFont(); |
186 } | 135 } |
187 | 136 |
188 void Link::SetHighlightedColor(const SkColor& color) { | 137 void Link::SetEnabledColor(const SkColor& color) { |
189 highlighted_color_ = color; | 138 requested_enabled_color_ = color; |
190 ValidateStyle(); | 139 if (!pressed_) |
| 140 Label::SetEnabledColor(requested_enabled_color_); |
191 } | 141 } |
192 | 142 |
193 void Link::SetDisabledColor(const SkColor& color) { | 143 void Link::SetPressedColor(const SkColor& color) { |
194 disabled_color_ = color; | 144 requested_pressed_color_ = color; |
195 ValidateStyle(); | 145 if (pressed_) |
| 146 Label::SetEnabledColor(requested_pressed_color_); |
196 } | 147 } |
197 | 148 |
198 void Link::SetNormalColor(const SkColor& color) { | 149 void Link::Init() { |
199 normal_color_ = color; | 150 static bool initialized = false; |
200 ValidateStyle(); | 151 static SkColor kDefaultEnabledColor; |
| 152 static SkColor kDefaultDisabledColor; |
| 153 static SkColor kDefaultPressedColor; |
| 154 if (!initialized) { |
| 155 #if defined(OS_WIN) |
| 156 kDefaultEnabledColor = color_utils::GetSysSkColor(COLOR_HOTLIGHT); |
| 157 kDefaultDisabledColor = color_utils::GetSysSkColor(COLOR_WINDOWTEXT); |
| 158 kDefaultPressedColor = SkColorSetRGB(200, 0, 0); |
| 159 #else |
| 160 // TODO(beng): source from theme provider. |
| 161 kDefaultEnabledColor = SkColorSetRGB(0, 51, 153); |
| 162 kDefaultDisabledColor = SK_ColorBLACK; |
| 163 kDefaultPressedColor = SK_ColorRED; |
| 164 #endif |
| 165 |
| 166 initialized = true; |
| 167 } |
| 168 |
| 169 listener_ = NULL; |
| 170 pressed_ = false; |
| 171 SetEnabledColor(kDefaultEnabledColor); |
| 172 SetDisabledColor(kDefaultDisabledColor); |
| 173 SetPressedColor(kDefaultPressedColor); |
| 174 RecalculateFont(); |
| 175 set_focusable(true); |
201 } | 176 } |
202 | 177 |
203 void Link::MakeReadableOverBackgroundColor(const SkColor& color) { | 178 void Link::SetPressed(bool pressed) { |
204 GetColors(&color, &highlighted_color_, &disabled_color_, &normal_color_); | 179 if (pressed_ != pressed) { |
205 ValidateStyle(); | 180 pressed_ = pressed; |
206 } | 181 Label::SetEnabledColor(pressed_ ? |
207 | 182 requested_pressed_color_ : requested_enabled_color_); |
208 void Link::SetHighlighted(bool f) { | 183 RecalculateFont(); |
209 if (f != highlighted_) { | |
210 highlighted_ = f; | |
211 ValidateStyle(); | |
212 SchedulePaint(); | 184 SchedulePaint(); |
213 } | 185 } |
214 } | 186 } |
215 | 187 |
216 void Link::ValidateStyle() { | 188 void Link::RecalculateFont() { |
217 if (IsEnabled()) { | 189 // The font should be underlined iff the link is enabled. |
218 if (!(font().GetStyle() & gfx::Font::UNDERLINED)) { | 190 if (IsEnabled() == !(font().GetStyle() & gfx::Font::UNDERLINED)) { |
219 Label::SetFont( | 191 Label::SetFont(font().DeriveFont(0, IsEnabled() ? |
220 font().DeriveFont(0, font().GetStyle() | gfx::Font::UNDERLINED)); | 192 (font().GetStyle() | gfx::Font::UNDERLINED) : |
221 } | 193 (font().GetStyle() & ~gfx::Font::UNDERLINED))); |
222 Label::SetColor(highlighted_ ? highlighted_color_ : normal_color_); | |
223 } else { | |
224 if (font().GetStyle() & gfx::Font::UNDERLINED) { | |
225 Label::SetFont( | |
226 font().DeriveFont(0, font().GetStyle() & ~gfx::Font::UNDERLINED)); | |
227 } | |
228 Label::SetColor(disabled_color_); | |
229 } | 194 } |
230 } | 195 } |
231 | 196 |
232 } // namespace views | 197 } // namespace views |
OLD | NEW |