Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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/views/payments/payment_sheet_view_controller.h" | 5 #include "chrome/browser/ui/views/payments/payment_sheet_view_controller.h" |
| 6 | 6 |
| 7 #include <algorithm> | |
| 7 #include <memory> | 8 #include <memory> |
| 8 #include <utility> | 9 #include <utility> |
| 9 | 10 |
| 10 #include "base/memory/ptr_util.h" | 11 #include "base/memory/ptr_util.h" |
| 11 #include "base/strings/utf_string_conversions.h" | 12 #include "base/strings/utf_string_conversions.h" |
| 13 #include "chrome/browser/browser_process.h" | |
| 12 #include "chrome/browser/ui/views/payments/payment_request_dialog.h" | 14 #include "chrome/browser/ui/views/payments/payment_request_dialog.h" |
| 13 #include "chrome/browser/ui/views/payments/payment_request_views_util.h" | 15 #include "chrome/browser/ui/views/payments/payment_request_views_util.h" |
| 14 #include "chrome/grit/generated_resources.h" | 16 #include "chrome/grit/generated_resources.h" |
| 17 #include "components/autofill/core/browser/autofill_data_util.h" | |
| 18 #include "components/autofill/core/browser/autofill_type.h" | |
| 19 #include "components/autofill/core/browser/credit_card.h" | |
| 20 #include "components/autofill/core/browser/field_types.h" | |
| 15 #include "components/payments/payment_request.h" | 21 #include "components/payments/payment_request.h" |
| 16 #include "components/strings/grit/components_strings.h" | 22 #include "components/strings/grit/components_strings.h" |
| 23 #include "content/public/browser/web_contents.h" | |
| 17 #include "third_party/skia/include/core/SkColor.h" | 24 #include "third_party/skia/include/core/SkColor.h" |
| 18 #include "ui/base/l10n/l10n_util.h" | 25 #include "ui/base/l10n/l10n_util.h" |
| 26 #include "ui/base/resource/resource_bundle.h" | |
| 19 #include "ui/gfx/color_utils.h" | 27 #include "ui/gfx/color_utils.h" |
| 20 #include "ui/gfx/font.h" | 28 #include "ui/gfx/font.h" |
| 21 #include "ui/gfx/geometry/insets.h" | 29 #include "ui/gfx/geometry/insets.h" |
| 22 #include "ui/gfx/paint_vector_icon.h" | 30 #include "ui/gfx/paint_vector_icon.h" |
| 23 #include "ui/gfx/range/range.h" | 31 #include "ui/gfx/range/range.h" |
| 24 #include "ui/gfx/vector_icons_public.h" | 32 #include "ui/gfx/vector_icons_public.h" |
| 25 #include "ui/views/border.h" | 33 #include "ui/views/border.h" |
| 26 #include "ui/views/controls/button/custom_button.h" | 34 #include "ui/views/controls/button/custom_button.h" |
| 27 #include "ui/views/controls/button/label_button.h" | 35 #include "ui/views/controls/button/label_button.h" |
| 28 #include "ui/views/controls/button/md_text_button.h" | 36 #include "ui/views/controls/button/md_text_button.h" |
| 29 #include "ui/views/controls/image_view.h" | 37 #include "ui/views/controls/image_view.h" |
| 30 #include "ui/views/controls/label.h" | 38 #include "ui/views/controls/label.h" |
| 31 #include "ui/views/controls/styled_label.h" | 39 #include "ui/views/controls/styled_label.h" |
| 40 #include "ui/views/layout/fill_layout.h" | |
| 32 #include "ui/views/layout/grid_layout.h" | 41 #include "ui/views/layout/grid_layout.h" |
| 33 #include "ui/views/view.h" | 42 #include "ui/views/view.h" |
| 34 | 43 |
| 35 namespace payments { | 44 namespace payments { |
| 36 namespace { | 45 namespace { |
| 37 | 46 |
| 38 enum class PaymentSheetViewControllerTags { | 47 enum class PaymentSheetViewControllerTags { |
| 39 // The tag for the button that navigates to the Order Summary sheet. | 48 // The tag for the button that navigates to the Order Summary sheet. |
| 40 SHOW_ORDER_SUMMARY_BUTTON = static_cast<int>( | 49 SHOW_ORDER_SUMMARY_BUTTON = static_cast<int>( |
| 41 payments::PaymentRequestCommonTags::PAYMENT_REQUEST_COMMON_TAG_MAX), | 50 payments::PaymentRequestCommonTags::PAYMENT_REQUEST_COMMON_TAG_MAX), |
| 51 SHOW_PAYMENT_METHOD_BUTTON, | |
| 42 }; | 52 }; |
| 43 | 53 |
| 44 // Creates a clickable row to be displayed in the Payment Sheet. It contains | 54 // Creates a clickable row to be displayed in the Payment Sheet. It contains |
| 45 // a section name and some content, followed by a chevron as a clickability | 55 // a section name and some content, followed by a chevron as a clickability |
| 46 // affordance. Both, either, or none of |content_view| and |extra_content_view| | 56 // affordance. Both, either, or none of |content_view| and |extra_content_view| |
| 47 // may be present, the difference between the two being that content is pinned | 57 // may be present, the difference between the two being that content is pinned |
| 48 // to the left and extra_content is pinned to the right. | 58 // to the left and extra_content is pinned to the right. |
| 49 // The row also displays a light gray horizontal ruler on its lower boundary. | 59 // The row also displays a light gray horizontal ruler on its lower boundary. |
| 60 // The name column has a fixed width equal to |name_column_width|. | |
| 50 // +----------------------------+ | 61 // +----------------------------+ |
| 51 // | Name | Content | Extra | > | | 62 // | Name | Content | Extra | > | |
| 52 // +~~~~~~~~~~~~~~~~~~~~~~~~~~~~+ <-- ruler | 63 // +~~~~~~~~~~~~~~~~~~~~~~~~~~~~+ <-- ruler |
| 53 class PaymentSheetRow : public views::CustomButton { | 64 class PaymentSheetRow : public views::CustomButton { |
| 54 public: | 65 public: |
| 55 PaymentSheetRow(views::ButtonListener* listener, | 66 PaymentSheetRow(views::ButtonListener* listener, |
| 56 const base::string16& section_name, | 67 const base::string16& section_name, |
| 57 std::unique_ptr<views::View> content_view, | 68 std::unique_ptr<views::View> content_view, |
| 58 std::unique_ptr<views::View> extra_content_view) | 69 std::unique_ptr<views::View> extra_content_view, |
| 70 int name_column_width) | |
| 59 : views::CustomButton(listener) { | 71 : views::CustomButton(listener) { |
| 60 SetBorder(views::CreateSolidSidedBorder(0, 0, 1, 0, SK_ColorLTGRAY)); | 72 SetBorder(views::CreateSolidSidedBorder(0, 0, 1, 0, SK_ColorLTGRAY)); |
| 61 views::GridLayout* layout = new views::GridLayout(this); | 73 views::GridLayout* layout = new views::GridLayout(this); |
| 62 | 74 |
| 63 constexpr int kRowVerticalInset = 18; | 75 constexpr int kRowVerticalInset = 8; |
| 64 // The rows have extra inset compared to the header so that their right edge | 76 // The rows have extra inset compared to the header so that their right edge |
| 65 // lines up with the close button's X rather than its invisible right edge. | 77 // lines up with the close button's X rather than its invisible right edge. |
| 66 constexpr int kRowExtraRightInset = 8; | 78 constexpr int kRowExtraRightInset = 8; |
| 67 layout->SetInsets( | 79 layout->SetInsets( |
| 68 kRowVerticalInset, 0, kRowVerticalInset, kRowExtraRightInset); | 80 kRowVerticalInset, 0, kRowVerticalInset, kRowExtraRightInset); |
| 69 SetLayoutManager(layout); | 81 SetLayoutManager(layout); |
| 70 | 82 |
| 71 views::ColumnSet* columns = layout->AddColumnSet(0); | 83 views::ColumnSet* columns = layout->AddColumnSet(0); |
| 72 // A column for the section name. | 84 // A column for the section name. |
| 73 columns->AddColumn(views::GridLayout::LEADING, views::GridLayout::CENTER, | 85 columns->AddColumn(views::GridLayout::LEADING, |
| 74 0, views::GridLayout::USE_PREF, 0, 0); | 86 views::GridLayout::LEADING, |
| 87 0, | |
| 88 views::GridLayout::FIXED, | |
| 89 name_column_width, | |
| 90 0); | |
| 91 | |
| 92 constexpr int kPaddingColumnsWidth = 25; | |
| 93 columns->AddPaddingColumn(0, kPaddingColumnsWidth); | |
| 94 | |
| 75 // A column for the content. | 95 // A column for the content. |
| 76 columns->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER, | 96 columns->AddColumn(views::GridLayout::FILL, views::GridLayout::LEADING, |
| 77 1, views::GridLayout::USE_PREF, 0, 0); | 97 1, views::GridLayout::USE_PREF, 0, 0); |
| 78 // A column for the extra content. | 98 // A column for the extra content. |
| 79 columns->AddColumn(views::GridLayout::TRAILING, views::GridLayout::CENTER, | 99 columns->AddColumn(views::GridLayout::TRAILING, views::GridLayout::CENTER, |
| 80 0, views::GridLayout::USE_PREF, 0, 0); | 100 0, views::GridLayout::USE_PREF, 0, 0); |
| 81 | 101 |
| 82 constexpr int kPaddingColumnsWidth = 25; | |
| 83 columns->AddPaddingColumn(0, kPaddingColumnsWidth); | 102 columns->AddPaddingColumn(0, kPaddingColumnsWidth); |
| 84 // A column for the chevron. | 103 // A column for the chevron. |
| 85 columns->AddColumn(views::GridLayout::TRAILING, views::GridLayout::CENTER, | 104 columns->AddColumn(views::GridLayout::TRAILING, views::GridLayout::CENTER, |
| 86 0, views::GridLayout::USE_PREF, 0, 0); | 105 0, views::GridLayout::USE_PREF, 0, 0); |
| 87 | 106 |
| 88 layout->StartRow(0, 0); | 107 layout->StartRow(0, 0); |
| 89 views::Label* name_label = new views::Label(section_name); | 108 views::Label* name_label = new views::Label(section_name); |
| 90 layout->AddView(name_label); | 109 layout->AddView(name_label); |
| 91 | 110 |
| 92 if (content_view) { | 111 if (content_view) { |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 109 } | 128 } |
| 110 | 129 |
| 111 DISALLOW_COPY_AND_ASSIGN(PaymentSheetRow); | 130 DISALLOW_COPY_AND_ASSIGN(PaymentSheetRow); |
| 112 }; | 131 }; |
| 113 | 132 |
| 114 } // namespace | 133 } // namespace |
| 115 | 134 |
| 116 PaymentSheetViewController::PaymentSheetViewController( | 135 PaymentSheetViewController::PaymentSheetViewController( |
| 117 PaymentRequest* request, | 136 PaymentRequest* request, |
| 118 PaymentRequestDialog* dialog) | 137 PaymentRequestDialog* dialog) |
| 119 : PaymentRequestSheetController(request, dialog) {} | 138 : PaymentRequestSheetController(request, dialog), |
| 139 widest_name_column_view_width_(0) { | |
| 140 InitWidestNameColumnViewWidth(); | |
| 141 } | |
| 120 | 142 |
| 121 PaymentSheetViewController::~PaymentSheetViewController() {} | 143 PaymentSheetViewController::~PaymentSheetViewController() {} |
| 122 | 144 |
| 123 std::unique_ptr<views::View> PaymentSheetViewController::CreateView() { | 145 std::unique_ptr<views::View> PaymentSheetViewController::CreateView() { |
| 124 std::unique_ptr<views::View> content_view = base::MakeUnique<views::View>(); | 146 std::unique_ptr<views::View> content_view = base::MakeUnique<views::View>(); |
| 125 | 147 |
| 126 views::GridLayout* layout = new views::GridLayout(content_view.get()); | 148 views::GridLayout* layout = new views::GridLayout(content_view.get()); |
| 127 content_view->SetLayoutManager(layout); | 149 content_view->SetLayoutManager(layout); |
| 128 views::ColumnSet* columns = layout->AddColumnSet(0); | 150 views::ColumnSet* columns = layout->AddColumnSet(0); |
| 129 columns->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER, | 151 columns->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER, |
| 130 1, views::GridLayout::USE_PREF, 0, 0); | 152 1, views::GridLayout::USE_PREF, 0, 0); |
| 131 | 153 |
| 132 layout->StartRow(0, 0); | 154 layout->StartRow(0, 0); |
| 133 layout->AddView(CreatePaymentSheetSummaryRow().release()); | 155 layout->AddView(CreatePaymentSheetSummaryRow().release()); |
| 156 layout->StartRow(0, 0); | |
| 157 layout->AddView(CreatePaymentMethodRow().release()); | |
| 134 | 158 |
| 135 return CreatePaymentView( | 159 return CreatePaymentView( |
| 136 CreateSheetHeaderView( | 160 CreateSheetHeaderView( |
| 137 false, | 161 false, |
| 138 l10n_util::GetStringUTF16(IDS_PAYMENT_REQUEST_PAYMENT_SHEET_TITLE), | 162 l10n_util::GetStringUTF16(IDS_PAYMENT_REQUEST_PAYMENT_SHEET_TITLE), |
| 139 this), | 163 this), |
| 140 std::move(content_view)); | 164 std::move(content_view)); |
| 141 } | 165 } |
| 142 | 166 |
| 143 void PaymentSheetViewController::ButtonPressed( | 167 void PaymentSheetViewController::ButtonPressed( |
| 144 views::Button* sender, const ui::Event& event) { | 168 views::Button* sender, const ui::Event& event) { |
| 145 switch (sender->tag()) { | 169 switch (sender->tag()) { |
| 146 case static_cast<int>(PaymentRequestCommonTags::CLOSE_BUTTON_TAG): | 170 case static_cast<int>(PaymentRequestCommonTags::CLOSE_BUTTON_TAG): |
| 147 dialog()->CloseDialog(); | 171 dialog()->CloseDialog(); |
| 148 break; | 172 break; |
| 149 case static_cast<int>( | 173 case static_cast<int>( |
| 150 PaymentSheetViewControllerTags::SHOW_ORDER_SUMMARY_BUTTON): | 174 PaymentSheetViewControllerTags::SHOW_ORDER_SUMMARY_BUTTON): |
| 151 dialog()->ShowOrderSummary(); | 175 dialog()->ShowOrderSummary(); |
| 152 break; | 176 break; |
| 177 case static_cast<int>( | |
| 178 PaymentSheetViewControllerTags::SHOW_PAYMENT_METHOD_BUTTON): | |
| 179 dialog()->ShowPaymentMethodSheet(); | |
| 180 break; | |
| 153 default: | 181 default: |
| 154 NOTREACHED(); | 182 NOTREACHED(); |
| 155 } | 183 } |
| 156 } | 184 } |
| 157 | 185 |
| 158 std::unique_ptr<views::View> | 186 std::unique_ptr<views::View> |
| 159 PaymentSheetViewController::CreateOrderSummarySectionContent() { | 187 PaymentSheetViewController::CreateOrderSummarySectionContent() { |
| 160 base::string16 label_value = l10n_util::GetStringFUTF16( | 188 base::string16 label_value = l10n_util::GetStringFUTF16( |
| 161 IDS_PAYMENT_REQUEST_ORDER_SUMMARY_SECTION_TOTAL_FORMAT, | 189 IDS_PAYMENT_REQUEST_ORDER_SUMMARY_SECTION_TOTAL_FORMAT, |
| 162 base::ASCIIToUTF16(request()->details()->total->label), | 190 base::ASCIIToUTF16(request()->details()->total->label), |
| 163 base::ASCIIToUTF16(request()->details()->total->amount->currency), | 191 base::ASCIIToUTF16(request()->details()->total->amount->currency), |
| 164 base::ASCIIToUTF16(request()->details()->total->amount->value)); | 192 base::ASCIIToUTF16(request()->details()->total->amount->value)); |
| 165 | 193 |
| 166 return base::MakeUnique<views::Label>(label_value); | 194 return base::MakeUnique<views::Label>(label_value); |
| 167 } | 195 } |
| 168 | 196 |
| 197 // Creates the Order Summary row, which contains an "Order Summary" label, | |
| 198 // a Total Amount label, and a Chevron. | |
| 199 // +----------------------------------------------+ | |
| 200 // | Order Summary Total USD $12.34 > | | |
| 201 // +----------------------------------------------+ | |
| 169 std::unique_ptr<views::Button> | 202 std::unique_ptr<views::Button> |
| 170 PaymentSheetViewController::CreatePaymentSheetSummaryRow() { | 203 PaymentSheetViewController::CreatePaymentSheetSummaryRow() { |
| 171 std::unique_ptr<views::Button> section = base::MakeUnique<PaymentSheetRow>( | 204 std::unique_ptr<views::Button> section = base::MakeUnique<PaymentSheetRow>( |
| 172 this, | 205 this, |
| 173 l10n_util::GetStringUTF16(IDS_PAYMENT_REQUEST_ORDER_SUMMARY_SECTION_NAME), | 206 l10n_util::GetStringUTF16(IDS_PAYMENT_REQUEST_ORDER_SUMMARY_SECTION_NAME), |
| 174 std::unique_ptr<views::View>(nullptr), | 207 std::unique_ptr<views::View>(nullptr), |
| 175 CreateOrderSummarySectionContent()); | 208 CreateOrderSummarySectionContent(), |
| 209 widest_name_column_view_width_); | |
| 176 section->set_tag(static_cast<int>( | 210 section->set_tag(static_cast<int>( |
| 177 PaymentSheetViewControllerTags::SHOW_ORDER_SUMMARY_BUTTON)); | 211 PaymentSheetViewControllerTags::SHOW_ORDER_SUMMARY_BUTTON)); |
| 178 return section; | 212 return section; |
| 179 } | 213 } |
| 180 | 214 |
| 215 // Creates the Payment Method row, which contains a "Payment" label, the user's | |
| 216 // masked Credit Card details, the icon for the selected card, and a chevron. | |
| 217 // +----------------------------------------------+ | |
| 218 // | Payment Visa ****0000 | | |
| 219 // | John Smith | VISA | > | | |
| 220 // | | | |
| 221 // +----------------------------------------------+ | |
| 222 std::unique_ptr<views::Button> | |
| 223 PaymentSheetViewController::CreatePaymentMethodRow() { | |
| 224 autofill::CreditCard* selected_card = | |
| 225 request()->GetCurrentlySelectedCreditCard(); | |
| 226 | |
| 227 std::unique_ptr<views::View> content_view; | |
| 228 std::unique_ptr<views::ImageView> card_icon_view; | |
| 229 if (selected_card) { | |
| 230 content_view = base::MakeUnique<views::View>(); | |
| 231 | |
| 232 views::GridLayout* layout = new views::GridLayout(content_view.get()); | |
| 233 content_view->SetLayoutManager(layout); | |
| 234 views::ColumnSet* columns = layout->AddColumnSet(0); | |
| 235 columns->AddColumn(views::GridLayout::LEADING, views::GridLayout::CENTER, | |
| 236 1, views::GridLayout::USE_PREF, 0, 0); | |
| 237 | |
| 238 layout->StartRow(0, 0); | |
| 239 layout->AddView(new views::Label(selected_card->TypeAndLastFourDigits())); | |
| 240 layout->StartRow(0, 0); | |
| 241 layout->AddView(new views::Label( | |
| 242 selected_card->GetInfo( | |
| 243 autofill::AutofillType(autofill::CREDIT_CARD_NAME_FULL), | |
| 244 g_browser_process->GetApplicationLocale()))); | |
| 245 | |
| 246 card_icon_view = base::MakeUnique<views::ImageView>(); | |
| 247 card_icon_view->SetImage( | |
| 248 ResourceBundle::GetSharedInstance() | |
| 249 .GetImageNamed(autofill::data_util::GetPaymentRequestData( | |
| 250 selected_card->type()).icon_resource_id) | |
| 251 .AsImageSkia()); | |
| 252 card_icon_view->SetBorder( | |
| 253 views::CreateRoundedRectBorder(1, 3, SK_ColorLTGRAY)); | |
| 254 | |
| 255 constexpr gfx::Size kCardIconSize = gfx::Size(32, 20); | |
| 256 card_icon_view->SetImageSize(kCardIconSize); | |
| 257 } | |
| 258 | |
| 259 std::unique_ptr<views::Button> section = base::MakeUnique<PaymentSheetRow>( | |
| 260 this, | |
| 261 l10n_util::GetStringUTF16( | |
| 262 IDS_PAYMENT_REQUEST_PAYMENT_METHOD_SECTION_NAME), | |
| 263 std::move(content_view), | |
| 264 std::move(card_icon_view), | |
| 265 widest_name_column_view_width_); | |
| 266 section->set_tag(static_cast<int>( | |
| 267 PaymentSheetViewControllerTags::SHOW_PAYMENT_METHOD_BUTTON)); | |
| 268 return section; | |
| 269 } | |
| 270 | |
| 271 void PaymentSheetViewController::InitWidestNameColumnViewWidth() { | |
|
sky
2017/01/13 23:42:52
Effective c++ recommends preferring non-member fun
anthonyvd
2017/01/16 15:33:07
Great point! Done.
| |
| 272 DCHECK_EQ(0, widest_name_column_view_width_); | |
| 273 | |
| 274 // The name colums in each row should all have the same width, large enough to | |
| 275 // accomodate the longest piece of text they contain. Because of this, each | |
| 276 // row's GridLayout requires its first column to have a fixed width of the | |
| 277 // correct size. To measure the required size, layout a label with each | |
| 278 // section name, measure its width, then initialize | |
| 279 // |widest_name_column_view_width_| with the largest value. | |
| 280 // This should only be performed once, when this sheet is shown, because | |
| 281 // language/font size can't change while the dialog is open. | |
| 282 std::vector<int> section_names { | |
| 283 IDS_PAYMENT_REQUEST_ORDER_SUMMARY_SECTION_NAME, | |
| 284 IDS_PAYMENT_REQUEST_PAYMENT_METHOD_SECTION_NAME, | |
| 285 }; | |
| 286 | |
| 287 views::Label label(base::ASCIIToUTF16("")); | |
| 288 for (int name_id: section_names) { | |
|
sky
2017/01/13 23:42:52
So much more readable!
| |
| 289 label.SetText(l10n_util::GetStringUTF16(name_id)); | |
| 290 widest_name_column_view_width_ = std::max( | |
| 291 label.GetPreferredSize().width(), | |
| 292 widest_name_column_view_width_); | |
| 293 } | |
| 294 } | |
| 295 | |
| 181 } // namespace payments | 296 } // namespace payments |
| OLD | NEW |