| OLD | NEW |
| (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/infobars/extension_infobar_gtk.h" | |
| 6 | |
| 7 #include "base/debug/trace_event.h" | |
| 8 #include "chrome/browser/extensions/extension_context_menu_model.h" | |
| 9 #include "chrome/browser/extensions/extension_view_host.h" | |
| 10 #include "chrome/browser/extensions/image_loader.h" | |
| 11 #include "chrome/browser/platform_util.h" | |
| 12 #include "chrome/browser/ui/gtk/browser_window_gtk.h" | |
| 13 #include "chrome/browser/ui/gtk/custom_button.h" | |
| 14 #include "chrome/browser/ui/gtk/gtk_chrome_button.h" | |
| 15 #include "chrome/browser/ui/gtk/gtk_util.h" | |
| 16 #include "chrome/browser/ui/gtk/infobars/infobar_container_gtk.h" | |
| 17 #include "content/public/browser/render_view_host.h" | |
| 18 #include "content/public/browser/render_widget_host_view.h" | |
| 19 #include "extensions/common/constants.h" | |
| 20 #include "extensions/common/extension.h" | |
| 21 #include "extensions/common/extension_icon_set.h" | |
| 22 #include "extensions/common/extension_resource.h" | |
| 23 #include "extensions/common/manifest_handlers/icons_handler.h" | |
| 24 #include "grit/theme_resources.h" | |
| 25 #include "ui/base/gtk/gtk_signal_registrar.h" | |
| 26 #include "ui/base/resource/resource_bundle.h" | |
| 27 #include "ui/gfx/canvas.h" | |
| 28 #include "ui/gfx/gtk_util.h" | |
| 29 #include "ui/gfx/image/image.h" | |
| 30 | |
| 31 | |
| 32 // ExtensionInfoBarDelegate --------------------------------------------------- | |
| 33 | |
| 34 // static | |
| 35 scoped_ptr<InfoBar> ExtensionInfoBarDelegate::CreateInfoBar( | |
| 36 scoped_ptr<ExtensionInfoBarDelegate> delegate) { | |
| 37 return scoped_ptr<InfoBar>(new ExtensionInfoBarGtk(delegate.Pass())); | |
| 38 } | |
| 39 | |
| 40 | |
| 41 // ExtensionInfoBarGtk -------------------------------------------------------- | |
| 42 | |
| 43 ExtensionInfoBarGtk::ExtensionInfoBarGtk( | |
| 44 scoped_ptr<ExtensionInfoBarDelegate> delegate) | |
| 45 : InfoBarGtk(delegate.PassAs<InfoBarDelegate>()), | |
| 46 view_(NULL), | |
| 47 button_(NULL), | |
| 48 icon_(NULL), | |
| 49 alignment_(NULL), | |
| 50 weak_ptr_factory_(this) { | |
| 51 int height = GetDelegate()->height(); | |
| 52 SetBarTargetHeight((height > 0) ? (height + kSeparatorLineHeight) : 0); | |
| 53 } | |
| 54 | |
| 55 ExtensionInfoBarGtk::~ExtensionInfoBarGtk() { | |
| 56 } | |
| 57 | |
| 58 void ExtensionInfoBarGtk::PlatformSpecificSetOwner() { | |
| 59 InfoBarGtk::PlatformSpecificSetOwner(); | |
| 60 | |
| 61 // Always render the close button as if we were doing chrome style widget | |
| 62 // rendering. For extension infobars, we force chrome style rendering because | |
| 63 // extension authors are going to expect to match the declared gradient in | |
| 64 // extensions_infobar.css, and the close button provided by some GTK+ themes | |
| 65 // won't look good on this background. | |
| 66 ForceCloseButtonToUseChromeTheme(); | |
| 67 | |
| 68 icon_ = gtk_image_new(); | |
| 69 gtk_misc_set_alignment(GTK_MISC(icon_), 0.5, 0.5); | |
| 70 | |
| 71 extensions::ExtensionViewHost* extension_view_host = | |
| 72 GetDelegate()->extension_view_host(); | |
| 73 const extensions::Extension* extension = extension_view_host->extension(); | |
| 74 | |
| 75 if (extension->ShowConfigureContextMenus()) { | |
| 76 button_ = gtk_chrome_button_new(); | |
| 77 gtk_chrome_button_set_use_gtk_rendering(GTK_CHROME_BUTTON(button_), FALSE); | |
| 78 g_object_set_data(G_OBJECT(button_), "left-align-popup", | |
| 79 reinterpret_cast<void*>(true)); | |
| 80 | |
| 81 gtk_button_set_image(GTK_BUTTON(button_), icon_); | |
| 82 gtk_util::CenterWidgetInHBox(hbox(), button_, false, 0); | |
| 83 } else { | |
| 84 gtk_util::CenterWidgetInHBox(hbox(), icon_, false, 0); | |
| 85 } | |
| 86 | |
| 87 // Start loading the image for the menu button. | |
| 88 extensions::ExtensionResource icon_resource = | |
| 89 extensions::IconsInfo::GetIconResource( | |
| 90 extension, | |
| 91 extension_misc::EXTENSION_ICON_BITTY, | |
| 92 ExtensionIconSet::MATCH_EXACTLY); | |
| 93 // Load image asynchronously, calling back OnImageLoaded. | |
| 94 extensions::ImageLoader* loader = | |
| 95 extensions::ImageLoader::Get(extension_view_host->browser_context()); | |
| 96 loader->LoadImageAsync(extension, icon_resource, | |
| 97 gfx::Size(extension_misc::EXTENSION_ICON_BITTY, | |
| 98 extension_misc::EXTENSION_ICON_BITTY), | |
| 99 base::Bind(&ExtensionInfoBarGtk::OnImageLoaded, | |
| 100 weak_ptr_factory_.GetWeakPtr())); | |
| 101 | |
| 102 // Pad the bottom of the infobar by one pixel for the border. | |
| 103 alignment_ = gtk_alignment_new(0.0, 0.0, 1.0, 1.0); | |
| 104 gtk_alignment_set_padding(GTK_ALIGNMENT(alignment_), 0, 1, 0, 0); | |
| 105 gtk_box_pack_start(GTK_BOX(hbox()), alignment_, TRUE, TRUE, 0); | |
| 106 | |
| 107 view_ = extension_view_host->view(); | |
| 108 | |
| 109 if (gtk_widget_get_parent(view_->native_view())) { | |
| 110 gtk_widget_reparent(view_->native_view(), alignment_); | |
| 111 } else { | |
| 112 gtk_container_add(GTK_CONTAINER(alignment_), view_->native_view()); | |
| 113 } | |
| 114 | |
| 115 if (button_) { | |
| 116 signals()->Connect(button_, "button-press-event", | |
| 117 G_CALLBACK(&OnButtonPressThunk), this); | |
| 118 } | |
| 119 signals()->Connect(view_->native_view(), "expose-event", | |
| 120 G_CALLBACK(&OnExposeThunk), this); | |
| 121 signals()->Connect(view_->native_view(), "size_allocate", | |
| 122 G_CALLBACK(&OnSizeAllocateThunk), this); | |
| 123 } | |
| 124 | |
| 125 void ExtensionInfoBarGtk::PlatformSpecificHide(bool animate) { | |
| 126 DCHECK(view_); | |
| 127 DCHECK(alignment_); | |
| 128 gtk_util::RemoveAllChildren(alignment_); | |
| 129 } | |
| 130 | |
| 131 void ExtensionInfoBarGtk::GetTopColor(InfoBarDelegate::Type type, | |
| 132 double* r, double* g, double* b) { | |
| 133 // Extension infobars are always drawn with chrome-theme colors. | |
| 134 *r = *g = *b = 233.0 / 255.0; | |
| 135 } | |
| 136 | |
| 137 void ExtensionInfoBarGtk::GetBottomColor(InfoBarDelegate::Type type, | |
| 138 double* r, double* g, double* b) { | |
| 139 *r = *g = *b = 218.0 / 255.0; | |
| 140 } | |
| 141 | |
| 142 void ExtensionInfoBarGtk::StoppedShowing() { | |
| 143 if (button_) | |
| 144 gtk_chrome_button_unset_paint_state(GTK_CHROME_BUTTON(button_)); | |
| 145 } | |
| 146 | |
| 147 void ExtensionInfoBarGtk::OnImageLoaded(const gfx::Image& image) { | |
| 148 | |
| 149 DCHECK(icon_); | |
| 150 // TODO(erg): IDR_EXTENSIONS_SECTION should have an IDR_INFOBAR_EXTENSIONS | |
| 151 // icon of the correct size with real subpixel shading and such. | |
| 152 const gfx::ImageSkia* icon = NULL; | |
| 153 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | |
| 154 if (image.IsEmpty()) | |
| 155 icon = rb.GetImageSkiaNamed(IDR_EXTENSIONS_SECTION); | |
| 156 else | |
| 157 icon = image.ToImageSkia(); | |
| 158 | |
| 159 SkBitmap bitmap; | |
| 160 if (button_) { | |
| 161 gfx::ImageSkia* drop_image = rb.GetImageSkiaNamed(IDR_APP_DROPARROW); | |
| 162 | |
| 163 int image_size = extension_misc::EXTENSION_ICON_BITTY; | |
| 164 // The margin between the extension icon and the drop-down arrow bitmap. | |
| 165 static const int kDropArrowLeftMargin = 3; | |
| 166 scoped_ptr<gfx::Canvas> canvas(new gfx::Canvas( | |
| 167 gfx::Size(image_size + kDropArrowLeftMargin + drop_image->width(), | |
| 168 image_size), 1.0f, false)); | |
| 169 canvas->DrawImageInt(*icon, 0, 0, icon->width(), icon->height(), 0, 0, | |
| 170 image_size, image_size, false); | |
| 171 canvas->DrawImageInt(*drop_image, image_size + kDropArrowLeftMargin, | |
| 172 image_size / 2); | |
| 173 bitmap = canvas->ExtractImageRep().sk_bitmap(); | |
| 174 } else { | |
| 175 bitmap = *icon->bitmap(); | |
| 176 } | |
| 177 | |
| 178 GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(bitmap); | |
| 179 gtk_image_set_from_pixbuf(GTK_IMAGE(icon_), pixbuf); | |
| 180 g_object_unref(pixbuf); | |
| 181 } | |
| 182 | |
| 183 ExtensionInfoBarDelegate* ExtensionInfoBarGtk::GetDelegate() { | |
| 184 return delegate()->AsExtensionInfoBarDelegate(); | |
| 185 } | |
| 186 | |
| 187 Browser* ExtensionInfoBarGtk::GetBrowser() { | |
| 188 DCHECK(icon_); | |
| 189 // Get the Browser object this infobar is attached to. | |
| 190 GtkWindow* parent = platform_util::GetTopLevel(icon_); | |
| 191 return parent ? | |
| 192 BrowserWindowGtk::GetBrowserWindowForNativeWindow(parent)->browser() : | |
| 193 NULL; | |
| 194 } | |
| 195 | |
| 196 ExtensionContextMenuModel* ExtensionInfoBarGtk::BuildMenuModel() { | |
| 197 const extensions::Extension* extension = GetDelegate()->extension(); | |
| 198 if (!extension->ShowConfigureContextMenus()) | |
| 199 return NULL; | |
| 200 | |
| 201 Browser* browser = GetBrowser(); | |
| 202 if (!browser) | |
| 203 return NULL; | |
| 204 | |
| 205 return new ExtensionContextMenuModel(extension, browser); | |
| 206 } | |
| 207 | |
| 208 void ExtensionInfoBarGtk::OnSizeAllocate(GtkWidget* widget, | |
| 209 GtkAllocation* allocation) { | |
| 210 gfx::Size new_size(allocation->width, allocation->height); | |
| 211 | |
| 212 GetDelegate()->extension_view_host()->view()->render_view_host()->GetView()-> | |
| 213 SetSize(new_size); | |
| 214 } | |
| 215 | |
| 216 gboolean ExtensionInfoBarGtk::OnButtonPress(GtkWidget* widget, | |
| 217 GdkEventButton* event) { | |
| 218 if (event->button != 1) | |
| 219 return FALSE; | |
| 220 | |
| 221 DCHECK(button_); | |
| 222 | |
| 223 context_menu_model_ = BuildMenuModel(); | |
| 224 if (!context_menu_model_.get()) | |
| 225 return FALSE; | |
| 226 | |
| 227 gtk_chrome_button_set_paint_state(GTK_CHROME_BUTTON(widget), | |
| 228 GTK_STATE_ACTIVE); | |
| 229 ShowMenuWithModel(widget, this, context_menu_model_.get()); | |
| 230 | |
| 231 return TRUE; | |
| 232 } | |
| 233 | |
| 234 gboolean ExtensionInfoBarGtk::OnExpose(GtkWidget* sender, | |
| 235 GdkEventExpose* event) { | |
| 236 TRACE_EVENT0("ui::gtk", "ExtensionInfoBarGtk::OnExpose"); | |
| 237 | |
| 238 // We also need to draw our infobar arrows over the renderer. | |
| 239 static_cast<InfoBarContainerGtk*>(container())-> | |
| 240 PaintInfobarBitsOn(sender, event, this); | |
| 241 | |
| 242 return FALSE; | |
| 243 } | |
| OLD | NEW |