blob: f3aba897393724301e47f3a10114abaae0744ba3 [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// 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 <tuple>
#include <unordered_map>
#include <utility>
#include <vector>
#include "base/macros.h"
#include "base/strings/string16.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/combobox/combobox_listener.h"
#include "ui/views/controls/textfield/textfield_controller.h"
#include "ui/views/view.h"
namespace ui {
class ComboboxModel;
}
namespace views {
class GridLayout;
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::ServerFieldType type,
base::string16 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::ServerFieldType type;
// Label to be shown alongside the field.
base::string16 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 views::ComboboxListener {
public:
using TextFieldsMap =
std::unordered_map<ValidatingTextfield*, const EditorField>;
using ComboboxMap =
std::unordered_map<ValidatingCombobox*, const EditorField>;
using ErrorLabelMap = std::map<autofill::ServerFieldType, views::View*>;
// 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(PaymentRequestSpec* spec,
PaymentRequestState* state,
PaymentRequestDialogView* dialog,
BackNavigationType back_navigation_type,
bool is_incognito);
~EditorViewController() override;
// Will display |error_message| alongside the input field represented by
// field |type|.
void DisplayErrorMessageForField(autofill::ServerFieldType type,
const base::string16& 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::ServerFieldType 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::ServerFieldType type,
views::View** focusable_field,
bool* valid,
base::string16* 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::ServerFieldType 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 base::string16 GetInitialValueForType(
autofill::ServerFieldType 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::ServerFieldType& type) = 0;
// Returns true if all fields are valid.
bool ValidateInputFields();
// PaymentRequestSheetController;
std::unique_ptr<views::Button> CreatePrimaryButton() override;
void FillContentView(views::View* content_view) override;
// views::ComboboxListener:
void OnPerformAction(views::Combobox* combobox) override;
// 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:
void ButtonPressed(views::Button* sender, const ui::Event& event) override;
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,
base::string16* error_message);
bool is_incognito() const { return is_incognito_; }
private:
// views::TextfieldController:
void ContentsChanged(views::Textfield* sender,
const base::string16& 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 |layout|, 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::GridLayout* layout,
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::ServerFieldType type,
const base::string16& error_message);
// 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.
views::View* initial_focus_field_view_;
// Identifies where to go back when the editing completes successfully.
BackNavigationType back_navigation_type_;
bool is_incognito_;
DISALLOW_COPY_AND_ASSIGN(EditorViewController);
};
} // namespace payments
#endif // CHROME_BROWSER_UI_VIEWS_PAYMENTS_EDITOR_VIEW_CONTROLLER_H_