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

Side by Side Diff: chrome/browser/gtk/bookmark_bar_gtk.cc

Issue 200029: Make the bookmark toolbar folders act like a menu bar.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: lint Created 11 years, 3 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
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2009 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/gtk/bookmark_bar_gtk.h" 5 #include "chrome/browser/gtk/bookmark_bar_gtk.h"
6 6
7 #include <vector> 7 #include <vector>
8 8
9 #include "app/gfx/text_elider.h" 9 #include "app/gfx/text_elider.h"
10 #include "app/gtk_dnd_util.h" 10 #include "app/gtk_dnd_util.h"
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
94 BrowserWindowGtk* window) 94 BrowserWindowGtk* window)
95 : profile_(NULL), 95 : profile_(NULL),
96 page_navigator_(NULL), 96 page_navigator_(NULL),
97 browser_(browser), 97 browser_(browser),
98 window_(window), 98 window_(window),
99 model_(NULL), 99 model_(NULL),
100 instructions_(NULL), 100 instructions_(NULL),
101 dragged_node_(NULL), 101 dragged_node_(NULL),
102 toolbar_drop_item_(NULL), 102 toolbar_drop_item_(NULL),
103 theme_provider_(GtkThemeProvider::GetFrom(profile)), 103 theme_provider_(GtkThemeProvider::GetFrom(profile)),
104 show_instructions_(true) { 104 show_instructions_(true),
105 menu_bar_helper_(this) {
105 Init(profile); 106 Init(profile);
106 SetProfile(profile); 107 SetProfile(profile);
107 108
108 registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED, 109 registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED,
109 NotificationService::AllSources()); 110 NotificationService::AllSources());
110 } 111 }
111 112
112 BookmarkBarGtk::~BookmarkBarGtk() { 113 BookmarkBarGtk::~BookmarkBarGtk() {
113 if (model_) 114 if (model_)
114 model_->RemoveObserver(this); 115 model_->RemoveObserver(this);
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after
302 303
303 void BookmarkBarGtk::BookmarkNodeAdded(BookmarkModel* model, 304 void BookmarkBarGtk::BookmarkNodeAdded(BookmarkModel* model,
304 const BookmarkNode* parent, 305 const BookmarkNode* parent,
305 int index) { 306 int index) {
306 if (parent != model_->GetBookmarkBarNode()) { 307 if (parent != model_->GetBookmarkBarNode()) {
307 // We only care about nodes on the bookmark bar. 308 // We only care about nodes on the bookmark bar.
308 return; 309 return;
309 } 310 }
310 DCHECK(index >= 0 && index <= GetBookmarkButtonCount()); 311 DCHECK(index >= 0 && index <= GetBookmarkButtonCount());
311 312
312 GtkToolItem* item = CreateBookmarkToolItem(parent->GetChild(index)); 313 const BookmarkNode* node = parent->GetChild(index);
314 GtkToolItem* item = CreateBookmarkToolItem(node);
313 gtk_toolbar_insert(GTK_TOOLBAR(bookmark_toolbar_.get()), 315 gtk_toolbar_insert(GTK_TOOLBAR(bookmark_toolbar_.get()),
314 item, index); 316 item, index);
317 if (node->is_folder())
318 menu_bar_helper_.Add(gtk_bin_get_child(GTK_BIN(item)));
315 319
316 SetInstructionState(); 320 SetInstructionState();
317 SetChevronState(); 321 SetChevronState();
318 } 322 }
319 323
320 void BookmarkBarGtk::BookmarkNodeRemoved(BookmarkModel* model, 324 void BookmarkBarGtk::BookmarkNodeRemoved(BookmarkModel* model,
321 const BookmarkNode* parent, 325 const BookmarkNode* parent,
322 int old_index, 326 int old_index,
323 const BookmarkNode* node) { 327 const BookmarkNode* node) {
324 if (parent != model_->GetBookmarkBarNode()) { 328 if (parent != model_->GetBookmarkBarNode()) {
325 // We only care about nodes on the bookmark bar. 329 // We only care about nodes on the bookmark bar.
326 return; 330 return;
327 } 331 }
328 DCHECK(old_index >= 0 && old_index < GetBookmarkButtonCount()); 332 DCHECK(old_index >= 0 && old_index < GetBookmarkButtonCount());
329 333
330 GtkWidget* to_remove = GTK_WIDGET(gtk_toolbar_get_nth_item( 334 GtkWidget* to_remove = GTK_WIDGET(gtk_toolbar_get_nth_item(
331 GTK_TOOLBAR(bookmark_toolbar_.get()), old_index)); 335 GTK_TOOLBAR(bookmark_toolbar_.get()), old_index));
336 menu_bar_helper_.Remove(gtk_bin_get_child(GTK_BIN(to_remove)));
332 gtk_container_remove(GTK_CONTAINER(bookmark_toolbar_.get()), 337 gtk_container_remove(GTK_CONTAINER(bookmark_toolbar_.get()),
333 to_remove); 338 to_remove);
334 339
335 SetInstructionState(); 340 SetInstructionState();
336 SetChevronState(); 341 SetChevronState();
337 } 342 }
338 343
339 void BookmarkBarGtk::BookmarkNodeChanged(BookmarkModel* model, 344 void BookmarkBarGtk::BookmarkNodeChanged(BookmarkModel* model,
340 const BookmarkNode* node) { 345 const BookmarkNode* node) {
341 if (node->GetParent() != model_->GetBookmarkBarNode()) { 346 if (node->GetParent() != model_->GetBookmarkBarNode()) {
(...skipping 26 matching lines...) Expand all
368 } 373 }
369 374
370 void BookmarkBarGtk::CreateAllBookmarkButtons() { 375 void BookmarkBarGtk::CreateAllBookmarkButtons() {
371 const BookmarkNode* node = model_->GetBookmarkBarNode(); 376 const BookmarkNode* node = model_->GetBookmarkBarNode();
372 DCHECK(node && model_->other_node()); 377 DCHECK(node && model_->other_node());
373 378
374 // Create a button for each of the children on the bookmark bar. 379 // Create a button for each of the children on the bookmark bar.
375 for (int i = 0; i < node->GetChildCount(); ++i) { 380 for (int i = 0; i < node->GetChildCount(); ++i) {
376 GtkToolItem* item = CreateBookmarkToolItem(node->GetChild(i)); 381 GtkToolItem* item = CreateBookmarkToolItem(node->GetChild(i));
377 gtk_toolbar_insert(GTK_TOOLBAR(bookmark_toolbar_.get()), item, -1); 382 gtk_toolbar_insert(GTK_TOOLBAR(bookmark_toolbar_.get()), item, -1);
383 if (node->is_folder())
384 menu_bar_helper_.Add(gtk_bin_get_child(GTK_BIN(item)));
378 } 385 }
379 386
380 bookmark_utils::ConfigureButtonForNode(model_->other_node(), 387 bookmark_utils::ConfigureButtonForNode(model_->other_node(),
381 model_, other_bookmarks_button_, theme_provider_); 388 model_, other_bookmarks_button_, theme_provider_);
382 389
383 SetInstructionState(); 390 SetInstructionState();
384 SetChevronState(); 391 SetChevronState();
385 } 392 }
386 393
387 void BookmarkBarGtk::SetInstructionState() { 394 void BookmarkBarGtk::SetInstructionState() {
388 show_instructions_ = (model_->GetBookmarkBarNode()->GetChildCount() == 0); 395 show_instructions_ = (model_->GetBookmarkBarNode()->GetChildCount() == 0);
389 if (show_instructions_) { 396 if (show_instructions_) {
390 gtk_widget_show_all(instructions_); 397 gtk_widget_show_all(instructions_);
391 } else { 398 } else {
392 gtk_widget_hide(instructions_); 399 gtk_widget_hide(instructions_);
393 } 400 }
394 } 401 }
395 402
396 void BookmarkBarGtk::SetChevronState() { 403 void BookmarkBarGtk::SetChevronState() {
397 int extra_space = 0; 404 int extra_space = 0;
398 405
399 if (GTK_WIDGET_VISIBLE(overflow_button_)) 406 if (GTK_WIDGET_VISIBLE(overflow_button_))
400 extra_space = overflow_button_->allocation.width; 407 extra_space = overflow_button_->allocation.width;
401 408
402 int overflow_idx = GetFirstHiddenBookmark(extra_space); 409 int overflow_idx = GetFirstHiddenBookmark(extra_space, NULL);
403 if (overflow_idx == -1) 410 if (overflow_idx == -1)
404 gtk_widget_hide(overflow_button_); 411 gtk_widget_hide(overflow_button_);
405 else 412 else
406 gtk_widget_show_all(overflow_button_); 413 gtk_widget_show_all(overflow_button_);
407 } 414 }
408 415
409 void BookmarkBarGtk::RemoveAllBookmarkButtons() { 416 void BookmarkBarGtk::RemoveAllBookmarkButtons() {
410 gtk_util::RemoveAllChildren(bookmark_toolbar_.get()); 417 gtk_util::RemoveAllChildren(bookmark_toolbar_.get());
418 menu_bar_helper_.Clear();
419 menu_bar_helper_.Add(other_bookmarks_button_);
420 menu_bar_helper_.Add(overflow_button_);
411 } 421 }
412 422
413 int BookmarkBarGtk::GetBookmarkButtonCount() { 423 int BookmarkBarGtk::GetBookmarkButtonCount() {
414 GList* children = gtk_container_get_children( 424 GList* children = gtk_container_get_children(
415 GTK_CONTAINER(bookmark_toolbar_.get())); 425 GTK_CONTAINER(bookmark_toolbar_.get()));
416 int count = g_list_length(children); 426 int count = g_list_length(children);
417 g_list_free(children); 427 g_list_free(children);
418 return count; 428 return count;
419 } 429 }
420 430
421 void BookmarkBarGtk::SetOverflowButtonAppearance() { 431 void BookmarkBarGtk::SetOverflowButtonAppearance() {
422 GtkWidget* former_child = gtk_bin_get_child(GTK_BIN(overflow_button_)); 432 GtkWidget* former_child = gtk_bin_get_child(GTK_BIN(overflow_button_));
423 if (former_child) 433 if (former_child)
424 gtk_widget_destroy(former_child); 434 gtk_widget_destroy(former_child);
425 435
426 GtkWidget* new_child = theme_provider_->UseGtkTheme() ? 436 GtkWidget* new_child = theme_provider_->UseGtkTheme() ?
427 gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_NONE) : 437 gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_NONE) :
428 gtk_image_new_from_pixbuf(ResourceBundle::GetSharedInstance(). 438 gtk_image_new_from_pixbuf(ResourceBundle::GetSharedInstance().
429 GetRTLEnabledPixbufNamed(IDR_BOOKMARK_BAR_CHEVRONS)); 439 GetRTLEnabledPixbufNamed(IDR_BOOKMARK_BAR_CHEVRONS));
430 440
431 gtk_container_add(GTK_CONTAINER(overflow_button_), new_child); 441 gtk_container_add(GTK_CONTAINER(overflow_button_), new_child);
432 SetChevronState(); 442 SetChevronState();
433 } 443 }
434 444
435 int BookmarkBarGtk::GetFirstHiddenBookmark(int extra_space) { 445 int BookmarkBarGtk::GetFirstHiddenBookmark(
446 int extra_space, std::vector<GtkWidget*>* showing_folders) {
436 int rv = 0; 447 int rv = 0;
437 bool overflow = false; 448 bool overflow = false;
438 GList* toolbar_items = 449 GList* toolbar_items =
439 gtk_container_get_children(GTK_CONTAINER(bookmark_toolbar_.get())); 450 gtk_container_get_children(GTK_CONTAINER(bookmark_toolbar_.get()));
440 for (GList* iter = toolbar_items; iter; iter = g_list_next(iter)) { 451 for (GList* iter = toolbar_items; iter; iter = g_list_next(iter)) {
441 GtkWidget* tool_item = reinterpret_cast<GtkWidget*>(iter->data); 452 GtkWidget* tool_item = reinterpret_cast<GtkWidget*>(iter->data);
442 if (tool_item->allocation.x + tool_item->allocation.width > 453 if (tool_item->allocation.x + tool_item->allocation.width >
443 bookmark_toolbar_.get()->allocation.width + extra_space) { 454 bookmark_toolbar_.get()->allocation.width + extra_space) {
444 overflow = true; 455 overflow = true;
445 break; 456 break;
446 } 457 }
458 if (showing_folders &&
459 model_->GetBookmarkBarNode()->GetChild(rv)->is_folder()) {
460 showing_folders->push_back(gtk_bin_get_child(GTK_BIN(tool_item)));
461 }
447 rv++; 462 rv++;
448 } 463 }
449 464
450 g_list_free(toolbar_items); 465 g_list_free(toolbar_items);
451 466
452 if (!overflow) 467 if (!overflow)
453 return -1; 468 return -1;
454 469
455 return rv; 470 return rv;
456 } 471 }
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
523 if (node->is_url()) { 538 if (node->is_url()) {
524 // Connect to 'button-release-event' instead of 'clicked' because we need 539 // Connect to 'button-release-event' instead of 'clicked' because we need
525 // access to the modifier keys and we do different things on each 540 // access to the modifier keys and we do different things on each
526 // button. 541 // button.
527 g_signal_connect(G_OBJECT(button), "button-press-event", 542 g_signal_connect(G_OBJECT(button), "button-press-event",
528 G_CALLBACK(OnButtonPressed), this); 543 G_CALLBACK(OnButtonPressed), this);
529 g_signal_connect(G_OBJECT(button), "clicked", 544 g_signal_connect(G_OBJECT(button), "clicked",
530 G_CALLBACK(OnClicked), this); 545 G_CALLBACK(OnClicked), this);
531 gtk_util::SetButtonTriggersNavigation(button); 546 gtk_util::SetButtonTriggersNavigation(button);
532 } else { 547 } else {
533 // TODO(erg): This button can also be a drop target.
534 ConnectFolderButtonEvents(button); 548 ConnectFolderButtonEvents(button);
535 } 549 }
536 550
537 return button; 551 return button;
538 } 552 }
539 553
540 GtkToolItem* BookmarkBarGtk::CreateBookmarkToolItem(const BookmarkNode* node) { 554 GtkToolItem* BookmarkBarGtk::CreateBookmarkToolItem(const BookmarkNode* node) {
541 GtkWidget* button = CreateBookmarkButton(node); 555 GtkWidget* button = CreateBookmarkButton(node);
542 g_object_set_data(G_OBJECT(button), "left-align-popup", 556 g_object_set_data(G_OBJECT(button), "left-align-popup",
543 reinterpret_cast<void*>(true)); 557 reinterpret_cast<void*>(true));
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
706 guint target_type, guint time, 720 guint target_type, guint time,
707 BookmarkBarGtk* bar) { 721 BookmarkBarGtk* bar) {
708 const BookmarkNode* node = bookmark_utils::BookmarkNodeForWidget(widget); 722 const BookmarkNode* node = bookmark_utils::BookmarkNodeForWidget(widget);
709 bookmark_utils::WriteBookmarkToSelection(node, selection_data, target_type, 723 bookmark_utils::WriteBookmarkToSelection(node, selection_data, target_type,
710 bar->profile_); 724 bar->profile_);
711 } 725 }
712 726
713 // static 727 // static
714 void BookmarkBarGtk::OnFolderClicked(GtkWidget* sender, 728 void BookmarkBarGtk::OnFolderClicked(GtkWidget* sender,
715 BookmarkBarGtk* bar) { 729 BookmarkBarGtk* bar) {
716 const BookmarkNode* node = bar->GetNodeForToolButton(sender); 730 bar->PopupForButton(sender);
717 DCHECK(node);
718 DCHECK(bar->page_navigator_);
719
720 int start_child_idx = 0;
721 if (sender == bar->overflow_button_)
722 start_child_idx = bar->GetFirstHiddenBookmark(0);
723
724 bar->current_menu_.reset(
725 new BookmarkMenuController(bar->browser_, bar->profile_,
726 bar->page_navigator_,
727 GTK_WINDOW(gtk_widget_get_toplevel(sender)),
728 node,
729 start_child_idx,
730 false));
731 GdkEventButton* event =
732 reinterpret_cast<GdkEventButton*>(gtk_get_current_event());
733 bar->current_menu_->Popup(sender, event->button, event->time);
734 } 731 }
735 732
736 // static 733 // static
737 gboolean BookmarkBarGtk::OnToolbarExpose(GtkWidget* widget, 734 gboolean BookmarkBarGtk::OnToolbarExpose(GtkWidget* widget,
738 GdkEventExpose* event, 735 GdkEventExpose* event,
739 BookmarkBarGtk* bar) { 736 BookmarkBarGtk* bar) {
740 // A GtkToolbar's expose handler first draws a box. We don't want that so we 737 // A GtkToolbar's expose handler first draws a box. We don't want that so we
741 // need to propagate the expose event to all the container's children. 738 // need to propagate the expose event to all the container's children.
742 GList* children = gtk_container_get_children(GTK_CONTAINER(widget)); 739 GList* children = gtk_container_get_children(GTK_CONTAINER(widget));
743 for (GList* item = children; item; item = item->next) { 740 for (GList* item = children; item; item = item->next) {
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after
957 cairo_set_line_width(cr, 1.0); 954 cairo_set_line_width(cr, 1.0);
958 cairo_move_to(cr, start_x, widget->allocation.y); 955 cairo_move_to(cr, start_x, widget->allocation.y);
959 cairo_line_to(cr, start_x, 956 cairo_line_to(cr, start_x,
960 widget->allocation.y + widget->allocation.height); 957 widget->allocation.y + widget->allocation.height);
961 cairo_stroke(cr); 958 cairo_stroke(cr);
962 cairo_destroy(cr); 959 cairo_destroy(cr);
963 cairo_pattern_destroy(pattern); 960 cairo_pattern_destroy(pattern);
964 961
965 return TRUE; 962 return TRUE;
966 } 963 }
964
965 // MenuBarHelper::Delegate implementation --------------------------------------
966 void BookmarkBarGtk::PopupForButton(GtkWidget* button) {
967 const BookmarkNode* node = GetNodeForToolButton(button);
968 DCHECK(node);
969 DCHECK(page_navigator_);
970
971 int first_hidden = GetFirstHiddenBookmark(0, NULL);
972 if (button != overflow_button_ && button != other_bookmarks_button_ &&
973 node->GetParent()->IndexOfChild(node) >= first_hidden) {
974 return;
975 }
976
977 current_menu_.reset(
978 new BookmarkMenuController(browser_, profile_,
979 page_navigator_,
980 GTK_WINDOW(gtk_widget_get_toplevel(button)),
981 node,
982 button == overflow_button_ ?
983 first_hidden : 0,
984 false));
985 menu_bar_helper_.MenuStartedShowing(button, current_menu_->widget());
986 GdkEventButton* event =
987 reinterpret_cast<GdkEventButton*>(gtk_get_current_event());
988 current_menu_->Popup(button, event->button, event->time);
989 }
990
991 void BookmarkBarGtk::PopupForButtonNextTo(GtkWidget* button,
992 GtkMenuDirectionType dir) {
993 const BookmarkNode* relative_node = GetNodeForToolButton(button);
994 DCHECK(relative_node);
995
996 // Find out the order of the buttons.
997 std::vector<GtkWidget*> folder_list;
998 const int first_hidden = GetFirstHiddenBookmark(0, &folder_list);
999 if (first_hidden != -1)
1000 folder_list.push_back(overflow_button_);
1001 folder_list.push_back(other_bookmarks_button_);
1002
1003 // Find the position of |button|.
1004 int button_idx = -1;
1005 for (size_t i = 0; i < folder_list.size(); ++i) {
1006 if (folder_list[i] == button) {
1007 button_idx = i;
1008 break;
1009 }
1010 }
1011 DCHECK_NE(button_idx, -1);
1012
1013 // Find the GtkWidget* for the actual target button.
1014 int shift = dir == GTK_MENU_DIR_PARENT ? -1 : 1;
1015 button_idx = (button_idx + shift + folder_list.size()) % folder_list.size();
1016 PopupForButton(folder_list[button_idx]);
1017 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698