Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/ui/gtk/web_intent_picker_gtk.h" | 5 #include "chrome/browser/ui/gtk/web_intent_picker_gtk.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/callback.h" | 10 #include "base/callback.h" |
| 11 #include "base/utf_string_conversions.h" | |
| 11 #include "chrome/browser/favicon/favicon_service.h" | 12 #include "chrome/browser/favicon/favicon_service.h" |
| 12 #include "chrome/browser/profiles/profile.h" | 13 #include "chrome/browser/profiles/profile.h" |
| 13 #include "chrome/browser/ui/browser.h" | 14 #include "chrome/browser/ui/browser.h" |
| 14 #include "chrome/browser/ui/browser_window.h" | 15 #include "chrome/browser/ui/browser_window.h" |
| 15 #include "chrome/browser/ui/gtk/browser_toolbar_gtk.h" | 16 #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/browser_window_gtk.h" |
| 17 #include "chrome/browser/ui/gtk/custom_button.h" | 18 #include "chrome/browser/ui/gtk/custom_button.h" |
| 18 #include "chrome/browser/ui/gtk/gtk_theme_service.h" | 19 #include "chrome/browser/ui/gtk/gtk_theme_service.h" |
| 19 #include "chrome/browser/ui/gtk/gtk_util.h" | 20 #include "chrome/browser/ui/gtk/gtk_util.h" |
| 20 #include "chrome/browser/ui/gtk/location_bar_view_gtk.h" | 21 #include "chrome/browser/ui/gtk/location_bar_view_gtk.h" |
| 21 #include "chrome/browser/ui/gtk/tab_contents_container_gtk.h" | 22 #include "chrome/browser/ui/gtk/tab_contents_container_gtk.h" |
| 22 #include "chrome/browser/ui/intents/web_intent_picker_controller.h" | 23 #include "chrome/browser/ui/intents/web_intent_picker_controller.h" |
| 23 #include "chrome/browser/ui/intents/web_intent_picker_delegate.h" | 24 #include "chrome/browser/ui/intents/web_intent_picker_delegate.h" |
| 25 #include "chrome/browser/ui/intents/web_intent_picker_model.h" | |
| 24 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" | 26 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" |
| 25 #include "content/browser/renderer_host/render_view_host.h" | 27 #include "content/browser/renderer_host/render_view_host.h" |
| 26 #include "content/browser/renderer_host/render_widget_host_view_gtk.h" | 28 #include "content/browser/renderer_host/render_widget_host_view_gtk.h" |
| 27 #include "content/public/browser/notification_registrar.h" | 29 #include "content/public/browser/notification_registrar.h" |
| 28 #include "content/public/browser/notification_source.h" | 30 #include "content/public/browser/notification_source.h" |
| 29 #include "content/public/browser/notification_types.h" | 31 #include "content/public/browser/notification_types.h" |
| 30 #include "content/public/browser/web_contents.h" | 32 #include "content/public/browser/web_contents.h" |
| 31 #include "content/public/browser/web_contents_view.h" | 33 #include "content/public/browser/web_contents_view.h" |
| 32 #include "googleurl/src/gurl.h" | 34 #include "googleurl/src/gurl.h" |
| 33 #include "grit/generated_resources.h" | 35 #include "grit/generated_resources.h" |
| 34 #include "grit/theme_resources.h" | |
| 35 #include "grit/theme_resources_standard.h" | |
| 36 #include "grit/ui_resources.h" | |
| 37 #include "ui/base/gtk/gtk_hig_constants.h" | 36 #include "ui/base/gtk/gtk_hig_constants.h" |
| 38 #include "ui/base/l10n/l10n_util.h" | 37 #include "ui/base/l10n/l10n_util.h" |
| 39 #include "ui/base/resource/resource_bundle.h" | 38 #include "ui/base/resource/resource_bundle.h" |
| 40 #include "ui/gfx/gtk_util.h" | 39 #include "ui/gfx/gtk_util.h" |
| 41 #include "ui/gfx/image/image.h" | 40 #include "ui/gfx/image/image.h" |
| 42 | 41 |
| 43 using content::WebContents; | 42 using content::WebContents; |
| 44 | 43 |
| 45 namespace { | 44 namespace { |
| 46 | 45 |
| 47 // The width in pixels of the area between the icon on the left and the close | 46 // The width in pixels of the area between the icon on the left and the close |
| 48 // button on the right. | 47 // button on the right. |
| 49 const int kMainContentWidth = 300; | 48 const int kMainContentWidth = 300; |
| 50 | 49 |
| 51 // The length in pixels of the label at the bottom of the picker. Text longer | 50 // The length in pixels of the label at the bottom of the picker. Text longer |
| 52 // than this width will wrap. | 51 // than this width will wrap. |
| 53 const int kWebStoreLabelLength = 300; | 52 const int kWebStoreLabelLength = 300; |
| 54 | 53 |
| 55 // The pixel size of the label at the bottom of the picker. | 54 // The pixel size of the label at the bottom of the picker. |
| 56 const int kWebStoreLabelPixelSize = 11; | 55 const int kWebStoreLabelPixelSize = 11; |
| 57 | 56 |
| 58 // How much to scale the the buttons up from their favicon size. | |
| 59 const int kServiceButtonScale = 3; | |
| 60 | |
| 61 GtkThemeService *GetThemeService(TabContentsWrapper* wrapper) { | 57 GtkThemeService *GetThemeService(TabContentsWrapper* wrapper) { |
| 62 return GtkThemeService::GetFrom(wrapper->profile()); | 58 return GtkThemeService::GetFrom(wrapper->profile()); |
| 63 } | 59 } |
| 64 | 60 |
| 65 // Set the image of |button| to |pixbuf|, and scale the button up by | 61 // Set the image of |button| to |pixbuf|, and scale the button up by |
| 66 // |kServiceButtonScale|. | 62 // |kServiceButtonScale|. |
| 67 void SetServiceButtonImage(GtkWidget* button, GdkPixbuf* pixbuf) { | 63 void SetServiceButtonImage(GtkWidget* button, GdkPixbuf* pixbuf) { |
| 68 int width = gdk_pixbuf_get_width(pixbuf); | 64 gtk_button_set_image(GTK_BUTTON(button), gtk_image_new_from_pixbuf(pixbuf)); |
| 69 int height = gdk_pixbuf_get_height(pixbuf); | 65 gtk_button_set_image_position(GTK_BUTTON(button), GTK_POS_LEFT); |
| 70 gtk_button_set_image(GTK_BUTTON(button), | 66 } |
| 71 gtk_image_new_from_pixbuf(pixbuf)); | 67 |
| 72 gtk_widget_set_size_request(button, | 68 // This helper function removes a widget from its parent container widget. |
| 73 width * kServiceButtonScale, | 69 void RemoveAllHelper(GtkWidget* widget, gpointer data) { |
| 74 height * kServiceButtonScale); | 70 GtkWidget* parent = gtk_widget_get_parent(widget); |
| 71 gtk_container_remove(GTK_CONTAINER(parent), widget); | |
| 75 } | 72 } |
| 76 | 73 |
| 77 } // namespace | 74 } // namespace |
| 78 | 75 |
| 79 // static | 76 // static |
| 80 WebIntentPicker* WebIntentPicker::Create(Browser* browser, | 77 WebIntentPicker* WebIntentPicker::Create(Browser* browser, |
| 81 TabContentsWrapper* wrapper, | 78 TabContentsWrapper* wrapper, |
| 82 WebIntentPickerDelegate* delegate) { | 79 WebIntentPickerDelegate* delegate, |
| 83 return new WebIntentPickerGtk(browser, wrapper, delegate); | 80 WebIntentPickerModel* model) { |
| 81 return new WebIntentPickerGtk(browser, wrapper, delegate, model); | |
| 84 } | 82 } |
| 85 | 83 |
| 86 WebIntentPickerGtk::WebIntentPickerGtk(Browser* browser, | 84 WebIntentPickerGtk::WebIntentPickerGtk(Browser* browser, |
| 87 TabContentsWrapper* wrapper, | 85 TabContentsWrapper* wrapper, |
| 88 WebIntentPickerDelegate* delegate) | 86 WebIntentPickerDelegate* delegate, |
| 87 WebIntentPickerModel* model) | |
| 89 : wrapper_(wrapper), | 88 : wrapper_(wrapper), |
| 90 delegate_(delegate), | 89 delegate_(delegate), |
| 90 model_(model), | |
| 91 contents_(NULL), | 91 contents_(NULL), |
| 92 button_hbox_(NULL), | 92 button_vbox_(NULL), |
| 93 bubble_(NULL), | 93 bubble_(NULL), |
| 94 browser_(browser) { | 94 browser_(browser) { |
| 95 DCHECK(delegate_ != NULL); | 95 DCHECK(delegate_ != NULL); |
| 96 DCHECK(browser); | 96 DCHECK(browser); |
| 97 DCHECK(browser->window()); | 97 DCHECK(browser->window()); |
| 98 | |
| 99 model_->set_observer(this); | |
| 100 | |
| 98 BrowserWindowGtk* browser_window = | 101 BrowserWindowGtk* browser_window = |
| 99 BrowserWindowGtk::GetBrowserWindowForNativeWindow( | 102 BrowserWindowGtk::GetBrowserWindowForNativeWindow( |
| 100 browser->window()->GetNativeHandle()); | 103 browser->window()->GetNativeHandle()); |
| 101 | 104 |
| 102 GtkWidget* anchor = browser_window-> | 105 GtkWidget* anchor = browser_window-> |
| 103 GetToolbar()->GetLocationBarView()->location_icon_widget(); | 106 GetToolbar()->GetLocationBarView()->location_icon_widget(); |
| 104 | 107 |
| 105 InitContents(); | 108 InitContents(); |
| 106 | 109 |
| 107 BubbleGtk::ArrowLocationGtk arrow_location = base::i18n::IsRTL() ? | 110 BubbleGtk::ArrowLocationGtk arrow_location = base::i18n::IsRTL() ? |
| 108 BubbleGtk::ARROW_LOCATION_TOP_RIGHT : | 111 BubbleGtk::ARROW_LOCATION_TOP_RIGHT : |
| 109 BubbleGtk::ARROW_LOCATION_TOP_LEFT; | 112 BubbleGtk::ARROW_LOCATION_TOP_LEFT; |
| 110 bubble_ = BubbleGtk::Show(anchor, | 113 bubble_ = BubbleGtk::Show(anchor, |
| 111 NULL, // |rect| | 114 NULL, // |rect| |
| 112 contents_, | 115 contents_, |
| 113 arrow_location, | 116 arrow_location, |
| 114 true, // |match_system_theme| | 117 true, // |match_system_theme| |
| 115 true, // |grab_input| | 118 true, // |grab_input| |
| 116 GetThemeService(wrapper), | 119 GetThemeService(wrapper), |
| 117 this); // |delegate| | 120 this); // |delegate| |
| 118 } | 121 } |
| 119 | 122 |
| 120 WebIntentPickerGtk::~WebIntentPickerGtk() { | 123 WebIntentPickerGtk::~WebIntentPickerGtk() { |
| 121 DCHECK(bubble_ == NULL) << "Should have closed window before destroying."; | 124 DCHECK(bubble_ == NULL) << "Should have closed window before destroying."; |
| 122 } | 125 } |
| 123 | 126 |
| 124 void WebIntentPickerGtk::SetServiceURLs(const std::vector<GURL>& urls) { | 127 void WebIntentPickerGtk::OnModelChanged(WebIntentPickerModel* model) { |
| 125 for (size_t i = 0; i < urls.size(); ++i) { | 128 RemoveAllFrom(button_vbox_); |
| 129 | |
| 130 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | |
| 131 | |
| 132 for (size_t i = 0; i < model->GetItemCount(); ++i) { | |
| 133 const WebIntentPickerModel::Item& item = model->GetItemAt(i); | |
| 134 | |
| 126 GtkWidget* button = gtk_button_new(); | 135 GtkWidget* button = gtk_button_new(); |
| 127 gtk_widget_set_tooltip_text(button, urls[i].spec().c_str()); | 136 |
| 128 gtk_box_pack_start(GTK_BOX(button_hbox_), button, FALSE, FALSE, 0); | 137 gtk_widget_set_tooltip_text(button, item.url.spec().c_str()); |
| 138 gtk_button_set_label(GTK_BUTTON(button), UTF16ToUTF8(item.title).c_str()); | |
| 139 | |
| 140 gtk_box_pack_start(GTK_BOX(button_vbox_), button, FALSE, FALSE, 0); | |
| 129 g_signal_connect(button, | 141 g_signal_connect(button, |
| 130 "clicked", | 142 "clicked", |
| 131 G_CALLBACK(OnServiceButtonClickThunk), | 143 G_CALLBACK(OnServiceButtonClickThunk), |
| 132 this); | 144 this); |
| 145 | |
| 146 SetServiceButtonImage(button, item.favicon.ToGdkPixbuf()); | |
| 133 } | 147 } |
| 134 | 148 |
| 135 // Add the '+' button, to use the Chrome Web Store. | 149 gtk_widget_show_all(button_vbox_); |
| 136 GtkWidget* plus_button = gtk_button_new(); | |
| 137 gtk_widget_set_tooltip_text( | |
| 138 plus_button, | |
| 139 l10n_util::GetStringUTF8(IDS_FIND_MORE_INTENT_HANDLER_TOOLTIP).c_str()); | |
| 140 gtk_box_pack_start(GTK_BOX(button_hbox_), plus_button, FALSE, FALSE, 0); | |
| 141 | |
| 142 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | |
| 143 GdkPixbuf* icon_pixbuf = rb.GetNativeImageNamed(IDR_SIDETABS_NEW_TAB); | |
| 144 SetServiceButtonImage(plus_button, icon_pixbuf); | |
| 145 | |
| 146 gtk_widget_show_all(button_hbox_); | |
| 147 } | 150 } |
| 148 | 151 |
| 149 void WebIntentPickerGtk::SetServiceIcon(size_t index, const SkBitmap& icon) { | 152 void WebIntentPickerGtk::OnFaviconChanged(WebIntentPickerModel* model, |
| 150 if (icon.empty()) | 153 size_t index) { |
| 151 return; | 154 const WebIntentPickerModel::Item& item = model->GetItemAt(index); |
| 152 | |
| 153 GtkWidget* button = GetServiceButton(index); | 155 GtkWidget* button = GetServiceButton(index); |
| 154 | 156 SetServiceButtonImage(button, item.favicon.ToGdkPixbuf()); |
| 155 GdkPixbuf* icon_pixbuf = gfx::GdkPixbufFromSkBitmap(&icon); | |
| 156 SetServiceButtonImage(button, icon_pixbuf); | |
| 157 g_object_unref(icon_pixbuf); | |
| 158 } | 157 } |
| 159 | 158 |
| 160 void WebIntentPickerGtk::SetDefaultServiceIcon(size_t index) { | 159 void WebIntentPickerGtk::OnInlineDisposition(WebIntentPickerModel* model) { |
| 161 GtkWidget* button = GetServiceButton(index); | 160 const WebIntentPickerModel::Item& item = model->GetItemAt( |
| 161 model->inline_disposition_index()); | |
| 162 const GURL& url = item.url; | |
| 162 | 163 |
| 163 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | 164 content::WebContents* web_contents = content::WebContents::Create( |
| 164 GdkPixbuf* icon_pixbuf = rb.GetNativeImageNamed(IDR_DEFAULT_FAVICON); | 165 browser_->profile(), NULL, MSG_ROUTING_NONE, NULL, NULL); |
| 165 SetServiceButtonImage(button, icon_pixbuf); | 166 inline_disposition_tab_contents_.reset(new TabContentsWrapper(web_contents)); |
| 167 inline_disposition_delegate_.reset(new InlineDispositionDelegate); | |
| 168 web_contents->SetDelegate(inline_disposition_delegate_.get()); | |
| 169 tab_contents_container_.reset(new TabContentsContainerGtk(NULL)); | |
| 170 tab_contents_container_->SetTab(inline_disposition_tab_contents_.get()); | |
| 171 | |
| 172 inline_disposition_tab_contents_->web_contents()->GetController().LoadURL( | |
| 173 url, content::Referrer(), content::PAGE_TRANSITION_START_PAGE, | |
| 174 std::string()); | |
| 175 | |
| 176 // Replace the bubble picker contents with the inline disposition. | |
| 177 | |
| 178 RemoveAllFrom(contents_); | |
| 179 | |
| 180 GtkWidget* service_hbox = gtk_hbox_new(FALSE, ui::kControlSpacing); | |
| 181 // TODO(gbillock): Eventually get the service icon button here. | |
| 182 // Maybe add a title or something too? | |
| 183 close_button_.reset( | |
| 184 CustomDrawButton::CloseButton(GetThemeService(wrapper_))); | |
| 185 g_signal_connect(close_button_->widget(), | |
| 186 "clicked", | |
| 187 G_CALLBACK(OnCloseButtonClickThunk), | |
| 188 this); | |
| 189 gtk_widget_set_can_focus(close_button_->widget(), FALSE); | |
| 190 GtkWidget* close_vbox = gtk_vbox_new(FALSE, 0); | |
| 191 gtk_box_pack_start(GTK_BOX(close_vbox), close_button_->widget(), | |
| 192 FALSE, FALSE, 0); | |
| 193 gtk_box_pack_end(GTK_BOX(service_hbox), close_vbox, FALSE, FALSE, 0); | |
| 194 | |
| 195 GtkWidget* vbox = gtk_vbox_new(FALSE, ui::kContentAreaSpacing); | |
| 196 gtk_box_pack_start(GTK_BOX(vbox), service_hbox, TRUE, TRUE, 0); | |
| 197 | |
| 198 // The separator between the icon/title/close and the inline renderer. | |
| 199 gtk_box_pack_start(GTK_BOX(vbox), gtk_hseparator_new(), FALSE, TRUE, 0); | |
| 200 | |
| 201 gtk_box_pack_end(GTK_BOX(vbox), tab_contents_container_->widget(), | |
| 202 TRUE, TRUE, 0); | |
| 203 | |
| 204 gtk_container_add(GTK_CONTAINER(contents_), vbox); | |
| 205 | |
| 206 // TODO(gbillock): This size calculation needs more thought. | |
| 207 // Move up to WebIntentPicker? | |
| 208 gfx::Size tab_size = wrapper_->web_contents()->GetView()->GetContainerSize(); | |
| 209 int width = std::max(tab_size.width()/2, kMainContentWidth); | |
| 210 int height = std::max(tab_size.height()/2, kMainContentWidth); | |
| 211 gtk_widget_set_size_request(tab_contents_container_->widget(), | |
| 212 width, height); | |
| 213 gtk_widget_show_all(contents_); | |
| 214 | |
| 215 delegate_->OnInlineDispositionWebContentsCreated(web_contents); | |
| 166 } | 216 } |
| 167 | 217 |
| 168 void WebIntentPickerGtk::Close() { | 218 void WebIntentPickerGtk::Close() { |
| 169 bubble_->Close(); | 219 bubble_->Close(); |
| 170 bubble_ = NULL; | |
| 171 if (inline_disposition_tab_contents_.get()) | 220 if (inline_disposition_tab_contents_.get()) |
| 172 inline_disposition_tab_contents_->web_contents()->OnCloseStarted(); | 221 inline_disposition_tab_contents_->web_contents()->OnCloseStarted(); |
| 173 } | 222 } |
| 174 | 223 |
| 175 void WebIntentPickerGtk::BubbleClosing(BubbleGtk* bubble, | 224 void WebIntentPickerGtk::BubbleClosing(BubbleGtk* bubble, |
| 176 bool closed_by_escape) { | 225 bool closed_by_escape) { |
| 177 delegate_->OnClosing(); | 226 delegate_->OnClosing(); |
| 178 } | 227 } |
| 179 | 228 |
| 180 void WebIntentPickerGtk::OnCloseButtonClick(GtkWidget* button) { | 229 void WebIntentPickerGtk::OnCloseButtonClick(GtkWidget* button) { |
| 181 delegate_->OnCancelled(); | 230 delegate_->OnCancelled(); |
| 182 delegate_->OnClosing(); | 231 delegate_->OnClosing(); |
| 183 } | 232 } |
| 184 | 233 |
| 234 void WebIntentPickerGtk::OnDestroy(GtkWidget* button) { | |
| 235 // Destroy this object when the BubbleGtk is destroyed. It can't be "delete | |
| 236 // this" because this function happens in a callback. | |
| 237 MessageLoop::current()->DeleteSoon(FROM_HERE, this); | |
| 238 model_->set_observer(NULL); | |
| 239 bubble_ = NULL; | |
| 240 } | |
| 241 | |
| 185 void WebIntentPickerGtk::OnServiceButtonClick(GtkWidget* button) { | 242 void WebIntentPickerGtk::OnServiceButtonClick(GtkWidget* button) { |
| 186 GList* button_list = gtk_container_get_children(GTK_CONTAINER(button_hbox_)); | 243 GList* button_list = gtk_container_get_children(GTK_CONTAINER(button_vbox_)); |
| 187 gint index = g_list_index(button_list, button); | 244 gint index = g_list_index(button_list, button); |
| 188 DCHECK(index != -1); | 245 DCHECK(index != -1); |
| 189 | 246 |
| 190 delegate_->OnServiceChosen(static_cast<size_t>(index)); | 247 const WebIntentPickerModel::Item& item = model_->GetItemAt(index); |
| 248 | |
| 249 delegate_->OnServiceChosen(static_cast<size_t>(index), item.disposition); | |
| 191 } | 250 } |
| 192 | 251 |
| 193 void WebIntentPickerGtk::InitContents() { | 252 void WebIntentPickerGtk::InitContents() { |
| 194 GtkThemeService* theme_service = GetThemeService(wrapper_); | 253 GtkThemeService* theme_service = GetThemeService(wrapper_); |
| 195 | 254 |
| 196 contents_ = gtk_hbox_new(FALSE, ui::kContentAreaSpacing); | 255 contents_ = gtk_hbox_new(FALSE, ui::kContentAreaSpacing); |
| 197 gtk_container_set_border_width(GTK_CONTAINER(contents_), | 256 gtk_container_set_border_width(GTK_CONTAINER(contents_), |
| 198 ui::kContentAreaBorder); | 257 ui::kContentAreaBorder); |
| 199 | 258 |
| 200 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | |
| 201 GdkPixbuf* image_pixbuf = rb.GetNativeImageNamed(IDR_PAGEINFO_INFO); | |
| 202 GtkWidget* image = gtk_image_new_from_pixbuf(image_pixbuf); | |
| 203 gtk_box_pack_start(GTK_BOX(contents_), image, FALSE, FALSE, 0); | |
| 204 gtk_misc_set_alignment(GTK_MISC(image), 0, 0); | |
| 205 | |
| 206 GtkWidget* vbox = gtk_vbox_new(FALSE, ui::kContentAreaSpacing); | 259 GtkWidget* vbox = gtk_vbox_new(FALSE, ui::kContentAreaSpacing); |
| 207 | 260 |
| 208 GtkWidget* label = theme_service->BuildLabel( | 261 GtkWidget* label = theme_service->BuildLabel( |
| 209 l10n_util::GetStringUTF8(IDS_CHOOSE_INTENT_HANDLER_MESSAGE).c_str(), | 262 l10n_util::GetStringUTF8(IDS_CHOOSE_INTENT_HANDLER_MESSAGE).c_str(), |
| 210 ui::kGdkBlack); | 263 ui::kGdkBlack); |
| 211 gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0); | 264 gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0); |
| 212 gtk_misc_set_alignment(GTK_MISC(label), 0, 0); | 265 gtk_misc_set_alignment(GTK_MISC(label), 0, 0); |
| 213 | 266 |
| 214 gtk_widget_set_size_request(vbox, kMainContentWidth, -1); | 267 gtk_widget_set_size_request(vbox, kMainContentWidth, -1); |
| 215 | 268 |
| 216 button_hbox_ = gtk_hbox_new(FALSE, ui::kControlSpacing); | 269 button_vbox_ = gtk_vbox_new(FALSE, ui::kControlSpacing); |
| 217 gtk_box_pack_start(GTK_BOX(vbox), button_hbox_, TRUE, TRUE, 0); | 270 gtk_box_pack_start(GTK_BOX(vbox), button_vbox_, TRUE, TRUE, 0); |
| 218 | 271 |
| 219 GtkWidget* cws_label = theme_service->BuildLabel( | 272 GtkWidget* cws_label = theme_service->BuildLabel( |
| 220 l10n_util::GetStringUTF8(IDS_FIND_MORE_INTENT_HANDLER_MESSAGE).c_str(), | 273 l10n_util::GetStringUTF8(IDS_FIND_MORE_INTENT_HANDLER_MESSAGE).c_str(), |
| 221 ui::kGdkBlack); | 274 ui::kGdkBlack); |
| 222 gtk_box_pack_start(GTK_BOX(vbox), cws_label, TRUE, TRUE, 0); | 275 gtk_box_pack_start(GTK_BOX(vbox), cws_label, TRUE, TRUE, 0); |
| 223 gtk_misc_set_alignment(GTK_MISC(cws_label), 0, 0); | 276 gtk_misc_set_alignment(GTK_MISC(cws_label), 0, 0); |
| 224 gtk_util::SetLabelWidth(cws_label, kWebStoreLabelLength); | 277 gtk_util::SetLabelWidth(cws_label, kWebStoreLabelLength); |
| 225 gtk_util::ForceFontSizePixels(cws_label, kWebStoreLabelPixelSize); | 278 gtk_util::ForceFontSizePixels(cws_label, kWebStoreLabelPixelSize); |
| 226 | 279 |
| 227 gtk_box_pack_start(GTK_BOX(contents_), vbox, TRUE, TRUE, 0); | 280 gtk_box_pack_start(GTK_BOX(contents_), vbox, TRUE, TRUE, 0); |
| 228 | 281 |
| 229 close_button_.reset( | 282 close_button_.reset( |
| 230 CustomDrawButton::CloseButton(GetThemeService(wrapper_))); | 283 CustomDrawButton::CloseButton(GetThemeService(wrapper_))); |
| 231 g_signal_connect(close_button_->widget(), | 284 g_signal_connect(close_button_->widget(), |
| 232 "clicked", | 285 "clicked", |
| 233 G_CALLBACK(OnCloseButtonClickThunk), | 286 G_CALLBACK(OnCloseButtonClickThunk), |
| 234 this); | 287 this); |
| 235 gtk_widget_set_can_focus(close_button_->widget(), FALSE); | 288 gtk_widget_set_can_focus(close_button_->widget(), FALSE); |
| 236 | 289 |
| 237 GtkWidget* close_vbox = gtk_vbox_new(FALSE, 0); | 290 GtkWidget* close_vbox = gtk_vbox_new(FALSE, 0); |
| 238 gtk_box_pack_start(GTK_BOX(close_vbox), close_button_->widget(), FALSE, FALSE, | 291 gtk_box_pack_start(GTK_BOX(close_vbox), close_button_->widget(), FALSE, FALSE, |
| 239 0); | 292 0); |
| 240 gtk_box_pack_end(GTK_BOX(contents_), close_vbox, FALSE, FALSE, 0); | 293 gtk_box_pack_end(GTK_BOX(contents_), close_vbox, FALSE, FALSE, 0); |
| 241 } | 294 g_signal_connect(contents_, "destroy", G_CALLBACK(&OnDestroyThunk), this); |
| 242 | |
| 243 void RemoveAllHelper(GtkWidget* widget, gpointer data) { | |
| 244 GtkWidget* parent = gtk_widget_get_parent(widget); | |
| 245 gtk_container_remove(GTK_CONTAINER(parent), widget); | |
| 246 } | |
| 247 | |
| 248 WebContents* WebIntentPickerGtk::SetInlineDisposition(const GURL& url) { | |
| 249 WebContents* web_contents = WebContents::Create( | |
| 250 browser_->profile(), NULL, MSG_ROUTING_NONE, NULL, NULL); | |
| 251 inline_disposition_tab_contents_.reset(new TabContentsWrapper(web_contents)); | |
| 252 inline_disposition_delegate_.reset(new InlineDispositionDelegate); | |
| 253 web_contents->SetDelegate(inline_disposition_delegate_.get()); | |
| 254 tab_contents_container_.reset(new TabContentsContainerGtk(NULL)); | |
| 255 tab_contents_container_->SetTab(inline_disposition_tab_contents_.get()); | |
| 256 | |
| 257 inline_disposition_tab_contents_->web_contents()->GetController().LoadURL( | |
| 258 url, content::Referrer(), content::PAGE_TRANSITION_START_PAGE, | |
| 259 std::string()); | |
| 260 | |
| 261 // Replace the bubble picker contents with the inline disposition. | |
| 262 | |
| 263 gtk_container_foreach(GTK_CONTAINER(contents_), RemoveAllHelper, NULL); | |
| 264 | |
| 265 GtkWidget* service_hbox = gtk_hbox_new(FALSE, ui::kControlSpacing); | |
| 266 // TODO(gbillock): Eventually get the service icon button here. | |
| 267 // Maybe add a title or something too? | |
| 268 close_button_.reset( | |
| 269 CustomDrawButton::CloseButton(GetThemeService(wrapper_))); | |
| 270 g_signal_connect(close_button_->widget(), | |
| 271 "clicked", | |
| 272 G_CALLBACK(OnCloseButtonClickThunk), | |
| 273 this); | |
| 274 gtk_widget_set_can_focus(close_button_->widget(), FALSE); | |
| 275 GtkWidget* close_vbox = gtk_vbox_new(FALSE, 0); | |
| 276 gtk_box_pack_start(GTK_BOX(close_vbox), close_button_->widget(), | |
| 277 FALSE, FALSE, 0); | |
| 278 gtk_box_pack_end(GTK_BOX(service_hbox), close_vbox, FALSE, FALSE, 0); | |
| 279 | |
| 280 GtkWidget* vbox = gtk_vbox_new(FALSE, ui::kContentAreaSpacing); | |
| 281 gtk_box_pack_start(GTK_BOX(vbox), service_hbox, TRUE, TRUE, 0); | |
| 282 | |
| 283 // The separator between the icon/title/close and the inline renderer. | |
| 284 gtk_box_pack_start(GTK_BOX(vbox), gtk_hseparator_new(), FALSE, TRUE, 0); | |
| 285 | |
| 286 gtk_box_pack_end(GTK_BOX(vbox), tab_contents_container_->widget(), | |
| 287 TRUE, TRUE, 0); | |
| 288 | |
| 289 gtk_container_add(GTK_CONTAINER(contents_), vbox); | |
| 290 | |
| 291 // TODO(gbillock): This size calculation needs more thought. | |
| 292 // Move up to WebIntentPicker? | |
| 293 gfx::Size tab_size = wrapper_->web_contents()->GetView()->GetContainerSize(); | |
| 294 int width = std::max(tab_size.width()/2, kMainContentWidth); | |
| 295 int height = std::max(tab_size.height()/2, kMainContentWidth); | |
| 296 gtk_widget_set_size_request(tab_contents_container_->widget(), | |
| 297 width, height); | |
| 298 gtk_widget_show_all(contents_); | |
| 299 | |
| 300 return inline_disposition_tab_contents_->web_contents(); | |
| 301 } | 295 } |
| 302 | 296 |
| 303 GtkWidget* WebIntentPickerGtk::GetServiceButton(size_t index) { | 297 GtkWidget* WebIntentPickerGtk::GetServiceButton(size_t index) { |
| 304 GList* button_list = gtk_container_get_children(GTK_CONTAINER(button_hbox_)); | 298 GList* button_list = gtk_container_get_children(GTK_CONTAINER(button_vbox_)); |
| 305 GtkWidget* button = GTK_WIDGET(g_list_nth_data(button_list, index)); | 299 GtkWidget* button = GTK_WIDGET(g_list_nth_data(button_list, index)); |
| 306 DCHECK(button != NULL); | 300 DCHECK(button != NULL); |
| 307 | 301 |
| 308 return button; | 302 return button; |
| 309 } | 303 } |
| 310 | 304 |
| 305 void WebIntentPickerGtk::RemoveAllFrom(GtkWidget* container) { | |
| 306 gtk_container_foreach(GTK_CONTAINER(container), RemoveAllHelper, NULL); | |
|
Elliot Glaysher
2012/01/27 18:30:18
gtk_util::RemoveAllChildren(). declared in chrome/
binji
2012/01/27 19:04:20
Done.
| |
| 307 } | |
| 308 | |
| 311 // WebIntentPickerGtk::InlineDispositionDelegate | 309 // WebIntentPickerGtk::InlineDispositionDelegate |
| 312 | 310 |
| 313 WebIntentPickerGtk::InlineDispositionDelegate::InlineDispositionDelegate() {} | 311 WebIntentPickerGtk::InlineDispositionDelegate::InlineDispositionDelegate() {} |
| 314 WebIntentPickerGtk::InlineDispositionDelegate::~InlineDispositionDelegate() {} | 312 WebIntentPickerGtk::InlineDispositionDelegate::~InlineDispositionDelegate() {} |
| 315 | 313 |
| 316 | |
| 317 bool WebIntentPickerGtk::InlineDispositionDelegate::IsPopupOrPanel( | 314 bool WebIntentPickerGtk::InlineDispositionDelegate::IsPopupOrPanel( |
| 318 const WebContents* source) const { | 315 const WebContents* source) const { |
| 319 return true; | 316 return true; |
| 320 } | 317 } |
| 321 | 318 |
| 322 bool WebIntentPickerGtk::InlineDispositionDelegate:: | 319 bool WebIntentPickerGtk::InlineDispositionDelegate:: |
| 323 ShouldAddNavigationToHistory( | 320 ShouldAddNavigationToHistory( |
| 324 const history::HistoryAddPageArgs& add_page_args, | 321 const history::HistoryAddPageArgs& add_page_args, |
| 325 content::NavigationType navigation_type) { | 322 content::NavigationType navigation_type) { |
| 326 return false; | 323 return false; |
| 327 } | 324 } |
| OLD | NEW |