Chromium Code Reviews| 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 <algorithm> | 7 #include <algorithm> |
| 8 #include <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| 11 #include "base/utf_string_conversions.h" | 11 #include "base/utf_string_conversions.h" |
| 12 #include "chrome/browser/ui/autofill/autofill_popup_delegate.h" | 12 #include "chrome/browser/ui/autofill/autofill_popup_delegate.h" |
| 13 #include "chrome/browser/ui/autofill/autofill_popup_view.h" | 13 #include "chrome/browser/ui/autofill/autofill_popup_view.h" |
| 14 #include "content/public/browser/native_web_keyboard_event.h" | 14 #include "content/public/browser/native_web_keyboard_event.h" |
| 15 #include "grit/webkit_resources.h" | 15 #include "grit/webkit_resources.h" |
| 16 #include "third_party/WebKit/Source/WebKit/chromium/public/WebAutofillClient.h" | 16 #include "third_party/WebKit/Source/WebKit/chromium/public/WebAutofillClient.h" |
| 17 #include "ui/base/events/event.h" | 17 #include "ui/base/events/event.h" |
| 18 #include "ui/base/text/text_elider.h" | 18 #include "ui/base/text/text_elider.h" |
| 19 #include "ui/gfx/display.h" | 19 #include "ui/gfx/display.h" |
| 20 #include "ui/gfx/rect_conversions.h" | |
| 20 #include "ui/gfx/screen.h" | 21 #include "ui/gfx/screen.h" |
| 21 #include "ui/gfx/vector2d.h" | 22 #include "ui/gfx/vector2d.h" |
| 22 | 23 |
| 23 using WebKit::WebAutofillClient; | 24 using WebKit::WebAutofillClient; |
| 24 | 25 |
| 25 namespace { | 26 namespace { |
| 26 | 27 |
| 27 // Used to indicate that no line is currently selected by the user. | 28 // Used to indicate that no line is currently selected by the user. |
| 28 const int kNoSelection = -1; | 29 const int kNoSelection = -1; |
| 29 | 30 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 67 { "visaCC", IDR_AUTOFILL_CC_VISA }, | 68 { "visaCC", IDR_AUTOFILL_CC_VISA }, |
| 68 }; | 69 }; |
| 69 | 70 |
| 70 } // end namespace | 71 } // end namespace |
| 71 | 72 |
| 72 // static | 73 // static |
| 73 AutofillPopupControllerImpl* AutofillPopupControllerImpl::GetOrCreate( | 74 AutofillPopupControllerImpl* AutofillPopupControllerImpl::GetOrCreate( |
| 74 AutofillPopupControllerImpl* previous, | 75 AutofillPopupControllerImpl* previous, |
| 75 AutofillPopupDelegate* delegate, | 76 AutofillPopupDelegate* delegate, |
| 76 gfx::NativeView container_view, | 77 gfx::NativeView container_view, |
| 77 const gfx::Rect& element_bounds) { | 78 const gfx::RectF& element_bounds) { |
| 78 DCHECK(!previous || previous->delegate_ == delegate); | 79 DCHECK(!previous || previous->delegate_ == delegate); |
| 79 | 80 |
| 80 if (previous && | 81 if (previous && |
| 81 previous->container_view() == container_view && | 82 previous->container_view() == container_view && |
| 82 previous->element_bounds() == element_bounds) { | 83 previous->element_bounds() == element_bounds) { |
| 83 return previous; | 84 return previous; |
| 84 } | 85 } |
| 85 | 86 |
| 86 if (previous) | 87 if (previous) |
| 87 previous->Hide(); | 88 previous->Hide(); |
| 88 | 89 |
| 89 return new AutofillPopupControllerImpl( | 90 return new AutofillPopupControllerImpl( |
| 90 delegate, container_view, element_bounds); | 91 delegate, container_view, element_bounds); |
| 91 } | 92 } |
| 92 | 93 |
| 93 AutofillPopupControllerImpl::AutofillPopupControllerImpl( | 94 AutofillPopupControllerImpl::AutofillPopupControllerImpl( |
| 94 AutofillPopupDelegate* delegate, | 95 AutofillPopupDelegate* delegate, |
| 95 gfx::NativeView container_view, | 96 gfx::NativeView container_view, |
| 96 const gfx::Rect& element_bounds) | 97 const gfx::RectF& element_bounds) |
| 97 : view_(NULL), | 98 : view_(NULL), |
| 98 delegate_(delegate), | 99 delegate_(delegate), |
| 99 container_view_(container_view), | 100 container_view_(container_view), |
| 100 element_bounds_(element_bounds), | 101 element_bounds_(element_bounds), |
| 101 selected_line_(kNoSelection), | 102 selected_line_(kNoSelection), |
| 102 delete_icon_hovered_(false), | 103 delete_icon_hovered_(false), |
| 103 is_hiding_(false), | 104 is_hiding_(false), |
| 104 inform_delegate_of_destruction_(true) { | 105 inform_delegate_of_destruction_(true) { |
| 105 #if !defined(OS_ANDROID) | 106 #if !defined(OS_ANDROID) |
| 106 subtext_font_ = name_font_.DeriveFont(kLabelFontSizeDelta); | 107 subtext_font_ = name_font_.DeriveFont(kLabelFontSizeDelta); |
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 280 } | 281 } |
| 281 | 282 |
| 282 const gfx::Rect& AutofillPopupControllerImpl::popup_bounds() const { | 283 const gfx::Rect& AutofillPopupControllerImpl::popup_bounds() const { |
| 283 return popup_bounds_; | 284 return popup_bounds_; |
| 284 } | 285 } |
| 285 | 286 |
| 286 gfx::NativeView AutofillPopupControllerImpl::container_view() const { | 287 gfx::NativeView AutofillPopupControllerImpl::container_view() const { |
| 287 return container_view_; | 288 return container_view_; |
| 288 } | 289 } |
| 289 | 290 |
| 290 const gfx::Rect& AutofillPopupControllerImpl::element_bounds() const { | 291 const gfx::RectF& AutofillPopupControllerImpl::element_bounds() const { |
| 291 return element_bounds_; | 292 return element_bounds_; |
| 292 } | 293 } |
| 293 | 294 |
| 295 const gfx::Rect AutofillPopupControllerImpl::rounded_element_bounds() const { | |
|
Ilya Sherman
2013/02/05 02:27:53
nit: This method is not a trivial member variable
aurimas (slooooooooow)
2013/02/06 00:05:27
Done.
| |
| 296 return gfx::ToNearestRect(element_bounds_); | |
| 297 } | |
| 298 | |
| 294 const std::vector<string16>& AutofillPopupControllerImpl::names() const { | 299 const std::vector<string16>& AutofillPopupControllerImpl::names() const { |
| 295 return names_; | 300 return names_; |
| 296 } | 301 } |
| 297 | 302 |
| 298 const std::vector<string16>& AutofillPopupControllerImpl::subtexts() const { | 303 const std::vector<string16>& AutofillPopupControllerImpl::subtexts() const { |
| 299 return subtexts_; | 304 return subtexts_; |
| 300 } | 305 } |
| 301 | 306 |
| 302 const std::vector<string16>& AutofillPopupControllerImpl::icons() const { | 307 const std::vector<string16>& AutofillPopupControllerImpl::icons() const { |
| 303 return icons_; | 308 return icons_; |
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 498 } | 503 } |
| 499 | 504 |
| 500 #if !defined(OS_ANDROID) | 505 #if !defined(OS_ANDROID) |
| 501 int AutofillPopupControllerImpl::GetDesiredPopupWidth() const { | 506 int AutofillPopupControllerImpl::GetDesiredPopupWidth() const { |
| 502 if (!name_font_.platform_font() || !subtext_font_.platform_font()) { | 507 if (!name_font_.platform_font() || !subtext_font_.platform_font()) { |
| 503 // We can't calculate the size of the popup if the fonts | 508 // We can't calculate the size of the popup if the fonts |
| 504 // aren't present. | 509 // aren't present. |
| 505 return 0; | 510 return 0; |
| 506 } | 511 } |
| 507 | 512 |
| 508 int popup_width = element_bounds().width(); | 513 int popup_width = rounded_element_bounds().width(); |
| 509 DCHECK_EQ(names().size(), subtexts().size()); | 514 DCHECK_EQ(names().size(), subtexts().size()); |
| 510 for (size_t i = 0; i < names().size(); ++i) { | 515 for (size_t i = 0; i < names().size(); ++i) { |
| 511 int row_size = name_font_.GetStringWidth(names()[i]) + | 516 int row_size = name_font_.GetStringWidth(names()[i]) + |
| 512 subtext_font_.GetStringWidth(subtexts()[i]) + | 517 subtext_font_.GetStringWidth(subtexts()[i]) + |
| 513 RowWidthWithoutText(i); | 518 RowWidthWithoutText(i); |
| 514 | 519 |
| 515 popup_width = std::max(popup_width, row_size); | 520 popup_width = std::max(popup_width, row_size); |
| 516 } | 521 } |
| 517 | 522 |
| 518 return popup_width; | 523 return popup_width; |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 544 | 549 |
| 545 return row_size; | 550 return row_size; |
| 546 } | 551 } |
| 547 | 552 |
| 548 void AutofillPopupControllerImpl::UpdatePopupBounds() { | 553 void AutofillPopupControllerImpl::UpdatePopupBounds() { |
| 549 int popup_required_width = GetDesiredPopupWidth(); | 554 int popup_required_width = GetDesiredPopupWidth(); |
| 550 int popup_height = GetDesiredPopupHeight(); | 555 int popup_height = GetDesiredPopupHeight(); |
| 551 // This is the top left point of the popup if the popup is above the element | 556 // This is the top left point of the popup if the popup is above the element |
| 552 // and grows to the left (since that is the highest and furthest left the | 557 // and grows to the left (since that is the highest and furthest left the |
| 553 // popup go could). | 558 // popup go could). |
| 554 gfx::Point top_left_corner_of_popup = element_bounds().origin() + | 559 gfx::Point top_left_corner_of_popup = rounded_element_bounds().origin() + |
| 555 gfx::Vector2d(element_bounds().width() - popup_required_width, | 560 gfx::Vector2d(rounded_element_bounds().width() - popup_required_width, |
| 556 -popup_height); | 561 -popup_height); |
| 557 | 562 |
| 558 // This is the bottom right point of the popup if the popup is below the | 563 // This is the bottom right point of the popup if the popup is below the |
| 559 // element and grows to the right (since the is the lowest and furthest right | 564 // element and grows to the right (since the is the lowest and furthest right |
| 560 // the popup could go). | 565 // the popup could go). |
| 561 gfx::Point bottom_right_corner_of_popup = element_bounds().origin() + | 566 gfx::Point bottom_right_corner_of_popup = rounded_element_bounds().origin() + |
| 562 gfx::Vector2d(popup_required_width, | 567 gfx::Vector2d(popup_required_width, |
| 563 element_bounds().height() + popup_height); | 568 rounded_element_bounds().height() + popup_height); |
| 564 | 569 |
| 565 gfx::Display top_left_display = GetDisplayNearestPoint( | 570 gfx::Display top_left_display = GetDisplayNearestPoint( |
| 566 top_left_corner_of_popup); | 571 top_left_corner_of_popup); |
| 567 gfx::Display bottom_right_display = GetDisplayNearestPoint( | 572 gfx::Display bottom_right_display = GetDisplayNearestPoint( |
| 568 bottom_right_corner_of_popup); | 573 bottom_right_corner_of_popup); |
| 569 | 574 |
| 570 std::pair<int, int> popup_x_and_width = CalculatePopupXAndWidth( | 575 std::pair<int, int> popup_x_and_width = CalculatePopupXAndWidth( |
| 571 top_left_display, bottom_right_display, popup_required_width); | 576 top_left_display, bottom_right_display, popup_required_width); |
| 572 std::pair<int, int> popup_y_and_height = CalculatePopupYAndHeight( | 577 std::pair<int, int> popup_y_and_height = CalculatePopupYAndHeight( |
| 573 top_left_display, bottom_right_display, popup_height); | 578 top_left_display, bottom_right_display, popup_height); |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 591 int popup_required_width) const { | 596 int popup_required_width) const { |
| 592 int leftmost_display_x = left_display.bounds().x() * | 597 int leftmost_display_x = left_display.bounds().x() * |
| 593 left_display.device_scale_factor(); | 598 left_display.device_scale_factor(); |
| 594 int rightmost_display_x = right_display.GetSizeInPixel().width() + | 599 int rightmost_display_x = right_display.GetSizeInPixel().width() + |
| 595 right_display.bounds().x() * right_display.device_scale_factor(); | 600 right_display.bounds().x() * right_display.device_scale_factor(); |
| 596 | 601 |
| 597 // Calculate the start coordinates for the popup if it is growing right or | 602 // Calculate the start coordinates for the popup if it is growing right or |
| 598 // the end position if it is growing to the left, capped to screen space. | 603 // the end position if it is growing to the left, capped to screen space. |
| 599 int right_growth_start = std::max(leftmost_display_x, | 604 int right_growth_start = std::max(leftmost_display_x, |
| 600 std::min(rightmost_display_x, | 605 std::min(rightmost_display_x, |
| 601 element_bounds().x())); | 606 rounded_element_bounds().x())); |
| 602 int left_growth_end = std::max(leftmost_display_x, | 607 int left_growth_end = std::max(leftmost_display_x, |
| 603 std::min(rightmost_display_x, | 608 std::min(rightmost_display_x, |
| 604 element_bounds().right())); | 609 rounded_element_bounds().right())); |
| 605 | 610 |
| 606 int right_available = rightmost_display_x - right_growth_start; | 611 int right_available = rightmost_display_x - right_growth_start; |
| 607 int left_available = left_growth_end - leftmost_display_x; | 612 int left_available = left_growth_end - leftmost_display_x; |
| 608 | 613 |
| 609 int popup_width = std::min(popup_required_width, | 614 int popup_width = std::min(popup_required_width, |
| 610 std::max(right_available, left_available)); | 615 std::max(right_available, left_available)); |
| 611 | 616 |
| 612 // If there is enough space for the popup on the right, show it there, | 617 // If there is enough space for the popup on the right, show it there, |
| 613 // otherwise choose the larger size. | 618 // otherwise choose the larger size. |
| 614 if (right_available >= popup_width || right_available >= left_available) | 619 if (right_available >= popup_width || right_available >= left_available) |
| 615 return std::make_pair(right_growth_start, popup_width); | 620 return std::make_pair(right_growth_start, popup_width); |
| 616 else | 621 else |
| 617 return std::make_pair(left_growth_end - popup_width, popup_width); | 622 return std::make_pair(left_growth_end - popup_width, popup_width); |
| 618 } | 623 } |
| 619 | 624 |
| 620 std::pair<int,int> AutofillPopupControllerImpl::CalculatePopupYAndHeight( | 625 std::pair<int,int> AutofillPopupControllerImpl::CalculatePopupYAndHeight( |
| 621 const gfx::Display& top_display, | 626 const gfx::Display& top_display, |
| 622 const gfx::Display& bottom_display, | 627 const gfx::Display& bottom_display, |
| 623 int popup_required_height) const { | 628 int popup_required_height) const { |
| 624 int topmost_display_y = top_display.bounds().y() * | 629 int topmost_display_y = top_display.bounds().y() * |
| 625 top_display.device_scale_factor(); | 630 top_display.device_scale_factor(); |
| 626 int bottommost_display_y = bottom_display.GetSizeInPixel().height() + | 631 int bottommost_display_y = bottom_display.GetSizeInPixel().height() + |
| 627 (bottom_display.bounds().y() * | 632 (bottom_display.bounds().y() * |
| 628 bottom_display.device_scale_factor()); | 633 bottom_display.device_scale_factor()); |
| 629 | 634 |
| 630 // Calculate the start coordinates for the popup if it is growing down or | 635 // Calculate the start coordinates for the popup if it is growing down or |
| 631 // the end position if it is growing up, capped to screen space. | 636 // the end position if it is growing up, capped to screen space. |
| 632 int top_growth_end = std::max(topmost_display_y, | 637 int top_growth_end = std::max(topmost_display_y, |
| 633 std::min(bottommost_display_y, | 638 std::min(bottommost_display_y, |
| 634 element_bounds().y())); | 639 rounded_element_bounds().y())); |
| 635 int bottom_growth_start = std::max(topmost_display_y, | 640 int bottom_growth_start = std::max(topmost_display_y, |
| 636 std::min(bottommost_display_y, | 641 std::min(bottommost_display_y, rounded_element_bounds().bottom())); |
| 637 element_bounds().bottom())); | |
| 638 | 642 |
| 639 int top_available = bottom_growth_start - topmost_display_y; | 643 int top_available = bottom_growth_start - topmost_display_y; |
| 640 int bottom_available = bottommost_display_y - top_growth_end; | 644 int bottom_available = bottommost_display_y - top_growth_end; |
| 641 | 645 |
| 642 // TODO(csharp): Restrict the popup height to what is available. | 646 // TODO(csharp): Restrict the popup height to what is available. |
| 643 if (bottom_available >= popup_required_height || | 647 if (bottom_available >= popup_required_height || |
| 644 bottom_available >= top_available) { | 648 bottom_available >= top_available) { |
| 645 // The popup can appear below the field. | 649 // The popup can appear below the field. |
| 646 return std::make_pair(bottom_growth_start, popup_required_height); | 650 return std::make_pair(bottom_growth_start, popup_required_height); |
| 647 } else { | 651 } else { |
| 648 // The popup must appear above the field. | 652 // The popup must appear above the field. |
| 649 return std::make_pair(top_growth_end - popup_required_height, | 653 return std::make_pair(top_growth_end - popup_required_height, |
| 650 popup_required_height); | 654 popup_required_height); |
| 651 } | 655 } |
| 652 } | 656 } |
| OLD | NEW |