Index: chrome/browser/gtk/bookmark_utils_gtk.cc |
=================================================================== |
--- chrome/browser/gtk/bookmark_utils_gtk.cc (revision 71352) |
+++ chrome/browser/gtk/bookmark_utils_gtk.cc (working copy) |
@@ -1,440 +0,0 @@ |
-// Copyright (c) 2010 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#include "chrome/browser/gtk/bookmark_utils_gtk.h" |
- |
-#include "app/gtk_dnd_util.h" |
-#include "app/l10n_util.h" |
-#include "app/resource_bundle.h" |
-#include "base/pickle.h" |
-#include "base/string16.h" |
-#include "base/string_util.h" |
-#include "base/utf_string_conversions.h" |
-#include "chrome/browser/bookmarks/bookmark_node_data.h" |
-#include "chrome/browser/bookmarks/bookmark_model.h" |
-#include "chrome/browser/bookmarks/bookmark_utils.h" |
-#include "chrome/browser/gtk/gtk_chrome_button.h" |
-#include "chrome/browser/gtk/gtk_theme_provider.h" |
-#include "chrome/browser/gtk/gtk_util.h" |
-#include "chrome/browser/profiles/profile.h" |
-#include "gfx/canvas_skia_paint.h" |
-#include "gfx/font.h" |
-#include "gfx/gtk_util.h" |
- |
-namespace { |
- |
-// Spacing between the favicon and the text. |
-const int kBarButtonPadding = 4; |
- |
-// Used in gtk_selection_data_set(). (I assume from this parameter that gtk has |
-// to some really exotic hardware...) |
-const int kBitsInAByte = 8; |
- |
-// Maximum number of characters on a bookmark button. |
-const size_t kMaxCharsOnAButton = 15; |
- |
-// Max size of each component of the button tooltips. |
-const size_t kMaxTooltipTitleLength = 100; |
-const size_t kMaxTooltipURLLength = 400; |
- |
-// Padding between the chrome button highlight border and the contents (favicon, |
-// text). |
-const int kButtonPaddingTop = 0; |
-const int kButtonPaddingBottom = 0; |
-const int kButtonPaddingLeft = 5; |
-const int kButtonPaddingRight = 0; |
- |
-void* AsVoid(const BookmarkNode* node) { |
- return const_cast<BookmarkNode*>(node); |
-} |
- |
-// Creates the widget hierarchy for a bookmark button. |
-void PackButton(GdkPixbuf* pixbuf, const string16& title, bool ellipsize, |
- GtkThemeProvider* provider, GtkWidget* button) { |
- GtkWidget* former_child = gtk_bin_get_child(GTK_BIN(button)); |
- if (former_child) |
- gtk_container_remove(GTK_CONTAINER(button), former_child); |
- |
- // We pack the button manually (rather than using gtk_button_set_*) so that |
- // we can have finer control over its label. |
- GtkWidget* image = gtk_image_new_from_pixbuf(pixbuf); |
- |
- GtkWidget* box = gtk_hbox_new(FALSE, kBarButtonPadding); |
- gtk_box_pack_start(GTK_BOX(box), image, FALSE, FALSE, 0); |
- |
- std::string label_string = UTF16ToUTF8(title); |
- if (!label_string.empty()) { |
- GtkWidget* label = gtk_label_new(label_string.c_str()); |
- // Until we switch to vector graphics, force the font size. |
- gtk_util::ForceFontSizePixels(label, 13.4); // 13.4px == 10pt @ 96dpi |
- |
- // Ellipsize long bookmark names. |
- if (ellipsize) { |
- gtk_label_set_max_width_chars(GTK_LABEL(label), kMaxCharsOnAButton); |
- gtk_label_set_ellipsize(GTK_LABEL(label), PANGO_ELLIPSIZE_END); |
- } |
- |
- gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0); |
- bookmark_utils::SetButtonTextColors(label, provider); |
- } |
- |
- GtkWidget* alignment = gtk_alignment_new(0.0, 0.0, 1.0, 1.0); |
- // If we are not showing the label, don't set any padding, so that the icon |
- // will just be centered. |
- if (label_string.c_str()) { |
- gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), |
- kButtonPaddingTop, kButtonPaddingBottom, |
- kButtonPaddingLeft, kButtonPaddingRight); |
- } |
- gtk_container_add(GTK_CONTAINER(alignment), box); |
- gtk_container_add(GTK_CONTAINER(button), alignment); |
- |
- gtk_widget_show_all(alignment); |
-} |
- |
-const int kDragRepresentationWidth = 140; |
- |
-struct DragRepresentationData { |
- public: |
- GdkPixbuf* favicon; |
- string16 text; |
- SkColor text_color; |
- |
- DragRepresentationData(GdkPixbuf* favicon, |
- const string16& text, |
- SkColor text_color) |
- : favicon(favicon), |
- text(text), |
- text_color(text_color) { |
- g_object_ref(favicon); |
- } |
- |
- ~DragRepresentationData() { |
- g_object_unref(favicon); |
- } |
- |
- private: |
- DISALLOW_COPY_AND_ASSIGN(DragRepresentationData); |
-}; |
- |
-gboolean OnDragIconExpose(GtkWidget* sender, |
- GdkEventExpose* event, |
- DragRepresentationData* data) { |
- // Clear the background. |
- cairo_t* cr = gdk_cairo_create(event->window); |
- gdk_cairo_rectangle(cr, &event->area); |
- cairo_clip(cr); |
- cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR); |
- cairo_paint(cr); |
- |
- cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); |
- gdk_cairo_set_source_pixbuf(cr, data->favicon, 0, 0); |
- cairo_paint(cr); |
- cairo_destroy(cr); |
- |
- // Paint the title text. |
- gfx::CanvasSkiaPaint canvas(event, false); |
- int text_x = gdk_pixbuf_get_width(data->favicon) + kBarButtonPadding; |
- int text_width = sender->allocation.width - text_x; |
- ResourceBundle& rb = ResourceBundle::GetSharedInstance(); |
- const gfx::Font& base_font = rb.GetFont(ResourceBundle::BaseFont); |
- canvas.DrawStringInt(data->text, base_font, data->text_color, |
- text_x, 0, text_width, sender->allocation.height); |
- |
- return TRUE; |
-} |
- |
-void OnDragIconDestroy(GtkWidget* drag_icon, |
- DragRepresentationData* data) { |
- g_object_unref(drag_icon); |
- delete data; |
-} |
- |
-} // namespace |
- |
-namespace bookmark_utils { |
- |
-const char kBookmarkNode[] = "bookmark-node"; |
- |
-GdkPixbuf* GetPixbufForNode(const BookmarkNode* node, BookmarkModel* model, |
- bool native) { |
- GdkPixbuf* pixbuf; |
- |
- if (node->is_url()) { |
- if (model->GetFavIcon(node).width() != 0) { |
- pixbuf = gfx::GdkPixbufFromSkBitmap(&model->GetFavIcon(node)); |
- } else { |
- pixbuf = GtkThemeProvider::GetDefaultFavicon(native); |
- g_object_ref(pixbuf); |
- } |
- } else { |
- pixbuf = GtkThemeProvider::GetFolderIcon(native); |
- g_object_ref(pixbuf); |
- } |
- |
- return pixbuf; |
-} |
- |
-GtkWidget* GetDragRepresentation(GdkPixbuf* pixbuf, |
- const string16& title, |
- GtkThemeProvider* provider) { |
- GtkWidget* window = gtk_window_new(GTK_WINDOW_POPUP); |
- |
- if (gtk_util::IsScreenComposited() && |
- gtk_util::AddWindowAlphaChannel(window)) { |
- DragRepresentationData* data = new DragRepresentationData( |
- pixbuf, title, |
- provider->GetColor(BrowserThemeProvider::COLOR_BOOKMARK_TEXT)); |
- g_signal_connect(window, "expose-event", G_CALLBACK(OnDragIconExpose), |
- data); |
- g_object_ref(window); |
- g_signal_connect(window, "destroy", G_CALLBACK(OnDragIconDestroy), data); |
- |
- ResourceBundle& rb = ResourceBundle::GetSharedInstance(); |
- const gfx::Font& base_font = rb.GetFont(ResourceBundle::BaseFont); |
- gtk_widget_set_size_request(window, kDragRepresentationWidth, |
- base_font.GetHeight()); |
- } else { |
- if (!provider->UseGtkTheme()) { |
- GdkColor color = provider->GetGdkColor( |
- BrowserThemeProvider::COLOR_TOOLBAR); |
- gtk_widget_modify_bg(window, GTK_STATE_NORMAL, &color); |
- } |
- gtk_widget_realize(window); |
- |
- GtkWidget* frame = gtk_frame_new(NULL); |
- gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_OUT); |
- gtk_container_add(GTK_CONTAINER(window), frame); |
- |
- GtkWidget* floating_button = provider->BuildChromeButton(); |
- PackButton(pixbuf, title, true, provider, floating_button); |
- gtk_container_add(GTK_CONTAINER(frame), floating_button); |
- gtk_widget_show_all(frame); |
- } |
- |
- return window; |
-} |
- |
-GtkWidget* GetDragRepresentationForNode(const BookmarkNode* node, |
- BookmarkModel* model, |
- GtkThemeProvider* provider) { |
- GdkPixbuf* pixbuf = GetPixbufForNode(node, model, provider->UseGtkTheme()); |
- GtkWidget* widget = GetDragRepresentation(pixbuf, node->GetTitle(), provider); |
- g_object_unref(pixbuf); |
- return widget; |
-} |
- |
-void ConfigureButtonForNode(const BookmarkNode* node, BookmarkModel* model, |
- GtkWidget* button, GtkThemeProvider* provider) { |
- GdkPixbuf* pixbuf = bookmark_utils::GetPixbufForNode(node, model, |
- provider->UseGtkTheme()); |
- PackButton(pixbuf, node->GetTitle(), node != model->other_node(), provider, |
- button); |
- g_object_unref(pixbuf); |
- |
- std::string tooltip = BuildTooltipFor(node); |
- if (!tooltip.empty()) |
- gtk_widget_set_tooltip_markup(button, tooltip.c_str()); |
- |
- g_object_set_data(G_OBJECT(button), bookmark_utils::kBookmarkNode, |
- AsVoid(node)); |
-} |
- |
-std::string BuildTooltipFor(const BookmarkNode* node) { |
- const std::string& url = node->GetURL().possibly_invalid_spec(); |
- const std::string& title = UTF16ToUTF8(node->GetTitle()); |
- |
- std::string truncated_url = UTF16ToUTF8(l10n_util::TruncateString( |
- UTF8ToUTF16(url), kMaxTooltipURLLength)); |
- gchar* escaped_url_cstr = g_markup_escape_text(truncated_url.c_str(), |
- truncated_url.size()); |
- std::string escaped_url(escaped_url_cstr); |
- g_free(escaped_url_cstr); |
- |
- std::string tooltip; |
- if (url == title || title.empty()) { |
- return escaped_url; |
- } else { |
- std::string truncated_title = UTF16ToUTF8(l10n_util::TruncateString( |
- node->GetTitle(), kMaxTooltipTitleLength)); |
- gchar* escaped_title_cstr = g_markup_escape_text(truncated_title.c_str(), |
- truncated_title.size()); |
- std::string escaped_title(escaped_title_cstr); |
- g_free(escaped_title_cstr); |
- |
- if (!escaped_url.empty()) |
- return std::string("<b>") + escaped_title + "</b>\n" + escaped_url; |
- else |
- return std::string("<b>") + escaped_title + "</b>"; |
- } |
-} |
- |
-const BookmarkNode* BookmarkNodeForWidget(GtkWidget* widget) { |
- return reinterpret_cast<const BookmarkNode*>( |
- g_object_get_data(G_OBJECT(widget), bookmark_utils::kBookmarkNode)); |
-} |
- |
-void SetButtonTextColors(GtkWidget* label, GtkThemeProvider* provider) { |
- if (provider->UseGtkTheme()) { |
- gtk_util::SetLabelColor(label, NULL); |
- } else { |
- GdkColor color = provider->GetGdkColor( |
- BrowserThemeProvider::COLOR_BOOKMARK_TEXT); |
- gtk_widget_modify_fg(label, GTK_STATE_NORMAL, &color); |
- gtk_widget_modify_fg(label, GTK_STATE_INSENSITIVE, &color); |
- |
- // Because the prelight state is a white image that doesn't change by the |
- // theme, force the text color to black when it would be used. |
- gtk_widget_modify_fg(label, GTK_STATE_ACTIVE, >k_util::kGdkBlack); |
- gtk_widget_modify_fg(label, GTK_STATE_PRELIGHT, >k_util::kGdkBlack); |
- } |
-} |
- |
-// DnD-related ----------------------------------------------------------------- |
- |
-int GetCodeMask(bool folder) { |
- int rv = gtk_dnd_util::CHROME_BOOKMARK_ITEM; |
- if (!folder) { |
- rv |= gtk_dnd_util::TEXT_URI_LIST | |
- gtk_dnd_util::TEXT_PLAIN | |
- gtk_dnd_util::NETSCAPE_URL; |
- } |
- return rv; |
-} |
- |
-void WriteBookmarkToSelection(const BookmarkNode* node, |
- GtkSelectionData* selection_data, |
- guint target_type, |
- Profile* profile) { |
- DCHECK(node); |
- std::vector<const BookmarkNode*> nodes; |
- nodes.push_back(node); |
- WriteBookmarksToSelection(nodes, selection_data, target_type, profile); |
-} |
- |
-void WriteBookmarksToSelection(const std::vector<const BookmarkNode*>& nodes, |
- GtkSelectionData* selection_data, |
- guint target_type, |
- Profile* profile) { |
- switch (target_type) { |
- case gtk_dnd_util::CHROME_BOOKMARK_ITEM: { |
- BookmarkNodeData data(nodes); |
- Pickle pickle; |
- data.WriteToPickle(profile, &pickle); |
- |
- gtk_selection_data_set(selection_data, selection_data->target, |
- kBitsInAByte, |
- static_cast<const guchar*>(pickle.data()), |
- pickle.size()); |
- break; |
- } |
- case gtk_dnd_util::NETSCAPE_URL: { |
- // _NETSCAPE_URL format is URL + \n + title. |
- std::string utf8_text = nodes[0]->GetURL().spec() + "\n" + |
- UTF16ToUTF8(nodes[0]->GetTitle()); |
- gtk_selection_data_set(selection_data, |
- selection_data->target, |
- kBitsInAByte, |
- reinterpret_cast<const guchar*>(utf8_text.c_str()), |
- utf8_text.length()); |
- break; |
- } |
- case gtk_dnd_util::TEXT_URI_LIST: { |
- gchar** uris = reinterpret_cast<gchar**>(malloc(sizeof(gchar*) * |
- (nodes.size() + 1))); |
- for (size_t i = 0; i < nodes.size(); ++i) { |
- // If the node is a folder, this will be empty. TODO(estade): figure out |
- // if there are any ramifications to passing an empty URI. After a |
- // little testing, it seems fine. |
- const GURL& url = nodes[i]->GetURL(); |
- // This const cast should be safe as gtk_selection_data_set_uris() |
- // makes copies. |
- uris[i] = const_cast<gchar*>(url.spec().c_str()); |
- } |
- uris[nodes.size()] = NULL; |
- |
- gtk_selection_data_set_uris(selection_data, uris); |
- free(uris); |
- break; |
- } |
- case gtk_dnd_util::TEXT_PLAIN: { |
- gtk_selection_data_set_text(selection_data, |
- nodes[0]->GetURL().spec().c_str(), -1); |
- break; |
- } |
- default: { |
- DLOG(ERROR) << "Unsupported drag get type!"; |
- } |
- } |
-} |
- |
-std::vector<const BookmarkNode*> GetNodesFromSelection( |
- GdkDragContext* context, |
- GtkSelectionData* selection_data, |
- guint target_type, |
- Profile* profile, |
- gboolean* delete_selection_data, |
- gboolean* dnd_success) { |
- if (delete_selection_data) |
- *delete_selection_data = FALSE; |
- if (dnd_success) |
- *dnd_success = FALSE; |
- |
- if (selection_data && selection_data->length > 0) { |
- if (context && delete_selection_data && context->action == GDK_ACTION_MOVE) |
- *delete_selection_data = TRUE; |
- |
- switch (target_type) { |
- case gtk_dnd_util::CHROME_BOOKMARK_ITEM: { |
- if (dnd_success) |
- *dnd_success = TRUE; |
- Pickle pickle(reinterpret_cast<char*>(selection_data->data), |
- selection_data->length); |
- BookmarkNodeData drag_data; |
- drag_data.ReadFromPickle(&pickle); |
- return drag_data.GetNodes(profile); |
- } |
- default: { |
- DLOG(ERROR) << "Unsupported drag received type: " << target_type; |
- } |
- } |
- } |
- |
- return std::vector<const BookmarkNode*>(); |
-} |
- |
-bool CreateNewBookmarkFromNamedUrl(GtkSelectionData* selection_data, |
- BookmarkModel* model, const BookmarkNode* parent, int idx) { |
- GURL url; |
- string16 title; |
- if (!gtk_dnd_util::ExtractNamedURL(selection_data, &url, &title)) |
- return false; |
- |
- model->AddURL(parent, idx, title, url); |
- return true; |
-} |
- |
-bool CreateNewBookmarksFromURIList(GtkSelectionData* selection_data, |
- BookmarkModel* model, const BookmarkNode* parent, int idx) { |
- std::vector<GURL> urls; |
- gtk_dnd_util::ExtractURIList(selection_data, &urls); |
- for (size_t i = 0; i < urls.size(); ++i) { |
- std::string title = GetNameForURL(urls[i]); |
- model->AddURL(parent, idx++, UTF8ToUTF16(title), urls[i]); |
- } |
- return true; |
-} |
- |
-bool CreateNewBookmarkFromNetscapeURL(GtkSelectionData* selection_data, |
- BookmarkModel* model, const BookmarkNode* parent, int idx) { |
- GURL url; |
- string16 title; |
- if (!gtk_dnd_util::ExtractNetscapeURL(selection_data, &url, &title)) |
- return false; |
- |
- model->AddURL(parent, idx, title, url); |
- return true; |
-} |
- |
-} // namespace bookmark_utils |