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 3 // found in the LICENSE file. 4 5 #import <Cocoa/Cocoa.h> 6 7 #include "chrome/browser/speech/speech_input_bubble.h" 8 9 #import "base/memory/scoped_nsobject.h" 10 #import "chrome/browser/ui/cocoa/speech_input_window_controller.h" 11 #include "content/browser/tab_contents/tab_contents.h" 12 #include "content/browser/tab_contents/tab_contents_view.h" 13 #include "skia/ext/skia_utils_mac.h" 14 15 namespace { 16 17 // A class to bridge between the speech recognition C++ code and the Objective-C 18 // bubble implementation. See chrome/browser/speech/speech_input_bubble.h for 19 // more information on how this gets used. 20 class SpeechInputBubbleImpl : public SpeechInputBubbleBase { 21 public: 22 SpeechInputBubbleImpl(TabContents* tab_contents, 23 Delegate* delegate, 24 const gfx::Rect& element_rect); 25 virtual ~SpeechInputBubbleImpl(); 26 virtual void Show(); 27 virtual void Hide(); 28 virtual void UpdateLayout(); 29 virtual void UpdateImage(); 30 31 private: 32 scoped_nsobject<SpeechInputWindowController> window_; 33 Delegate* delegate_; 34 gfx::Rect element_rect_; 35 }; 36 37 SpeechInputBubbleImpl::SpeechInputBubbleImpl(TabContents* tab_contents, 38 Delegate* delegate, 39 const gfx::Rect& element_rect) 40 : SpeechInputBubbleBase(tab_contents), 41 delegate_(delegate), 42 element_rect_(element_rect) { 43 } 44 45 SpeechInputBubbleImpl::~SpeechInputBubbleImpl() { 46 if (window_.get()) 47 [window_.get() close]; 48 } 49 50 void SpeechInputBubbleImpl::UpdateImage() { 51 if (window_.get()) 52 [window_.get() setImage:gfx::SkBitmapToNSImage(icon_image())]; 53 } 54 55 void SpeechInputBubbleImpl::Show() { 56 if (window_.get()) { 57 [window_.get() show]; 58 return; 59 } 60 61 // Find the screen coordinates for the given tab and position the bubble's 62 // arrow anchor point inside that to point at the bottom-left of the html 63 // input element rect. 64 gfx::NativeView view = tab_contents()->view()->GetNativeView(); 65 NSRect tab_bounds = [view bounds]; 66 int anchor_x = tab_bounds.origin.x + element_rect_.x() + 67 element_rect_.width() - kBubbleTargetOffsetX; 68 int anchor_y = tab_bounds.origin.y + tab_bounds.size.height - 69 element_rect_.y() - element_rect_.height(); 70 NSPoint anchor = NSMakePoint(anchor_x, anchor_y); 71 anchor = [view convertPoint:anchor toView:nil]; 72 anchor = [[view window] convertBaseToScreen:anchor]; 73 74 window_.reset([[SpeechInputWindowController alloc] 75 initWithParentWindow:tab_contents()->view()->GetTopLevelNativeWindow() 76 delegate:delegate_ 77 anchoredAt:anchor]); 78 79 UpdateLayout(); 80 [window_.get() show]; 81 } 82 83 void SpeechInputBubbleImpl::Hide() { 84 if (!window_.get()) 85 return; 86 87 [window_.get() close]; 88 window_.reset(); 89 } 90 91 void SpeechInputBubbleImpl::UpdateLayout() { 92 if (!window_.get()) 93 return; 94 95 [window_.get() updateLayout:display_mode() 96 messageText:message_text() 97 iconImage:gfx::SkBitmapToNSImage(icon_image())]; 98 } 99 100 } // namespace 101 102 SpeechInputBubble* SpeechInputBubble::CreateNativeBubble( 103 TabContents* tab_contents, 104 Delegate* delegate, 105 const gfx::Rect& element_rect) { 106 return new SpeechInputBubbleImpl(tab_contents, delegate, element_rect); 107 } 108 109