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

Unified Diff: chrome/browser/speech/speech_input_extension_notification_ui.cc

Issue 8386074: Add a tray notification UI for speech input recording in the extension API. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: requested file renames and api constants refactor. 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/speech/speech_input_extension_notification_ui.cc
diff --git a/chrome/browser/speech/speech_input_extension_notification_ui.cc b/chrome/browser/speech/speech_input_extension_notification_ui.cc
new file mode 100644
index 0000000000000000000000000000000000000000..130a468e4bc13079b492ee59bdf08836aeffde49
--- /dev/null
+++ b/chrome/browser/speech/speech_input_extension_notification_ui.cc
@@ -0,0 +1,166 @@
+// Copyright (c) 2011 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.
+
+#include "chrome/browser/speech/speech_input_extension_notification_ui.h"
+
+#include "base/lazy_instance.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/status_icons/status_icon.h"
+#include "chrome/browser/status_icons/status_tray.h"
+#include "chrome/common/extensions/extension.h"
+#include "grit/chromium_strings.h"
+#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas_skia.h"
+#include "ui/gfx/rect.h"
+#include "ui/gfx/skbitmap_operations.h"
+
+namespace {
+
+// A lazily initialized singleton to hold all the images used by the
+// notification icon and safely destroy them on exit.
+class NotificationTrayImages {
+ public:
+ SkBitmap* mic_full() { return mic_full_; }
+ SkBitmap* mic_empty() { return mic_empty_; }
+ SkBitmap* balloon_icon() { return balloon_icon_; }
+
+ private:
+ // Private constructor to enforce singleton.
+ friend struct base::DefaultLazyInstanceTraits<NotificationTrayImages>;
+ NotificationTrayImages();
+
+ // These bitmaps are owned by ResourceBundle and need not be destroyed.
+ SkBitmap* mic_full_; // Tray mic image with full volume.
+ SkBitmap* mic_empty_; // Tray mic image with zero volume.
+ SkBitmap* balloon_icon_; // High resolution mic for the notification balloon.
+};
+
+NotificationTrayImages::NotificationTrayImages() {
+ int icon_ids[] = {
+#if defined(OS_WIN)
+ IDR_SPEECH_INPUT_TRAY_WINDOWS_MIC_EMPTY,
Satish 2011/11/07 18:16:31 any reason why we need 3 different set of IDs? cou
Leandro Graciá Gil 2011/11/07 19:34:42 Done.
+ IDR_SPEECH_INPUT_TRAY_WINDOWS_MIC_FULL,
+#elif defined(OS_MACOSX)
+ IDR_SPEECH_INPUT_TRAY_MACOSX_MIC_EMPTY,
+ IDR_SPEECH_INPUT_TRAY_MACOSX_MIC_FULL,
+#else
Satish 2011/11/07 18:16:31 can you make this into an explicit linux & chrome
Leandro Graciá Gil 2011/11/07 19:34:42 Done.
+ // Linux and Chrome OS icons.
+ IDR_SPEECH_INPUT_TRAY_LINUX_MIC_EMPTY,
+ IDR_SPEECH_INPUT_TRAY_LINUX_MIC_FULL,
+#endif
+ };
+
+ mic_empty_ = ResourceBundle::GetSharedInstance().GetBitmapNamed(icon_ids[0]);
+ mic_full_ = ResourceBundle::GetSharedInstance().GetBitmapNamed(icon_ids[1]);
+ balloon_icon_ = ResourceBundle::GetSharedInstance().GetBitmapNamed(
+ IDR_SPEECH_INPUT_TRAY_BALLOON_ICON);
+}
+
+base::LazyInstance<NotificationTrayImages> g_images(base::LINKER_INITIALIZED);
+
+} // namespace
+
+SpeechInputExtensionNotificationUI::SpeechInputExtensionNotificationUI(
+ Profile* profile)
+ : profile_(profile),
+ tray_icon_(NULL) {
+ mic_image_.reset(new SkBitmap());
+ mic_image_->setConfig(SkBitmap::kARGB_8888_Config,
+ g_images.Get().mic_empty()->width(),
+ g_images.Get().mic_empty()->height());
+ mic_image_->allocPixels();
+
+ buffer_image_.reset(new SkBitmap());
+ buffer_image_->setConfig(SkBitmap::kARGB_8888_Config,
+ g_images.Get().mic_empty()->width(),
+ g_images.Get().mic_empty()->height());
+ buffer_image_->allocPixels();
+}
+
+SpeechInputExtensionNotificationUI::~SpeechInputExtensionNotificationUI() {
+}
+
+void SpeechInputExtensionNotificationUI::DrawVolume(
+ SkCanvas* canvas,
+ const SkBitmap& bitmap,
+ float volume) {
+ buffer_image_->eraseARGB(0, 0, 0, 0);
+
+ int width = mic_image_->width();
+ int height = mic_image_->height();
+ SkCanvas buffer_canvas(*buffer_image_);
+
+ buffer_canvas.save();
Satish 2011/11/07 18:16:31 since this is a scoped canvas and gets destroyed o
Leandro Graciá Gil 2011/11/07 19:34:42 Done.
+ const int kVolumeSteps = 6;
Satish 2011/11/07 18:16:31 move this to an anonymous namespace constant
Leandro Graciá Gil 2011/11/07 19:34:42 Done.
+ SkScalar clip_top =
+ (((1.0f - volume) * (height * (kVolumeSteps + 1))) - height) /
+ kVolumeSteps;
+ buffer_canvas.clipRect(SkRect::MakeLTRB(0, clip_top,
+ SkIntToScalar(width), SkIntToScalar(height)));
+ buffer_canvas.drawBitmap(bitmap, 0, 0);
+ buffer_canvas.restore();
+
+ canvas->drawBitmap(*buffer_image_.get(), 0, 0);
+}
+
+void SpeechInputExtensionNotificationUI::SetVUMeterVolume(float volume) {
+ if (!tray_icon_)
+ return;
+
+ mic_image_->eraseARGB(0, 0, 0, 0);
+ SkCanvas canvas(*mic_image_);
+
+ // Draw the empty volume image first and the current volume image on top.
+ canvas.drawBitmap(*g_images.Get().mic_empty(), 0, 0);
+ DrawVolume(&canvas, *g_images.Get().mic_full(), volume);
+
+ tray_icon_->SetImage(*mic_image_.get());
+}
+
+void SpeechInputExtensionNotificationUI::Show(const Extension* extension,
+ bool show_balloon) {
+ if (StatusTray* status_tray = g_browser_process->status_tray()) {
+ DCHECK(!tray_icon_);
+ tray_icon_ = status_tray->CreateStatusIcon();
+ DCHECK(tray_icon_);
+ VLOG(1) << "Tray icon added.";
+
+ SetVUMeterVolume(0.0f);
+ tray_icon_->SetToolTip(l10n_util::GetStringFUTF16(
+ IDS_SPEECH_INPUT_TRAY_TOOLTIP,
+ UTF8ToUTF16(extension->name()),
+ l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)));
+ } else {
+ VLOG(1) << "This platform doesn't support notification icons.";
+ return;
+ }
+
+ if (show_balloon)
+ ShowNotificationBalloon(extension);
+}
+
+void SpeechInputExtensionNotificationUI::Hide() {
+ if (StatusTray* status_tray = g_browser_process->status_tray()) {
+ DCHECK(tray_icon_);
+ status_tray->RemoveStatusIcon(tray_icon_);
+ tray_icon_ = NULL;
+ VLOG(1) << "Tray icon removed.";
+ }
+}
+
+void SpeechInputExtensionNotificationUI::ShowNotificationBalloon(
+ const Extension* extension) {
+ string16 title = l10n_util::GetStringUTF16(
+ IDS_SPEECH_INPUT_TRAY_BALLOON_TITLE);
+ string16 message = l10n_util::GetStringFUTF16(
+ IDS_SPEECH_INPUT_TRAY_BALLOON_BODY,
+ UTF8ToUTF16(extension->name()),
+ l10n_util::GetStringUTF16(IDS_PRODUCT_NAME));
+
+ tray_icon_->DisplayBalloon(*g_images.Get().balloon_icon(), title, message);
+}

Powered by Google App Engine
This is Rietveld 408576698