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

Side by Side Diff: chrome/browser/views/browser_actions_container.cc

Issue 570014: Adding drag-drop support in and out of the Browser Action overflow menu.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 10 years, 10 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) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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/views/browser_actions_container.h" 5 #include "chrome/browser/views/browser_actions_container.h"
6 6
7 #include "app/gfx/canvas.h" 7 #include "app/gfx/canvas.h"
8 #include "app/resource_bundle.h" 8 #include "app/resource_bundle.h"
9 #include "app/slide_animation.h" 9 #include "app/slide_animation.h"
10 #include "base/stl_util-inl.h" 10 #include "base/stl_util-inl.h"
11 #include "base/string_util.h" 11 #include "base/string_util.h"
12 #include "chrome/browser/browser.h" 12 #include "chrome/browser/browser.h"
13 #include "chrome/browser/browser_theme_provider.h" 13 #include "chrome/browser/browser_theme_provider.h"
14 #include "chrome/browser/browser_window.h" 14 #include "chrome/browser/browser_window.h"
15 #include "chrome/browser/extensions/extension_browser_event_router.h" 15 #include "chrome/browser/extensions/extension_browser_event_router.h"
16 #include "chrome/browser/extensions/extensions_service.h" 16 #include "chrome/browser/extensions/extensions_service.h"
17 #include "chrome/browser/extensions/extension_tabs_module.h" 17 #include "chrome/browser/extensions/extension_tabs_module.h"
18 #include "chrome/browser/renderer_host/render_widget_host_view.h" 18 #include "chrome/browser/renderer_host/render_widget_host_view.h"
19 #include "chrome/browser/profile.h" 19 #include "chrome/browser/profile.h"
20 #include "chrome/browser/view_ids.h" 20 #include "chrome/browser/view_ids.h"
21 #include "chrome/browser/views/detachable_toolbar_view.h" 21 #include "chrome/browser/views/detachable_toolbar_view.h"
22 #include "chrome/browser/views/extensions/browser_action_drag_data.h" 22 #include "chrome/browser/views/extensions/browser_action_drag_data.h"
23 #include "chrome/browser/views/extensions/browser_action_overflow_menu_controlle r.h"
24 #include "chrome/browser/views/extensions/extension_popup.h" 23 #include "chrome/browser/views/extensions/extension_popup.h"
25 #include "chrome/browser/views/toolbar_view.h" 24 #include "chrome/browser/views/toolbar_view.h"
26 #include "chrome/common/notification_source.h" 25 #include "chrome/common/notification_source.h"
27 #include "chrome/common/notification_type.h" 26 #include "chrome/common/notification_type.h"
28 #include "chrome/common/pref_names.h" 27 #include "chrome/common/pref_names.h"
29 #include "grit/app_resources.h" 28 #include "grit/app_resources.h"
30 #include "third_party/skia/include/core/SkBitmap.h" 29 #include "third_party/skia/include/core/SkBitmap.h"
31 #include "third_party/skia/include/core/SkTypeface.h" 30 #include "third_party/skia/include/core/SkTypeface.h"
32 #include "third_party/skia/include/effects/SkGradientShader.h" 31 #include "third_party/skia/include/effects/SkGradientShader.h"
33 #include "views/controls/button/menu_button.h" 32 #include "views/controls/button/menu_button.h"
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after
294 293
295 BrowserActionsContainer::BrowserActionsContainer( 294 BrowserActionsContainer::BrowserActionsContainer(
296 Profile* profile, ToolbarView* toolbar) 295 Profile* profile, ToolbarView* toolbar)
297 : profile_(profile), 296 : profile_(profile),
298 toolbar_(toolbar), 297 toolbar_(toolbar),
299 popup_(NULL), 298 popup_(NULL),
300 popup_button_(NULL), 299 popup_button_(NULL),
301 model_(NULL), 300 model_(NULL),
302 resize_gripper_(NULL), 301 resize_gripper_(NULL),
303 chevron_(NULL), 302 chevron_(NULL),
303 overflow_menu_(NULL),
304 suppress_chevron_(false), 304 suppress_chevron_(false),
305 resize_amount_(0), 305 resize_amount_(0),
306 animation_target_size_(0), 306 animation_target_size_(0),
307 drop_indicator_position_(-1), 307 drop_indicator_position_(-1),
308 ALLOW_THIS_IN_INITIALIZER_LIST(task_factory_(this)) { 308 ALLOW_THIS_IN_INITIALIZER_LIST(task_factory_(this)),
309 ALLOW_THIS_IN_INITIALIZER_LIST(show_menu_task_factory_(this)) {
309 SetID(VIEW_ID_BROWSER_ACTION_TOOLBAR); 310 SetID(VIEW_ID_BROWSER_ACTION_TOOLBAR);
310 311
311 ExtensionsService* extension_service = profile->GetExtensionsService(); 312 ExtensionsService* extension_service = profile->GetExtensionsService();
312 if (!extension_service) // The |extension_service| can be NULL in Incognito. 313 if (!extension_service) // The |extension_service| can be NULL in Incognito.
313 return; 314 return;
314 315
315 registrar_.Add(this, NotificationType::EXTENSION_HOST_VIEW_SHOULD_CLOSE, 316 registrar_.Add(this, NotificationType::EXTENSION_HOST_VIEW_SHOULD_CLOSE,
316 Source<Profile>(profile_)); 317 Source<Profile>(profile_));
317 318
318 model_ = extension_service->toolbar_model(); 319 model_ = extension_service->toolbar_model();
(...skipping 21 matching lines...) Expand all
340 // except when no width has been saved. So, in that case ask the model 341 // except when no width has been saved. So, in that case ask the model
341 // how many icons we'll show and set initial size to that. 342 // how many icons we'll show and set initial size to that.
342 predefined_width = IconCountToWidth(model_->size()); 343 predefined_width = IconCountToWidth(model_->size());
343 } 344 }
344 container_size_ = gfx::Size(predefined_width, kButtonSize); 345 container_size_ = gfx::Size(predefined_width, kButtonSize);
345 } 346 }
346 347
347 BrowserActionsContainer::~BrowserActionsContainer() { 348 BrowserActionsContainer::~BrowserActionsContainer() {
348 if (model_) 349 if (model_)
349 model_->RemoveObserver(this); 350 model_->RemoveObserver(this);
351 StopShowFolderDropMenuTimer();
350 CloseOverflowMenu(); 352 CloseOverflowMenu();
351 HidePopup(); 353 HidePopup();
352 DeleteBrowserActionViews(); 354 DeleteBrowserActionViews();
353 } 355 }
354 356
355 // Static. 357 // Static.
356 void BrowserActionsContainer::RegisterUserPrefs(PrefService* prefs) { 358 void BrowserActionsContainer::RegisterUserPrefs(PrefService* prefs) {
357 prefs->RegisterIntegerPref(prefs::kBrowserActionContainerWidth, 0); 359 prefs->RegisterIntegerPref(prefs::kBrowserActionContainerWidth, 0);
358 } 360 }
359 361
(...skipping 17 matching lines...) Expand all
377 return NULL; 379 return NULL;
378 } 380 }
379 381
380 void BrowserActionsContainer::RefreshBrowserActionViews() { 382 void BrowserActionsContainer::RefreshBrowserActionViews() {
381 for (size_t i = 0; i < browser_action_views_.size(); ++i) 383 for (size_t i = 0; i < browser_action_views_.size(); ++i)
382 browser_action_views_[i]->button()->UpdateState(); 384 browser_action_views_[i]->button()->UpdateState();
383 } 385 }
384 386
385 void BrowserActionsContainer::CloseOverflowMenu() { 387 void BrowserActionsContainer::CloseOverflowMenu() {
386 // Close the overflow menu if open (and the context menu off of that). 388 // Close the overflow menu if open (and the context menu off of that).
387 if (overflow_menu_.get()) 389 if (overflow_menu_)
388 overflow_menu_->CancelMenu(); 390 overflow_menu_->CancelMenu();
389 } 391 }
390 392
393 void BrowserActionsContainer::StopShowFolderDropMenuTimer() {
394 show_menu_task_factory_.RevokeAll();
395 }
396
397 void BrowserActionsContainer::StartShowFolderDropMenuTimer() {
398 int delay = View::GetMenuShowDelay();
399 MessageLoop::current()->PostDelayedTask(FROM_HERE,
400 show_menu_task_factory_.NewRunnableMethod(
401 &BrowserActionsContainer::ShowDropFolder),
402 delay);
403 }
404
405 void BrowserActionsContainer::ShowDropFolder() {
406 DCHECK(!overflow_menu_);
407 overflow_menu_ = new BrowserActionOverflowMenuController(
408 this, chevron_, browser_action_views_, VisibleBrowserActions());
409 overflow_menu_->set_observer(this);
410 overflow_menu_->RunMenu(GetWindow()->GetNativeWindow(), true);
411 }
412
413 void BrowserActionsContainer::SetDropIndicator(int x_pos) {
414 if (drop_indicator_position_ != x_pos) {
415 drop_indicator_position_ = x_pos;
416 SchedulePaint();
417 }
418 }
419
391 void BrowserActionsContainer::CreateBrowserActionViews() { 420 void BrowserActionsContainer::CreateBrowserActionViews() {
392 DCHECK(browser_action_views_.empty()); 421 DCHECK(browser_action_views_.empty());
393 for (ExtensionList::iterator iter = model_->begin(); 422 for (ExtensionList::iterator iter = model_->begin();
394 iter != model_->end(); ++iter) { 423 iter != model_->end(); ++iter) {
395 BrowserActionView* view = new BrowserActionView(*iter, this); 424 BrowserActionView* view = new BrowserActionView(*iter, this);
396 browser_action_views_.push_back(view); 425 browser_action_views_.push_back(view);
397 AddChildView(view); 426 AddChildView(view);
398 } 427 }
399 } 428 }
400 429
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after
628 return false; 657 return false;
629 return drop_data.IsFromProfile(profile_); 658 return drop_data.IsFromProfile(profile_);
630 } 659 }
631 660
632 void BrowserActionsContainer::OnDragEntered( 661 void BrowserActionsContainer::OnDragEntered(
633 const views::DropTargetEvent& event) { 662 const views::DropTargetEvent& event) {
634 } 663 }
635 664
636 int BrowserActionsContainer::OnDragUpdated( 665 int BrowserActionsContainer::OnDragUpdated(
637 const views::DropTargetEvent& event) { 666 const views::DropTargetEvent& event) {
667 // First check if we are above the chevron (overflow) menu.
668 if (GetViewForPoint(event.location()) == chevron_) {
669 SetDropIndicator(-1);
670
671 if (show_menu_task_factory_.empty() && !overflow_menu_)
672 StartShowFolderDropMenuTimer();
673 return DragDropTypes::DRAG_MOVE;
674 } else {
675 StopShowFolderDropMenuTimer();
676 }
677
638 // Modifying the x value before clamping affects how far you have to drag to 678 // Modifying the x value before clamping affects how far you have to drag to
639 // get the drop indicator to shift to another position. Modifying after 679 // get the drop indicator to shift to another position. Modifying after
640 // clamping affects where the drop indicator is drawn. 680 // clamping affects where the drop indicator is drawn.
641 681
642 // We add half a button size so that when you drag a button to the right and 682 // We add half a button size so that when you drag a button to the right and
643 // you are half-way dragging across a button the drop indicator moves from the 683 // you are half-way dragging across a button the drop indicator moves from the
644 // left of that button to the right of that button. 684 // left of that button to the right of that button.
645 int x = event.x() + (kButtonSize / 2) + (2 * kBrowserActionButtonPadding); 685 int x = event.x() + (kButtonSize / 2) + (2 * kBrowserActionButtonPadding);
646 if (chevron_->IsVisible()) 686 if (chevron_->IsVisible())
647 x += chevron_->bounds().width(); 687 x += chevron_->bounds().width();
648 x = ClampToNearestIconCount(x, false); 688 x = ClampToNearestIconCount(x, false);
649 689
650 if (!UILayoutIsRightToLeft() && chevron_->IsVisible()) { 690 if (!UILayoutIsRightToLeft() && chevron_->IsVisible()) {
651 // The clamping function includes the chevron width. In LTR locales, the 691 // The clamping function includes the chevron width. In LTR locales, the
652 // chevron is on the right and we never want to account for its width. In 692 // chevron is on the right and we never want to account for its width. In
653 // RTL it is on the left and we always want to count the width. 693 // RTL it is on the left and we always want to count the width.
654 x -= chevron_->width(); 694 x -= chevron_->width();
655 } 695 }
656 696
657 // Clamping gives us a value where the next button will be drawn, but we want 697 // Clamping gives us a value where the next button will be drawn, but we want
658 // to subtract the padding (and then some) to make it appear in-between the 698 // to subtract the padding (and then some) to make it appear in-between the
659 // buttons. 699 // buttons.
660 drop_indicator_position_ = x - kBrowserActionButtonPadding - 700 SetDropIndicator(x - kBrowserActionButtonPadding -
661 (UILayoutIsRightToLeft() ? kDropIndicatorOffsetRtl : 701 (UILayoutIsRightToLeft() ? kDropIndicatorOffsetRtl :
662 kDropIndicatorOffsetLtr); 702 kDropIndicatorOffsetLtr));
663
664 SchedulePaint();
665 return DragDropTypes::DRAG_MOVE; 703 return DragDropTypes::DRAG_MOVE;
666 } 704 }
667 705
668 void BrowserActionsContainer::OnDragExited() { 706 void BrowserActionsContainer::OnDragExited() {
707 StopShowFolderDropMenuTimer();
669 drop_indicator_position_ = -1; 708 drop_indicator_position_ = -1;
670 SchedulePaint(); 709 SchedulePaint();
671 } 710 }
672 711
673 int BrowserActionsContainer::OnPerformDrop( 712 int BrowserActionsContainer::OnPerformDrop(
674 const views::DropTargetEvent& event) { 713 const views::DropTargetEvent& event) {
675 BrowserActionDragData data; 714 BrowserActionDragData data;
676 if (!data.Read(event.GetData())) 715 if (!data.Read(event.GetData()))
677 return DragDropTypes::DRAG_NONE; 716 return DragDropTypes::DRAG_NONE;
678 717
(...skipping 25 matching lines...) Expand all
704 // * Well, it can also point to the end, but not when dragging to the left. :) 743 // * Well, it can also point to the end, but not when dragging to the left. :)
705 if (i > data.index()) 744 if (i > data.index())
706 --i; 745 --i;
707 746
708 model_->MoveBrowserAction(dragging, i); 747 model_->MoveBrowserAction(dragging, i);
709 748
710 OnDragExited(); // Perform clean up after dragging. 749 OnDragExited(); // Perform clean up after dragging.
711 return DragDropTypes::DRAG_MOVE; 750 return DragDropTypes::DRAG_MOVE;
712 } 751 }
713 752
753 void BrowserActionsContainer::MoveBrowserAction(
754 const std::string& extension_id, size_t new_index) {
755 ExtensionsService* service = profile_->GetExtensionsService();
756 Extension* extension = service->GetExtensionById(extension_id, false);
757 model_->MoveBrowserAction(extension, new_index);
758 SchedulePaint();
759 }
760
714 void BrowserActionsContainer::Observe(NotificationType type, 761 void BrowserActionsContainer::Observe(NotificationType type,
715 const NotificationSource& source, 762 const NotificationSource& source,
716 const NotificationDetails& details) { 763 const NotificationDetails& details) {
717 switch (type.value) { 764 switch (type.value) {
718 case NotificationType::EXTENSION_HOST_VIEW_SHOULD_CLOSE: 765 case NotificationType::EXTENSION_HOST_VIEW_SHOULD_CLOSE:
719 // If we aren't the host of the popup, then disregard the notification. 766 // If we aren't the host of the popup, then disregard the notification.
720 if (!popup_ || Details<ExtensionHost>(popup_->host()) != details) 767 if (!popup_ || Details<ExtensionHost>(popup_->host()) != details)
721 return; 768 return;
722 769
723 HidePopup(); 770 HidePopup();
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
765 // This is a bit annoying. If you click on the button that generated the 812 // This is a bit annoying. If you click on the button that generated the
766 // current popup, then we first get this lost focus message, and then 813 // current popup, then we first get this lost focus message, and then
767 // we get the click action. This results in the popup being immediately 814 // we get the click action. This results in the popup being immediately
768 // shown again. To workaround this, we put in a delay. 815 // shown again. To workaround this, we put in a delay.
769 MessageLoop::current()->PostTask(FROM_HERE, 816 MessageLoop::current()->PostTask(FROM_HERE,
770 task_factory_.NewRunnableMethod(&BrowserActionsContainer::HidePopup)); 817 task_factory_.NewRunnableMethod(&BrowserActionsContainer::HidePopup));
771 } 818 }
772 819
773 void BrowserActionsContainer::RunMenu(View* source, const gfx::Point& pt) { 820 void BrowserActionsContainer::RunMenu(View* source, const gfx::Point& pt) {
774 if (source == chevron_) { 821 if (source == chevron_) {
775 overflow_menu_.reset(new BrowserActionOverflowMenuController( 822 overflow_menu_ = new BrowserActionOverflowMenuController(
776 this, chevron_, browser_action_views_, VisibleBrowserActions())); 823 this, chevron_, browser_action_views_, VisibleBrowserActions());
777 overflow_menu_->RunMenu(GetWindow()->GetNativeWindow()); 824 overflow_menu_->set_observer(this);
825 overflow_menu_->RunMenu(GetWindow()->GetNativeWindow(), false);
778 } 826 }
779 } 827 }
780 828
781 void BrowserActionsContainer::WriteDragData( 829 void BrowserActionsContainer::WriteDragData(
782 View* sender, int press_x, int press_y, OSExchangeData* data) { 830 View* sender, int press_x, int press_y, OSExchangeData* data) {
783 DCHECK(data); 831 DCHECK(data);
784 832
785 for (size_t i = 0; i < browser_action_views_.size(); ++i) { 833 for (size_t i = 0; i < browser_action_views_.size(); ++i) {
786 if (browser_action_views_[i]->button() == sender) { 834 if (browser_action_views_[i]->button() == sender) {
787 BrowserActionDragData drag_data( 835 BrowserActionDragData drag_data(
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after
1000 void BrowserActionsContainer::AnimationEnded(const Animation* animation) { 1048 void BrowserActionsContainer::AnimationEnded(const Animation* animation) {
1001 container_size_.set_width(animation_target_size_); 1049 container_size_.set_width(animation_target_size_);
1002 animation_target_size_ = 0; 1050 animation_target_size_ = 0;
1003 resize_amount_ = 0; 1051 resize_amount_ = 0;
1004 OnBrowserActionVisibilityChanged(); 1052 OnBrowserActionVisibilityChanged();
1005 suppress_chevron_ = false; 1053 suppress_chevron_ = false;
1006 1054
1007 profile_->GetPrefs()->SetInteger(prefs::kBrowserActionContainerWidth, 1055 profile_->GetPrefs()->SetInteger(prefs::kBrowserActionContainerWidth,
1008 container_size_.width()); 1056 container_size_.width());
1009 } 1057 }
1058
1059 void BrowserActionsContainer::NotifyMenuDeleted(
1060 BrowserActionOverflowMenuController* controller) {
1061 DCHECK(controller == overflow_menu_);
1062 overflow_menu_ = NULL;
1063 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698