Chromium Code Reviews| Index: chrome/browser/ui/views/payments/editor_view_controller.cc |
| diff --git a/chrome/browser/ui/views/payments/editor_view_controller.cc b/chrome/browser/ui/views/payments/editor_view_controller.cc |
| index 2b4c1efce5bfb583a685a0e41b707c17aad498a9..7c8f5f180f54c03fd9a1a53bc1ca916d2d9f6338 100644 |
| --- a/chrome/browser/ui/views/payments/editor_view_controller.cc |
| +++ b/chrome/browser/ui/views/payments/editor_view_controller.cc |
| @@ -61,14 +61,13 @@ std::unique_ptr<views::View> EditorViewController::CreateView() { |
| layout->set_cross_axis_alignment( |
| views::BoxLayout::CROSS_AXIS_ALIGNMENT_STRETCH); |
| content_view->SetLayoutManager(layout); |
| + // No insets. Child views below are responsible for their padding. |
| + // An editor can optionally have a header view specific to it. |
| content_view->AddChildView(CreateHeaderView().release()); |
| - // Create an input label/textfield for each field definition. |
| - std::vector<EditorField> fields = GetFieldDefinitions(); |
| - for (const auto& field : fields) { |
| - content_view->AddChildView(CreateInputField(field).release()); |
| - } |
| + // The heart of the editor dialog: all the input fields with their labels. |
| + content_view->AddChildView(CreateEditorView().release()); |
| return CreatePaymentView( |
| CreateSheetHeaderView( |
| @@ -102,6 +101,16 @@ std::unique_ptr<views::View> EditorViewController::CreateLeadingFooterView() { |
| return content_view; |
| } |
| +void EditorViewController::DisplayErrorMessageForField( |
| + const EditorField& field, |
| + const base::string16& error_message) { |
| + const auto& label_it = error_labels_.find(field); |
| + DCHECK(label_it != error_labels_.end()); |
| + label_it->second->SetText(error_message); |
| + label_it->second->SchedulePaint(); |
| + dialog()->Layout(); |
| +} |
| + |
| std::unique_ptr<views::Button> EditorViewController::CreatePrimaryButton() { |
| std::unique_ptr<views::Button> button( |
| views::MdTextButton::CreateSecondaryUiBlueButton( |
| @@ -133,35 +142,60 @@ void EditorViewController::OnPerformAction(views::Combobox* sender) { |
| static_cast<ValidatingCombobox*>(sender)->OnContentsChanged(); |
| } |
| -std::unique_ptr<views::View> EditorViewController::CreateInputField( |
| - const EditorField& field) { |
| - std::unique_ptr<views::View> row = base::MakeUnique<views::View>(); |
| +std::unique_ptr<views::View> EditorViewController::CreateEditorView() { |
| + std::unique_ptr<views::View> editor_view = base::MakeUnique<views::View>(); |
| - row->SetBorder(payments::CreatePaymentRequestRowBorder()); |
| + views::GridLayout* editor_layout = new views::GridLayout(editor_view.get()); |
| - views::GridLayout* layout = new views::GridLayout(row.get()); |
| + // The editor grid layout is padded vertically from the top and bottom, and |
| + // horizontally inset like other content views. The top padding needs to be |
| + // added to the top padding of the first row. |
| + constexpr int kEditorVerticalInset = 16; |
| + editor_layout->SetInsets( |
| + kEditorVerticalInset, payments::kPaymentRequestRowHorizontalInsets, |
| + kEditorVerticalInset, payments::kPaymentRequestRowHorizontalInsets); |
| - // The vertical spacing for these rows is slightly different than the spacing |
| - // spacing for clickable rows, so don't use kPaymentRequestRowVerticalInsets. |
| - constexpr int kRowVerticalInset = 12; |
| - layout->SetInsets( |
| - kRowVerticalInset, payments::kPaymentRequestRowHorizontalInsets, |
| - kRowVerticalInset, payments::kPaymentRequestRowHorizontalInsets); |
| - |
| - row->SetLayoutManager(layout); |
| - views::ColumnSet* columns = layout->AddColumnSet(0); |
| + editor_view->SetLayoutManager(editor_layout); |
| + views::ColumnSet* columns = editor_layout->AddColumnSet(0); |
| columns->AddColumn(views::GridLayout::LEADING, views::GridLayout::CENTER, 0, |
| views::GridLayout::USE_PREF, 0, 0); |
| - columns->AddPaddingColumn(1, 0); |
| - columns->AddColumn(views::GridLayout::TRAILING, views::GridLayout::CENTER, 0, |
| + |
| + // This is the horizontal padding between the label and the input field. |
| + constexpr int kLabelInputFieldHorizontalPadding = 16; |
| + columns->AddPaddingColumn(0, kLabelInputFieldHorizontalPadding); |
| + |
| + columns->AddColumn(views::GridLayout::LEADING, views::GridLayout::CENTER, 0, |
| views::GridLayout::USE_PREF, 0, 0); |
| - layout->StartRow(0, 0); |
| - layout->AddView(new views::Label(field.label)); |
| + std::vector<EditorField> fields = GetFieldDefinitions(); |
| + for (const auto& field : fields) { |
| + CreateInputField(editor_layout, field); |
| + } |
| + |
| + return editor_view; |
| +} |
| + |
| +// Each input field is a 4-quadrant grid. |
| +// +----------------------------------------------------------+ |
| +// | Field Label | Input field (textfield/combobox) | |
| +// |_______________________|__________________________________| |
| +// | (empty) | Error label | |
| +// +----------------------------------------------------------+ |
| +void EditorViewController::CreateInputField(views::GridLayout* layout, |
| + const EditorField& field) { |
| + // This is the top padding for every row. |
| + constexpr int kInputRowSpacing = 6; |
| + layout->StartRowWithPadding(0, 0, 0, kInputRowSpacing); |
| + |
| + std::unique_ptr<views::Label> label = base::MakeUnique<views::Label>( |
| + field.required ? field.label + base::ASCIIToUTF16("*") : field.label); |
| + // A very long label will wrap. |
| + label->SetMultiLine(true); |
|
anthonyvd
2017/02/22 19:32:45
I don't see where the max width of the label is se
Mathieu
2017/02/22 20:08:59
Correct! I've set a max width now.
|
| + layout->AddView(label.release()); |
| if (field.control_type == EditorField::ControlType::TEXTFIELD) { |
| ValidatingTextfield* text_field = |
| - new ValidatingTextfield(CreateValidationDelegate(field)); |
| + new ValidatingTextfield(CreateValidationDelegate(field, this)); |
| text_field->set_controller(this); |
| // Using autofill field type as a view ID (for testing). |
| text_field->set_id(static_cast<int>(field.type)); |
| @@ -174,8 +208,9 @@ std::unique_ptr<views::View> EditorViewController::CreateInputField( |
| // |text_field| will now be owned by |row|. |
| layout->AddView(text_field); |
| } else if (field.control_type == EditorField::ControlType::COMBOBOX) { |
| - ValidatingCombobox* combobox = new ValidatingCombobox( |
| - GetComboboxModelForType(field.type), CreateValidationDelegate(field)); |
| + ValidatingCombobox* combobox = |
| + new ValidatingCombobox(GetComboboxModelForType(field.type), |
| + CreateValidationDelegate(field, this)); |
| // Using autofill field type as a view ID (for testing). |
| combobox->set_id(static_cast<int>(field.type)); |
| combobox->set_listener(this); |
| @@ -186,7 +221,22 @@ std::unique_ptr<views::View> EditorViewController::CreateInputField( |
| NOTREACHED(); |
| } |
| - return row; |
| + // This is the vertical space between the input field and its error label. |
| + constexpr int kInputErrorLabelPadding = 6; |
| + layout->StartRowWithPadding(0, 0, 0, kInputErrorLabelPadding); |
| + layout->SkipColumns(1); |
| + // Error label is initially empty. |
| + std::unique_ptr<views::Label> error_label = |
| + base::MakeUnique<views::Label>(base::ASCIIToUTF16("")); |
| + error_label->set_id(static_cast<int>(DialogViewID::ERROR_LABEL_OFFSET) + |
| + field.type); |
|
anthonyvd
2017/02/22 19:32:45
Are all fields guaranteed to have a different type
Mathieu
2017/02/22 20:08:59
Yes they all have different type, it's the autofil
|
| + error_label->SetFontList( |
| + error_label->GetDefaultFontList().DeriveWithSizeDelta(-1)); |
| + error_label->SetEnabledColor(error_label->GetNativeTheme()->GetSystemColor( |
| + ui::NativeTheme::kColorId_AlertSeverityHigh)); |
| + error_labels_[field] = error_label.get(); |
| + |
| + layout->AddView(error_label.release()); |
| } |
| } // namespace payments |