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