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" |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 60 { "americanExpressCC", IDR_AUTOFILL_CC_AMEX }, | 60 { "americanExpressCC", IDR_AUTOFILL_CC_AMEX }, |
| 61 { "dinersCC", IDR_AUTOFILL_CC_DINERS }, | 61 { "dinersCC", IDR_AUTOFILL_CC_DINERS }, |
| 62 { "discoverCC", IDR_AUTOFILL_CC_DISCOVER }, | 62 { "discoverCC", IDR_AUTOFILL_CC_DISCOVER }, |
| 63 { "genericCC", IDR_AUTOFILL_CC_GENERIC }, | 63 { "genericCC", IDR_AUTOFILL_CC_GENERIC }, |
| 64 { "jcbCC", IDR_AUTOFILL_CC_JCB }, | 64 { "jcbCC", IDR_AUTOFILL_CC_JCB }, |
| 65 { "masterCardCC", IDR_AUTOFILL_CC_MASTERCARD }, | 65 { "masterCardCC", IDR_AUTOFILL_CC_MASTERCARD }, |
| 66 { "soloCC", IDR_AUTOFILL_CC_SOLO }, | 66 { "soloCC", IDR_AUTOFILL_CC_SOLO }, |
| 67 { "visaCC", IDR_AUTOFILL_CC_VISA }, | 67 { "visaCC", IDR_AUTOFILL_CC_VISA }, |
| 68 }; | 68 }; |
| 69 | 69 |
| 70 int round(float x) { | |
| 71 return x >= 0 ? floor(x + 0.5) : ceil(x - 0.5); | |
| 72 } | |
| 73 | |
| 70 } // end namespace | 74 } // end namespace |
| 71 | 75 |
| 72 // static | 76 // static |
| 73 AutofillPopupControllerImpl* AutofillPopupControllerImpl::GetOrCreate( | 77 AutofillPopupControllerImpl* AutofillPopupControllerImpl::GetOrCreate( |
| 74 AutofillPopupControllerImpl* previous, | 78 AutofillPopupControllerImpl* previous, |
| 75 AutofillPopupDelegate* delegate, | 79 AutofillPopupDelegate* delegate, |
| 76 gfx::NativeView container_view, | 80 gfx::NativeView container_view, |
| 77 const gfx::Rect& element_bounds) { | 81 const gfx::RectF& element_bounds) { |
| 78 DCHECK(!previous || previous->delegate_ == delegate); | 82 DCHECK(!previous || previous->delegate_ == delegate); |
| 79 | 83 |
| 80 if (previous && | 84 if (previous && |
| 81 previous->container_view() == container_view && | 85 previous->container_view() == container_view && |
| 82 previous->element_bounds() == element_bounds) { | 86 previous->element_bounds() == element_bounds) { |
| 83 return previous; | 87 return previous; |
| 84 } | 88 } |
| 85 | 89 |
| 86 if (previous) | 90 if (previous) |
| 87 previous->Hide(); | 91 previous->Hide(); |
| 88 | 92 |
| 89 return new AutofillPopupControllerImpl( | 93 return new AutofillPopupControllerImpl( |
| 90 delegate, container_view, element_bounds); | 94 delegate, container_view, element_bounds); |
| 91 } | 95 } |
| 92 | 96 |
| 93 AutofillPopupControllerImpl::AutofillPopupControllerImpl( | 97 AutofillPopupControllerImpl::AutofillPopupControllerImpl( |
| 94 AutofillPopupDelegate* delegate, | 98 AutofillPopupDelegate* delegate, |
| 95 gfx::NativeView container_view, | 99 gfx::NativeView container_view, |
| 96 const gfx::Rect& element_bounds) | 100 const gfx::RectF& element_bounds) |
| 97 : view_(NULL), | 101 : view_(NULL), |
| 98 delegate_(delegate), | 102 delegate_(delegate), |
| 99 container_view_(container_view), | 103 container_view_(container_view), |
| 100 element_bounds_(element_bounds), | 104 element_bounds_(element_bounds), |
| 101 selected_line_(kNoSelection), | 105 selected_line_(kNoSelection), |
| 102 delete_icon_hovered_(false), | 106 delete_icon_hovered_(false), |
| 103 is_hiding_(false), | 107 is_hiding_(false), |
| 104 inform_delegate_of_destruction_(true) { | 108 inform_delegate_of_destruction_(true) { |
| 105 #if !defined(OS_ANDROID) | 109 #if !defined(OS_ANDROID) |
| 106 subtext_font_ = name_font_.DeriveFont(kLabelFontSizeDelta); | 110 subtext_font_ = name_font_.DeriveFont(kLabelFontSizeDelta); |
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 280 } | 284 } |
| 281 | 285 |
| 282 const gfx::Rect& AutofillPopupControllerImpl::popup_bounds() const { | 286 const gfx::Rect& AutofillPopupControllerImpl::popup_bounds() const { |
| 283 return popup_bounds_; | 287 return popup_bounds_; |
| 284 } | 288 } |
| 285 | 289 |
| 286 gfx::NativeView AutofillPopupControllerImpl::container_view() const { | 290 gfx::NativeView AutofillPopupControllerImpl::container_view() const { |
| 287 return container_view_; | 291 return container_view_; |
| 288 } | 292 } |
| 289 | 293 |
| 290 const gfx::Rect& AutofillPopupControllerImpl::element_bounds() const { | 294 const gfx::RectF& AutofillPopupControllerImpl::element_bounds() const { |
| 291 return element_bounds_; | 295 return element_bounds_; |
| 292 } | 296 } |
| 293 | 297 |
| 294 const std::vector<string16>& AutofillPopupControllerImpl::names() const { | 298 const std::vector<string16>& AutofillPopupControllerImpl::names() const { |
| 295 return names_; | 299 return names_; |
| 296 } | 300 } |
| 297 | 301 |
| 298 const std::vector<string16>& AutofillPopupControllerImpl::subtexts() const { | 302 const std::vector<string16>& AutofillPopupControllerImpl::subtexts() const { |
| 299 return subtexts_; | 303 return subtexts_; |
| 300 } | 304 } |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 498 } | 502 } |
| 499 | 503 |
| 500 #if !defined(OS_ANDROID) | 504 #if !defined(OS_ANDROID) |
| 501 int AutofillPopupControllerImpl::GetDesiredPopupWidth() const { | 505 int AutofillPopupControllerImpl::GetDesiredPopupWidth() const { |
| 502 if (!name_font_.platform_font() || !subtext_font_.platform_font()) { | 506 if (!name_font_.platform_font() || !subtext_font_.platform_font()) { |
| 503 // We can't calculate the size of the popup if the fonts | 507 // We can't calculate the size of the popup if the fonts |
| 504 // aren't present. | 508 // aren't present. |
| 505 return 0; | 509 return 0; |
| 506 } | 510 } |
| 507 | 511 |
| 508 int popup_width = element_bounds().width(); | 512 int popup_width = round(element_bounds().width()); |
| 509 DCHECK_EQ(names().size(), subtexts().size()); | 513 DCHECK_EQ(names().size(), subtexts().size()); |
| 510 for (size_t i = 0; i < names().size(); ++i) { | 514 for (size_t i = 0; i < names().size(); ++i) { |
| 511 int row_size = name_font_.GetStringWidth(names()[i]) + | 515 int row_size = name_font_.GetStringWidth(names()[i]) + |
| 512 subtext_font_.GetStringWidth(subtexts()[i]) + | 516 subtext_font_.GetStringWidth(subtexts()[i]) + |
| 513 RowWidthWithoutText(i); | 517 RowWidthWithoutText(i); |
| 514 | 518 |
| 515 popup_width = std::max(popup_width, row_size); | 519 popup_width = std::max(popup_width, row_size); |
| 516 } | 520 } |
| 517 | 521 |
| 518 return popup_width; | 522 return popup_width; |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 544 | 548 |
| 545 return row_size; | 549 return row_size; |
| 546 } | 550 } |
| 547 | 551 |
| 548 void AutofillPopupControllerImpl::UpdatePopupBounds() { | 552 void AutofillPopupControllerImpl::UpdatePopupBounds() { |
| 549 int popup_required_width = GetDesiredPopupWidth(); | 553 int popup_required_width = GetDesiredPopupWidth(); |
| 550 int popup_height = GetDesiredPopupHeight(); | 554 int popup_height = GetDesiredPopupHeight(); |
| 551 // This is the top left point of the popup if the popup is above the element | 555 // 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 | 556 // and grows to the left (since that is the highest and furthest left the |
| 553 // popup go could). | 557 // popup go could). |
| 554 gfx::Point top_left_corner_of_popup = element_bounds().origin() + | 558 gfx::Point top_left_corner_of_popup = round(element_bounds().origin()) + |
|
Ilya Sherman
2013/02/04 23:23:28
Rounding a gfx::Point doesn't compile.
| |
| 555 gfx::Vector2d(element_bounds().width() - popup_required_width, | 559 gfx::Vector2d(round(element_bounds().width()) - popup_required_width, |
| 556 -popup_height); | 560 -popup_height); |
| 557 | 561 |
| 558 // This is the bottom right point of the popup if the popup is below the | 562 // 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 | 563 // element and grows to the right (since the is the lowest and furthest right |
| 560 // the popup could go). | 564 // the popup could go). |
| 561 gfx::Point bottom_right_corner_of_popup = element_bounds().origin() + | 565 gfx::Point bottom_right_corner_of_popup = round(element_bounds().origin()) + |
|
Ilya Sherman
2013/02/04 23:23:28
Ditto.
| |
| 562 gfx::Vector2d(popup_required_width, | 566 gfx::Vector2d(popup_required_width, |
| 563 element_bounds().height() + popup_height); | 567 round(element_bounds().height()) + popup_height); |
| 564 | 568 |
| 565 gfx::Display top_left_display = GetDisplayNearestPoint( | 569 gfx::Display top_left_display = GetDisplayNearestPoint( |
| 566 top_left_corner_of_popup); | 570 top_left_corner_of_popup); |
| 567 gfx::Display bottom_right_display = GetDisplayNearestPoint( | 571 gfx::Display bottom_right_display = GetDisplayNearestPoint( |
| 568 bottom_right_corner_of_popup); | 572 bottom_right_corner_of_popup); |
| 569 | 573 |
| 570 std::pair<int, int> popup_x_and_width = CalculatePopupXAndWidth( | 574 std::pair<int, int> popup_x_and_width = CalculatePopupXAndWidth( |
| 571 top_left_display, bottom_right_display, popup_required_width); | 575 top_left_display, bottom_right_display, popup_required_width); |
| 572 std::pair<int, int> popup_y_and_height = CalculatePopupYAndHeight( | 576 std::pair<int, int> popup_y_and_height = CalculatePopupYAndHeight( |
| 573 top_left_display, bottom_right_display, popup_height); | 577 top_left_display, bottom_right_display, popup_height); |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 591 int popup_required_width) const { | 595 int popup_required_width) const { |
| 592 int leftmost_display_x = left_display.bounds().x() * | 596 int leftmost_display_x = left_display.bounds().x() * |
| 593 left_display.device_scale_factor(); | 597 left_display.device_scale_factor(); |
| 594 int rightmost_display_x = right_display.GetSizeInPixel().width() + | 598 int rightmost_display_x = right_display.GetSizeInPixel().width() + |
| 595 right_display.bounds().x() * right_display.device_scale_factor(); | 599 right_display.bounds().x() * right_display.device_scale_factor(); |
| 596 | 600 |
| 597 // Calculate the start coordinates for the popup if it is growing right or | 601 // 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. | 602 // the end position if it is growing to the left, capped to screen space. |
| 599 int right_growth_start = std::max(leftmost_display_x, | 603 int right_growth_start = std::max(leftmost_display_x, |
| 600 std::min(rightmost_display_x, | 604 std::min(rightmost_display_x, |
| 601 element_bounds().x())); | 605 round(element_bounds().x()))); |
| 602 int left_growth_end = std::max(leftmost_display_x, | 606 int left_growth_end = std::max(leftmost_display_x, |
| 603 std::min(rightmost_display_x, | 607 std::min(rightmost_display_x, |
| 604 element_bounds().right())); | 608 round(element_bounds().right()))); |
| 605 | 609 |
| 606 int right_available = rightmost_display_x - right_growth_start; | 610 int right_available = rightmost_display_x - right_growth_start; |
| 607 int left_available = left_growth_end - leftmost_display_x; | 611 int left_available = left_growth_end - leftmost_display_x; |
| 608 | 612 |
| 609 int popup_width = std::min(popup_required_width, | 613 int popup_width = std::min(popup_required_width, |
| 610 std::max(right_available, left_available)); | 614 std::max(right_available, left_available)); |
| 611 | 615 |
| 612 // If there is enough space for the popup on the right, show it there, | 616 // If there is enough space for the popup on the right, show it there, |
| 613 // otherwise choose the larger size. | 617 // otherwise choose the larger size. |
| 614 if (right_available >= popup_width || right_available >= left_available) | 618 if (right_available >= popup_width || right_available >= left_available) |
| 615 return std::make_pair(right_growth_start, popup_width); | 619 return std::make_pair(right_growth_start, popup_width); |
| 616 else | 620 else |
| 617 return std::make_pair(left_growth_end - popup_width, popup_width); | 621 return std::make_pair(left_growth_end - popup_width, popup_width); |
| 618 } | 622 } |
| 619 | 623 |
| 620 std::pair<int,int> AutofillPopupControllerImpl::CalculatePopupYAndHeight( | 624 std::pair<int,int> AutofillPopupControllerImpl::CalculatePopupYAndHeight( |
| 621 const gfx::Display& top_display, | 625 const gfx::Display& top_display, |
| 622 const gfx::Display& bottom_display, | 626 const gfx::Display& bottom_display, |
| 623 int popup_required_height) const { | 627 int popup_required_height) const { |
| 624 int topmost_display_y = top_display.bounds().y() * | 628 int topmost_display_y = top_display.bounds().y() * |
| 625 top_display.device_scale_factor(); | 629 top_display.device_scale_factor(); |
| 626 int bottommost_display_y = bottom_display.GetSizeInPixel().height() + | 630 int bottommost_display_y = bottom_display.GetSizeInPixel().height() + |
| 627 (bottom_display.bounds().y() * | 631 (bottom_display.bounds().y() * |
| 628 bottom_display.device_scale_factor()); | 632 bottom_display.device_scale_factor()); |
| 629 | 633 |
| 630 // Calculate the start coordinates for the popup if it is growing down or | 634 // 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. | 635 // the end position if it is growing up, capped to screen space. |
| 632 int top_growth_end = std::max(topmost_display_y, | 636 int top_growth_end = std::max(topmost_display_y, |
| 633 std::min(bottommost_display_y, | 637 std::min(bottommost_display_y, |
| 634 element_bounds().y())); | 638 round(element_bounds().y()))); |
| 635 int bottom_growth_start = std::max(topmost_display_y, | 639 int bottom_growth_start = std::max(topmost_display_y, |
|
Ilya Sherman
2013/02/04 23:23:28
nit: Since you're now wrapping one of the argument
| |
| 636 std::min(bottommost_display_y, | 640 std::min(bottommost_display_y, round(element_bounds().bottom()))); |
| 637 element_bounds().bottom())); | |
| 638 | 641 |
| 639 int top_available = bottom_growth_start - topmost_display_y; | 642 int top_available = bottom_growth_start - topmost_display_y; |
| 640 int bottom_available = bottommost_display_y - top_growth_end; | 643 int bottom_available = bottommost_display_y - top_growth_end; |
| 641 | 644 |
| 642 // TODO(csharp): Restrict the popup height to what is available. | 645 // TODO(csharp): Restrict the popup height to what is available. |
| 643 if (bottom_available >= popup_required_height || | 646 if (bottom_available >= popup_required_height || |
| 644 bottom_available >= top_available) { | 647 bottom_available >= top_available) { |
| 645 // The popup can appear below the field. | 648 // The popup can appear below the field. |
| 646 return std::make_pair(bottom_growth_start, popup_required_height); | 649 return std::make_pair(bottom_growth_start, popup_required_height); |
| 647 } else { | 650 } else { |
| 648 // The popup must appear above the field. | 651 // The popup must appear above the field. |
| 649 return std::make_pair(top_growth_end - popup_required_height, | 652 return std::make_pair(top_growth_end - popup_required_height, |
| 650 popup_required_height); | 653 popup_required_height); |
| 651 } | 654 } |
| 652 } | 655 } |
| OLD | NEW |