<commit_before>// Copyright (c) 2010 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/speech/speech_input_bubble.h"

#include "app/l10n_util.h"
#include "app/resource_bundle.h"
#include "base/message_loop.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_window.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/tab_contents/tab_contents_view.h"
#include "chrome/browser/views/info_bubble.h"
#include "chrome/common/notification_observer.h"
#include "chrome/common/notification_registrar.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/notification_type.h"
#include "gfx/canvas.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
#include "views/controls/image_view.h"
#include "views/controls/label.h"
#include "views/controls/link.h"
#include "views/standard_layout.h"
#include "views/view.h"

namespace {

const int kBubbleHorizMargin = 40;
const int kBubbleVertMargin = 0;

// This is the content view which is placed inside a SpeechInputBubble.
class ContentView
    : public views::View,
      public views::LinkController {
 public:
  explicit ContentView(SpeechInputBubbleDelegate* delegate);

  void SetRecognizingMode();

  // views::LinkController methods.
  virtual void LinkActivated(views::Link* source, int event_flags);

  // views::View overrides.
  virtual gfx::Size GetPreferredSize();
  virtual void Layout();

 private:
  SpeechInputBubbleDelegate* delegate_;
  views::ImageView* icon_;
  views::Label* heading_;
  views::Link* cancel_;

  DISALLOW_COPY_AND_ASSIGN(ContentView);
};

ContentView::ContentView(SpeechInputBubbleDelegate* delegate)
     : delegate_(delegate) {
  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
  const gfx::Font& font = rb.GetFont(ResourceBundle::BaseFont);

  heading_ = new views::Label(
      l10n_util::GetString(IDS_SPEECH_INPUT_BUBBLE_HEADING));
  heading_->SetFont(font.DeriveFont(3, gfx::Font::NORMAL));
  heading_->SetHorizontalAlignment(views::Label::ALIGN_CENTER);
  AddChildView(heading_);

  icon_ = new views::ImageView();
  icon_->SetImage(*ResourceBundle::GetSharedInstance().GetBitmapNamed(
      IDR_SPEECH_INPUT_RECORDING));
  icon_->SetHorizontalAlignment(views::ImageView::CENTER);
  AddChildView(icon_);

  cancel_ = new views::Link(l10n_util::GetString(IDS_CANCEL));
  cancel_->SetController(this);
  cancel_->SetFont(font.DeriveFont(3, gfx::Font::NORMAL));
  cancel_->SetHorizontalAlignment(views::Label::ALIGN_CENTER);
  AddChildView(cancel_);
}

void ContentView::SetRecognizingMode() {
  icon_->SetImage(*ResourceBundle::GetSharedInstance().GetBitmapNamed(
      IDR_SPEECH_INPUT_PROCESSING));
}

void ContentView::LinkActivated(views::Link* source, int event_flags) {
  if (source == cancel_) {
    delegate_->RecognitionCancelled();
  } else {
    NOTREACHED() << "Unknown view";
  }
}

gfx::Size ContentView::GetPreferredSize() {
  int width = heading_->GetPreferredSize().width();
  int control_width = cancel_->GetPreferredSize().width();
  if (control_width > width)
    width = control_width;
  control_width = icon_->GetPreferredSize().width();
  if (control_width > width)
    width = control_width;
  width += kBubbleHorizMargin * 2;

  int height = kBubbleVertMargin * 2 +
               heading_->GetPreferredSize().height() +
               cancel_->GetPreferredSize().height() +
               icon_->GetImage().height();
  return gfx::Size(width, height);
}

void ContentView::Layout() {
  int x = kBubbleHorizMargin;
  int y = kBubbleVertMargin;
  int control_width = width() - kBubbleHorizMargin * 2;

  int height = heading_->GetPreferredSize().height();
  heading_->SetBounds(x, y, control_width, height);
  y += height;

  height = icon_->GetImage().height();
  icon_->SetBounds(x, y, control_width, height);
  y += height;

  height = cancel_->GetPreferredSize().height();
  cancel_->SetBounds(x, y, control_width, height);
}

// Implementation of SpeechInputBubble.
class SpeechInputBubbleImpl
    : public SpeechInputBubble,
      public InfoBubbleDelegate,
      public NotificationObserver {
 public:
  SpeechInputBubbleImpl(TabContents* tab_contents,
                        Delegate* delegate,
                        const gfx::Rect& element_rect);
  virtual ~SpeechInputBubbleImpl();

  virtual void SetRecognizingMode();

  // Returns the screen rectangle to use as the info bubble's target.
  // |element_rect| is the html element's bounds in page coordinates.
  gfx::Rect GetInfoBubbleTarget(const gfx::Rect& element_rect);

  // NotificationObserver implementation.
  virtual void Observe(NotificationType type,
                       const NotificationSource& source,
                       const NotificationDetails& details);

  // InfoBubbleDelegate
  virtual void InfoBubbleClosing(InfoBubble* info_bubble,
                                 bool closed_by_escape);
  virtual bool CloseOnEscape();
  virtual bool FadeInOnShow();

 private:
  Delegate* delegate_;
  InfoBubble* info_bubble_;
  TabContents* tab_contents_;
  ContentView* bubble_content_;
  NotificationRegistrar registrar_;

  // Set to true if the object is being destroyed normally instead of the
  // user clicking outside the window causing it to close automatically.
  bool did_invoke_close_;

  DISALLOW_COPY_AND_ASSIGN(SpeechInputBubbleImpl);
};

SpeechInputBubbleImpl::SpeechInputBubbleImpl(TabContents* tab_contents,
                                             Delegate* delegate,
                                             const gfx::Rect& element_rect)
    : delegate_(delegate),
      info_bubble_(NULL),
      tab_contents_(tab_contents),
      bubble_content_(NULL),
      did_invoke_close_(false) {
  bubble_content_ = new ContentView(delegate_);

  views::Widget* parent = views::Widget::GetWidgetFromNativeWindow(
      tab_contents_->view()->GetTopLevelNativeWindow());
  info_bubble_ = InfoBubble::Show(parent,
                                  GetInfoBubbleTarget(element_rect),
                                  BubbleBorder::TOP_LEFT, bubble_content_,
                                  this);

  // We don't want fade outs when closing because it makes speech recognition
  // appear slower than it is. Also setting it to false allows |Close| to
  // destroy the bubble immediately instead of waiting for the fade animation
  // to end so the caller can manage this object's life cycle like a normal
  // stack based or member variable object.
  info_bubble_->set_fade_away_on_close(false);

  registrar_.Add(this, NotificationType::TAB_CONTENTS_DESTROYED,
                 Source<TabContents>(tab_contents_));
}

SpeechInputBubbleImpl::~SpeechInputBubbleImpl() {
  if (info_bubble_) {
    did_invoke_close_ = true;
    info_bubble_->Close();
  }
}

void SpeechInputBubbleImpl::SetRecognizingMode() {
  DCHECK(info_bubble_);
  DCHECK(bubble_content_);
  bubble_content_->SetRecognizingMode();
}

gfx::Rect SpeechInputBubbleImpl::GetInfoBubbleTarget(
    const gfx::Rect& element_rect) {
  gfx::Rect container_rect;
  tab_contents_->GetContainerBounds(&container_rect);
  return gfx::Rect(
      container_rect.x() + element_rect.x() + kBubbleTargetOffsetX,
      container_rect.y() + element_rect.y() + element_rect.height(), 1, 1);
}

void SpeechInputBubbleImpl::Observe(NotificationType type,
                                const NotificationSource& source,
                                const NotificationDetails& details) {
  if (type == NotificationType::TAB_CONTENTS_DESTROYED) {
    delegate_->RecognitionCancelled();
  } else {
    NOTREACHED() << "Unknown notification";
  }
}

void SpeechInputBubbleImpl::InfoBubbleClosing(InfoBubble* info_bubble,
                                          bool closed_by_escape) {
  registrar_.Remove(this, NotificationType::TAB_CONTENTS_DESTROYED,
                    Source<TabContents>(tab_contents_));
  info_bubble_ = NULL;
  bubble_content_ = NULL;
  if (!did_invoke_close_)
    delegate_->InfoBubbleClosed();
}

bool SpeechInputBubbleImpl::CloseOnEscape() {
  return false;
}

bool SpeechInputBubbleImpl::FadeInOnShow() {
  return false;
}

}  // namespace

SpeechInputBubble* SpeechInputBubble::CreateNativeBubble(
    TabContents* tab_contents,
    SpeechInputBubble::Delegate* delegate,
    const gfx::Rect& element_rect) {
  return new SpeechInputBubbleImpl(tab_contents, delegate, element_rect);
}
<commit_msg>Changed a link widget to button per feedback from UX.<commit_after>// Copyright (c) 2010 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/speech/speech_input_bubble.h"

#include "app/l10n_util.h"
#include "app/resource_bundle.h"
#include "base/message_loop.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_window.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/tab_contents/tab_contents_view.h"
#include "chrome/browser/views/info_bubble.h"
#include "chrome/common/notification_observer.h"
#include "chrome/common/notification_registrar.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/notification_type.h"
#include "gfx/canvas.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
#include "views/controls/button/native_button.h"
#include "views/controls/image_view.h"
#include "views/controls/label.h"
#include "views/standard_layout.h"
#include "views/view.h"

namespace {

const int kBubbleHorizMargin = 40;
const int kBubbleVertMargin = 0;

// This is the content view which is placed inside a SpeechInputBubble.
class ContentView
    : public views::View,
      public views::ButtonListener {
 public:
  explicit ContentView(SpeechInputBubbleDelegate* delegate);

  void SetRecognizingMode();

  // views::ButtonListener methods.
  virtual void ButtonPressed(views::Button* source, const views::Event& event);

  // views::View overrides.
  virtual gfx::Size GetPreferredSize();
  virtual void Layout();

 private:
  SpeechInputBubbleDelegate* delegate_;
  views::ImageView* icon_;
  views::Label* heading_;
  views::NativeButton* cancel_;

  DISALLOW_COPY_AND_ASSIGN(ContentView);
};

ContentView::ContentView(SpeechInputBubbleDelegate* delegate)
     : delegate_(delegate) {
  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
  const gfx::Font& font = rb.GetFont(ResourceBundle::BaseFont);

  heading_ = new views::Label(
      l10n_util::GetString(IDS_SPEECH_INPUT_BUBBLE_HEADING));
  heading_->SetFont(font.DeriveFont(3, gfx::Font::NORMAL));
  heading_->SetHorizontalAlignment(views::Label::ALIGN_CENTER);
  AddChildView(heading_);

  icon_ = new views::ImageView();
  icon_->SetImage(*ResourceBundle::GetSharedInstance().GetBitmapNamed(
      IDR_SPEECH_INPUT_RECORDING));
  icon_->SetHorizontalAlignment(views::ImageView::CENTER);
  AddChildView(icon_);

  cancel_ = new views::NativeButton(this, l10n_util::GetString(IDS_CANCEL));
  AddChildView(cancel_);
}

void ContentView::SetRecognizingMode() {
  icon_->SetImage(*ResourceBundle::GetSharedInstance().GetBitmapNamed(
      IDR_SPEECH_INPUT_PROCESSING));
}

void ContentView::ButtonPressed(views::Button* source,
                                const views::Event& event) {
  if (source == cancel_) {
    delegate_->RecognitionCancelled();
  } else {
    NOTREACHED() << "Unknown view";
  }
}

gfx::Size ContentView::GetPreferredSize() {
  int width = heading_->GetPreferredSize().width();
  int control_width = cancel_->GetPreferredSize().width();
  if (control_width > width)
    width = control_width;
  control_width = icon_->GetPreferredSize().width();
  if (control_width > width)
    width = control_width;
  width += kBubbleHorizMargin * 2;

  int height = kBubbleVertMargin * 2 +
               heading_->GetPreferredSize().height() +
               cancel_->GetPreferredSize().height() +
               icon_->GetImage().height();
  return gfx::Size(width, height);
}

void ContentView::Layout() {
  int x = kBubbleHorizMargin;
  int y = kBubbleVertMargin;
  int control_width = width() - kBubbleHorizMargin * 2;

  int height = heading_->GetPreferredSize().height();
  heading_->SetBounds(x, y, control_width, height);
  y += height;

  height = icon_->GetImage().height();
  icon_->SetBounds(x, y, control_width, height);
  y += height;

  height = cancel_->GetPreferredSize().height();
  cancel_->SetBounds(x, y, control_width, height);
}

// Implementation of SpeechInputBubble.
class SpeechInputBubbleImpl
    : public SpeechInputBubble,
      public InfoBubbleDelegate,
      public NotificationObserver {
 public:
  SpeechInputBubbleImpl(TabContents* tab_contents,
                        Delegate* delegate,
                        const gfx::Rect& element_rect);
  virtual ~SpeechInputBubbleImpl();

  virtual void SetRecognizingMode();

  // Returns the screen rectangle to use as the info bubble's target.
  // |element_rect| is the html element's bounds in page coordinates.
  gfx::Rect GetInfoBubbleTarget(const gfx::Rect& element_rect);

  // NotificationObserver implementation.
  virtual void Observe(NotificationType type,
                       const NotificationSource& source,
                       const NotificationDetails& details);

  // InfoBubbleDelegate
  virtual void InfoBubbleClosing(InfoBubble* info_bubble,
                                 bool closed_by_escape);
  virtual bool CloseOnEscape();
  virtual bool FadeInOnShow();

 private:
  Delegate* delegate_;
  InfoBubble* info_bubble_;
  TabContents* tab_contents_;
  ContentView* bubble_content_;
  NotificationRegistrar registrar_;

  // Set to true if the object is being destroyed normally instead of the
  // user clicking outside the window causing it to close automatically.
  bool did_invoke_close_;

  DISALLOW_COPY_AND_ASSIGN(SpeechInputBubbleImpl);
};

SpeechInputBubbleImpl::SpeechInputBubbleImpl(TabContents* tab_contents,
                                             Delegate* delegate,
                                             const gfx::Rect& element_rect)
    : delegate_(delegate),
      info_bubble_(NULL),
      tab_contents_(tab_contents),
      bubble_content_(NULL),
      did_invoke_close_(false) {
  bubble_content_ = new ContentView(delegate_);

  views::Widget* parent = views::Widget::GetWidgetFromNativeWindow(
      tab_contents_->view()->GetTopLevelNativeWindow());
  info_bubble_ = InfoBubble::Show(parent,
                                  GetInfoBubbleTarget(element_rect),
                                  BubbleBorder::TOP_LEFT, bubble_content_,
                                  this);

  // We don't want fade outs when closing because it makes speech recognition
  // appear slower than it is. Also setting it to false allows |Close| to
  // destroy the bubble immediately instead of waiting for the fade animation
  // to end so the caller can manage this object's life cycle like a normal
  // stack based or member variable object.
  info_bubble_->set_fade_away_on_close(false);

  registrar_.Add(this, NotificationType::TAB_CONTENTS_DESTROYED,
                 Source<TabContents>(tab_contents_));
}

SpeechInputBubbleImpl::~SpeechInputBubbleImpl() {
  if (info_bubble_) {
    did_invoke_close_ = true;
    info_bubble_->Close();
  }
}

void SpeechInputBubbleImpl::SetRecognizingMode() {
  DCHECK(info_bubble_);
  DCHECK(bubble_content_);
  bubble_content_->SetRecognizingMode();
}

gfx::Rect SpeechInputBubbleImpl::GetInfoBubbleTarget(
    const gfx::Rect& element_rect) {
  gfx::Rect container_rect;
  tab_contents_->GetContainerBounds(&container_rect);
  return gfx::Rect(
      container_rect.x() + element_rect.x() + kBubbleTargetOffsetX,
      container_rect.y() + element_rect.y() + element_rect.height(), 1, 1);
}

void SpeechInputBubbleImpl::Observe(NotificationType type,
                                const NotificationSource& source,
                                const NotificationDetails& details) {
  if (type == NotificationType::TAB_CONTENTS_DESTROYED) {
    delegate_->RecognitionCancelled();
  } else {
    NOTREACHED() << "Unknown notification";
  }
}

void SpeechInputBubbleImpl::InfoBubbleClosing(InfoBubble* info_bubble,
                                          bool closed_by_escape) {
  registrar_.Remove(this, NotificationType::TAB_CONTENTS_DESTROYED,
                    Source<TabContents>(tab_contents_));
  info_bubble_ = NULL;
  bubble_content_ = NULL;
  if (!did_invoke_close_)
    delegate_->InfoBubbleClosed();
}

bool SpeechInputBubbleImpl::CloseOnEscape() {
  return false;
}

bool SpeechInputBubbleImpl::FadeInOnShow() {
  return false;
}

}  // namespace

SpeechInputBubble* SpeechInputBubble::CreateNativeBubble(
    TabContents* tab_contents,
    SpeechInputBubble::Delegate* delegate,
    const gfx::Rect& element_rect) {
  return new SpeechInputBubbleImpl(tab_contents, delegate, element_rect);
}

{'fraction_non_alphanumeric': 0.10610516409834138, 'fraction_numerical': 0.00229384778261381, 'mean_word_length': 3.952810952519662, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 66, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 20, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '669943', 'n_tokens_mistral': 5111, 'n_tokens_neox': 4945, 'n_words': 1062}