Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3244)

Unified Diff: chrome/browser/views/speech_input_bubble.cc

Issue 3133034: Adds a speech input info bubble. (Closed)
Patch Set: Reorganised speech bubble into an interface and implementation. Created 10 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/views/speech_input_bubble.cc
diff --git a/chrome/browser/views/speech_input_bubble.cc b/chrome/browser/views/speech_input_bubble.cc
new file mode 100644
index 0000000000000000000000000000000000000000..b43ca86f719e948542e1ff4d9312c00ce67095b7
--- /dev/null
+++ b/chrome/browser/views/speech_input_bubble.cc
@@ -0,0 +1,255 @@
+// 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 {
+
+// The speech bubble's arrow is so many pixels from the left of html element.
+const int kBubbleTargetOffsetX = 5;
+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,
sky 2010/08/24 16:08:28 align with ( on previous line.
+ const gfx::Rect& element_rect);
+ ~SpeechInputBubbleImpl();
sky 2010/08/24 16:08:28 virtual
+
+ 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_;
+ bool did_close_; // Set to true if |Close()| was invoked by caller.
sky 2010/08/24 16:08:28 Update comment.
+
+ 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_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_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);
sky 2010/08/24 16:08:28 Sounds the size be that of element_rect?
Satish 2010/08/24 16:22:04 We want the bubble's arrow to point at x, y positi
+}
+
+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_close_)
+ delegate_->InfoBubbleClosed();
+}
+
+bool SpeechInputBubbleImpl::CloseOnEscape() {
+ return false;
+}
+
+bool SpeechInputBubbleImpl::FadeInOnShow() {
+ return false;
+}
+
+} // namespace
+
+SpeechInputBubble* SpeechInputBubble::Create(
+ TabContents* tab_contents,
+ SpeechInputBubble::Delegate* delegate,
+ const gfx::Rect& element_rect) {
+ return new SpeechInputBubbleImpl(tab_contents, delegate, element_rect);
+}

Powered by Google App Engine
This is Rietveld 408576698