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 11 matching lines...) Expand all Loading... | |
| 104 views::ImageView* chevron = new views::ImageView(); | 123 views::ImageView* chevron = new views::ImageView(); |
| 105 chevron->SetImage(gfx::CreateVectorIcon( | 124 chevron->SetImage(gfx::CreateVectorIcon( |
| 106 gfx::VectorIconId::SUBMENU_ARROW, | 125 gfx::VectorIconId::SUBMENU_ARROW, |
| 107 color_utils::DeriveDefaultIconColor(name_label->enabled_color()))); | 126 color_utils::DeriveDefaultIconColor(name_label->enabled_color()))); |
| 108 layout->AddView(chevron); | 127 layout->AddView(chevron); |
| 109 } | 128 } |
| 110 | 129 |
| 111 DISALLOW_COPY_AND_ASSIGN(PaymentSheetRow); | 130 DISALLOW_COPY_AND_ASSIGN(PaymentSheetRow); |
| 112 }; | 131 }; |
| 113 | 132 |
| 133 int ComputeWidestNameColumnViewWidth() { | |
| 134 // The name colums in each row should all have the same width, large enough to | |
| 135 // accomodate the longest piece of text they contain. Because of this, each | |
| 136 // row's GridLayout requires its first column to have a fixed width of the | |
| 137 // correct size. To measure the required size, layout a label with each | |
| 138 // section name, measure its width, then initialize |widest_column_width| | |
| 139 // with the largest value. | |
| 140 std::vector<int> section_names { | |
| 141 IDS_PAYMENT_REQUEST_ORDER_SUMMARY_SECTION_NAME, | |
| 142 IDS_PAYMENT_REQUEST_PAYMENT_METHOD_SECTION_NAME, | |
| 143 }; | |
| 144 | |
| 145 int widest_column_width = 0; | |
| 146 | |
| 147 views::Label label(base::ASCIIToUTF16("")); | |
| 148 for (int name_id: section_names) { | |
|
sky
2017/01/17 17:40:07
nit: space before and after ':', e.g. "name_id : s
anthonyvd
2017/01/17 19:43:51
Done.
| |
| 149 label.SetText(l10n_util::GetStringUTF16(name_id)); | |
| 150 widest_column_width = std::max( | |
| 151 label.GetPreferredSize().width(), | |
| 152 widest_column_width); | |
| 153 } | |
| 154 | |
| 155 return widest_column_width; | |
| 156 } | |
| 157 | |
| 114 } // namespace | 158 } // namespace |
| 115 | 159 |
| 116 PaymentSheetViewController::PaymentSheetViewController( | 160 PaymentSheetViewController::PaymentSheetViewController( |
| 117 PaymentRequest* request, | 161 PaymentRequest* request, |
| 118 PaymentRequestDialog* dialog) | 162 PaymentRequestDialog* dialog) |
| 119 : PaymentRequestSheetController(request, dialog) {} | 163 : PaymentRequestSheetController(request, dialog), |
| 164 widest_name_column_view_width_(ComputeWidestNameColumnViewWidth()) {} | |
| 120 | 165 |
| 121 PaymentSheetViewController::~PaymentSheetViewController() {} | 166 PaymentSheetViewController::~PaymentSheetViewController() {} |
| 122 | 167 |
| 123 std::unique_ptr<views::View> PaymentSheetViewController::CreateView() { | 168 std::unique_ptr<views::View> PaymentSheetViewController::CreateView() { |
| 124 std::unique_ptr<views::View> content_view = base::MakeUnique<views::View>(); | 169 std::unique_ptr<views::View> content_view = base::MakeUnique<views::View>(); |
| 125 | 170 |
| 126 views::GridLayout* layout = new views::GridLayout(content_view.get()); | 171 views::GridLayout* layout = new views::GridLayout(content_view.get()); |
| 127 content_view->SetLayoutManager(layout); | 172 content_view->SetLayoutManager(layout); |
| 128 views::ColumnSet* columns = layout->AddColumnSet(0); | 173 views::ColumnSet* columns = layout->AddColumnSet(0); |
| 129 columns->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER, | 174 columns->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER, |
| 130 1, views::GridLayout::USE_PREF, 0, 0); | 175 1, views::GridLayout::USE_PREF, 0, 0); |
| 131 | 176 |
| 132 layout->StartRow(0, 0); | 177 layout->StartRow(0, 0); |
| 133 layout->AddView(CreatePaymentSheetSummaryRow().release()); | 178 layout->AddView(CreatePaymentSheetSummaryRow().release()); |
| 179 layout->StartRow(0, 0); | |
| 180 layout->AddView(CreatePaymentMethodRow().release()); | |
| 134 | 181 |
| 135 return CreatePaymentView( | 182 return CreatePaymentView( |
| 136 CreateSheetHeaderView( | 183 CreateSheetHeaderView( |
| 137 false, | 184 false, |
| 138 l10n_util::GetStringUTF16(IDS_PAYMENT_REQUEST_PAYMENT_SHEET_TITLE), | 185 l10n_util::GetStringUTF16(IDS_PAYMENT_REQUEST_PAYMENT_SHEET_TITLE), |
| 139 this), | 186 this), |
| 140 std::move(content_view)); | 187 std::move(content_view)); |
| 141 } | 188 } |
| 142 | 189 |
| 143 void PaymentSheetViewController::ButtonPressed( | 190 void PaymentSheetViewController::ButtonPressed( |
| 144 views::Button* sender, const ui::Event& event) { | 191 views::Button* sender, const ui::Event& event) { |
| 145 switch (sender->tag()) { | 192 switch (sender->tag()) { |
| 146 case static_cast<int>(PaymentRequestCommonTags::CLOSE_BUTTON_TAG): | 193 case static_cast<int>(PaymentRequestCommonTags::CLOSE_BUTTON_TAG): |
| 147 dialog()->CloseDialog(); | 194 dialog()->CloseDialog(); |
| 148 break; | 195 break; |
| 149 case static_cast<int>( | 196 case static_cast<int>( |
| 150 PaymentSheetViewControllerTags::SHOW_ORDER_SUMMARY_BUTTON): | 197 PaymentSheetViewControllerTags::SHOW_ORDER_SUMMARY_BUTTON): |
| 151 dialog()->ShowOrderSummary(); | 198 dialog()->ShowOrderSummary(); |
| 152 break; | 199 break; |
| 200 case static_cast<int>( | |
| 201 PaymentSheetViewControllerTags::SHOW_PAYMENT_METHOD_BUTTON): | |
| 202 dialog()->ShowPaymentMethodSheet(); | |
| 203 break; | |
| 153 default: | 204 default: |
| 154 NOTREACHED(); | 205 NOTREACHED(); |
| 155 } | 206 } |
| 156 } | 207 } |
| 157 | 208 |
| 158 std::unique_ptr<views::View> | 209 std::unique_ptr<views::View> |
| 159 PaymentSheetViewController::CreateOrderSummarySectionContent() { | 210 PaymentSheetViewController::CreateOrderSummarySectionContent() { |
| 160 base::string16 label_value = l10n_util::GetStringFUTF16( | 211 base::string16 label_value = l10n_util::GetStringFUTF16( |
| 161 IDS_PAYMENT_REQUEST_ORDER_SUMMARY_SECTION_TOTAL_FORMAT, | 212 IDS_PAYMENT_REQUEST_ORDER_SUMMARY_SECTION_TOTAL_FORMAT, |
| 162 base::ASCIIToUTF16(request()->details()->total->label), | 213 base::ASCIIToUTF16(request()->details()->total->label), |
| 163 base::ASCIIToUTF16(request()->details()->total->amount->currency), | 214 base::ASCIIToUTF16(request()->details()->total->amount->currency), |
| 164 base::ASCIIToUTF16(request()->details()->total->amount->value)); | 215 base::ASCIIToUTF16(request()->details()->total->amount->value)); |
| 165 | 216 |
| 166 return base::MakeUnique<views::Label>(label_value); | 217 return base::MakeUnique<views::Label>(label_value); |
| 167 } | 218 } |
| 168 | 219 |
| 220 // Creates the Order Summary row, which contains an "Order Summary" label, | |
| 221 // a Total Amount label, and a Chevron. | |
| 222 // +----------------------------------------------+ | |
| 223 // | Order Summary Total USD $12.34 > | | |
| 224 // +----------------------------------------------+ | |
| 169 std::unique_ptr<views::Button> | 225 std::unique_ptr<views::Button> |
| 170 PaymentSheetViewController::CreatePaymentSheetSummaryRow() { | 226 PaymentSheetViewController::CreatePaymentSheetSummaryRow() { |
| 171 std::unique_ptr<views::Button> section = base::MakeUnique<PaymentSheetRow>( | 227 std::unique_ptr<views::Button> section = base::MakeUnique<PaymentSheetRow>( |
| 172 this, | 228 this, |
| 173 l10n_util::GetStringUTF16(IDS_PAYMENT_REQUEST_ORDER_SUMMARY_SECTION_NAME), | 229 l10n_util::GetStringUTF16(IDS_PAYMENT_REQUEST_ORDER_SUMMARY_SECTION_NAME), |
| 174 std::unique_ptr<views::View>(nullptr), | 230 std::unique_ptr<views::View>(nullptr), |
| 175 CreateOrderSummarySectionContent()); | 231 CreateOrderSummarySectionContent(), |
| 232 widest_name_column_view_width_); | |
| 176 section->set_tag(static_cast<int>( | 233 section->set_tag(static_cast<int>( |
| 177 PaymentSheetViewControllerTags::SHOW_ORDER_SUMMARY_BUTTON)); | 234 PaymentSheetViewControllerTags::SHOW_ORDER_SUMMARY_BUTTON)); |
| 178 return section; | 235 return section; |
| 179 } | 236 } |
| 180 | 237 |
| 238 // Creates the Payment Method row, which contains a "Payment" label, the user's | |
| 239 // masked Credit Card details, the icon for the selected card, and a chevron. | |
| 240 // +----------------------------------------------+ | |
| 241 // | Payment Visa ****0000 | | |
| 242 // | John Smith | VISA | > | | |
| 243 // | | | |
| 244 // +----------------------------------------------+ | |
| 245 std::unique_ptr<views::Button> | |
| 246 PaymentSheetViewController::CreatePaymentMethodRow() { | |
| 247 autofill::CreditCard* selected_card = | |
| 248 request()->GetCurrentlySelectedCreditCard(); | |
| 249 | |
| 250 std::unique_ptr<views::View> content_view; | |
| 251 std::unique_ptr<views::ImageView> card_icon_view; | |
| 252 if (selected_card) { | |
| 253 content_view = base::MakeUnique<views::View>(); | |
| 254 | |
| 255 views::GridLayout* layout = new views::GridLayout(content_view.get()); | |
| 256 content_view->SetLayoutManager(layout); | |
| 257 views::ColumnSet* columns = layout->AddColumnSet(0); | |
| 258 columns->AddColumn(views::GridLayout::LEADING, views::GridLayout::CENTER, | |
| 259 1, views::GridLayout::USE_PREF, 0, 0); | |
| 260 | |
| 261 layout->StartRow(0, 0); | |
| 262 layout->AddView(new views::Label(selected_card->TypeAndLastFourDigits())); | |
| 263 layout->StartRow(0, 0); | |
| 264 layout->AddView(new views::Label( | |
| 265 selected_card->GetInfo( | |
| 266 autofill::AutofillType(autofill::CREDIT_CARD_NAME_FULL), | |
| 267 g_browser_process->GetApplicationLocale()))); | |
| 268 | |
| 269 card_icon_view = base::MakeUnique<views::ImageView>(); | |
| 270 card_icon_view->SetImage( | |
| 271 ResourceBundle::GetSharedInstance() | |
| 272 .GetImageNamed(autofill::data_util::GetPaymentRequestData( | |
| 273 selected_card->type()).icon_resource_id) | |
| 274 .AsImageSkia()); | |
| 275 card_icon_view->SetBorder( | |
| 276 views::CreateRoundedRectBorder(1, 3, SK_ColorLTGRAY)); | |
| 277 | |
| 278 constexpr gfx::Size kCardIconSize = gfx::Size(32, 20); | |
| 279 card_icon_view->SetImageSize(kCardIconSize); | |
| 280 } | |
| 281 | |
| 282 std::unique_ptr<views::Button> section = base::MakeUnique<PaymentSheetRow>( | |
| 283 this, | |
| 284 l10n_util::GetStringUTF16( | |
| 285 IDS_PAYMENT_REQUEST_PAYMENT_METHOD_SECTION_NAME), | |
| 286 std::move(content_view), | |
| 287 std::move(card_icon_view), | |
| 288 widest_name_column_view_width_); | |
| 289 section->set_tag(static_cast<int>( | |
| 290 PaymentSheetViewControllerTags::SHOW_PAYMENT_METHOD_BUTTON)); | |
| 291 return section; | |
| 292 } | |
| 293 | |
| 181 } // namespace payments | 294 } // namespace payments |
| OLD | NEW |