OLD | NEW |
1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 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/profile_list_view_controller.h" | 5 #include "chrome/browser/ui/views/payments/profile_list_view_controller.h" |
6 | 6 |
| 7 #include "base/strings/utf_string_conversions.h" |
7 #include "chrome/browser/ui/views/payments/payment_request_dialog_view.h" | 8 #include "chrome/browser/ui/views/payments/payment_request_dialog_view.h" |
8 #include "chrome/browser/ui/views/payments/payment_request_dialog_view_ids.h" | 9 #include "chrome/browser/ui/views/payments/payment_request_dialog_view_ids.h" |
9 #include "chrome/browser/ui/views/payments/payment_request_row_view.h" | 10 #include "chrome/browser/ui/views/payments/payment_request_row_view.h" |
10 #include "chrome/browser/ui/views/payments/payment_request_views_util.h" | 11 #include "chrome/browser/ui/views/payments/payment_request_views_util.h" |
11 #include "chrome/grit/generated_resources.h" | 12 #include "chrome/grit/generated_resources.h" |
12 #include "components/payments/content/payment_request_spec.h" | 13 #include "components/payments/content/payment_request_spec.h" |
13 #include "components/payments/content/payment_request_state.h" | 14 #include "components/payments/content/payment_request_state.h" |
14 #include "components/payments/core/payments_profile_comparator.h" | 15 #include "components/payments/core/payments_profile_comparator.h" |
15 #include "components/payments/core/strings_util.h" | 16 #include "components/payments/core/strings_util.h" |
16 #include "components/strings/grit/components_strings.h" | 17 #include "components/strings/grit/components_strings.h" |
17 #include "ui/base/l10n/l10n_util.h" | 18 #include "ui/base/l10n/l10n_util.h" |
| 19 #include "ui/gfx/paint_vector_icon.h" |
| 20 #include "ui/native_theme/native_theme.h" |
| 21 #include "ui/vector_icons/vector_icons.h" |
18 #include "ui/views/controls/button/label_button.h" | 22 #include "ui/views/controls/button/label_button.h" |
19 #include "ui/views/controls/button/md_text_button.h" | 23 #include "ui/views/controls/button/md_text_button.h" |
20 #include "ui/views/controls/image_view.h" | 24 #include "ui/views/controls/image_view.h" |
21 #include "ui/views/layout/box_layout.h" | 25 #include "ui/views/layout/box_layout.h" |
22 #include "ui/views/layout/fill_layout.h" | 26 #include "ui/views/layout/fill_layout.h" |
23 #include "ui/views/layout/grid_layout.h" | 27 #include "ui/views/layout/grid_layout.h" |
24 | 28 |
25 namespace payments { | 29 namespace payments { |
26 | 30 |
27 namespace { | 31 namespace { |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
68 return parent_view_->GetLabel(profile_); | 72 return parent_view_->GetLabel(profile_); |
69 } | 73 } |
70 | 74 |
71 void SelectedStateChanged() override { | 75 void SelectedStateChanged() override { |
72 if (selected()) { | 76 if (selected()) { |
73 parent_view_->SelectProfile(profile_); | 77 parent_view_->SelectProfile(profile_); |
74 dialog_->GoBack(); | 78 dialog_->GoBack(); |
75 } | 79 } |
76 } | 80 } |
77 | 81 |
78 bool CanBeSelected() const override { | 82 bool IsEnabled() override { return parent_view_->IsEnabled(profile_); } |
79 return parent_view_->IsValidProfile(*profile_); | 83 |
| 84 bool CanBeSelected() override { |
| 85 // In order to be selectable, a profile entry needs to be enabled, and the |
| 86 // profile valid according to the controller. If either condition is false, |
| 87 // PerformSelectionFallback() is called. |
| 88 return IsEnabled() && parent_view_->IsValidProfile(*profile_); |
80 } | 89 } |
81 | 90 |
82 void PerformSelectionFallback() override { | 91 void PerformSelectionFallback() override { |
83 parent_view_->ShowEditor(profile_); | 92 // If enabled, the editor is opened to complete the invalid profile. |
| 93 if (IsEnabled()) |
| 94 parent_view_->ShowEditor(profile_); |
84 } | 95 } |
85 | 96 |
86 ProfileListViewController* parent_view_; | 97 ProfileListViewController* parent_view_; |
87 autofill::AutofillProfile* profile_; | 98 autofill::AutofillProfile* profile_; |
88 PaymentRequestDialogView* dialog_; | 99 PaymentRequestDialogView* dialog_; |
89 | 100 |
90 DISALLOW_COPY_AND_ASSIGN(ProfileItem); | 101 DISALLOW_COPY_AND_ASSIGN(ProfileItem); |
91 }; | 102 }; |
92 | 103 |
93 // The ProfileListViewController subtype for the Shipping address list | 104 // The ProfileListViewController subtype for the Shipping address list |
94 // screen of the Payment Request flow. | 105 // screen of the Payment Request flow. |
95 class ShippingProfileViewController : public ProfileListViewController { | 106 class ShippingProfileViewController : public ProfileListViewController { |
96 public: | 107 public: |
97 ShippingProfileViewController(PaymentRequestSpec* spec, | 108 ShippingProfileViewController(PaymentRequestSpec* spec, |
98 PaymentRequestState* state, | 109 PaymentRequestState* state, |
99 PaymentRequestDialogView* dialog) | 110 PaymentRequestDialogView* dialog) |
100 : ProfileListViewController(spec, state, dialog) { | 111 : ProfileListViewController(spec, state, dialog) { |
101 PopulateList(); | 112 PopulateList(); |
102 } | 113 } |
103 ~ShippingProfileViewController() override {} | 114 ~ShippingProfileViewController() override {} |
104 | 115 |
105 protected: | 116 protected: |
106 // ProfileListViewController: | 117 // ProfileListViewController: |
107 std::unique_ptr<views::View> GetLabel( | 118 std::unique_ptr<views::View> GetLabel( |
108 autofill::AutofillProfile* profile) override { | 119 autofill::AutofillProfile* profile) override { |
109 return GetShippingAddressLabel(AddressStyleType::DETAILED, | 120 if (!IsEnabled(profile)) { |
110 state()->GetApplicationLocale(), *profile, | 121 // The error is not shown in the label itself on this screen, but the |
111 *spec(), *(state()->profile_comparator())); | 122 // entry is disabled. |
| 123 return GetShippingAddressLabelWithError( |
| 124 AddressStyleType::DETAILED, state()->GetApplicationLocale(), *profile, |
| 125 /*error=*/base::string16(), /*disabled_state=*/true); |
| 126 } |
| 127 return GetShippingAddressLabelWithMissingInfo( |
| 128 AddressStyleType::DETAILED, state()->GetApplicationLocale(), *profile, |
| 129 *(state()->profile_comparator())); |
112 } | 130 } |
113 | 131 |
114 void SelectProfile(autofill::AutofillProfile* profile) override { | 132 void SelectProfile(autofill::AutofillProfile* profile) override { |
115 state()->SetSelectedShippingProfile(profile); | 133 state()->SetSelectedShippingProfile(profile); |
116 } | 134 } |
117 | 135 |
118 void ShowEditor(autofill::AutofillProfile* profile) override { | 136 void ShowEditor(autofill::AutofillProfile* profile) override { |
119 dialog()->ShowShippingAddressEditor( | 137 dialog()->ShowShippingAddressEditor( |
120 /*on_edited=*/base::BindOnce( | 138 /*on_edited=*/base::BindOnce( |
121 &PaymentRequestState::SetSelectedShippingProfile, | 139 &PaymentRequestState::SetSelectedShippingProfile, |
122 base::Unretained(state()), profile), | 140 base::Unretained(state()), profile), |
123 /*on_added=*/ | 141 /*on_added=*/ |
124 base::BindOnce(&PaymentRequestState::AddAutofillShippingProfile, | 142 base::BindOnce(&PaymentRequestState::AddAutofillShippingProfile, |
125 base::Unretained(state()), /*selected=*/true), | 143 base::Unretained(state()), /*selected=*/true), |
126 profile); | 144 profile); |
127 } | 145 } |
128 | 146 |
129 autofill::AutofillProfile* GetSelectedProfile() override { | 147 autofill::AutofillProfile* GetSelectedProfile() override { |
130 return state()->selected_shipping_profile(); | 148 // If there are no errors with the currently selected profile, return it. |
| 149 return spec()->selected_shipping_option_error().empty() |
| 150 ? state()->selected_shipping_profile() |
| 151 : nullptr; |
131 } | 152 } |
132 | 153 |
133 bool IsValidProfile(const autofill::AutofillProfile& profile) override { | 154 bool IsValidProfile(const autofill::AutofillProfile& profile) override { |
134 return state()->profile_comparator()->IsShippingComplete(&profile); | 155 return state()->profile_comparator()->IsShippingComplete(&profile); |
135 } | 156 } |
136 | 157 |
137 std::vector<autofill::AutofillProfile*> GetProfiles() override { | 158 std::vector<autofill::AutofillProfile*> GetProfiles() override { |
138 return state()->shipping_profiles(); | 159 return state()->shipping_profiles(); |
139 } | 160 } |
140 | 161 |
141 DialogViewID GetDialogViewId() override { | 162 DialogViewID GetDialogViewId() override { |
142 return DialogViewID::SHIPPING_ADDRESS_SHEET_LIST_VIEW; | 163 return DialogViewID::SHIPPING_ADDRESS_SHEET_LIST_VIEW; |
143 } | 164 } |
144 | 165 |
| 166 std::unique_ptr<views::View> CreateHeaderView() override { |
| 167 if (spec()->selected_shipping_option_error().empty()) |
| 168 return nullptr; |
| 169 |
| 170 std::unique_ptr<views::View> header_view = base::MakeUnique<views::View>(); |
| 171 // 8 pixels between the warning icon view and the text. |
| 172 constexpr int kRowHorizontalSpacing = 8; |
| 173 views::BoxLayout* layout = new views::BoxLayout( |
| 174 views::BoxLayout::kHorizontal, |
| 175 payments::kPaymentRequestRowHorizontalInsets, 0, kRowHorizontalSpacing); |
| 176 layout->set_main_axis_alignment( |
| 177 views::BoxLayout::MAIN_AXIS_ALIGNMENT_START); |
| 178 layout->set_cross_axis_alignment( |
| 179 views::BoxLayout::CROSS_AXIS_ALIGNMENT_STRETCH); |
| 180 header_view->SetLayoutManager(layout); |
| 181 |
| 182 std::unique_ptr<views::ImageView> warning_icon = |
| 183 base::MakeUnique<views::ImageView>(); |
| 184 warning_icon->set_can_process_events_within_subtree(false); |
| 185 warning_icon->SetImage(gfx::CreateVectorIcon( |
| 186 ui::kWarningIcon, 16, |
| 187 warning_icon->GetNativeTheme()->GetSystemColor( |
| 188 ui::NativeTheme::kColorId_AlertSeverityHigh))); |
| 189 header_view->AddChildView(warning_icon.release()); |
| 190 |
| 191 std::unique_ptr<views::Label> label = base::MakeUnique<views::Label>( |
| 192 spec()->selected_shipping_option_error()); |
| 193 label->set_id( |
| 194 static_cast<int>(DialogViewID::SHIPPING_ADDRESS_OPTION_ERROR)); |
| 195 label->SetEnabledColor(label->GetNativeTheme()->GetSystemColor( |
| 196 ui::NativeTheme::kColorId_AlertSeverityHigh)); |
| 197 label->SetMultiLine(true); |
| 198 header_view->AddChildView(label.release()); |
| 199 return header_view; |
| 200 } |
| 201 |
145 base::string16 GetSheetTitle() override { | 202 base::string16 GetSheetTitle() override { |
146 return GetShippingAddressSectionString(spec()->shipping_type()); | 203 return GetShippingAddressSectionString(spec()->shipping_type()); |
147 } | 204 } |
148 | 205 |
149 int GetSecondaryButtonTextId() override { | 206 int GetSecondaryButtonTextId() override { |
150 return IDS_AUTOFILL_ADD_ADDRESS_CAPTION; | 207 return IDS_AUTOFILL_ADD_ADDRESS_CAPTION; |
151 } | 208 } |
152 | 209 |
153 int GetSecondaryButtonTag() override { | 210 int GetSecondaryButtonTag() override { |
154 return static_cast<int>( | 211 return static_cast<int>( |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
249 } | 306 } |
250 | 307 |
251 ProfileListViewController::ProfileListViewController( | 308 ProfileListViewController::ProfileListViewController( |
252 PaymentRequestSpec* spec, | 309 PaymentRequestSpec* spec, |
253 PaymentRequestState* state, | 310 PaymentRequestState* state, |
254 PaymentRequestDialogView* dialog) | 311 PaymentRequestDialogView* dialog) |
255 : PaymentRequestSheetController(spec, state, dialog) {} | 312 : PaymentRequestSheetController(spec, state, dialog) {} |
256 | 313 |
257 ProfileListViewController::~ProfileListViewController() {} | 314 ProfileListViewController::~ProfileListViewController() {} |
258 | 315 |
| 316 bool ProfileListViewController::IsEnabled(autofill::AutofillProfile* profile) { |
| 317 // If selected_shipping_option_error() is not empty, it means the current |
| 318 // selected_shipping_profile() is not supported by this merchant and should be |
| 319 // shown in a disabled state. Therefore, |profile| is enabled in cases where |
| 320 // (1) it's not the selected_shipping_profile |
| 321 // OR |
| 322 // (2) if it is, there is no shipping option error reported by the merchant. |
| 323 return profile != state()->selected_shipping_profile() || |
| 324 spec()->selected_shipping_option_error().empty(); |
| 325 } |
| 326 |
| 327 std::unique_ptr<views::View> ProfileListViewController::CreateHeaderView() { |
| 328 return nullptr; |
| 329 } |
| 330 |
259 void ProfileListViewController::PopulateList() { | 331 void ProfileListViewController::PopulateList() { |
260 autofill::AutofillProfile* selected_profile = GetSelectedProfile(); | 332 autofill::AutofillProfile* selected_profile = GetSelectedProfile(); |
261 | 333 |
262 // This must be done at Create-time, rather than construct-time, because | 334 // This must be done at Create-time, rather than construct-time, because |
263 // the subclass method GetProfiles can't be called in the ctor. | 335 // the subclass method GetProfiles can't be called in the ctor. |
264 for (auto* profile : GetProfiles()) { | 336 for (auto* profile : GetProfiles()) { |
265 list_.AddItem(base::MakeUnique<ProfileItem>(profile, spec(), state(), | 337 list_.AddItem(base::MakeUnique<ProfileItem>(profile, spec(), state(), |
266 &list_, this, dialog(), | 338 &list_, this, dialog(), |
267 profile == selected_profile)); | 339 profile == selected_profile)); |
268 } | 340 } |
269 } | 341 } |
270 | 342 |
271 void ProfileListViewController::FillContentView(views::View* content_view) { | 343 void ProfileListViewController::FillContentView(views::View* content_view) { |
272 content_view->SetLayoutManager(new views::FillLayout); | 344 views::BoxLayout* layout = |
| 345 new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0); |
| 346 layout->set_main_axis_alignment(views::BoxLayout::MAIN_AXIS_ALIGNMENT_START); |
| 347 layout->set_cross_axis_alignment( |
| 348 views::BoxLayout::CROSS_AXIS_ALIGNMENT_STRETCH); |
| 349 content_view->SetLayoutManager(layout); |
| 350 std::unique_ptr<views::View> header_view = CreateHeaderView(); |
| 351 if (header_view) |
| 352 content_view->AddChildView(header_view.release()); |
273 std::unique_ptr<views::View> list_view = list_.CreateListView(); | 353 std::unique_ptr<views::View> list_view = list_.CreateListView(); |
274 list_view->set_id(static_cast<int>(GetDialogViewId())); | 354 list_view->set_id(static_cast<int>(GetDialogViewId())); |
275 content_view->AddChildView(list_view.release()); | 355 content_view->AddChildView(list_view.release()); |
276 } | 356 } |
277 | 357 |
278 std::unique_ptr<views::View> | 358 std::unique_ptr<views::View> |
279 ProfileListViewController::CreateExtraFooterView() { | 359 ProfileListViewController::CreateExtraFooterView() { |
280 std::unique_ptr<views::View> extra_view = base::MakeUnique<views::View>(); | 360 std::unique_ptr<views::View> extra_view = base::MakeUnique<views::View>(); |
281 | 361 |
282 extra_view->SetLayoutManager(new views::BoxLayout( | 362 extra_view->SetLayoutManager(new views::BoxLayout( |
(...skipping 10 matching lines...) Expand all Loading... |
293 | 373 |
294 void ProfileListViewController::ButtonPressed(views::Button* sender, | 374 void ProfileListViewController::ButtonPressed(views::Button* sender, |
295 const ui::Event& event) { | 375 const ui::Event& event) { |
296 if (sender->tag() == GetSecondaryButtonTag()) | 376 if (sender->tag() == GetSecondaryButtonTag()) |
297 ShowEditor(nullptr); | 377 ShowEditor(nullptr); |
298 else | 378 else |
299 PaymentRequestSheetController::ButtonPressed(sender, event); | 379 PaymentRequestSheetController::ButtonPressed(sender, event); |
300 } | 380 } |
301 | 381 |
302 } // namespace payments | 382 } // namespace payments |
OLD | NEW |