| 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
|
| index 0bd2fd0afdd05af8b95973252f17be913f97802d..6b895fd1b9402be875ff7a16d087becbf7e8e097 100644
|
| --- a/chrome/browser/ui/views/autofill/autofill_dialog_views.cc
|
| +++ b/chrome/browser/ui/views/autofill/autofill_dialog_views.cc
|
| @@ -23,7 +23,6 @@
|
| #include "grit/theme_resources.h"
|
| #include "grit/ui_resources.h"
|
| #include "third_party/skia/include/core/SkColor.h"
|
| -#include "ui/base/animation/animation_delegate.h"
|
| #include "ui/base/animation/multi_animation.h"
|
| #include "ui/base/l10n/l10n_util.h"
|
| #include "ui/base/models/combobox_model.h"
|
| @@ -68,29 +67,29 @@ const int kMinimumContentsHeight = 100;
|
| const int kAroundTextPadding = 4;
|
|
|
| // Padding around icons inside DecoratedTextfields.
|
| -const size_t kTextfieldIconPadding = 3;
|
| +const int kTextfieldIconPadding = 3;
|
|
|
| // Size of the triangular mark that indicates an invalid textfield (in pixels).
|
| -const size_t kDogEarSize = 10;
|
| +const int kDogEarSize = 10;
|
|
|
| // The space between the edges of a notification bar and the text within (in
|
| // pixels).
|
| -const size_t kNotificationPadding = 14;
|
| +const int kNotificationPadding = 14;
|
|
|
| // Vertical padding above and below each detail section (in pixels).
|
| -const size_t kDetailSectionInset = 10;
|
| +const int kDetailSectionInset = 10;
|
|
|
| -const size_t kAutocheckoutStepsAreaPadding = 28;
|
| -const size_t kAutocheckoutStepInset = 20;
|
| +const int kAutocheckoutStepsAreaPadding = 28;
|
| +const int kAutocheckoutStepInset = 20;
|
|
|
| -const size_t kAutocheckoutProgressBarWidth = 375;
|
| -const size_t kAutocheckoutProgressBarHeight = 15;
|
| +const int kAutocheckoutProgressBarWidth = 375;
|
| +const int kAutocheckoutProgressBarHeight = 15;
|
|
|
| -const size_t kArrowHeight = 7;
|
| -const size_t kArrowWidth = 2 * kArrowHeight;
|
| +const int kArrowHeight = 7;
|
| +const int kArrowWidth = 2 * kArrowHeight;
|
|
|
| // The padding around the edges of the legal documents text, in pixels.
|
| -const size_t kLegalDocPadding = 20;
|
| +const int kLegalDocPadding = 20;
|
|
|
| // Slight shading for mouse hover and legal document background.
|
| SkColor kShadingColor = SkColorSetARGB(7, 0, 0, 0);
|
| @@ -99,13 +98,23 @@ SkColor kShadingColor = SkColorSetARGB(7, 0, 0, 0);
|
| SkColor kSubtleBorderColor = SkColorSetARGB(10, 0, 0, 0);
|
|
|
| // The top padding, in pixels, for the suggestions menu dropdown arrows.
|
| -const size_t kMenuButtonTopOffset = 5;
|
| +const int kMenuButtonTopOffset = 5;
|
|
|
| // The side padding, in pixels, for the suggestions menu dropdown arrows.
|
| -const size_t kMenuButtonHorizontalPadding = 20;
|
| +const int kMenuButtonHorizontalPadding = 20;
|
| +
|
| +// The padding around text in the overlay view.
|
| +const int kOverlayTextPadding = 20;
|
| +
|
| +// Spacing between lines of text in the overlay view.
|
| +const int kOverlayTextInterlineSpacing = 10;
|
|
|
| const char kDecoratedTextfieldClassName[] = "autofill/DecoratedTextfield";
|
| const char kNotificationAreaClassName[] = "autofill/NotificationArea";
|
| +const char kOverlayViewClassName[] = "autofill/OverlayView";
|
| +
|
| +typedef ui::MultiAnimation::Part Part;
|
| +typedef ui::MultiAnimation::Parts Parts;
|
|
|
| views::Border* CreateLabelAlignmentBorder() {
|
| // TODO(estade): this should be made to match the native textfield top
|
| @@ -125,99 +134,17 @@ views::Label* CreateDetailsSectionLabel(const string16& text) {
|
| // Draws an arrow at the top of |canvas| pointing to |tip_x|.
|
| void DrawArrow(gfx::Canvas* canvas, int tip_x, const SkColor& color) {
|
| const int arrow_half_width = kArrowWidth / 2.0f;
|
| - const int arrow_middle = tip_x - arrow_half_width;
|
|
|
| SkPath arrow;
|
| - arrow.moveTo(arrow_middle - arrow_half_width, kArrowHeight);
|
| - arrow.lineTo(arrow_middle + arrow_half_width, kArrowHeight);
|
| - arrow.lineTo(arrow_middle, 0);
|
| + arrow.moveTo(tip_x, 0);
|
| + arrow.rLineTo(arrow_half_width, kArrowHeight);
|
| + arrow.rLineTo(-kArrowWidth, 0);
|
| arrow.close();
|
| - canvas->ClipPath(arrow);
|
| - canvas->DrawColor(color);
|
| + SkPaint paint;
|
| + paint.setColor(color);
|
| + canvas->DrawPath(arrow, paint);
|
| }
|
|
|
| -typedef ui::MultiAnimation::Part Part;
|
| -typedef ui::MultiAnimation::Parts Parts;
|
| -
|
| -class OverlayView : public views::View,
|
| - public ui::AnimationDelegate {
|
| - public:
|
| - OverlayView() {
|
| - SetLayoutManager(new views::FillLayout());
|
| -
|
| - set_background(views::Background::CreateSolidBackground(GetNativeTheme()->
|
| - GetSystemColor(ui::NativeTheme::kColorId_DialogBackground)));
|
| -
|
| - Parts parts;
|
| - // For this part of the animation, simply show the splash image.
|
| - parts.push_back(Part(kSplashDisplayDurationMs, ui::Tween::ZERO));
|
| - // For this part of the animation, fade out the splash image.
|
| - parts.push_back(Part(kSplashFadeOutDurationMs, ui::Tween::EASE_IN));
|
| - // For this part of the animation, fade out |this| (fade in the dialog).
|
| - parts.push_back(Part(kSplashFadeInDialogDurationMs, ui::Tween::EASE_OUT));
|
| - fade_out_.reset(
|
| - new ui::MultiAnimation(parts,
|
| - ui::MultiAnimation::GetDefaultTimerInterval()));
|
| - fade_out_->set_delegate(this);
|
| - fade_out_->set_continuous(false);
|
| - fade_out_->Start();
|
| - }
|
| -
|
| - virtual ~OverlayView() {}
|
| -
|
| - // ui::AnimationDelegate implementation:
|
| - virtual void AnimationProgressed(const ui::Animation* animation) OVERRIDE {
|
| - DCHECK_EQ(animation, fade_out_.get());
|
| - if (fade_out_->current_part_index() != 0)
|
| - SchedulePaint();
|
| - }
|
| -
|
| - virtual void AnimationEnded(const ui::Animation* animation) OVERRIDE {
|
| - DCHECK_EQ(animation, fade_out_.get());
|
| - SetVisible(false);
|
| - }
|
| -
|
| - // views::View implementation:
|
| - virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE {
|
| - // BubbleFrameView doesn't mask the window, it just draws the border via
|
| - // image assets. Match that rounding here.
|
| - static const SkScalar kCornerRadius = SkIntToScalar(2);
|
| - gfx::Rect rect =
|
| - GetWidget()->non_client_view()->frame_view()->GetLocalBounds();
|
| - rect.Inset(12, 12, 12, 12);
|
| - gfx::Path window_mask;
|
| - window_mask.addRoundRect(gfx::RectToSkRect(rect),
|
| - kCornerRadius, kCornerRadius);
|
| - canvas->ClipPath(window_mask);
|
| -
|
| - if (fade_out_->current_part_index() == 2) {
|
| - canvas->SaveLayerAlpha((1 - fade_out_->GetCurrentValue()) * 255);
|
| - views::View::OnPaint(canvas);
|
| - canvas->Restore();
|
| - } else {
|
| - views::View::OnPaint(canvas);
|
| - }
|
| - }
|
| -
|
| - virtual void PaintChildren(gfx::Canvas* canvas) OVERRIDE {
|
| - if (fade_out_->current_part_index() == 0) {
|
| - views::View::PaintChildren(canvas);
|
| - } else if (fade_out_->current_part_index() == 1) {
|
| - canvas->SaveLayerAlpha((1 - fade_out_->GetCurrentValue()) * 255);
|
| - views::View::PaintChildren(canvas);
|
| - canvas->Restore();
|
| - }
|
| - }
|
| -
|
| - private:
|
| - // This MultiAnimation is used to first fade out the contents of the overlay,
|
| - // then fade out the background of the overlay (revealing the dialog behind
|
| - // the overlay). This avoids cross-fade.
|
| - scoped_ptr<ui::MultiAnimation> fade_out_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(OverlayView);
|
| -};
|
| -
|
| // 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
|
| @@ -609,6 +536,184 @@ void AutofillDialogViews::AccountChooser::LinkClicked(views::Link* source,
|
| controller_->SignInLinkClicked();
|
| }
|
|
|
| +// AutofillDialogViews::OverlayView --------------------------------------------
|
| +
|
| +AutofillDialogViews::OverlayView::OverlayView(views::ButtonListener* listener)
|
| + : image_view_(new views::ImageView()),
|
| + message_stack_(new views::View()),
|
| + button_(new views::LabelButton(listener, string16())) {
|
| + set_border(views::Border::CreateEmptyBorder(12, 12, 12, 12));
|
| + set_background(views::Background::CreateSolidBackground(GetNativeTheme()->
|
| + GetSystemColor(ui::NativeTheme::kColorId_DialogBackground)));
|
| +
|
| + AddChildView(image_view_);
|
| +
|
| + AddChildView(message_stack_);
|
| + message_stack_->SetLayoutManager(
|
| + new views::BoxLayout(views::BoxLayout::kVertical, 0, 0,
|
| + kOverlayTextInterlineSpacing));
|
| + message_stack_->set_border(views::Border::CreateEmptyBorder(
|
| + kOverlayTextPadding, kOverlayTextPadding, 0, kOverlayTextPadding));
|
| +
|
| + AddChildView(button_);
|
| + button_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
|
| + button_->set_focusable(true);
|
| +}
|
| +
|
| +AutofillDialogViews::OverlayView::~OverlayView() {}
|
| +
|
| +void AutofillDialogViews::OverlayView::SetState(
|
| + const DialogOverlayState& state,
|
| + views::ButtonListener* listener) {
|
| + // Don't update anything if we're still fading out the old state.
|
| + if (fade_out_)
|
| + return;
|
| +
|
| + if (state.image.IsEmpty()) {
|
| + SetVisible(false);
|
| + return;
|
| + }
|
| +
|
| + image_view_->SetImage(state.image.ToImageSkia());
|
| +
|
| + message_stack_->RemoveAllChildViews(true);
|
| + for (size_t i = 0; i < state.strings.size(); ++i) {
|
| + views::Label* label = new views::Label();
|
| + label->SetMultiLine(true);
|
| + label->SetText(state.strings[i].text);
|
| + label->SetFont(state.strings[i].font);
|
| + label->SetHorizontalAlignment(state.strings[i].alignment);
|
| + message_stack_->AddChildView(label);
|
| + }
|
| + message_stack_->SetVisible(message_stack_->child_count() > 0);
|
| +
|
| + button_->SetVisible(!state.button_text.empty());
|
| + if (!state.button_text.empty())
|
| + button_->SetText(state.button_text);
|
| +
|
| + SetVisible(true);
|
| + if (parent())
|
| + parent()->Layout();
|
| +}
|
| +
|
| +void AutofillDialogViews::OverlayView::BeginFadeOut() {
|
| + Parts parts;
|
| + // For this part of the animation, simply show the splash image.
|
| + parts.push_back(Part(kSplashDisplayDurationMs, ui::Tween::ZERO));
|
| + // For this part of the animation, fade out the splash image.
|
| + parts.push_back(Part(kSplashFadeOutDurationMs, ui::Tween::EASE_IN));
|
| + // For this part of the animation, fade out |this| (fade in the dialog).
|
| + parts.push_back(Part(kSplashFadeInDialogDurationMs, ui::Tween::EASE_OUT));
|
| + fade_out_.reset(
|
| + new ui::MultiAnimation(parts,
|
| + ui::MultiAnimation::GetDefaultTimerInterval()));
|
| + fade_out_->set_delegate(this);
|
| + fade_out_->set_continuous(false);
|
| + fade_out_->Start();
|
| +}
|
| +
|
| +void AutofillDialogViews::OverlayView::AnimationProgressed(
|
| + const ui::Animation* animation) {
|
| + DCHECK_EQ(animation, fade_out_.get());
|
| + if (fade_out_->current_part_index() != 0)
|
| + SchedulePaint();
|
| +}
|
| +
|
| +void AutofillDialogViews::OverlayView::AnimationEnded(
|
| + const ui::Animation* animation) {
|
| + DCHECK_EQ(animation, fade_out_.get());
|
| + SetVisible(false);
|
| + fade_out_.reset();
|
| +}
|
| +
|
| +void AutofillDialogViews::OverlayView::Layout() {
|
| + gfx::Rect bounds = GetContentsBounds();
|
| + if (!message_stack_->visible()) {
|
| + image_view_->SetBoundsRect(bounds);
|
| + return;
|
| + }
|
| +
|
| + int y = bounds.bottom() - views::kButtonVEdgeMarginNew;
|
| + if (button_->visible()) {
|
| + button_->SizeToPreferredSize();
|
| + y -= button_->height();
|
| + button_->SetPosition(gfx::Point(
|
| + bounds.width() - button_->width() -
|
| + views::kButtonHEdgeMarginNew,
|
| + y));
|
| + y -= views::kButtonVEdgeMarginNew;
|
| + }
|
| +
|
| + int message_height = message_stack_->GetHeightForWidth(bounds.width());
|
| + y -= message_height;
|
| + message_stack_->SetBounds(bounds.x(), y, bounds.width(), message_height);
|
| +
|
| + gfx::Size image_size = image_view_->GetPreferredSize();
|
| + const int kImageBottomMargin = 40;
|
| + y -= image_size.height() + kImageBottomMargin;
|
| + image_view_->SetBounds(bounds.x(), y, bounds.width(), image_size.height());
|
| +}
|
| +
|
| +const char* AutofillDialogViews::OverlayView::GetClassName() const {
|
| + return kOverlayViewClassName;
|
| +}
|
| +
|
| +void AutofillDialogViews::OverlayView::OnPaint(gfx::Canvas* canvas) {
|
| + // BubbleFrameView doesn't mask the window, it just draws the border via
|
| + // image assets. Match that rounding here.
|
| + static const SkScalar kCornerRadius = SkIntToScalar(2);
|
| + gfx::Rect rect = GetContentsBounds();
|
| + gfx::Path window_mask;
|
| + window_mask.addRoundRect(gfx::RectToSkRect(rect),
|
| + kCornerRadius, kCornerRadius);
|
| + canvas->ClipPath(window_mask);
|
| +
|
| + // Fade out background (i.e. fade in what's behind |this|).
|
| + if (fade_out_ && fade_out_->current_part_index() == 2)
|
| + canvas->SaveLayerAlpha((1 - fade_out_->GetCurrentValue()) * 255);
|
| +
|
| + OnPaintBackground(canvas);
|
| +
|
| + // Draw the arrow, border, and fill for the bottom area.
|
| + if (message_stack_->visible()) {
|
| + const int arrow_half_width = kArrowWidth / 2.0f;
|
| + SkPath arrow;
|
| + int y = message_stack_->y() - 1;
|
| + // Note that we purposely draw slightly outside of |rect| so that the
|
| + // stroke is hidden on the sides.
|
| + arrow.moveTo(rect.x() - 1, y);
|
| + arrow.rLineTo(rect.width() / 2 - arrow_half_width, 0);
|
| + arrow.rLineTo(arrow_half_width, -kArrowHeight);
|
| + arrow.rLineTo(arrow_half_width, kArrowHeight);
|
| + arrow.lineTo(rect.right() + 1, y);
|
| + arrow.lineTo(rect.right() + 1, rect.bottom() + 1);
|
| + arrow.lineTo(rect.x() - 1, rect.bottom() + 1);
|
| + arrow.close();
|
| +
|
| + SkPaint paint;
|
| + paint.setColor(kShadingColor);
|
| + paint.setStyle(SkPaint::kFill_Style);
|
| + canvas->DrawPath(arrow, paint);
|
| + paint.setColor(kSubtleBorderColor);
|
| + paint.setStyle(SkPaint::kStroke_Style);
|
| + canvas->DrawPath(arrow, paint);
|
| + }
|
| +
|
| + PaintChildren(canvas);
|
| +}
|
| +
|
| +void AutofillDialogViews::OverlayView::PaintChildren(gfx::Canvas* canvas) {
|
| + // Don't draw children.
|
| + if (fade_out_ && fade_out_->current_part_index() == 2)
|
| + return;
|
| +
|
| + // Fade out children.
|
| + if (fade_out_ && fade_out_->current_part_index() == 1)
|
| + canvas->SaveLayerAlpha((1 - fade_out_->GetCurrentValue()) * 255);
|
| +
|
| + views::View::PaintChildren(canvas);
|
| +}
|
| +
|
| // AutofillDialogViews::NotificationArea ---------------------------------------
|
|
|
| AutofillDialogViews::NotificationArea::NotificationArea(
|
| @@ -1018,6 +1123,14 @@ void AutofillDialogViews::Show() {
|
| views::Widget::GetTopLevelWidgetForNativeView(
|
| controller_->web_contents()->GetView()->GetNativeView());
|
| observer_.Add(browser_widget);
|
| +
|
| + gfx::Image splash_image = controller_->SplashPageImage();
|
| + if (!splash_image.IsEmpty()) {
|
| + DialogOverlayState state;
|
| + state.image = splash_image;
|
| + overlay_view_->SetState(state, NULL);
|
| + overlay_view_->BeginFadeOut();
|
| + }
|
| }
|
|
|
| void AutofillDialogViews::Hide() {
|
| @@ -1069,6 +1182,9 @@ void AutofillDialogViews::UpdateButtonStrip() {
|
| autocheckout_progress_bar_view_->SetVisible(
|
| controller_->ShouldShowProgressBar());
|
| GetDialogClientView()->UpdateDialogButtons();
|
| +
|
| + overlay_view_->SetState(controller_->GetDialogOverlay(), this);
|
| +
|
| ContentsPreferredSizeChanged();
|
| }
|
|
|
| @@ -1401,15 +1517,6 @@ views::View* AutofillDialogViews::CreateFootnoteView() {
|
| }
|
|
|
| views::View* AutofillDialogViews::CreateOverlayView() {
|
| - gfx::Image splash_image = controller_->SplashPageImage();
|
| - if (splash_image.IsEmpty())
|
| - return NULL;
|
| -
|
| - overlay_view_ = new OverlayView();
|
| - views::ImageView* image = new views::ImageView();
|
| - image->SetImage(splash_image.ToImageSkia());
|
| - overlay_view_->AddChildView(image);
|
| -
|
| return overlay_view_;
|
| }
|
|
|
| @@ -1439,6 +1546,11 @@ views::NonClientFrameView* AutofillDialogViews::CreateNonClientFrameView(
|
|
|
| void AutofillDialogViews::ButtonPressed(views::Button* sender,
|
| const ui::Event& event) {
|
| + if (sender->GetAncestorWithClassName(kOverlayViewClassName)) {
|
| + controller_->OverlayButtonPressed();
|
| + return;
|
| + }
|
| +
|
| // TODO(estade): Should the menu be shown on mouse down?
|
| DetailsGroup* group = NULL;
|
| for (DetailGroupMap::iterator iter = detail_groups_.begin();
|
| @@ -1581,6 +1693,9 @@ void AutofillDialogViews::InitChildViews() {
|
| sign_in_delegate_.reset(
|
| new AutofillDialogSignInDelegate(this,
|
| sign_in_webview_->GetWebContents()));
|
| +
|
| + overlay_view_ = new OverlayView(this);
|
| + overlay_view_->SetVisible(false);
|
| }
|
|
|
| views::View* AutofillDialogViews::CreateDetailsContainer() {
|
|
|