| // Copyright (c) 2012 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. |
| |
| #import <Cocoa/Cocoa.h> |
| |
| #include "chrome/browser/speech/speech_recognition_bubble.h" |
| |
| #import "base/mac/scoped_nsobject.h" |
| #include "chrome/browser/ui/browser.h" |
| #include "chrome/browser/ui/cocoa/browser_window_cocoa.h" |
| #include "chrome/browser/ui/cocoa/browser_window_controller.h" |
| #include "chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h" |
| #import "chrome/browser/ui/cocoa/speech_recognition_window_controller.h" |
| #include "content/public/browser/web_contents.h" |
| #include "content/public/browser/web_contents_view.h" |
| #include "ui/gfx/image/image_skia_util_mac.h" |
| |
| using content::WebContents; |
| |
| namespace { |
| |
| // A class to bridge between the speech recognition C++ code and the Objective-C |
| // bubble implementation. See chrome/browser/speech/speech_recognition_bubble.h |
| // for more information on how this gets used. |
| class SpeechRecognitionBubbleImpl : public SpeechRecognitionBubbleBase { |
| public: |
| SpeechRecognitionBubbleImpl(WebContents* web_contents, |
| Delegate* delegate, |
| const gfx::Rect& element_rect); |
| virtual ~SpeechRecognitionBubbleImpl(); |
| virtual void Show() OVERRIDE; |
| virtual void Hide() OVERRIDE; |
| virtual void UpdateLayout() OVERRIDE; |
| virtual void UpdateImage() OVERRIDE; |
| |
| private: |
| base::scoped_nsobject<SpeechRecognitionWindowController> window_; |
| Delegate* delegate_; |
| gfx::Rect element_rect_; |
| }; |
| |
| SpeechRecognitionBubbleImpl::SpeechRecognitionBubbleImpl( |
| WebContents* web_contents, |
| Delegate* delegate, |
| const gfx::Rect& element_rect) |
| : SpeechRecognitionBubbleBase(web_contents), |
| delegate_(delegate), |
| element_rect_(element_rect) { |
| } |
| |
| SpeechRecognitionBubbleImpl::~SpeechRecognitionBubbleImpl() { |
| if (window_.get()) |
| [window_.get() close]; |
| } |
| |
| void SpeechRecognitionBubbleImpl::UpdateImage() { |
| if (window_.get()) |
| [window_.get() setImage:gfx::NSImageFromImageSkia(icon_image())]; |
| } |
| |
| void SpeechRecognitionBubbleImpl::Show() { |
| if (window_.get()) { |
| [window_.get() show]; |
| return; |
| } |
| |
| // Find the screen coordinates for the given tab and position the bubble's |
| // arrow anchor point inside that to point at the bottom-left of the html |
| // input element rect if the position is valid, otherwise point it towards |
| // the page icon in the omnibox. |
| gfx::NativeView view = GetWebContents()->GetView()->GetNativeView(); |
| NSWindow* parent_window = [view window]; |
| NSRect tab_bounds = [view bounds]; |
| int anchor_x = tab_bounds.origin.x + element_rect_.x() + |
| element_rect_.width() - kBubbleTargetOffsetX; |
| int anchor_y = tab_bounds.origin.y + tab_bounds.size.height - |
| element_rect_.y() - element_rect_.height(); |
| |
| NSPoint anchor = NSMakePoint(anchor_x, anchor_y); |
| if (NSPointInRect(anchor, tab_bounds)) { |
| // Good, convert to window coordinates. |
| anchor = [view convertPoint:anchor toView:nil]; |
| } else { |
| LocationBarViewMac* locationBar = |
| [[parent_window windowController] locationBarBridge]; |
| |
| if (locationBar) { |
| anchor = locationBar->GetPageInfoBubblePoint(); |
| } else { |
| // This is very rare, but possible. Just use the top-left corner. |
| // See http://crbug.com/119237 |
| anchor = NSMakePoint(NSMinX(tab_bounds), NSMaxY(tab_bounds)); |
| anchor = [view convertPoint:anchor toView:nil]; |
| } |
| } |
| |
| anchor = [parent_window convertBaseToScreen:anchor]; |
| |
| window_.reset([[SpeechRecognitionWindowController alloc] |
| initWithParentWindow:parent_window |
| delegate:delegate_ |
| anchoredAt:anchor]); |
| |
| UpdateLayout(); |
| [window_.get() show]; |
| } |
| |
| void SpeechRecognitionBubbleImpl::Hide() { |
| if (!window_.get()) |
| return; |
| |
| [window_.get() close]; |
| window_.reset(); |
| } |
| |
| void SpeechRecognitionBubbleImpl::UpdateLayout() { |
| if (!window_.get()) |
| return; |
| |
| [window_.get() updateLayout:display_mode() |
| messageText:message_text() |
| iconImage:gfx::NSImageFromImageSkia(icon_image())]; |
| } |
| |
| } // namespace |
| |
| SpeechRecognitionBubble* SpeechRecognitionBubble::CreateNativeBubble( |
| WebContents* web_contents, |
| Delegate* delegate, |
| const gfx::Rect& element_rect) { |
| return new SpeechRecognitionBubbleImpl(web_contents, delegate, element_rect); |
| } |