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

Side by Side Diff: chrome/browser/speech/speech_input_bubble_views.cc

Issue 8565003: Rebase SpeechInputBubble on the new views bubble. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Take another approach. Created 9 years, 1 month 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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/speech/speech_input_bubble.h" 5 #include "chrome/browser/speech/speech_input_bubble.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/message_loop.h"
10 #include "base/utf_string_conversions.h" 9 #include "base/utf_string_conversions.h"
11 #include "chrome/browser/ui/browser.h" 10 #include "chrome/browser/ui/browser.h"
12 #include "chrome/browser/ui/views/bubble/bubble.h"
13 #include "chrome/browser/ui/views/frame/browser_view.h" 11 #include "chrome/browser/ui/views/frame/browser_view.h"
12 #include "chrome/browser/ui/views/location_bar/location_icon_view.h"
14 #include "chrome/browser/ui/views/toolbar_view.h" 13 #include "chrome/browser/ui/views/toolbar_view.h"
15 #include "content/browser/tab_contents/tab_contents.h" 14 #include "content/browser/tab_contents/tab_contents.h"
16 #include "content/browser/tab_contents/tab_contents_view.h" 15 #include "content/browser/tab_contents/tab_contents_view.h"
17 #include "grit/generated_resources.h" 16 #include "grit/generated_resources.h"
18 #include "grit/theme_resources.h" 17 #include "grit/theme_resources.h"
19 #include "media/audio/audio_manager.h" 18 #include "media/audio/audio_manager.h"
20 #include "ui/base/l10n/l10n_util.h" 19 #include "ui/base/l10n/l10n_util.h"
21 #include "ui/base/resource/resource_bundle.h" 20 #include "ui/base/resource/resource_bundle.h"
22 #include "ui/gfx/canvas.h" 21 #include "views/bubble/bubble_delegate.h"
23 #include "views/border.h"
24 #include "views/controls/button/text_button.h" 22 #include "views/controls/button/text_button.h"
25 #include "views/controls/image_view.h" 23 #include "views/controls/image_view.h"
26 #include "views/controls/label.h" 24 #include "views/controls/label.h"
27 #include "views/controls/link.h" 25 #include "views/controls/link.h"
28 #include "views/controls/link_listener.h" 26 #include "views/controls/link_listener.h"
29 #include "views/layout/layout_constants.h" 27 #include "views/layout/layout_constants.h"
30 #include "views/view.h"
31 28
32 namespace { 29 namespace {
33 30
31 // TODO(msw): Get color from theme/window color.
32 const SkColor kColor = SK_ColorWHITE;
33
34 const int kBubbleHorizMargin = 6; 34 const int kBubbleHorizMargin = 6;
35 const int kBubbleVertMargin = 4; 35 const int kBubbleVertMargin = 4;
36 const int kBubbleHeadingVertMargin = 6; 36 const int kBubbleHeadingVertMargin = 6;
37 const int kIconHorizontalOffset = 27; 37 const int kIconHorizontalOffset = 27;
38 const int kIconVerticalOffset = -7; 38 const int kIconVerticalOffset = -7;
39 39
40 // This is the content view which is placed inside a SpeechInputBubble. 40 // This is the SpeechInputBubble content and views bubble delegate.
41 class ContentView 41 class SpeechInputBubbleView
42 : public views::View, 42 : public views::BubbleDelegateView,
43 public views::ButtonListener, 43 public views::ButtonListener,
44 public views::LinkListener { 44 public views::LinkListener {
45 public: 45 public:
46 explicit ContentView(SpeechInputBubbleDelegate* delegate); 46 SpeechInputBubbleView(SpeechInputBubbleDelegate* delegate,
47 views::View* anchor_view,
48 const gfx::Rect& element_rect,
49 TabContents* tab_contents);
47 50
48 void UpdateLayout(SpeechInputBubbleBase::DisplayMode mode, 51 void UpdateLayout(SpeechInputBubbleBase::DisplayMode mode,
49 const string16& message_text, 52 const string16& message_text,
50 const SkBitmap& image); 53 const SkBitmap& image);
51 void SetImage(const SkBitmap& image); 54 void SetImage(const SkBitmap& image);
52 55
56 // views::BubbleDelegateView methods.
57 virtual void OnWidgetActivationChanged(views::Widget* widget,
58 bool active) OVERRIDE;
59 virtual gfx::Point GetAnchorPoint() OVERRIDE;
60 virtual void Init() OVERRIDE;
61
53 // views::ButtonListener methods. 62 // views::ButtonListener methods.
54 virtual void ButtonPressed(views::Button* source, const views::Event& event); 63 virtual void ButtonPressed(views::Button* source, const views::Event& event);
55 64
56 // views::LinkListener methods. 65 // views::LinkListener methods.
57 virtual void LinkClicked(views::Link* source, int event_flags) OVERRIDE; 66 virtual void LinkClicked(views::Link* source, int event_flags) OVERRIDE;
58 67
59 // views::View overrides. 68 // views::View overrides.
60 virtual gfx::Size GetPreferredSize(); 69 virtual gfx::Size GetPreferredSize();
61 virtual void Layout(); 70 virtual void Layout();
62 71
63 private: 72 private:
64 SpeechInputBubbleDelegate* delegate_; 73 SpeechInputBubbleDelegate* delegate_;
74 gfx::Rect element_rect_;
75 TabContents* tab_contents_;
65 views::ImageView* icon_; 76 views::ImageView* icon_;
66 views::Label* heading_; 77 views::Label* heading_;
67 views::Label* message_; 78 views::Label* message_;
68 views::TextButton* try_again_; 79 views::TextButton* try_again_;
69 views::TextButton* cancel_; 80 views::TextButton* cancel_;
70 views::Link* mic_settings_; 81 views::Link* mic_settings_;
71 SpeechInputBubbleBase::DisplayMode display_mode_; 82 SpeechInputBubbleBase::DisplayMode display_mode_;
72 const int kIconLayoutMinWidth; 83 const int kIconLayoutMinWidth;
73 84
74 DISALLOW_COPY_AND_ASSIGN(ContentView); 85 DISALLOW_COPY_AND_ASSIGN(SpeechInputBubbleView);
75 }; 86 };
76 87
77 ContentView::ContentView(SpeechInputBubbleDelegate* delegate) 88 SpeechInputBubbleView::SpeechInputBubbleView(
78 : delegate_(delegate), 89 SpeechInputBubbleDelegate* delegate,
79 display_mode_(SpeechInputBubbleBase::DISPLAY_MODE_WARM_UP), 90 views::View* anchor_view,
80 kIconLayoutMinWidth(ResourceBundle::GetSharedInstance().GetBitmapNamed( 91 const gfx::Rect& element_rect,
81 IDR_SPEECH_INPUT_MIC_EMPTY)->width()) { 92 TabContents* tab_contents)
93 : BubbleDelegateView(anchor_view, views::BubbleBorder::TOP_LEFT, kColor),
94 delegate_(delegate),
95 element_rect_(element_rect),
96 tab_contents_(tab_contents),
97 display_mode_(SpeechInputBubbleBase::DISPLAY_MODE_WARM_UP),
98 kIconLayoutMinWidth(ResourceBundle::GetSharedInstance().GetBitmapNamed(
99 IDR_SPEECH_INPUT_MIC_EMPTY)->width()) {
100 set_close_on_esc(false);
msw 2011/11/17 07:05:25 indentation fixed.
101 }
102
103 void SpeechInputBubbleView::OnWidgetActivationChanged(views::Widget* widget,
104 bool active) {
105 if (widget == GetWidget() && !active)
106 delegate_->InfoBubbleFocusChanged();
107 BubbleDelegateView::OnWidgetActivationChanged(widget, active);
108 }
109
110 gfx::Point SpeechInputBubbleView::GetAnchorPoint() {
111 gfx::Rect container_rect;
112 tab_contents_->GetContainerBounds(&container_rect);
113 gfx::Point anchor(container_rect.x() + element_rect_.CenterPoint().x(),
114 container_rect.y() + element_rect_.bottom());
115 if (!container_rect.Contains(anchor))
116 return BubbleDelegateView::GetAnchorPoint();
117 return anchor;
118 }
119
120 void SpeechInputBubbleView::Init() {
82 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); 121 ResourceBundle& rb = ResourceBundle::GetSharedInstance();
83 const gfx::Font& font = rb.GetFont(ResourceBundle::MediumFont); 122 const gfx::Font& font = rb.GetFont(ResourceBundle::MediumFont);
84 123
85 heading_ = new views::Label( 124 heading_ = new views::Label(
86 l10n_util::GetStringUTF16(IDS_SPEECH_INPUT_BUBBLE_HEADING)); 125 l10n_util::GetStringUTF16(IDS_SPEECH_INPUT_BUBBLE_HEADING));
87 heading_->set_border(views::Border::CreateEmptyBorder( 126 heading_->set_border(views::Border::CreateEmptyBorder(
88 kBubbleHeadingVertMargin, 0, kBubbleHeadingVertMargin, 0)); 127 kBubbleHeadingVertMargin, 0, kBubbleHeadingVertMargin, 0));
89 heading_->SetFont(font); 128 heading_->SetFont(font);
90 heading_->SetHorizontalAlignment(views::Label::ALIGN_CENTER); 129 heading_->SetHorizontalAlignment(views::Label::ALIGN_CENTER);
91 heading_->SetText( 130 heading_->SetText(
(...skipping 17 matching lines...) Expand all
109 try_again_ = new views::NativeTextButton( 148 try_again_ = new views::NativeTextButton(
110 this, l10n_util::GetStringUTF16(IDS_SPEECH_INPUT_TRY_AGAIN)); 149 this, l10n_util::GetStringUTF16(IDS_SPEECH_INPUT_TRY_AGAIN));
111 AddChildView(try_again_); 150 AddChildView(try_again_);
112 151
113 mic_settings_ = new views::Link( 152 mic_settings_ = new views::Link(
114 l10n_util::GetStringUTF16(IDS_SPEECH_INPUT_MIC_SETTINGS)); 153 l10n_util::GetStringUTF16(IDS_SPEECH_INPUT_MIC_SETTINGS));
115 mic_settings_->set_listener(this); 154 mic_settings_->set_listener(this);
116 AddChildView(mic_settings_); 155 AddChildView(mic_settings_);
117 } 156 }
118 157
119 void ContentView::UpdateLayout(SpeechInputBubbleBase::DisplayMode mode, 158 void SpeechInputBubbleView::UpdateLayout(
120 const string16& message_text, 159 SpeechInputBubbleBase::DisplayMode mode,
121 const SkBitmap& image) { 160 const string16& message_text,
161 const SkBitmap& image) {
122 display_mode_ = mode; 162 display_mode_ = mode;
123 bool is_message = (mode == SpeechInputBubbleBase::DISPLAY_MODE_MESSAGE); 163 bool is_message = (mode == SpeechInputBubbleBase::DISPLAY_MODE_MESSAGE);
124 icon_->SetVisible(!is_message); 164 icon_->SetVisible(!is_message);
125 message_->SetVisible(is_message); 165 message_->SetVisible(is_message);
126 mic_settings_->SetVisible(is_message); 166 mic_settings_->SetVisible(is_message);
127 try_again_->SetVisible(is_message); 167 try_again_->SetVisible(is_message);
128 cancel_->SetVisible(mode != SpeechInputBubbleBase::DISPLAY_MODE_WARM_UP); 168 cancel_->SetVisible(mode != SpeechInputBubbleBase::DISPLAY_MODE_WARM_UP);
129 heading_->SetVisible(mode == SpeechInputBubbleBase::DISPLAY_MODE_RECORDING); 169 heading_->SetVisible(mode == SpeechInputBubbleBase::DISPLAY_MODE_RECORDING);
130 170
131 if (is_message) { 171 if (is_message) {
132 message_->SetText(message_text); 172 message_->SetText(message_text);
133 } else { 173 } else {
134 SetImage(image); 174 SetImage(image);
alicet1 2011/11/17 17:59:13 is this method needed anywhere else? otherwise jus
msw 2011/11/17 20:42:53 SetImage is also called by SpeechInputBubbleImpl::
135 } 175 }
136 176
137 if (icon_->IsVisible()) 177 if (icon_->IsVisible())
138 icon_->ResetImageSize(); 178 icon_->ResetImageSize();
139 179
140 // When moving from warming up to recording state, the size of the content 180 // When moving from warming up to recording state, the size of the content
141 // stays the same. So we wouldn't get a resize/layout call from the view 181 // stays the same. So we wouldn't get a resize/layout call from the view
142 // system and we do it ourselves. 182 // system and we do it ourselves.
143 if (GetPreferredSize() == size()) // |size()| here is the current size. 183 if (GetPreferredSize() == size()) // |size()| here is the current size.
144 Layout(); 184 Layout();
185
186 SizeToContents();
145 } 187 }
146 188
147 void ContentView::SetImage(const SkBitmap& image) { 189 void SpeechInputBubbleView::SetImage(const SkBitmap& image) {
148 icon_->SetImage(image); 190 icon_->SetImage(image);
149 } 191 }
150 192
151 void ContentView::ButtonPressed(views::Button* source, 193 void SpeechInputBubbleView::ButtonPressed(views::Button* source,
152 const views::Event& event) { 194 const views::Event& event) {
153 if (source == cancel_) { 195 if (source == cancel_) {
154 delegate_->InfoBubbleButtonClicked(SpeechInputBubble::BUTTON_CANCEL); 196 delegate_->InfoBubbleButtonClicked(SpeechInputBubble::BUTTON_CANCEL);
197 GetWidget()->RemoveObserver(this);
155 } else if (source == try_again_) { 198 } else if (source == try_again_) {
156 delegate_->InfoBubbleButtonClicked(SpeechInputBubble::BUTTON_TRY_AGAIN); 199 delegate_->InfoBubbleButtonClicked(SpeechInputBubble::BUTTON_TRY_AGAIN);
157 } else { 200 } else {
158 NOTREACHED() << "Unknown button"; 201 NOTREACHED() << "Unknown button";
159 } 202 }
160 } 203 }
161 204
162 void ContentView::LinkClicked(views::Link* source, int event_flags) { 205 void SpeechInputBubbleView::LinkClicked(views::Link* source, int event_flags) {
163 DCHECK_EQ(source, mic_settings_); 206 DCHECK_EQ(source, mic_settings_);
164 AudioManager::GetAudioManager()->ShowAudioInputSettings(); 207 AudioManager::GetAudioManager()->ShowAudioInputSettings();
165 } 208 }
166 209
167 gfx::Size ContentView::GetPreferredSize() { 210 gfx::Size SpeechInputBubbleView::GetPreferredSize() {
168 int width = heading_->GetPreferredSize().width(); 211 int width = heading_->GetPreferredSize().width();
169 int control_width = cancel_->GetPreferredSize().width(); 212 int control_width = cancel_->GetPreferredSize().width();
170 if (try_again_->IsVisible()) { 213 if (try_again_->IsVisible()) {
171 control_width += try_again_->GetPreferredSize().width() + 214 control_width += try_again_->GetPreferredSize().width() +
172 views::kRelatedButtonHSpacing; 215 views::kRelatedButtonHSpacing;
173 } 216 }
174 width = std::max(width, control_width); 217 width = std::max(width, control_width);
175 control_width = std::max(icon_->GetPreferredSize().width(), 218 control_width = std::max(icon_->GetPreferredSize().width(),
176 kIconLayoutMinWidth); 219 kIconLayoutMinWidth);
177 width = std::max(width, control_width); 220 width = std::max(width, control_width);
(...skipping 12 matching lines...) Expand all
190 if (icon_->IsVisible()) 233 if (icon_->IsVisible())
191 height += icon_->GetImage().height(); 234 height += icon_->GetImage().height();
192 if (mic_settings_->IsVisible()) 235 if (mic_settings_->IsVisible())
193 height += mic_settings_->GetPreferredSize().height(); 236 height += mic_settings_->GetPreferredSize().height();
194 width += kBubbleHorizMargin * 2; 237 width += kBubbleHorizMargin * 2;
195 height += kBubbleVertMargin * 2; 238 height += kBubbleVertMargin * 2;
196 239
197 return gfx::Size(width, height); 240 return gfx::Size(width, height);
198 } 241 }
199 242
200 void ContentView::Layout() { 243 void SpeechInputBubbleView::Layout() {
201 int x = kBubbleHorizMargin; 244 int x = kBubbleHorizMargin;
202 int y = kBubbleVertMargin; 245 int y = kBubbleVertMargin;
203 int available_width = width() - kBubbleHorizMargin * 2; 246 int available_width = width() - kBubbleHorizMargin * 2;
204 int available_height = height() - kBubbleVertMargin * 2; 247 int available_height = height() - kBubbleVertMargin * 2;
205 248
206 if (message_->IsVisible()) { 249 if (message_->IsVisible()) {
207 DCHECK(try_again_->IsVisible()); 250 DCHECK(try_again_->IsVisible());
208 251
209 int control_height = try_again_->GetPreferredSize().height(); 252 int control_height = try_again_->GetPreferredSize().height();
210 int try_again_width = try_again_->GetPreferredSize().width(); 253 int try_again_width = try_again_->GetPreferredSize().width();
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
242 if (cancel_->IsVisible()) { 285 if (cancel_->IsVisible()) {
243 control_height = cancel_->GetPreferredSize().height(); 286 control_height = cancel_->GetPreferredSize().height();
244 int width = cancel_->GetPreferredSize().width(); 287 int width = cancel_->GetPreferredSize().width();
245 cancel_->SetBounds(x + (available_width - width) / 2, y, width, 288 cancel_->SetBounds(x + (available_width - width) / 2, y, width,
246 control_height); 289 control_height);
247 } 290 }
248 } 291 }
249 } 292 }
250 293
251 // Implementation of SpeechInputBubble. 294 // Implementation of SpeechInputBubble.
252 class SpeechInputBubbleImpl 295 class SpeechInputBubbleImpl : public SpeechInputBubbleBase {
253 : public SpeechInputBubbleBase,
254 public BubbleDelegate {
255 public: 296 public:
256 SpeechInputBubbleImpl(TabContents* tab_contents, 297 SpeechInputBubbleImpl(TabContents* tab_contents,
257 Delegate* delegate, 298 Delegate* delegate,
258 const gfx::Rect& element_rect); 299 const gfx::Rect& element_rect);
259 virtual ~SpeechInputBubbleImpl(); 300 virtual ~SpeechInputBubbleImpl();
260 301
261 // SpeechInputBubble methods. 302 // SpeechInputBubble methods.
262 virtual void Show() OVERRIDE; 303 virtual void Show() OVERRIDE;
263 virtual void Hide() OVERRIDE; 304 virtual void Hide() OVERRIDE;
264 305
265 // SpeechInputBubbleBase methods. 306 // SpeechInputBubbleBase methods.
266 virtual void UpdateLayout() OVERRIDE; 307 virtual void UpdateLayout() OVERRIDE;
267 virtual void UpdateImage() OVERRIDE; 308 virtual void UpdateImage() OVERRIDE;
268 309
269 // Returns the screen rectangle to use as the info bubble's target.
270 // |element_rect| is the html element's bounds in page coordinates.
271 gfx::Rect GetInfoBubbleTarget(const gfx::Rect& element_rect);
272
273 // BubbleDelegate
274 virtual void BubbleClosing(Bubble* bubble, bool closed_by_escape) OVERRIDE;
275 virtual bool CloseOnEscape() OVERRIDE;
276 virtual bool FadeInOnShow() OVERRIDE;
277
278 private: 310 private:
279 Delegate* delegate_; 311 Delegate* delegate_;
280 Bubble* bubble_; 312 SpeechInputBubbleView* bubble_;
281 ContentView* bubble_content_;
282 gfx::Rect element_rect_; 313 gfx::Rect element_rect_;
283 314
284 // Set to true if the object is being destroyed normally instead of the
285 // user clicking outside the window causing it to close automatically.
286 bool did_invoke_close_;
287
288 DISALLOW_COPY_AND_ASSIGN(SpeechInputBubbleImpl); 315 DISALLOW_COPY_AND_ASSIGN(SpeechInputBubbleImpl);
289 }; 316 };
290 317
291 SpeechInputBubbleImpl::SpeechInputBubbleImpl(TabContents* tab_contents, 318 SpeechInputBubbleImpl::SpeechInputBubbleImpl(TabContents* tab_contents,
292 Delegate* delegate, 319 Delegate* delegate,
293 const gfx::Rect& element_rect) 320 const gfx::Rect& element_rect)
294 : SpeechInputBubbleBase(tab_contents), 321 : SpeechInputBubbleBase(tab_contents),
295 delegate_(delegate), 322 delegate_(delegate),
296 bubble_(NULL), 323 bubble_(NULL),
297 bubble_content_(NULL), 324 element_rect_(element_rect) {
298 element_rect_(element_rect),
299 did_invoke_close_(false) {
300 } 325 }
301 326
302 SpeechInputBubbleImpl::~SpeechInputBubbleImpl() { 327 SpeechInputBubbleImpl::~SpeechInputBubbleImpl() {
303 did_invoke_close_ = true;
304 Hide(); 328 Hide();
305 } 329 }
306 330
307 gfx::Rect SpeechInputBubbleImpl::GetInfoBubbleTarget(
308 const gfx::Rect& element_rect) {
309 gfx::Rect container_rect;
310 tab_contents()->GetContainerBounds(&container_rect);
311 return gfx::Rect(
312 container_rect.x() + element_rect.right() - kBubbleTargetOffsetX,
313 container_rect.y() + element_rect.bottom(), 1, 1);
314 }
315
316 void SpeechInputBubbleImpl::BubbleClosing(Bubble* bubble,
317 bool closed_by_escape) {
318 bubble_ = NULL;
319 bubble_content_ = NULL;
320 if (!did_invoke_close_)
321 delegate_->InfoBubbleFocusChanged();
alicet1 2011/11/17 17:59:13 I think you moved this to be called when activatio
msw 2011/11/17 20:42:53 In general you would be right to move such code to
322 }
323
324 bool SpeechInputBubbleImpl::CloseOnEscape() {
alicet1 2011/11/17 17:59:13 this doesn't want close on esc? we should honor?
msw 2011/11/17 20:42:53 Yup, I call set_close_on_esc(false); in the Speech
325 return false;
326 }
327
328 bool SpeechInputBubbleImpl::FadeInOnShow() {
329 return false;
330 }
331
332 void SpeechInputBubbleImpl::Show() { 331 void SpeechInputBubbleImpl::Show() {
333 if (bubble_) 332 if (bubble_)
334 return; // nothing to do, already visible. 333 return;
335 334
336 bubble_content_ = new ContentView(delegate_); 335 // Anchor to the location icon view, in case |element_rect| is offscreen.
336 Profile* profile =
337 Profile::FromBrowserContext(tab_contents()->browser_context());
338 Browser* browser = Browser::GetOrCreateTabbedBrowser(profile);
339 BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser);
340 views::View* icon = browser_view->GetLocationBarView()->location_icon_view();
341 bubble_ = new SpeechInputBubbleView(delegate_, icon, element_rect_,
342 tab_contents());
343 views::BubbleDelegateView::CreateBubble(bubble_);
337 UpdateLayout(); 344 UpdateLayout();
338 345 bubble_->Show();
339 views::Widget* toplevel_widget =
340 views::Widget::GetTopLevelWidgetForNativeView(
341 tab_contents()->view()->GetNativeView());
342 if (toplevel_widget) {
alicet1 2011/11/17 17:59:13 how come you don't have to check for this now? I t
msw 2011/11/17 20:42:53 This ensured that the toplevel widget was availabl
343 gfx::Rect container_rect;
344 tab_contents()->GetContainerBounds(&container_rect);
345 gfx::Rect target_rect = GetInfoBubbleTarget(element_rect_);
346 if (!container_rect.Contains(target_rect.x(), target_rect.y())) {
347 // Target is not in screen view, so point to page icon in omnibox.
348 Profile* profile =
349 Profile::FromBrowserContext(tab_contents()->browser_context());
350 Browser* browser = Browser::GetOrCreateTabbedBrowser(profile);
351 BrowserView* browser_view =
352 BrowserView::GetBrowserViewForBrowser(browser);
353 gfx::Point point;
354 if (base::i18n::IsRTL()) {
355 int width = browser_view->toolbar()->location_bar()->width();
356 point = gfx::Point(width - kIconHorizontalOffset, 0);
357 }
358 point.Offset(0, kIconVerticalOffset);
359 views::View::ConvertPointToScreen(browser_view->toolbar()->location_bar(),
360 &point);
361 target_rect = browser_view->toolbar()->location_bar()->bounds();
362 target_rect.set_origin(point);
363 target_rect.set_width(kIconHorizontalOffset);
364 }
365 bubble_ = Bubble::Show(toplevel_widget,
366 target_rect,
367 views::BubbleBorder::TOP_LEFT,
368 views::BubbleBorder::ALIGN_ARROW_TO_MID_ANCHOR,
369 bubble_content_, this);
370 // We don't want fade outs when closing because it makes speech recognition
371 // appear slower than it is. Also setting it to false allows |Close| to
372 // destroy the bubble immediately instead of waiting for the fade animation
373 // to end so the caller can manage this object's life cycle like a normal
374 // stack based or member variable object.
375 bubble_->set_fade_away_on_close(false);
376 }
377 } 346 }
378 347
379 void SpeechInputBubbleImpl::Hide() { 348 void SpeechInputBubbleImpl::Hide() {
380 if (bubble_) 349 if (bubble_)
381 bubble_->Close(); 350 bubble_->GetWidget()->Close();
351 bubble_ = NULL;
382 } 352 }
383 353
384 void SpeechInputBubbleImpl::UpdateLayout() { 354 void SpeechInputBubbleImpl::UpdateLayout() {
385 if (bubble_content_) 355 if (bubble_)
386 bubble_content_->UpdateLayout(display_mode(), message_text(), icon_image()); 356 bubble_->UpdateLayout(display_mode(), message_text(), icon_image());
387 if (bubble_) // Will be null on first call.
388 bubble_->SizeToContents();
389 } 357 }
390 358
391 void SpeechInputBubbleImpl::UpdateImage() { 359 void SpeechInputBubbleImpl::UpdateImage() {
392 if (bubble_content_) 360 if (bubble_)
393 bubble_content_->SetImage(icon_image()); 361 bubble_->SetImage(icon_image());
394 } 362 }
395 363
396 } // namespace 364 } // namespace
397 365
398 SpeechInputBubble* SpeechInputBubble::CreateNativeBubble( 366 SpeechInputBubble* SpeechInputBubble::CreateNativeBubble(
399 TabContents* tab_contents, 367 TabContents* tab_contents,
400 SpeechInputBubble::Delegate* delegate, 368 SpeechInputBubble::Delegate* delegate,
401 const gfx::Rect& element_rect) { 369 const gfx::Rect& element_rect) {
402 return new SpeechInputBubbleImpl(tab_contents, delegate, element_rect); 370 return new SpeechInputBubbleImpl(tab_contents, delegate, element_rect);
403 } 371 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698