1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/ui/gtk/extensions/bundle_installed_bubble_gtk.h"
10 #include "base/bind_helpers.h"
11 #include "base/i18n/rtl.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "chrome/browser/ui/browser.h"
15 #include "chrome/browser/ui/gtk/browser_toolbar_gtk.h"
16 #include "chrome/browser/ui/gtk/browser_window_gtk.h"
17 #include "chrome/browser/ui/gtk/gtk_theme_service.h"
18 #include "chrome/browser/ui/gtk/gtk_util.h"
19 #include "grit/generated_resources.h"
20 #include "grit/theme_resources.h"
21 #include "ui/base/l10n/l10n_util.h"
22 #include "ui/base/resource/resource_bundle.h"
23 #include "ui/gfx/gtk_util.h"
25 using extensions::BundleInstaller
;
29 // The horizontal spacing for the main content area.
30 const int kHorizontalColumnSpacing
= 10;
32 // The vertical spacing for the text area.
33 const int kTextColumnVerticalSpacing
= 7;
35 // The width of the content area.
36 const int kContentWidth
= 350;
38 // The padding for list items.
39 const int kListItemPadding
= 2;
41 // Padding between content and edge of bubble.
42 const int kContentPadding
= 12;
47 void BundleInstaller::ShowInstalledBubble(
48 const BundleInstaller
* bundle
, Browser
* browser
) {
49 new BundleInstalledBubbleGtk(bundle
, browser
);
52 BundleInstalledBubbleGtk::BundleInstalledBubbleGtk(
53 const BundleInstaller
* bundle
, Browser
* browser
)
56 AddRef(); // Balanced in Close().
60 BundleInstalledBubbleGtk::~BundleInstalledBubbleGtk() {}
62 void BundleInstalledBubbleGtk::ShowInternal(const BundleInstaller
* bundle
) {
63 BrowserWindowGtk
* browser_window
=
64 BrowserWindowGtk::GetBrowserWindowForNativeWindow(
65 browser_
->window()->GetNativeWindow());
67 GtkThemeService
* theme_provider
= GtkThemeService::GetFrom(
70 // Anchor the bubble to the wrench menu.
71 GtkWidget
* reference_widget
=
72 browser_window
->GetToolbar()->GetAppMenuButton();
74 GtkWidget
* bubble_content
= gtk_hbox_new(FALSE
, kHorizontalColumnSpacing
);
75 gtk_container_set_border_width(
76 GTK_CONTAINER(bubble_content
), kContentPadding
);
78 GtkWidget
* text_column
= gtk_vbox_new(FALSE
, kTextColumnVerticalSpacing
);
79 gtk_box_pack_start(GTK_BOX(bubble_content
), text_column
, FALSE
, FALSE
, 0);
82 text_column
, bundle
, BundleInstaller::Item::STATE_INSTALLED
);
83 InsertExtensionList(text_column
, bundle
, BundleInstaller::Item::STATE_FAILED
);
86 GtkWidget
* close_column
= gtk_vbox_new(FALSE
, 0);
87 gtk_box_pack_start(GTK_BOX(bubble_content
), close_column
, FALSE
, FALSE
, 0);
88 close_button_
.reset(CustomDrawButton::CloseButtonBubble(theme_provider
));
89 g_signal_connect(close_button_
->widget(), "clicked",
90 G_CALLBACK(OnButtonClick
), this);
91 gtk_box_pack_start(GTK_BOX(close_column
), close_button_
->widget(),
94 gfx::Rect bounds
= gtk_util::WidgetBounds(reference_widget
);
96 bubble_
= BubbleGtk::Show(reference_widget
,
99 BubbleGtk::ANCHOR_TOP_RIGHT
,
100 BubbleGtk::MATCH_SYSTEM_THEME
|
101 BubbleGtk::POPUP_WINDOW
|
102 BubbleGtk::GRAB_INPUT
,
107 void BundleInstalledBubbleGtk::InsertExtensionList(
109 const BundleInstaller
* bundle
,
110 BundleInstaller::Item::State state
) {
111 base::string16 heading
= bundle
->GetHeadingTextFor(state
);
112 BundleInstaller::ItemList items
= bundle
->GetItemsWithState(state
);
113 if (heading
.empty() || items
.empty())
116 GtkWidget
* heading_label
=
117 gtk_util::CreateBoldLabel(base::UTF16ToUTF8(heading
));
118 gtk_util::SetLabelWidth(heading_label
, kContentWidth
);
119 gtk_box_pack_start(GTK_BOX(parent
), heading_label
, FALSE
, FALSE
, 0);
121 for (size_t i
= 0; i
< items
.size(); ++i
) {
122 GtkWidget
* extension_label
= gtk_label_new(base::UTF16ToUTF8(
123 items
[i
].GetNameForDisplay()).c_str());
124 gtk_util::SetLabelWidth(extension_label
, kContentWidth
);
125 gtk_box_pack_start(GTK_BOX(parent
), extension_label
, false, false,
130 void BundleInstalledBubbleGtk::BubbleClosing(BubbleGtk
* bubble
,
131 bool closed_by_escape
) {
132 // We need to allow the bubble to close and remove the widgets from
133 // the window before we call Release() because close_button_ depends
134 // on all references being cleared before it is destroyed.
135 base::MessageLoopForUI::current()->PostTask(
136 FROM_HERE
, base::Bind(&BundleInstalledBubbleGtk::Close
, this));
139 void BundleInstalledBubbleGtk::Close() {
142 Release(); // Balanced in BundleInstalledBubbleGtk().
145 void BundleInstalledBubbleGtk::OnButtonClick(GtkWidget
* button
,
146 BundleInstalledBubbleGtk
* bubble
) {
147 if (button
== bubble
->close_button_
->widget())
148 bubble
->bubble_
->Close();