autofill_dialog_views.h revision 868fa2fe829687343ffae624259930155e16dbd8
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 3// found in the LICENSE file. 4 5#ifndef CHROME_BROWSER_UI_VIEWS_AUTOFILL_AUTOFILL_DIALOG_VIEWS_H_ 6#define CHROME_BROWSER_UI_VIEWS_AUTOFILL_AUTOFILL_DIALOG_VIEWS_H_ 7 8#include <map> 9 10#include "base/memory/weak_ptr.h" 11#include "base/scoped_observer.h" 12#include "chrome/browser/ui/autofill/autofill_dialog_controller.h" 13#include "chrome/browser/ui/autofill/autofill_dialog_view.h" 14#include "chrome/browser/ui/autofill/testable_autofill_dialog_view.h" 15#include "ui/base/accelerators/accelerator.h" 16#include "ui/views/controls/button/button.h" 17#include "ui/views/controls/button/menu_button_listener.h" 18#include "ui/views/controls/combobox/combobox_listener.h" 19#include "ui/views/controls/link_listener.h" 20#include "ui/views/controls/progress_bar.h" 21#include "ui/views/controls/scroll_view.h" 22#include "ui/views/controls/styled_label_listener.h" 23#include "ui/views/controls/textfield/textfield_controller.h" 24#include "ui/views/focus/focus_manager.h" 25#include "ui/views/widget/widget_observer.h" 26#include "ui/views/window/dialog_delegate.h" 27 28namespace content { 29class KeyboardListener; 30} 31 32namespace gfx { 33class Image; 34} 35 36namespace views { 37class Checkbox; 38class Combobox; 39class FocusManager; 40class ImageButton; 41class ImageView; 42class Label; 43class Link; 44class MenuRunner; 45class StyledLabel; 46class Textfield; 47class WebView; 48class Widget; 49} 50 51namespace ui { 52class ComboboxModel; 53class KeyEvent; 54} 55 56namespace autofill { 57 58class AutofillDialogSignInDelegate; 59struct DetailInput; 60 61// Views toolkit implementation of the Autofill dialog that handles the 62// imperative autocomplete API call. 63class AutofillDialogViews : public AutofillDialogView, 64 public TestableAutofillDialogView, 65 public views::DialogDelegate, 66 public views::WidgetObserver, 67 public views::ButtonListener, 68 public views::TextfieldController, 69 public views::FocusChangeListener, 70 public views::LinkListener, 71 public views::ComboboxListener, 72 public views::StyledLabelListener, 73 public ui::AcceleratorTarget { 74 public: 75 explicit AutofillDialogViews(AutofillDialogController* controller); 76 virtual ~AutofillDialogViews(); 77 78 // AutofillDialogView implementation: 79 virtual void Show() OVERRIDE; 80 virtual void Hide() OVERRIDE; 81 virtual void UpdateAccountChooser() OVERRIDE; 82 virtual void UpdateButtonStrip() OVERRIDE; 83 virtual void UpdateDetailArea() OVERRIDE; 84 virtual void UpdateNotificationArea() OVERRIDE; 85 virtual void UpdateSection(DialogSection section) OVERRIDE; 86 virtual void FillSection(DialogSection section, 87 const DetailInput& originating_input) OVERRIDE; 88 virtual void GetUserInput(DialogSection section, 89 DetailOutputMap* output) OVERRIDE; 90 virtual string16 GetCvc() OVERRIDE; 91 virtual bool SaveDetailsLocally() OVERRIDE; 92 virtual const content::NavigationController* ShowSignIn() OVERRIDE; 93 virtual void HideSignIn() OVERRIDE; 94 virtual void UpdateProgressBar(double value) OVERRIDE; 95 virtual void ModelChanged() OVERRIDE; 96 virtual TestableAutofillDialogView* GetTestableView() OVERRIDE; 97 virtual void OnSignInResize(const gfx::Size& pref_size) OVERRIDE; 98 99 // TestableAutofillDialogView implementation: 100 virtual void SubmitForTesting() OVERRIDE; 101 virtual void CancelForTesting() OVERRIDE; 102 virtual string16 GetTextContentsOfInput(const DetailInput& input) OVERRIDE; 103 virtual void SetTextContentsOfInput(const DetailInput& input, 104 const string16& contents) OVERRIDE; 105 virtual void ActivateInput(const DetailInput& input) OVERRIDE; 106 virtual gfx::Size GetSize() const OVERRIDE; 107 108 // ui::AcceleratorTarget implementation: 109 virtual bool AcceleratorPressed(const ui::Accelerator& accelerator) OVERRIDE; 110 virtual bool CanHandleAccelerators() const OVERRIDE; 111 112 // views::DialogDelegate implementation: 113 virtual string16 GetWindowTitle() const OVERRIDE; 114 virtual void WindowClosing() OVERRIDE; 115 virtual void DeleteDelegate() OVERRIDE; 116 virtual views::Widget* GetWidget() OVERRIDE; 117 virtual const views::Widget* GetWidget() const OVERRIDE; 118 virtual views::View* GetContentsView() OVERRIDE; 119 virtual int GetDialogButtons() const OVERRIDE; 120 virtual string16 GetDialogButtonLabel(ui::DialogButton button) const OVERRIDE; 121 virtual bool IsDialogButtonEnabled(ui::DialogButton button) const OVERRIDE; 122 virtual views::View* CreateExtraView() OVERRIDE; 123 virtual views::View* CreateTitlebarExtraView() OVERRIDE; 124 virtual views::View* CreateFootnoteView() OVERRIDE; 125 virtual bool Cancel() OVERRIDE; 126 virtual bool Accept() OVERRIDE; 127 virtual views::NonClientFrameView* CreateNonClientFrameView( 128 views::Widget* widget) OVERRIDE; 129 130 // views::WidgetObserver implementation: 131 virtual void OnWidgetClosing(views::Widget* widget) OVERRIDE; 132 virtual void OnWidgetBoundsChanged(views::Widget* widget, 133 const gfx::Rect& new_bounds) OVERRIDE; 134 135 // views::ButtonListener implementation: 136 virtual void ButtonPressed(views::Button* sender, 137 const ui::Event& event) OVERRIDE; 138 139 // views::TextfieldController implementation: 140 virtual void ContentsChanged(views::Textfield* sender, 141 const string16& new_contents) OVERRIDE; 142 virtual bool HandleKeyEvent(views::Textfield* sender, 143 const ui::KeyEvent& key_event) OVERRIDE; 144 virtual bool HandleMouseEvent(views::Textfield* sender, 145 const ui::MouseEvent& key_event) OVERRIDE; 146 147 // views::FocusChangeListener implementation. 148 virtual void OnWillChangeFocus(views::View* focused_before, 149 views::View* focused_now) OVERRIDE; 150 virtual void OnDidChangeFocus(views::View* focused_before, 151 views::View* focused_now) OVERRIDE; 152 153 // views::LinkListener implementation: 154 virtual void LinkClicked(views::Link* source, int event_flags) OVERRIDE; 155 156 // views::ComboboxListener implementation: 157 virtual void OnSelectedIndexChanged(views::Combobox* combobox) OVERRIDE; 158 159 // views::StyledLabelListener implementation: 160 virtual void StyledLabelLinkClicked(const ui::Range& range, int event_flags) 161 OVERRIDE; 162 163 private: 164 // A view that contains a single child view, and adds a vertical scrollbar 165 // after a certain maximum height is reached. 166 class SizeLimitedScrollView : public views::ScrollView { 167 public: 168 explicit SizeLimitedScrollView(views::View* scroll_contents); 169 virtual ~SizeLimitedScrollView(); 170 171 // views::View implementation. 172 virtual void Layout() OVERRIDE; 173 virtual gfx::Size GetPreferredSize() OVERRIDE; 174 175 // Sets the maximum height for the viewport. 176 void SetMaximumHeight(int max_height); 177 178 private: 179 int max_height_; 180 181 DISALLOW_COPY_AND_ASSIGN(SizeLimitedScrollView); 182 }; 183 184 // A class that creates and manages a widget for error messages. 185 class ErrorBubble : public views::WidgetObserver { 186 public: 187 ErrorBubble(views::View* anchor, const string16& message); 188 virtual ~ErrorBubble(); 189 190 bool IsShowing(); 191 192 // Re-positions the bubble over |anchor_|. If |anchor_| is not visible, 193 // the bubble will hide. 194 void UpdatePosition(); 195 196 virtual void OnWidgetClosing(views::Widget* widget) OVERRIDE; 197 198 views::View* anchor() { return anchor_; } 199 200 private: 201 // Calculates and returns the bounds of |widget_|, depending on |anchor_| 202 // and |contents_|. 203 gfx::Rect GetBoundsForWidget(); 204 205 views::Widget* widget_; // Weak, may be NULL. 206 views::View* anchor_; // Weak. 207 // The contents view of |widget_|. 208 views::View* contents_; // Weak. 209 ScopedObserver<views::Widget, ErrorBubble> observer_; 210 211 DISALLOW_COPY_AND_ASSIGN(ErrorBubble); 212 }; 213 214 // A class which holds a textfield and draws extra stuff on top, like 215 // invalid content indications. 216 class DecoratedTextfield : public views::View { 217 public: 218 DecoratedTextfield(const string16& default_value, 219 const string16& placeholder, 220 views::TextfieldController* controller); 221 virtual ~DecoratedTextfield(); 222 223 // The wrapped text field. 224 views::Textfield* textfield() { return textfield_; } 225 226 // Sets whether to indicate the textfield has invalid content. 227 void SetInvalid(bool invalid); 228 bool invalid() const { return invalid_; } 229 230 // views::View implementation. 231 virtual const char* GetClassName() const OVERRIDE; 232 virtual void PaintChildren(gfx::Canvas* canvas) OVERRIDE; 233 virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE; 234 virtual void RequestFocus() OVERRIDE; 235 236 private: 237 views::Textfield* textfield_; 238 bool invalid_; 239 240 DISALLOW_COPY_AND_ASSIGN(DecoratedTextfield); 241 }; 242 243 // A View which displays the currently selected account and lets the user 244 // switch accounts. 245 class AccountChooser : public views::View, 246 public views::LinkListener, 247 public base::SupportsWeakPtr<AccountChooser> { 248 public: 249 explicit AccountChooser(AutofillDialogController* controller); 250 virtual ~AccountChooser(); 251 252 // Updates the view based on the state that |controller_| reports. 253 void Update(); 254 255 // views::View implementation. 256 virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE; 257 virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE; 258 259 // views::LinkListener implementation. 260 virtual void LinkClicked(views::Link* source, int event_flags) OVERRIDE; 261 262 private: 263 // The icon for the currently in-use account. 264 views::ImageView* image_; 265 266 // The label for the currently in-use account. 267 views::Label* label_; 268 269 // The drop arrow. 270 views::ImageView* arrow_; 271 272 // The sign in link. 273 views::Link* link_; 274 275 // The controller |this| queries for logic and state. 276 AutofillDialogController* controller_; 277 278 // Runs the suggestion menu (triggered by each section's |suggested_button|. 279 scoped_ptr<views::MenuRunner> menu_runner_; 280 281 DISALLOW_COPY_AND_ASSIGN(AccountChooser); 282 }; 283 284 // An area for notifications. Some notifications point at the account chooser. 285 class NotificationArea : public views::View, 286 public views::ButtonListener { 287 public: 288 explicit NotificationArea(AutofillDialogController* controller); 289 virtual ~NotificationArea(); 290 291 // Displays the given notifications. 292 void SetNotifications(const std::vector<DialogNotification>& notifications); 293 294 // views::View implementation. 295 virtual gfx::Size GetPreferredSize() OVERRIDE; 296 virtual const char* GetClassName() const OVERRIDE; 297 virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE; 298 299 // views::ButtonListener implementation: 300 virtual void ButtonPressed(views::Button* sender, 301 const ui::Event& event) OVERRIDE; 302 303 void set_arrow_centering_anchor( 304 const base::WeakPtr<views::View>& arrow_centering_anchor) { 305 arrow_centering_anchor_ = arrow_centering_anchor; 306 } 307 308 private: 309 // Utility function for determining whether an arrow should be drawn 310 // pointing at |arrow_centering_anchor_|. 311 bool HasArrow(); 312 313 // A reference to the controller than owns this view. Used to report when 314 // checkboxes change their values. 315 AutofillDialogController* controller_; // weak 316 317 // The currently showing checkbox, or NULL if none exists. 318 views::Checkbox* checkbox_; // weak 319 320 // If HasArrow() is true, the arrow should point at this. 321 base::WeakPtr<views::View> arrow_centering_anchor_; 322 323 std::vector<DialogNotification> notifications_; 324 325 DISALLOW_COPY_AND_ASSIGN(NotificationArea); 326 }; 327 328 typedef std::map<const DetailInput*, DecoratedTextfield*> TextfieldMap; 329 typedef std::map<const DetailInput*, views::Combobox*> ComboboxMap; 330 331 // A view that packs a label on the left and some related controls 332 // on the right. 333 class SectionContainer : public views::View { 334 public: 335 SectionContainer(const string16& label, 336 views::View* controls, 337 views::Button* proxy_button); 338 virtual ~SectionContainer(); 339 340 // Sets the visual appearance of the section to active (considered active 341 // when showing the menu or hovered by the mouse cursor). 342 void SetActive(bool active); 343 344 // Sets whether mouse events should be forwarded to |proxy_button_|. 345 void SetForwardMouseEvents(bool forward); 346 347 // views::View implementation. 348 virtual void OnMouseMoved(const ui::MouseEvent& event) OVERRIDE; 349 virtual void OnMouseEntered(const ui::MouseEvent& event) OVERRIDE; 350 virtual void OnMouseExited(const ui::MouseEvent& event) OVERRIDE; 351 virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE; 352 virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE; 353 354 private: 355 // Converts |event| to one suitable for |proxy_button_|. 356 static ui::MouseEvent ProxyEvent(const ui::MouseEvent& event); 357 358 // Mouse events on |this| are sent to this button. 359 views::Button* proxy_button_; // Weak reference. 360 361 // When true, mouse events will be forwarded to |proxy_button_|. 362 bool forward_mouse_events_; 363 364 DISALLOW_COPY_AND_ASSIGN(SectionContainer); 365 }; 366 367 // A view that contains a suggestion (such as a known address) and a link to 368 // edit the suggestion. 369 class SuggestionView : public views::View { 370 public: 371 SuggestionView(const string16& edit_label, 372 AutofillDialogViews* autofill_dialog); 373 virtual ~SuggestionView(); 374 375 // Whether this section is editable or not. 376 void SetEditable(bool editable); 377 378 // Sets the display text of the suggestion. 379 void SetSuggestionText(const string16& text, gfx::Font::FontStyle style); 380 381 // Sets the icon which should be displayed ahead of the text. 382 void SetSuggestionIcon(const gfx::Image& image); 383 384 // Shows an auxiliary textfield to the right of the suggestion icon and 385 // text. This is currently only used to show a CVC field for the CC section. 386 void ShowTextfield(const string16& placeholder_text, 387 const gfx::ImageSkia& icon); 388 389 DecoratedTextfield* decorated_textfield() { return decorated_; } 390 391 private: 392 // The label that holds the suggestion description text. 393 views::Label* label_; 394 // The second (and greater) line of text that describes the suggestion. 395 views::Label* label_line_2_; 396 // The icon that comes just before |label_|. 397 views::ImageView* icon_; 398 // A view to contain |label_| and |icon_|. 399 views::View* label_container_; 400 // The input set by ShowTextfield. 401 DecoratedTextfield* decorated_; 402 // An "Edit" link that flips to editable inputs rather than suggestion text. 403 views::Link* edit_link_; 404 405 DISALLOW_COPY_AND_ASSIGN(SuggestionView); 406 }; 407 408 // A convenience struct for holding pointers to views within each detail 409 // section. None of the member pointers are owned. 410 struct DetailsGroup { 411 explicit DetailsGroup(DialogSection section); 412 ~DetailsGroup(); 413 414 // The section this group is associated with. 415 const DialogSection section; 416 // The view that contains the entire section (label + input). 417 SectionContainer* container; 418 // The view that allows manual input. 419 views::View* manual_input; 420 // The textfields in |manual_input|, tracked by their DetailInput. 421 TextfieldMap textfields; 422 // The comboboxes in |manual_input|, tracked by their DetailInput. 423 ComboboxMap comboboxes; 424 // The view that holds the text of the suggested data. This will be 425 // visible IFF |manual_input| is not visible. 426 SuggestionView* suggested_info; 427 // The view that allows selecting other data suggestions. 428 views::ImageButton* suggested_button; 429 }; 430 431 class AutocheckoutProgressBar : public views::ProgressBar { 432 public: 433 AutocheckoutProgressBar(); 434 virtual ~AutocheckoutProgressBar(); 435 436 private: 437 // Overidden from View: 438 virtual gfx::Size GetPreferredSize() OVERRIDE; 439 440 DISALLOW_COPY_AND_ASSIGN(AutocheckoutProgressBar); 441 }; 442 443 typedef std::map<DialogSection, DetailsGroup> DetailGroupMap; 444 445 void InitChildViews(); 446 447 // Creates and returns a view that holds all detail sections. 448 views::View* CreateDetailsContainer(); 449 450 // Creates and returns a view that holds the requesting host and intro text. 451 views::View* CreateNotificationArea(); 452 453 // Creates and returns a view that holds the main controls of this dialog. 454 views::View* CreateMainContainer(); 455 456 // Creates a detail section (Shipping, Email, etc.) with the given label, 457 // inputs View, and suggestion model. Relevant pointers are stored in |group|. 458 void CreateDetailsSection(DialogSection section); 459 460 // Like CreateDetailsSection, but creates the combined billing/cc section, 461 // which is somewhat more complicated than the others. 462 void CreateBillingSection(); 463 464 // Creates the view that holds controls for inputing or selecting data for 465 // a given section. 466 views::View* CreateInputsContainer(DialogSection section); 467 468 // Creates a grid of textfield views for the given section, and stores them 469 // in the appropriate DetailsGroup. The top level View in the hierarchy is 470 // returned. 471 views::View* InitInputsView(DialogSection section); 472 473 // Updates the given section to match the state provided by |controller_|. If 474 // |clobber_inputs| is true, the current state of the textfields will be 475 // ignored, otherwise their contents will be preserved. 476 void UpdateSectionImpl(DialogSection section, bool clobber_inputs); 477 478 // Updates the visual state of the given group as per the model. 479 void UpdateDetailsGroupState(const DetailsGroup& group); 480 481 // Gets a pointer to the DetailsGroup that's associated with the given section 482 // of the dialog. 483 DetailsGroup* GroupForSection(DialogSection section); 484 485 // Gets a pointer to the DetailsGroup that's associated with a given |view|. 486 // Returns NULL if no DetailsGroup was found. 487 DetailsGroup* GroupForView(views::View* view); 488 489 // Sets the visual state for an input to be either valid or invalid. This 490 // should work on Comboboxes or DecoratedTextfields. If |message| is empty, 491 // the input is valid. 492 template<class T> 493 void SetValidityForInput(T* input, const string16& message); 494 495 // Shows an error bubble pointing at |view| if |view| has a message in 496 // |validity_map_|. 497 void ShowErrorBubbleForViewIfNecessary(views::View* view); 498 499 // Checks all manual inputs in |group| for validity. Decorates the invalid 500 // ones and returns true if all were valid. 501 bool ValidateGroup(const DetailsGroup& group, ValidationType type); 502 503 // Checks all manual inputs in the form for validity. Decorates the invalid 504 // ones and returns true if all were valid. 505 bool ValidateForm(); 506 507 // When an input textfield is edited (its contents change) or activated 508 // (clicked while focused), this function will inform the controller that it's 509 // time to show a suggestion popup and possibly reset the validity state of 510 // the input. 511 void TextfieldEditedOrActivated(views::Textfield* textfield, bool was_edit); 512 513 // Updates the [X] Save in Chrome checkbox in the button strip. 514 void UpdateSaveInChromeCheckbox(); 515 516 // Call this when the size of anything in |contents_| might've changed. 517 void ContentsPreferredSizeChanged(); 518 519 // Gets the textfield view that is shown for the given DetailInput model, or 520 // NULL. 521 views::Textfield* TextfieldForInput(const DetailInput& input); 522 523 // Gets the combobox view that is shown for the given DetailInput model, or 524 // NULL. 525 views::Combobox* ComboboxForInput(const DetailInput& input); 526 527 // Called when the details container changes in size or position. 528 void DetailsContainerBoundsChanged(); 529 530 // The controller that drives this view. Weak pointer, always non-NULL. 531 AutofillDialogController* const controller_; 532 533 // The window that displays |contents_|. Weak pointer; may be NULL when the 534 // dialog is closing. 535 views::Widget* window_; 536 537 // The top-level View for the dialog. Owned by the constrained window. 538 views::View* contents_; 539 540 // A DialogSection-keyed map of the DetailGroup structs. 541 DetailGroupMap detail_groups_; 542 543 // Somewhere to show notification messages about errors, warnings, or promos. 544 NotificationArea* notification_area_; 545 546 // Runs the suggestion menu (triggered by each section's |suggested_button|. 547 scoped_ptr<views::MenuRunner> menu_runner_; 548 549 // The view that allows the user to toggle the data source. 550 AccountChooser* account_chooser_; 551 552 // A WebView to that navigates to a Google sign-in page to allow the user to 553 // sign-in. 554 views::WebView* sign_in_webview_; 555 556 // View to host everything that isn't related to sign-in. 557 views::View* main_container_; 558 559 // View that wraps |details_container_| and makes it scroll vertically. 560 SizeLimitedScrollView* scrollable_area_; 561 562 // View to host details sections. 563 views::View* details_container_; 564 565 // The "Extra view" is on the same row as the dialog buttons. 566 views::View* button_strip_extra_view_; 567 568 // This checkbox controls whether new details are saved to the Autofill 569 // database. It lives in |extra_view_|. 570 views::Checkbox* save_in_chrome_checkbox_; 571 572 // View to host |autocheckout_progress_bar_| and its label. 573 views::View* autocheckout_progress_bar_view_; 574 575 // Progress bar for displaying Autocheckout progress. 576 AutocheckoutProgressBar* autocheckout_progress_bar_; 577 578 // The view that is appended to the bottom of the dialog, below the button 579 // strip. Used to display legal document links. 580 views::View* footnote_view_; 581 582 // The legal document text and links. 583 views::StyledLabel* legal_document_view_; 584 585 // The focus manager for |window_|. 586 views::FocusManager* focus_manager_; 587 588 // The object that manages the error bubble widget. 589 scoped_ptr<ErrorBubble> error_bubble_; 590 591 // Map from input view (textfield or combobox) to error string. 592 std::map<views::View*, string16> validity_map_; 593 594 ScopedObserver<views::Widget, AutofillDialogViews> observer_; 595 596 // Delegate for the sign-in dialog's webview. 597 scoped_ptr<AutofillDialogSignInDelegate> sign_in_delegate_; 598 599 DISALLOW_COPY_AND_ASSIGN(AutofillDialogViews); 600}; 601 602} // namespace autofill 603 604#endif // CHROME_BROWSER_UI_VIEWS_AUTOFILL_AUTOFILL_DIALOG_VIEWS_H_ 605