15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/views/autofill/autofill_popup_view_views.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/autofill/autofill_popup_controller.h"
8a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "components/autofill/core/browser/popup_item_ids.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/resource/resource_bundle.h"
10d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ui/events/keycodes/keyboard_codes.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/canvas.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/image/image.h"
13424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "ui/gfx/native_widget_types.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/point.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/rect.h"
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/gfx/text_utils.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/border.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/widget/widget.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace autofill {
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AutofillPopupViewViews::AutofillPopupViewViews(
23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    AutofillPopupController* controller, views::Widget* observing_widget)
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : AutofillPopupBaseView(controller, observing_widget),
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      controller_(controller) {}
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)AutofillPopupViewViews::~AutofillPopupViewViews() {}
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AutofillPopupViewViews::Show() {
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DoShow();
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AutofillPopupViewViews::Hide() {
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The controller is no longer valid after it hides us.
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  controller_ = NULL;
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DoHide();
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AutofillPopupViewViews::UpdateBoundsAndRedrawPopup() {
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DoUpdateBoundsAndRedrawPopup();
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AutofillPopupViewViews::OnPaint(gfx::Canvas* canvas) {
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!controller_)
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  canvas->DrawColor(kPopupBackground);
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OnPaintBorder(canvas);
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0; i < controller_->names().size(); ++i) {
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    gfx::Rect line_rect = controller_->GetRowBounds(i);
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (controller_->identifiers()[i] == POPUP_ITEM_ID_SEPARATOR) {
556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      canvas->FillRect(line_rect, kItemTextColor);
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DrawAutofillEntry(canvas, i, line_rect);
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AutofillPopupViewViews::InvalidateRow(size_t row) {
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SchedulePaintInRect(controller_->GetRowBounds(row));
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AutofillPopupViewViews::DrawAutofillEntry(gfx::Canvas* canvas,
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               int index,
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               const gfx::Rect& entry_rect) {
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (controller_->selected_line() == index)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    canvas->FillRect(entry_rect, kHoveredBackgroundColor);
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const bool is_rtl = controller_->IsRTL();
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const int value_text_width =
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      gfx::GetStringWidth(controller_->names()[index],
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                          controller_->GetNameFontListForRow(index));
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const int value_content_x = is_rtl ?
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      entry_rect.width() - value_text_width - kEndPadding : kEndPadding;
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  canvas->DrawStringRectWithFlags(
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      controller_->names()[index],
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      controller_->GetNameFontListForRow(index),
827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      controller_->IsWarning(index) ? kWarningTextColor : kValueTextColor,
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      gfx::Rect(value_content_x,
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                entry_rect.y(),
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                value_text_width,
865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                entry_rect.height()),
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      gfx::Canvas::TEXT_ALIGN_CENTER);
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Use this to figure out where all the other Autofill items should be placed.
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int x_align_left = is_rtl ? kEndPadding : entry_rect.width() - kEndPadding;
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Draw the Autofill icon, if one exists
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int row_height = controller_->GetRowBounds(index).height();
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!controller_->icons()[index].empty()) {
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int icon = controller_->GetIconResourceID(controller_->icons()[index]);
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_NE(-1, icon);
980f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    const gfx::ImageSkia* image = rb.GetImageSkiaNamed(icon);
990f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    int icon_y = entry_rect.y() + (row_height - image->height()) / 2;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1010f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    x_align_left += is_rtl ? 0 : -image->width();
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1030f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    canvas->DrawImageInt(*image, x_align_left, icon_y);
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1050f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    x_align_left += is_rtl ? image->width() + kIconPadding : -kIconPadding;
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Draw the name text.
1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const int subtext_width =
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      gfx::GetStringWidth(controller_->subtexts()[index],
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                          controller_->subtext_font_list());
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!is_rtl)
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    x_align_left -= subtext_width;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  canvas->DrawStringRectWithFlags(
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      controller_->subtexts()[index],
1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      controller_->subtext_font_list(),
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      kItemTextColor,
1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      gfx::Rect(x_align_left,
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                entry_rect.y(),
1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                subtext_width,
1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                entry_rect.height()),
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      gfx::Canvas::TEXT_ALIGN_CENTER);
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)AutofillPopupView* AutofillPopupView::Create(
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    AutofillPopupController* controller) {
128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  views::Widget* observing_widget =
129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      views::Widget::GetTopLevelWidgetForNativeView(
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          controller->container_view());
131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // If the top level widget can't be found, cancel the popup since we can't
133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // fully set it up.
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!observing_widget)
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return NULL;
136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return new AutofillPopupViewViews(controller, observing_widget);
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace autofill
141