Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(683)

Side by Side Diff: chrome/browser/ui/gtk/global_bookmark_menu.cc

Issue 6980011: GTK: Implement the global bookmarks menu. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: 'GlobalBookmarkMenu' Created 9 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/browser/ui/gtk/global_bookmark_menu.h ('k') | chrome/browser/ui/gtk/global_menu_bar.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2011 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/global_bookmark_menu.h"
6
7 #include <gtk/gtk.h>
8
9 #include "base/logging.h"
10 #include "base/utf_string_conversions.h"
11 #include "chrome/browser/bookmarks/bookmark_model.h"
12 #include "chrome/browser/profiles/profile.h"
13 #include "chrome/browser/ui/browser.h"
14 #include "chrome/browser/ui/gtk/global_bookmark_menu.h"
15 #include "chrome/browser/ui/gtk/global_menu_bar.h"
16 #include "chrome/browser/ui/gtk/gtk_theme_service.h"
17 #include "chrome/browser/ui/gtk/gtk_util.h"
18 #include "content/common/notification_service.h"
19 #include "grit/generated_resources.h"
20 #include "ui/base/l10n/l10n_util.h"
21 #include "ui/gfx/gtk_util.h"
22
23 namespace {
24
25 const int kMaxChars = 50;
26
27 } // namespace
28
29 GlobalBookmarkMenu::GlobalBookmarkMenu(Browser* browser)
30 : browser_(browser),
31 profile_(browser->profile()),
32 default_favicon_(NULL),
33 ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {
34 DCHECK(profile_);
35
36 default_favicon_ = GtkThemeService::GetDefaultFavicon(true);
37 default_folder_ = GtkThemeService::GetFolderIcon(true);
38 registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED,
39 Source<Profile>(profile_));
40 }
41
42 GlobalBookmarkMenu::~GlobalBookmarkMenu() {
43 profile_->GetBookmarkModel()->RemoveObserver(this);
44 }
45
46 void GlobalBookmarkMenu::Init(GtkWidget* bookmark_menu) {
47 bookmark_menu_ = bookmark_menu;
48
49 BookmarkModel* model = profile_->GetBookmarkModel();
50 model->AddObserver(this);
51 if (model->IsLoaded())
52 Loaded(model);
53 }
54
55 void GlobalBookmarkMenu::RebuildMenuInFuture() {
56 method_factory_.RevokeAll();
57 MessageLoop::current()->PostTask(
58 FROM_HERE,
59 method_factory_.NewRunnableMethod(&GlobalBookmarkMenu::RebuildMenu));
60 }
61
62 void GlobalBookmarkMenu::RebuildMenu() {
63 BookmarkModel* model = profile_->GetBookmarkModel();
64 DCHECK(model);
65 DCHECK(model->IsLoaded());
66
67 ClearBookmarkMenu();
68
69 const BookmarkNode* bar_node = model->GetBookmarkBarNode();
70 if (bar_node->child_count()) {
71 AddBookmarkMenuItem(bookmark_menu_, gtk_separator_menu_item_new());
72 AddNodeToMenu(bar_node, bookmark_menu_);
73 }
74
75 // Only display the other bookmarks folder in the menu if it has items in it.
76 const BookmarkNode* other_node = model->other_node();
77 if (other_node->child_count()) {
78 GtkWidget* submenu = gtk_menu_new();
79 AddNodeToMenu(other_node, submenu);
80
81 AddBookmarkMenuItem(bookmark_menu_, gtk_separator_menu_item_new());
82
83 GtkWidget* menu_item = gtk_image_menu_item_new_with_label(
84 l10n_util::GetStringUTF8(IDS_BOOMARK_BAR_OTHER_FOLDER_NAME).c_str());
85 gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item), submenu);
86 gtk_image_menu_item_set_image(
87 GTK_IMAGE_MENU_ITEM(menu_item),
88 gtk_image_new_from_pixbuf(default_folder_));
89
90 AddBookmarkMenuItem(bookmark_menu_, menu_item);
91 }
92 }
93
94 void GlobalBookmarkMenu::AddBookmarkMenuItem(GtkWidget* menu,
95 GtkWidget* menu_item) {
96 g_object_set_data(G_OBJECT(menu_item), "type-tag",
97 GINT_TO_POINTER(GlobalMenuBar::TAG_BOOKMARK_CLEARABLE));
98 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
99 gtk_widget_show(menu_item);
100 }
101
102 void GlobalBookmarkMenu::AddNodeToMenu(const BookmarkNode* node,
103 GtkWidget* menu) {
104 int child_count = node->child_count();
105 if (!child_count) {
106 GtkWidget* item = gtk_menu_item_new_with_label(
107 l10n_util::GetStringUTF8(IDS_MENU_EMPTY_SUBMENU).c_str());
108 gtk_widget_set_sensitive(item, FALSE);
109 AddBookmarkMenuItem(menu, item);
110 } else {
111 for (int i = 0; i < child_count; i++) {
112 const BookmarkNode* child = node->GetChild(i);
113 GtkWidget* item = gtk_image_menu_item_new();
114 ConfigureMenuItem(child, item);
115 bookmark_nodes_[child] = item;
116
117 if (child->is_folder()) {
118 GtkWidget* submenu = gtk_menu_new();
119 AddNodeToMenu(child, submenu);
120 gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), submenu);
121 } else {
122 g_object_set_data(G_OBJECT(item), "bookmark-node",
123 const_cast<BookmarkNode*>(child));
124 g_signal_connect(item, "activate",
125 G_CALLBACK(OnBookmarkItemActivatedThunk), this);
126 }
127
128 AddBookmarkMenuItem(menu, item);
129 }
130 }
131 }
132
133 void GlobalBookmarkMenu::ConfigureMenuItem(const BookmarkNode* node,
134 GtkWidget* menu_item) {
135 string16 elided_name = l10n_util::TruncateString(node->GetTitle(), kMaxChars);
136 gtk_menu_item_set_label(GTK_MENU_ITEM(menu_item),
137 UTF16ToUTF8(elided_name).c_str());
138
139 if (node->is_url()) {
140 std::string tooltip = gtk_util::BuildTooltipTitleFor(node->GetTitle(),
141 node->GetURL());
142 gtk_widget_set_tooltip_markup(menu_item, tooltip.c_str());
143 }
144
145 const SkBitmap& bitmap = profile_->GetBookmarkModel()->GetFavicon(node);
146 if (!bitmap.isNull()) {
147 GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(&bitmap);
148 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item),
149 gtk_image_new_from_pixbuf(pixbuf));
150 g_object_unref(pixbuf);
151 } else {
152 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item),
153 gtk_image_new_from_pixbuf(
154 node->is_url() ? default_favicon_ :
155 default_folder_));
156 }
157 }
158
159 GtkWidget* GlobalBookmarkMenu::MenuItemForNode(const BookmarkNode* node) {
160 if (!node)
161 return NULL;
162 std::map<const BookmarkNode*, GtkWidget*>::iterator it =
163 bookmark_nodes_.find(node);
164 if (it == bookmark_nodes_.end())
165 return NULL;
166 return it->second;
167 }
168
169 void GlobalBookmarkMenu::ClearBookmarkMenu() {
170 bookmark_nodes_.clear();
171
172 gtk_container_foreach(GTK_CONTAINER(bookmark_menu_),
173 &ClearBookmarkItemCallback,
174 NULL);
175 }
176
177 // static
178 void GlobalBookmarkMenu::ClearBookmarkItemCallback(GtkWidget* menu_item,
179 void* unused) {
180 int tag = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(menu_item), "type-tag"));
181 if (tag == GlobalMenuBar::TAG_BOOKMARK_CLEARABLE)
182 gtk_widget_destroy(menu_item);
183 }
184
185 void GlobalBookmarkMenu::Observe(NotificationType type,
186 const NotificationSource& source,
187 const NotificationDetails& details) {
188 DCHECK(type.value == NotificationType::BROWSER_THEME_CHANGED);
189
190 // Change the icon and invalidate the menu.
191 default_favicon_ = GtkThemeService::GetDefaultFavicon(true);
192 default_folder_ = GtkThemeService::GetFolderIcon(true);
193 RebuildMenuInFuture();
194 }
195
196 void GlobalBookmarkMenu::Loaded(BookmarkModel* model) {
197 // If we have a Loaded() event, then we need to build the menu immediately
198 // for the first time.
199 RebuildMenu();
200 }
201
202 void GlobalBookmarkMenu::BookmarkModelBeingDeleted(BookmarkModel* model) {
203 ClearBookmarkMenu();
204 }
205
206 void GlobalBookmarkMenu::BookmarkNodeMoved(BookmarkModel* model,
207 const BookmarkNode* old_parent,
208 int old_index,
209 const BookmarkNode* new_parent,
210 int new_index) {
211 RebuildMenuInFuture();
212 }
213
214 void GlobalBookmarkMenu::BookmarkNodeAdded(BookmarkModel* model,
215 const BookmarkNode* parent,
216 int index) {
217 RebuildMenuInFuture();
218 }
219
220 void GlobalBookmarkMenu::BookmarkNodeRemoved(BookmarkModel* model,
221 const BookmarkNode* parent,
222 int old_index,
223 const BookmarkNode* node) {
224 GtkWidget* item = MenuItemForNode(node);
225 if (item) {
226 gtk_widget_destroy(item);
227 bookmark_nodes_.erase(node);
228 }
229 }
230
231 void GlobalBookmarkMenu::BookmarkNodeChanged(BookmarkModel* model,
232 const BookmarkNode* node) {
233 GtkWidget* item = MenuItemForNode(node);
234 if (item)
235 ConfigureMenuItem(node, item);
236 }
237
238 void GlobalBookmarkMenu::BookmarkNodeFaviconLoaded(BookmarkModel* model,
239 const BookmarkNode* node) {
240 GtkWidget* item = MenuItemForNode(node);
241 if (item)
242 ConfigureMenuItem(node, item);
243 }
244
245 void GlobalBookmarkMenu::BookmarkNodeChildrenReordered(
246 BookmarkModel* model,
247 const BookmarkNode* node) {
248 RebuildMenuInFuture();
249 }
250
251 void GlobalBookmarkMenu::OnBookmarkItemActivated(GtkWidget* menu_item) {
252 // The actual mouse event that generated this activated event was in a
253 // different process. Go with something default.
254 const BookmarkNode* node = static_cast<const BookmarkNode*>(
255 g_object_get_data(G_OBJECT(menu_item), "bookmark-node"));
256
257 browser_->OpenURL(node->GetURL(), GURL(), NEW_FOREGROUND_TAB,
258 PageTransition::AUTO_BOOKMARK);
259 }
260
OLDNEW
« no previous file with comments | « chrome/browser/ui/gtk/global_bookmark_menu.h ('k') | chrome/browser/ui/gtk/global_menu_bar.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698