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

Side by Side Diff: chrome/browser/ui/gtk/extensions/extension_installed_bubble_gtk.cc

Issue 231733005: Delete the GTK+ port of Chrome. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Remerge to ToT Created 6 years, 8 months 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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.
4
5 #include "chrome/browser/ui/gtk/extensions/extension_installed_bubble_gtk.h"
6
7 #include <string>
8
9 #include "base/i18n/rtl.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "chrome/browser/chrome_notification_types.h"
12 #include "chrome/browser/extensions/api/commands/command_service.h"
13 #include "chrome/browser/extensions/extension_action.h"
14 #include "chrome/browser/extensions/extension_action_manager.h"
15 #include "chrome/browser/ui/browser.h"
16 #include "chrome/browser/ui/browser_dialogs.h"
17 #include "chrome/browser/ui/gtk/browser_actions_toolbar_gtk.h"
18 #include "chrome/browser/ui/gtk/browser_toolbar_gtk.h"
19 #include "chrome/browser/ui/gtk/browser_window_gtk.h"
20 #include "chrome/browser/ui/gtk/gtk_theme_service.h"
21 #include "chrome/browser/ui/gtk/gtk_util.h"
22 #include "chrome/browser/ui/gtk/location_bar_view_gtk.h"
23 #include "chrome/browser/ui/singleton_tabs.h"
24 #include "chrome/common/extensions/api/omnibox/omnibox_handler.h"
25 #include "chrome/common/url_constants.h"
26 #include "content/public/browser/notification_details.h"
27 #include "content/public/browser/notification_source.h"
28 #include "extensions/common/extension.h"
29 #include "grit/chromium_strings.h"
30 #include "grit/generated_resources.h"
31 #include "grit/theme_resources.h"
32 #include "ui/base/gtk/gtk_hig_constants.h"
33 #include "ui/base/l10n/l10n_util.h"
34 #include "ui/base/resource/resource_bundle.h"
35 #include "ui/gfx/gtk_util.h"
36
37 using extensions::Extension;
38 using extensions::ExtensionActionManager;
39
40 namespace {
41
42 const int kHorizontalColumnSpacing = 10;
43 const int kIconPadding = 3;
44 const int kIconSize = 43;
45 const int kTextColumnVerticalSpacing = 7;
46 const int kTextColumnWidth = 350;
47
48 } // namespace
49
50 namespace chrome {
51
52 void ShowExtensionInstalledBubble(const Extension* extension,
53 Browser* browser,
54 const SkBitmap& icon) {
55 ExtensionInstalledBubbleGtk::Show(extension, browser, icon);
56 }
57
58 } // namespace chrome
59
60 void ExtensionInstalledBubbleGtk::Show(const Extension* extension,
61 Browser* browser,
62 const SkBitmap& icon) {
63 new ExtensionInstalledBubbleGtk(extension, browser, icon);
64 }
65
66 ExtensionInstalledBubbleGtk::ExtensionInstalledBubbleGtk(
67 const Extension* extension, Browser *browser, const SkBitmap& icon)
68 : bubble_(this, extension, browser, icon) {
69 }
70
71 ExtensionInstalledBubbleGtk::~ExtensionInstalledBubbleGtk() {}
72
73 void ExtensionInstalledBubbleGtk::OnDestroy(GtkWidget* widget) {
74 gtk_bubble_ = NULL;
75 delete this;
76 }
77
78 bool ExtensionInstalledBubbleGtk::MaybeShowNow() {
79 BrowserWindowGtk* browser_window =
80 BrowserWindowGtk::GetBrowserWindowForNativeWindow(
81 bubble_.browser()->window()->GetNativeWindow());
82
83 GtkWidget* reference_widget = NULL;
84
85 if (bubble_.type() == bubble_.BROWSER_ACTION) {
86 BrowserActionsToolbarGtk* toolbar =
87 browser_window->GetToolbar()->GetBrowserActionsToolbar();
88 if (toolbar->animating())
89 return false;
90
91 reference_widget = toolbar->GetBrowserActionWidget(bubble_.extension());
92 // glib delays recalculating layout, but we need reference_widget to know
93 // its coordinates, so we force a check_resize here.
94 gtk_container_check_resize(GTK_CONTAINER(
95 browser_window->GetToolbar()->widget()));
96 // If the widget is not visible then browser_window could be incognito
97 // with this extension disabled. Try showing it on the chevron.
98 // If that fails, fall back to default position.
99 if (reference_widget && !gtk_widget_get_visible(reference_widget)) {
100 reference_widget = gtk_widget_get_visible(toolbar->chevron()) ?
101 toolbar->chevron() : NULL;
102 }
103 } else if (bubble_.type() == bubble_.PAGE_ACTION) {
104 LocationBarViewGtk* location_bar_view =
105 browser_window->GetToolbar()->GetLocationBarView();
106 ExtensionAction* page_action =
107 ExtensionActionManager::Get(bubble_.browser()->profile())->
108 GetPageAction(*bubble_.extension());
109 location_bar_view->SetPreviewEnabledPageAction(page_action,
110 true); // preview_enabled
111 reference_widget = location_bar_view->GetPageActionWidget(page_action);
112 // glib delays recalculating layout, but we need reference_widget to know
113 // its coordinates, so we force a check_resize here.
114 gtk_container_check_resize(GTK_CONTAINER(
115 browser_window->GetToolbar()->widget()));
116 DCHECK(reference_widget);
117 } else if (bubble_.type() == bubble_.OMNIBOX_KEYWORD) {
118 LocationBarViewGtk* location_bar_view =
119 browser_window->GetToolbar()->GetLocationBarView();
120 reference_widget = location_bar_view->location_entry_widget();
121 DCHECK(reference_widget);
122 }
123
124 // Default case.
125 if (reference_widget == NULL)
126 reference_widget = browser_window->GetToolbar()->GetAppMenuButton();
127
128 GtkThemeService* theme_provider = GtkThemeService::GetFrom(
129 bubble_.browser()->profile());
130
131 // Setup the BubbleGtk content.
132 GtkWidget* bubble_content = gtk_hbox_new(FALSE, kHorizontalColumnSpacing);
133 gtk_container_set_border_width(GTK_CONTAINER(bubble_content),
134 ui::kContentAreaBorder);
135
136 if (!bubble_.icon().isNull()) {
137 // Scale icon down to 43x43, but allow smaller icons (don't scale up).
138 GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(bubble_.icon());
139 gfx::Size size(bubble_.icon().width(), bubble_.icon().height());
140 if (size.width() > kIconSize || size.height() > kIconSize) {
141 if (size.width() > size.height()) {
142 size.set_height(size.height() * kIconSize / size.width());
143 size.set_width(kIconSize);
144 } else {
145 size.set_width(size.width() * kIconSize / size.height());
146 size.set_height(kIconSize);
147 }
148
149 GdkPixbuf* old = pixbuf;
150 pixbuf = gdk_pixbuf_scale_simple(pixbuf, size.width(), size.height(),
151 GDK_INTERP_BILINEAR);
152 g_object_unref(old);
153 }
154
155 // Put Icon in top of the left column.
156 GtkWidget* icon_column = gtk_vbox_new(FALSE, 0);
157 // Use 3 pixel padding to get visual balance with BubbleGtk border on the
158 // left.
159 gtk_box_pack_start(GTK_BOX(bubble_content), icon_column, FALSE, FALSE,
160 kIconPadding);
161 GtkWidget* image = gtk_image_new_from_pixbuf(pixbuf);
162 g_object_unref(pixbuf);
163 gtk_box_pack_start(GTK_BOX(icon_column), image, FALSE, FALSE, 0);
164 }
165
166 // Center text column.
167 GtkWidget* text_column = gtk_vbox_new(FALSE, kTextColumnVerticalSpacing);
168 gtk_box_pack_start(GTK_BOX(bubble_content), text_column, FALSE, FALSE, 0);
169
170 // Heading label.
171 GtkWidget* heading_label = gtk_label_new(NULL);
172 base::string16 extension_name =
173 base::UTF8ToUTF16(bubble_.extension()->name());
174 base::i18n::AdjustStringForLocaleDirection(&extension_name);
175 std::string heading_text = l10n_util::GetStringFUTF8(
176 IDS_EXTENSION_INSTALLED_HEADING, extension_name);
177 char* markup = g_markup_printf_escaped("<span size=\"larger\">%s</span>",
178 heading_text.c_str());
179 gtk_label_set_markup(GTK_LABEL(heading_label), markup);
180 g_free(markup);
181
182 gtk_util::SetLabelWidth(heading_label, kTextColumnWidth);
183 gtk_box_pack_start(GTK_BOX(text_column), heading_label, FALSE, FALSE, 0);
184
185 bool has_keybinding = false;
186
187 // Browser action label.
188 if (bubble_.type() == bubble_.BROWSER_ACTION) {
189 extensions::CommandService* command_service =
190 extensions::CommandService::Get(bubble_.browser()->profile());
191 extensions::Command browser_action_command;
192 GtkWidget* info_label;
193 if (!command_service->GetBrowserActionCommand(
194 bubble_.extension()->id(),
195 extensions::CommandService::ACTIVE_ONLY,
196 &browser_action_command,
197 NULL)) {
198 info_label = gtk_label_new(l10n_util::GetStringUTF8(
199 IDS_EXTENSION_INSTALLED_BROWSER_ACTION_INFO).c_str());
200 } else {
201 info_label = gtk_label_new(l10n_util::GetStringFUTF8(
202 IDS_EXTENSION_INSTALLED_BROWSER_ACTION_INFO_WITH_SHORTCUT,
203 browser_action_command.accelerator().GetShortcutText()).c_str());
204 has_keybinding = true;
205 }
206 gtk_util::SetLabelWidth(info_label, kTextColumnWidth);
207 gtk_box_pack_start(GTK_BOX(text_column), info_label, FALSE, FALSE, 0);
208 }
209
210 // Page action label.
211 if (bubble_.type() == bubble_.PAGE_ACTION) {
212 extensions::CommandService* command_service =
213 extensions::CommandService::Get(bubble_.browser()->profile());
214 extensions::Command page_action_command;
215 GtkWidget* info_label;
216 if (!command_service->GetPageActionCommand(
217 bubble_.extension()->id(),
218 extensions::CommandService::ACTIVE_ONLY,
219 &page_action_command,
220 NULL)) {
221 info_label = gtk_label_new(l10n_util::GetStringUTF8(
222 IDS_EXTENSION_INSTALLED_PAGE_ACTION_INFO).c_str());
223 } else {
224 info_label = gtk_label_new(l10n_util::GetStringFUTF8(
225 IDS_EXTENSION_INSTALLED_PAGE_ACTION_INFO_WITH_SHORTCUT,
226 page_action_command.accelerator().GetShortcutText()).c_str());
227 has_keybinding = true;
228 }
229 gtk_util::SetLabelWidth(info_label, kTextColumnWidth);
230 gtk_box_pack_start(GTK_BOX(text_column), info_label, FALSE, FALSE, 0);
231 }
232
233 // Omnibox keyword label.
234 if (bubble_.type() == bubble_.OMNIBOX_KEYWORD) {
235 GtkWidget* info_label = gtk_label_new(l10n_util::GetStringFUTF8(
236 IDS_EXTENSION_INSTALLED_OMNIBOX_KEYWORD_INFO,
237 base::UTF8ToUTF16(extensions::OmniboxInfo::GetKeyword(
238 bubble_.extension()))).c_str());
239 gtk_util::SetLabelWidth(info_label, kTextColumnWidth);
240 gtk_box_pack_start(GTK_BOX(text_column), info_label, FALSE, FALSE, 0);
241 }
242
243 if (has_keybinding) {
244 GtkWidget* manage_link = theme_provider->BuildChromeLinkButton(
245 l10n_util::GetStringUTF8(IDS_EXTENSION_INSTALLED_MANAGE_SHORTCUTS));
246 GtkWidget* link_hbox = gtk_hbox_new(FALSE, 0);
247 // Stick it in an hbox so it doesn't expand to the whole width.
248 gtk_box_pack_end(GTK_BOX(link_hbox), manage_link, FALSE, FALSE, 0);
249 gtk_box_pack_start(GTK_BOX(text_column), link_hbox, FALSE, FALSE, 0);
250 g_signal_connect(manage_link, "clicked",
251 G_CALLBACK(OnLinkClickedThunk), this);
252 } else {
253 // Manage label.
254 GtkWidget* manage_label = gtk_label_new(
255 l10n_util::GetStringUTF8(IDS_EXTENSION_INSTALLED_MANAGE_INFO).c_str());
256 gtk_util::SetLabelWidth(manage_label, kTextColumnWidth);
257 gtk_box_pack_start(GTK_BOX(text_column), manage_label, FALSE, FALSE, 0);
258 }
259
260 // Create and pack the close button.
261 GtkWidget* close_column = gtk_vbox_new(FALSE, 0);
262 gtk_box_pack_start(GTK_BOX(bubble_content), close_column, FALSE, FALSE, 0);
263 close_button_.reset(CustomDrawButton::CloseButtonBubble(theme_provider));
264 g_signal_connect(close_button_->widget(), "clicked",
265 G_CALLBACK(OnButtonClick), this);
266 gtk_box_pack_start(GTK_BOX(close_column), close_button_->widget(),
267 FALSE, FALSE, 0);
268
269 BubbleGtk::FrameStyle frame_style = BubbleGtk::ANCHOR_TOP_RIGHT;
270
271 gfx::Rect bounds = gtk_util::WidgetBounds(reference_widget);
272 if (bubble_.type() == bubble_.OMNIBOX_KEYWORD) {
273 // Reverse the arrow for omnibox keywords, since the bubble will be on the
274 // other side of the window. We also clear the width to avoid centering
275 // the popup on the URL bar.
276 frame_style = BubbleGtk::ANCHOR_TOP_LEFT;
277 if (base::i18n::IsRTL())
278 bounds.Offset(bounds.width(), 0);
279 bounds.set_width(0);
280 }
281
282 gtk_bubble_ = BubbleGtk::Show(reference_widget,
283 &bounds,
284 bubble_content,
285 frame_style,
286 BubbleGtk::MATCH_SYSTEM_THEME |
287 BubbleGtk::POPUP_WINDOW |
288 BubbleGtk::GRAB_INPUT,
289 theme_provider,
290 this);
291 g_signal_connect(bubble_content, "destroy",
292 G_CALLBACK(&OnDestroyThunk), this);
293
294 // gtk_bubble_ is now the owner of |this| and deletes it when the bubble
295 // goes away.
296 bubble_.IgnoreBrowserClosing();
297 return true;
298 }
299
300 // static
301 void ExtensionInstalledBubbleGtk::OnButtonClick(GtkWidget* button,
302 ExtensionInstalledBubbleGtk* bubble) {
303 if (button == bubble->close_button_->widget()) {
304 bubble->gtk_bubble_->Close();
305 } else {
306 NOTREACHED();
307 }
308 }
309
310 void ExtensionInstalledBubbleGtk::OnLinkClicked(GtkWidget* widget) {
311 gtk_bubble_->Close();
312
313 std::string configure_url = chrome::kChromeUIExtensionsURL;
314 configure_url += chrome::kExtensionConfigureCommandsSubPage;
315 chrome::NavigateParams params(
316 chrome::GetSingletonTabNavigateParams(
317 bubble_.browser(), GURL(configure_url.c_str())));
318 chrome::Navigate(&params);
319 }
320
321 void ExtensionInstalledBubbleGtk::BubbleClosing(BubbleGtk* bubble,
322 bool closed_by_escape) {
323 if (bubble_.extension() && bubble_.type() == bubble_.PAGE_ACTION) {
324 // Turn the page action preview off.
325 BrowserWindowGtk* browser_window =
326 BrowserWindowGtk::GetBrowserWindowForNativeWindow(
327 bubble_.browser()->window()->GetNativeWindow());
328 LocationBarViewGtk* location_bar_view =
329 browser_window->GetToolbar()->GetLocationBarView();
330 location_bar_view->SetPreviewEnabledPageAction(
331 ExtensionActionManager::Get(bubble_.browser()->profile())->
332 GetPageAction(*bubble_.extension()),
333 false); // preview_enabled
334 }
335 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698