OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/ui/views/autofill/autofill_dialog_views.h" | 5 #include "chrome/browser/ui/views/autofill/autofill_dialog_views.h" |
6 | 6 |
7 #include <utility> | 7 #include <utility> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/location.h" | 10 #include "base/location.h" |
11 #include "base/strings/utf_string_conversions.h" | 11 #include "base/strings/utf_string_conversions.h" |
12 #include "chrome/browser/profiles/profile.h" | 12 #include "chrome/browser/profiles/profile.h" |
13 #include "chrome/browser/ui/autofill/autofill_dialog_sign_in_delegate.h" | 13 #include "chrome/browser/ui/autofill/autofill_dialog_sign_in_delegate.h" |
14 #include "chrome/browser/ui/autofill/autofill_dialog_view_delegate.h" | 14 #include "chrome/browser/ui/autofill/autofill_dialog_view_delegate.h" |
15 #include "chrome/browser/ui/autofill/loading_animation.h" | 15 #include "chrome/browser/ui/autofill/loading_animation.h" |
16 #include "chrome/browser/ui/views/autofill/decorated_textfield.h" | 16 #include "chrome/browser/ui/views/autofill/decorated_textfield.h" |
| 17 #include "chrome/browser/ui/views/autofill/info_bubble.h" |
17 #include "chrome/browser/ui/views/autofill/tooltip_icon.h" | 18 #include "chrome/browser/ui/views/autofill/tooltip_icon.h" |
18 #include "chrome/browser/ui/views/constrained_window_views.h" | 19 #include "chrome/browser/ui/views/constrained_window_views.h" |
19 #include "components/autofill/content/browser/wallet/wallet_service_url.h" | 20 #include "components/autofill/content/browser/wallet/wallet_service_url.h" |
20 #include "components/autofill/core/browser/autofill_type.h" | 21 #include "components/autofill/core/browser/autofill_type.h" |
21 #include "components/web_modal/web_contents_modal_dialog_host.h" | 22 #include "components/web_modal/web_contents_modal_dialog_host.h" |
22 #include "components/web_modal/web_contents_modal_dialog_manager.h" | 23 #include "components/web_modal/web_contents_modal_dialog_manager.h" |
23 #include "components/web_modal/web_contents_modal_dialog_manager_delegate.h" | 24 #include "components/web_modal/web_contents_modal_dialog_manager_delegate.h" |
24 #include "content/public/browser/native_web_keyboard_event.h" | 25 #include "content/public/browser/native_web_keyboard_event.h" |
25 #include "content/public/browser/navigation_controller.h" | 26 #include "content/public/browser/navigation_controller.h" |
26 #include "content/public/browser/web_contents.h" | 27 #include "content/public/browser/web_contents.h" |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
90 | 91 |
91 const int kArrowHeight = 7; | 92 const int kArrowHeight = 7; |
92 const int kArrowWidth = 2 * kArrowHeight; | 93 const int kArrowWidth = 2 * kArrowHeight; |
93 | 94 |
94 // The padding inside the edges of the dialog, in pixels. | 95 // The padding inside the edges of the dialog, in pixels. |
95 const int kDialogEdgePadding = 20; | 96 const int kDialogEdgePadding = 20; |
96 | 97 |
97 // The vertical padding between rows of manual inputs (in pixels). | 98 // The vertical padding between rows of manual inputs (in pixels). |
98 const int kManualInputRowPadding = 10; | 99 const int kManualInputRowPadding = 10; |
99 | 100 |
100 // The margin between the content of the error bubble and its border. | |
101 const int kErrorBubbleHorizontalMargin = 14; | |
102 const int kErrorBubbleVerticalMargin = 12; | |
103 | |
104 // The visible width of bubble borders (differs from the actual width) in px. | |
105 const int kBubbleBorderVisibleWidth = 1; | |
106 | |
107 // Slight shading for mouse hover and legal document background. | 101 // Slight shading for mouse hover and legal document background. |
108 SkColor kShadingColor = SkColorSetARGB(7, 0, 0, 0); | 102 SkColor kShadingColor = SkColorSetARGB(7, 0, 0, 0); |
109 | 103 |
110 // A border color for the legal document view. | 104 // A border color for the legal document view. |
111 SkColor kSubtleBorderColor = SkColorSetARGB(10, 0, 0, 0); | 105 SkColor kSubtleBorderColor = SkColorSetARGB(10, 0, 0, 0); |
112 | 106 |
113 // The top and bottom padding, in pixels, for the suggestions menu dropdown | 107 // The top and bottom padding, in pixels, for the suggestions menu dropdown |
114 // arrows. | 108 // arrows. |
115 const int kMenuButtonTopInset = 3; | 109 const int kMenuButtonTopInset = 3; |
116 const int kMenuButtonBottomInset = 6; | 110 const int kMenuButtonBottomInset = 6; |
(...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
453 // Contains the "Loading" label and the dots. | 447 // Contains the "Loading" label and the dots. |
454 views::View* container_; | 448 views::View* container_; |
455 | 449 |
456 LoadingAnimation animation_; | 450 LoadingAnimation animation_; |
457 | 451 |
458 DISALLOW_COPY_AND_ASSIGN(LoadingAnimationView); | 452 DISALLOW_COPY_AND_ASSIGN(LoadingAnimationView); |
459 }; | 453 }; |
460 | 454 |
461 } // namespace | 455 } // namespace |
462 | 456 |
463 // AutofillDialogViews::ErrorBubble -------------------------------------------- | |
464 | |
465 AutofillDialogViews::ErrorBubble::ErrorBubble(views::View* anchor, | |
466 views::View* anchor_container, | |
467 const base::string16& message) | |
468 : anchor_(anchor), | |
469 anchor_container_(anchor_container), | |
470 show_above_anchor_( | |
471 anchor->GetClassName() == views::Combobox::kViewClassName) { | |
472 DCHECK(anchor_container_->Contains(anchor)); | |
473 SetAnchorView(anchor_); | |
474 | |
475 // TODO(dbeam): currently we assume that combobox menus always show downward | |
476 // (which isn't true). If the invalid combobox is low enough on the screen, | |
477 // its menu will actually show upward and obscure the bubble. Figure out when | |
478 // this might happen and adjust |show_above_anchor_| accordingly. This is not | |
479 // that big of deal because it rarely happens in practice. | |
480 if (show_above_anchor_) { | |
481 set_arrow(ShouldArrowGoOnTheRight() ? views::BubbleBorder::BOTTOM_RIGHT : | |
482 views::BubbleBorder::BOTTOM_LEFT); | |
483 } else { | |
484 set_arrow(ShouldArrowGoOnTheRight() ? views::BubbleBorder::TOP_RIGHT : | |
485 views::BubbleBorder::TOP_LEFT); | |
486 } | |
487 | |
488 set_margins(gfx::Insets(kErrorBubbleVerticalMargin, | |
489 kErrorBubbleHorizontalMargin, | |
490 kErrorBubbleVerticalMargin, | |
491 kErrorBubbleHorizontalMargin)); | |
492 set_use_focusless(true); | |
493 | |
494 SetLayoutManager(new views::FillLayout); | |
495 views::Label* label = new views::Label(message); | |
496 label->SetHorizontalAlignment(gfx::ALIGN_LEFT); | |
497 label->SetMultiLine(true); | |
498 AddChildView(label); | |
499 | |
500 widget_ = views::BubbleDelegateView::CreateBubble(this); | |
501 UpdatePosition(); | |
502 } | |
503 | |
504 AutofillDialogViews::ErrorBubble::~ErrorBubble() { | |
505 DCHECK(!widget_); | |
506 } | |
507 | |
508 void AutofillDialogViews::ErrorBubble::Hide() { | |
509 views::Widget* widget = GetWidget(); | |
510 if (widget && !widget->IsClosed()) | |
511 widget->Close(); | |
512 } | |
513 | |
514 void AutofillDialogViews::ErrorBubble::UpdatePosition() { | |
515 if (!widget_) | |
516 return; | |
517 | |
518 if (!anchor_->GetVisibleBounds().IsEmpty()) { | |
519 SizeToContents(); | |
520 widget_->SetVisibilityChangedAnimationsEnabled(true); | |
521 widget_->ShowInactive(); | |
522 } else { | |
523 widget_->SetVisibilityChangedAnimationsEnabled(false); | |
524 widget_->Hide(); | |
525 } | |
526 } | |
527 | |
528 gfx::Size AutofillDialogViews::ErrorBubble::GetPreferredSize() { | |
529 int pref_width = GetPreferredBubbleWidth(); | |
530 pref_width -= GetBubbleFrameView()->GetInsets().width(); | |
531 pref_width -= 2 * kBubbleBorderVisibleWidth; | |
532 return gfx::Size(pref_width, GetHeightForWidth(pref_width)); | |
533 } | |
534 | |
535 gfx::Rect AutofillDialogViews::ErrorBubble::GetBubbleBounds() { | |
536 gfx::Rect bounds = views::BubbleDelegateView::GetBubbleBounds(); | |
537 gfx::Rect anchor_bounds = anchor_->GetBoundsInScreen(); | |
538 | |
539 if (show_above_anchor_) | |
540 bounds.set_y(anchor_bounds.y() - GetBubbleFrameView()->height()); | |
541 | |
542 anchor_bounds.Inset(-GetBubbleFrameView()->bubble_border()->GetInsets()); | |
543 bounds.set_x(ShouldArrowGoOnTheRight() ? | |
544 anchor_bounds.right() - bounds.width() - kBubbleBorderVisibleWidth : | |
545 anchor_bounds.x() + kBubbleBorderVisibleWidth); | |
546 return bounds; | |
547 } | |
548 | |
549 void AutofillDialogViews::ErrorBubble::OnWidgetClosing(views::Widget* widget) { | |
550 if (widget == widget_) | |
551 widget_ = NULL; | |
552 } | |
553 | |
554 bool AutofillDialogViews::ErrorBubble::ShouldFlipArrowForRtl() const { | |
555 return false; | |
556 } | |
557 | |
558 int AutofillDialogViews::ErrorBubble::GetContainerWidth() { | |
559 return anchor_container_->width() - anchor_container_->GetInsets().width(); | |
560 } | |
561 | |
562 int AutofillDialogViews::ErrorBubble::GetPreferredBubbleWidth() { | |
563 return (GetContainerWidth() - views::kRelatedControlHorizontalSpacing) / 2; | |
564 } | |
565 | |
566 bool AutofillDialogViews::ErrorBubble::ShouldArrowGoOnTheRight() { | |
567 gfx::Point anchor_offset; | |
568 views::View::ConvertPointToTarget(anchor_, anchor_container_, &anchor_offset); | |
569 anchor_offset.Offset(-anchor_container_->GetInsets().left(), 0); | |
570 | |
571 if (base::i18n::IsRTL()) { | |
572 int anchor_right_x = anchor_offset.x() + anchor_->width(); | |
573 return anchor_right_x >= GetPreferredBubbleWidth(); | |
574 } | |
575 | |
576 return anchor_offset.x() + GetPreferredBubbleWidth() > GetContainerWidth(); | |
577 } | |
578 | |
579 // AutofillDialogViews::AccountChooser ----------------------------------------- | 457 // AutofillDialogViews::AccountChooser ----------------------------------------- |
580 | 458 |
581 AutofillDialogViews::AccountChooser::AccountChooser( | 459 AutofillDialogViews::AccountChooser::AccountChooser( |
582 AutofillDialogViewDelegate* delegate) | 460 AutofillDialogViewDelegate* delegate) |
583 : image_(new views::ImageView()), | 461 : image_(new views::ImageView()), |
584 menu_button_(new views::MenuButton(NULL, base::string16(), this, true)), | 462 menu_button_(new views::MenuButton(NULL, base::string16(), this, true)), |
585 link_(new views::Link()), | 463 link_(new views::Link()), |
586 delegate_(delegate) { | 464 delegate_(delegate) { |
587 set_border(views::Border::CreateEmptyBorder(0, 0, 0, 10)); | 465 set_border(views::Border::CreateEmptyBorder(0, 0, 0, 10)); |
588 SetLayoutManager( | 466 SetLayoutManager( |
(...skipping 1660 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2249 return; | 2127 return; |
2250 } | 2128 } |
2251 | 2129 |
2252 std::map<views::View*, base::string16>::iterator error_message = | 2130 std::map<views::View*, base::string16>::iterator error_message = |
2253 validity_map_.find(view); | 2131 validity_map_.find(view); |
2254 if (error_message != validity_map_.end()) { | 2132 if (error_message != validity_map_.end()) { |
2255 view->ScrollRectToVisible(view->GetLocalBounds()); | 2133 view->ScrollRectToVisible(view->GetLocalBounds()); |
2256 | 2134 |
2257 if (!error_bubble_ || error_bubble_->anchor() != view) { | 2135 if (!error_bubble_ || error_bubble_->anchor() != view) { |
2258 HideErrorBubble(); | 2136 HideErrorBubble(); |
2259 views::View* section = | 2137 error_bubble_ = new InfoBubble(view, error_message->second); |
2260 view->GetAncestorWithClassName(kSectionContainerClassName); | 2138 error_bubble_->set_align_to_anchor_edge(true); |
2261 error_bubble_ = new ErrorBubble(view, section, error_message->second); | 2139 error_bubble_->set_container_insets(gfx::Insets(kDialogEdgePadding, |
| 2140 kDialogEdgePadding, |
| 2141 kDialogEdgePadding, |
| 2142 kDialogEdgePadding)); |
| 2143 error_bubble_->set_preferred_width( |
| 2144 (kSectionContainerWidth - views::kRelatedControlVerticalSpacing) / 2); |
| 2145 bool show_above = view->GetClassName() == views::Combobox::kViewClassName; |
| 2146 error_bubble_->set_show_above_anchor(show_above); |
| 2147 error_bubble_->Show(); |
2262 } | 2148 } |
2263 } | 2149 } |
2264 } | 2150 } |
2265 | 2151 |
2266 void AutofillDialogViews::HideErrorBubble() { | 2152 void AutofillDialogViews::HideErrorBubble() { |
2267 if (error_bubble_) { | 2153 if (error_bubble_) { |
2268 error_bubble_->Hide(); | 2154 error_bubble_->Hide(); |
2269 error_bubble_ = NULL; | 2155 error_bubble_ = NULL; |
2270 } | 2156 } |
2271 } | 2157 } |
(...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2572 AutofillDialogViews::DetailsGroup::DetailsGroup(DialogSection section) | 2458 AutofillDialogViews::DetailsGroup::DetailsGroup(DialogSection section) |
2573 : section(section), | 2459 : section(section), |
2574 container(NULL), | 2460 container(NULL), |
2575 manual_input(NULL), | 2461 manual_input(NULL), |
2576 suggested_info(NULL), | 2462 suggested_info(NULL), |
2577 suggested_button(NULL) {} | 2463 suggested_button(NULL) {} |
2578 | 2464 |
2579 AutofillDialogViews::DetailsGroup::~DetailsGroup() {} | 2465 AutofillDialogViews::DetailsGroup::~DetailsGroup() {} |
2580 | 2466 |
2581 } // namespace autofill | 2467 } // namespace autofill |
OLD | NEW |