| Index: chrome/browser/ui/views/autofill/autofill_dialog_views.cc
|
| diff --git a/chrome/browser/ui/views/autofill/autofill_dialog_views.cc b/chrome/browser/ui/views/autofill/autofill_dialog_views.cc
|
| deleted file mode 100644
|
| index a2ee6460be0625fd94daf9e650644bccbdb92f4b..0000000000000000000000000000000000000000
|
| --- a/chrome/browser/ui/views/autofill/autofill_dialog_views.cc
|
| +++ /dev/null
|
| @@ -1,1917 +0,0 @@
|
| -// Copyright (c) 2012 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.
|
| -
|
| -#include "chrome/browser/ui/views/autofill/autofill_dialog_views.h"
|
| -
|
| -#include <stddef.h>
|
| -
|
| -#include <utility>
|
| -
|
| -#include "base/bind.h"
|
| -#include "base/location.h"
|
| -#include "base/macros.h"
|
| -#include "base/strings/utf_string_conversions.h"
|
| -#include "chrome/browser/profiles/profile.h"
|
| -#include "chrome/browser/ui/autofill/autofill_dialog_view_delegate.h"
|
| -#include "chrome/browser/ui/autofill/loading_animation.h"
|
| -#include "chrome/browser/ui/views/autofill/expanding_textfield.h"
|
| -#include "chrome/browser/ui/views/autofill/info_bubble.h"
|
| -#include "chrome/browser/ui/views/autofill/tooltip_icon.h"
|
| -#include "components/autofill/core/browser/autofill_type.h"
|
| -#include "components/constrained_window/constrained_window_views.h"
|
| -#include "components/web_modal/web_contents_modal_dialog_host.h"
|
| -#include "components/web_modal/web_contents_modal_dialog_manager.h"
|
| -#include "components/web_modal/web_contents_modal_dialog_manager_delegate.h"
|
| -#include "content/public/browser/native_web_keyboard_event.h"
|
| -#include "content/public/browser/navigation_controller.h"
|
| -#include "content/public/browser/web_contents.h"
|
| -#include "grit/theme_resources.h"
|
| -#include "third_party/skia/include/core/SkColor.h"
|
| -#include "ui/base/models/combobox_model.h"
|
| -#include "ui/base/models/menu_model.h"
|
| -#include "ui/base/resource/resource_bundle.h"
|
| -#include "ui/compositor/paint_recorder.h"
|
| -#include "ui/events/event_handler.h"
|
| -#include "ui/gfx/animation/animation_delegate.h"
|
| -#include "ui/gfx/canvas.h"
|
| -#include "ui/gfx/color_utils.h"
|
| -#include "ui/gfx/font_list.h"
|
| -#include "ui/gfx/geometry/point.h"
|
| -#include "ui/gfx/path.h"
|
| -#include "ui/gfx/skia_util.h"
|
| -#include "ui/views/background.h"
|
| -#include "ui/views/border.h"
|
| -#include "ui/views/bubble/bubble_border.h"
|
| -#include "ui/views/bubble/bubble_frame_view.h"
|
| -#include "ui/views/controls/button/blue_button.h"
|
| -#include "ui/views/controls/button/checkbox.h"
|
| -#include "ui/views/controls/button/label_button.h"
|
| -#include "ui/views/controls/button/label_button_border.h"
|
| -#include "ui/views/controls/button/menu_button.h"
|
| -#include "ui/views/controls/combobox/combobox.h"
|
| -#include "ui/views/controls/image_view.h"
|
| -#include "ui/views/controls/label.h"
|
| -#include "ui/views/controls/link.h"
|
| -#include "ui/views/controls/menu/menu_runner.h"
|
| -#include "ui/views/controls/separator.h"
|
| -#include "ui/views/controls/styled_label.h"
|
| -#include "ui/views/controls/textfield/textfield.h"
|
| -#include "ui/views/controls/webview/webview.h"
|
| -#include "ui/views/layout/box_layout.h"
|
| -#include "ui/views/layout/fill_layout.h"
|
| -#include "ui/views/layout/grid_layout.h"
|
| -#include "ui/views/layout/layout_constants.h"
|
| -#include "ui/views/painter.h"
|
| -#include "ui/views/view_targeter.h"
|
| -#include "ui/views/widget/widget.h"
|
| -#include "ui/views/window/dialog_client_view.h"
|
| -#include "ui/views/window/non_client_view.h"
|
| -
|
| -namespace autofill {
|
| -
|
| -namespace {
|
| -
|
| -// The width for the section container.
|
| -const int kSectionContainerWidth = 440;
|
| -
|
| -// The minimum useful height of the contents area of the dialog.
|
| -const int kMinimumContentsHeight = 101;
|
| -
|
| -// Horizontal padding between text and other elements (in pixels).
|
| -const int kAroundTextPadding = 4;
|
| -
|
| -// The space between the edges of a notification bar and the text within (in
|
| -// pixels).
|
| -const int kNotificationPadding = 17;
|
| -
|
| -// Vertical padding above and below each detail section (in pixels).
|
| -const int kDetailSectionVerticalPadding = 10;
|
| -
|
| -const int kArrowHeight = 7;
|
| -const int kArrowWidth = 2 * kArrowHeight;
|
| -
|
| -// The padding inside the edges of the dialog, in pixels.
|
| -const int kDialogEdgePadding = 20;
|
| -
|
| -// The vertical padding between rows of manual inputs (in pixels).
|
| -const int kManualInputRowPadding = 10;
|
| -
|
| -// The top and bottom padding, in pixels, for the suggestions menu dropdown
|
| -// arrows.
|
| -const int kMenuButtonTopInset = 3;
|
| -const int kMenuButtonBottomInset = 6;
|
| -
|
| -const char kNotificationAreaClassName[] = "autofill/NotificationArea";
|
| -const char kSectionContainerClassName[] = "autofill/SectionContainer";
|
| -const char kSuggestedButtonClassName[] = "autofill/SuggestedButton";
|
| -
|
| -// Draws an arrow at the top of |canvas| pointing to |tip_x|.
|
| -void DrawArrow(gfx::Canvas* canvas,
|
| - int tip_x,
|
| - const SkColor& fill_color,
|
| - const SkColor& stroke_color) {
|
| - const int arrow_half_width = kArrowWidth / 2.0f;
|
| -
|
| - SkPath arrow;
|
| - arrow.moveTo(tip_x - arrow_half_width, kArrowHeight);
|
| - arrow.lineTo(tip_x, 0);
|
| - arrow.lineTo(tip_x + arrow_half_width, kArrowHeight);
|
| -
|
| - SkPaint fill_paint;
|
| - fill_paint.setColor(fill_color);
|
| - canvas->DrawPath(arrow, fill_paint);
|
| -
|
| - if (stroke_color != SK_ColorTRANSPARENT) {
|
| - SkPaint stroke_paint;
|
| - stroke_paint.setColor(stroke_color);
|
| - stroke_paint.setStyle(SkPaint::kStroke_Style);
|
| - canvas->DrawPath(arrow, stroke_paint);
|
| - }
|
| -}
|
| -
|
| -void SelectComboboxValueOrSetToDefault(views::Combobox* combobox,
|
| - const base::string16& value) {
|
| - if (!combobox->SelectValue(value))
|
| - combobox->SetSelectedIndex(combobox->model()->GetDefaultIndex());
|
| -}
|
| -
|
| -// This class handles layout for the first row of a SuggestionView.
|
| -// It exists to circumvent shortcomings of GridLayout and BoxLayout (namely that
|
| -// the former doesn't fully respect child visibility, and that the latter won't
|
| -// expand a single child).
|
| -class SectionRowView : public views::View {
|
| - public:
|
| - SectionRowView() { SetBorder(views::Border::CreateEmptyBorder(10, 0, 0, 0)); }
|
| -
|
| - ~SectionRowView() override {}
|
| -
|
| - // views::View implementation:
|
| - gfx::Size GetPreferredSize() const override {
|
| - int height = 0;
|
| - int width = 0;
|
| - for (int i = 0; i < child_count(); ++i) {
|
| - if (child_at(i)->visible()) {
|
| - if (width > 0)
|
| - width += kAroundTextPadding;
|
| -
|
| - gfx::Size size = child_at(i)->GetPreferredSize();
|
| - height = std::max(height, size.height());
|
| - width += size.width();
|
| - }
|
| - }
|
| -
|
| - gfx::Insets insets = GetInsets();
|
| - return gfx::Size(width + insets.width(), height + insets.height());
|
| - }
|
| -
|
| - void Layout() override {
|
| - const gfx::Rect bounds = GetContentsBounds();
|
| -
|
| - // Icon is left aligned.
|
| - int start_x = bounds.x();
|
| - views::View* icon = child_at(0);
|
| - if (icon->visible()) {
|
| - icon->SizeToPreferredSize();
|
| - icon->SetX(start_x);
|
| - icon->SetY(bounds.y() +
|
| - (bounds.height() - icon->bounds().height()) / 2);
|
| - start_x += icon->bounds().width() + kAroundTextPadding;
|
| - }
|
| -
|
| - // Textfield is right aligned.
|
| - int end_x = bounds.width();
|
| - views::View* textfield = child_at(2);
|
| - if (textfield->visible()) {
|
| - const int preferred_width = textfield->GetPreferredSize().width();
|
| - textfield->SetBounds(bounds.width() - preferred_width, bounds.y(),
|
| - preferred_width, bounds.height());
|
| - end_x = textfield->bounds().x() - kAroundTextPadding;
|
| - }
|
| -
|
| - // Label takes up all the space in between.
|
| - views::View* label = child_at(1);
|
| - if (label->visible())
|
| - label->SetBounds(start_x, bounds.y(), end_x - start_x, bounds.height());
|
| -
|
| - views::View::Layout();
|
| - }
|
| -
|
| - private:
|
| - DISALLOW_COPY_AND_ASSIGN(SectionRowView);
|
| -};
|
| -
|
| -// A view that propagates visibility and preferred size changes.
|
| -class LayoutPropagationView : public views::View {
|
| - public:
|
| - LayoutPropagationView() {}
|
| - ~LayoutPropagationView() override {}
|
| -
|
| - protected:
|
| - void ChildVisibilityChanged(views::View* child) override {
|
| - PreferredSizeChanged();
|
| - }
|
| - void ChildPreferredSizeChanged(views::View* child) override {
|
| - PreferredSizeChanged();
|
| - }
|
| -
|
| - private:
|
| - DISALLOW_COPY_AND_ASSIGN(LayoutPropagationView);
|
| -};
|
| -
|
| -// A View for a single notification banner.
|
| -class NotificationView : public views::View,
|
| - public views::StyledLabelListener {
|
| - public:
|
| - NotificationView(const DialogNotification& data,
|
| - AutofillDialogViewDelegate* delegate)
|
| - : data_(data),
|
| - delegate_(delegate),
|
| - checkbox_(NULL) {
|
| - std::unique_ptr<views::View> label_view;
|
| - std::unique_ptr<views::StyledLabel> label(
|
| - new views::StyledLabel(data.display_text(), this));
|
| - label->set_auto_color_readability_enabled(false);
|
| -
|
| - views::StyledLabel::RangeStyleInfo text_style;
|
| - text_style.color = data.GetTextColor();
|
| -
|
| - if (data.link_range().is_empty()) {
|
| - label->AddStyleRange(gfx::Range(0, data.display_text().size()),
|
| - text_style);
|
| - } else {
|
| - gfx::Range prefix_range(0, data.link_range().start());
|
| - if (!prefix_range.is_empty())
|
| - label->AddStyleRange(prefix_range, text_style);
|
| -
|
| - label->AddStyleRange(data.link_range(),
|
| - views::StyledLabel::RangeStyleInfo::CreateForLink());
|
| -
|
| - gfx::Range suffix_range(data.link_range().end(),
|
| - data.display_text().size());
|
| - if (!suffix_range.is_empty())
|
| - label->AddStyleRange(suffix_range, text_style);
|
| - }
|
| - label_view.reset(label.release());
|
| -
|
| - AddChildView(label_view.release());
|
| -
|
| - if (!data.tooltip_text().empty())
|
| - AddChildView(new TooltipIcon(data.tooltip_text()));
|
| -
|
| - set_background(
|
| - views::Background::CreateSolidBackground(data.GetBackgroundColor()));
|
| - SetBorder(views::Border::CreateSolidSidedBorder(
|
| - 1, 0, 1, 0, data.GetBorderColor()));
|
| - }
|
| -
|
| - ~NotificationView() override {}
|
| -
|
| - views::Checkbox* checkbox() {
|
| - return checkbox_;
|
| - }
|
| -
|
| - // views::View implementation.
|
| - gfx::Insets GetInsets() const override {
|
| - int vertical_padding = kNotificationPadding;
|
| - if (checkbox_)
|
| - vertical_padding -= 3;
|
| - return gfx::Insets(vertical_padding, kDialogEdgePadding,
|
| - vertical_padding, kDialogEdgePadding);
|
| - }
|
| -
|
| - int GetHeightForWidth(int width) const override {
|
| - int label_width = width - GetInsets().width();
|
| - if (child_count() > 1) {
|
| - const views::View* tooltip_icon = child_at(1);
|
| - label_width -= tooltip_icon->GetPreferredSize().width() +
|
| - kDialogEdgePadding;
|
| - }
|
| -
|
| - return child_at(0)->GetHeightForWidth(label_width) + GetInsets().height();
|
| - }
|
| -
|
| - void Layout() override {
|
| - // Surprisingly, GetContentsBounds() doesn't consult GetInsets().
|
| - gfx::Rect bounds = GetLocalBounds();
|
| - bounds.Inset(GetInsets());
|
| - int right_bound = bounds.right();
|
| -
|
| - if (child_count() > 1) {
|
| - // The icon takes up the entire vertical space and an extra 20px on
|
| - // each side. This increases the hover target for the tooltip.
|
| - views::View* tooltip_icon = child_at(1);
|
| - gfx::Size icon_size = tooltip_icon->GetPreferredSize();
|
| - int icon_width = icon_size.width() + kDialogEdgePadding;
|
| - right_bound -= icon_width;
|
| - tooltip_icon->SetBounds(
|
| - right_bound, 0,
|
| - icon_width + kDialogEdgePadding, GetLocalBounds().height());
|
| - }
|
| -
|
| - child_at(0)->SetBounds(bounds.x(), bounds.y(),
|
| - right_bound - bounds.x(), bounds.height());
|
| - }
|
| -
|
| - // views::StyledLabelListener implementation.
|
| - void StyledLabelLinkClicked(views::StyledLabel* label,
|
| - const gfx::Range& range,
|
| - int event_flags) override {
|
| - delegate_->LinkClicked(data_.link_url());
|
| - }
|
| -
|
| - private:
|
| - // The model data for this notification.
|
| - DialogNotification data_;
|
| -
|
| - // The delegate that handles interaction with |this|.
|
| - AutofillDialogViewDelegate* delegate_;
|
| -
|
| - // The checkbox associated with this notification, or NULL if there is none.
|
| - views::Checkbox* checkbox_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(NotificationView);
|
| -};
|
| -
|
| -// Gets either the Combobox or ExpandingTextfield that is an ancestor (including
|
| -// self) of |view|.
|
| -views::View* GetAncestralInputView(views::View* view) {
|
| - if (view->GetClassName() == views::Combobox::kViewClassName)
|
| - return view;
|
| -
|
| - return view->GetAncestorWithClassName(ExpandingTextfield::kViewClassName);
|
| -}
|
| -
|
| -// A class that informs |delegate_| when an unhandled mouse press occurs.
|
| -class MousePressedHandler : public ui::EventHandler {
|
| - public:
|
| - explicit MousePressedHandler(AutofillDialogViewDelegate* delegate)
|
| - : delegate_(delegate) {}
|
| -
|
| - // ui::EventHandler implementation.
|
| - void OnMouseEvent(ui::MouseEvent* event) override {
|
| - if (event->type() == ui::ET_MOUSE_PRESSED && !event->handled())
|
| - delegate_->FocusMoved();
|
| - }
|
| -
|
| - private:
|
| - AutofillDialogViewDelegate* const delegate_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(MousePressedHandler);
|
| -};
|
| -
|
| -} // namespace
|
| -
|
| -// AutofillDialogViews::NotificationArea ---------------------------------------
|
| -
|
| -AutofillDialogViews::NotificationArea::NotificationArea(
|
| - AutofillDialogViewDelegate* delegate)
|
| - : delegate_(delegate) {
|
| - // Reserve vertical space for the arrow (regardless of whether one exists).
|
| - // The -1 accounts for the border.
|
| - SetBorder(views::Border::CreateEmptyBorder(kArrowHeight - 1, 0, 0, 0));
|
| -
|
| - views::BoxLayout* box_layout =
|
| - new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0);
|
| - SetLayoutManager(box_layout);
|
| -}
|
| -
|
| -AutofillDialogViews::NotificationArea::~NotificationArea() {}
|
| -
|
| -void AutofillDialogViews::NotificationArea::SetNotifications(
|
| - const std::vector<DialogNotification>& notifications) {
|
| - notifications_ = notifications;
|
| -
|
| - RemoveAllChildViews(true);
|
| -
|
| - if (notifications_.empty())
|
| - return;
|
| -
|
| - for (size_t i = 0; i < notifications_.size(); ++i) {
|
| - const DialogNotification& notification = notifications_[i];
|
| - std::unique_ptr<NotificationView> view(
|
| - new NotificationView(notification, delegate_));
|
| -
|
| - AddChildView(view.release());
|
| - }
|
| -
|
| - PreferredSizeChanged();
|
| -}
|
| -
|
| -gfx::Size AutofillDialogViews::NotificationArea::GetPreferredSize() const {
|
| - gfx::Size size = views::View::GetPreferredSize();
|
| - // Ensure that long notifications wrap and don't enlarge the dialog.
|
| - size.set_width(1);
|
| - return size;
|
| -}
|
| -
|
| -const char* AutofillDialogViews::NotificationArea::GetClassName() const {
|
| - return kNotificationAreaClassName;
|
| -}
|
| -
|
| -void AutofillDialogViews::NotificationArea::PaintChildren(
|
| - const ui::PaintContext& context) {
|
| - views::View::PaintChildren(context);
|
| - if (HasArrow()) {
|
| - ui::PaintRecorder recorder(context, size());
|
| - DrawArrow(
|
| - recorder.canvas(),
|
| - GetMirroredXInView(width() - arrow_centering_anchor_->width() / 2.0f),
|
| - notifications_[0].GetBackgroundColor(),
|
| - notifications_[0].GetBorderColor());
|
| - }
|
| -}
|
| -
|
| -void AutofillDialogViews::OnWidgetDestroying(views::Widget* widget) {
|
| - if (widget == window_)
|
| - window_->GetRootView()->RemovePostTargetHandler(event_handler_.get());
|
| -}
|
| -
|
| -void AutofillDialogViews::OnWidgetClosing(views::Widget* widget) {
|
| - observer_.Remove(widget);
|
| - if (error_bubble_ && error_bubble_->GetWidget() == widget)
|
| - error_bubble_ = NULL;
|
| -}
|
| -
|
| -void AutofillDialogViews::OnWidgetBoundsChanged(views::Widget* widget,
|
| - const gfx::Rect& new_bounds) {
|
| - if (error_bubble_ && error_bubble_->GetWidget() == widget)
|
| - return;
|
| - HideErrorBubble();
|
| -}
|
| -
|
| -bool AutofillDialogViews::NotificationArea::HasArrow() {
|
| - return !notifications_.empty() && notifications_[0].HasArrow() &&
|
| - arrow_centering_anchor_.get();
|
| -}
|
| -
|
| -// AutofillDialogViews::SectionContainer ---------------------------------------
|
| -
|
| -AutofillDialogViews::SectionContainer::SectionContainer(
|
| - const base::string16& label,
|
| - views::View* controls,
|
| - views::Button* proxy_button)
|
| - : proxy_button_(proxy_button),
|
| - forward_mouse_events_(false) {
|
| - set_notify_enter_exit_on_child(true);
|
| -
|
| - SetBorder(views::Border::CreateEmptyBorder(kDetailSectionVerticalPadding,
|
| - kDialogEdgePadding,
|
| - kDetailSectionVerticalPadding,
|
| - kDialogEdgePadding));
|
| -
|
| - ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
|
| - views::Label* label_view = new views::Label(
|
| - label, rb.GetFontList(ui::ResourceBundle::BoldFont));
|
| - label_view->SetHorizontalAlignment(gfx::ALIGN_LEFT);
|
| -
|
| - views::View* label_bar = new views::View();
|
| - views::GridLayout* label_bar_layout = new views::GridLayout(label_bar);
|
| - label_bar->SetLayoutManager(label_bar_layout);
|
| - const int kColumnSetId = 0;
|
| - views::ColumnSet* columns = label_bar_layout->AddColumnSet(kColumnSetId);
|
| - columns->AddColumn(
|
| - views::GridLayout::LEADING,
|
| - views::GridLayout::LEADING,
|
| - 0,
|
| - views::GridLayout::FIXED,
|
| - kSectionContainerWidth - proxy_button->GetPreferredSize().width(),
|
| - 0);
|
| - columns->AddColumn(views::GridLayout::LEADING,
|
| - views::GridLayout::LEADING,
|
| - 0,
|
| - views::GridLayout::USE_PREF,
|
| - 0,
|
| - 0);
|
| - label_bar_layout->StartRow(0, kColumnSetId);
|
| - label_bar_layout->AddView(label_view);
|
| - label_bar_layout->AddView(proxy_button);
|
| -
|
| - SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0));
|
| - AddChildView(label_bar);
|
| - AddChildView(controls);
|
| -
|
| - SetEventTargeter(
|
| - std::unique_ptr<views::ViewTargeter>(new views::ViewTargeter(this)));
|
| -}
|
| -
|
| -AutofillDialogViews::SectionContainer::~SectionContainer() {}
|
| -
|
| -void AutofillDialogViews::SectionContainer::SetActive(bool active) {
|
| - bool is_active = active && proxy_button_->visible();
|
| - if (is_active == !!background())
|
| - return;
|
| -
|
| - set_background(
|
| - is_active ? views::Background::CreateSolidBackground(kLightShadingColor)
|
| - : NULL);
|
| - SchedulePaint();
|
| -}
|
| -
|
| -void AutofillDialogViews::SectionContainer::SetForwardMouseEvents(
|
| - bool forward) {
|
| - forward_mouse_events_ = forward;
|
| - if (!forward)
|
| - set_background(NULL);
|
| -}
|
| -
|
| -const char* AutofillDialogViews::SectionContainer::GetClassName() const {
|
| - return kSectionContainerClassName;
|
| -}
|
| -
|
| -void AutofillDialogViews::SectionContainer::OnMouseMoved(
|
| - const ui::MouseEvent& event) {
|
| - SetActive(ShouldForwardEvent(event));
|
| -}
|
| -
|
| -void AutofillDialogViews::SectionContainer::OnMouseEntered(
|
| - const ui::MouseEvent& event) {
|
| - if (!ShouldForwardEvent(event))
|
| - return;
|
| -
|
| - SetActive(true);
|
| - proxy_button_->OnMouseEntered(ProxyEvent(event));
|
| - SchedulePaint();
|
| -}
|
| -
|
| -void AutofillDialogViews::SectionContainer::OnMouseExited(
|
| - const ui::MouseEvent& event) {
|
| - SetActive(false);
|
| - if (!ShouldForwardEvent(event))
|
| - return;
|
| -
|
| - proxy_button_->OnMouseExited(ProxyEvent(event));
|
| - SchedulePaint();
|
| -}
|
| -
|
| -bool AutofillDialogViews::SectionContainer::OnMousePressed(
|
| - const ui::MouseEvent& event) {
|
| - if (!ShouldForwardEvent(event))
|
| - return false;
|
| -
|
| - return proxy_button_->OnMousePressed(ProxyEvent(event));
|
| -}
|
| -
|
| -void AutofillDialogViews::SectionContainer::OnMouseReleased(
|
| - const ui::MouseEvent& event) {
|
| - if (!ShouldForwardEvent(event))
|
| - return;
|
| -
|
| - proxy_button_->OnMouseReleased(ProxyEvent(event));
|
| -}
|
| -
|
| -void AutofillDialogViews::SectionContainer::OnGestureEvent(
|
| - ui::GestureEvent* event) {
|
| - if (!ShouldForwardEvent(*event))
|
| - return;
|
| -
|
| - proxy_button_->OnGestureEvent(event);
|
| -}
|
| -
|
| -views::View* AutofillDialogViews::SectionContainer::TargetForRect(
|
| - views::View* root,
|
| - const gfx::Rect& rect) {
|
| - CHECK_EQ(root, this);
|
| - views::View* handler = views::ViewTargeterDelegate::TargetForRect(root, rect);
|
| -
|
| - // If the event is not in the label bar and there's no background to be
|
| - // cleared, let normal event handling take place.
|
| - if (!background() &&
|
| - rect.CenterPoint().y() > child_at(0)->bounds().bottom()) {
|
| - return handler;
|
| - }
|
| -
|
| - // Special case for (CVC) inputs in the suggestion view.
|
| - if (forward_mouse_events_ &&
|
| - handler->GetAncestorWithClassName(ExpandingTextfield::kViewClassName)) {
|
| - return handler;
|
| - }
|
| -
|
| - // Special case for the proxy button itself.
|
| - if (handler == proxy_button_)
|
| - return handler;
|
| -
|
| - return this;
|
| -}
|
| -
|
| -// static
|
| -ui::MouseEvent AutofillDialogViews::SectionContainer::ProxyEvent(
|
| - const ui::MouseEvent& event) {
|
| - ui::MouseEvent event_copy = event;
|
| - event_copy.set_location(gfx::Point());
|
| - return event_copy;
|
| -}
|
| -
|
| -bool AutofillDialogViews::SectionContainer::ShouldForwardEvent(
|
| - const ui::LocatedEvent& event) {
|
| - // Always forward events on the label bar.
|
| - return forward_mouse_events_ || event.y() <= child_at(0)->bounds().bottom();
|
| -}
|
| -
|
| -// AutofillDialogViews::SuggestedButton ----------------------------------------
|
| -
|
| -AutofillDialogViews::SuggestedButton::SuggestedButton(
|
| - views::MenuButtonListener* listener)
|
| - : views::MenuButton(base::string16(), listener, false) {
|
| - const int kFocusBorderWidth = 1;
|
| - SetBorder(views::Border::CreateEmptyBorder(kMenuButtonTopInset,
|
| - kFocusBorderWidth,
|
| - kMenuButtonBottomInset,
|
| - kFocusBorderWidth));
|
| - gfx::Insets insets = GetInsets();
|
| - insets += gfx::Insets(-kFocusBorderWidth, -kFocusBorderWidth,
|
| - -kFocusBorderWidth, -kFocusBorderWidth);
|
| - SetFocusPainter(
|
| - views::Painter::CreateDashedFocusPainterWithInsets(insets));
|
| - SetFocusBehavior(FocusBehavior::ALWAYS);
|
| -}
|
| -
|
| -AutofillDialogViews::SuggestedButton::~SuggestedButton() {}
|
| -
|
| -gfx::Size AutofillDialogViews::SuggestedButton::GetPreferredSize() const {
|
| - ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
|
| - gfx::Size size = rb.GetImageNamed(ResourceIDForState()).Size();
|
| - const gfx::Insets insets = GetInsets();
|
| - size.Enlarge(insets.width(), insets.height());
|
| - return size;
|
| -}
|
| -
|
| -const char* AutofillDialogViews::SuggestedButton::GetClassName() const {
|
| - return kSuggestedButtonClassName;
|
| -}
|
| -
|
| -void AutofillDialogViews::SuggestedButton::OnPaint(gfx::Canvas* canvas) {
|
| - ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
|
| - const gfx::Insets insets = GetInsets();
|
| - canvas->DrawImageInt(*rb.GetImageSkiaNamed(ResourceIDForState()),
|
| - insets.left(), insets.top());
|
| - views::Painter::PaintFocusPainter(this, canvas, focus_painter());
|
| -}
|
| -
|
| -int AutofillDialogViews::SuggestedButton::ResourceIDForState() const {
|
| - views::Button::ButtonState button_state = state();
|
| - if (button_state == views::Button::STATE_PRESSED)
|
| - return IDR_AUTOFILL_DIALOG_MENU_BUTTON_P;
|
| - else if (button_state == views::Button::STATE_HOVERED)
|
| - return IDR_AUTOFILL_DIALOG_MENU_BUTTON_H;
|
| - else if (button_state == views::Button::STATE_DISABLED)
|
| - return IDR_AUTOFILL_DIALOG_MENU_BUTTON_D;
|
| - DCHECK_EQ(views::Button::STATE_NORMAL, button_state);
|
| - return IDR_AUTOFILL_DIALOG_MENU_BUTTON;
|
| -}
|
| -
|
| -// AutofillDialogViews::DetailsContainerView -----------------------------------
|
| -
|
| -AutofillDialogViews::DetailsContainerView::DetailsContainerView(
|
| - const base::Closure& callback)
|
| - : bounds_changed_callback_(callback),
|
| - ignore_layouts_(false) {}
|
| -
|
| -AutofillDialogViews::DetailsContainerView::~DetailsContainerView() {}
|
| -
|
| -void AutofillDialogViews::DetailsContainerView::OnBoundsChanged(
|
| - const gfx::Rect& previous_bounds) {
|
| - bounds_changed_callback_.Run();
|
| -}
|
| -
|
| -void AutofillDialogViews::DetailsContainerView::Layout() {
|
| - if (!ignore_layouts_)
|
| - views::View::Layout();
|
| -}
|
| -
|
| -// AutofillDialogViews::SuggestionView -----------------------------------------
|
| -
|
| -AutofillDialogViews::SuggestionView::SuggestionView(
|
| - AutofillDialogViews* autofill_dialog)
|
| - : label_(new views::Label()),
|
| - label_line_2_(new views::Label()),
|
| - icon_(new views::ImageView()),
|
| - textfield_(
|
| - new ExpandingTextfield(base::string16(),
|
| - base::string16(),
|
| - false,
|
| - autofill_dialog)) {
|
| - // TODO(estade): Make this the correct color.
|
| - SetBorder(views::Border::CreateSolidSidedBorder(1, 0, 0, 0, SK_ColorLTGRAY));
|
| -
|
| - SectionRowView* label_container = new SectionRowView();
|
| - AddChildView(label_container);
|
| -
|
| - // Label and icon.
|
| - label_container->AddChildView(icon_);
|
| - label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
|
| - label_container->AddChildView(label_);
|
| -
|
| - // TODO(estade): get the sizing and spacing right on this textfield.
|
| - textfield_->SetVisible(false);
|
| - textfield_->SetDefaultWidthInCharacters(15);
|
| - label_container->AddChildView(textfield_);
|
| -
|
| - label_line_2_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
|
| - label_line_2_->SetVisible(false);
|
| - label_line_2_->SetLineHeight(22);
|
| - label_line_2_->SetMultiLine(true);
|
| - AddChildView(label_line_2_);
|
| -
|
| - SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 7));
|
| -}
|
| -
|
| -AutofillDialogViews::SuggestionView::~SuggestionView() {}
|
| -
|
| -gfx::Size AutofillDialogViews::SuggestionView::GetPreferredSize() const {
|
| - // There's no preferred width. The parent's layout should get the preferred
|
| - // height from GetHeightForWidth().
|
| - return gfx::Size();
|
| -}
|
| -
|
| -int AutofillDialogViews::SuggestionView::GetHeightForWidth(int width) const {
|
| - int height = 0;
|
| - CanUseVerticallyCompactText(width, &height);
|
| - return height;
|
| -}
|
| -
|
| -bool AutofillDialogViews::SuggestionView::CanUseVerticallyCompactText(
|
| - int available_width,
|
| - int* resulting_height) const {
|
| - // This calculation may be costly, avoid doing it more than once per width.
|
| - if (!calculated_heights_.count(available_width)) {
|
| - // Changing the state of |this| now will lead to extra layouts and
|
| - // paints we don't want, so create another SuggestionView to calculate
|
| - // which label we have room to show.
|
| - SuggestionView sizing_view(NULL);
|
| - sizing_view.SetLabelText(state_.vertically_compact_text);
|
| - sizing_view.SetIcon(state_.icon);
|
| - sizing_view.SetTextfield(state_.extra_text, state_.extra_icon);
|
| - sizing_view.label_->SetSize(gfx::Size(available_width, 0));
|
| - sizing_view.label_line_2_->SetSize(gfx::Size(available_width, 0));
|
| -
|
| - // Shortcut |sizing_view|'s GetHeightForWidth() to avoid an infinite loop.
|
| - // Its BoxLayout must do these calculations for us.
|
| - views::LayoutManager* layout = sizing_view.GetLayoutManager();
|
| - if (layout->GetPreferredSize(&sizing_view).width() <= available_width) {
|
| - calculated_heights_[available_width] = std::make_pair(
|
| - true,
|
| - layout->GetPreferredHeightForWidth(&sizing_view, available_width));
|
| - } else {
|
| - sizing_view.SetLabelText(state_.horizontally_compact_text);
|
| - calculated_heights_[available_width] = std::make_pair(
|
| - false,
|
| - layout->GetPreferredHeightForWidth(&sizing_view, available_width));
|
| - }
|
| - }
|
| -
|
| - const std::pair<bool, int>& values = calculated_heights_[available_width];
|
| - *resulting_height = values.second;
|
| - return values.first;
|
| -}
|
| -
|
| -void AutofillDialogViews::SuggestionView::OnBoundsChanged(
|
| - const gfx::Rect& previous_bounds) {
|
| - UpdateLabelText();
|
| -}
|
| -
|
| -void AutofillDialogViews::SuggestionView::SetState(
|
| - const SuggestionState& state) {
|
| - calculated_heights_.clear();
|
| - state_ = state;
|
| - SetVisible(state_.visible);
|
| - UpdateLabelText();
|
| - SetIcon(state_.icon);
|
| - SetTextfield(state_.extra_text, state_.extra_icon);
|
| - PreferredSizeChanged();
|
| -}
|
| -
|
| -void AutofillDialogViews::SuggestionView::SetLabelText(
|
| - const base::string16& text) {
|
| - // TODO(estade): does this localize well?
|
| - base::string16 line_return(base::ASCIIToUTF16("\n"));
|
| - size_t position = text.find(line_return);
|
| - if (position == base::string16::npos) {
|
| - label_->SetText(text);
|
| - label_line_2_->SetVisible(false);
|
| - } else {
|
| - label_->SetText(text.substr(0, position));
|
| - label_line_2_->SetText(text.substr(position + line_return.length()));
|
| - label_line_2_->SetVisible(true);
|
| - }
|
| -}
|
| -
|
| -void AutofillDialogViews::SuggestionView::SetIcon(
|
| - const gfx::Image& image) {
|
| - icon_->SetVisible(!image.IsEmpty());
|
| - icon_->SetImage(image.AsImageSkia());
|
| -}
|
| -
|
| -void AutofillDialogViews::SuggestionView::SetTextfield(
|
| - const base::string16& placeholder_text,
|
| - const gfx::Image& icon) {
|
| - textfield_->SetPlaceholderText(placeholder_text);
|
| - textfield_->SetIcon(icon);
|
| - textfield_->SetVisible(!placeholder_text.empty());
|
| -}
|
| -
|
| -void AutofillDialogViews::SuggestionView::UpdateLabelText() {
|
| - int unused;
|
| - SetLabelText(CanUseVerticallyCompactText(width(), &unused) ?
|
| - state_.vertically_compact_text :
|
| - state_.horizontally_compact_text);
|
| -}
|
| -
|
| -// AutofillDialogView ----------------------------------------------------------
|
| -
|
| -// static
|
| -AutofillDialogView* AutofillDialogView::Create(
|
| - AutofillDialogViewDelegate* delegate) {
|
| - return new AutofillDialogViews(delegate);
|
| -}
|
| -
|
| -// AutofillDialogViews ---------------------------------------------------------
|
| -
|
| -AutofillDialogViews::AutofillDialogViews(AutofillDialogViewDelegate* delegate)
|
| - : delegate_(delegate),
|
| - updates_scope_(0),
|
| - needs_update_(false),
|
| - window_(NULL),
|
| - notification_area_(NULL),
|
| - scrollable_area_(NULL),
|
| - details_container_(NULL),
|
| - button_strip_extra_view_(NULL),
|
| - save_in_chrome_checkbox_(NULL),
|
| - save_in_chrome_checkbox_container_(NULL),
|
| - focus_manager_(NULL),
|
| - error_bubble_(NULL),
|
| - observer_(this) {
|
| - DCHECK(delegate);
|
| - detail_groups_.insert(std::make_pair(SECTION_CC,
|
| - DetailsGroup(SECTION_CC)));
|
| - detail_groups_.insert(std::make_pair(SECTION_BILLING,
|
| - DetailsGroup(SECTION_BILLING)));
|
| - detail_groups_.insert(std::make_pair(SECTION_SHIPPING,
|
| - DetailsGroup(SECTION_SHIPPING)));
|
| -}
|
| -
|
| -AutofillDialogViews::~AutofillDialogViews() {
|
| - HideErrorBubble();
|
| - DCHECK(!window_);
|
| -}
|
| -
|
| -void AutofillDialogViews::Show() {
|
| - InitChildViews();
|
| - UpdateNotificationArea();
|
| - UpdateButtonStripExtraView();
|
| -
|
| - window_ = constrained_window::ShowWebModalDialogViews(
|
| - this, delegate_->GetWebContents());
|
| - focus_manager_ = window_->GetFocusManager();
|
| - focus_manager_->AddFocusChangeListener(this);
|
| -
|
| - FocusInitialView();
|
| -
|
| - // Listen for size changes on the browser.
|
| - views::Widget* browser_widget =
|
| - views::Widget::GetTopLevelWidgetForNativeView(
|
| - delegate_->GetWebContents()->GetNativeView());
|
| - observer_.Add(browser_widget);
|
| -
|
| - // Listen for unhandled mouse presses on the non-client view.
|
| - event_handler_.reset(new MousePressedHandler(delegate_));
|
| - window_->GetRootView()->AddPostTargetHandler(event_handler_.get());
|
| - observer_.Add(window_);
|
| -}
|
| -
|
| -void AutofillDialogViews::Hide() {
|
| - if (window_)
|
| - window_->Close();
|
| -}
|
| -
|
| -void AutofillDialogViews::UpdatesStarted() {
|
| - updates_scope_++;
|
| -}
|
| -
|
| -void AutofillDialogViews::UpdatesFinished() {
|
| - updates_scope_--;
|
| - DCHECK_GE(updates_scope_, 0);
|
| - if (updates_scope_ == 0 && needs_update_) {
|
| - needs_update_ = false;
|
| - ContentsPreferredSizeChanged();
|
| - }
|
| -}
|
| -
|
| -void AutofillDialogViews::UpdateButtonStrip() {
|
| - button_strip_extra_view_->SetVisible(
|
| - GetDialogButtons() != ui::DIALOG_BUTTON_NONE);
|
| - UpdateButtonStripExtraView();
|
| - GetDialogClientView()->UpdateDialogButtons();
|
| -
|
| - ContentsPreferredSizeChanged();
|
| -}
|
| -
|
| -void AutofillDialogViews::UpdateDetailArea() {
|
| - scrollable_area_->SetVisible(true);
|
| - ContentsPreferredSizeChanged();
|
| -}
|
| -
|
| -void AutofillDialogViews::UpdateForErrors() {
|
| - ValidateForm();
|
| -}
|
| -
|
| -void AutofillDialogViews::UpdateNotificationArea() {
|
| - DCHECK(notification_area_);
|
| - notification_area_->SetNotifications(delegate_->CurrentNotifications());
|
| - ContentsPreferredSizeChanged();
|
| -}
|
| -
|
| -void AutofillDialogViews::UpdateSection(DialogSection section) {
|
| - UpdateSectionImpl(section, true);
|
| -}
|
| -
|
| -void AutofillDialogViews::UpdateErrorBubble() {
|
| - if (!delegate_->ShouldShowErrorBubble())
|
| - HideErrorBubble();
|
| -}
|
| -
|
| -void AutofillDialogViews::FillSection(DialogSection section,
|
| - ServerFieldType originating_type) {
|
| - DetailsGroup* group = GroupForSection(section);
|
| - // Make sure to overwrite the originating input if it exists.
|
| - TextfieldMap::iterator text_mapping =
|
| - group->textfields.find(originating_type);
|
| - if (text_mapping != group->textfields.end())
|
| - text_mapping->second->SetText(base::string16());
|
| -
|
| - // If the Autofill data comes from a credit card, make sure to overwrite the
|
| - // CC comboboxes (even if they already have something in them). If the
|
| - // Autofill data comes from an AutofillProfile, leave the comboboxes alone.
|
| - if (section == GetCreditCardSection() &&
|
| - AutofillType(originating_type).group() == CREDIT_CARD) {
|
| - for (ComboboxMap::const_iterator it = group->comboboxes.begin();
|
| - it != group->comboboxes.end(); ++it) {
|
| - if (AutofillType(it->first).group() == CREDIT_CARD)
|
| - it->second->SetSelectedIndex(it->second->model()->GetDefaultIndex());
|
| - }
|
| - }
|
| -
|
| - UpdateSectionImpl(section, false);
|
| -}
|
| -
|
| -void AutofillDialogViews::GetUserInput(DialogSection section,
|
| - FieldValueMap* output) {
|
| - DetailsGroup* group = GroupForSection(section);
|
| - for (TextfieldMap::const_iterator it = group->textfields.begin();
|
| - it != group->textfields.end(); ++it) {
|
| - output->insert(std::make_pair(it->first, it->second->GetText()));
|
| - }
|
| - for (ComboboxMap::const_iterator it = group->comboboxes.begin();
|
| - it != group->comboboxes.end(); ++it) {
|
| - output->insert(std::make_pair(it->first,
|
| - it->second->model()->GetItemAt(it->second->selected_index())));
|
| - }
|
| -}
|
| -
|
| -base::string16 AutofillDialogViews::GetCvc() {
|
| - return GroupForSection(GetCreditCardSection())->suggested_info->
|
| - textfield()->GetText();
|
| -}
|
| -
|
| -bool AutofillDialogViews::SaveDetailsLocally() {
|
| - DCHECK(save_in_chrome_checkbox_->visible());
|
| - return save_in_chrome_checkbox_->checked();
|
| -}
|
| -
|
| -void AutofillDialogViews::ModelChanged() {
|
| - menu_runner_.reset();
|
| -
|
| - for (DetailGroupMap::const_iterator iter = detail_groups_.begin();
|
| - iter != detail_groups_.end(); ++iter) {
|
| - UpdateDetailsGroupState(iter->second);
|
| - }
|
| -}
|
| -
|
| -void AutofillDialogViews::ValidateSection(DialogSection section) {
|
| - ValidateGroup(*GroupForSection(section), VALIDATE_EDIT);
|
| -}
|
| -
|
| -gfx::Size AutofillDialogViews::GetPreferredSize() const {
|
| - if (preferred_size_.IsEmpty())
|
| - preferred_size_ = CalculatePreferredSize(false);
|
| -
|
| - return preferred_size_;
|
| -}
|
| -
|
| -gfx::Size AutofillDialogViews::GetMinimumSize() const {
|
| - return CalculatePreferredSize(true);
|
| -}
|
| -
|
| -void AutofillDialogViews::Layout() {
|
| - const gfx::Rect content_bounds = GetContentsBounds();
|
| - const int x = content_bounds.x();
|
| - const int y = content_bounds.y();
|
| - const int width = content_bounds.width();
|
| - // Layout notification area at top of dialog.
|
| - int notification_height = notification_area_->GetHeightForWidth(width);
|
| - notification_area_->SetBounds(x, y, width, notification_height);
|
| -
|
| - // The rest (the |scrollable_area_|) takes up whatever's left.
|
| - if (scrollable_area_->visible()) {
|
| - int scroll_y = y;
|
| - if (notification_height > notification_area_->GetInsets().height())
|
| - scroll_y += notification_height + views::kRelatedControlVerticalSpacing;
|
| -
|
| - int scroll_bottom = content_bounds.bottom();
|
| - DCHECK_EQ(scrollable_area_->contents(), details_container_);
|
| - details_container_->SizeToPreferredSize();
|
| - details_container_->Layout();
|
| - // TODO(estade): remove this hack. See crbug.com/285996
|
| - details_container_->set_ignore_layouts(true);
|
| - scrollable_area_->SetBounds(x, scroll_y, width, scroll_bottom - scroll_y);
|
| - details_container_->set_ignore_layouts(false);
|
| - }
|
| -
|
| - if (error_bubble_)
|
| - error_bubble_->UpdatePosition();
|
| -}
|
| -
|
| -ui::ModalType AutofillDialogViews::GetModalType() const {
|
| - return ui::MODAL_TYPE_CHILD;
|
| -}
|
| -
|
| -base::string16 AutofillDialogViews::GetWindowTitle() const {
|
| - base::string16 title = delegate_->DialogTitle();
|
| - // Hack alert: we don't want the dialog to jiggle when a title is added or
|
| - // removed. Setting a non-empty string here keeps the dialog's title bar the
|
| - // same size.
|
| - return title.empty() ? base::ASCIIToUTF16(" ") : title;
|
| -}
|
| -
|
| -void AutofillDialogViews::WindowClosing() {
|
| - focus_manager_->RemoveFocusChangeListener(this);
|
| -}
|
| -
|
| -void AutofillDialogViews::DeleteDelegate() {
|
| - window_ = NULL;
|
| - // |this| belongs to the controller (|delegate_|).
|
| - delegate_->ViewClosed();
|
| -}
|
| -
|
| -int AutofillDialogViews::GetDialogButtons() const {
|
| - return delegate_->GetDialogButtons();
|
| -}
|
| -
|
| -int AutofillDialogViews::GetDefaultDialogButton() const {
|
| - if (GetDialogButtons() & ui::DIALOG_BUTTON_OK)
|
| - return ui::DIALOG_BUTTON_OK;
|
| -
|
| - return ui::DIALOG_BUTTON_NONE;
|
| -}
|
| -
|
| -base::string16 AutofillDialogViews::GetDialogButtonLabel(
|
| - ui::DialogButton button) const {
|
| - return button == ui::DIALOG_BUTTON_OK ?
|
| - delegate_->ConfirmButtonText() : delegate_->CancelButtonText();
|
| -}
|
| -
|
| -bool AutofillDialogViews::ShouldDefaultButtonBeBlue() const {
|
| - return true;
|
| -}
|
| -
|
| -bool AutofillDialogViews::IsDialogButtonEnabled(ui::DialogButton button) const {
|
| - return delegate_->IsDialogButtonEnabled(button);
|
| -}
|
| -
|
| -views::View* AutofillDialogViews::GetInitiallyFocusedView() {
|
| - if (!window_ || !focus_manager_)
|
| - return NULL;
|
| -
|
| - DCHECK(scrollable_area_->visible());
|
| -
|
| - views::FocusManager* manager = focus_manager_;
|
| - for (views::View* next = scrollable_area_;
|
| - next;
|
| - next = manager->GetNextFocusableView(next, window_, false, true)) {
|
| - views::View* input_view = GetAncestralInputView(next);
|
| - if (!input_view)
|
| - continue;
|
| -
|
| - // If there are no invalid inputs, return the first input found. Otherwise,
|
| - // return the first invalid input found.
|
| - if (validity_map_.empty() ||
|
| - validity_map_.find(input_view) != validity_map_.end()) {
|
| - return next;
|
| - }
|
| - }
|
| -
|
| - return views::DialogDelegateView::GetInitiallyFocusedView();
|
| -}
|
| -
|
| -views::View* AutofillDialogViews::CreateExtraView() {
|
| - return button_strip_extra_view_;
|
| -}
|
| -
|
| -bool AutofillDialogViews::Cancel() {
|
| - delegate_->OnCancel();
|
| - return true;
|
| -}
|
| -
|
| -bool AutofillDialogViews::Accept() {
|
| - if (ValidateForm()) {
|
| - delegate_->OnAccept();
|
| - } else {
|
| - // |ValidateForm()| failed; there should be invalid views in
|
| - // |validity_map_|.
|
| - DCHECK(!validity_map_.empty());
|
| - FocusInitialView();
|
| - }
|
| -
|
| - return false;
|
| -}
|
| -
|
| -void AutofillDialogViews::ContentsChanged(views::Textfield* sender,
|
| - const base::string16& new_contents) {
|
| - InputEditedOrActivated(TypeForTextfield(sender),
|
| - sender->GetBoundsInScreen(),
|
| - true);
|
| -
|
| - const ExpandingTextfield* expanding = static_cast<ExpandingTextfield*>(
|
| - sender->GetAncestorWithClassName(ExpandingTextfield::kViewClassName));
|
| - if (expanding && expanding->needs_layout())
|
| - ContentsPreferredSizeChanged();
|
| -}
|
| -
|
| -bool AutofillDialogViews::HandleKeyEvent(views::Textfield* sender,
|
| - const ui::KeyEvent& key_event) {
|
| - content::NativeWebKeyboardEvent event(key_event);
|
| - return delegate_->HandleKeyPressEventInInput(event);
|
| -}
|
| -
|
| -bool AutofillDialogViews::HandleMouseEvent(views::Textfield* sender,
|
| - const ui::MouseEvent& mouse_event) {
|
| - if (mouse_event.IsLeftMouseButton() && sender->HasFocus()) {
|
| - InputEditedOrActivated(TypeForTextfield(sender),
|
| - sender->GetBoundsInScreen(),
|
| - false);
|
| - // Show an error bubble if a user clicks on an input that's already focused
|
| - // (and invalid).
|
| - ShowErrorBubbleForViewIfNecessary(sender);
|
| - }
|
| -
|
| - return false;
|
| -}
|
| -
|
| -void AutofillDialogViews::OnWillChangeFocus(
|
| - views::View* focused_before,
|
| - views::View* focused_now) {
|
| - delegate_->FocusMoved();
|
| - HideErrorBubble();
|
| -}
|
| -
|
| -void AutofillDialogViews::OnDidChangeFocus(
|
| - views::View* focused_before,
|
| - views::View* focused_now) {
|
| - // If user leaves an edit-field, revalidate the group it belongs to.
|
| - if (focused_before) {
|
| - DetailsGroup* group = GroupForView(focused_before);
|
| - if (group && group->container->visible())
|
| - ValidateGroup(*group, VALIDATE_EDIT);
|
| - }
|
| -
|
| - // Show an error bubble when the user focuses the input.
|
| - if (focused_now) {
|
| - focused_now->ScrollRectToVisible(focused_now->GetLocalBounds());
|
| - ShowErrorBubbleForViewIfNecessary(focused_now);
|
| - }
|
| -}
|
| -
|
| -void AutofillDialogViews::OnPerformAction(views::Combobox* combobox) {
|
| - DialogSection section = GroupForView(combobox)->section;
|
| - InputEditedOrActivated(TypeForCombobox(combobox), gfx::Rect(), true);
|
| - // NOTE: |combobox| may have been deleted.
|
| - ValidateGroup(*GroupForSection(section), VALIDATE_EDIT);
|
| -}
|
| -
|
| -void AutofillDialogViews::OnMenuButtonClicked(views::MenuButton* source,
|
| - const gfx::Point& point,
|
| - const ui::Event* event) {
|
| - DCHECK_EQ(kSuggestedButtonClassName, source->GetClassName());
|
| -
|
| - DetailsGroup* group = NULL;
|
| - for (DetailGroupMap::iterator iter = detail_groups_.begin();
|
| - iter != detail_groups_.end(); ++iter) {
|
| - if (source == iter->second.suggested_button) {
|
| - group = &iter->second;
|
| - break;
|
| - }
|
| - }
|
| - DCHECK(group);
|
| -
|
| - if (!group->suggested_button->visible())
|
| - return;
|
| -
|
| - menu_runner_.reset(
|
| - new views::MenuRunner(delegate_->MenuModelForSection(group->section), 0));
|
| -
|
| - group->container->SetActive(true);
|
| -
|
| - gfx::Rect screen_bounds = source->GetBoundsInScreen();
|
| - screen_bounds.Inset(source->GetInsets());
|
| - if (menu_runner_->RunMenuAt(source->GetWidget(),
|
| - group->suggested_button,
|
| - screen_bounds,
|
| - views::MENU_ANCHOR_TOPRIGHT,
|
| - ui::MENU_SOURCE_NONE) ==
|
| - views::MenuRunner::MENU_DELETED) {
|
| - return;
|
| - }
|
| -
|
| - group->container->SetActive(false);
|
| -}
|
| -
|
| -gfx::Size AutofillDialogViews::CalculatePreferredSize(
|
| - bool get_minimum_size) const {
|
| - gfx::Insets insets = GetInsets();
|
| - gfx::Size scroll_size = scrollable_area_->contents()->GetPreferredSize();
|
| - // The width is always set by the scroll area.
|
| - const int width = scroll_size.width();
|
| -
|
| - int height = 0;
|
| - const int notification_height = notification_area_->GetHeightForWidth(width);
|
| - if (notification_height > notification_area_->GetInsets().height())
|
| - height += notification_height + views::kRelatedControlVerticalSpacing;
|
| -
|
| - if (scrollable_area_->visible())
|
| - height += get_minimum_size ? kMinimumContentsHeight : scroll_size.height();
|
| -
|
| - return gfx::Size(width + insets.width(), height + insets.height());
|
| -}
|
| -
|
| -gfx::Size AutofillDialogViews::GetMinimumSignInViewSize() const {
|
| - return gfx::Size(GetDialogClientView()->size().width() - GetInsets().width(),
|
| - kMinimumContentsHeight);
|
| -}
|
| -
|
| -gfx::Size AutofillDialogViews::GetMaximumSignInViewSize() const {
|
| - web_modal::WebContentsModalDialogHost* dialog_host =
|
| - web_modal::WebContentsModalDialogManager::FromWebContents(
|
| - delegate_->GetWebContents())->delegate()->
|
| - GetWebContentsModalDialogHost();
|
| -
|
| - // Inset the maximum dialog height to get the maximum content height.
|
| - int height = dialog_host->GetMaximumDialogSize().height();
|
| - const int non_client_height = GetWidget()->non_client_view()->height();
|
| - const int client_height = GetWidget()->client_view()->height();
|
| - // TODO(msw): Resolve the 12 pixel discrepancy; is that the bubble border?
|
| - height -= non_client_height - client_height - 12;
|
| - height = std::max(height, kMinimumContentsHeight);
|
| -
|
| - // The dialog's width never changes.
|
| - const int width = GetDialogClientView()->size().width() - GetInsets().width();
|
| - return gfx::Size(width, height);
|
| -}
|
| -
|
| -// TODO(estade): remove.
|
| -DialogSection AutofillDialogViews::GetCreditCardSection() const {
|
| - return SECTION_CC;
|
| -}
|
| -
|
| -void AutofillDialogViews::InitChildViews() {
|
| - button_strip_extra_view_ = new LayoutPropagationView();
|
| - button_strip_extra_view_->SetLayoutManager(
|
| - new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 0));
|
| -
|
| - save_in_chrome_checkbox_container_ = new views::View();
|
| - save_in_chrome_checkbox_container_->SetLayoutManager(
|
| - new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 7));
|
| - button_strip_extra_view_->AddChildView(save_in_chrome_checkbox_container_);
|
| -
|
| - save_in_chrome_checkbox_ =
|
| - new views::Checkbox(delegate_->SaveLocallyText());
|
| - save_in_chrome_checkbox_->SetChecked(delegate_->ShouldSaveInChrome());
|
| - save_in_chrome_checkbox_container_->AddChildView(save_in_chrome_checkbox_);
|
| -
|
| - save_in_chrome_checkbox_container_->AddChildView(
|
| - new TooltipIcon(delegate_->SaveLocallyTooltip()));
|
| -
|
| - notification_area_ = new NotificationArea(delegate_);
|
| - AddChildView(notification_area_);
|
| -
|
| - scrollable_area_ = new views::ScrollView();
|
| - scrollable_area_->set_hide_horizontal_scrollbar(true);
|
| - scrollable_area_->SetContents(CreateDetailsContainer());
|
| - AddChildView(scrollable_area_);
|
| -}
|
| -
|
| -views::View* AutofillDialogViews::CreateDetailsContainer() {
|
| - details_container_ = new DetailsContainerView(
|
| - base::Bind(&AutofillDialogViews::DetailsContainerBoundsChanged,
|
| - base::Unretained(this)));
|
| -
|
| - // A box layout is used because it respects widget visibility.
|
| - details_container_->SetLayoutManager(
|
| - new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0));
|
| - for (DetailGroupMap::iterator iter = detail_groups_.begin();
|
| - iter != detail_groups_.end(); ++iter) {
|
| - CreateDetailsSection(iter->second.section);
|
| - details_container_->AddChildView(iter->second.container);
|
| - }
|
| -
|
| - return details_container_;
|
| -}
|
| -
|
| -void AutofillDialogViews::CreateDetailsSection(DialogSection section) {
|
| - // Inputs container (manual inputs + combobox).
|
| - views::View* inputs_container = CreateInputsContainer(section);
|
| -
|
| - DetailsGroup* group = GroupForSection(section);
|
| - // Container (holds label + inputs).
|
| - group->container = new SectionContainer(delegate_->LabelForSection(section),
|
| - inputs_container,
|
| - group->suggested_button);
|
| - DCHECK(group->suggested_button->parent());
|
| - UpdateDetailsGroupState(*group);
|
| -}
|
| -
|
| -views::View* AutofillDialogViews::CreateInputsContainer(DialogSection section) {
|
| - // The |info_view| holds |manual_inputs| and |suggested_info|, allowing the
|
| - // dialog to toggle which is shown.
|
| - views::View* info_view = new views::View();
|
| - info_view->SetLayoutManager(
|
| - new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0));
|
| -
|
| - DetailsGroup* group = GroupForSection(section);
|
| - group->manual_input = new views::View();
|
| - InitInputsView(section);
|
| - info_view->AddChildView(group->manual_input);
|
| -
|
| - group->suggested_info = new SuggestionView(this);
|
| - info_view->AddChildView(group->suggested_info);
|
| -
|
| - // TODO(estade): It might be slightly more OO if this button were created
|
| - // and listened to by the section container.
|
| - group->suggested_button = new SuggestedButton(this);
|
| -
|
| - return info_view;
|
| -}
|
| -
|
| -// TODO(estade): we should be using Chrome-style constrained window padding
|
| -// values.
|
| -void AutofillDialogViews::InitInputsView(DialogSection section) {
|
| - DetailsGroup* group = GroupForSection(section);
|
| - EraseInvalidViewsInGroup(group);
|
| -
|
| - TextfieldMap* textfields = &group->textfields;
|
| - textfields->clear();
|
| -
|
| - ComboboxMap* comboboxes = &group->comboboxes;
|
| - comboboxes->clear();
|
| -
|
| - views::View* view = group->manual_input;
|
| - view->RemoveAllChildViews(true);
|
| -
|
| - views::GridLayout* layout = new views::GridLayout(view);
|
| - view->SetLayoutManager(layout);
|
| -
|
| - int column_set_id = 0;
|
| - const DetailInputs& inputs = delegate_->RequestedFieldsForSection(section);
|
| - for (DetailInputs::const_iterator it = inputs.begin();
|
| - it != inputs.end(); ++it) {
|
| - const DetailInput& input = *it;
|
| -
|
| - ui::ComboboxModel* input_model =
|
| - delegate_->ComboboxModelForAutofillType(input.type);
|
| - std::unique_ptr<views::View> view_to_add;
|
| - if (input_model) {
|
| - views::Combobox* combobox = new views::Combobox(input_model);
|
| - combobox->set_listener(this);
|
| - comboboxes->insert(std::make_pair(input.type, combobox));
|
| - SelectComboboxValueOrSetToDefault(combobox, input.initial_value);
|
| - view_to_add.reset(combobox);
|
| - } else {
|
| - ExpandingTextfield* field = new ExpandingTextfield(input.initial_value,
|
| - input.placeholder_text,
|
| - input.IsMultiline(),
|
| - this);
|
| - textfields->insert(std::make_pair(input.type, field));
|
| - view_to_add.reset(field);
|
| - }
|
| -
|
| - if (input.length == DetailInput::NONE) {
|
| - other_owned_views_.push_back(view_to_add.release());
|
| - continue;
|
| - }
|
| -
|
| - if (input.length == DetailInput::LONG)
|
| - ++column_set_id;
|
| -
|
| - views::ColumnSet* column_set = layout->GetColumnSet(column_set_id);
|
| - if (!column_set) {
|
| - // Create a new column set and row.
|
| - column_set = layout->AddColumnSet(column_set_id);
|
| - if (it != inputs.begin())
|
| - layout->AddPaddingRow(0, kManualInputRowPadding);
|
| - layout->StartRow(0, column_set_id);
|
| - } else {
|
| - // Add a new column to existing row.
|
| - column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
|
| - // Must explicitly skip the padding column since we've already started
|
| - // adding views.
|
| - layout->SkipColumns(1);
|
| - }
|
| -
|
| - float expand = input.expand_weight;
|
| - column_set->AddColumn(views::GridLayout::FILL,
|
| - views::GridLayout::FILL,
|
| - expand ? expand : 1.0,
|
| - views::GridLayout::USE_PREF,
|
| - 0,
|
| - 0);
|
| -
|
| - // This is the same as AddView(view_to_add), except that 1 is used for the
|
| - // view's preferred width. Thus the width of the column completely depends
|
| - // on |expand|.
|
| - layout->AddView(view_to_add.release(), 1, 1,
|
| - views::GridLayout::FILL, views::GridLayout::FILL,
|
| - 1, 0);
|
| -
|
| - if (input.length == DetailInput::LONG ||
|
| - input.length == DetailInput::SHORT_EOL) {
|
| - ++column_set_id;
|
| - }
|
| - }
|
| -
|
| - SetIconsForSection(section);
|
| -}
|
| -
|
| -void AutofillDialogViews::UpdateSectionImpl(
|
| - DialogSection section,
|
| - bool clobber_inputs) {
|
| - DetailsGroup* group = GroupForSection(section);
|
| -
|
| - if (clobber_inputs) {
|
| - ServerFieldType type = UNKNOWN_TYPE;
|
| - views::View* focused = GetFocusManager()->GetFocusedView();
|
| - if (focused && group->container->Contains(focused)) {
|
| - // Remember which view was focused before the inputs are clobbered.
|
| - if (focused->GetClassName() == ExpandingTextfield::kViewClassName)
|
| - type = TypeForTextfield(focused);
|
| - else if (focused->GetClassName() == views::Combobox::kViewClassName)
|
| - type = TypeForCombobox(static_cast<views::Combobox*>(focused));
|
| - }
|
| -
|
| - InitInputsView(section);
|
| -
|
| - if (type != UNKNOWN_TYPE) {
|
| - // Restore the focus to the input with the previous type (e.g. country).
|
| - views::View* to_focus = TextfieldForType(type);
|
| - if (!to_focus) to_focus = ComboboxForType(type);
|
| - if (to_focus)
|
| - to_focus->RequestFocus();
|
| - }
|
| - } else {
|
| - const DetailInputs& updated_inputs =
|
| - delegate_->RequestedFieldsForSection(section);
|
| -
|
| - for (DetailInputs::const_iterator iter = updated_inputs.begin();
|
| - iter != updated_inputs.end(); ++iter) {
|
| - const DetailInput& input = *iter;
|
| -
|
| - TextfieldMap::iterator text_mapping = group->textfields.find(input.type);
|
| - if (text_mapping != group->textfields.end()) {
|
| - ExpandingTextfield* textfield = text_mapping->second;
|
| - if (textfield->GetText().empty())
|
| - textfield->SetText(input.initial_value);
|
| - }
|
| -
|
| - ComboboxMap::iterator combo_mapping = group->comboboxes.find(input.type);
|
| - if (combo_mapping != group->comboboxes.end()) {
|
| - views::Combobox* combobox = combo_mapping->second;
|
| - if (combobox->selected_index() == combobox->model()->GetDefaultIndex())
|
| - SelectComboboxValueOrSetToDefault(combobox, input.initial_value);
|
| - }
|
| - }
|
| -
|
| - SetIconsForSection(section);
|
| - }
|
| -
|
| - UpdateDetailsGroupState(*group);
|
| -}
|
| -
|
| -void AutofillDialogViews::UpdateDetailsGroupState(const DetailsGroup& group) {
|
| - const SuggestionState& suggestion_state =
|
| - delegate_->SuggestionStateForSection(group.section);
|
| - group.suggested_info->SetState(suggestion_state);
|
| - group.manual_input->SetVisible(!suggestion_state.visible);
|
| -
|
| - UpdateButtonStripExtraView();
|
| -
|
| - const bool has_menu = !!delegate_->MenuModelForSection(group.section);
|
| -
|
| - if (group.suggested_button)
|
| - group.suggested_button->SetVisible(has_menu);
|
| -
|
| - if (group.container) {
|
| - group.container->SetForwardMouseEvents(
|
| - has_menu && suggestion_state.visible);
|
| - group.container->SetVisible(delegate_->SectionIsActive(group.section));
|
| - if (group.container->visible())
|
| - ValidateGroup(group, VALIDATE_EDIT);
|
| - }
|
| -
|
| - ContentsPreferredSizeChanged();
|
| -}
|
| -
|
| -void AutofillDialogViews::FocusInitialView() {
|
| - views::View* to_focus = GetInitiallyFocusedView();
|
| - if (to_focus && !to_focus->HasFocus())
|
| - to_focus->RequestFocus();
|
| -}
|
| -
|
| -template<class T>
|
| -void AutofillDialogViews::SetValidityForInput(
|
| - T* input,
|
| - const base::string16& message) {
|
| - bool invalid = !message.empty();
|
| - input->SetInvalid(invalid);
|
| -
|
| - if (invalid) {
|
| - validity_map_[input] = message;
|
| - } else {
|
| - validity_map_.erase(input);
|
| -
|
| - if (error_bubble_ &&
|
| - error_bubble_->anchor()->GetAncestorWithClassName(
|
| - input->GetClassName()) == input) {
|
| - validity_map_.erase(input);
|
| - HideErrorBubble();
|
| - }
|
| - }
|
| -}
|
| -
|
| -void AutofillDialogViews::ShowErrorBubbleForViewIfNecessary(views::View* view) {
|
| - if (!view->GetWidget())
|
| - return;
|
| -
|
| - if (!delegate_->ShouldShowErrorBubble()) {
|
| - DCHECK(!error_bubble_);
|
| - return;
|
| - }
|
| -
|
| - if (view->GetClassName() == DecoratedTextfield::kViewClassName &&
|
| - !static_cast<DecoratedTextfield*>(view)->invalid()) {
|
| - return;
|
| - }
|
| -
|
| - views::View* input_view = GetAncestralInputView(view);
|
| - std::map<views::View*, base::string16>::iterator error_message =
|
| - validity_map_.find(input_view);
|
| - if (error_message != validity_map_.end()) {
|
| - input_view->ScrollRectToVisible(input_view->GetLocalBounds());
|
| -
|
| - if (!error_bubble_ || error_bubble_->anchor() != view) {
|
| - HideErrorBubble();
|
| - error_bubble_ = new InfoBubble(view, error_message->second);
|
| - error_bubble_->set_align_to_anchor_edge(true);
|
| - error_bubble_->set_preferred_width(
|
| - (kSectionContainerWidth - views::kRelatedControlVerticalSpacing) / 2);
|
| - bool show_above = view->GetClassName() == views::Combobox::kViewClassName;
|
| - error_bubble_->set_show_above_anchor(show_above);
|
| - error_bubble_->Show();
|
| - observer_.Add(error_bubble_->GetWidget());
|
| - }
|
| - }
|
| -}
|
| -
|
| -void AutofillDialogViews::HideErrorBubble() {
|
| - if (error_bubble_)
|
| - error_bubble_->Hide();
|
| -}
|
| -
|
| -void AutofillDialogViews::MarkInputsInvalid(
|
| - DialogSection section,
|
| - const ValidityMessages& messages,
|
| - bool overwrite_unsure) {
|
| - DetailsGroup* group = GroupForSection(section);
|
| - DCHECK(group->container->visible());
|
| -
|
| - if (group->manual_input->visible()) {
|
| - for (TextfieldMap::const_iterator iter = group->textfields.begin();
|
| - iter != group->textfields.end(); ++iter) {
|
| - const ValidityMessage& message =
|
| - messages.GetMessageOrDefault(iter->first);
|
| - if (overwrite_unsure || message.sure)
|
| - SetValidityForInput(iter->second, message.text);
|
| - }
|
| - for (ComboboxMap::const_iterator iter = group->comboboxes.begin();
|
| - iter != group->comboboxes.end(); ++iter) {
|
| - const ValidityMessage& message =
|
| - messages.GetMessageOrDefault(iter->first);
|
| - if (overwrite_unsure || message.sure)
|
| - SetValidityForInput(iter->second, message.text);
|
| - }
|
| - } else {
|
| - EraseInvalidViewsInGroup(group);
|
| -
|
| - if (section == GetCreditCardSection()) {
|
| - // Special case CVC as it's not part of |group->manual_input|.
|
| - const ValidityMessage& message =
|
| - messages.GetMessageOrDefault(CREDIT_CARD_VERIFICATION_CODE);
|
| - if (overwrite_unsure || message.sure) {
|
| - SetValidityForInput(group->suggested_info->textfield(), message.text);
|
| - }
|
| - }
|
| - }
|
| -}
|
| -
|
| -bool AutofillDialogViews::ValidateGroup(const DetailsGroup& group,
|
| - ValidationType validation_type) {
|
| - DCHECK(group.container->visible());
|
| -
|
| - FieldValueMap detail_outputs;
|
| -
|
| - if (group.manual_input->visible()) {
|
| - for (TextfieldMap::const_iterator iter = group.textfields.begin();
|
| - iter != group.textfields.end(); ++iter) {
|
| - if (!iter->second->editable())
|
| - continue;
|
| -
|
| - detail_outputs[iter->first] = iter->second->GetText();
|
| - }
|
| - for (ComboboxMap::const_iterator iter = group.comboboxes.begin();
|
| - iter != group.comboboxes.end(); ++iter) {
|
| - if (!iter->second->enabled())
|
| - continue;
|
| -
|
| - views::Combobox* combobox = iter->second;
|
| - base::string16 item =
|
| - combobox->model()->GetItemAt(combobox->selected_index());
|
| - detail_outputs[iter->first] = item;
|
| - }
|
| - } else if (group.section == GetCreditCardSection()) {
|
| - ExpandingTextfield* cvc = group.suggested_info->textfield();
|
| - if (cvc->visible())
|
| - detail_outputs[CREDIT_CARD_VERIFICATION_CODE] = cvc->GetText();
|
| - }
|
| -
|
| - ValidityMessages validity = delegate_->InputsAreValid(group.section,
|
| - detail_outputs);
|
| - MarkInputsInvalid(group.section, validity, validation_type == VALIDATE_FINAL);
|
| -
|
| - // If there are any validation errors, sure or unsure, the group is invalid.
|
| - return !validity.HasErrors();
|
| -}
|
| -
|
| -bool AutofillDialogViews::ValidateForm() {
|
| - bool all_valid = true;
|
| - validity_map_.clear();
|
| -
|
| - for (DetailGroupMap::iterator iter = detail_groups_.begin();
|
| - iter != detail_groups_.end(); ++iter) {
|
| - const DetailsGroup& group = iter->second;
|
| - if (!group.container->visible())
|
| - continue;
|
| -
|
| - if (!ValidateGroup(group, VALIDATE_FINAL))
|
| - all_valid = false;
|
| - }
|
| -
|
| - return all_valid;
|
| -}
|
| -
|
| -void AutofillDialogViews::InputEditedOrActivated(ServerFieldType type,
|
| - const gfx::Rect& bounds,
|
| - bool was_edit) {
|
| - DCHECK_NE(UNKNOWN_TYPE, type);
|
| -
|
| - ExpandingTextfield* textfield = TextfieldForType(type);
|
| - views::Combobox* combobox = ComboboxForType(type);
|
| -
|
| - // Both views may be NULL if the event comes from an inactive section, which
|
| - // may occur when using an IME.
|
| - if (!combobox && !textfield)
|
| - return;
|
| -
|
| - DCHECK_NE(!!combobox, !!textfield);
|
| - DetailsGroup* group = textfield ? GroupForView(textfield) :
|
| - GroupForView(combobox);
|
| - base::string16 text = textfield ?
|
| - textfield->GetText() :
|
| - combobox->model()->GetItemAt(combobox->selected_index());
|
| - DCHECK(group);
|
| -
|
| - delegate_->UserEditedOrActivatedInput(group->section,
|
| - type,
|
| - GetWidget()->GetNativeView(),
|
| - bounds,
|
| - text,
|
| - was_edit);
|
| -
|
| - // If the field is a textfield and is invalid, check if the text is now valid.
|
| - // Many fields (i.e. CC#) are invalid for most of the duration of editing,
|
| - // so flagging them as invalid prematurely is not helpful. However,
|
| - // correcting a minor mistake (i.e. a wrong CC digit) should immediately
|
| - // result in validation - positive user feedback.
|
| - if (textfield && textfield->invalid() && was_edit) {
|
| - SetValidityForInput(
|
| - textfield,
|
| - delegate_->InputValidityMessage(
|
| - group->section, type, textfield->GetText()));
|
| -
|
| - // If the field transitioned from invalid to valid, re-validate the group,
|
| - // since inter-field checks become meaningful with valid fields.
|
| - if (!textfield->invalid())
|
| - ValidateGroup(*group, VALIDATE_EDIT);
|
| - }
|
| -
|
| - if (delegate_->FieldControlsIcons(type))
|
| - SetIconsForSection(group->section);
|
| -}
|
| -
|
| -void AutofillDialogViews::UpdateButtonStripExtraView() {
|
| - save_in_chrome_checkbox_container_->SetVisible(
|
| - delegate_->ShouldOfferToSaveInChrome());
|
| -}
|
| -
|
| -void AutofillDialogViews::ContentsPreferredSizeChanged() {
|
| - if (updates_scope_ != 0) {
|
| - needs_update_ = true;
|
| - return;
|
| - }
|
| -
|
| - preferred_size_ = gfx::Size();
|
| -
|
| - if (GetWidget() && delegate_ && delegate_->GetWebContents()) {
|
| - constrained_window::UpdateWebContentsModalDialogPosition(
|
| - GetWidget(),
|
| - web_modal::WebContentsModalDialogManager::FromWebContents(
|
| - delegate_->GetWebContents())->delegate()->
|
| - GetWebContentsModalDialogHost());
|
| - SetBoundsRect(bounds());
|
| - }
|
| -}
|
| -
|
| -AutofillDialogViews::DetailsGroup* AutofillDialogViews::GroupForSection(
|
| - DialogSection section) {
|
| - return &detail_groups_.find(section)->second;
|
| -}
|
| -
|
| -AutofillDialogViews::DetailsGroup* AutofillDialogViews::GroupForView(
|
| - views::View* view) {
|
| - DCHECK(view);
|
| -
|
| - views::View* input_view = GetAncestralInputView(view);
|
| - if (!input_view)
|
| - return NULL;
|
| -
|
| - for (DetailGroupMap::iterator iter = detail_groups_.begin();
|
| - iter != detail_groups_.end(); ++iter) {
|
| - DetailsGroup* group = &iter->second;
|
| - if (input_view->parent() == group->manual_input)
|
| - return group;
|
| -
|
| - // Textfields need to check a second case, since they can be suggested
|
| - // inputs instead of directly editable inputs. Those are accessed via
|
| - // |suggested_info|.
|
| - if (input_view == group->suggested_info->textfield()) {
|
| - return group;
|
| - }
|
| - }
|
| -
|
| - return NULL;
|
| -}
|
| -
|
| -void AutofillDialogViews::EraseInvalidViewsInGroup(const DetailsGroup* group) {
|
| - std::map<views::View*, base::string16>::iterator it = validity_map_.begin();
|
| - while (it != validity_map_.end()) {
|
| - if (GroupForView(it->first) == group)
|
| - validity_map_.erase(it++);
|
| - else
|
| - ++it;
|
| - }
|
| -}
|
| -
|
| -ExpandingTextfield* AutofillDialogViews::TextfieldForType(
|
| - ServerFieldType type) {
|
| - if (type == CREDIT_CARD_VERIFICATION_CODE) {
|
| - DetailsGroup* group = GroupForSection(GetCreditCardSection());
|
| - if (!group->manual_input->visible())
|
| - return group->suggested_info->textfield();
|
| - }
|
| -
|
| - for (DetailGroupMap::iterator iter = detail_groups_.begin();
|
| - iter != detail_groups_.end(); ++iter) {
|
| - const DetailsGroup& group = iter->second;
|
| - if (!delegate_->SectionIsActive(group.section))
|
| - continue;
|
| -
|
| - TextfieldMap::const_iterator text_mapping = group.textfields.find(type);
|
| - if (text_mapping != group.textfields.end())
|
| - return text_mapping->second;
|
| - }
|
| -
|
| - return NULL;
|
| -}
|
| -
|
| -ServerFieldType AutofillDialogViews::TypeForTextfield(
|
| - const views::View* textfield) {
|
| - const views::View* expanding =
|
| - textfield->GetAncestorWithClassName(ExpandingTextfield::kViewClassName);
|
| -
|
| - DetailsGroup* cc_group = GroupForSection(GetCreditCardSection());
|
| - if (expanding == cc_group->suggested_info->textfield())
|
| - return CREDIT_CARD_VERIFICATION_CODE;
|
| -
|
| - for (DetailGroupMap::const_iterator it = detail_groups_.begin();
|
| - it != detail_groups_.end(); ++it) {
|
| - if (!delegate_->SectionIsActive(it->second.section))
|
| - continue;
|
| -
|
| - for (TextfieldMap::const_iterator text_it = it->second.textfields.begin();
|
| - text_it != it->second.textfields.end(); ++text_it) {
|
| - if (expanding == text_it->second)
|
| - return text_it->first;
|
| - }
|
| - }
|
| -
|
| - return UNKNOWN_TYPE;
|
| -}
|
| -
|
| -views::Combobox* AutofillDialogViews::ComboboxForType(
|
| - ServerFieldType type) {
|
| - for (DetailGroupMap::iterator iter = detail_groups_.begin();
|
| - iter != detail_groups_.end(); ++iter) {
|
| - const DetailsGroup& group = iter->second;
|
| - if (!delegate_->SectionIsActive(group.section))
|
| - continue;
|
| -
|
| - ComboboxMap::const_iterator combo_mapping = group.comboboxes.find(type);
|
| - if (combo_mapping != group.comboboxes.end())
|
| - return combo_mapping->second;
|
| - }
|
| -
|
| - return NULL;
|
| -}
|
| -
|
| -ServerFieldType AutofillDialogViews::TypeForCombobox(
|
| - const views::Combobox* combobox) const {
|
| - for (DetailGroupMap::const_iterator it = detail_groups_.begin();
|
| - it != detail_groups_.end(); ++it) {
|
| - const DetailsGroup& group = it->second;
|
| - if (!delegate_->SectionIsActive(group.section))
|
| - continue;
|
| -
|
| - for (ComboboxMap::const_iterator combo_it = group.comboboxes.begin();
|
| - combo_it != group.comboboxes.end(); ++combo_it) {
|
| - if (combo_it->second == combobox)
|
| - return combo_it->first;
|
| - }
|
| - }
|
| -
|
| - return UNKNOWN_TYPE;
|
| -}
|
| -
|
| -void AutofillDialogViews::DetailsContainerBoundsChanged() {
|
| - if (error_bubble_)
|
| - error_bubble_->UpdatePosition();
|
| -}
|
| -
|
| -void AutofillDialogViews::SetIconsForSection(DialogSection section) {
|
| - FieldValueMap user_input;
|
| - GetUserInput(section, &user_input);
|
| - FieldIconMap field_icons = delegate_->IconsForFields(user_input);
|
| - TextfieldMap* textfields = &GroupForSection(section)->textfields;
|
| - for (TextfieldMap::const_iterator textfield_it = textfields->begin();
|
| - textfield_it != textfields->end();
|
| - ++textfield_it) {
|
| - ServerFieldType field_type = textfield_it->first;
|
| - FieldIconMap::const_iterator field_icon_it = field_icons.find(field_type);
|
| - ExpandingTextfield* textfield = textfield_it->second;
|
| - if (field_icon_it != field_icons.end())
|
| - textfield->SetIcon(field_icon_it->second);
|
| - else
|
| - textfield->SetTooltipIcon(delegate_->TooltipForField(field_type));
|
| - }
|
| -}
|
| -
|
| -void AutofillDialogViews::NonClientMousePressed() {
|
| - delegate_->FocusMoved();
|
| -}
|
| -
|
| -views::View* AutofillDialogViews::GetNotificationAreaForTesting() {
|
| - return notification_area_;
|
| -}
|
| -
|
| -views::View* AutofillDialogViews::GetScrollableAreaForTesting() {
|
| - return scrollable_area_;
|
| -}
|
| -
|
| -AutofillDialogViews::DetailsGroup::DetailsGroup(DialogSection section)
|
| - : section(section),
|
| - container(NULL),
|
| - manual_input(NULL),
|
| - suggested_info(NULL),
|
| - suggested_button(NULL) {}
|
| -
|
| -AutofillDialogViews::DetailsGroup::DetailsGroup(const DetailsGroup& other) =
|
| - default;
|
| -
|
| -AutofillDialogViews::DetailsGroup::~DetailsGroup() {}
|
| -
|
| -} // namespace autofill
|
|
|