summaryrefslogtreecommitdiffstats
path: root/chrome/browser/views/theme_install_bubble_view.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/views/theme_install_bubble_view.cc')
-rw-r--r--chrome/browser/views/theme_install_bubble_view.cc165
1 files changed, 165 insertions, 0 deletions
diff --git a/chrome/browser/views/theme_install_bubble_view.cc b/chrome/browser/views/theme_install_bubble_view.cc
new file mode 100644
index 0000000..4e54812
--- /dev/null
+++ b/chrome/browser/views/theme_install_bubble_view.cc
@@ -0,0 +1,165 @@
+// Copyright (c) 2010 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/views/theme_install_bubble_view.h"
+
+#include "app/l10n_util.h"
+#include "app/resource_bundle.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "gfx/canvas_skia.h"
+#include "grit/generated_resources.h"
+#include "views/widget/widget.h"
+
+namespace {
+
+// The roundedness of the edges of our bubble.
+static const int kBubbleCornerRadius = 4;
+
+// Padding around text in popup box.
+static const int kTextHorizPadding = 90;
+static const int kTextVertPadding = 45;
+
+// Multiple loads can be started at once. Only show one bubble, and keep
+// track of number of loads happening. Close bubble when num_loads < 1.
+static int num_loads_extant_ = 0;
+
+}
+
+ThemeInstallBubbleView::ThemeInstallBubbleView(TabContents* tab_contents)
+ : popup_(NULL) {
+ if (!tab_contents)
+ Close();
+
+ text_ = l10n_util::GetString(IDS_THEME_LOADING_TITLE);
+ ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+ gfx::Font font(rb.GetFont(ResourceBundle::LargeFont));
+ SetFont(font);
+
+ // We can't check for the size of tab_contents before we've generated
+ // the string and the font that determine the size of the bubble.
+ tab_contents->GetContainerBounds(&tab_contents_bounds_);
+ if (tab_contents_bounds_.height() < GetPreferredSize().height())
+ Close();
+
+ // Close when theme has been installed.
+ registrar_.Add(
+ this,
+ NotificationType::BROWSER_THEME_CHANGED,
+ NotificationService::AllSources());
+
+ // Close when we are installing an extension, not a theme.
+ registrar_.Add(
+ this,
+ NotificationType::NO_THEME_DETECTED,
+ NotificationService::AllSources());
+ registrar_.Add(
+ this,
+ NotificationType::EXTENSION_INSTALLED,
+ NotificationService::AllSources());
+ registrar_.Add(
+ this,
+ NotificationType::EXTENSION_INSTALL_ERROR,
+ NotificationService::AllSources());
+
+ // Don't let the bubble overlap the confirm dialog.
+ registrar_.Add(
+ this,
+ NotificationType::EXTENSION_WILL_SHOW_CONFIRM_DIALOG,
+ NotificationService::AllSources());
+
+ gfx::Rect rc(0, 0, 0, 0);
+ popup_ = views::Widget::CreatePopupWidget(views::Widget::Transparent,
+ views::Widget::NotAcceptEvents,
+ views::Widget::DeleteOnDestroy,
+ views::Widget::MirrorOriginInRTL);
+ popup_->SetOpacity(0xCC);
+ popup_->Init(tab_contents->GetNativeView(), rc);
+ popup_->SetContentsView(this);
+ Reposition();
+ popup_->Show();
+
+ SchedulePaint();
+}
+
+ThemeInstallBubbleView::~ThemeInstallBubbleView() {
+ num_loads_extant_ = 0;
+}
+
+gfx::Size ThemeInstallBubbleView::GetPreferredSize() {
+ return gfx::Size(views::Label::font().GetStringWidth(text_) +
+ kTextHorizPadding,
+ ResourceBundle::GetSharedInstance().GetFont(
+ ResourceBundle::LargeFont).height() + kTextVertPadding);
+}
+
+void ThemeInstallBubbleView::Reposition() {
+ if (!popup_)
+ Close();
+
+ gfx::Size size = GetPreferredSize();
+ int mid_x = tab_contents_bounds_.x() +
+ (tab_contents_bounds_.right() - tab_contents_bounds_.x()) / 2;
+
+ int x = base::i18n::IsRTL() ?
+ mid_x + size.width() / 2 : mid_x - size.width() / 2;
+ int y = static_cast<int>(tab_contents_bounds_.y() +
+ (tab_contents_bounds_.bottom() - tab_contents_bounds_.y()) / 2 -
+ size.height() / 2);
+
+ popup_->SetBounds(gfx::Rect(x, y, size.width(), size.height()));
+}
+
+void ThemeInstallBubbleView::Paint(gfx::Canvas* canvas) {
+ SkScalar rad[8];
+ for (int i = 0; i < 8; ++i)
+ rad[i] = SkIntToScalar(kBubbleCornerRadius);
+
+ SkPaint paint;
+ paint.setStyle(SkPaint::kFill_Style);
+ paint.setFlags(SkPaint::kAntiAlias_Flag);
+ paint.setColor(SK_ColorBLACK);
+
+ SkRect rect;
+ rect.set(0, 0,
+ SkIntToScalar(width()),
+ SkIntToScalar(height()));
+ SkPath path;
+ path.addRoundRect(rect, rad, SkPath::kCW_Direction);
+ canvas->AsCanvasSkia()->drawPath(path, paint);
+
+ int text_width = views::Label::font().GetStringWidth(text_);
+ gfx::Rect body_bounds(kTextHorizPadding / 2, 0, text_width, height());
+ body_bounds.set_x(MirroredLeftPointForRect(body_bounds));
+
+ SkColor text_color = SK_ColorWHITE;
+ canvas->DrawStringInt(text_, views::Label::font(), text_color,
+ body_bounds.x(), body_bounds.y(), body_bounds.width(),
+ body_bounds.height());
+}
+
+void ThemeInstallBubbleView::Close() {
+ --num_loads_extant_;
+ if (!popup_) {
+ num_loads_extant_ = 0;
+ return;
+ }
+ if (num_loads_extant_ < 1) {
+ registrar_.RemoveAll();
+ popup_->Close();
+ }
+}
+
+void ThemeInstallBubbleView::Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ Close();
+}
+
+// static
+void ThemeInstallBubbleView::Show(TabContents* tab_contents) {
+ ++num_loads_extant_;
+ if (num_loads_extant_ < 2)
+ new ThemeInstallBubbleView(tab_contents);
+}
+