| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 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/views/wrench_menu.h" | 5 #include "chrome/browser/ui/views/wrench_menu.h" |
| 6 | 6 |
| 7 #include <cmath> | 7 #include <cmath> |
| 8 | 8 |
| 9 #include "base/string_number_conversions.h" | 9 #include "base/string_number_conversions.h" |
| 10 #include "base/utf_string_conversions.h" | 10 #include "base/utf_string_conversions.h" |
| 11 #include "chrome/app/chrome_command_ids.h" | 11 #include "chrome/app/chrome_command_ids.h" |
| 12 #include "chrome/browser/bookmarks/bookmark_model.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" |
| 15 #include "chrome/browser/ui/browser_window.h" |
| 16 #include "chrome/browser/ui/views/bookmarks/bookmark_menu_delegate.h" |
| 14 #include "content/browser/tab_contents/tab_contents.h" | 17 #include "content/browser/tab_contents/tab_contents.h" |
| 15 #include "content/browser/user_metrics.h" | 18 #include "content/browser/user_metrics.h" |
| 16 #include "content/common/notification_observer.h" | 19 #include "content/common/notification_observer.h" |
| 17 #include "content/common/notification_registrar.h" | 20 #include "content/common/notification_registrar.h" |
| 18 #include "content/common/notification_source.h" | 21 #include "content/common/notification_source.h" |
| 19 #include "content/common/notification_type.h" | 22 #include "content/common/notification_type.h" |
| 20 #include "grit/chromium_strings.h" | 23 #include "grit/chromium_strings.h" |
| 21 #include "grit/generated_resources.h" | 24 #include "grit/generated_resources.h" |
| 22 #include "grit/theme_resources.h" | 25 #include "grit/theme_resources.h" |
| 23 #include "third_party/skia/include/core/SkPaint.h" | 26 #include "third_party/skia/include/core/SkPaint.h" |
| (...skipping 533 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 557 int zoom_label_width_; | 560 int zoom_label_width_; |
| 558 | 561 |
| 559 DISALLOW_COPY_AND_ASSIGN(ZoomView); | 562 DISALLOW_COPY_AND_ASSIGN(ZoomView); |
| 560 }; | 563 }; |
| 561 | 564 |
| 562 // WrenchMenu ------------------------------------------------------------------ | 565 // WrenchMenu ------------------------------------------------------------------ |
| 563 | 566 |
| 564 WrenchMenu::WrenchMenu(Browser* browser) | 567 WrenchMenu::WrenchMenu(Browser* browser) |
| 565 : browser_(browser), | 568 : browser_(browser), |
| 566 selected_menu_model_(NULL), | 569 selected_menu_model_(NULL), |
| 567 selected_index_(0) { | 570 selected_index_(0), |
| 571 bookmark_menu_(NULL), |
| 572 first_bookmark_command_id_(0) { |
| 568 } | 573 } |
| 569 | 574 |
| 570 void WrenchMenu::Init(ui::MenuModel* model) { | 575 void WrenchMenu::Init(ui::MenuModel* model) { |
| 571 DCHECK(!root_.get()); | 576 DCHECK(!root_.get()); |
| 572 root_.reset(new MenuItemView(this)); | 577 root_.reset(new MenuItemView(this)); |
| 573 root_->set_has_icons(true); // We have checks, radios and icons, set this | 578 root_->set_has_icons(true); // We have checks, radios and icons, set this |
| 574 // so we get the taller menu style. | 579 // so we get the taller menu style. |
| 575 int next_id = 1; | 580 int next_id = 1; |
| 576 PopulateMenu(root_.get(), model, &next_id); | 581 PopulateMenu(root_.get(), model, &next_id); |
| 582 first_bookmark_command_id_ = next_id + 1; |
| 577 } | 583 } |
| 578 | 584 |
| 579 void WrenchMenu::RunMenu(views::MenuButton* host) { | 585 void WrenchMenu::RunMenu(views::MenuButton* host) { |
| 580 // Up the ref count while the menu is displaying. This way if the window is | 586 // Up the ref count while the menu is displaying. This way if the window is |
| 581 // deleted while we're running we won't prematurely delete the menu. | 587 // deleted while we're running we won't prematurely delete the menu. |
| 582 // TODO(sky): fix this, the menu should really take ownership of the menu | 588 // TODO(sky): fix this, the menu should really take ownership of the menu |
| 583 // (57890). | 589 // (57890). |
| 584 scoped_refptr<WrenchMenu> dont_delete_while_running(this); | 590 scoped_refptr<WrenchMenu> dont_delete_while_running(this); |
| 585 gfx::Point screen_loc; | 591 gfx::Point screen_loc; |
| 586 views::View::ConvertPointToScreen(host, &screen_loc); | 592 views::View::ConvertPointToScreen(host, &screen_loc); |
| 587 gfx::Rect bounds(screen_loc, host->size()); | 593 gfx::Rect bounds(screen_loc, host->size()); |
| 588 UserMetrics::RecordAction(UserMetricsAction("ShowAppMenu")); | 594 UserMetrics::RecordAction(UserMetricsAction("ShowAppMenu")); |
| 589 root_->RunMenuAt(host->GetWindow()->GetNativeWindow(), host, bounds, | 595 root_->RunMenuAt(host->GetWindow()->GetNativeWindow(), host, bounds, |
| 590 base::i18n::IsRTL() ? MenuItemView::TOPLEFT : MenuItemView::TOPRIGHT, | 596 base::i18n::IsRTL() ? MenuItemView::TOPLEFT : MenuItemView::TOPRIGHT, |
| 591 true); | 597 true); |
| 598 if (bookmark_menu_delegate_.get()) { |
| 599 BookmarkModel* model = browser_->profile()->GetBookmarkModel(); |
| 600 if (model) |
| 601 model->RemoveObserver(this); |
| 602 } |
| 592 if (selected_menu_model_) | 603 if (selected_menu_model_) |
| 593 selected_menu_model_->ActivatedAt(selected_index_); | 604 selected_menu_model_->ActivatedAt(selected_index_); |
| 594 } | 605 } |
| 595 | 606 |
| 607 std::wstring WrenchMenu::GetTooltipText(int id, |
| 608 const gfx::Point& p) { |
| 609 return is_bookmark_command(id) ? |
| 610 bookmark_menu_delegate_->GetTooltipText(id, p) : std::wstring(); |
| 611 } |
| 612 |
| 613 bool WrenchMenu::IsTriggerableEvent(views::MenuItemView* menu, |
| 614 const views::MouseEvent& e) { |
| 615 return is_bookmark_command(menu->GetCommand()) ? |
| 616 bookmark_menu_delegate_->IsTriggerableEvent(menu, e) : |
| 617 MenuDelegate::IsTriggerableEvent(menu, e); |
| 618 } |
| 619 |
| 620 bool WrenchMenu::GetDropFormats( |
| 621 MenuItemView* menu, |
| 622 int* formats, |
| 623 std::set<ui::OSExchangeData::CustomFormat>* custom_formats) { |
| 624 CreateBookmarkMenu(); |
| 625 return bookmark_menu_delegate_.get() && |
| 626 bookmark_menu_delegate_->GetDropFormats(menu, formats, custom_formats); |
| 627 } |
| 628 |
| 629 bool WrenchMenu::AreDropTypesRequired(MenuItemView* menu) { |
| 630 CreateBookmarkMenu(); |
| 631 return bookmark_menu_delegate_.get() && |
| 632 bookmark_menu_delegate_->AreDropTypesRequired(menu); |
| 633 } |
| 634 |
| 635 bool WrenchMenu::CanDrop(MenuItemView* menu, |
| 636 const ui::OSExchangeData& data) { |
| 637 CreateBookmarkMenu(); |
| 638 return bookmark_menu_delegate_.get() && |
| 639 bookmark_menu_delegate_->CanDrop(menu, data); |
| 640 } |
| 641 |
| 642 int WrenchMenu::GetDropOperation( |
| 643 MenuItemView* item, |
| 644 const views::DropTargetEvent& event, |
| 645 DropPosition* position) { |
| 646 return is_bookmark_command(item->GetCommand()) ? |
| 647 bookmark_menu_delegate_->GetDropOperation(item, event, position) : |
| 648 ui::DragDropTypes::DRAG_NONE; |
| 649 } |
| 650 |
| 651 int WrenchMenu::OnPerformDrop(MenuItemView* menu, |
| 652 DropPosition position, |
| 653 const views::DropTargetEvent& event) { |
| 654 if (!is_bookmark_command(menu->GetCommand())) |
| 655 return ui::DragDropTypes::DRAG_NONE; |
| 656 |
| 657 int result = bookmark_menu_delegate_->OnPerformDrop(menu, position, event); |
| 658 return result; |
| 659 } |
| 660 |
| 661 bool WrenchMenu::ShowContextMenu(MenuItemView* source, |
| 662 int id, |
| 663 const gfx::Point& p, |
| 664 bool is_mouse_gesture) { |
| 665 return is_bookmark_command(id) ? |
| 666 bookmark_menu_delegate_->ShowContextMenu(source, id, p, |
| 667 is_mouse_gesture) : |
| 668 false; |
| 669 } |
| 670 |
| 671 bool WrenchMenu::CanDrag(MenuItemView* menu) { |
| 672 return is_bookmark_command(menu->GetCommand()) ? |
| 673 bookmark_menu_delegate_->CanDrag(menu) : false; |
| 674 } |
| 675 |
| 676 void WrenchMenu::WriteDragData(MenuItemView* sender, |
| 677 ui::OSExchangeData* data) { |
| 678 DCHECK(is_bookmark_command(sender->GetCommand())); |
| 679 return bookmark_menu_delegate_->WriteDragData(sender, data); |
| 680 } |
| 681 |
| 682 int WrenchMenu::GetDragOperations(MenuItemView* sender) { |
| 683 return is_bookmark_command(sender->GetCommand()) ? |
| 684 bookmark_menu_delegate_->GetDragOperations(sender) : |
| 685 MenuDelegate::GetDragOperations(sender); |
| 686 } |
| 687 |
| 688 int WrenchMenu::GetMaxWidthForMenu(MenuItemView* menu) { |
| 689 return is_bookmark_command(menu->GetCommand()) ? |
| 690 bookmark_menu_delegate_->GetMaxWidthForMenu(menu) : |
| 691 MenuDelegate::GetMaxWidthForMenu(menu); |
| 692 } |
| 693 |
| 596 bool WrenchMenu::IsItemChecked(int id) const { | 694 bool WrenchMenu::IsItemChecked(int id) const { |
| 695 if (!is_bookmark_command(id)) |
| 696 return false; |
| 697 |
| 597 const Entry& entry = id_to_entry_.find(id)->second; | 698 const Entry& entry = id_to_entry_.find(id)->second; |
| 598 return entry.first->IsItemCheckedAt(entry.second); | 699 return entry.first->IsItemCheckedAt(entry.second); |
| 599 } | 700 } |
| 600 | 701 |
| 601 bool WrenchMenu::IsCommandEnabled(int id) const { | 702 bool WrenchMenu::IsCommandEnabled(int id) const { |
| 703 if (is_bookmark_command(id)) |
| 704 return true; |
| 705 |
| 602 if (id == 0) | 706 if (id == 0) |
| 603 return false; // The root item. | 707 return false; // The root item. |
| 604 | 708 |
| 605 const Entry& entry = id_to_entry_.find(id)->second; | 709 const Entry& entry = id_to_entry_.find(id)->second; |
| 606 int command_id = entry.first->GetCommandIdAt(entry.second); | 710 int command_id = entry.first->GetCommandIdAt(entry.second); |
| 607 // The items representing the cut (cut/copy/paste) and zoom menu | 711 // The items representing the cut (cut/copy/paste) and zoom menu |
| 608 // (increment/decrement/reset) are always enabled. The child views of these | 712 // (increment/decrement/reset) are always enabled. The child views of these |
| 609 // items enabled state updates appropriately. | 713 // items enabled state updates appropriately. |
| 610 return command_id == IDC_CUT || command_id == IDC_ZOOM_MINUS || | 714 return command_id == IDC_CUT || command_id == IDC_ZOOM_MINUS || |
| 611 entry.first->IsEnabledAt(entry.second); | 715 entry.first->IsEnabledAt(entry.second); |
| 612 } | 716 } |
| 613 | 717 |
| 614 void WrenchMenu::ExecuteCommand(int id) { | 718 void WrenchMenu::ExecuteCommand(int id, int mouse_event_flags) { |
| 719 if (is_bookmark_command(id)) { |
| 720 bookmark_menu_delegate_->ExecuteCommand(id, mouse_event_flags); |
| 721 return; |
| 722 } |
| 723 |
| 724 // Not a bookmark |
| 615 const Entry& entry = id_to_entry_.find(id)->second; | 725 const Entry& entry = id_to_entry_.find(id)->second; |
| 616 int command_id = entry.first->GetCommandIdAt(entry.second); | 726 int command_id = entry.first->GetCommandIdAt(entry.second); |
| 617 | 727 |
| 618 if (command_id == IDC_CUT || command_id == IDC_ZOOM_MINUS) { | 728 if (command_id == IDC_CUT || command_id == IDC_ZOOM_MINUS) { |
| 619 // These items are represented by child views. If ExecuteCommand is invoked | 729 // These items are represented by child views. If ExecuteCommand is invoked |
| 620 // it means the user clicked on the area around the buttons and we should | 730 // it means the user clicked on the area around the buttons and we should |
| 621 // not do anyting. | 731 // not do anyting. |
| 622 return; | 732 return; |
| 623 } | 733 } |
| 624 | 734 |
| 625 return entry.first->ActivatedAt(entry.second); | 735 return entry.first->ActivatedAt(entry.second); |
| 626 } | 736 } |
| 627 | 737 |
| 628 bool WrenchMenu::GetAccelerator(int id, views::Accelerator* accelerator) { | 738 bool WrenchMenu::GetAccelerator(int id, views::Accelerator* accelerator) { |
| 739 if (is_bookmark_command(id)) |
| 740 return false; |
| 741 |
| 629 const Entry& entry = id_to_entry_.find(id)->second; | 742 const Entry& entry = id_to_entry_.find(id)->second; |
| 630 int command_id = entry.first->GetCommandIdAt(entry.second); | 743 int command_id = entry.first->GetCommandIdAt(entry.second); |
| 631 if (command_id == IDC_CUT || command_id == IDC_ZOOM_MINUS) { | 744 if (command_id == IDC_CUT || command_id == IDC_ZOOM_MINUS) { |
| 632 // These have special child views; don't show the accelerator for them. | 745 // These have special child views; don't show the accelerator for them. |
| 633 return false; | 746 return false; |
| 634 } | 747 } |
| 635 | 748 |
| 636 ui::Accelerator menu_accelerator; | 749 ui::Accelerator menu_accelerator; |
| 637 if (!entry.first->GetAcceleratorAt(entry.second, &menu_accelerator)) | 750 if (!entry.first->GetAcceleratorAt(entry.second, &menu_accelerator)) |
| 638 return false; | 751 return false; |
| 639 | 752 |
| 640 *accelerator = views::Accelerator(menu_accelerator.key_code(), | 753 *accelerator = views::Accelerator(menu_accelerator.key_code(), |
| 641 menu_accelerator.modifiers()); | 754 menu_accelerator.modifiers()); |
| 642 return true; | 755 return true; |
| 643 } | 756 } |
| 644 | 757 |
| 758 void WrenchMenu::WillShowMenu(MenuItemView* menu) { |
| 759 if (menu == bookmark_menu_) |
| 760 CreateBookmarkMenu(); |
| 761 } |
| 762 |
| 763 void WrenchMenu::BookmarkModelChanged() { |
| 764 root_->Cancel(); |
| 765 } |
| 766 |
| 645 WrenchMenu::~WrenchMenu() { | 767 WrenchMenu::~WrenchMenu() { |
| 646 } | 768 } |
| 647 | 769 |
| 648 void WrenchMenu::PopulateMenu(MenuItemView* parent, | 770 void WrenchMenu::PopulateMenu(MenuItemView* parent, |
| 649 MenuModel* model, | 771 MenuModel* model, |
| 650 int* next_id) { | 772 int* next_id) { |
| 651 int index_offset = model->GetFirstItemIndex(NULL); | 773 int index_offset = model->GetFirstItemIndex(NULL); |
| 652 for (int i = 0, max = model->GetItemCount(); i < max; ++i) { | 774 for (int i = 0, max = model->GetItemCount(); i < max; ++i) { |
| 653 int index = i + index_offset; | 775 int index = i + index_offset; |
| 654 | 776 |
| 655 MenuItemView* item = | 777 MenuItemView* item = |
| 656 AppendMenuItem(parent, model, index, model->GetTypeAt(index), next_id); | 778 AppendMenuItem(parent, model, index, model->GetTypeAt(index), next_id); |
| 657 | 779 |
| 658 if (model->GetTypeAt(index) == MenuModel::TYPE_SUBMENU) | 780 if (model->GetTypeAt(index) == MenuModel::TYPE_SUBMENU) |
| 659 PopulateMenu(item, model->GetSubmenuModelAt(index), next_id); | 781 PopulateMenu(item, model->GetSubmenuModelAt(index), next_id); |
| 660 | 782 |
| 661 if (model->GetCommandIdAt(index) == IDC_CUT) { | 783 switch (model->GetCommandIdAt(index)) { |
| 662 DCHECK_EQ(MenuModel::TYPE_COMMAND, model->GetTypeAt(index)); | 784 case IDC_CUT: |
| 663 DCHECK_LT(i + 2, max); | 785 DCHECK_EQ(MenuModel::TYPE_COMMAND, model->GetTypeAt(index)); |
| 664 DCHECK_EQ(IDC_COPY, model->GetCommandIdAt(index + 1)); | 786 DCHECK_LT(i + 2, max); |
| 665 DCHECK_EQ(IDC_PASTE, model->GetCommandIdAt(index + 2)); | 787 DCHECK_EQ(IDC_COPY, model->GetCommandIdAt(index + 1)); |
| 666 item->SetTitle(UTF16ToWide(l10n_util::GetStringUTF16(IDS_EDIT2))); | 788 DCHECK_EQ(IDC_PASTE, model->GetCommandIdAt(index + 2)); |
| 667 item->AddChildView( | 789 item->SetTitle(UTF16ToWide(l10n_util::GetStringUTF16(IDS_EDIT2))); |
| 668 new CutCopyPasteView(this, model, index, index + 1, index + 2)); | 790 item->AddChildView( |
| 669 i += 2; | 791 new CutCopyPasteView(this, model, index, index + 1, index + 2)); |
| 670 } else if (model->GetCommandIdAt(index) == IDC_ZOOM_MINUS) { | 792 i += 2; |
| 671 DCHECK_EQ(MenuModel::TYPE_COMMAND, model->GetTypeAt(index)); | 793 break; |
| 672 DCHECK_EQ(IDC_ZOOM_PLUS, model->GetCommandIdAt(index + 1)); | 794 |
| 673 DCHECK_EQ(IDC_FULLSCREEN, model->GetCommandIdAt(index + 2)); | 795 case IDC_ZOOM_MINUS: |
| 674 item->SetTitle(UTF16ToWide(l10n_util::GetStringUTF16(IDS_ZOOM_MENU2))); | 796 DCHECK_EQ(MenuModel::TYPE_COMMAND, model->GetTypeAt(index)); |
| 675 item->AddChildView( | 797 DCHECK_EQ(IDC_ZOOM_PLUS, model->GetCommandIdAt(index + 1)); |
| 676 new ZoomView(this, model, index, index + 1, index + 2)); | 798 DCHECK_EQ(IDC_FULLSCREEN, model->GetCommandIdAt(index + 2)); |
| 677 i += 2; | 799 item->SetTitle(UTF16ToWide(l10n_util::GetStringUTF16(IDS_ZOOM_MENU2))); |
| 800 item->AddChildView( |
| 801 new ZoomView(this, model, index, index + 1, index + 2)); |
| 802 i += 2; |
| 803 break; |
| 804 |
| 805 case IDC_BOOKMARKS_MENU: |
| 806 DCHECK(!bookmark_menu_); |
| 807 bookmark_menu_ = item; |
| 808 break; |
| 809 |
| 810 default: |
| 811 break; |
| 678 } | 812 } |
| 679 } | 813 } |
| 680 } | 814 } |
| 681 | 815 |
| 682 MenuItemView* WrenchMenu::AppendMenuItem(MenuItemView* parent, | 816 MenuItemView* WrenchMenu::AppendMenuItem(MenuItemView* parent, |
| 683 MenuModel* model, | 817 MenuModel* model, |
| 684 int index, | 818 int index, |
| 685 MenuModel::ItemType menu_type, | 819 MenuModel::ItemType menu_type, |
| 686 int* next_id) { | 820 int* next_id) { |
| 687 int id = (*next_id)++; | 821 int id = (*next_id)++; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 701 } | 835 } |
| 702 | 836 |
| 703 return menu_item; | 837 return menu_item; |
| 704 } | 838 } |
| 705 | 839 |
| 706 void WrenchMenu::CancelAndEvaluate(MenuModel* model, int index) { | 840 void WrenchMenu::CancelAndEvaluate(MenuModel* model, int index) { |
| 707 selected_menu_model_ = model; | 841 selected_menu_model_ = model; |
| 708 selected_index_ = index; | 842 selected_index_ = index; |
| 709 root_->Cancel(); | 843 root_->Cancel(); |
| 710 } | 844 } |
| 845 |
| 846 void WrenchMenu::CreateBookmarkMenu() { |
| 847 if (bookmark_menu_delegate_.get()) |
| 848 return; // Already created the menu. |
| 849 |
| 850 BookmarkModel* model = browser_->profile()->GetBookmarkModel(); |
| 851 if (!model->IsLoaded()) |
| 852 return; |
| 853 |
| 854 model->AddObserver(this); |
| 855 bookmark_menu_delegate_.reset( |
| 856 new BookmarkMenuDelegate(browser_->profile(), |
| 857 NULL, |
| 858 browser_->window()->GetNativeHandle(), |
| 859 first_bookmark_command_id_)); |
| 860 bookmark_menu_delegate_->Init( |
| 861 this, bookmark_menu_, model->GetBookmarkBarNode(), 0, |
| 862 BookmarkMenuDelegate::SHOW_OTHER_FOLDER); |
| 863 } |
| OLD | NEW |