OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/browser/ui/autofill/autofill_popup_controller_impl.h" | 5 #include "chrome/browser/ui/autofill/autofill_popup_controller_impl.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "base/utf_string_conversions.h" | 8 #include "base/utf_string_conversions.h" |
9 #include "chrome/browser/ui/autofill/autofill_popup_delegate.h" | 9 #include "chrome/browser/ui/autofill/autofill_popup_delegate.h" |
10 #include "chrome/browser/ui/autofill/autofill_popup_view.h" | 10 #include "chrome/browser/ui/autofill/autofill_popup_view.h" |
11 #include "content/public/browser/native_web_keyboard_event.h" | 11 #include "content/public/browser/native_web_keyboard_event.h" |
12 #include "grit/webkit_resources.h" | 12 #include "grit/webkit_resources.h" |
13 #include "third_party/WebKit/Source/WebKit/chromium/public/WebAutofillClient.h" | 13 #include "third_party/WebKit/Source/WebKit/chromium/public/WebAutofillClient.h" |
14 #include "ui/base/events/event.h" | 14 #include "ui/base/events/event.h" |
15 #include "ui/base/text/text_elider.h" | |
16 #include "ui/gfx/display.h" | |
17 #include "ui/gfx/screen.h" | |
18 #include "ui/gfx/vector2d.h" | |
15 | 19 |
16 using WebKit::WebAutofillClient; | 20 using WebKit::WebAutofillClient; |
17 | 21 |
18 namespace { | 22 namespace { |
19 | 23 |
20 // Used to indicate that no line is currently selected by the user. | 24 // Used to indicate that no line is currently selected by the user. |
21 const int kNoSelection = -1; | 25 const int kNoSelection = -1; |
22 | 26 |
23 // Size difference between name and subtext in pixels. | 27 // Size difference between name and subtext in pixels. |
24 const int kLabelFontSizeDelta = -2; | 28 const int kLabelFontSizeDelta = -2; |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
111 const std::vector<string16>& icons, | 115 const std::vector<string16>& icons, |
112 const std::vector<int>& identifiers) { | 116 const std::vector<int>& identifiers) { |
113 names_ = names; | 117 names_ = names; |
114 subtexts_ = subtexts; | 118 subtexts_ = subtexts; |
115 icons_ = icons; | 119 icons_ = icons; |
116 identifiers_ = identifiers; | 120 identifiers_ = identifiers; |
117 | 121 |
118 #if !defined(OS_ANDROID) | 122 #if !defined(OS_ANDROID) |
119 // Android displays the long text with ellipsis using the view attributes. | 123 // Android displays the long text with ellipsis using the view attributes. |
120 | 124 |
121 // TODO(csharp): Fix crbug.com/156163 and use better logic when clipping. | 125 int popup_width = CalculateAndSetPopupWidth(); |
126 | |
127 // Elide the name and subtext strings so that the popup fits in the available | |
128 // space. | |
122 for (size_t i = 0; i < names_.size(); ++i) { | 129 for (size_t i = 0; i < names_.size(); ++i) { |
123 if (names_[i].length() > 15) | 130 int total_text_length = name_font().GetStringWidth(names[i]) + |
124 names_[i].erase(15); | 131 subtext_font().GetStringWidth(subtexts_[i]); |
125 if (subtexts[i].length() > 15) | 132 // The line can have no strings if it represents a UI element, such as |
126 subtexts_[i].erase(15); | 133 // a separator line. |
134 if (total_text_length == 0) | |
135 continue; | |
136 | |
137 int available_width = popup_width - RowWidthWithoutText(i); | |
138 | |
139 // Each field recieves space in proportion to its length. | |
140 int name_size = available_width * | |
141 name_font().GetStringWidth(names_[i]) / total_text_length; | |
Ilya Sherman
2013/01/11 23:05:35
nit: Might be worth caching the result of the GetS
csharp
2013/01/14 20:32:33
Done.
| |
142 names_[i] = ui::ElideText(names_[i], | |
143 name_font(), | |
144 name_size, | |
145 ui::ELIDE_AT_END); | |
146 | |
147 int subtext_size = available_width * | |
148 subtext_font().GetStringWidth(subtexts[i]) / total_text_length; | |
149 subtexts_[i] = ui::ElideText(subtexts_[i], | |
150 subtext_font(), | |
151 subtext_size, | |
152 ui::ELIDE_AT_END); | |
127 } | 153 } |
128 #endif | 154 #endif |
129 | 155 |
130 if (!view_) { | 156 if (!view_) { |
131 view_ = AutofillPopupView::Create(this); | 157 view_ = AutofillPopupView::Create(this); |
132 ShowView(); | 158 ShowView(); |
133 } else { | 159 } else { |
134 UpdateBoundsAndRedrawPopup(); | 160 UpdateBoundsAndRedrawPopup(); |
135 } | 161 } |
136 } | 162 } |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
191 } | 217 } |
192 | 218 |
193 bool AutofillPopupControllerImpl::CanDelete(size_t index) { | 219 bool AutofillPopupControllerImpl::CanDelete(size_t index) { |
194 int id = identifiers_[index]; | 220 int id = identifiers_[index]; |
195 return id > 0 || | 221 return id > 0 || |
196 id == WebAutofillClient::MenuItemIDAutocompleteEntry || | 222 id == WebAutofillClient::MenuItemIDAutocompleteEntry || |
197 id == WebAutofillClient::MenuItemIDPasswordEntry; | 223 id == WebAutofillClient::MenuItemIDPasswordEntry; |
198 } | 224 } |
199 | 225 |
200 #if !defined(OS_ANDROID) | 226 #if !defined(OS_ANDROID) |
201 int AutofillPopupControllerImpl::GetPopupRequiredWidth() { | 227 int AutofillPopupControllerImpl::GetPopupRequiredWidth() { |
Ilya Sherman
2013/01/11 23:05:35
Rather than exposing this method to the view, IMO
csharp
2013/01/14 20:32:33
Done.
| |
202 if (name_font_.platform_font() == NULL || | 228 if (name_font_.platform_font() == NULL || |
203 subtext_font_.platform_font() == NULL) { | 229 subtext_font_.platform_font() == NULL) { |
204 // We can't calculate the size of the popup if the fonts | 230 // We can't calculate the size of the popup if the fonts |
205 // aren't present. | 231 // aren't present. |
206 return 0; | 232 return 0; |
207 } | 233 } |
208 | 234 |
209 int popup_width = element_bounds().width(); | 235 int popup_width = element_bounds().width(); |
210 DCHECK_EQ(names().size(), subtexts().size()); | 236 DCHECK_EQ(names().size(), subtexts().size()); |
211 for (size_t i = 0; i < names().size(); ++i) { | 237 for (size_t i = 0; i < names().size(); ++i) { |
212 int row_size = kEndPadding + | 238 int row_size = name_font_.GetStringWidth(names()[i]) + |
213 name_font_.GetStringWidth(names()[i]) + | 239 subtext_font_.GetStringWidth(subtexts()[i]) + |
214 kNamePadding + | 240 RowWidthWithoutText(i); |
215 subtext_font_.GetStringWidth(subtexts()[i]); | |
216 | |
217 // Add the Autofill icon size, if required. | |
218 if (!icons()[i].empty()) | |
219 row_size += kAutofillIconWidth + kIconPadding; | |
220 | |
221 // Add delete icon, if required. | |
222 if (CanDelete(i)) | |
223 row_size += kDeleteIconWidth + kIconPadding; | |
224 | |
225 // Add the padding at the end | |
226 row_size += kEndPadding; | |
227 | 241 |
228 popup_width = std::max(popup_width, row_size); | 242 popup_width = std::max(popup_width, row_size); |
229 } | 243 } |
230 | 244 |
231 return popup_width; | 245 return popup_width; |
232 } | 246 } |
233 | 247 |
234 int AutofillPopupControllerImpl::GetPopupRequiredHeight() { | 248 int AutofillPopupControllerImpl::GetPopupRequiredHeight() { |
235 int popup_height = 0; | 249 int popup_height = 0; |
236 | 250 |
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
497 identifiers_[0] == WebAutofillClient::MenuItemIDDataListEntry); | 511 identifiers_[0] == WebAutofillClient::MenuItemIDDataListEntry); |
498 } | 512 } |
499 | 513 |
500 void AutofillPopupControllerImpl::ShowView() { | 514 void AutofillPopupControllerImpl::ShowView() { |
501 view_->Show(); | 515 view_->Show(); |
502 } | 516 } |
503 | 517 |
504 void AutofillPopupControllerImpl::InvalidateRow(size_t row) { | 518 void AutofillPopupControllerImpl::InvalidateRow(size_t row) { |
505 view_->InvalidateRow(row); | 519 view_->InvalidateRow(row); |
506 } | 520 } |
521 | |
522 int AutofillPopupControllerImpl::RowWidthWithoutText(int row) { | |
523 int row_size = kEndPadding + kNamePadding; | |
524 | |
525 // Add the Autofill icon size, if required. | |
526 if (!icons_[row].empty()) | |
527 row_size += kAutofillIconWidth + kIconPadding; | |
528 | |
529 // Add the delete icon size, if required. | |
530 if (CanDelete(row)) | |
531 row_size += kDeleteIconWidth + kIconPadding; | |
532 | |
533 // Add the padding at the end | |
534 row_size += kEndPadding; | |
535 | |
536 return row_size; | |
537 } | |
538 | |
539 int AutofillPopupControllerImpl::CalculateAndSetPopupWidth() { | |
540 int popup_required_width = GetPopupRequiredWidth(); | |
541 gfx::Point right_corner_of_popup = element_bounds().origin() + | |
542 gfx::Vector2d(popup_required_width, 0); | |
543 | |
544 gfx::Screen* screen = | |
545 gfx::Screen::GetScreenFor(container_view()); | |
546 gfx::Display left_display = screen->GetDisplayNearestPoint( | |
547 element_bounds().origin()); | |
Ilya Sherman
2013/01/11 23:05:35
Hmm, shouldn't this be the display that's at the l
csharp
2013/01/14 20:32:33
Yup, fixed.
| |
548 gfx::Display right_display = screen->GetDisplayNearestPoint( | |
549 right_corner_of_popup); | |
550 | |
551 int leftmost_display_x = left_display.bounds().x() * | |
552 left_display.device_scale_factor(); | |
553 int rightmost_display_x = right_display.GetSizeInPixel().width() + | |
554 right_display.bounds().x() * right_display.device_scale_factor(); | |
555 | |
556 // Calculate the leftmost and rightmost values the popup can have without | |
557 // going off the screen. | |
558 int popup_left_cutoff = std::max(element_bounds().origin().x(), | |
559 leftmost_display_x); | |
Ilya Sherman
2013/01/11 23:05:35
nit: indentation
csharp
2013/01/14 20:32:33
Done.
| |
560 int popup_right_cutoff = std::min(element_bounds().top_right().x(), | |
561 rightmost_display_x); | |
Ilya Sherman
2013/01/11 23:05:35
nit: indentation
csharp
2013/01/14 20:32:33
Done.
| |
562 | |
563 int right_available = rightmost_display_x - popup_left_cutoff; | |
564 int left_available = popup_right_cutoff - leftmost_display_x; | |
565 | |
566 int popup_width = std::min(popup_required_width, | |
567 std::max(right_available, left_available)); | |
Ilya Sherman
2013/01/11 23:05:35
nit: #include <algorithm> for std::min and ::max.
csharp
2013/01/14 20:32:33
Done.
| |
568 // If there is enough space for the popup on the right, show it there, | |
569 // otherwise choose the larger size. | |
570 if (right_available >= popup_width || right_available >= left_available) { | |
571 popup_bounds_.set_x(popup_left_cutoff); | |
572 } else { | |
573 popup_bounds_.set_x(popup_right_cutoff - popup_width); | |
574 } | |
Ilya Sherman
2013/01/11 23:05:35
nit: No need for curlies
csharp
2013/01/14 20:32:33
Done.
| |
575 | |
576 return popup_width; | |
577 } | |
OLD | NEW |