1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235
|
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_UI_VIEWS_PAYMENTS_EDITOR_VIEW_CONTROLLER_H_
#define CHROME_BROWSER_UI_VIEWS_PAYMENTS_EDITOR_VIEW_CONTROLLER_H_
#include <map>
#include <memory>
#include <string>
#include <tuple>
#include <unordered_map>
#include <utility>
#include <vector>
#include "base/memory/raw_ptr.h"
#include "chrome/browser/ui/views/payments/payment_request_dialog_view.h"
#include "chrome/browser/ui/views/payments/payment_request_sheet_controller.h"
#include "chrome/browser/ui/views/payments/validation_delegate.h"
#include "components/autofill/core/browser/field_types.h"
#include "ui/views/controls/textfield/textfield_controller.h"
#include "ui/views/view.h"
namespace ui {
class ComboboxModel;
}
namespace views {
class Label;
class Textfield;
class View;
} // namespace views
namespace payments {
class PaymentRequestSpec;
class PaymentRequestState;
class ValidatingCombobox;
class ValidatingTextfield;
// Field definition for an editor field, used to build the UI.
struct EditorField {
enum class LengthHint : int { HINT_LONG, HINT_SHORT };
enum class ControlType : int {
TEXTFIELD,
TEXTFIELD_NUMBER,
COMBOBOX,
CUSTOMFIELD,
READONLY_LABEL
};
EditorField(autofill::FieldType type,
std::u16string label,
LengthHint length_hint,
bool required,
ControlType control_type = ControlType::TEXTFIELD)
: type(type),
label(std::move(label)),
length_hint(length_hint),
required(required),
control_type(control_type) {}
// Data type in the field.
autofill::FieldType type;
// Label to be shown alongside the field.
std::u16string label;
// Hint about the length of this field's contents.
LengthHint length_hint;
// Whether the field is required.
bool required;
// The control type.
ControlType control_type;
};
// The PaymentRequestSheetController subtype for the editor screens of the
// Payment Request flow.
class EditorViewController : public PaymentRequestSheetController,
public views::TextfieldController {
public:
using TextFieldsMap =
std::unordered_map<ValidatingTextfield*, const EditorField>;
using ComboboxMap =
std::unordered_map<ValidatingCombobox*, const EditorField>;
using ErrorLabelMap =
std::map<autofill::FieldType, raw_ptr<views::View, CtnExperimental>>;
// Does not take ownership of the arguments, which should outlive this object.
// |back_navigation_type| identifies what sort of back navigation should be
// done when editing is successful. This is independent of the back arrow
// which always goes back one step.
EditorViewController(base::WeakPtr<PaymentRequestSpec> spec,
base::WeakPtr<PaymentRequestState> state,
base::WeakPtr<PaymentRequestDialogView> dialog,
BackNavigationType back_navigation_type,
bool is_incognito);
EditorViewController(const EditorViewController&) = delete;
EditorViewController& operator=(const EditorViewController&) = delete;
~EditorViewController() override;
// Will display |error_message| alongside the input field represented by
// field |type|.
void DisplayErrorMessageForField(autofill::FieldType type,
const std::u16string& error_message);
const ComboboxMap& comboboxes() const { return comboboxes_; }
const TextFieldsMap& text_fields() const { return text_fields_; }
// Returns the View ID that can be used to lookup the input field for |type|.
static int GetInputFieldViewId(autofill::FieldType type);
protected:
// Create a header view to be inserted before all fields.
virtual std::unique_ptr<views::View> CreateHeaderView();
// |focusable_field| is to be set with a pointer to the view that should get
// default focus within the custom view. |valid| should be set to the initial
// validity state of the custom view. If a custom view requires model
// validation, it should be tracked in |text_fields_| or |comboboxes_| (e.g.,
// by using CreateComboboxForField). |error_message| should be set to the
// error message for the whole custom view, if applicable. It's possible this
// message will only be shown in certain circumstances by the
// EditorViewController.
virtual std::unique_ptr<views::View> CreateCustomFieldView(
autofill::FieldType type,
views::View** focusable_field,
bool* valid,
std::u16string* error_message);
// Create an extra view to go to the right of the field with |type|, which
// can either be a textfield, combobox, or custom view.
virtual std::unique_ptr<views::View> CreateExtraViewForField(
autofill::FieldType type);
// Returns whether the editor is editing an existing item.
virtual bool IsEditingExistingItem() = 0;
// Returns the field definitions used to build the UI.
virtual std::vector<EditorField> GetFieldDefinitions() = 0;
virtual std::u16string GetInitialValueForType(autofill::FieldType type) = 0;
// Validates the data entered and attempts to save; returns true on success.
virtual bool ValidateModelAndSave() = 0;
// Creates a ValidationDelegate which knows how to validate for a given
// |field| definition.
virtual std::unique_ptr<ValidationDelegate> CreateValidationDelegate(
const EditorField& field) = 0;
virtual std::unique_ptr<ui::ComboboxModel> GetComboboxModelForType(
const autofill::FieldType& type) = 0;
// Returns true if all fields are valid.
bool ValidateInputFields();
// PaymentRequestSheetController:
void Stop() override;
std::u16string GetPrimaryButtonLabel() override;
ButtonCallback GetPrimaryButtonCallback() override;
int GetPrimaryButtonId() override;
bool GetPrimaryButtonEnabled() override;
bool ShouldShowSecondaryButton() override;
void FillContentView(views::View* content_view) override;
bool ShouldAccelerateEnterKey() override;
// Combobox callback.
virtual void OnPerformAction(ValidatingCombobox* combobox);
// Update the editor view by removing all it's child views and recreating
// the input fields returned by GetFieldDefinitions. Note that
// CreateEditorView MUST have been called at least once before calling
// UpdateEditorView.
virtual void UpdateEditorView();
// PaymentRequestSheetController:
views::View* GetFirstFocusedView() override;
// Will create a combobox according to the |field| definition. Will also keep
// track of this field to populate the edited model on save. Fills
// |error_message| with an error message about this field's data, if
// appropriate.
std::unique_ptr<ValidatingCombobox> CreateComboboxForField(
const EditorField& field,
std::u16string* error_message);
bool is_incognito() const { return is_incognito_; }
private:
// views::TextfieldController:
void ContentsChanged(views::Textfield* sender,
const std::u16string& new_contents) override;
// Creates the whole editor view to go within the editor dialog. It
// encompasses all the input fields created by CreateInputField().
std::unique_ptr<views::View> CreateEditorView();
// Adds some views to `editor_view`, to represent an input field and its
// labels. |field| is the field definition, which contains the label and the
// hint about the length of the input field. A placeholder error label is also
// added (see implementation). Returns the input view for this field that
// could be used as the initial focused and set |valid| with false if the
// initial value of the field is not valid.
views::View* CreateInputField(views::View* editor_view,
const EditorField& field,
bool* valid);
// Returns the widest column width of across all extra views of a certain
// |size| type.
int ComputeWidestExtraViewWidth(EditorField::LengthHint size);
void AddOrUpdateErrorMessageForField(autofill::FieldType type,
const std::u16string& error_message);
void SaveButtonPressed(const ui::Event& event);
// Resets all the (raw) pointers to views that the controller keeps. It also
// resets the controllers of the `text_fields_` to nullptr.
void ClearViewPointers();
// Used to remember the association between the input field UI element and the
// original field definition. The ValidatingTextfield* and ValidatingCombobox*
// are owned by their parent view, this only keeps a reference that is good as
// long as the input field is visible.
TextFieldsMap text_fields_;
ComboboxMap comboboxes_;
// Tracks the relationship between a field and its error label.
ErrorLabelMap error_labels_;
// The input field view in the editor used to set the initial focus.
raw_ptr<views::View> initial_focus_field_view_ = nullptr;
// Identifies where to go back when the editing completes successfully.
BackNavigationType back_navigation_type_;
bool is_incognito_;
};
} // namespace payments
#endif // CHROME_BROWSER_UI_VIEWS_PAYMENTS_EDITOR_VIEW_CONTROLLER_H_
|