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