172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// Use of this source code is governed by a BSD-style license that can be 3bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// found in the LICENSE file. 4bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 5bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "chrome/browser/speech/speech_input_bubble.h" 6bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 7bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "base/utf_string_conversions.h" 8dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/browser/ui/gtk/gtk_chrome_link_button.h" 9ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/gtk/gtk_theme_service.h" 1072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/gtk_util.h" 1172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/info_bubble_gtk.h" 1272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/owned_widget_gtk.h" 13dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/tab_contents/tab_contents.h" 14bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "grit/generated_resources.h" 15bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "grit/theme_resources.h" 16dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "media/audio/audio_manager.h" 1772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/l10n/l10n_util.h" 1872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/resource/resource_bundle.h" 1972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/gtk_util.h" 2072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/rect.h" 21bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 22bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsennamespace { 23bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 24dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenconst int kBubbleControlVerticalSpacing = 5; 25bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenconst int kBubbleControlHorizontalSpacing = 20; 26dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenconst int kIconHorizontalPadding = 10; 27bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenconst int kButtonBarHorizontalSpacing = 10; 28bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 29bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// Use black for text labels since the bubble has white background. 30513209b27ff55e2841eac0e4120199c23acce758Ben Murdochconst GdkColor kLabelTextColor = gtk_util::kGdkBlack; 31bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 32bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// Implementation of SpeechInputBubble for GTK. This shows a speech input 33bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// info bubble on screen. 34bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenclass SpeechInputBubbleGtk 35bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen : public SpeechInputBubbleBase, 36bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen public InfoBubbleGtkDelegate { 37bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen public: 38bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen SpeechInputBubbleGtk(TabContents* tab_contents, 39bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen Delegate* delegate, 40bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen const gfx::Rect& element_rect); 41bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen ~SpeechInputBubbleGtk(); 42bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 43bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen private: 44bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // InfoBubbleDelegate methods. 45bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen virtual void InfoBubbleClosing(InfoBubbleGtk* info_bubble, 46bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen bool closed_by_escape); 47bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 48bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // SpeechInputBubble methods. 49bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen virtual void Show(); 50bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen virtual void Hide(); 51bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen virtual void UpdateLayout(); 52ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen virtual void UpdateImage(); 53bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 54bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen CHROMEGTK_CALLBACK_0(SpeechInputBubbleGtk, void, OnCancelClicked); 55bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen CHROMEGTK_CALLBACK_0(SpeechInputBubbleGtk, void, OnTryAgainClicked); 56dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen CHROMEGTK_CALLBACK_0(SpeechInputBubbleGtk, void, OnMicSettingsClicked); 57bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 58bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen Delegate* delegate_; 59bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen InfoBubbleGtk* info_bubble_; 60bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen gfx::Rect element_rect_; 61bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen bool did_invoke_close_; 62bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 63bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen GtkWidget* label_; 64ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen GtkWidget* cancel_button_; 65bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen GtkWidget* try_again_button_; 66bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen GtkWidget* icon_; 67ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen GtkWidget* icon_container_; 68dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen GtkWidget* mic_settings_; 69bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 70bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen DISALLOW_COPY_AND_ASSIGN(SpeechInputBubbleGtk); 71bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}; 72bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 73bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian MonsenSpeechInputBubbleGtk::SpeechInputBubbleGtk(TabContents* tab_contents, 74bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen Delegate* delegate, 75bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen const gfx::Rect& element_rect) 763f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen : SpeechInputBubbleBase(tab_contents), 773f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen delegate_(delegate), 78bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen info_bubble_(NULL), 79bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen element_rect_(element_rect), 80bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen did_invoke_close_(false), 81bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen label_(NULL), 82ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen cancel_button_(NULL), 83bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen try_again_button_(NULL), 84dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen icon_(NULL), 85ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen icon_container_(NULL), 86dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen mic_settings_(NULL) { 87bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 88bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 89bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian MonsenSpeechInputBubbleGtk::~SpeechInputBubbleGtk() { 90bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // The |Close| call below invokes our |InfoBubbleClosing| method. Since we 91bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // were destroyed by the caller we don't need to call them back, hence set 92bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // this flag here. 93bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen did_invoke_close_ = true; 94bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen Hide(); 95bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 96bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 97bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid SpeechInputBubbleGtk::InfoBubbleClosing(InfoBubbleGtk* info_bubble, 98bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen bool closed_by_escape) { 99bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen info_bubble_ = NULL; 100bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen if (!did_invoke_close_) 101bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen delegate_->InfoBubbleFocusChanged(); 102bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 103bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 104bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid SpeechInputBubbleGtk::OnCancelClicked(GtkWidget* widget) { 105bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen delegate_->InfoBubbleButtonClicked(BUTTON_CANCEL); 106bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 107bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 108bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid SpeechInputBubbleGtk::OnTryAgainClicked(GtkWidget* widget) { 109bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen delegate_->InfoBubbleButtonClicked(BUTTON_TRY_AGAIN); 110bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 111bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 112dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid SpeechInputBubbleGtk::OnMicSettingsClicked(GtkWidget* widget) { 113dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen AudioManager::GetAudioManager()->ShowAudioInputSettings(); 114dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 115dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 116bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid SpeechInputBubbleGtk::Show() { 117bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen if (info_bubble_) 118bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen return; // Nothing further to do since the bubble is already visible. 119bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 120bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // We use a vbox to arrange the controls (label, image, button bar) vertically 121bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // and the button bar is a hbox holding the 2 buttons (try again and cancel). 122bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // To get horizontal space around them we place this vbox with padding in a 123bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // GtkAlignment below. 124dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen GtkWidget* vbox = gtk_vbox_new(FALSE, 0); 125bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 126bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // The icon with a some padding on the left and right. 127ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen icon_container_ = gtk_alignment_new(0, 0, 0, 0); 128bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen icon_ = gtk_image_new(); 129ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen gtk_container_add(GTK_CONTAINER(icon_container_), icon_); 130ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen gtk_box_pack_start(GTK_BOX(vbox), icon_container_, FALSE, FALSE, 131dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen kBubbleControlVerticalSpacing); 132dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 133dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen label_ = gtk_label_new(NULL); 134dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen gtk_util::SetLabelColor(label_, &kLabelTextColor); 135dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen gtk_box_pack_start(GTK_BOX(vbox), label_, FALSE, FALSE, 136dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen kBubbleControlVerticalSpacing); 137dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 138dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (AudioManager::GetAudioManager()->CanShowAudioInputSettings()) { 139dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen mic_settings_ = gtk_chrome_link_button_new( 140dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen l10n_util::GetStringUTF8(IDS_SPEECH_INPUT_MIC_SETTINGS).c_str()); 141dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen gtk_box_pack_start(GTK_BOX(vbox), mic_settings_, FALSE, FALSE, 142dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen kBubbleControlVerticalSpacing); 143dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen g_signal_connect(mic_settings_, "clicked", 144dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen G_CALLBACK(&OnMicSettingsClickedThunk), this); 145dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 146bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 147bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen GtkWidget* button_bar = gtk_hbox_new(FALSE, kButtonBarHorizontalSpacing); 148dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen gtk_box_pack_start(GTK_BOX(vbox), button_bar, FALSE, FALSE, 149dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen kBubbleControlVerticalSpacing); 150bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 151ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen cancel_button_ = gtk_button_new_with_label( 152bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen l10n_util::GetStringUTF8(IDS_CANCEL).c_str()); 153ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen gtk_box_pack_start(GTK_BOX(button_bar), cancel_button_, TRUE, FALSE, 0); 154ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen g_signal_connect(cancel_button_, "clicked", 155bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen G_CALLBACK(&OnCancelClickedThunk), this); 156bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 157bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen try_again_button_ = gtk_button_new_with_label( 158bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen l10n_util::GetStringUTF8(IDS_SPEECH_INPUT_TRY_AGAIN).c_str()); 159bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen gtk_box_pack_start(GTK_BOX(button_bar), try_again_button_, TRUE, FALSE, 0); 160bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen g_signal_connect(try_again_button_, "clicked", 161bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen G_CALLBACK(&OnTryAgainClickedThunk), this); 162bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 163bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen GtkWidget* content = gtk_alignment_new(0, 0, 0, 0); 164bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen gtk_alignment_set_padding(GTK_ALIGNMENT(content), 165bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen kBubbleControlVerticalSpacing, kBubbleControlVerticalSpacing, 166bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen kBubbleControlHorizontalSpacing, kBubbleControlHorizontalSpacing); 167bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen gtk_container_add(GTK_CONTAINER(content), vbox); 168bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 169ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen GtkThemeService* theme_provider = GtkThemeService::GetFrom( 1703f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen tab_contents()->profile()); 171dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen gfx::Rect rect( 172dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen element_rect_.x() + element_rect_.width() - kBubbleTargetOffsetX, 173dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen element_rect_.y() + element_rect_.height(), 1, 1); 1743f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen info_bubble_ = InfoBubbleGtk::Show(tab_contents()->GetNativeView(), 175bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen &rect, 176bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen content, 177bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen InfoBubbleGtk::ARROW_LOCATION_TOP_LEFT, 178bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen false, // match_system_theme 179bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen true, // grab_input 180bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen theme_provider, 181bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen this); 182bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 183bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen UpdateLayout(); 184bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 185bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 186bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid SpeechInputBubbleGtk::Hide() { 187bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen if (info_bubble_) 188bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen info_bubble_->Close(); 189bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 190bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 191bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid SpeechInputBubbleGtk::UpdateLayout() { 192bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen if (!info_bubble_) 193bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen return; 194bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 195bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen if (display_mode() == DISPLAY_MODE_MESSAGE) { 196bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // Message text and the Try Again + Cancel buttons are visible, hide the 197bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // icon. 198bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen gtk_label_set_text(GTK_LABEL(label_), 199bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen UTF16ToUTF8(message_text()).c_str()); 200dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen gtk_widget_show(label_); 201bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen gtk_widget_show(try_again_button_); 202dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (mic_settings_) 203dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen gtk_widget_show(mic_settings_); 204bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen gtk_widget_hide(icon_); 205bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen } else { 206bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // Heading text, icon and cancel button are visible, hide the Try Again 207bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // button. 208ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen gtk_label_set_text(GTK_LABEL(label_), 209ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen l10n_util::GetStringUTF8(IDS_SPEECH_INPUT_BUBBLE_HEADING).c_str()); 210bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen if (display_mode() == DISPLAY_MODE_RECORDING) { 211dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen gtk_widget_show(label_); 212201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch } else { 213dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen gtk_widget_hide(label_); 214bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen } 215ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen UpdateImage(); 216bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen gtk_widget_show(icon_); 217bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen gtk_widget_hide(try_again_button_); 218dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (mic_settings_) 219dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen gtk_widget_hide(mic_settings_); 220ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (display_mode() == DISPLAY_MODE_WARM_UP) { 221ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen gtk_widget_hide(cancel_button_); 222ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 223ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // The text label and cancel button are hidden in this mode, but we want 224ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // the popup to appear the same size as it would once recording starts, 225ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // so as to reduce UI jank when recording starts. So we calculate the 226ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // difference in size between the two sets of controls and add that as 227ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // padding around the icon here. 228ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen GtkRequisition cancel_size; 229ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen gtk_widget_get_child_requisition(cancel_button_, &cancel_size); 230ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen GtkRequisition label_size; 231ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen gtk_widget_get_child_requisition(label_, &label_size); 232ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SkBitmap* volume = ResourceBundle::GetSharedInstance().GetBitmapNamed( 233ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen IDR_SPEECH_INPUT_MIC_EMPTY); 234ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int desired_width = std::max(volume->width(), cancel_size.width) + 235ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen kIconHorizontalPadding * 2; 236ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int desired_height = volume->height() + label_size.height + 237ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen cancel_size.height + 238ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen kBubbleControlVerticalSpacing * 2; 239ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int diff_width = desired_width - icon_image().width(); 240ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int diff_height = desired_height - icon_image().height(); 241ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen gtk_alignment_set_padding(GTK_ALIGNMENT(icon_container_), 242ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen diff_height / 2, diff_height - diff_height / 2, 243ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen diff_width / 2, diff_width - diff_width / 2); 244ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } else { 245ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Reset the padding done above. 246ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen gtk_alignment_set_padding(GTK_ALIGNMENT(icon_container_), 0, 0, 247ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen kIconHorizontalPadding, kIconHorizontalPadding); 248ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen gtk_widget_show(cancel_button_); 249ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 250bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen } 251bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 252bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 253ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid SpeechInputBubbleGtk::UpdateImage() { 254ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SkBitmap image = icon_image(); 25572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (image.isNull() || !info_bubble_) 256bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen return; 257bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 258bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(&image); 259bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen gtk_image_set_from_pixbuf(GTK_IMAGE(icon_), pixbuf); 260bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen g_object_unref(pixbuf); 261bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 262bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 263bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} // namespace 264bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 265bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian MonsenSpeechInputBubble* SpeechInputBubble::CreateNativeBubble( 266bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen TabContents* tab_contents, 267bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen Delegate* delegate, 268bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen const gfx::Rect& element_rect) { 269bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen return new SpeechInputBubbleGtk(tab_contents, delegate, element_rect); 270bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 271bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 272