Chromium Code Reviews| Index: chrome/browser/ui/gtk/web_intent_picker_gtk.cc |
| diff --git a/chrome/browser/ui/gtk/web_intent_picker_gtk.cc b/chrome/browser/ui/gtk/web_intent_picker_gtk.cc |
| index 6671b00cd0aa00fb8a2c8ffcac6ee16bee4fe006..405b1e5d90b0bbd361503ae20559511269e43e9f 100644 |
| --- a/chrome/browser/ui/gtk/web_intent_picker_gtk.cc |
| +++ b/chrome/browser/ui/gtk/web_intent_picker_gtk.cc |
| @@ -8,6 +8,7 @@ |
| #include "base/bind.h" |
| #include "base/callback.h" |
| +#include "base/utf_string_conversions.h" |
| #include "chrome/browser/favicon/favicon_service.h" |
| #include "chrome/browser/profiles/profile.h" |
| #include "chrome/browser/ui/browser.h" |
| @@ -21,6 +22,7 @@ |
| #include "chrome/browser/ui/gtk/tab_contents_container_gtk.h" |
| #include "chrome/browser/ui/intents/web_intent_picker_controller.h" |
| #include "chrome/browser/ui/intents/web_intent_picker_delegate.h" |
| +#include "chrome/browser/ui/intents/web_intent_picker_model.h" |
| #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" |
| #include "content/browser/renderer_host/render_view_host.h" |
| #include "content/browser/renderer_host/render_widget_host_view_gtk.h" |
| @@ -31,9 +33,6 @@ |
| #include "content/public/browser/web_contents_view.h" |
| #include "googleurl/src/gurl.h" |
| #include "grit/generated_resources.h" |
| -#include "grit/theme_resources.h" |
| -#include "grit/theme_resources_standard.h" |
| -#include "grit/ui_resources.h" |
| #include "ui/base/gtk/gtk_hig_constants.h" |
| #include "ui/base/l10n/l10n_util.h" |
| #include "ui/base/resource/resource_bundle.h" |
| @@ -55,9 +54,6 @@ const int kWebStoreLabelLength = 300; |
| // The pixel size of the label at the bottom of the picker. |
| const int kWebStoreLabelPixelSize = 11; |
| -// How much to scale the the buttons up from their favicon size. |
| -const int kServiceButtonScale = 3; |
| - |
| GtkThemeService *GetThemeService(TabContentsWrapper* wrapper) { |
| return GtkThemeService::GetFrom(wrapper->profile()); |
| } |
| @@ -65,13 +61,8 @@ GtkThemeService *GetThemeService(TabContentsWrapper* wrapper) { |
| // Set the image of |button| to |pixbuf|, and scale the button up by |
| // |kServiceButtonScale|. |
|
Elliot Glaysher
2012/01/27 19:19:44
Comment is wrong
binji
2012/01/27 19:39:41
Done.
|
| void SetServiceButtonImage(GtkWidget* button, GdkPixbuf* pixbuf) { |
| - int width = gdk_pixbuf_get_width(pixbuf); |
| - int height = gdk_pixbuf_get_height(pixbuf); |
| - gtk_button_set_image(GTK_BUTTON(button), |
| - gtk_image_new_from_pixbuf(pixbuf)); |
| - gtk_widget_set_size_request(button, |
| - width * kServiceButtonScale, |
| - height * kServiceButtonScale); |
| + gtk_button_set_image(GTK_BUTTON(button), gtk_image_new_from_pixbuf(pixbuf)); |
| + gtk_button_set_image_position(GTK_BUTTON(button), GTK_POS_LEFT); |
| } |
| } // namespace |
| @@ -79,22 +70,28 @@ void SetServiceButtonImage(GtkWidget* button, GdkPixbuf* pixbuf) { |
| // static |
| WebIntentPicker* WebIntentPicker::Create(Browser* browser, |
| TabContentsWrapper* wrapper, |
| - WebIntentPickerDelegate* delegate) { |
| - return new WebIntentPickerGtk(browser, wrapper, delegate); |
| + WebIntentPickerDelegate* delegate, |
| + WebIntentPickerModel* model) { |
| + return new WebIntentPickerGtk(browser, wrapper, delegate, model); |
| } |
| WebIntentPickerGtk::WebIntentPickerGtk(Browser* browser, |
| TabContentsWrapper* wrapper, |
| - WebIntentPickerDelegate* delegate) |
| + WebIntentPickerDelegate* delegate, |
| + WebIntentPickerModel* model) |
| : wrapper_(wrapper), |
| delegate_(delegate), |
| + model_(model), |
| contents_(NULL), |
| - button_hbox_(NULL), |
| + button_vbox_(NULL), |
| bubble_(NULL), |
| browser_(browser) { |
| DCHECK(delegate_ != NULL); |
| DCHECK(browser); |
| DCHECK(browser->window()); |
| + |
| + model_->set_observer(this); |
| + |
| BrowserWindowGtk* browser_window = |
| BrowserWindowGtk::GetBrowserWindowForNativeWindow( |
| browser->window()->GetNativeHandle()); |
| @@ -121,53 +118,97 @@ WebIntentPickerGtk::~WebIntentPickerGtk() { |
| DCHECK(bubble_ == NULL) << "Should have closed window before destroying."; |
| } |
| -void WebIntentPickerGtk::SetServiceURLs(const std::vector<GURL>& urls) { |
| - for (size_t i = 0; i < urls.size(); ++i) { |
| +void WebIntentPickerGtk::OnModelChanged(WebIntentPickerModel* model) { |
| + gtk_util::RemoveAllChildren(button_vbox_); |
| + |
| + for (size_t i = 0; i < model->GetItemCount(); ++i) { |
| + const WebIntentPickerModel::Item& item = model->GetItemAt(i); |
| + |
| GtkWidget* button = gtk_button_new(); |
| - gtk_widget_set_tooltip_text(button, urls[i].spec().c_str()); |
| - gtk_box_pack_start(GTK_BOX(button_hbox_), button, FALSE, FALSE, 0); |
| + |
| + gtk_widget_set_tooltip_text(button, item.url.spec().c_str()); |
| + gtk_button_set_label(GTK_BUTTON(button), UTF16ToUTF8(item.title).c_str()); |
| + |
| + gtk_box_pack_start(GTK_BOX(button_vbox_), button, FALSE, FALSE, 0); |
| g_signal_connect(button, |
| "clicked", |
| G_CALLBACK(OnServiceButtonClickThunk), |
| this); |
| - } |
| - // Add the '+' button, to use the Chrome Web Store. |
| - GtkWidget* plus_button = gtk_button_new(); |
| - gtk_widget_set_tooltip_text( |
| - plus_button, |
| - l10n_util::GetStringUTF8(IDS_FIND_MORE_INTENT_HANDLER_TOOLTIP).c_str()); |
| - gtk_box_pack_start(GTK_BOX(button_hbox_), plus_button, FALSE, FALSE, 0); |
| + SetServiceButtonImage(button, item.favicon.ToGdkPixbuf()); |
| + } |
| - ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); |
| - GdkPixbuf* icon_pixbuf = rb.GetNativeImageNamed(IDR_SIDETABS_NEW_TAB); |
| - SetServiceButtonImage(plus_button, icon_pixbuf); |
| + gtk_widget_show_all(button_vbox_); |
| +} |
| - gtk_widget_show_all(button_hbox_); |
| +void WebIntentPickerGtk::OnFaviconChanged(WebIntentPickerModel* model, |
| + size_t index) { |
| + const WebIntentPickerModel::Item& item = model->GetItemAt(index); |
| + GtkWidget* button = GetServiceButton(index); |
| + SetServiceButtonImage(button, item.favicon.ToGdkPixbuf()); |
| } |
| -void WebIntentPickerGtk::SetServiceIcon(size_t index, const SkBitmap& icon) { |
| - if (icon.empty()) |
| - return; |
| +void WebIntentPickerGtk::OnInlineDisposition(WebIntentPickerModel* model) { |
| + const WebIntentPickerModel::Item& item = model->GetItemAt( |
| + model->inline_disposition_index()); |
| + const GURL& url = item.url; |
| - GtkWidget* button = GetServiceButton(index); |
| + content::WebContents* web_contents = content::WebContents::Create( |
| + browser_->profile(), NULL, MSG_ROUTING_NONE, NULL, NULL); |
| + inline_disposition_tab_contents_.reset(new TabContentsWrapper(web_contents)); |
| + inline_disposition_delegate_.reset(new InlineDispositionDelegate); |
| + web_contents->SetDelegate(inline_disposition_delegate_.get()); |
| + tab_contents_container_.reset(new TabContentsContainerGtk(NULL)); |
| + tab_contents_container_->SetTab(inline_disposition_tab_contents_.get()); |
| - GdkPixbuf* icon_pixbuf = gfx::GdkPixbufFromSkBitmap(&icon); |
| - SetServiceButtonImage(button, icon_pixbuf); |
| - g_object_unref(icon_pixbuf); |
| -} |
| + inline_disposition_tab_contents_->web_contents()->GetController().LoadURL( |
| + url, content::Referrer(), content::PAGE_TRANSITION_START_PAGE, |
| + std::string()); |
| -void WebIntentPickerGtk::SetDefaultServiceIcon(size_t index) { |
| - GtkWidget* button = GetServiceButton(index); |
| + // Replace the bubble picker contents with the inline disposition. |
| + |
| + gtk_util::RemoveAllChildren(contents_); |
| + |
| + GtkWidget* service_hbox = gtk_hbox_new(FALSE, ui::kControlSpacing); |
| + // TODO(gbillock): Eventually get the service icon button here. |
| + // Maybe add a title or something too? |
| + close_button_.reset( |
| + CustomDrawButton::CloseButton(GetThemeService(wrapper_))); |
| + g_signal_connect(close_button_->widget(), |
| + "clicked", |
| + G_CALLBACK(OnCloseButtonClickThunk), |
| + this); |
| + gtk_widget_set_can_focus(close_button_->widget(), FALSE); |
| + GtkWidget* close_vbox = gtk_vbox_new(FALSE, 0); |
| + gtk_box_pack_start(GTK_BOX(close_vbox), close_button_->widget(), |
| + FALSE, FALSE, 0); |
| + gtk_box_pack_end(GTK_BOX(service_hbox), close_vbox, FALSE, FALSE, 0); |
| + |
| + GtkWidget* vbox = gtk_vbox_new(FALSE, ui::kContentAreaSpacing); |
| + gtk_box_pack_start(GTK_BOX(vbox), service_hbox, TRUE, TRUE, 0); |
| + |
| + // The separator between the icon/title/close and the inline renderer. |
| + gtk_box_pack_start(GTK_BOX(vbox), gtk_hseparator_new(), FALSE, TRUE, 0); |
| + |
| + gtk_box_pack_end(GTK_BOX(vbox), tab_contents_container_->widget(), |
| + TRUE, TRUE, 0); |
| + |
| + gtk_container_add(GTK_CONTAINER(contents_), vbox); |
| + |
| + // TODO(gbillock): This size calculation needs more thought. |
| + // Move up to WebIntentPicker? |
| + gfx::Size tab_size = wrapper_->web_contents()->GetView()->GetContainerSize(); |
| + int width = std::max(tab_size.width()/2, kMainContentWidth); |
| + int height = std::max(tab_size.height()/2, kMainContentWidth); |
| + gtk_widget_set_size_request(tab_contents_container_->widget(), |
| + width, height); |
| + gtk_widget_show_all(contents_); |
| - ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); |
| - GdkPixbuf* icon_pixbuf = rb.GetNativeImageNamed(IDR_DEFAULT_FAVICON); |
| - SetServiceButtonImage(button, icon_pixbuf); |
| + delegate_->OnInlineDispositionWebContentsCreated(web_contents); |
| } |
| void WebIntentPickerGtk::Close() { |
| bubble_->Close(); |
| - bubble_ = NULL; |
| if (inline_disposition_tab_contents_.get()) |
| inline_disposition_tab_contents_->web_contents()->OnCloseStarted(); |
| } |
| @@ -182,12 +223,22 @@ void WebIntentPickerGtk::OnCloseButtonClick(GtkWidget* button) { |
| delegate_->OnClosing(); |
| } |
| +void WebIntentPickerGtk::OnDestroy(GtkWidget* button) { |
| + // Destroy this object when the BubbleGtk is destroyed. It can't be "delete |
| + // this" because this function happens in a callback. |
| + MessageLoop::current()->DeleteSoon(FROM_HERE, this); |
| + model_->set_observer(NULL); |
| + bubble_ = NULL; |
| +} |
| + |
| void WebIntentPickerGtk::OnServiceButtonClick(GtkWidget* button) { |
| - GList* button_list = gtk_container_get_children(GTK_CONTAINER(button_hbox_)); |
| + GList* button_list = gtk_container_get_children(GTK_CONTAINER(button_vbox_)); |
| gint index = g_list_index(button_list, button); |
| DCHECK(index != -1); |
| - delegate_->OnServiceChosen(static_cast<size_t>(index)); |
| + const WebIntentPickerModel::Item& item = model_->GetItemAt(index); |
| + |
| + delegate_->OnServiceChosen(static_cast<size_t>(index), item.disposition); |
| } |
| void WebIntentPickerGtk::InitContents() { |
| @@ -197,12 +248,6 @@ void WebIntentPickerGtk::InitContents() { |
| gtk_container_set_border_width(GTK_CONTAINER(contents_), |
| ui::kContentAreaBorder); |
| - ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); |
| - GdkPixbuf* image_pixbuf = rb.GetNativeImageNamed(IDR_PAGEINFO_INFO); |
| - GtkWidget* image = gtk_image_new_from_pixbuf(image_pixbuf); |
| - gtk_box_pack_start(GTK_BOX(contents_), image, FALSE, FALSE, 0); |
| - gtk_misc_set_alignment(GTK_MISC(image), 0, 0); |
| - |
| GtkWidget* vbox = gtk_vbox_new(FALSE, ui::kContentAreaSpacing); |
| GtkWidget* label = theme_service->BuildLabel( |
| @@ -213,8 +258,8 @@ void WebIntentPickerGtk::InitContents() { |
| gtk_widget_set_size_request(vbox, kMainContentWidth, -1); |
| - button_hbox_ = gtk_hbox_new(FALSE, ui::kControlSpacing); |
| - gtk_box_pack_start(GTK_BOX(vbox), button_hbox_, TRUE, TRUE, 0); |
| + button_vbox_ = gtk_vbox_new(FALSE, ui::kControlSpacing); |
| + gtk_box_pack_start(GTK_BOX(vbox), button_vbox_, TRUE, TRUE, 0); |
| GtkWidget* cws_label = theme_service->BuildLabel( |
| l10n_util::GetStringUTF8(IDS_FIND_MORE_INTENT_HANDLER_MESSAGE).c_str(), |
| @@ -238,70 +283,11 @@ void WebIntentPickerGtk::InitContents() { |
| gtk_box_pack_start(GTK_BOX(close_vbox), close_button_->widget(), FALSE, FALSE, |
| 0); |
| gtk_box_pack_end(GTK_BOX(contents_), close_vbox, FALSE, FALSE, 0); |
| -} |
| - |
| -void RemoveAllHelper(GtkWidget* widget, gpointer data) { |
| - GtkWidget* parent = gtk_widget_get_parent(widget); |
| - gtk_container_remove(GTK_CONTAINER(parent), widget); |
| -} |
| - |
| -WebContents* WebIntentPickerGtk::SetInlineDisposition(const GURL& url) { |
| - WebContents* web_contents = WebContents::Create( |
| - browser_->profile(), NULL, MSG_ROUTING_NONE, NULL, NULL); |
| - inline_disposition_tab_contents_.reset(new TabContentsWrapper(web_contents)); |
| - inline_disposition_delegate_.reset(new InlineDispositionDelegate); |
| - web_contents->SetDelegate(inline_disposition_delegate_.get()); |
| - tab_contents_container_.reset(new TabContentsContainerGtk(NULL)); |
| - tab_contents_container_->SetTab(inline_disposition_tab_contents_.get()); |
| - |
| - inline_disposition_tab_contents_->web_contents()->GetController().LoadURL( |
| - url, content::Referrer(), content::PAGE_TRANSITION_START_PAGE, |
| - std::string()); |
| - |
| - // Replace the bubble picker contents with the inline disposition. |
| - |
| - gtk_container_foreach(GTK_CONTAINER(contents_), RemoveAllHelper, NULL); |
| - |
| - GtkWidget* service_hbox = gtk_hbox_new(FALSE, ui::kControlSpacing); |
| - // TODO(gbillock): Eventually get the service icon button here. |
| - // Maybe add a title or something too? |
| - close_button_.reset( |
| - CustomDrawButton::CloseButton(GetThemeService(wrapper_))); |
| - g_signal_connect(close_button_->widget(), |
| - "clicked", |
| - G_CALLBACK(OnCloseButtonClickThunk), |
| - this); |
| - gtk_widget_set_can_focus(close_button_->widget(), FALSE); |
| - GtkWidget* close_vbox = gtk_vbox_new(FALSE, 0); |
| - gtk_box_pack_start(GTK_BOX(close_vbox), close_button_->widget(), |
| - FALSE, FALSE, 0); |
| - gtk_box_pack_end(GTK_BOX(service_hbox), close_vbox, FALSE, FALSE, 0); |
| - |
| - GtkWidget* vbox = gtk_vbox_new(FALSE, ui::kContentAreaSpacing); |
| - gtk_box_pack_start(GTK_BOX(vbox), service_hbox, TRUE, TRUE, 0); |
| - |
| - // The separator between the icon/title/close and the inline renderer. |
| - gtk_box_pack_start(GTK_BOX(vbox), gtk_hseparator_new(), FALSE, TRUE, 0); |
| - |
| - gtk_box_pack_end(GTK_BOX(vbox), tab_contents_container_->widget(), |
| - TRUE, TRUE, 0); |
| - |
| - gtk_container_add(GTK_CONTAINER(contents_), vbox); |
| - |
| - // TODO(gbillock): This size calculation needs more thought. |
| - // Move up to WebIntentPicker? |
| - gfx::Size tab_size = wrapper_->web_contents()->GetView()->GetContainerSize(); |
| - int width = std::max(tab_size.width()/2, kMainContentWidth); |
| - int height = std::max(tab_size.height()/2, kMainContentWidth); |
| - gtk_widget_set_size_request(tab_contents_container_->widget(), |
| - width, height); |
| - gtk_widget_show_all(contents_); |
| - |
| - return inline_disposition_tab_contents_->web_contents(); |
| + g_signal_connect(contents_, "destroy", G_CALLBACK(&OnDestroyThunk), this); |
| } |
| GtkWidget* WebIntentPickerGtk::GetServiceButton(size_t index) { |
| - GList* button_list = gtk_container_get_children(GTK_CONTAINER(button_hbox_)); |
| + GList* button_list = gtk_container_get_children(GTK_CONTAINER(button_vbox_)); |
| GtkWidget* button = GTK_WIDGET(g_list_nth_data(button_list, index)); |
| DCHECK(button != NULL); |
| @@ -313,7 +299,6 @@ GtkWidget* WebIntentPickerGtk::GetServiceButton(size_t index) { |
| WebIntentPickerGtk::InlineDispositionDelegate::InlineDispositionDelegate() {} |
| WebIntentPickerGtk::InlineDispositionDelegate::~InlineDispositionDelegate() {} |
| - |
| bool WebIntentPickerGtk::InlineDispositionDelegate::IsPopupOrPanel( |
| const WebContents* source) const { |
| return true; |