blob: a03b8b594797ab1b54a6ca775d37d2afacfa4c55 [file] [log] [blame]
[email protected]a32bd2112010-03-30 20:51:191// Copyright (c) 2010 The Chromium Authors. All rights reserved.
[email protected]91e1bd82009-09-03 22:04:402// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]ded49f82010-01-13 16:10:455#include "chrome/browser/views/theme_install_bubble_view.h"
6
[email protected]91e1bd82009-09-03 22:04:407#include "app/l10n_util.h"
8#include "app/resource_bundle.h"
[email protected]ded49f82010-01-13 16:10:459#include "chrome/browser/tab_contents/tab_contents.h"
[email protected]91e1bd82009-09-03 22:04:4010#include "grit/generated_resources.h"
[email protected]ded49f82010-01-13 16:10:4511#include "views/widget/widget.h"
[email protected]91e1bd82009-09-03 22:04:4012
13namespace {
[email protected]91e1bd82009-09-03 22:04:4014
[email protected]a99f5b8a2009-10-15 15:55:3315// The roundedness of the edges of our bubble.
16static const int kBubbleCornerRadius = 4;
17
18// Padding around text in popup box.
19static const int kTextHorizPadding = 90;
20static const int kTextVertPadding = 45;
21
22// Multiple loads can be started at once. Only show one bubble, and keep
23// track of number of loads happening. Close bubble when num_loads < 1.
24static int num_loads_extant_ = 0;
25
[email protected]91e1bd82009-09-03 22:04:4026}
27
28ThemeInstallBubbleView::ThemeInstallBubbleView(TabContents* tab_contents)
29 : popup_(NULL) {
30 if (!tab_contents)
31 Close();
32
[email protected]ded49f82010-01-13 16:10:4533 text_ = l10n_util::GetString(IDS_THEME_LOADING_TITLE);
[email protected]91e1bd82009-09-03 22:04:4034 ResourceBundle& rb = ResourceBundle::GetSharedInstance();
35 gfx::Font font(rb.GetFont(ResourceBundle::LargeFont));
36 SetFont(font);
37
38 // We can't check for the size of tab_contents before we've generated
39 // the string and the font that determine the size of the bubble.
40 tab_contents->GetContainerBounds(&tab_contents_bounds_);
41 if (tab_contents_bounds_.height() < GetPreferredSize().height())
42 Close();
43
44 // Close when theme has been installed.
45 registrar_.Add(
46 this,
47 NotificationType::BROWSER_THEME_CHANGED,
48 NotificationService::AllSources());
49
50 // Close when we are installing an extension, not a theme.
51 registrar_.Add(
52 this,
53 NotificationType::NO_THEME_DETECTED,
54 NotificationService::AllSources());
55 registrar_.Add(
56 this,
57 NotificationType::EXTENSION_INSTALLED,
58 NotificationService::AllSources());
[email protected]f4ea11282009-10-14 00:19:3159 registrar_.Add(
60 this,
61 NotificationType::EXTENSION_INSTALL_ERROR,
62 NotificationService::AllSources());
[email protected]201ebfe2009-10-29 18:34:1263
64 // Don't let the bubble overlap the confirm dialog.
65 registrar_.Add(
66 this,
67 NotificationType::EXTENSION_WILL_SHOW_CONFIRM_DIALOG,
68 NotificationService::AllSources());
69
[email protected]91e1bd82009-09-03 22:04:4070 gfx::Rect rc(0, 0, 0, 0);
[email protected]ded49f82010-01-13 16:10:4571 popup_ = views::Widget::CreatePopupWidget(views::Widget::Transparent,
72 views::Widget::NotAcceptEvents,
73 views::Widget::DeleteOnDestroy);
[email protected]91e1bd82009-09-03 22:04:4074 popup_->SetOpacity(0xCC);
75 popup_->Init(tab_contents->GetNativeView(), rc);
76 popup_->SetContentsView(this);
77 Reposition();
78 popup_->Show();
79
80 SchedulePaint();
81}
82
83ThemeInstallBubbleView::~ThemeInstallBubbleView() {
84 num_loads_extant_ = 0;
85}
86
87gfx::Size ThemeInstallBubbleView::GetPreferredSize() {
[email protected]a32bd2112010-03-30 20:51:1988 return gfx::Size(views::Label::font().GetStringWidth(text_) +
[email protected]91e1bd82009-09-03 22:04:4089 kTextHorizPadding,
90 ResourceBundle::GetSharedInstance().GetFont(
91 ResourceBundle::LargeFont).height() + kTextVertPadding);
92}
93
94void ThemeInstallBubbleView::Reposition() {
95 if (!popup_)
96 Close();
97
98 gfx::Size size = GetPreferredSize();
99 int mid_x = tab_contents_bounds_.x() +
100 (tab_contents_bounds_.right() - tab_contents_bounds_.x()) / 2;
101
[email protected]c2f4bdb72010-05-10 23:15:21102 int x = base::i18n::IsRTL() ?
[email protected]91e1bd82009-09-03 22:04:40103 mid_x + size.width() / 2 : mid_x - size.width() / 2;
104 int y = static_cast<int>(tab_contents_bounds_.y() +
105 (tab_contents_bounds_.bottom() - tab_contents_bounds_.y()) / 2 -
106 size.height() / 2);
107
[email protected]ded49f82010-01-13 16:10:45108 popup_->SetBounds(gfx::Rect(x, y, size.width(), size.height()));
[email protected]91e1bd82009-09-03 22:04:40109}
110
111void ThemeInstallBubbleView::Paint(gfx::Canvas* canvas) {
112 SkScalar rad[8];
113 for (int i = 0; i < 8; ++i)
114 rad[i] = SkIntToScalar(kBubbleCornerRadius);
115
[email protected]91e1bd82009-09-03 22:04:40116 SkPaint paint;
117 paint.setStyle(SkPaint::kFill_Style);
118 paint.setFlags(SkPaint::kAntiAlias_Flag);
119 paint.setColor(SK_ColorBLACK);
120
[email protected]91e1bd82009-09-03 22:04:40121 SkRect rect;
122 rect.set(0, 0,
[email protected]ded49f82010-01-13 16:10:45123 SkIntToScalar(width()),
124 SkIntToScalar(height()));
[email protected]91e1bd82009-09-03 22:04:40125 SkPath path;
126 path.addRoundRect(rect, rad, SkPath::kCW_Direction);
127 canvas->drawPath(path, paint);
128
[email protected]a32bd2112010-03-30 20:51:19129 int text_width = views::Label::font().GetStringWidth(text_);
[email protected]ded49f82010-01-13 16:10:45130 gfx::Rect body_bounds(kTextHorizPadding / 2, 0, text_width, height());
[email protected]91e1bd82009-09-03 22:04:40131 body_bounds.set_x(MirroredLeftPointForRect(body_bounds));
132
133 SkColor text_color = SK_ColorWHITE;
[email protected]a32bd2112010-03-30 20:51:19134 canvas->DrawStringInt(text_, views::Label::font(), text_color,
[email protected]91e1bd82009-09-03 22:04:40135 body_bounds.x(), body_bounds.y(), body_bounds.width(),
136 body_bounds.height());
137}
138
139void ThemeInstallBubbleView::Close() {
140 --num_loads_extant_;
141 if (!popup_) {
142 num_loads_extant_ = 0;
143 return;
144 }
145 if (num_loads_extant_ < 1) {
146 registrar_.RemoveAll();
147 popup_->Close();
148 }
149}
150
151void ThemeInstallBubbleView::Observe(NotificationType type,
152 const NotificationSource& source,
153 const NotificationDetails& details) {
154 Close();
155}
156
157// static
158void ThemeInstallBubbleView::Show(TabContents* tab_contents) {
159 ++num_loads_extant_;
160 if (num_loads_extant_ < 2)
161 new ThemeInstallBubbleView(tab_contents);
162}
163