[email protected] | 5c31135 | 2010-05-07 19:36:15 | [diff] [blame] | 1 | // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
[email protected] | e5f72c7 | 2009-06-05 19:15:33 | [diff] [blame] | 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/gtk/bookmark_utils_gtk.h" |
| 6 | |
[email protected] | f29bbb6 | 2009-08-18 15:37:20 | [diff] [blame] | 7 | #include "app/gtk_dnd_util.h" |
[email protected] | 8098d2d7 | 2009-08-27 22:56:36 | [diff] [blame] | 8 | #include "app/l10n_util.h" |
[email protected] | e5f72c7 | 2009-06-05 19:15:33 | [diff] [blame] | 9 | #include "app/resource_bundle.h" |
[email protected] | e5f72c7 | 2009-06-05 19:15:33 | [diff] [blame] | 10 | #include "base/pickle.h" |
[email protected] | aa7dc4f | 2009-06-29 18:21:33 | [diff] [blame] | 11 | #include "base/string_util.h" |
[email protected] | e5f72c7 | 2009-06-05 19:15:33 | [diff] [blame] | 12 | #include "chrome/browser/bookmarks/bookmark_drag_data.h" |
| 13 | #include "chrome/browser/bookmarks/bookmark_model.h" |
[email protected] | 903e7a8 | 2009-07-28 00:45:35 | [diff] [blame] | 14 | #include "chrome/browser/bookmarks/bookmark_utils.h" |
[email protected] | aa7dc4f | 2009-06-29 18:21:33 | [diff] [blame] | 15 | #include "chrome/browser/gtk/gtk_chrome_button.h" |
[email protected] | 3c78ae92 | 2009-07-07 00:37:08 | [diff] [blame] | 16 | #include "chrome/browser/gtk/gtk_theme_provider.h" |
[email protected] | 16d51df | 2010-03-02 09:16:44 | [diff] [blame] | 17 | #include "chrome/browser/gtk/gtk_util.h" |
[email protected] | e5f72c7 | 2009-06-05 19:15:33 | [diff] [blame] | 18 | #include "chrome/browser/profile.h" |
[email protected] | 302433879 | 2010-06-23 23:04:23 | [diff] [blame] | 19 | #include "gfx/canvas_skia_paint.h" |
[email protected] | 36622b1 | 2010-04-30 23:35:44 | [diff] [blame] | 20 | #include "gfx/font.h" |
[email protected] | 5c7293a | 2010-03-17 06:40:57 | [diff] [blame] | 21 | #include "gfx/gtk_util.h" |
[email protected] | e5f72c7 | 2009-06-05 19:15:33 | [diff] [blame] | 22 | |
[email protected] | aa7dc4f | 2009-06-29 18:21:33 | [diff] [blame] | 23 | namespace { |
| 24 | |
[email protected] | 36622b1 | 2010-04-30 23:35:44 | [diff] [blame] | 25 | // Spacing between the favicon and the text. |
| 26 | const int kBarButtonPadding = 4; |
| 27 | |
[email protected] | e5f72c7 | 2009-06-05 19:15:33 | [diff] [blame] | 28 | // Used in gtk_selection_data_set(). (I assume from this parameter that gtk has |
| 29 | // to some really exotic hardware...) |
| 30 | const int kBitsInAByte = 8; |
| 31 | |
[email protected] | aa7dc4f | 2009-06-29 18:21:33 | [diff] [blame] | 32 | // Maximum number of characters on a bookmark button. |
| 33 | const size_t kMaxCharsOnAButton = 15; |
| 34 | |
[email protected] | 8098d2d7 | 2009-08-27 22:56:36 | [diff] [blame] | 35 | // Max size of each component of the button tooltips. |
| 36 | const size_t kMaxTooltipTitleLength = 100; |
| 37 | const size_t kMaxTooltipURLLength = 400; |
| 38 | |
[email protected] | aa7dc4f | 2009-06-29 18:21:33 | [diff] [blame] | 39 | // Only used for the background of the drag widget. |
| 40 | const GdkColor kBackgroundColor = GDK_COLOR_RGB(0xe6, 0xed, 0xf4); |
| 41 | |
[email protected] | 9f040e43 | 2009-07-10 18:23:58 | [diff] [blame] | 42 | // Padding between the chrome button highlight border and the contents (favicon, |
| 43 | // text). |
[email protected] | 9f040e43 | 2009-07-10 18:23:58 | [diff] [blame] | 44 | const int kButtonPaddingTop = 0; |
| 45 | const int kButtonPaddingBottom = 0; |
[email protected] | ce04ada | 2010-06-16 20:36:15 | [diff] [blame] | 46 | const int kButtonPaddingLeft = 5; |
[email protected] | 9f040e43 | 2009-07-10 18:23:58 | [diff] [blame] | 47 | const int kButtonPaddingRight = 0; |
| 48 | |
[email protected] | aa7dc4f | 2009-06-29 18:21:33 | [diff] [blame] | 49 | void* AsVoid(const BookmarkNode* node) { |
| 50 | return const_cast<BookmarkNode*>(node); |
| 51 | } |
| 52 | |
[email protected] | 36622b1 | 2010-04-30 23:35:44 | [diff] [blame] | 53 | // Creates the widget hierarchy for a bookmark button. |
| 54 | void PackButton(GdkPixbuf* pixbuf, const std::wstring& title, bool ellipsize, |
| 55 | GtkThemeProvider* provider, GtkWidget* button) { |
| 56 | GtkWidget* former_child = gtk_bin_get_child(GTK_BIN(button)); |
| 57 | if (former_child) |
| 58 | gtk_container_remove(GTK_CONTAINER(button), former_child); |
| 59 | |
| 60 | // We pack the button manually (rather than using gtk_button_set_*) so that |
| 61 | // we can have finer control over its label. |
| 62 | GtkWidget* image = gtk_image_new_from_pixbuf(pixbuf); |
| 63 | |
| 64 | GtkWidget* box = gtk_hbox_new(FALSE, kBarButtonPadding); |
| 65 | gtk_box_pack_start(GTK_BOX(box), image, FALSE, FALSE, 0); |
| 66 | |
| 67 | std::string label_string = WideToUTF8(title); |
| 68 | if (!label_string.empty()) { |
| 69 | GtkWidget* label = gtk_label_new(label_string.c_str()); |
| 70 | // Until we switch to vector graphics, force the font size. |
| 71 | gtk_util::ForceFontSizePixels(label, 13.4); // 13.4px == 10pt @ 96dpi |
| 72 | |
| 73 | // Ellipsize long bookmark names. |
| 74 | if (ellipsize) { |
| 75 | gtk_label_set_max_width_chars(GTK_LABEL(label), kMaxCharsOnAButton); |
| 76 | gtk_label_set_ellipsize(GTK_LABEL(label), PANGO_ELLIPSIZE_END); |
| 77 | } |
| 78 | |
| 79 | gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0); |
| 80 | bookmark_utils::SetButtonTextColors(label, provider); |
| 81 | } |
| 82 | |
| 83 | GtkWidget* alignment = gtk_alignment_new(0.0, 0.0, 1.0, 1.0); |
| 84 | // If we are not showing the label, don't set any padding, so that the icon |
| 85 | // will just be centered. |
| 86 | if (label_string.c_str()) { |
| 87 | gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), |
| 88 | kButtonPaddingTop, kButtonPaddingBottom, |
| 89 | kButtonPaddingLeft, kButtonPaddingRight); |
| 90 | } |
| 91 | gtk_container_add(GTK_CONTAINER(alignment), box); |
| 92 | gtk_container_add(GTK_CONTAINER(button), alignment); |
| 93 | |
| 94 | gtk_widget_show_all(alignment); |
| 95 | } |
| 96 | |
| 97 | const int kDragRepresentationWidth = 140; |
| 98 | |
| 99 | struct DragRepresentationData { |
| 100 | public: |
| 101 | GdkPixbuf* favicon; |
| 102 | std::wstring text; |
| 103 | SkColor text_color; |
| 104 | |
| 105 | DragRepresentationData(GdkPixbuf* favicon, |
| 106 | const std::wstring& text, |
| 107 | SkColor text_color) |
| 108 | : favicon(favicon), |
| 109 | text(text), |
| 110 | text_color(text_color) { |
| 111 | g_object_ref(favicon); |
| 112 | } |
| 113 | |
| 114 | ~DragRepresentationData() { |
| 115 | g_object_unref(favicon); |
| 116 | } |
| 117 | |
| 118 | private: |
| 119 | DISALLOW_COPY_AND_ASSIGN(DragRepresentationData); |
| 120 | }; |
| 121 | |
| 122 | gboolean OnDragIconExpose(GtkWidget* sender, |
| 123 | GdkEventExpose* event, |
| 124 | DragRepresentationData* data) { |
| 125 | // Clear the background. |
| 126 | cairo_t* cr = gdk_cairo_create(event->window); |
| 127 | gdk_cairo_rectangle(cr, &event->area); |
| 128 | cairo_clip(cr); |
| 129 | cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR); |
| 130 | cairo_paint(cr); |
| 131 | |
| 132 | cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); |
| 133 | gdk_cairo_set_source_pixbuf(cr, data->favicon, 0, 0); |
| 134 | cairo_paint(cr); |
| 135 | cairo_destroy(cr); |
| 136 | |
| 137 | // Paint the title text. |
[email protected] | 302433879 | 2010-06-23 23:04:23 | [diff] [blame] | 138 | gfx::CanvasSkiaPaint canvas(event, false); |
[email protected] | 36622b1 | 2010-04-30 23:35:44 | [diff] [blame] | 139 | int text_x = gdk_pixbuf_get_width(data->favicon) + kBarButtonPadding; |
| 140 | int text_width = sender->allocation.width - text_x; |
| 141 | ResourceBundle& rb = ResourceBundle::GetSharedInstance(); |
| 142 | const gfx::Font& base_font = rb.GetFont(ResourceBundle::BaseFont); |
| 143 | canvas.DrawStringInt(data->text, |
| 144 | base_font, data->text_color, |
| 145 | text_x, 0, text_width, sender->allocation.height); |
| 146 | |
| 147 | return TRUE; |
| 148 | } |
| 149 | |
| 150 | void OnDragIconDestroy(GtkWidget* drag_icon, |
| 151 | DragRepresentationData* data) { |
| 152 | g_object_unref(drag_icon); |
| 153 | delete data; |
| 154 | } |
| 155 | |
[email protected] | aa7dc4f | 2009-06-29 18:21:33 | [diff] [blame] | 156 | } // namespace |
| 157 | |
[email protected] | e5f72c7 | 2009-06-05 19:15:33 | [diff] [blame] | 158 | namespace bookmark_utils { |
| 159 | |
[email protected] | aa7dc4f | 2009-06-29 18:21:33 | [diff] [blame] | 160 | const char kBookmarkNode[] = "bookmark-node"; |
| 161 | |
[email protected] | 94d88ad3 | 2009-08-08 02:18:31 | [diff] [blame] | 162 | GdkPixbuf* GetPixbufForNode(const BookmarkNode* node, BookmarkModel* model, |
| 163 | bool native) { |
[email protected] | e5f72c7 | 2009-06-05 19:15:33 | [diff] [blame] | 164 | GdkPixbuf* pixbuf; |
| 165 | |
| 166 | if (node->is_url()) { |
| 167 | if (model->GetFavIcon(node).width() != 0) { |
| 168 | pixbuf = gfx::GdkPixbufFromSkBitmap(&model->GetFavIcon(node)); |
| 169 | } else { |
[email protected] | 54a1029 | 2009-09-11 01:15:04 | [diff] [blame] | 170 | pixbuf = GtkThemeProvider::GetDefaultFavicon(native); |
[email protected] | e5f72c7 | 2009-06-05 19:15:33 | [diff] [blame] | 171 | g_object_ref(pixbuf); |
| 172 | } |
| 173 | } else { |
[email protected] | 54a1029 | 2009-09-11 01:15:04 | [diff] [blame] | 174 | pixbuf = GtkThemeProvider::GetFolderIcon(native); |
[email protected] | e5f72c7 | 2009-06-05 19:15:33 | [diff] [blame] | 175 | g_object_ref(pixbuf); |
| 176 | } |
| 177 | |
| 178 | return pixbuf; |
| 179 | } |
| 180 | |
[email protected] | 36622b1 | 2010-04-30 23:35:44 | [diff] [blame] | 181 | GtkWidget* GetDragRepresentation(GdkPixbuf* pixbuf, |
| 182 | const std::wstring& title, |
[email protected] | 5fdafb2 | 2009-07-13 23:23:08 | [diff] [blame] | 183 | GtkThemeProvider* provider) { |
[email protected] | aa7dc4f | 2009-06-29 18:21:33 | [diff] [blame] | 184 | GtkWidget* window = gtk_window_new(GTK_WINDOW_POPUP); |
[email protected] | 36622b1 | 2010-04-30 23:35:44 | [diff] [blame] | 185 | |
| 186 | if (gtk_util::IsScreenComposited() && |
| 187 | gtk_util::AddWindowAlphaChannel(window)) { |
| 188 | DragRepresentationData* data = new DragRepresentationData( |
| 189 | pixbuf, title, |
| 190 | provider->GetColor(BrowserThemeProvider::COLOR_BOOKMARK_TEXT)); |
| 191 | g_signal_connect(window, "expose-event", G_CALLBACK(OnDragIconExpose), |
| 192 | data); |
| 193 | g_object_ref(window); |
| 194 | g_signal_connect(window, "destroy", G_CALLBACK(OnDragIconDestroy), data); |
| 195 | |
| 196 | ResourceBundle& rb = ResourceBundle::GetSharedInstance(); |
| 197 | const gfx::Font& base_font = rb.GetFont(ResourceBundle::BaseFont); |
| 198 | gtk_widget_set_size_request(window, kDragRepresentationWidth, |
| 199 | base_font.height()); |
| 200 | } else { |
| 201 | if (!provider->UseGtkTheme()) { |
| 202 | // TODO(erg): Theme wise, which color should I be picking here? |
| 203 | // COLOR_BUTTON_BACKGROUND doesn't match the default theme! |
| 204 | gtk_widget_modify_bg(window, GTK_STATE_NORMAL, &kBackgroundColor); |
| 205 | } |
| 206 | gtk_widget_realize(window); |
| 207 | |
| 208 | GtkWidget* frame = gtk_frame_new(NULL); |
| 209 | gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_OUT); |
| 210 | gtk_container_add(GTK_CONTAINER(window), frame); |
| 211 | |
| 212 | GtkWidget* floating_button = provider->BuildChromeButton(); |
| 213 | PackButton(pixbuf, title, true, provider, floating_button); |
| 214 | gtk_container_add(GTK_CONTAINER(frame), floating_button); |
| 215 | gtk_widget_show_all(frame); |
[email protected] | 3c78ae92 | 2009-07-07 00:37:08 | [diff] [blame] | 216 | } |
[email protected] | aa7dc4f | 2009-06-29 18:21:33 | [diff] [blame] | 217 | |
| 218 | return window; |
| 219 | } |
| 220 | |
[email protected] | 36622b1 | 2010-04-30 23:35:44 | [diff] [blame] | 221 | GtkWidget* GetDragRepresentationForNode(const BookmarkNode* node, |
| 222 | BookmarkModel* model, |
| 223 | GtkThemeProvider* provider) { |
| 224 | GdkPixbuf* pixbuf = GetPixbufForNode(node, model, provider->UseGtkTheme()); |
| 225 | GtkWidget* widget = GetDragRepresentation(pixbuf, node->GetTitle(), provider); |
| 226 | g_object_unref(pixbuf); |
| 227 | return widget; |
| 228 | } |
| 229 | |
[email protected] | aa7dc4f | 2009-06-29 18:21:33 | [diff] [blame] | 230 | void ConfigureButtonForNode(const BookmarkNode* node, BookmarkModel* model, |
[email protected] | 5fdafb2 | 2009-07-13 23:23:08 | [diff] [blame] | 231 | GtkWidget* button, GtkThemeProvider* provider) { |
[email protected] | 36622b1 | 2010-04-30 23:35:44 | [diff] [blame] | 232 | GdkPixbuf* pixbuf = bookmark_utils::GetPixbufForNode(node, model, |
| 233 | provider->UseGtkTheme()); |
| 234 | PackButton(pixbuf, node->GetTitle(), node != model->other_node(), |
| 235 | provider, button); |
| 236 | g_object_unref(pixbuf); |
[email protected] | 2fc9093 | 2009-07-02 20:33:40 | [diff] [blame] | 237 | |
[email protected] | aa7dc4f | 2009-06-29 18:21:33 | [diff] [blame] | 238 | std::string tooltip = BuildTooltipFor(node); |
| 239 | if (!tooltip.empty()) |
[email protected] | 8098d2d7 | 2009-08-27 22:56:36 | [diff] [blame] | 240 | gtk_widget_set_tooltip_markup(button, tooltip.c_str()); |
[email protected] | aa7dc4f | 2009-06-29 18:21:33 | [diff] [blame] | 241 | |
[email protected] | aa7dc4f | 2009-06-29 18:21:33 | [diff] [blame] | 242 | g_object_set_data(G_OBJECT(button), bookmark_utils::kBookmarkNode, |
| 243 | AsVoid(node)); |
| 244 | } |
| 245 | |
| 246 | std::string BuildTooltipFor(const BookmarkNode* node) { |
[email protected] | 8098d2d7 | 2009-08-27 22:56:36 | [diff] [blame] | 247 | const std::string& url = node->GetURL().possibly_invalid_spec(); |
| 248 | const std::string& title = WideToUTF8(node->GetTitle()); |
| 249 | |
| 250 | std::string truncated_url = WideToUTF8(l10n_util::TruncateString( |
| 251 | UTF8ToWide(url), kMaxTooltipURLLength)); |
| 252 | gchar* escaped_url_cstr = g_markup_escape_text(truncated_url.c_str(), |
| 253 | truncated_url.size()); |
| 254 | std::string escaped_url(escaped_url_cstr); |
| 255 | g_free(escaped_url_cstr); |
| 256 | |
| 257 | std::string tooltip; |
[email protected] | 2edf323 | 2009-09-16 23:33:34 | [diff] [blame] | 258 | if (url == title || title.empty()) { |
[email protected] | 8098d2d7 | 2009-08-27 22:56:36 | [diff] [blame] | 259 | return escaped_url; |
| 260 | } else { |
| 261 | std::string truncated_title = WideToUTF8(l10n_util::TruncateString( |
| 262 | node->GetTitle(), kMaxTooltipTitleLength)); |
| 263 | gchar* escaped_title_cstr = g_markup_escape_text(truncated_title.c_str(), |
| 264 | truncated_title.size()); |
| 265 | std::string escaped_title(escaped_title_cstr); |
| 266 | g_free(escaped_title_cstr); |
| 267 | |
[email protected] | a24004b | 2009-09-03 17:24:54 | [diff] [blame] | 268 | if (!escaped_url.empty()) |
| 269 | return std::string("<b>") + escaped_title + "</b>\n" + escaped_url; |
| 270 | else |
| 271 | return std::string("<b>") + escaped_title + "</b>"; |
[email protected] | 8098d2d7 | 2009-08-27 22:56:36 | [diff] [blame] | 272 | } |
[email protected] | aa7dc4f | 2009-06-29 18:21:33 | [diff] [blame] | 273 | } |
| 274 | |
| 275 | const BookmarkNode* BookmarkNodeForWidget(GtkWidget* widget) { |
| 276 | return reinterpret_cast<const BookmarkNode*>( |
| 277 | g_object_get_data(G_OBJECT(widget), bookmark_utils::kBookmarkNode)); |
| 278 | } |
| 279 | |
[email protected] | 5fdafb2 | 2009-07-13 23:23:08 | [diff] [blame] | 280 | void SetButtonTextColors(GtkWidget* label, GtkThemeProvider* provider) { |
| 281 | if (provider->UseGtkTheme()) { |
[email protected] | c7e082e | 2009-08-03 18:43:28 | [diff] [blame] | 282 | gtk_util::SetLabelColor(label, NULL); |
[email protected] | 3c78ae92 | 2009-07-07 00:37:08 | [diff] [blame] | 283 | } else { |
[email protected] | 5fdafb2 | 2009-07-13 23:23:08 | [diff] [blame] | 284 | GdkColor color = provider->GetGdkColor( |
[email protected] | 3c78ae92 | 2009-07-07 00:37:08 | [diff] [blame] | 285 | BrowserThemeProvider::COLOR_BOOKMARK_TEXT); |
[email protected] | c7e082e | 2009-08-03 18:43:28 | [diff] [blame] | 286 | gtk_util::SetLabelColor(label, &color); |
[email protected] | 3c78ae92 | 2009-07-07 00:37:08 | [diff] [blame] | 287 | } |
[email protected] | aa7dc4f | 2009-06-29 18:21:33 | [diff] [blame] | 288 | } |
| 289 | |
[email protected] | e5f72c7 | 2009-06-05 19:15:33 | [diff] [blame] | 290 | // DnD-related ----------------------------------------------------------------- |
| 291 | |
[email protected] | 2ca8a06 | 2010-03-18 17:10:18 | [diff] [blame] | 292 | int GetCodeMask(bool folder) { |
| 293 | int rv = gtk_dnd_util::CHROME_BOOKMARK_ITEM; |
| 294 | if (!folder) { |
| 295 | rv |= gtk_dnd_util::TEXT_URI_LIST | |
| 296 | gtk_dnd_util::TEXT_PLAIN | |
| 297 | gtk_dnd_util::NETSCAPE_URL; |
| 298 | } |
| 299 | return rv; |
| 300 | } |
| 301 | |
[email protected] | b3c33d46 | 2009-06-26 22:29:20 | [diff] [blame] | 302 | void WriteBookmarkToSelection(const BookmarkNode* node, |
[email protected] | e5f72c7 | 2009-06-05 19:15:33 | [diff] [blame] | 303 | GtkSelectionData* selection_data, |
| 304 | guint target_type, |
| 305 | Profile* profile) { |
| 306 | DCHECK(node); |
[email protected] | b3c33d46 | 2009-06-26 22:29:20 | [diff] [blame] | 307 | std::vector<const BookmarkNode*> nodes; |
[email protected] | d99bf74 | 2009-06-25 00:17:01 | [diff] [blame] | 308 | nodes.push_back(node); |
| 309 | WriteBookmarksToSelection(nodes, selection_data, target_type, profile); |
| 310 | } |
| 311 | |
[email protected] | b3c33d46 | 2009-06-26 22:29:20 | [diff] [blame] | 312 | void WriteBookmarksToSelection(const std::vector<const BookmarkNode*>& nodes, |
[email protected] | d99bf74 | 2009-06-25 00:17:01 | [diff] [blame] | 313 | GtkSelectionData* selection_data, |
| 314 | guint target_type, |
| 315 | Profile* profile) { |
[email protected] | e5f72c7 | 2009-06-05 19:15:33 | [diff] [blame] | 316 | switch (target_type) { |
[email protected] | 6e64343 | 2010-03-10 18:32:14 | [diff] [blame] | 317 | case gtk_dnd_util::CHROME_BOOKMARK_ITEM: { |
[email protected] | d99bf74 | 2009-06-25 00:17:01 | [diff] [blame] | 318 | BookmarkDragData data(nodes); |
[email protected] | e5f72c7 | 2009-06-05 19:15:33 | [diff] [blame] | 319 | Pickle pickle; |
| 320 | data.WriteToPickle(profile, &pickle); |
| 321 | |
| 322 | gtk_selection_data_set(selection_data, selection_data->target, |
| 323 | kBitsInAByte, |
| 324 | static_cast<const guchar*>(pickle.data()), |
| 325 | pickle.size()); |
| 326 | break; |
| 327 | } |
[email protected] | 6e64343 | 2010-03-10 18:32:14 | [diff] [blame] | 328 | case gtk_dnd_util::NETSCAPE_URL: { |
[email protected] | 1a4a5cc | 2010-01-20 00:27:42 | [diff] [blame] | 329 | // _NETSCAPE_URL format is URL + \n + title. |
| 330 | std::string utf8_text = nodes[0]->GetURL().spec() + "\n" + UTF16ToUTF8( |
| 331 | nodes[0]->GetTitleAsString16()); |
| 332 | gtk_selection_data_set(selection_data, |
| 333 | selection_data->target, |
| 334 | kBitsInAByte, |
| 335 | reinterpret_cast<const guchar*>(utf8_text.c_str()), |
| 336 | utf8_text.length()); |
| 337 | break; |
| 338 | } |
[email protected] | 6e64343 | 2010-03-10 18:32:14 | [diff] [blame] | 339 | case gtk_dnd_util::TEXT_URI_LIST: { |
[email protected] | 3f873e1c | 2009-07-08 01:01:53 | [diff] [blame] | 340 | gchar** uris = reinterpret_cast<gchar**>(malloc(sizeof(gchar*) * |
| 341 | (nodes.size() + 1))); |
| 342 | for (size_t i = 0; i < nodes.size(); ++i) { |
| 343 | // If the node is a folder, this will be empty. TODO(estade): figure out |
| 344 | // if there are any ramifications to passing an empty URI. After a |
[email protected] | 903e7a8 | 2009-07-28 00:45:35 | [diff] [blame] | 345 | // little testing, it seems fine. |
[email protected] | 3f873e1c | 2009-07-08 01:01:53 | [diff] [blame] | 346 | const GURL& url = nodes[i]->GetURL(); |
| 347 | // This const cast should be safe as gtk_selection_data_set_uris() |
| 348 | // makes copies. |
| 349 | uris[i] = const_cast<gchar*>(url.spec().c_str()); |
| 350 | } |
| 351 | uris[nodes.size()] = NULL; |
| 352 | |
| 353 | gtk_selection_data_set_uris(selection_data, uris); |
| 354 | free(uris); |
| 355 | break; |
| 356 | } |
[email protected] | 6e64343 | 2010-03-10 18:32:14 | [diff] [blame] | 357 | case gtk_dnd_util::TEXT_PLAIN: { |
[email protected] | 3462f90 | 2009-12-02 00:40:29 | [diff] [blame] | 358 | gtk_selection_data_set_text(selection_data, |
| 359 | nodes[0]->GetURL().spec().c_str(), -1); |
| 360 | break; |
[email protected] | 3462f90 | 2009-12-02 00:40:29 | [diff] [blame] | 361 | } |
[email protected] | e5f72c7 | 2009-06-05 19:15:33 | [diff] [blame] | 362 | default: { |
| 363 | DLOG(ERROR) << "Unsupported drag get type!"; |
| 364 | } |
| 365 | } |
| 366 | } |
| 367 | |
[email protected] | b3c33d46 | 2009-06-26 22:29:20 | [diff] [blame] | 368 | std::vector<const BookmarkNode*> GetNodesFromSelection( |
[email protected] | e5f72c7 | 2009-06-05 19:15:33 | [diff] [blame] | 369 | GdkDragContext* context, |
| 370 | GtkSelectionData* selection_data, |
| 371 | guint target_type, |
| 372 | Profile* profile, |
| 373 | gboolean* delete_selection_data, |
| 374 | gboolean* dnd_success) { |
[email protected] | 2ca8a06 | 2010-03-18 17:10:18 | [diff] [blame] | 375 | if (delete_selection_data) |
| 376 | *delete_selection_data = FALSE; |
| 377 | if (dnd_success) |
| 378 | *dnd_success = FALSE; |
[email protected] | e5f72c7 | 2009-06-05 19:15:33 | [diff] [blame] | 379 | |
[email protected] | 5c31135 | 2010-05-07 19:36:15 | [diff] [blame] | 380 | if (selection_data && selection_data->length > 0) { |
[email protected] | 2ca8a06 | 2010-03-18 17:10:18 | [diff] [blame] | 381 | if (context && delete_selection_data && context->action == GDK_ACTION_MOVE) |
[email protected] | e5f72c7 | 2009-06-05 19:15:33 | [diff] [blame] | 382 | *delete_selection_data = TRUE; |
[email protected] | e5f72c7 | 2009-06-05 19:15:33 | [diff] [blame] | 383 | |
| 384 | switch (target_type) { |
[email protected] | 6e64343 | 2010-03-10 18:32:14 | [diff] [blame] | 385 | case gtk_dnd_util::CHROME_BOOKMARK_ITEM: { |
[email protected] | 2ca8a06 | 2010-03-18 17:10:18 | [diff] [blame] | 386 | if (dnd_success) |
| 387 | *dnd_success = TRUE; |
[email protected] | e5f72c7 | 2009-06-05 19:15:33 | [diff] [blame] | 388 | Pickle pickle(reinterpret_cast<char*>(selection_data->data), |
| 389 | selection_data->length); |
| 390 | BookmarkDragData drag_data; |
| 391 | drag_data.ReadFromPickle(&pickle); |
| 392 | return drag_data.GetNodes(profile); |
| 393 | } |
| 394 | default: { |
| 395 | DLOG(ERROR) << "Unsupported drag received type: " << target_type; |
| 396 | } |
| 397 | } |
| 398 | } |
| 399 | |
[email protected] | b3c33d46 | 2009-06-26 22:29:20 | [diff] [blame] | 400 | return std::vector<const BookmarkNode*>(); |
[email protected] | e5f72c7 | 2009-06-05 19:15:33 | [diff] [blame] | 401 | } |
| 402 | |
[email protected] | cd6966178 | 2009-07-17 00:17:56 | [diff] [blame] | 403 | bool CreateNewBookmarkFromNamedUrl(GtkSelectionData* selection_data, |
| 404 | BookmarkModel* model, const BookmarkNode* parent, int idx) { |
[email protected] | 00d8380 | 2009-08-11 21:32:30 | [diff] [blame] | 405 | GURL url; |
| 406 | string16 title; |
[email protected] | 6e64343 | 2010-03-10 18:32:14 | [diff] [blame] | 407 | if (!gtk_dnd_util::ExtractNamedURL(selection_data, &url, &title)) |
[email protected] | 00d8380 | 2009-08-11 21:32:30 | [diff] [blame] | 408 | return false; |
| 409 | |
| 410 | model->AddURL(parent, idx, UTF16ToWideHack(title), url); |
| 411 | return true; |
[email protected] | cd6966178 | 2009-07-17 00:17:56 | [diff] [blame] | 412 | } |
| 413 | |
[email protected] | 903e7a8 | 2009-07-28 00:45:35 | [diff] [blame] | 414 | bool CreateNewBookmarksFromURIList(GtkSelectionData* selection_data, |
| 415 | BookmarkModel* model, const BookmarkNode* parent, int idx) { |
[email protected] | 00d8380 | 2009-08-11 21:32:30 | [diff] [blame] | 416 | std::vector<GURL> urls; |
[email protected] | 6e64343 | 2010-03-10 18:32:14 | [diff] [blame] | 417 | gtk_dnd_util::ExtractURIList(selection_data, &urls); |
[email protected] | 00d8380 | 2009-08-11 21:32:30 | [diff] [blame] | 418 | for (size_t i = 0; i < urls.size(); ++i) { |
| 419 | std::string title = GetNameForURL(urls[i]); |
| 420 | model->AddURL(parent, idx++, UTF8ToWide(title), urls[i]); |
[email protected] | 903e7a8 | 2009-07-28 00:45:35 | [diff] [blame] | 421 | } |
[email protected] | 903e7a8 | 2009-07-28 00:45:35 | [diff] [blame] | 422 | return true; |
| 423 | } |
| 424 | |
[email protected] | e5f72c7 | 2009-06-05 19:15:33 | [diff] [blame] | 425 | } // namespace bookmark_utils |